[PATCH 2/4] reg: Add wchar/raw data conversion functions

xantares 09 xantares09 at hotmail.com
Fri Jul 31 00:59:42 CDT 2015


---

 programs/reg/reg.c       | 145 ++++++++++++++++++++++++++++++++++++++---------

 programs/reg/reg.h       |   1 +

 programs/reg/reg.rc      |   1 +

 programs/reg/tests/reg.c |  57 +++++++++----------

 4 files changed, 149 insertions(+), 55 deletions(-)



diff --git a/programs/reg/reg.c b/programs/reg/reg.c

index cf6425e..b2447fc 100644

--- a/programs/reg/reg.c

+++ b/programs/reg/reg.c

@@ -18,10 +18,15 @@

  
 #include <windows.h>

 #include <wine/unicode.h>

+#include <wine/debug.h>

 #include "reg.h"

  
 #define ARRAY_SIZE(A) (sizeof(A)/sizeof(*A))

  
+WINE_DEFAULT_DEBUG_CHANNEL(reg);

+

+static const WCHAR empty_wstr[] = {0};

+

 static const WCHAR short_hklm[] = {'H','K','L','M',0};

 static const WCHAR short_hkcu[] = {'H','K','C','U',0};

 static const WCHAR short_hkcr[] = {'H','K','C','R',0};

@@ -189,43 +194,126 @@ static DWORD wchar_get_type(const WCHAR *type_name)

     return ~0u;

 }

  
-static LPBYTE get_regdata(LPWSTR data, DWORD reg_type, WCHAR separator, DWORD *reg_count)

+static BYTE *wchar_get_data(const WCHAR *input, const DWORD type, const WCHAR separator,

+    DWORD *size_out)

 {

-    LPBYTE out_data = NULL;

-    *reg_count = 0;

+    DWORD i;

+

+    if (!input)

+        input = empty_wstr;

  
-    switch (reg_type)

+    switch (type)

     {

+        case REG_NONE:

         case REG_SZ:

+        case REG_EXPAND_SZ:

         {

-            *reg_count = (lstrlenW(data) + 1) * sizeof(WCHAR);

-            out_data = HeapAlloc(GetProcessHeap(),0,*reg_count);

-            lstrcpyW((LPWSTR)out_data,data);

-            break;

+            BYTE *data;

+

+            i = (strlenW(input) + 1) * sizeof(WCHAR);

+            *size_out = i;

+            data = HeapAlloc(GetProcessHeap(), 0, i);

+            memcpy(data, input, i);

+            return data;

         }

         case REG_DWORD:

+        case REG_DWORD_BIG_ENDIAN:

         {

-            LPWSTR rest;

-            DWORD val;

-            val = strtolW(data, &rest, 0);

-            if (rest == data) {

-                static const WCHAR nonnumber[] = {'E','r','r','o','r',':',' ','/','d',' ','r','e','q','u','i','r','e','s',' ','n','u','m','b','e','r','.','\n',0};

-                reg_printfW(nonnumber);

-                break;

+            BYTE *data;

+            WCHAR *temp;

+

+            if (input[0] == '0' && (input[1] == 'x' || input[1] == 'X'))

+                i = strtoulW(input, &temp, 16);

+            else

+                i = strtoulW(input, &temp, 10);

+

+            if (input[0] == '-' || temp[0] || temp == input)

+            {

+                reg_message(STRING_INVALID_DWORD);

+                return NULL;

             }

-            *reg_count = sizeof(DWORD);

-            out_data = HeapAlloc(GetProcessHeap(),0,*reg_count);

-            ((LPDWORD)out_data)[0] = val;

-            break;

+

+            if (i == 0xffffffff)

+                WINE_FIXME("Check for integer overflow.\n");

+

+            data = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD));

+            *(DWORD *) data = i;

+            *size_out = sizeof(DWORD);

+            return data;

+        }

+        case REG_MULTI_SZ:

+        {

+            WCHAR *data = HeapAlloc(GetProcessHeap(), 0, (strlenW(input) + 1) * sizeof(WCHAR));

+            DWORD p;

+

+            for (i = 0, p = 0; i <= strlenW(input); i++, p++)

+            {

+                /* If this character is the separator, or no separator has been given and these

+                 * characters are "\\0", then add a 0 indicating the end of this string */

+                if ( (separator && input[i] == separator) ||

+                     (!separator && input[i] == '\\' && input[i + 1] == '0') )

+                {

+                    /* If it's the first character or the previous one was a separator */

+                    if (!p || data[p - 1] == 0)

+                    {

+                        HeapFree(GetProcessHeap(), 0, data);

+                        reg_message(STRING_INVALID_CMDLINE);

+                        return NULL;

+                    }

+                    data[p] = 0;

+

+                    if (!separator)

+                        i++;

+                }

+                else

+                    data[p] = input[i];

+            }

+

+            /* Add a 0 to the end if the string wasn't "", and it wasn't

+             * double-0-terminated already (In the case of a trailing separator) */

+            if (p > 1 && data[p - 2])

+                data[p++] = 0;

+

+            *size_out = p * sizeof(WCHAR);

+            return (BYTE *) data;

+        }

+        case REG_BINARY:

+        {

+            BYTE *data = HeapAlloc(GetProcessHeap(), 0, strlenW(input));

+            DWORD p, odd;

+

+            for (i = 0; i < strlenW(input); i++)

+            {

+                if (input[i] >= '0' && input[i] <= '9')

+                    data[i] = input[i] - '0';

+                else if (input[i] >= 'a' && input[i] <= 'f')

+                    data[i] = input[i] - 'a' + 10;

+                else if (input[i] >= 'A' && input[i] <= 'F')

+                    data[i] = input[i] - 'A' + 10;

+                else

+                {

+                    HeapFree(GetProcessHeap(), 0, data);

+                    reg_message(STRING_INVALID_CMDLINE);

+                    return NULL;

+                }

+            }

+

+            odd = i & 1;

+            p = i >> 1;

+            data += odd;

+

+            for (i = 0; i < p; i++)

+                data[i] = (data[i * 2] << 4) | data[i * 2 + 1];

+

+            *size_out = p + odd;

+            return data - odd;

         }

         default:

         {

-            static const WCHAR unhandled[] = {'U','n','h','a','n','d','l','e','d',' ','T','y','p','e',' ','0','x','%','x',' ',' ','d','a','t','a',' ','%','s','\n',0};

-            reg_printfW(unhandled, reg_type,data);

+            WINE_FIXME("Add support for registry type: %u\n", type);

+            return NULL;

         }

     }

-

-    return out_data;

 }

  
 static BOOL sane_path(const WCHAR *key)

@@ -286,7 +374,14 @@ static int reg_add(WCHAR *key_name, WCHAR *value_name, BOOL value_empty,

         }

  
         if (data)

-            reg_data = get_regdata(data,reg_type,separator,®_count);

+        {

+            reg_data = wchar_get_data(data, reg_type, separator, ®_count);

+            if (!reg_data)

+            {

+                RegCloseKey(subkey);

+                return 1;

+            }

+        }

  
         RegSetValueExW(subkey,value_name,0,reg_type,reg_data,reg_count);

         HeapFree(GetProcessHeap(),0,reg_data);

@@ -336,8 +431,6 @@ static int reg_delete(WCHAR *key_name, WCHAR *value_name, BOOL value_empty,

     /* Delete subtree only if no /v* option is given */

     if (!value_name && !value_empty && !value_all)

     {

-        static const WCHAR empty_wstr[] = {0};

-

         err = RegDeleteTreeW(subkey, NULL);

         if (err != ERROR_SUCCESS)

         {

diff --git a/programs/reg/reg.h b/programs/reg/reg.h

index 6fca7eb..c6fb151 100644

--- a/programs/reg/reg.h

+++ b/programs/reg/reg.h

@@ -31,3 +31,4 @@

 #define STRING_NO_REMOTE        108

 #define STRING_CANNOT_FIND      109

 #define STRING_UNSUPPORTED_TYPE 110

+#define STRING_INVALID_DWORD    111

diff --git a/programs/reg/reg.rc b/programs/reg/reg.rc

index 94dddf2..dbd92ea 100644

--- a/programs/reg/reg.rc

+++ b/programs/reg/reg.rc

@@ -36,4 +36,5 @@ STRINGTABLE

     STRING_NO_REMOTE, "Error: Unable to access remote machine\n"

     STRING_CANNOT_FIND, "Error: The system was unable to find the specified registry key or value\n"

     STRING_UNSUPPORTED_TYPE, "Error: Unsupported type\n"

+    STRING_INVALID_DWORD, "Error: /d must be positive number\n"

 }

diff --git a/programs/reg/tests/reg.c b/programs/reg/tests/reg.c

index dbfce89..99b4813 100644

--- a/programs/reg/tests/reg.c

+++ b/programs/reg/tests/reg.c

@@ -154,7 +154,7 @@ static void test_add(void)

     /* REG_NONE */

     run_reg_exe("reg add HKCU\\" KEY_BASE " /v none0 /d deadbeef /t REG_NONE /f", &r);

     ok(r == REG_EXIT_SUCCESS, "got exit code %d\n", r);

-    verify_reg(hkey, "none0", REG_NONE, "d\0e\0a\0d\0b\0e\0e\0f\0\0", 18, TODO_REG_SIZE);

+    verify_reg(hkey, "none0", REG_NONE, "d\0e\0a\0d\0b\0e\0e\0f\0\0", 18, 0);

  
     /* REG_SZ */

     run_reg_exe("reg add HKCU\\" KEY_BASE " /d WineTest /f", &r);

@@ -188,11 +188,11 @@ static void test_add(void)

     /* REG_EXPAND_SZ */

     run_reg_exe("reg add HKCU\\" KEY_BASE " /v expand0 /t REG_EXpand_sz /d \"dead%PATH%beef\" /f", &r);

     ok(r == REG_EXIT_SUCCESS, "got exit code %u\n", r);

-    verify_reg(hkey, "expand0", REG_EXPAND_SZ, "dead%PATH%beef", 15, TODO_REG_SIZE);

+    verify_reg(hkey, "expand0", REG_EXPAND_SZ, "dead%PATH%beef", 15, 0);

  
     run_reg_exe("reg add HKCU\\" KEY_BASE " /v expand1 /t REG_EXpand_sz /d \"dead^%PATH^%beef\" /f", &r);

     ok(r == REG_EXIT_SUCCESS, "got exit code %u\n", r);

-    verify_reg(hkey, "expand1", REG_EXPAND_SZ, "dead^%PATH^%beef", 17, TODO_REG_SIZE);

+    verify_reg(hkey, "expand1", REG_EXPAND_SZ, "dead^%PATH^%beef", 17, 0);

  
     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_EXPAND_SZ /v expand2 /f", &r);

     ok(r == REG_EXIT_SUCCESS, "got exit code %u\n", r);

@@ -200,11 +200,11 @@ static void test_add(void)

  
     run_reg_exe("reg add HKEY_CURRENT_USER\\" KEY_BASE " /ve /t REG_EXPAND_SZ /d WineTEST /f", &r);

     ok(r == REG_EXIT_SUCCESS, "got exit code %u\n", r);

-    verify_reg(hkey, "", REG_EXPAND_SZ, "WineTEST", 9, TODO_REG_SIZE);

+    verify_reg(hkey, "", REG_EXPAND_SZ, "WineTEST", 9, 0);

  
     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_EXPAND_SZ /v expand3 /f /d \"\"", &r);

     ok(r == REG_EXIT_SUCCESS, "got exit code %u\n", r);

-    verify_reg(hkey, "expand3", REG_EXPAND_SZ, "", 1, TODO_REG_SIZE);

+    verify_reg(hkey, "expand3", REG_EXPAND_SZ, "", 1, 0);

  
     /* REG_BINARY */

     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_BINARY /v bin0 /f", &r);

@@ -214,14 +214,14 @@ static void test_add(void)

     run_reg_exe("reg add HKEY_CURRENT_USER\\" KEY_BASE " /ve /t REG_BINARY /d deadbeef /f", &r);

     ok(r == REG_EXIT_SUCCESS, "got exit code %u\n", r);

     dword = 0xefbeadde;

-    verify_reg(hkey, "", REG_BINARY, &dword, sizeof(DWORD), TODO_REG_SIZE);

+    verify_reg(hkey, "", REG_BINARY, &dword, sizeof(DWORD), 0);

  
     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_BINARY /v bin1 /f /d 0xDeAdBeEf", &r);

-    todo_wine ok(r == REG_EXIT_FAILURE, "got exit code %u\n", r);

+    ok(r == REG_EXIT_FAILURE, "got exit code %u\n", r);

     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_BINARY /v bin2 /f /d x01", &r);

-    todo_wine ok(r == REG_EXIT_FAILURE, "got exit code %u\n", r);

+    ok(r == REG_EXIT_FAILURE, "got exit code %u\n", r);

     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_BINARY /v bin3 /f /d 01x", &r);

-    todo_wine ok(r == REG_EXIT_FAILURE, "got exit code %u\n", r);

+    ok(r == REG_EXIT_FAILURE, "got exit code %u\n", r);

  
     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_BINARY /v bin4 /f /d DeAdBeEf0DD", &r);

     ok(r == REG_EXIT_SUCCESS, "got exit code %u\n", r);

@@ -235,8 +235,8 @@ static void test_add(void)

     err = RegQueryValueExA(hkey, "bin4", NULL, &type, (void *) (buffer+12), &size);

     ok(err == ERROR_SUCCESS, "RegQueryValueEx failed: got %d\n", err);

     ok(type == REG_BINARY, "got wrong type %u\n", type);

-    todo_wine ok(size == 6, "got wrong size %u\n", size);

-    todo_wine ok(memcmp(buffer, buffer+12, 6) == 0 ||

+    ok(size == 6, "got wrong size %u\n", size);

+    ok(memcmp(buffer, buffer+12, 6) == 0 ||

         broken(memcmp(buffer+6, buffer+12, 6) == 0 /* WinXP */), "got wrong data\n");

  
     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_BINARY /v bin5 /d \"\" /f", &r);

@@ -257,11 +257,11 @@ static void test_add(void)

     todo_wine ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS /* WinXP */),

        "got exit code %d, expected 0\n", r);

     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword2 /t REG_DWORD /d zzz /f", &r);

-    todo_wine ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);

+    ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);

     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword3 /t REG_DWORD /d deadbeef /f", &r);

-    todo_wine ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);

+    ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);

     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword4 /t REG_DWORD /d 123xyz /f", &r);

-    todo_wine ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);

+    ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);

  
     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword5 /t reg_dword /d 12345678 /f", &r);

     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);

@@ -275,22 +275,21 @@ static void test_add(void)

     ok(err == ERROR_SUCCESS, "RegQueryValueEx failed: got %d\n", err);

     ok(type == REG_DWORD, "got wrong type %d, expected %d\n", type, REG_DWORD);

     ok(size == sizeof(DWORD), "got wrong size %d, expected %d\n", size, (int)sizeof(DWORD));

-    todo_wine ok(dword == 123 || broken(dword == 0123 /* WinXP */),

+    ok(dword == 123 || broken(dword == 0123 /* WinXP */),

                  "got wrong data %d, expected %d\n", dword, 123);

  
     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword7 /t reg_dword /d 0xabcdefg /f", &r);

-    todo_wine ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);

+    ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);

  
     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword8 /t REG_dword /d 0xdeadbeef /f", &r);

     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);

     dword = 0xdeadbeef;

-    verify_reg(hkey, "dword8", REG_DWORD, &dword, sizeof(dword),

-               (sizeof(long) > sizeof(DWORD)) ? 0 : TODO_REG_DATA);

+    verify_reg(hkey, "dword8", REG_DWORD, &dword, sizeof(dword), 0);

  
     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_DWORD /v dword9 /f /d -1", &r);

-    todo_wine ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS /* WinXP */), "got exit code %u\n", r);

+    ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS /* WinXP */), "got exit code %u\n", r);

     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_DWORD /v dword10 /f /d -0x1", &r);

-    todo_wine ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS /* WinXP */), "got exit code %u\n", r);

+    ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS /* WinXP */), "got exit code %u\n", r);

  
     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword8 /t REG_dword /d 0x01ffffffff /f", &r);

     todo_wine ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS /* WinXP */), "got exit code %d\n", r);

@@ -305,7 +304,7 @@ static void test_add(void)

     run_reg_exe("reg add HKCU\\" KEY_BASE " /v DWORD_BE /t REG_DWORD_BIG_ENDIAN /d 456 /f", &r);

     ok(r == REG_EXIT_SUCCESS, "got exit code %u\n", r);

     dword = 456;

-    verify_reg(hkey, "DWORD_BE", REG_DWORD_BIG_ENDIAN, &dword, sizeof(dword), TODO_REG_SIZE);

+    verify_reg(hkey, "DWORD_BE", REG_DWORD_BIG_ENDIAN, &dword, sizeof(dword), 0);

     /* REG_DWORD_BIG_ENDIAN is broken in every version of windows. It behaves like

      * an ordinary REG_DWORD - that is little endian. GG */

  
@@ -313,15 +312,15 @@ static void test_add(void)

     run_reg_exe("reg add HKCU\\" KEY_BASE " /v multi0 /t REG_MULTI_SZ /d \"three\\0little\\0strings\" /f", &r);

     ok(r == REG_EXIT_SUCCESS, "got exit code %u\n", r);

     memcpy(buffer, "three\0little\0strings\0", 22);

-    verify_reg(hkey, "multi0", REG_MULTI_SZ, buffer, 22, TODO_REG_SIZE);

+    verify_reg(hkey, "multi0", REG_MULTI_SZ, buffer, 22, 0);

  
     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /v multi1 /s \"#\" /d \"three#little#strings\" /f", &r);

     ok(r == REG_EXIT_SUCCESS, "got exit code %u\n", r);

-    verify_reg(hkey, "multi1", REG_MULTI_SZ, buffer, 22, TODO_REG_SIZE);

+    verify_reg(hkey, "multi1", REG_MULTI_SZ, buffer, 22, 0);

  
     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /v multi2 /d \"\" /f", &r);

     ok(r == REG_EXIT_SUCCESS, "got exit code %u\n", r);

-    verify_reg(hkey, "multi2", REG_MULTI_SZ, &buffer[21], 1, TODO_REG_SIZE);

+    verify_reg(hkey, "multi2", REG_MULTI_SZ, &buffer[21], 1, 0);

  
     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /v multi3 /f", &r);

     ok(r == REG_EXIT_SUCCESS, "got exit code %u\n", r);

@@ -329,7 +328,7 @@ static void test_add(void)

  
     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /v multi4 /s \"#\" /d \"threelittlestrings\" /f", &r);

     ok(r == REG_EXIT_SUCCESS, "got exit code %u\n", r);

-    verify_reg(hkey, "multi4", REG_MULTI_SZ, "threelittlestrings\0", 20, TODO_REG_SIZE);

+    verify_reg(hkey, "multi4", REG_MULTI_SZ, "threelittlestrings\0", 20, 0);

  
     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /v multi5 /s \"#randomgibberish\" /d \"three#little#strings\" /f", &r);

     todo_wine ok(r == REG_EXIT_FAILURE, "got exit code %u\n", r);

@@ -338,16 +337,16 @@ static void test_add(void)

     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /v multi7 /s \"\" /d \"three#little#strings\" /f", &r);

     todo_wine ok(r == REG_EXIT_FAILURE, "got exit code %u\n", r);

     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /v multi8 /s \"#\" /d \"##\" /f", &r);

-    todo_wine ok(r == REG_EXIT_FAILURE, "got exit code %u\n", r);

+    ok(r == REG_EXIT_FAILURE, "got exit code %u\n", r);

     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /v multi9 /s \"#\" /d \"two##strings\" /f", &r);

-    todo_wine ok(r == REG_EXIT_FAILURE, "got exit code %u\n", r);

+    ok(r == REG_EXIT_FAILURE, "got exit code %u\n", r);

     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /v multi10 /s \"#\" /d \"#a\" /f", &r);

-    todo_wine ok(r == REG_EXIT_FAILURE, "got exit code %u\n", r);

+    ok(r == REG_EXIT_FAILURE, "got exit code %u\n", r);

  
     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /v multi11 /s \"#\" /d \"a#\" /f", &r);

     ok(r == REG_EXIT_SUCCESS, "got exit code %u\n", r);

     buffer[0]='a'; buffer[1]=0; buffer[2]=0;

-    verify_reg(hkey, "multi11", REG_MULTI_SZ, buffer, 3, TODO_REG_SIZE);

+    verify_reg(hkey, "multi11", REG_MULTI_SZ, buffer, 3, 0);

  
     RegCloseKey(hkey);

  
--  
2.5.0



 		 	   		   		 	   		  
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.winehq.org/pipermail/wine-patches/attachments/20150731/e979bf1d/attachment-0001.html>


More information about the wine-patches mailing list