From: Jonathan Vollebregt Subject: (resend) [PATCH v3 5/8] reg.exe: Add wchar/raw data conversion functions Message-Id: <540F689D.9080309@gmail.com> Date: Tue, 09 Sep 2014 22:52:45 +0200 --- 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