Hugh McMaster : regedit: Perform value name operations in the state machine.

Alexandre Julliard julliard at winehq.org
Thu Jun 15 15:34:19 CDT 2017


Module: wine
Branch: master
Commit: d60c31eadb121e834c44e4e8ff8cba663effc3e4
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=d60c31eadb121e834c44e4e8ff8cba663effc3e4

Author: Hugh McMaster <hugh.mcmaster at outlook.com>
Date:   Thu Jun 15 12:01:26 2017 +0000

regedit: Perform value name operations in the state machine.

Signed-off-by: Hugh McMaster <hugh.mcmaster at outlook.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 programs/regedit/regproc.c       | 146 +++++++++++++++++++++++++++------------
 programs/regedit/tests/regedit.c |   2 +-
 2 files changed, 101 insertions(+), 47 deletions(-)

diff --git a/programs/regedit/regproc.c b/programs/regedit/regproc.c
index e1352a7..ad3c5d5 100644
--- a/programs/regedit/regproc.c
+++ b/programs/regedit/regproc.c
@@ -138,6 +138,10 @@ enum parser_state
     LINE_START,          /* at the beginning of a registry line */
     KEY_NAME,            /* parsing a key name */
     DELETE_KEY,          /* deleting a registry key */
+    DEFAULT_VALUE_NAME,  /* parsing a default value name */
+    QUOTED_VALUE_NAME,   /* parsing a double-quoted value name */
+    DATA_START,          /* preparing for data parsing operations */
+    DELETE_VALUE,        /* deleting a registry value */
     SET_VALUE,           /* adding a value to the registry */
     NB_PARSER_STATES
 };
@@ -163,6 +167,10 @@ static WCHAR *parse_win31_line_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 *default_value_name_state(struct parser *parser, WCHAR *pos);
+static WCHAR *quoted_value_name_state(struct parser *parser, WCHAR *pos);
+static WCHAR *data_start_state(struct parser *parser, WCHAR *pos);
+static WCHAR *delete_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] =
@@ -172,6 +180,10 @@ static const parser_state_func parser_funcs[NB_PARSER_STATES] =
     line_start_state,          /* LINE_START */
     key_name_state,            /* KEY_NAME */
     delete_key_state,          /* DELETE_KEY */
+    default_value_name_state,  /* DEFAULT_VALUE_NAME */
+    quoted_value_name_state,   /* QUOTED_VALUE_NAME */
+    data_start_state,          /* DATA_START */
+    delete_value_state,        /* DELETE_VALUE */
     set_value_state,           /* SET_VALUE */
 };
 
@@ -435,7 +447,7 @@ static LONG setValue(WCHAR* val_name, WCHAR* val_data, BOOL is_unicode)
     DWORD  dwData, dwLen;
     WCHAR del[] = {'-',0};
 
-    if ( (val_name == NULL) || (val_data == NULL) )
+    if (!val_data)
         return ERROR_INVALID_PARAMETER;
 
     if (lstrcmpW(val_data, del) == 0)
@@ -549,49 +561,6 @@ static LONG openKeyW(WCHAR* stdInput)
 
 }
 
-/******************************************************************************
- * This function is a wrapper for the setValue function.  It prepares the
- * land and cleans the area once completed.
- * Note: this function modifies the line parameter.
- *
- * line - registry file unwrapped line. Should have the registry value name and
- *      complete registry value data.
- */
-static void processSetValue(WCHAR* line, BOOL is_unicode)
-{
-    WCHAR *val_name;
-    int len = 0;
-    LONG res;
-
-    /* get value name */
-    val_name = line;
-
-    if (*line == '@')
-        *line++ = 0;
-    else if (!REGPROC_unescape_string(++val_name, &line))
-        goto error;
-
-    while (*line == ' ' || *line == '\t') line++;
-    if (*line != '=')
-        goto error;
-    line++;
-    while (*line == ' ' || *line == '\t') line++;
-
-    /* trim trailing blanks */
-    len = strlenW(line);
-    while (len > 0 && (line[len - 1] == ' ' || line[len - 1] == '\t')) len--;
-    line[len] = 0;
-
-    res = setValue(val_name, line, is_unicode);
-    if ( res != ERROR_SUCCESS )
-        output_message(STRING_SETVALUE_FAILED, val_name, currentKeyName);
-    return;
-
-error:
-    output_message(STRING_SETVALUE_FAILED, val_name, currentKeyName);
-    output_message(STRING_INVALID_LINE_SYNTAX);
-}
-
 enum reg_versions {
     REG_VERSION_31,
     REG_VERSION_40,
@@ -728,9 +697,11 @@ static WCHAR *line_start_state(struct parser *parser, WCHAR *pos)
             set_state(parser, KEY_NAME);
             return p + 1;
         case '@':
-        case '"':
-            processSetValue(p, parser->is_unicode);
+            set_state(parser, DEFAULT_VALUE_NAME);
             return p;
+        case '"':
+            set_state(parser, QUOTED_VALUE_NAME);
+            return p + 1;
         case ' ':
         case '\t':
             break;
@@ -778,6 +749,86 @@ static WCHAR *delete_key_state(struct parser *parser, WCHAR *pos)
     return p;
 }
 
+/* handler for parser DEFAULT_VALUE_NAME state */
+static WCHAR *default_value_name_state(struct parser *parser, WCHAR *pos)
+{
+    parser->value_name = NULL;
+
+    set_state(parser, DATA_START);
+    return pos + 1;
+}
+
+/* handler for parser QUOTED_VALUE_NAME state */
+static WCHAR *quoted_value_name_state(struct parser *parser, WCHAR *pos)
+{
+    WCHAR *val_name = pos, *p;
+
+    if (parser->value_name)
+    {
+        HeapFree(GetProcessHeap(), 0, parser->value_name);
+        parser->value_name = NULL;
+    }
+
+    if (!REGPROC_unescape_string(val_name, &p))
+        goto invalid;
+
+    /* copy the value name in case we need to parse multiple lines and the buffer is overwritten */
+    parser->value_name = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(val_name) + 1) * sizeof(WCHAR));
+    CHECK_ENOUGH_MEMORY(parser->value_name);
+    lstrcpyW(parser->value_name, val_name);
+
+    set_state(parser, DATA_START);
+    return p;
+
+invalid:
+    set_state(parser, LINE_START);
+    return p;
+}
+
+/* handler for parser DATA_START state */
+static WCHAR *data_start_state(struct parser *parser, WCHAR *pos)
+{
+    WCHAR *p = pos;
+    unsigned int len;
+
+    while (*p == ' ' || *p == '\t') p++;
+    if (*p != '=') goto done;
+    p++;
+    while (*p == ' ' || *p == '\t') p++;
+
+    /* trim trailing whitespace */
+    len = strlenW(p);
+    while (len > 0 && (p[len - 1] == ' ' || p[len - 1] == '\t')) len--;
+    p[len] = 0;
+
+    if (*p == '-')
+    {
+        set_state(parser, DELETE_VALUE);
+        return p;
+    }
+    else if (setValue(parser->value_name, p, parser->is_unicode) != ERROR_SUCCESS)
+        output_message(STRING_SETVALUE_FAILED, parser->value_name, currentKeyName);
+
+done:
+    set_state(parser, LINE_START);
+    return p;
+}
+
+/* handler for parser DELETE_VALUE state */
+static WCHAR *delete_value_state(struct parser *parser, WCHAR *pos)
+{
+    WCHAR *p = pos + 1;
+
+    while (*p == ' ' || *p == '\t') p++;
+    if (*p && *p != ';') goto done;
+
+    RegDeleteValueW(currentKeyHandle, parser->value_name);
+
+done:
+    set_state(parser, LINE_START);
+    return p;
+}
+
 /* handler for parser SET_VALUE state */
 static WCHAR *set_value_state(struct parser *parser, WCHAR *pos)
 {
@@ -1432,6 +1483,9 @@ BOOL import_registry_file(FILE *reg_file)
     if (parser.reg_version == REG_VERSION_FUZZY || parser.reg_version == REG_VERSION_INVALID)
         return parser.reg_version == REG_VERSION_FUZZY;
 
+    if (parser.value_name)
+        HeapFree(GetProcessHeap(), 0, parser.value_name);
+
     closeKey();
     return TRUE;
 }
diff --git a/programs/regedit/tests/regedit.c b/programs/regedit/tests/regedit.c
index 32d190c..c7465d8 100644
--- a/programs/regedit/tests/regedit.c
+++ b/programs/regedit/tests/regedit.c
@@ -1289,7 +1289,7 @@ static void test_value_deletion(void)
     verify_reg_nonexist(hkey, "Wine46b");
     verify_reg_nonexist(hkey, "Wine46c");
     verify_reg(hkey, "Wine46d", REG_MULTI_SZ, "Line concatenation\0", 20, 0);
-    todo_wine verify_reg_nonexist(hkey, "Wine46e");
+    verify_reg_nonexist(hkey, "Wine46e");
     verify_reg(hkey, "Wine46f", REG_NONE, "V\0a\0l\0u\0e\0\0", 12, 0);
 
     lr = RegCloseKey(hkey);




More information about the wine-cvs mailing list