[v5 12/12] reg.exe: Implement query functionality

Jonathan Vollebregt jnvsor at gmail.com
Fri Oct 17 13:39:03 CDT 2014


---
 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




More information about the wine-patches mailing list