Commit ca98e234 authored by Hugh McMaster's avatar Hugh McMaster Committed by Alexandre Julliard

regedit: Perform key operations in the state machine.

parent ec878008
...@@ -136,6 +136,8 @@ enum parser_state ...@@ -136,6 +136,8 @@ enum parser_state
HEADER, /* parsing the registry file version header */ HEADER, /* parsing the registry file version header */
PARSE_WIN31_LINE, /* parsing a Windows 3.1 registry line */ PARSE_WIN31_LINE, /* parsing a Windows 3.1 registry line */
LINE_START, /* at the beginning of a registry line */ LINE_START, /* at the beginning of a registry line */
KEY_NAME, /* parsing a key name */
DELETE_KEY, /* deleting a registry key */
SET_VALUE, /* adding a value to the registry */ SET_VALUE, /* adding a value to the registry */
NB_PARSER_STATES NB_PARSER_STATES
}; };
...@@ -159,6 +161,8 @@ typedef WCHAR *(*parser_state_func)(struct parser *parser, WCHAR *pos); ...@@ -159,6 +161,8 @@ typedef WCHAR *(*parser_state_func)(struct parser *parser, WCHAR *pos);
static WCHAR *header_state(struct parser *parser, WCHAR *pos); static WCHAR *header_state(struct parser *parser, WCHAR *pos);
static WCHAR *parse_win31_line_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 *line_start_state(struct parser *parser, WCHAR *pos);
static WCHAR *key_name_state(struct parser *parser, WCHAR *pos);
static WCHAR *delete_key_state(struct parser *parser, WCHAR *pos);
static WCHAR *set_value_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] = static const parser_state_func parser_funcs[NB_PARSER_STATES] =
...@@ -166,6 +170,8 @@ static const parser_state_func parser_funcs[NB_PARSER_STATES] = ...@@ -166,6 +170,8 @@ static const parser_state_func parser_funcs[NB_PARSER_STATES] =
header_state, /* HEADER */ header_state, /* HEADER */
parse_win31_line_state, /* PARSE_WIN31_LINE */ parse_win31_line_state, /* PARSE_WIN31_LINE */
line_start_state, /* LINE_START */ line_start_state, /* LINE_START */
key_name_state, /* KEY_NAME */
delete_key_state, /* DELETE_KEY */
set_value_state, /* SET_VALUE */ set_value_state, /* SET_VALUE */
}; };
...@@ -348,21 +354,20 @@ static BOOL REGPROC_unescape_string(WCHAR *str, WCHAR **unparsed) ...@@ -348,21 +354,20 @@ static BOOL REGPROC_unescape_string(WCHAR *str, WCHAR **unparsed)
return ret; return ret;
} }
static HKEY parseKeyName(LPWSTR lpKeyName, LPWSTR *lpKeyPath) static HKEY parse_key_name(WCHAR *key_name, WCHAR **key_path)
{ {
unsigned int i; unsigned int i;
if (lpKeyName == NULL) if (!key_name) return 0;
return 0;
*lpKeyPath = strchrW(lpKeyName, '\\'); *key_path = strchrW(key_name, '\\');
if (*lpKeyPath) (*lpKeyPath)++; if (*key_path) (*key_path)++;
for (i = 0; i < ARRAY_SIZE(reg_class_keys); i++) for (i = 0; i < ARRAY_SIZE(reg_class_keys); i++)
{ {
int len = lstrlenW(reg_class_namesW[i]); int len = lstrlenW(reg_class_namesW[i]);
if (!strncmpW(lpKeyName, reg_class_namesW[i], len) && if (!strncmpW(key_name, reg_class_namesW[i], len) &&
(lpKeyName[len] == 0 || lpKeyName[len] == '\\')) (key_name[len] == 0 || key_name[len] == '\\'))
{ {
return reg_class_keys[i]; return reg_class_keys[i];
} }
...@@ -500,36 +505,36 @@ static LONG setValue(WCHAR* val_name, WCHAR* val_data, BOOL is_unicode) ...@@ -500,36 +505,36 @@ static LONG setValue(WCHAR* val_name, WCHAR* val_data, BOOL is_unicode)
return res; return res;
} }
static void closeKey(void)
{
if (currentKeyHandle)
{
HeapFree(GetProcessHeap(), 0, currentKeyName);
currentKeyName = NULL;
RegCloseKey(currentKeyHandle);
currentKeyHandle = NULL;
}
}
/****************************************************************************** /******************************************************************************
* A helper function for processRegEntry() that opens the current key. * Opens the registry key given by the input path.
* That key must be closed by calling closeKey(). * This key must be closed by calling close_key().
*/ */
static LONG openKeyW(WCHAR* stdInput) static LONG openKeyW(WCHAR* stdInput)
{ {
HKEY keyClass; HKEY key_class;
WCHAR* keyPath; WCHAR *key_path;
DWORD dwDisp;
LONG res; LONG res;
/* Sanity checks */ closeKey();
if (stdInput == NULL)
return ERROR_INVALID_PARAMETER;
/* Get the registry class */ /* Get the registry class */
if (!(keyClass = parseKeyName(stdInput, &keyPath))) if (!stdInput || !(key_class = parse_key_name(stdInput, &key_path)))
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
res = RegCreateKeyExW( res = RegCreateKeyExW(key_class, key_path, 0, NULL, REG_OPTION_NON_VOLATILE,
keyClass, /* Class */ KEY_ALL_ACCESS, NULL, &currentKeyHandle, NULL);
keyPath, /* Sub Key */
0, /* MUST BE 0 */
NULL, /* object type */
REG_OPTION_NON_VOLATILE, /* option, REG_OPTION_NON_VOLATILE ... */
KEY_ALL_ACCESS, /* access mask, KEY_ALL_ACCESS */
NULL, /* security attribute */
&currentKeyHandle, /* result */
&dwDisp); /* disposition, REG_CREATED_NEW_KEY or
REG_OPENED_EXISTING_KEY */
if (res == ERROR_SUCCESS) if (res == ERROR_SUCCESS)
{ {
...@@ -545,19 +550,6 @@ static LONG openKeyW(WCHAR* stdInput) ...@@ -545,19 +550,6 @@ static LONG openKeyW(WCHAR* stdInput)
} }
/****************************************************************************** /******************************************************************************
* Close the currently opened key.
*/
static void closeKey(void)
{
if (currentKeyHandle)
{
HeapFree(GetProcessHeap(), 0, currentKeyName);
RegCloseKey(currentKeyHandle);
currentKeyHandle = NULL;
}
}
/******************************************************************************
* This function is a wrapper for the setValue function. It prepares the * This function is a wrapper for the setValue function. It prepares the
* land and cleans the area once completed. * land and cleans the area once completed.
* Note: this function modifies the line parameter. * Note: this function modifies the line parameter.
...@@ -600,38 +592,6 @@ error: ...@@ -600,38 +592,6 @@ error:
output_message(STRING_INVALID_LINE_SYNTAX); output_message(STRING_INVALID_LINE_SYNTAX);
} }
/******************************************************************************
* This function receives the currently read entry and performs the
* corresponding action.
* isUnicode affects parsing of REG_MULTI_SZ values
*/
static void processRegEntry(WCHAR* stdInput, BOOL isUnicode)
{
if ( stdInput[0] == '[') /* We are reading a new key */
{
WCHAR* keyEnd;
closeKey(); /* Close the previous key */
/* Get rid of the square brackets */
stdInput++;
keyEnd = strrchrW(stdInput, ']');
if (keyEnd)
*keyEnd='\0';
else return;
/* delete the key if we encounter '-' at the start of reg key */
if (stdInput[0] == '-')
delete_registry_key(stdInput + 1);
else if (openKeyW(stdInput) != ERROR_SUCCESS)
output_message(STRING_OPEN_KEY_FAILED, stdInput);
} else if( currentKeyHandle &&
(( stdInput[0] == '@') || /* reading a default @=data pair */
( stdInput[0] == '\"'))) /* reading a new value=data pair */
{
processSetValue(stdInput, isUnicode);
}
}
enum reg_versions { enum reg_versions {
REG_VERSION_31, REG_VERSION_31,
REG_VERSION_40, REG_VERSION_40,
...@@ -765,11 +725,12 @@ static WCHAR *line_start_state(struct parser *parser, WCHAR *pos) ...@@ -765,11 +725,12 @@ static WCHAR *line_start_state(struct parser *parser, WCHAR *pos)
switch (*p) switch (*p)
{ {
case '[': case '[':
set_state(parser, KEY_NAME);
return p + 1;
case '@': case '@':
case '"': case '"':
processRegEntry(p, parser->is_unicode); processSetValue(p, parser->is_unicode);
set_state(parser, LINE_START); return p;
return line;
case ' ': case ' ':
case '\t': case '\t':
break; break;
...@@ -782,6 +743,41 @@ static WCHAR *line_start_state(struct parser *parser, WCHAR *pos) ...@@ -782,6 +743,41 @@ static WCHAR *line_start_state(struct parser *parser, WCHAR *pos)
return p; return p;
} }
/* handler for parser KEY_NAME state */
static WCHAR *key_name_state(struct parser *parser, WCHAR *pos)
{
WCHAR *p = pos, *key_end;
if (*p == ' ' || *p == '\t' || !(key_end = strrchrW(p, ']')))
goto done;
*key_end = 0;
if (*p == '-')
{
set_state(parser, DELETE_KEY);
return p + 1;
}
else if (openKeyW(p) != ERROR_SUCCESS)
output_message(STRING_OPEN_KEY_FAILED, p);
done:
set_state(parser, LINE_START);
return p;
}
/* handler for parser DELETE_KEY state */
static WCHAR *delete_key_state(struct parser *parser, WCHAR *pos)
{
WCHAR *p = pos;
if (*p == 'H')
delete_registry_key(p);
set_state(parser, LINE_START);
return p;
}
/* handler for parser SET_VALUE state */ /* handler for parser SET_VALUE state */
static WCHAR *set_value_state(struct parser *parser, WCHAR *pos) static WCHAR *set_value_state(struct parser *parser, WCHAR *pos)
{ {
...@@ -1348,7 +1344,7 @@ BOOL export_registry_key(WCHAR *file_name, WCHAR *reg_key_name, DWORD format) ...@@ -1348,7 +1344,7 @@ BOOL export_registry_key(WCHAR *file_name, WCHAR *reg_key_name, DWORD format)
lstrcpyW(reg_key_name_buf, reg_key_name); lstrcpyW(reg_key_name_buf, reg_key_name);
/* open the specified key */ /* open the specified key */
if (!(reg_key_class = parseKeyName(reg_key_name, &branch_name))) { if (!(reg_key_class = parse_key_name(reg_key_name, &branch_name))) {
output_message(STRING_INCORRECT_REG_CLASS, reg_key_name); output_message(STRING_INCORRECT_REG_CLASS, reg_key_name);
exit(1); exit(1);
} }
...@@ -1455,7 +1451,7 @@ void delete_registry_key(WCHAR *reg_key_name) ...@@ -1455,7 +1451,7 @@ void delete_registry_key(WCHAR *reg_key_name)
if (!reg_key_name || !reg_key_name[0]) if (!reg_key_name || !reg_key_name[0])
return; return;
if (!(key_class = parseKeyName(reg_key_name, &key_name))) { if (!(key_class = parse_key_name(reg_key_name, &key_name))) {
output_message(STRING_INCORRECT_REG_CLASS, reg_key_name); output_message(STRING_INCORRECT_REG_CLASS, reg_key_name);
exit(1); exit(1);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment