[PATCH 04/13] reg: Introduce a partial state machine for importing Windows 3.1 registry data

Hugh McMaster hugh.mcmaster at outlook.com
Fri Aug 18 04:30:04 CDT 2017


Signed-off-by: Hugh McMaster <hugh.mcmaster at outlook.com>
---
 programs/reg/import.c    | 408 ++++++++++++++++++++++++++++++++++++++++++++++-
 programs/reg/reg.c       |  12 +-
 programs/reg/reg.h       |  10 ++
 programs/reg/reg.rc      |   2 +
 programs/reg/resource.h  |   2 +
 programs/reg/tests/reg.c |  98 ++++++------
 6 files changed, 475 insertions(+), 57 deletions(-)

diff --git a/programs/reg/import.c b/programs/reg/import.c
index 734e6ae94c..ea070ef03d 100644
--- a/programs/reg/import.c
+++ b/programs/reg/import.c
@@ -17,14 +17,420 @@
  */
 
 #include <windows.h>
+#include <stdio.h>
+
+#include <wine/unicode.h>
 #include <wine/debug.h>
 
 #include "reg.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(reg);
 
+static WCHAR *GetWideString(const char *strA)
+{
+    if (strA)
+    {
+        WCHAR *strW;
+        int len = MultiByteToWideChar(CP_ACP, 0, strA, -1, NULL, 0);
+
+        strW = heap_xalloc(len * sizeof(WCHAR));
+        MultiByteToWideChar(CP_ACP, 0, strA, -1, strW, len);
+        return strW;
+    }
+    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 */
+    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 */
+    HKEY               hkey;           /* current registry key */
+    WCHAR             *key_name;       /* current key name */
+    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 *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 */
+    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;
+}
+
+static HKEY parse_key_name(WCHAR *key_name, WCHAR **key_path)
+{
+    if (!key_name) return 0;
+
+    *key_path = strchrW(key_name, '\\');
+    if (*key_path) (*key_path)++;
+
+    return path_get_rootkey(key_name);
+}
+
+static void close_key(struct parser *parser)
+{
+    if (parser->hkey)
+    {
+        heap_free(parser->key_name);
+        parser->key_name = NULL;
+
+        RegCloseKey(parser->hkey);
+        parser->hkey = NULL;
+    }
+}
+
+static LONG open_key(struct parser *parser, WCHAR *path)
+{
+    HKEY key_class;
+    WCHAR *key_path;
+    LONG res;
+
+    close_key(parser);
+
+    /* Get the registry class */
+    if (!path || !(key_class = parse_key_name(path, &key_path)))
+        return ERROR_INVALID_PARAMETER;
+
+    res = RegCreateKeyExW(key_class, key_path, 0, NULL, REG_OPTION_NON_VOLATILE,
+                          KEY_ALL_ACCESS, NULL, &parser->hkey, NULL);
+
+    if (res == ERROR_SUCCESS)
+    {
+        parser->key_name = heap_xalloc((lstrlenW(path) + 1) * sizeof(WCHAR));
+        lstrcpyW(parser->key_name, path);
+    }
+    else
+        parser->hkey = NULL;
+
+    return res;
+}
+
+static void free_parser_data(struct parser *parser)
+{
+    parser->data = NULL;
+    parser->data_size = 0;
+}
+
+enum reg_versions {
+    REG_VERSION_31,
+    REG_VERSION_40,
+    REG_VERSION_50,
+    REG_VERSION_FUZZY,
+    REG_VERSION_INVALID
+};
+
+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};
+    static const WCHAR header_50[] = {'W','i','n','d','o','w','s',' ',
+                                      'R','e','g','i','s','t','r','y',' ','E','d','i','t','o','r',' ',
+                                      'V','e','r','s','i','o','n',' ','5','.','0','0',0};
+
+    while (*s == ' ' || *s == '\t') s++;
+
+    if (!strcmpW(s, header_31))
+        return REG_VERSION_31;
+
+    if (!strcmpW(s, header_40))
+        return REG_VERSION_40;
+
+    if (!strcmpW(s, header_50))
+        return REG_VERSION_50;
+
+    /* The Windows version accepts registry file headers beginning with "REGEDIT" and ending
+     * with other characters, as long as "REGEDIT" appears at the start of the line. For example,
+     * "REGEDIT 4", "REGEDIT9" and "REGEDIT4FOO" are all treated as valid file headers.
+     * In all such cases, however, the contents of the registry file are not imported.
+     */
+    if (!strncmpW(s, header_31, 7)) /* "REGEDIT" without NUL */
+        return REG_VERSION_FUZZY;
+
+    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 = heap_xalloc((lstrlenW(line) + 3) * sizeof(WCHAR));
+        header[0] = parser->two_wchars[0];
+        header[1] = parser->two_wchars[1];
+        lstrcpyW(header + 2, line);
+        parser->reg_version = parse_file_header(header);
+        heap_free(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:
+    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)))
+        return line;
+
+    /* 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;
+
+    if (open_key(parser, line) != ERROR_SUCCESS)
+    {
+        output_message(STRING_OPEN_KEY_FAILED, line);
+        return line;
+    }
+
+    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;
+}
+
+/* handler for parser SET_VALUE state */
+static WCHAR *set_value_state(struct parser *parser, WCHAR *pos)
+{
+    RegSetValueExW(parser->hkey, parser->value_name, 0, parser->data_type,
+                   parser->data, parser->data_size);
+
+    free_parser_data(parser);
+
+    set_state(parser, PARSE_WIN31_LINE);
+
+    return pos;
+}
+
+#define REG_VAL_BUF_SIZE  4096
+
+static WCHAR *get_lineA(FILE *fp)
+{
+    static WCHAR *lineW;
+    static size_t size;
+    static char *buf, *next;
+    char *line;
+
+    heap_free(lineW);
+
+    if (!fp) goto cleanup;
+
+    if (!size)
+    {
+        size = REG_VAL_BUF_SIZE;
+        buf = heap_xalloc(size);
+        *buf = 0;
+        next = buf;
+    }
+    line = next;
+
+    while (next)
+    {
+        char *p = strpbrk(line, "\r\n");
+        if (!p)
+        {
+            size_t len, count;
+            len = strlen(next);
+            memmove(buf, next, len + 1);
+            if (size - len < 3)
+            {
+                size *= 2;
+                buf = heap_xrealloc(buf, size);
+            }
+            if (!(count = fread(buf + len, 1, size - len - 1, fp)))
+            {
+                next = NULL;
+                lineW = GetWideString(buf);
+                return lineW;
+            }
+            buf[len + count] = 0;
+            next = buf;
+            line = buf;
+            continue;
+        }
+        next = p + 1;
+        if (*p == '\r' && *(p + 1) == '\n') next++;
+        *p = 0;
+        lineW = GetWideString(line);
+        return lineW;
+    }
+
+cleanup:
+    lineW = NULL;
+    if (size) heap_free(buf);
+    size = 0;
+    return NULL;
+}
+
+static WCHAR *get_lineW(FILE *fp)
+{
+    static size_t size;
+    static WCHAR *buf, *next;
+    WCHAR *line;
+
+    if (!fp) goto cleanup;
+
+    if (!size)
+    {
+        size = REG_VAL_BUF_SIZE;
+        buf = heap_xalloc(size * sizeof(WCHAR));
+        *buf = 0;
+        next = buf;
+    }
+    line = next;
+
+    while (next)
+    {
+        static const WCHAR line_endings[] = {'\r','\n',0};
+        WCHAR *p = strpbrkW(line, line_endings);
+        if (!p)
+        {
+            size_t len, count;
+            len = strlenW(next);
+            memmove(buf, next, (len + 1) * sizeof(WCHAR));
+            if (size - len < 3)
+            {
+                size *= 2;
+                buf = heap_xrealloc(buf, size * sizeof(WCHAR));
+            }
+            if (!(count = fread(buf + len, sizeof(WCHAR), size - len - 1, fp)))
+            {
+                next = NULL;
+                return buf;
+            }
+            buf[len + count] = 0;
+            next = buf;
+            line = buf;
+            continue;
+        }
+        next = p + 1;
+        if (*p == '\r' && *(p + 1) == '\n') next++;
+        *p = 0;
+        return line;
+    }
+
+cleanup:
+    if (size) heap_free(buf);
+    size = 0;
+    return NULL;
+}
+
 int reg_import(const WCHAR *filename)
 {
-    FIXME(": operation not yet implemented\n");
+    FILE *fp;
+    static const WCHAR rb_mode[] = {'r','b',0};
+    BYTE s[2];
+    struct parser parser;
+    WCHAR *pos;
+
+    fp = _wfopen(filename, rb_mode);
+    if (!fp)
+    {
+        output_message(STRING_FILE_NOT_FOUND, filename);
+        return 1;
+    }
+
+    if (fread(s, sizeof(WCHAR), 1, fp) != 1)
+        goto error;
+
+    parser.is_unicode = (s[0] == 0xff && s[1] == 0xfe);
+    get_line = parser.is_unicode ? get_lineW : get_lineA;
+
+    parser.file          = fp;
+    parser.two_wchars[0] = s[0];
+    parser.two_wchars[1] = s[1];
+    parser.reg_version   = -1;
+    parser.hkey          = NULL;
+    parser.key_name      = NULL;
+    parser.data_type     = 0;
+    parser.data          = NULL;
+    parser.data_size     = 0;
+    parser.state         = HEADER;
+
+    pos = parser.two_wchars;
+
+    /* parser main loop */
+    while (pos)
+        pos = (parser_funcs[parser.state])(&parser, pos);
+
+    if (parser.reg_version == REG_VERSION_INVALID)
+        goto error;
+    else if (parser.reg_version == REG_VERSION_40 || parser.reg_version == REG_VERSION_50)
+    {
+        FIXME(": operation not yet implemented\n");
+        goto error;
+    }
+
+    close_key(&parser);
+
+    fclose(fp);
+    return 0;
+
+error:
+    fclose(fp);
     return 1;
 }
diff --git a/programs/reg/reg.c b/programs/reg/reg.c
index 43e5321704..fac3d22ea1 100644
--- a/programs/reg/reg.c
+++ b/programs/reg/reg.c
@@ -23,8 +23,6 @@
 #include <wine/debug.h>
 #include "reg.h"
 
-#define ARRAY_SIZE(A) (sizeof(A)/sizeof(*A))
-
 WINE_DEFAULT_DEBUG_CHANNEL(reg);
 
 static const WCHAR short_hklm[] = {'H','K','L','M',0};
@@ -79,7 +77,7 @@ type_rels[] =
     {REG_MULTI_SZ, type_multi_sz},
 };
 
-static void *heap_xalloc(size_t size)
+void *heap_xalloc(size_t size)
 {
     void *buf = HeapAlloc(GetProcessHeap(), 0, size);
     if (!buf)
@@ -90,7 +88,7 @@ static void *heap_xalloc(size_t size)
     return buf;
 }
 
-static void *heap_xrealloc(void *buf, size_t size)
+void *heap_xrealloc(void *buf, size_t size)
 {
     void *new_buf;
 
@@ -108,7 +106,7 @@ static void *heap_xrealloc(void *buf, size_t size)
     return new_buf;
 }
 
-static BOOL heap_free(void *buf)
+BOOL heap_free(void *buf)
 {
     return HeapFree(GetProcessHeap(), 0, buf);
 }
@@ -153,7 +151,7 @@ static void output_formatstring(const WCHAR *fmt, __ms_va_list va_args)
     LocalFree(str);
 }
 
-static void __cdecl output_message(unsigned int id, ...)
+void __cdecl output_message(unsigned int id, ...)
 {
     WCHAR fmt[1024];
     __ms_va_list va_args;
@@ -216,7 +214,7 @@ static inline BOOL path_rootname_cmp(const WCHAR *input_path, const WCHAR *rootk
             (input_path[length] == 0 || input_path[length] == '\\'));
 }
 
-static HKEY path_get_rootkey(const WCHAR *path)
+HKEY path_get_rootkey(const WCHAR *path)
 {
     DWORD i;
 
diff --git a/programs/reg/reg.h b/programs/reg/reg.h
index 1fbef7806c..14c05b13d4 100644
--- a/programs/reg/reg.h
+++ b/programs/reg/reg.h
@@ -21,6 +21,16 @@
 
 #include "resource.h"
 
+#define ARRAY_SIZE(A) (sizeof(A)/sizeof(*A))
+
+/* reg.c */
+void *heap_xalloc(size_t size);
+void *heap_xrealloc(void *buf, size_t size);
+BOOL heap_free(void *buf);
+void __cdecl output_message(unsigned int id, ...);
+HKEY path_get_rootkey(const WCHAR *path);
+
+/* import.c */
 int reg_import(const WCHAR *filename);
 
 #endif /* __REG_H__ */
diff --git a/programs/reg/reg.rc b/programs/reg/reg.rc
index e26970916f..6d4ccb593f 100644
--- a/programs/reg/reg.rc
+++ b/programs/reg/reg.rc
@@ -63,4 +63,6 @@ STRINGTABLE
     STRING_FUNC_HELP, "Type \"REG %1 /?\" for help.\n"
     STRING_VALUE_NOT_SET, "(value not set)"
     STRING_IMPORT_USAGE, "REG IMPORT file.reg\n"
+    STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
+    STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
 }
