(resend) [PATCH v3 5/8] reg.exe: Add wchar/raw data conversion functions
Jonathan Vollebregt
jnvsor at gmail.com
Tue Sep 9 15:52:45 CDT 2014
---
programs/reg/reg.c | 222 ++++++++++++++++++++++++++++++++++++++++++++++------
programs/reg/reg.h | 3 +
programs/reg/reg.rc | 3 +
3 files changed, 204 insertions(+), 24 deletions(-)
diff --git a/programs/reg/reg.c b/programs/reg/reg.c
index c7c97e0..5a648df 100644
--- a/programs/reg/reg.c
+++ b/programs/reg/reg.c
@@ -178,43 +178,209 @@ static DWORD wchar_get_type(const WCHAR *type)
return -1;
}
-static LPBYTE get_regdata(LPWSTR data, DWORD reg_type, WCHAR separator, DWORD *reg_count)
+static inline DWORD switch_endian(const DWORD i)
{
- LPBYTE out_data = NULL;
- *reg_count = 0;
+ return (i>>24) | ((i>>8)&0xFF00) | ((i&0xFF00)<<8) | (i<<24);
+}
+
+static WCHAR *data_get_wchar(const BYTE *data, const DWORD size, const DWORD type)
+{
+ static const WCHAR print_dwordW[] = {'0','x','%','0','8','x',0};
+ static const WCHAR print_byteW[] = {'%','0','2','x',0};
+ DWORD i = 0;
+ WCHAR *output = NULL;
- switch (reg_type)
+ switch(type)
{
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;
+ output = HeapAlloc(GetProcessHeap(), 0, size);
+ lstrcpyW(output, (WCHAR *) data);
+ return output;
}
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;
- }
- *reg_count = sizeof(DWORD);
- out_data = HeapAlloc(GetProcessHeap(),0,*reg_count);
- ((LPDWORD)out_data)[0] = val;
- break;
+ output = HeapAlloc(GetProcessHeap(), 0, 11 * sizeof(WCHAR));
+
+ i = * (DWORD *) data;
+ if (type == REG_DWORD_BIG_ENDIAN)
+ i = switch_endian(i);
+
+ sprintfW(output, print_dwordW, i);
+ return output;
+ }
+ case REG_MULTI_SZ:
+ {
+ WCHAR *input = (WCHAR *) data;
+
+ output = HeapAlloc(GetProcessHeap(), 0, size);
+
+ do
+ {
+ lstrcpyW(output+i, &input[i]);
+
+ i += strlenW(&input[i]) + 1;
+
+ if (input[i] != 0)
+ output[i - 1] = ',';
+ } while (input[i]);
+
+ return output;
}
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);
+ output = HeapAlloc(GetProcessHeap(), 0, (size * 2 + 1) * sizeof(WCHAR) );
+
+ for (i = 0; i < size; i++)
+ sprintfW(output + i * 2, print_byteW, data[i]);
+
+ return output;
}
}
+}
+
+static BYTE *data_default(const DWORD type, DWORD *size_out)
+{
+ static const WCHAR unhandled[] = {'\t','%','s','\n',0};
+ BYTE *output;
+
+ switch (type){
+ case REG_SZ:
+ case REG_EXPAND_SZ:
+ case REG_MULTI_SZ:
+ {
+ output = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR));
+ * (WCHAR *) output = 0;
+ *size_out = sizeof(WCHAR);
+ return output;
+ }
+ case REG_DWORD:
+ case REG_DWORD_BIG_ENDIAN:
+ {
+ reg_message(STRING_NAN);
+ return NULL;
+ }
+ case REG_BINARY:
+ {
+ output = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD));
+ * (DWORD *) output = 0;
+ *size_out = sizeof(DWORD);
+ return output;
+ }
+ default:
+ {
+ reg_message(STRING_UNHANDLED_TYPE);
+ reg_printfW(unhandled, type_get_wchar(type));
+ return NULL;
+ }
+ }
+}
+
+static BYTE *wchar_get_data(const WCHAR *input, const DWORD type,
+ const WCHAR seperator, DWORD *size_out)
+{
+ static const WCHAR unhandled[] = {'\t','%','s','\n',0};
+ BYTE *output = NULL;
+ DWORD i;
+
+ if (!input)
+ return data_default(type, size_out);
- return out_data;
+ switch (type){
+ case REG_SZ:
+ case REG_EXPAND_SZ:
+ {
+ i = (strlenW(input) + 1) * sizeof(WCHAR);
+ output = HeapAlloc(GetProcessHeap(), 0, i);
+ lstrcpyW((WCHAR *) output, input);
+ *size_out = i;
+ return output;
+ }
+ case REG_DWORD:
+ case REG_DWORD_BIG_ENDIAN:
+ {
+ WCHAR *temp;
+
+ if (input[0] == '0' && (input[1] == 'x' || input[1] == 'X'))
+ i = strtoulW(input, &temp, 16);
+ else
+ i = strtoulW(input, &temp, 10);
+
+ if (temp == input || temp[0]) {
+ reg_message(STRING_NAN);
+ return NULL;
+ }
+
+ if (type == REG_DWORD_BIG_ENDIAN)
+ i = switch_endian(i);
+
+ output = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD));
+ * (DWORD *) output = i;
+ *size_out = sizeof(DWORD);
+ return output;
+ }
+ case REG_MULTI_SZ:
+ {
+ WCHAR *temp = HeapAlloc(GetProcessHeap(), 0, (strlenW(input) + 1) * sizeof(WCHAR));
+ DWORD p;
+
+ for (i = 0, p = 0; i <= strlenW(input); i++, p++)
+ {
+ if (input[i] == seperator)
+ temp[p] = 0;
+ else if (seperator == 0 && input[i] == '\\' && input[i + 1] == '0')
+ {
+ temp[p] = 0;
+ i++;
+ }
+ else
+ temp[p] = input[i];
+ }
+ temp[p++] = 0;
+
+ *size_out = p * sizeof(WCHAR);
+ return HeapReAlloc(GetProcessHeap(), 0, temp, p * sizeof(WCHAR));
+ }
+ case REG_BINARY:
+ {
+ BYTE * temp = HeapAlloc(GetProcessHeap(), 0, strlenW(input));
+ DWORD p;
+
+ for (i = 0, p = 0; i < strlenW(input); i++, p++)
+ {
+ if (input[i] >= '0' && input[i] <= '9')
+ temp[p] = input[i] - '0';
+ else if (input[i] >= 'a' && input[i] <= 'f')
+ temp[p] = input[i] - 'a' + 10;
+ else if (input[i] >= 'A' && input[i] <= 'F')
+ temp[p] = input[i] - 'A' + 10;
+ else
+ break;
+ }
+
+ if (p % 2)
+ {
+ reg_message(STRING_BINARY_INCMPLT);
+ return NULL;
+ }
+
+ p /= 2;
+
+ for (i = 0; i < p; i++)
+ temp[i] = (temp[i * 2] << 4) | temp[i * 2 + 1];
+
+ *size_out = p;
+ return HeapReAlloc(GetProcessHeap(), 0, temp, p);
+ }
+ default:
+ {
+ reg_message(STRING_UNHANDLED_TYPE);
+ reg_printfW(unhandled, type_get_wchar(type));
+ return NULL;
+ }
+ }
}
static int reg_add(WCHAR *key_name, WCHAR *value_name, BOOL value_empty,
@@ -264,7 +430,15 @@ 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);
+ reg_message(STRING_ERROR);
+ return 1;
+ }
+ }
RegSetValueExW(subkey,value_name,0,reg_type,reg_data,reg_count);
HeapFree(GetProcessHeap(),0,reg_data);
diff --git a/programs/reg/reg.h b/programs/reg/reg.h
index 1c2ae83..e593695 100644
--- a/programs/reg/reg.h
+++ b/programs/reg/reg.h
@@ -31,3 +31,6 @@
#define STRING_NO_REMOTE 108
#define STRING_CANNOT_FIND 109
#define STRING_ERROR 110
+#define STRING_UNHANDLED_TYPE 111
+#define STRING_NAN 112
+#define STRING_BINARY_INCMPLT 113
diff --git a/programs/reg/reg.rc b/programs/reg/reg.rc
index 5d259c7..3180fd5 100644
--- a/programs/reg/reg.rc
+++ b/programs/reg/reg.rc
@@ -36,4 +36,7 @@ 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_ERROR, "Error: An internal error occurred\n"
+ STRING_UNHANDLED_TYPE, "Error: Unhandled Type"
+ STRING_NAN, "Error: This type requires /d to be a number\n"
+ STRING_BINARY_INCMPLT, "Error: REG_BINARY input must have even number of nibbles\n"
}
-- 2.1.0
More information about the wine-patches
mailing list