This patch significantly builds on the query function stub in programs/reg.exe. 
The patch includes recursion for subkeys.

Some examples of usage:

wine reg.exe query "HKCU"
wine reg.exe query "HKCU\Console"
wine reg.exe query "HKCU\Console" /v "ScreenSize"
wine reg.exe query "HKCU\Software" /s

---
 programs/reg/reg.c |  232 +++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 221 insertions(+), 11 deletions(-)

From f1fc5e53eef89380b4ce10e231eced591b21882a Mon Sep 17 00:00:00 2001
From: Hugh McMaster <hugh.mcmas...@masterindexing.com>
Date: Thu, 1 Aug 2013 23:34:33 +1000
Subject: reg query

---
 programs/reg/reg.c |  232 +++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 221 insertions(+), 11 deletions(-)

diff --git a/programs/reg/reg.c b/programs/reg/reg.c
index 1b46661..d96bc90 100644
--- a/programs/reg/reg.c
+++ b/programs/reg/reg.c
@@ -20,6 +20,20 @@
 #include <wine/unicode.h>
 #include "reg.h"
 
+static const WCHAR formatSW[] = {'%','s',0};
+static const WCHAR slashW[] = {'\\',0};
+static const WCHAR newlineW[] = {'\n',0};
+
+static LPVOID WINAPI mem_alloc(size_t size)
+{
+    return HeapAlloc(GetProcessHeap(), 0, size);
+}
+
+static void WINAPI mem_free(LPVOID mem)
+{
+    HeapFree(GetProcessHeap(), 0, mem);
+}
+
 static int reg_printfW(const WCHAR *msg, ...)
 {
     va_list va_args;
@@ -59,12 +73,11 @@ static int reg_printfW(const WCHAR *msg, ...)
 
 static int reg_message(int msg)
 {
-    static const WCHAR formatW[] = {'%','s',0};
     WCHAR msg_buffer[8192];
 
     LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer,
         sizeof(msg_buffer)/sizeof(WCHAR));
-    return reg_printfW(formatW, msg_buffer);
+    return reg_printfW(formatSW, msg_buffer);
 }
 
 static HKEY get_rootkey(LPWSTR key)
@@ -356,14 +369,211 @@ static int reg_delete(WCHAR *key_name, WCHAR 
*value_name, BOOL value_empty,
     return 0;
 }
 
-static int reg_query(WCHAR *key_name, WCHAR *value_name, BOOL value_empty,
-    BOOL subkey)
+static void reg_output_keyvalue(LPWSTR valueName, DWORD valueType, LPBYTE 
value, DWORD valueSize)
 {
-    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);
+    LPBYTE pValue;
+    int i;
+    static const WCHAR valueNameW[] = {'%','s',':',' ',0};
+    static const WCHAR formatXW[] = {'%','X',0};
+    static const WCHAR dwordW[] = {'0','x','%','0','8','X',0};
+
+    reg_printfW(valueNameW, valueName);
+
+    switch (valueType)
+    {
+        case REG_BINARY:
+        case REG_NONE:
+            pValue = value;
+            for (i=0; i<valueSize; i++, pValue++)
+                reg_printfW(formatXW, *pValue);
+            break;
+        case REG_DWORD:
+            reg_printfW(dwordW, *((DWORD*)value));
+            break;
+       case REG_SZ:
+        case REG_MULTI_SZ:
+        case REG_EXPAND_SZ:
+            reg_printfW(formatSW, (LPWSTR*)value);
+            break;
+    }
+
+    reg_printfW(formatSW, newlineW);
+}
+
+static void reg_output_subkey(LPWSTR key_name, LPWSTR subkeyName)
+{
+    reg_printfW(formatSW, key_name);
+
+    if (subkeyName > 0)
+    {
+        reg_printfW(formatSW, slashW);
+        reg_printfW(formatSW, subkeyName);
+        reg_printfW(formatSW, newlineW);
+    }
+}
+
+static int reg_run_query(HKEY hQueryKey, WCHAR *key_name, LPWSTR subkey,
+                         WCHAR *value_name, BOOL value_empty, BOOL recursive)
+{
+    HKEY hSubKey;
+    DWORD rc, numSubKeys, maxSubKeyLen;
+    DWORD numValues, maxValueNameLen, maxValueSize;
+
+    /* Open registry key */
+    if (RegOpenKeyW(hQueryKey, subkey, &hSubKey) != ERROR_SUCCESS)
+    {
+        reg_message(STRING_CANNOT_FIND);
+        return 1;
+    }
+
+    /* Get number of subkeys and values in the specified registry key */
+    rc = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &numSubKeys, 
&maxSubKeyLen,
+                          NULL, &numValues, &maxValueNameLen, &maxValueSize, 
NULL, NULL);
+    if (rc != ERROR_SUCCESS)
+    {
+        reg_message(STRING_CANNOT_FIND);
+        RegCloseKey(hSubKey);
+        return 1;
+    }
+
+    /* Output registry values */
+    if (numValues > 0)
+    {
+        DWORD index = 0, valueNameLen, valueSize, valueType = 0;
+        LPWSTR valueName;
+        LPBYTE value;
+
+        valueName = mem_alloc((maxValueNameLen + 1) * sizeof(WCHAR));
+        value = mem_alloc(maxValueSize);
+
+        while (index < numValues)
+        {
+            valueNameLen = maxValueNameLen + 1;
+            valueSize = maxValueSize + 1;
+            valueName[0] = '\0';
+            value[0] = '\0';
+
+            rc = RegEnumValueW(hSubKey, index, valueName, &valueNameLen,
+                               NULL, &valueType, value, &valueSize);
+            if (rc == ERROR_SUCCESS)
+            {
+                if (value_name)
+                {
+                    if (lstrcmpiW(value_name, valueName) == 0)
+                    {
+                        reg_output_keyvalue(valueName, valueType, value, 
valueSize);
+                        break;
+                    }
+                }
+                else reg_output_keyvalue(valueName, valueType, value, 
valueSize);
+            }
+            index++;
+        }
+
+        /* Free allocated memory */
+        if (valueName)
+        {
+            mem_free(valueName);
+            valueName = NULL;
+        }
+
+        if (value)
+        {
+            mem_free(value);
+            value = NULL;
+        }
+    }
+
+    /* Output subkey data */
+    if (numSubKeys > 0)
+    {
+        DWORD index = 0, subkeyNameLen;
+        LPWSTR subkeyName;
+        WCHAR fullSubKeyPath[MAX_PATH + 1];
+
+        if (!value_name && numValues > 0) reg_printfW(formatSW, newlineW);
+
+        subkeyName = mem_alloc((maxSubKeyLen + 1) * sizeof(WCHAR));
+
+        while (index < numSubKeys)
+        {
+            subkeyNameLen = maxSubKeyLen + 1;
+            subkeyName[0] = '\0';
+            rc = RegEnumKeyExW(hSubKey, index, subkeyName, &subkeyNameLen,
+                               NULL, NULL, NULL, NULL);
+            if (rc == ERROR_SUCCESS)
+            {
+                if (value_name)
+                {
+                    if (lstrcmpiW(value_name, subkeyName) == 0)
+                    {
+                        reg_output_subkey(key_name, subkeyName);
+                        break;
+                    }
+                }
+                else reg_output_subkey(key_name, subkeyName);
+
+                if (recursive)
+                {
+                    fullSubKeyPath[0] = '\0';
+                    lstrcatW(fullSubKeyPath, key_name);
+                    lstrcatW(fullSubKeyPath, slashW);
+                    lstrcatW(fullSubKeyPath, subkeyName);
+                    reg_run_query(hSubKey, fullSubKeyPath, subkeyName,
+                                  value_name, value_empty, recursive);
+                }
+            }
+            index++;
+        }
+
+        /* Free allocated memory */
+        if (subkeyName)
+        {
+            mem_free(subkeyName);
+            subkeyName = NULL;
+        }
+    }
+
+    RegCloseKey(hSubKey);
+    return 0;
+}
+
+static int reg_query(WCHAR *key_name, WCHAR *value_name, BOOL value_empty, 
BOOL recursive)
+{
+    HKEY root, hQueryKey;
+    LPWSTR p;
+    static const WCHAR stubW[] = {'Q','U','E','R','Y',' ','-',' ',
+        '%','s',' ','%','s',' ','%','d',' ','%','d','\n',0};
+
+    reg_printfW(stubW, key_name, value_name, value_empty, recursive);
+
+    if (key_name[0]=='\\' && key_name[1]=='\\')
+    {
+        reg_message(STRING_NO_REMOTE);
+        return 1;
+    }
+
+    root = get_rootkey(key_name);
+    if (!root)
+    {
+        reg_message(STRING_INVALID_KEY);
+        return 1;
+    }
+
+    p = strchrW(key_name,'\\');
+    if (!p)
+    {
+        p = 0;
+    }
+    else p++;
+
+    if (RegOpenKeyW(root, p, &hQueryKey) != ERROR_SUCCESS)
+    {
+        reg_message(STRING_CANNOT_FIND);
+        return 1;
+    }
 
-    return 1;
+    return reg_run_query(hQueryKey, key_name, NULL, value_name, value_empty, 
recursive);
 }
 
 int wmain(int argc, WCHAR *argvW[])
@@ -460,7 +670,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, recursive = FALSE;
 
         if (argc < 3)
         {
@@ -482,9 +692,9 @@ int wmain(int argc, WCHAR *argvW[])
             else if (!lstrcmpiW(argvW[i], slashVEW))
                 value_empty = TRUE;
             else if (!lstrcmpiW(argvW[i], slashSW))
-                subkey = TRUE;
+                recursive = TRUE;
         }
-        return reg_query(key_name, value_name, value_empty, subkey);
+        return reg_query(key_name, value_name, value_empty, recursive);
     }
     else
     {
-- 
1.7.10.4



Reply via email to