Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
b80ea415
Commit
b80ea415
authored
Jul 27, 2023
by
Piotr Caban
Committed by
Alexandre Julliard
Jul 31, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winedump: Add initial support for dumping Windows NT Registry Files (REGF).
parent
724e54d5
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
346 additions
and
1 deletion
+346
-1
Makefile.in
tools/winedump/Makefile.in
+1
-0
dump.c
tools/winedump/dump.c
+1
-0
reg.c
tools/winedump/reg.c
+341
-0
winedump.h
tools/winedump/winedump.h
+3
-1
No files found.
tools/winedump/Makefile.in
View file @
b80ea415
...
@@ -23,6 +23,7 @@ C_SRCS = \
...
@@ -23,6 +23,7 @@ C_SRCS = \
output.c
\
output.c
\
pdb.c
\
pdb.c
\
pe.c
\
pe.c
\
reg.c
\
search.c
\
search.c
\
symbol.c
\
symbol.c
\
tlb.c
tlb.c
...
...
tools/winedump/dump.c
View file @
b80ea415
...
@@ -261,6 +261,7 @@ dumpers[] =
...
@@ -261,6 +261,7 @@ dumpers[] =
{
SIG_FNT
,
get_kind_fnt
,
fnt_dump
},
{
SIG_FNT
,
get_kind_fnt
,
fnt_dump
},
{
SIG_TLB
,
get_kind_tlb
,
tlb_dump
},
{
SIG_TLB
,
get_kind_tlb
,
tlb_dump
},
{
SIG_NLS
,
get_kind_nls
,
nls_dump
},
{
SIG_NLS
,
get_kind_nls
,
nls_dump
},
{
SIG_REG
,
get_kind_reg
,
reg_dump
},
{
SIG_UNKNOWN
,
NULL
,
NULL
}
/* sentinel */
{
SIG_UNKNOWN
,
NULL
,
NULL
}
/* sentinel */
};
};
...
...
tools/winedump/reg.c
0 → 100644
View file @
b80ea415
/*
* Dump Windows NT Registry File (REGF)
*
* Copyright 2023 Piotr Caban for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include "winedump.h"
#define BLOCK_SIZE 4096
#define SECSPERDAY 86400
/* 1601 to 1970 is 369 years plus 89 leap days */
#define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
#define TICKSPERSEC 10000000
enum
file_type
{
REG_HIVE
};
typedef
struct
{
unsigned
int
signature
;
unsigned
int
seq_prim
;
unsigned
int
seq_sec
;
FILETIME
modif_time
;
unsigned
int
ver_major
;
unsigned
int
ver_minor
;
enum
file_type
file_type
;
unsigned
int
unk1
;
unsigned
int
root_key_off
;
unsigned
int
hive_bins_size
;
unsigned
int
unk2
[
116
];
unsigned
int
checksum
;
}
header
;
enum
key_flags
{
KEY_IS_VOLATILE
=
0x01
,
KEY_HIVE_EXIT
=
0x02
,
KEY_HIVE_ENTRY
=
0x04
,
KEY_NO_DELETE
=
0x08
,
KEY_SYM_LINK
=
0x10
,
KEY_COMP_NAME
=
0x20
};
typedef
struct
{
unsigned
int
size
;
short
signature
;
short
flags
;
FILETIME
timestamp
;
int
unk1
;
unsigned
int
parent_off
;
unsigned
int
sub_keys
;
unsigned
int
volatile_sub_keys
;
unsigned
int
sub_keys_list_off
;
unsigned
int
volatile_sub_keys_list_off
;
unsigned
int
values
;
unsigned
int
values_list_off
;
unsigned
int
sec_key_off
;
unsigned
int
class_off
;
unsigned
int
max_name_size
;
unsigned
int
max_class_size
;
unsigned
int
max_val_name_size
;
unsigned
int
max_val_size
;
int
unk2
;
unsigned
short
name_size
;
unsigned
short
class_size
;
}
named_key
;
enum
val_flags
{
VAL_COMP_NAME
=
0x1
};
typedef
struct
{
unsigned
int
size
;
unsigned
short
signature
;
unsigned
short
name_size
;
unsigned
int
data_size
;
unsigned
int
data_off
;
unsigned
int
data_type
;
unsigned
short
flags
;
unsigned
short
padding
;
}
value_key
;
typedef
struct
{
unsigned
int
size
;
unsigned
short
signature
;
unsigned
short
count
;
}
key_list
;
static
unsigned
int
path_len
;
static
char
path
[
512
*
256
];
static
BOOL
dump_key
(
unsigned
int
hive_off
,
unsigned
int
off
);
static
time_t
filetime_to_time_t
(
FILETIME
ft
)
{
ULONGLONG
*
ull
=
(
ULONGLONG
*
)
&
ft
;
time_t
t
=
*
ull
/
TICKSPERSEC
-
SECS_1601_TO_1970
;
return
*
ull
?
t
:
0
;
}
static
const
char
*
filetime_str
(
FILETIME
ft
)
{
return
get_time_str
(
filetime_to_time_t
(
ft
));
}
static
unsigned
int
header_checksum
(
const
header
*
h
)
{
unsigned
int
i
,
checksum
=
0
;
for
(
i
=
0
;
i
<
FIELD_OFFSET
(
header
,
checksum
)
/
sizeof
(
int
);
i
++
)
checksum
^=
((
unsigned
int
*
)
h
)[
i
];
return
checksum
;
}
enum
FileSig
get_kind_reg
(
void
)
{
const
header
*
hdr
;
hdr
=
PRD
(
0
,
BLOCK_SIZE
);
if
(
hdr
&&
!
memcmp
(
&
hdr
->
signature
,
"regf"
,
sizeof
(
hdr
->
signature
)))
return
SIG_REG
;
return
SIG_UNKNOWN
;
}
static
BOOL
dump_subkeys
(
unsigned
int
hive_off
,
unsigned
int
off
)
{
const
key_list
*
key_list
=
PRD
(
hive_off
+
off
,
sizeof
(
*
key_list
));
const
unsigned
int
*
offs
;
unsigned
int
i
;
if
(
!
key_list
)
return
FALSE
;
if
(
!
memcmp
(
&
key_list
->
signature
,
"lf"
,
2
)
||
!
memcmp
(
&
key_list
->
signature
,
"lh"
,
2
)
||
!
memcmp
(
&
key_list
->
signature
,
"li"
,
2
))
{
unsigned
int
elem_size
=
memcmp
(
&
key_list
->
signature
,
"li"
,
2
)
?
2
:
1
;
offs
=
PRD
(
hive_off
+
off
+
sizeof
(
*
key_list
),
key_list
->
count
*
elem_size
*
sizeof
(
*
offs
));
if
(
!
offs
)
return
FALSE
;
for
(
i
=
0
;
i
<
key_list
->
count
;
i
++
)
{
if
(
!
dump_key
(
hive_off
,
offs
[
elem_size
*
i
]))
return
FALSE
;
}
}
else
if
(
!
memcmp
(
&
key_list
->
signature
,
"ri"
,
2
))
{
offs
=
PRD
(
hive_off
+
off
+
sizeof
(
*
key_list
),
key_list
->
count
*
sizeof
(
*
offs
));
if
(
!
offs
)
return
FALSE
;
for
(
i
=
0
;
i
<
key_list
->
count
;
i
++
)
{
if
(
!
dump_subkeys
(
hive_off
,
offs
[
i
]))
return
FALSE
;
}
}
else
{
return
FALSE
;
}
return
TRUE
;
}
static
BOOL
dump_value
(
unsigned
int
hive_off
,
unsigned
int
off
)
{
const
void
*
data
=
NULL
;
const
value_key
*
val
;
const
char
*
name
;
val
=
PRD
(
hive_off
+
off
,
sizeof
(
*
val
));
if
(
!
val
||
memcmp
(
&
val
->
signature
,
"vk"
,
2
))
return
FALSE
;
if
(
!
(
val
->
flags
&
VAL_COMP_NAME
))
{
printf
(
"unsupported value flags: %x
\n
"
,
val
->
flags
);
return
FALSE
;
}
if
(
val
->
name_size
)
{
name
=
PRD
(
hive_off
+
off
+
sizeof
(
*
val
),
val
->
name_size
);
if
(
!
name
)
return
FALSE
;
printf
(
"
\"
%*s
\"
="
,
val
->
name_size
,
name
);
}
else
{
printf
(
"@="
);
}
if
(
val
->
data_size
)
{
data
=
PRD
(
hive_off
+
val
->
data_off
+
sizeof
(
unsigned
int
),
val
->
data_size
);
if
(
!
data
)
return
FALSE
;
}
switch
(
val
->
data_type
)
{
case
REG_SZ
:
printf
(
"%s"
,
!
data
?
""
:
get_unicode_str
((
const
WCHAR
*
)
data
,
val
->
data_size
/
sizeof
(
WCHAR
)));
break
;
default:
printf
(
"unhandled data type %d"
,
val
->
data_type
);
}
printf
(
"
\n
"
);
return
TRUE
;
}
static
BOOL
dump_key
(
unsigned
int
hive_off
,
unsigned
int
off
)
{
const
named_key
*
key
;
const
char
*
name
;
BOOL
ret
=
TRUE
;
key
=
PRD
(
hive_off
+
off
,
sizeof
(
*
key
));
if
(
!
key
||
memcmp
(
&
key
->
signature
,
"nk"
,
2
))
return
FALSE
;
if
(
!
(
key
->
flags
&
KEY_COMP_NAME
))
{
printf
(
"unsupported key flags: %x
\n
"
,
key
->
flags
);
return
FALSE
;
}
name
=
PRD
(
hive_off
+
off
+
sizeof
(
*
key
),
key
->
name_size
);
if
(
!
name
)
return
FALSE
;
if
(
path_len
)
path
[
path_len
++
]
=
'\\'
;
memcpy
(
path
+
path_len
,
name
,
key
->
name_size
);
path_len
+=
key
->
name_size
;
path
[
path_len
]
=
0
;
if
((
!
key
->
sub_keys
&&
!
key
->
volatile_sub_keys
)
||
key
->
values
)
{
printf
(
"[%s] %u
\n
"
,
path
,
(
int
)
filetime_to_time_t
(
key
->
timestamp
));
printf
(
"#time=%x%08x
\n
"
,
(
int
)
key
->
timestamp
.
dwHighDateTime
,
(
int
)
key
->
timestamp
.
dwLowDateTime
);
if
(
key
->
values
)
{
const
unsigned
int
*
offs
=
PRD
(
hive_off
+
key
->
values_list_off
+
sizeof
(
unsigned
int
),
key
->
values
*
sizeof
(
unsigned
int
));
unsigned
int
i
;
if
(
!
offs
)
return
FALSE
;
for
(
i
=
0
;
i
<
key
->
values
;
i
++
)
{
ret
=
dump_value
(
hive_off
,
offs
[
i
]);
if
(
!
ret
)
return
ret
;
}
}
else
{
printf
(
"@=""
\n
"
);
}
if
(
!
ret
)
return
FALSE
;
printf
(
"
\n
"
);
}
if
(
key
->
sub_keys
)
ret
=
dump_subkeys
(
hive_off
,
key
->
sub_keys_list_off
);
if
(
ret
&&
key
->
volatile_sub_keys
)
ret
=
dump_subkeys
(
hive_off
,
key
->
volatile_sub_keys_list_off
);
path_len
-=
key
->
name_size
+
1
;
path
[
path_len
]
=
0
;
return
ret
;
}
void
reg_dump
(
void
)
{
const
header
*
hdr
;
hdr
=
PRD
(
0
,
sizeof
(
BLOCK_SIZE
));
if
(
!
hdr
)
return
;
printf
(
"File Header
\n
"
);
printf
(
" %-20s %4s
\n
"
,
"signature:"
,
(
char
*
)
&
hdr
->
signature
);
printf
(
" %-20s %u
\n
"
,
"primary sequence:"
,
hdr
->
seq_prim
);
printf
(
" %-20s %u
\n
"
,
"secondary sequence:"
,
hdr
->
seq_sec
);
printf
(
" %-20s %s
\n
"
,
"modification time:"
,
filetime_str
(
hdr
->
modif_time
));
printf
(
" %-20s %u.%d
\n
"
,
"version:"
,
hdr
->
ver_major
,
hdr
->
ver_minor
);
printf
(
" %-20s %u
\n
"
,
"file type:"
,
hdr
->
file_type
);
printf
(
" %-20s %u
\n
"
,
"root key offset:"
,
hdr
->
root_key_off
);
printf
(
" %-20s %u
\n
"
,
"hive bins size:"
,
hdr
->
hive_bins_size
);
printf
(
" %-20s %x (%svalid)
\n
"
,
"checksum:"
,
hdr
->
checksum
,
header_checksum
(
hdr
)
==
hdr
->
checksum
?
""
:
"in"
);
printf
(
"
\n
"
);
if
(
hdr
->
ver_major
!=
1
||
hdr
->
ver_minor
<
2
||
hdr
->
ver_minor
>
5
||
hdr
->
file_type
!=
REG_HIVE
)
{
printf
(
"unsupported format, exiting
\n
"
);
return
;
}
path_len
=
0
;
path
[
0
]
=
0
;
if
(
!
dump_key
(
BLOCK_SIZE
,
hdr
->
root_key_off
))
printf
(
"error dumping file
\n
"
);
}
tools/winedump/winedump.h
View file @
b80ea415
...
@@ -216,7 +216,7 @@ const char *get_machine_str(int mach);
...
@@ -216,7 +216,7 @@ const char *get_machine_str(int mach);
/* file dumping functions */
/* file dumping functions */
enum
FileSig
{
SIG_UNKNOWN
,
SIG_DOS
,
SIG_PE
,
SIG_DBG
,
SIG_PDB
,
SIG_NE
,
SIG_LE
,
SIG_MDMP
,
SIG_COFFLIB
,
SIG_LNK
,
enum
FileSig
{
SIG_UNKNOWN
,
SIG_DOS
,
SIG_PE
,
SIG_DBG
,
SIG_PDB
,
SIG_NE
,
SIG_LE
,
SIG_MDMP
,
SIG_COFFLIB
,
SIG_LNK
,
SIG_EMF
,
SIG_EMFSPOOL
,
SIG_MF
,
SIG_FNT
,
SIG_TLB
,
SIG_NLS
};
SIG_EMF
,
SIG_EMFSPOOL
,
SIG_MF
,
SIG_FNT
,
SIG_TLB
,
SIG_NLS
,
SIG_REG
};
const
void
*
PRD
(
unsigned
long
prd
,
unsigned
long
len
);
const
void
*
PRD
(
unsigned
long
prd
,
unsigned
long
len
);
unsigned
long
Offset
(
const
void
*
ptr
);
unsigned
long
Offset
(
const
void
*
ptr
);
...
@@ -265,6 +265,8 @@ enum FileSig get_kind_tlb(void);
...
@@ -265,6 +265,8 @@ enum FileSig get_kind_tlb(void);
void
tlb_dump
(
void
);
void
tlb_dump
(
void
);
enum
FileSig
get_kind_nls
(
void
);
enum
FileSig
get_kind_nls
(
void
);
void
nls_dump
(
void
);
void
nls_dump
(
void
);
enum
FileSig
get_kind_reg
(
void
);
void
reg_dump
(
void
);
BOOL
codeview_dump_symbols
(
const
void
*
root
,
unsigned
long
start
,
unsigned
long
size
);
BOOL
codeview_dump_symbols
(
const
void
*
root
,
unsigned
long
start
,
unsigned
long
size
);
BOOL
codeview_dump_types_from_offsets
(
const
void
*
table
,
const
DWORD
*
offsets
,
unsigned
num_types
);
BOOL
codeview_dump_types_from_offsets
(
const
void
*
table
,
const
DWORD
*
offsets
,
unsigned
num_types
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment