[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