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
ec878008
Commit
ec878008
authored
Jun 15, 2017
by
Hugh McMaster
Committed by
Alexandre Julliard
Jun 15, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
regedit: Introduce a partial state machine for importing registry data.
Signed-off-by:
Hugh McMaster
<
hugh.mcmaster@outlook.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
b1e48fb4
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
201 additions
and
80 deletions
+201
-80
regproc.c
programs/regedit/regproc.c
+193
-72
regedit.c
programs/regedit/tests/regedit.c
+8
-8
No files found.
programs/regedit/regproc.c
View file @
ec878008
...
...
@@ -128,6 +128,55 @@ static char* GetMultiByteStringN(const WCHAR* strW, int chars, DWORD* len)
return
NULL
;
}
static
WCHAR
*
(
*
get_line
)(
FILE
*
);
/* parser definitions */
enum
parser_state
{
HEADER
,
/* parsing the registry file version header */
PARSE_WIN31_LINE
,
/* parsing a Windows 3.1 registry line */
LINE_START
,
/* at the beginning of a registry line */
SET_VALUE
,
/* adding a value to the registry */
NB_PARSER_STATES
};
struct
parser
{
FILE
*
file
;
/* pointer to a registry file */
WCHAR
two_wchars
[
2
];
/* first two characters from the encoding check */
BOOL
is_unicode
;
/* parsing Unicode or ASCII data */
short
int
reg_version
;
/* registry file version */
WCHAR
*
value_name
;
/* value name */
DWORD
data_type
;
/* data type */
void
*
data
;
/* value data */
DWORD
data_size
;
/* size of the data (in bytes) */
enum
parser_state
state
;
/* current parser state */
};
typedef
WCHAR
*
(
*
parser_state_func
)(
struct
parser
*
parser
,
WCHAR
*
pos
);
/* parser state machine functions */
static
WCHAR
*
header_state
(
struct
parser
*
parser
,
WCHAR
*
pos
);
static
WCHAR
*
parse_win31_line_state
(
struct
parser
*
parser
,
WCHAR
*
pos
);
static
WCHAR
*
line_start_state
(
struct
parser
*
parser
,
WCHAR
*
pos
);
static
WCHAR
*
set_value_state
(
struct
parser
*
parser
,
WCHAR
*
pos
);
static
const
parser_state_func
parser_funcs
[
NB_PARSER_STATES
]
=
{
header_state
,
/* HEADER */
parse_win31_line_state
,
/* PARSE_WIN31_LINE */
line_start_state
,
/* LINE_START */
set_value_state
,
/* SET_VALUE */
};
/* set the new parser state and return the previous one */
static
inline
enum
parser_state
set_state
(
struct
parser
*
parser
,
enum
parser_state
state
)
{
enum
parser_state
ret
=
parser
->
state
;
parser
->
state
=
state
;
return
ret
;
}
/******************************************************************************
* Converts a hex representation of a DWORD into a DWORD.
*/
...
...
@@ -583,44 +632,6 @@ static void processRegEntry(WCHAR* stdInput, BOOL isUnicode)
}
}
/* version for Windows 3.1 */
static
void
processRegEntry31
(
WCHAR
*
line
)
{
int
key_end
=
0
;
WCHAR
*
value
;
int
res
;
static
WCHAR
empty
[]
=
{
0
};
static
WCHAR
hkcr
[]
=
{
'H'
,
'K'
,
'E'
,
'Y'
,
'_'
,
'C'
,
'L'
,
'A'
,
'S'
,
'S'
,
'E'
,
'S'
,
'_'
,
'R'
,
'O'
,
'O'
,
'T'
};
if
(
strncmpW
(
line
,
hkcr
,
sizeof
(
hkcr
)
/
sizeof
(
WCHAR
)))
return
;
/* get key name */
while
(
line
[
key_end
]
&&
!
isspaceW
(
line
[
key_end
]))
key_end
++
;
value
=
line
+
key_end
;
while
(
isspaceW
(
value
[
0
]))
value
++
;
if
(
value
[
0
]
==
'='
)
value
++
;
if
(
value
[
0
]
==
' '
)
value
++
;
/* at most one space is skipped */
line
[
key_end
]
=
'\0'
;
if
(
openKeyW
(
line
)
!=
ERROR_SUCCESS
)
output_message
(
STRING_OPEN_KEY_FAILED
,
line
);
res
=
RegSetValueExW
(
currentKeyHandle
,
empty
,
0
,
/* Reserved */
REG_SZ
,
(
BYTE
*
)
value
,
(
strlenW
(
value
)
+
1
)
*
sizeof
(
WCHAR
));
if
(
res
!=
ERROR_SUCCESS
)
output_message
(
STRING_SETVALUE_FAILED
,
empty
,
currentKeyName
);
closeKey
();
}
enum
reg_versions
{
REG_VERSION_31
,
REG_VERSION_40
,
...
...
@@ -629,7 +640,7 @@ enum reg_versions {
REG_VERSION_INVALID
};
static
enum
reg_versions
parse_file_header
(
WCHAR
*
s
)
static
enum
reg_versions
parse_file_header
(
const
WCHAR
*
s
)
{
static
const
WCHAR
header_31
[]
=
{
'R'
,
'E'
,
'G'
,
'E'
,
'D'
,
'I'
,
'T'
,
0
};
static
const
WCHAR
header_40
[]
=
{
'R'
,
'E'
,
'G'
,
'E'
,
'D'
,
'I'
,
'T'
,
'4'
,
0
};
...
...
@@ -659,6 +670,129 @@ static enum reg_versions parse_file_header(WCHAR *s)
return
REG_VERSION_INVALID
;
}
/* handler for parser HEADER state */
static
WCHAR
*
header_state
(
struct
parser
*
parser
,
WCHAR
*
pos
)
{
WCHAR
*
line
,
*
header
;
if
(
!
(
line
=
get_line
(
parser
->
file
)))
return
NULL
;
if
(
!
parser
->
is_unicode
)
{
header
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
lstrlenW
(
line
)
+
3
)
*
sizeof
(
WCHAR
));
CHECK_ENOUGH_MEMORY
(
header
);
header
[
0
]
=
parser
->
two_wchars
[
0
];
header
[
1
]
=
parser
->
two_wchars
[
1
];
lstrcpyW
(
header
+
2
,
line
);
parser
->
reg_version
=
parse_file_header
(
header
);
HeapFree
(
GetProcessHeap
(),
0
,
header
);
}
else
parser
->
reg_version
=
parse_file_header
(
line
);
switch
(
parser
->
reg_version
)
{
case
REG_VERSION_31
:
set_state
(
parser
,
PARSE_WIN31_LINE
);
break
;
case
REG_VERSION_40
:
case
REG_VERSION_50
:
set_state
(
parser
,
LINE_START
);
break
;
default:
get_line
(
NULL
);
/* Reset static variables */
return
NULL
;
}
return
line
;
}
/* handler for parser PARSE_WIN31_LINE state */
static
WCHAR
*
parse_win31_line_state
(
struct
parser
*
parser
,
WCHAR
*
pos
)
{
WCHAR
*
line
,
*
value
;
static
WCHAR
hkcr
[]
=
{
'H'
,
'K'
,
'E'
,
'Y'
,
'_'
,
'C'
,
'L'
,
'A'
,
'S'
,
'S'
,
'E'
,
'S'
,
'_'
,
'R'
,
'O'
,
'O'
,
'T'
};
unsigned
int
key_end
=
0
;
if
(
!
(
line
=
get_line
(
parser
->
file
)))
return
NULL
;
if
(
strncmpW
(
line
,
hkcr
,
ARRAY_SIZE
(
hkcr
)))
goto
invalid
;
/* get key name */
while
(
line
[
key_end
]
&&
!
isspaceW
(
line
[
key_end
]))
key_end
++
;
value
=
line
+
key_end
;
while
(
*
value
==
' '
||
*
value
==
'\t'
)
value
++
;
if
(
*
value
==
'='
)
value
++
;
if
(
*
value
==
' '
)
value
++
;
/* at most one space is skipped */
line
[
key_end
]
=
0
;
closeKey
();
if
(
openKeyW
(
line
)
!=
ERROR_SUCCESS
)
{
output_message
(
STRING_OPEN_KEY_FAILED
,
line
);
goto
invalid
;
}
parser
->
value_name
=
NULL
;
parser
->
data_type
=
REG_SZ
;
parser
->
data
=
value
;
parser
->
data_size
=
(
lstrlenW
(
value
)
+
1
)
*
sizeof
(
WCHAR
);
set_state
(
parser
,
SET_VALUE
);
return
value
;
invalid:
set_state
(
parser
,
PARSE_WIN31_LINE
);
return
line
;
}
/* handler for parser LINE_START state */
static
WCHAR
*
line_start_state
(
struct
parser
*
parser
,
WCHAR
*
pos
)
{
WCHAR
*
line
,
*
p
;
if
(
!
(
line
=
get_line
(
parser
->
file
)))
return
NULL
;
for
(
p
=
line
;
*
p
;
p
++
)
{
switch
(
*
p
)
{
case
'['
:
case
'@'
:
case
'"'
:
processRegEntry
(
p
,
parser
->
is_unicode
);
set_state
(
parser
,
LINE_START
);
return
line
;
case
' '
:
case
'\t'
:
break
;
default:
set_state
(
parser
,
LINE_START
);
return
p
;
}
}
return
p
;
}
/* handler for parser SET_VALUE state */
static
WCHAR
*
set_value_state
(
struct
parser
*
parser
,
WCHAR
*
pos
)
{
RegSetValueExW
(
currentKeyHandle
,
parser
->
value_name
,
0
,
parser
->
data_type
,
parser
->
data
,
parser
->
data_size
);
set_state
(
parser
,
PARSE_WIN31_LINE
);
return
pos
;
}
static
WCHAR
*
get_lineA
(
FILE
*
fp
)
{
static
WCHAR
*
lineW
;
...
...
@@ -716,7 +850,6 @@ static WCHAR *get_lineA(FILE *fp)
next
=
line
;
continue
;
}
while
(
*
line
==
' '
||
*
line
==
'\t'
)
line
++
;
if
(
*
line
==
';'
||
*
line
==
'#'
)
{
line
=
next
;
...
...
@@ -787,7 +920,6 @@ static WCHAR *get_lineW(FILE *fp)
next
=
line
;
continue
;
}
while
(
*
line
==
' '
||
*
line
==
'\t'
)
line
++
;
if
(
*
line
==
';'
||
*
line
==
'#'
)
{
line
=
next
;
...
...
@@ -1273,47 +1405,36 @@ BOOL export_registry_key(WCHAR *file_name, WCHAR *reg_key_name, DWORD format)
/******************************************************************************
* Reads contents of the specified file into the registry.
*/
BOOL
import_registry_file
(
FILE
*
reg_file
)
BOOL
import_registry_file
(
FILE
*
reg_file
)
{
BYTE
s
[
2
];
BOOL
is_unicode
;
WCHAR
*
(
*
get_line
)(
FILE
*
);
WCHAR
*
line
,
*
header
;
int
reg_version
;
struct
parser
parser
;
WCHAR
*
pos
;
if
(
!
reg_file
||
(
fread
(
s
,
2
,
1
,
reg_file
)
!=
1
))
return
FALSE
;
is_unicode
=
(
s
[
0
]
==
0xff
&&
s
[
1
]
==
0xfe
);
get_line
=
is_unicode
?
get_lineW
:
get_lineA
;
parser
.
is_unicode
=
(
s
[
0
]
==
0xff
&&
s
[
1
]
==
0xfe
);
get_line
=
parser
.
is_unicode
?
get_lineW
:
get_lineA
;
line
=
get_line
(
reg_file
);
parser
.
file
=
reg_file
;
parser
.
two_wchars
[
0
]
=
s
[
0
];
parser
.
two_wchars
[
1
]
=
s
[
1
];
parser
.
reg_version
=
-
1
;
parser
.
value_name
=
NULL
;
parser
.
data_type
=
0
;
parser
.
data
=
NULL
;
parser
.
data_size
=
0
;
parser
.
state
=
HEADER
;
if
(
!
is_unicode
)
{
header
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
lstrlenW
(
line
)
+
3
)
*
sizeof
(
WCHAR
));
CHECK_ENOUGH_MEMORY
(
header
);
header
[
0
]
=
s
[
0
];
header
[
1
]
=
s
[
1
];
lstrcpyW
(
header
+
2
,
line
);
reg_version
=
parse_file_header
(
header
);
HeapFree
(
GetProcessHeap
(),
0
,
header
);
}
else
reg_version
=
parse_file_header
(
line
);
pos
=
parser
.
two_wchars
;
if
(
reg_version
==
REG_VERSION_FUZZY
||
reg_version
==
REG_VERSION_INVALID
)
{
get_line
(
NULL
);
/* Reset static variables */
return
reg_version
==
REG_VERSION_FUZZY
;
}
/* parser main loop */
while
(
pos
)
pos
=
(
parser_funcs
[
parser
.
state
])(
&
parser
,
pos
);
while
((
line
=
get_line
(
reg_file
)))
{
if
(
reg_version
==
REG_VERSION_31
)
processRegEntry31
(
line
);
else
processRegEntry
(
line
,
is_unicode
);
}
if
(
parser
.
reg_version
==
REG_VERSION_FUZZY
||
parser
.
reg_version
==
REG_VERSION_INVALID
)
return
parser
.
reg_version
==
REG_VERSION_FUZZY
;
closeKey
();
return
TRUE
;
...
...
programs/regedit/tests/regedit.c
View file @
ec878008
...
...
@@ -819,36 +819,36 @@ static void test_invalid_import_31(void)
/* Test character validity at the start of the line */
exec_import_str
(
"REGEDIT
\r\n
"
" HKEY_CLASSES_ROOT
\\
"
KEY_BASE
" = Value1a
\r\n
"
);
todo_wine
verify_reg_nonexist
(
hkey
,
""
);
verify_reg_nonexist
(
hkey
,
""
);
exec_import_str
(
"REGEDIT
\r\n
"
" HKEY_CLASSES_ROOT
\\
"
KEY_BASE
" = Value1b
\r\n
"
);
todo_wine
verify_reg_nonexist
(
hkey
,
""
);
verify_reg_nonexist
(
hkey
,
""
);
exec_import_str
(
"REGEDIT
\r\n
"
"
\t
HKEY_CLASSES_ROOT
\\
"
KEY_BASE
" = Value1c
\r\n
"
);
todo_wine
verify_reg_nonexist
(
hkey
,
""
);
verify_reg_nonexist
(
hkey
,
""
);
exec_import_str
(
"REGEDIT
\r\n
"
";HKEY_CLASSES_ROOT
\\
"
KEY_BASE
" = Value2a
\r\n
"
);
todo_wine
verify_reg_nonexist
(
hkey
,
""
);
verify_reg_nonexist
(
hkey
,
""
);
exec_import_str
(
"REGEDIT
\r\n
"
"#HKEY_CLASSES_ROOT
\\
"
KEY_BASE
" = Value2b
\r\n
"
);
todo_wine
verify_reg_nonexist
(
hkey
,
""
);
verify_reg_nonexist
(
hkey
,
""
);
/* Test case sensitivity */
exec_import_str
(
"REGEDIT
\r\n
"
"hkey_classes_root
\\
"
KEY_BASE
" = Value3a
\r\n
"
);
todo_wine
verify_reg_nonexist
(
hkey
,
""
);
verify_reg_nonexist
(
hkey
,
""
);
exec_import_str
(
"REGEDIT
\r\n
"
"hKEY_CLASSES_ROOT
\\
"
KEY_BASE
" = Value3b
\r\n
"
);
todo_wine
verify_reg_nonexist
(
hkey
,
""
);
verify_reg_nonexist
(
hkey
,
""
);
exec_import_str
(
"REGEDIT
\r\n
"
"Hkey_Classes_Root
\\
"
KEY_BASE
" = Value3c
\r\n
"
);
todo_wine
verify_reg_nonexist
(
hkey
,
""
);
verify_reg_nonexist
(
hkey
,
""
);
RegCloseKey
(
hkey
);
...
...
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