diff --git a/programs/reg/resource.h b/programs/reg/resource.h
index 31a83ee115..653a9d1e60 100644
--- a/programs/reg/resource.h
+++ b/programs/reg/resource.h
@@ -53,3 +53,5 @@
 #define STRING_FUNC_HELP        130
 #define STRING_VALUE_NOT_SET    131
 #define STRING_IMPORT_USAGE     132
+#define STRING_FILE_NOT_FOUND   133
+#define STRING_OPEN_KEY_FAILED  134
diff --git a/programs/reg/tests/reg.c b/programs/reg/tests/reg.c
index 69c01c00b9..2a6f35165e 100644
--- a/programs/reg/tests/reg.c
+++ b/programs/reg/tests/reg.c
@@ -847,10 +847,10 @@ static void test_import(void)
        "got exit code %d, expected 1\n", r);
 
     test_import_str("REGEDIT", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
 
     test_import_str("REGEDIT\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
 
     test_import_str("REGEDIT4\n", &r);
     todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
@@ -874,19 +874,19 @@ static void test_import(void)
        "got exit code %d, expected 1\n", r);
 
     test_import_str("REGEDIT3\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
 
     test_import_str("REGEDIT5\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
 
     test_import_str("REGEDIT9\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
 
     test_import_str("REGEDIT 4\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
 
     test_import_str("REGEDIT4 FOO\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
 
     test_import_str("REGEDIT4\n"
                     "[HKEY_CURRENT_USER\\" KEY_BASE "]\n", &r);
@@ -898,7 +898,7 @@ static void test_import(void)
     test_import_str("REGEDIT3\n\n"
                     "[HKEY_CURRENT_USER\\" KEY_BASE "]\n"
                     "\"Test1\"=\"Value\"\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
     todo_wine verify_reg_nonexist(hkey, "Test1");
 
     test_import_str("regedit4\n\n"
@@ -918,31 +918,31 @@ static void test_import(void)
     test_import_str("REGEDIT 4\n\n"
                     "[HKEY_CURRENT_USER\\" KEY_BASE "]\n"
                     "\"Test4\"=\"Value\"\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
     todo_wine verify_reg_nonexist(hkey, "Test4");
 
     test_import_str("REGEDIT4FOO\n\n"
                     "[HKEY_CURRENT_USER\\" KEY_BASE "]\n"
                     "\"Test5\"=\"Value\"\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
     todo_wine verify_reg_nonexist(hkey, "Test5");
 
     test_import_str("REGEDIT4 FOO\n\n"
                     "[HKEY_CURRENT_USER\\" KEY_BASE "]\n"
                     "\"Test6\"=\"Value\"\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
     todo_wine verify_reg_nonexist(hkey, "Test6");
 
     test_import_str("REGEDIT5\n\n"
                     "[HKEY_CURRENT_USER\\" KEY_BASE "]\n"
                     "\"Test7\"=\"Value\"\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
     todo_wine verify_reg_nonexist(hkey, "Test7");
 
     test_import_str("REGEDIT9\n\n"
                     "[HKEY_CURRENT_USER\\" KEY_BASE "]\n"
                     "\"Test8\"=\"Value\"\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
     todo_wine verify_reg_nonexist(hkey, "Test8");
 
     test_import_str("Windows Registry Editor Version 4.00\n\n"
@@ -2304,10 +2304,10 @@ static void test_unicode_import(void)
        "got exit code %d, expected 1\n", r);
 
     test_import_wstr("\xef\xbb\xbfREGEDIT", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
 
     test_import_wstr("\xef\xbb\xbfREGEDIT\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
 
     test_import_wstr("\xef\xbb\xbfREGEDIT4", &r);
     todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
@@ -2335,7 +2335,7 @@ static void test_unicode_import(void)
     test_import_wstr("\xef\xbb\xbfREGEDIT3\n\n"
                      "[HKEY_CURRENT_USER\\" KEY_BASE "]\n"
                      "\"Test1\"=\"Value\"\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
     todo_wine verify_reg_nonexist(hkey, "Test1");
 
     test_import_wstr("\xef\xbb\xbfregedit4\n\n"
@@ -2355,31 +2355,31 @@ static void test_unicode_import(void)
     test_import_wstr("\xef\xbb\xbfREGEDIT 4\n\n"
                      "[HKEY_CURRENT_USER\\" KEY_BASE "]\n"
                      "\"Test4\"=\"Value\"\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
     todo_wine verify_reg_nonexist(hkey, "Test4");
 
     test_import_wstr("\xef\xbb\xbfREGEDIT4FOO\n\n"
                      "[HKEY_CURRENT_USER\\" KEY_BASE "]\n"
                      "\"Test5\"=\"Value\"\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
     todo_wine verify_reg_nonexist(hkey, "Test5");
 
     test_import_wstr("\xef\xbb\xbfREGEDIT4 FOO\n\n"
                      "[HKEY_CURRENT_USER\\" KEY_BASE "]\n"
                      "\"Test6\"=\"Value\"\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
     todo_wine verify_reg_nonexist(hkey, "Test6");
 
     test_import_wstr("\xef\xbb\xbfREGEDIT5\n\n"
                      "[HKEY_CURRENT_USER\\" KEY_BASE "]\n"
                      "\"Test7\"=\"Value\"\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
     todo_wine verify_reg_nonexist(hkey, "Test7");
 
     test_import_wstr("\xef\xbb\xbfREGEDIT9\n\n"
                      "[HKEY_CURRENT_USER\\" KEY_BASE "]\n"
                      "\"Test8\"=\"Value\"\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
     todo_wine verify_reg_nonexist(hkey, "Test8");
 
     test_import_wstr("\xef\xbb\xbfREGEDIT4\n"
@@ -4074,94 +4074,94 @@ static void test_import_31(void)
 
     /* Test simple value */
     test_import_str("REGEDIT\r\n"
-		    "HKEY_CLASSES_ROOT\\" KEY_BASE " = Value0\r\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
-    todo_wine verify_reg(hkey, "", REG_SZ, "Value0", 7, 0);
+                    "HKEY_CLASSES_ROOT\\" KEY_BASE " = Value0\r\n", &r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    verify_reg(hkey, "", REG_SZ, "Value0", 7, 0);
 
     /* Test proper handling of spaces and equals signs */
     test_import_str("REGEDIT\r\n"
                     "HKEY_CLASSES_ROOT\\" KEY_BASE " =Value1\r\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
-    todo_wine verify_reg(hkey, "", REG_SZ, "Value1", 7, 0);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    verify_reg(hkey, "", REG_SZ, "Value1", 7, 0);
 
     test_import_str("REGEDIT\r\n"
                     "HKEY_CLASSES_ROOT\\" KEY_BASE " =  Value2\r\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
-    todo_wine verify_reg(hkey, "", REG_SZ, " Value2", 8, 0);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    verify_reg(hkey, "", REG_SZ, " Value2", 8, 0);
 
     test_import_str("REGEDIT\r\n"
                     "HKEY_CLASSES_ROOT\\" KEY_BASE " = Value3 \r\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
-    todo_wine verify_reg(hkey, "", REG_SZ, "Value3 ", 8, 0);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    verify_reg(hkey, "", REG_SZ, "Value3 ", 8, 0);
 
     test_import_str("REGEDIT\r\n"
                     "HKEY_CLASSES_ROOT\\" KEY_BASE " Value4\r\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
-    todo_wine verify_reg(hkey, "", REG_SZ, "Value4", 7, 0);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    verify_reg(hkey, "", REG_SZ, "Value4", 7, 0);
 
     test_import_str("REGEDIT\r\n"
                     "HKEY_CLASSES_ROOT\\" KEY_BASE "  Value5\r\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
-    todo_wine verify_reg(hkey, "", REG_SZ, "Value5", 7, 0);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    verify_reg(hkey, "", REG_SZ, "Value5", 7, 0);
 
     test_import_str("REGEDIT\r\n"
                     "HKEY_CLASSES_ROOT\\" KEY_BASE "\r\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
-    todo_wine verify_reg(hkey, "", REG_SZ, "", 1, 0);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    verify_reg(hkey, "", REG_SZ, "", 1, 0);
 
     test_import_str("REGEDIT\r\n"
                     "HKEY_CLASSES_ROOT\\" KEY_BASE "  \r\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
-    todo_wine verify_reg(hkey, "", REG_SZ, "", 1, 0);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    verify_reg(hkey, "", REG_SZ, "", 1, 0);
 
     test_import_str("REGEDIT\r\n"
                     "HKEY_CLASSES_ROOT\\" KEY_BASE " = No newline", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
-    todo_wine verify_reg(hkey, "", REG_SZ, "No newline", 11, 0);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    verify_reg(hkey, "", REG_SZ, "No newline", 11, 0);
 
     err = RegDeleteValueW(hkey, NULL);
-    todo_wine ok(err == ERROR_SUCCESS, "RegDeleteValue failed: %d\n", err);
+    ok(err == ERROR_SUCCESS, "RegDeleteValue failed: %d\n", err);
 
     /* Test character validity at the start of the line */
     test_import_str("REGEDIT\r\n"
                     " HKEY_CLASSES_ROOT\\" KEY_BASE " = Value1a\r\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
     verify_reg_nonexist(hkey, "");
 
     test_import_str("REGEDIT\r\n"
                     "  HKEY_CLASSES_ROOT\\" KEY_BASE " = Value1b\r\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
     verify_reg_nonexist(hkey, "");
 
     test_import_str("REGEDIT\r\n"
                     "\tHKEY_CLASSES_ROOT\\" KEY_BASE " = Value1c\r\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
     verify_reg_nonexist(hkey, "");
 
     test_import_str("REGEDIT\r\n"
                     ";HKEY_CLASSES_ROOT\\" KEY_BASE " = Value2a\r\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
     verify_reg_nonexist(hkey, "");
 
     test_import_str("REGEDIT\r\n"
                     "#HKEY_CLASSES_ROOT\\" KEY_BASE " = Value2b\r\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
     verify_reg_nonexist(hkey, "");
 
     /* Test case sensitivity */
     test_import_str("REGEDIT\r\n"
                     "hkey_classes_root\\" KEY_BASE " = Value3a\r\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
     verify_reg_nonexist(hkey, "");
 
     test_import_str("REGEDIT\r\n"
                     "hKEY_CLASSES_ROOT\\" KEY_BASE " = Value3b\r\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
     verify_reg_nonexist(hkey, "");
 
     test_import_str("REGEDIT\r\n"
                     "Hkey_Classes_Root\\" KEY_BASE " = Value3c\r\n", &r);
-    todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+    ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
     verify_reg_nonexist(hkey, "");
 
     RegCloseKey(hkey);
-- 
2.14.1




More information about the wine-patches mailing list