From: Jonathan Vollebregt Subject: [v5 12/12] reg.exe: Implement query functionality Message-Id: <1413571143-11658-12-git-send-email-jnvsor@gmail.com> Date: Fri, 17 Oct 2014 20:39:03 +0200 --- programs/reg/reg.c | 264 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 255 insertions(+), 9 deletions(-) diff --git a/programs/reg/reg.c b/programs/reg/reg.c index 9d49f33..655f72c 100755 --- a/programs/reg/reg.c +++ b/programs/reg/reg.c @@ -21,6 +21,7 @@ #include "reg.h" #define MAX_VALUE_NAME 16384 +#define MAX_KEY_LENGTH 256 #define MAX_ROOT_KEY_NAME_LENGTH 20 #define NUM_ROOT_KEYS 5 #define MAX_TYPE_LENGTH 21 @@ -208,6 +209,62 @@ static DWORD wchar_get_type(const WCHAR *type) return -1; } +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(type) + { + case REG_SZ: + case REG_EXPAND_SZ: + { + output = HeapAlloc(GetProcessHeap(), 0, size); + lstrcpyW(output, (WCHAR *) data); + return output; + } + case REG_DWORD: + case REG_DWORD_BIG_ENDIAN: + { + output = HeapAlloc(GetProcessHeap(), 0, 11 * sizeof(WCHAR)); + + i = * (DWORD *) data; + + 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: + { + 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}; @@ -357,6 +414,165 @@ static BYTE *wchar_get_data(const WCHAR *input, const DWORD type, } } +static void print_key(const WCHAR *path, const WCHAR *subkey) +{ + static const WCHAR part[] = {'\\','%','s',0}; + static const WCHAR newline[] = {'\n',0}; + + reg_printfW(&part[1], path_get_rootkey_name(path)); + + if (path_get_key(path) != path_get_rootkey(path)) + reg_printfW(part, strchrW(path, '\\') + 1); + if(subkey) + reg_printfW(part, subkey); + + reg_printfW(newline); +} + +static DWORD print_value(const HKEY hkey, const WCHAR *value_name) +{ + static const WCHAR default_value_name[] = {'(','N','O',' ','N','A','M','E',')',0}; + static const WCHAR print_value[] = {' ',' ',' ',' ','%','s',' ',' ',' ',' ','%','s',' ',' ',' ',' ','%','s','\n',0}; + DWORD rc, type, data_size; + WCHAR *out_data = NULL; + BYTE* data = NULL; + + rc = RegQueryValueExW(hkey, value_name, NULL, &type, NULL, &data_size); + + if (rc != ERROR_SUCCESS) + { + reg_message(STRING_CANNOT_FIND); + return 1; + } + + data = HeapAlloc(GetProcessHeap(), 0, data_size); + + if (!data) + { + reg_message(STRING_ERROR); + return 1; + } + + rc = RegQueryValueExW(hkey, value_name, NULL, NULL, data, &data_size); + + if (rc != ERROR_SUCCESS) + { + reg_message(STRING_ERROR); + HeapFree(GetProcessHeap(), 0, data); + return 1; + } + + out_data = data_get_wchar(data, data_size, type); + + if (!value_name || !value_name[0]) + reg_printfW(print_value, default_value_name, type_get_wchar(type), out_data); + else + reg_printfW(print_value, value_name, type_get_wchar(type), out_data); + + HeapFree(GetProcessHeap(), 0, data); + HeapFree(GetProcessHeap(), 0, out_data); + return 0; +} + +static DWORD print_all_values(const HKEY hkey, const WCHAR *key_name, const BOOL recurse) +{ + static const WCHAR format_subkey_path[] = {'%','s','\\','%','s',0}; + static const WCHAR newline[] = {'\n',0}; + WCHAR value_name[MAX_VALUE_NAME]; + WCHAR subkey_name[MAX_KEY_LENGTH]; + WCHAR *subkey_path = NULL; + LONG rc; + DWORD i, length, subkey_length, num_subkeys, num_values; + HKEY subkey; + + rc = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, &num_subkeys, NULL, NULL, + &num_values, NULL, NULL, NULL, NULL); + + if (rc != ERROR_SUCCESS) + { + reg_message(STRING_CANNOT_FIND); + return 1; + } + + print_key(key_name, NULL); + + for (i = 0; i < num_values; i++) + { + length = MAX_VALUE_NAME; + + rc = RegEnumValueW(hkey, i, value_name, &length, NULL, NULL, NULL, NULL); + + if (rc != ERROR_SUCCESS) + { + reg_message(STRING_ERROR); + return 1; + } + + if (!value_name[0]) + print_value(hkey, NULL); + else + print_value(hkey, value_name); + } + + if (num_subkeys) + reg_printfW(newline); + + for (i = 0; i < num_subkeys; i++) + { + length = MAX_KEY_LENGTH; + + rc = RegEnumKeyExW(hkey, i, subkey_name, &length, NULL, NULL, NULL, NULL); + + if (rc != ERROR_SUCCESS) + { + reg_message(STRING_ERROR); + return 1; + } + + if (!recurse) + { + print_key(key_name, subkey_name); + continue; + } + + subkey_length = strlenW(key_name) + length + 2; + subkey_path = HeapAlloc(GetProcessHeap(), 0, subkey_length * sizeof(WCHAR)); + + if (!subkey_path) + { + reg_message(STRING_ERROR); + return 1; + } + + rc = snprintfW(subkey_path, subkey_length, format_subkey_path, key_name, subkey_name); + + if (rc < 0 || rc >= subkey_length) + { + reg_message(STRING_ERROR); + HeapFree(GetProcessHeap(), 0, subkey_path); + return 1; + } + + subkey = path_get_key(subkey_path); + if (!subkey) + { + HeapFree(GetProcessHeap(), 0, subkey_path); + return 1; + } + + if (print_all_values(subkey, subkey_path, recurse)) + { + RegCloseKey(subkey); + HeapFree(GetProcessHeap(), 0, subkey_path); + return 1; + } + + RegCloseKey(subkey); + HeapFree(GetProcessHeap(), 0, subkey_path); + } + return 0; +} + static int reg_add( const WCHAR *key_name, const WCHAR *value_name, const BOOL value_empty, const WCHAR *type, const WCHAR separator, const WCHAR *data, const BOOL force) @@ -516,14 +732,44 @@ static int reg_delete(const WCHAR *key_name, const WCHAR *value_name, const return 0; } -static int reg_query(WCHAR *key_name, WCHAR *value_name, BOOL value_empty, - BOOL subkey) +static int reg_query( const WCHAR *key_name, const WCHAR *value_name, + const BOOL value_empty, const BOOL recurse) { - static const WCHAR stubW[] = {'S','T','U','B',' ','Q','U','E','R','Y',' ', - '-',' ','%','s',' ','%','s',' ','%','d',' ','%','d','\n',0}; - reg_printfW(stubW, key_name, value_name, value_empty, subkey); + static const WCHAR newline[] = {'\n',0}; + HKEY key; - return 1; + reg_printfW(newline); + + if (value_name && value_empty) + { + reg_message(STRING_INVALID_CMDLINE); + return 1; + } + + key = path_get_key(key_name); + + if (!key) + return 1; + + if (value_empty || value_name) + { + if (value_name && !value_name[0]) + value_name = NULL; + + if (print_value(key, value_name)) + { + RegCloseKey(key); + return 1; + } + } + else if (print_all_values(key, key_name, recurse)) + { + RegCloseKey(key); + return 1; + } + + RegCloseKey(key); + return 0; } int wmain(int argc, WCHAR *argvW[]) @@ -633,7 +879,7 @@ int wmain(int argc, WCHAR *argvW[]) else if (!lstrcmpiW(argvW[1], queryW)) { WCHAR *key_name, *value_name = NULL; - BOOL value_empty = FALSE, subkey = FALSE; + BOOL value_empty = FALSE, recurse = FALSE; if (argc < 3) { @@ -658,9 +904,9 @@ int wmain(int argc, WCHAR *argvW[]) else if (!lstrcmpiW(argvW[i], slashVEW)) value_empty = TRUE; else if (!lstrcmpiW(argvW[i], slashSW)) - subkey = TRUE; + recurse = TRUE; } - return reg_query(key_name, value_name, value_empty, subkey); + return reg_query(key_name, value_name, value_empty, recurse); } else { -- 2.1.1