[PATCH 5/5] reg.exe: Implement query functionality

Jonathan Vollebregt jnvsor at gmail.com
Mon Sep 1 08:05:34 CDT 2014


---
 programs/reg/reg.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 212 insertions(+), 8 deletions(-)

diff --git a/programs/reg/reg.c b/programs/reg/reg.c
index ad8582a..ad6adbd 100644
--- a/programs/reg/reg.c
+++ b/programs/reg/reg.c
@@ -20,7 +20,9 @@
 #include <wine/unicode.h>
 #include "reg.h"
 
+#define MAX_KEY_LENGTH 256
 #define MAX_ROOT_KEY_NAME_LENGTH 20
+#define MAX_VALUE_NAME 16384
 #define MAX_TYPE_LENGTH 32
 
 static const WCHAR short_HKEY_name[][5] = {
@@ -315,6 +317,166 @@ static LPBYTE wchar_get_data(const WCHAR * input, const DWORD type, WCHAR sepera
     return output;
 }
 
+static void print_key(WCHAR * path, WCHAR * subkey)
+{
+    WCHAR print_keyname[]={'%','s','\\','%','s','\\','%','s','\n',0};
+
+    if(subkey == NULL)
+    {
+        reg_printfW(&print_keyname[3],path_get_rootkey_name(path),strchrW(path,'\\')+1);
+    }
+    else
+    {
+        reg_printfW(print_keyname,path_get_rootkey_name(path),strchrW(path,'\\')+1,subkey);
+    }
+}
+
+static DWORD print_value(HKEY hkey, WCHAR *value_name)
+{
+    DWORD rc;
+    DWORD type;
+
+    BYTE* data=NULL;
+    DWORD data_size;
+    WCHAR *out_data=NULL;
+
+    WCHAR default_value_name[]={'(','N','O',' ','N','A','M','E',')',0};
+    WCHAR print_value[]={' ',' ',' ',' ','%','s',' ',' ',' ',' ','%','s',' ',' ',' ',' ','%','s','\n','\0'};
+
+    rc = RegGetValueW(hkey, NULL, value_name, RRF_RT_ANY | RRF_NOEXPAND, &type,
+         NULL, &data_size);
+
+    if (rc != ERROR_SUCCESS)
+    {
+        return 1;
+    }
+
+    data=HeapAlloc(GetProcessHeap(),0,data_size);
+
+    rc = RegGetValueW(hkey, NULL, value_name, RRF_RT_ANY, NULL,
+         data, &data_size);
+
+    if (rc != ERROR_SUCCESS)
+    {
+        HeapFree(GetProcessHeap(),0,data);
+        return 1;
+    }
+
+    out_data = data_get_wchar(data, data_size, type);
+
+    if (value_name==NULL)
+        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(HKEY hkey, WCHAR *key_name, BOOL recurse)
+{
+    LONG rc;
+    DWORD i=0;
+    DWORD num_subkeys=0;
+    DWORD num_values=0;
+
+    WCHAR value_name[MAX_VALUE_NAME];
+    DWORD value_name_length;
+
+    WCHAR subkey_name[MAX_KEY_LENGTH];
+    DWORD subkey_length;
+    LPWSTR subkey_path=NULL;
+    DWORD subkey_path_length;
+    HKEY subkey;
+
+    WCHAR format_subkey_path[]={'%','s','\\','%','s',0};
+
+    rc = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, &num_subkeys, NULL, NULL,
+         &num_values, NULL, NULL, NULL, NULL);
+
+    if (rc != ERROR_SUCCESS)
+    {
+        return 1;
+    }
+
+    print_key(key_name,NULL);
+
+    /*enumerate values*/
+    for (i=0; i<num_values; i++)
+    {
+        value_name_length = MAX_VALUE_NAME;
+
+        rc = RegEnumValueW(hkey, i, value_name, &value_name_length,
+             NULL, NULL, NULL, NULL);
+
+        if (rc != ERROR_SUCCESS)
+        {
+            return 1;
+        }
+
+        if(value_name[0] == '\0')
+        {
+            print_value(hkey, NULL);
+        }
+        else
+        {
+            print_value(hkey, value_name);
+        }
+    }
+
+    /*enumerate subkeys*/
+    for (i=0; i<num_subkeys; i++)
+    {
+        subkey_length = MAX_KEY_LENGTH;
+
+        rc = RegEnumKeyExW(hkey, i, subkey_name, &subkey_length,
+             NULL, NULL, NULL, NULL);
+
+        if (rc != ERROR_SUCCESS)
+        {
+            return 1;
+        }
+
+        subkey_name[subkey_length]='\0';
+
+        if(!recurse)
+        {
+            print_key(key_name,subkey_name);
+            continue;
+        }
+
+        subkey_path_length = strlenW(key_name) + strlenW(subkey_name) + 2;
+        subkey_path = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR) * subkey_path_length);
+
+        if (!subkey_path)
+        {
+            return 1;
+        }
+
+        rc = snprintfW(subkey_path,subkey_path_length,format_subkey_path,key_name,subkey_name);
+
+        if (rc < 0 || rc >= subkey_path_length)
+        {
+            return 1;
+        }
+
+        subkey = path_get_key(subkey_path);
+        if (!subkey)
+        {
+            return 1;
+        }
+
+        if(print_all_values(subkey, subkey_path, recurse))
+        {
+            return 1;
+        }
+        RegCloseKey(subkey);
+        HeapFree(GetProcessHeap(),0,subkey_path);
+    }
+    return 0;
+}
+
 static int reg_add(WCHAR *key_name, WCHAR *value_name, BOOL value_empty,
     WCHAR *type, WCHAR separator, WCHAR *data, BOOL force)
 {
@@ -456,13 +618,55 @@ static int reg_delete(WCHAR *key_name, WCHAR *value_name, BOOL value_empty,
 }
 
 static int reg_query(WCHAR *key_name, WCHAR *value_name, BOOL value_empty,
-    BOOL subkey)
+    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);
+    HKEY key = path_get_key(key_name);
+
+    WCHAR newline[]={'\n',0};
+    reg_printfW(newline);
+
+    if (value_name && value_empty)
+    {
+        reg_message(STRING_INVALID_CMDLINE);
+        return 1;
+    }
 
-    return 1;
+    if(!key)
+    {
+        return 1;
+    }
+
+    if (value_name)
+    {
+        if (print_value(key, value_name)!=0)
+        {
+            RegCloseKey(key);
+            reg_message(STRING_CANNOT_FIND);
+            return 1;
+        }
+    }
+    else if (value_empty)
+    {
+        if (print_value(key, NULL)!=0)
+        {
+            RegCloseKey(key);
+            reg_message(STRING_CANNOT_FIND);
+            return 1;
+        }
+    }
+    else
+    {
+        if (print_all_values(key, key_name, recurse)!=0)
+        {
+            RegCloseKey(key);
+            reg_message(STRING_CANNOT_FIND);
+            return 1;
+        }
+    }
+
+    RegCloseKey(key);
+
+    return 0;
 }
 
 int wmain(int argc, WCHAR *argvW[])
@@ -559,7 +763,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)
         {
@@ -581,9 +785,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.0




More information about the wine-patches mailing list