reg.exe - reg query implementation

Mieczyslaw Nalewaj namiltd at poczta.onet.pl
Tue Sep 18 03:29:10 CDT 2012


This is a new version of my patch for reg.exe which adds support for 
command "reg query".

P.S. The old version had the id 89851


-------------- next part --------------
diff --git a/programs/reg/reg.c b/programs/reg/reg.c
index 1b46661..8997235 100644
--- a/programs/reg/reg.c
+++ b/programs/reg/reg.c
@@ -1,5 +1,7 @@
 /*
  * Copyright 2008 Andrew Riedi
+ * Copyright 2010 Shuyin Lu
+ * Copyright 2012 Mieczyslaw Nalewaj
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -20,6 +22,10 @@
 #include <wine/unicode.h>
 #include "reg.h"
 
+#define MAX_KEY_LENGTH 256
+#define MAX_VALUE_NAME 16384
+#define MAX_TYPE_LENGTH 32
+
 static int reg_printfW(const WCHAR *msg, ...)
 {
     va_list va_args;
@@ -67,6 +73,22 @@ static int reg_message(int msg)
     return reg_printfW(formatW, msg_buffer);
 }
 
+static BOOL CompareRegW(LPCTSTR lpString1, LPCTSTR lpString2)
+{
+    int cchCount;
+    if ((!lpString1)||(!lpString2)||(!*lpString1)||(!*lpString2))
+        return FALSE;
+    cchCount = strlenW(lpString2);
+    if (strlenW(lpString1)<cchCount)
+        return FALSE;
+
+    if ( (CompareStringW(CP_ACP,NORM_IGNORECASE,lpString1,cchCount,lpString2,cchCount)==CSTR_EQUAL)
+     && ((lpString1[cchCount] == 0) || (lpString1[cchCount] == (WCHAR){'\\'})))
+        return TRUE;
+    else
+        return FALSE;
+}
+
 static HKEY get_rootkey(LPWSTR key)
 {
     static const WCHAR szHKLM[] = {'H','K','L','M',0};
@@ -80,24 +102,20 @@ static HKEY get_rootkey(LPWSTR key)
     static const WCHAR szHKCC[] = {'H','K','C','C',0};
     static const WCHAR szHKEY_CURRENT_CONFIG[] = {'H','K','E','Y','_','C','U','R','R','E','N','T','_','C','O','N','F','I','G',0};
 
-    if (CompareStringW(CP_ACP,NORM_IGNORECASE,key,4,szHKLM,4)==CSTR_EQUAL ||
-        CompareStringW(CP_ACP,NORM_IGNORECASE,key,18,szHKEY_LOCAL_MACHINE,18)==CSTR_EQUAL)
+    if ( CompareRegW(key,szHKLM) || CompareRegW(key,szHKEY_LOCAL_MACHINE) )
         return HKEY_LOCAL_MACHINE;
-    else if (CompareStringW(CP_ACP,NORM_IGNORECASE,key,4,szHKCU,4)==CSTR_EQUAL ||
-             CompareStringW(CP_ACP,NORM_IGNORECASE,key,17,szHKEY_CURRENT_USER,17)==CSTR_EQUAL)
+    else if ( CompareRegW(key,szHKCU) || CompareRegW(key,szHKEY_CURRENT_USER) )
         return HKEY_CURRENT_USER;
-    else if (CompareStringW(CP_ACP,NORM_IGNORECASE,key,4,szHKCR,4)==CSTR_EQUAL ||
-             CompareStringW(CP_ACP,NORM_IGNORECASE,key,17,szHKEY_CLASSES_ROOT,17)==CSTR_EQUAL)
+    else if ( CompareRegW(key,szHKCR) || CompareRegW(key,szHKEY_CLASSES_ROOT) )
         return HKEY_CLASSES_ROOT;
-    else if (CompareStringW(CP_ACP,NORM_IGNORECASE,key,3,szHKU,3)==CSTR_EQUAL ||
-             CompareStringW(CP_ACP,NORM_IGNORECASE,key,10,szHKEY_USERS,10)==CSTR_EQUAL)
+    else if ( CompareRegW(key,szHKU) || CompareRegW(key,szHKEY_USERS) )
         return HKEY_USERS;
-    else if (CompareStringW(CP_ACP,NORM_IGNORECASE,key,4,szHKCC,4)==CSTR_EQUAL ||
-             CompareStringW(CP_ACP,NORM_IGNORECASE,key,19,szHKEY_CURRENT_CONFIG,19)==CSTR_EQUAL)
+    else if ( CompareRegW(key,szHKCC) || CompareRegW(key,szHKEY_CURRENT_CONFIG) )
         return HKEY_CURRENT_CONFIG;
     else return NULL;
 }
 
+
 static DWORD get_regtype(LPWSTR type)
 {
     static const WCHAR szREG_SZ[] = {'R','E','G','_','S','Z',0};
@@ -163,6 +181,316 @@ static LPBYTE get_regdata(LPWSTR data, DWORD reg_type, WCHAR separator, DWORD *r
     return out_data;
 }
 
+/*convert DWORD data type to string*/
+static void convert_type_to_wchar(WCHAR *type, const DWORD value_type)
+{
+    static const WCHAR szREG_SZ[] = {'R','E','G','_','S','Z',0};
+    static const WCHAR szREG_MULTI_SZ[] = {'R','E','G','_','M','U','L','T','I','_','S','Z',0};
+    static const WCHAR szREG_DWORD_BIG_ENDIAN[] = {'R','E','G','_','D','W','O','R','D','_','B','I','G','_','E','N','D','I','A','N',0};
+    static const WCHAR szREG_DWORD[] = {'R','E','G','_','D','W','O','R','D',0};
+    static const WCHAR szREG_BINARY[] = {'R','E','G','_','B','I','N','A','R','Y',0};
+    static const WCHAR szREG_DWORD_LITTLE_ENDIAN[] = {'R','E','G','_','D','W','O','R','D','_','L','I','T','T','L','E','_','E','N','D','I','A','N',0};
+    static const WCHAR szREG_NONE[] = {'R','E','G','_','N','O','N','E',0};
+    static const WCHAR szREG_EXPAND_SZ[] = {'R','E','G','_','E','X','P','A','N','D','_','S','Z',0};
+
+    if (value_type==REG_SZ)
+        lstrcpyW(type, szREG_SZ);
+    else if (value_type==REG_DWORD)
+        lstrcpyW(type, szREG_DWORD);
+    else if (value_type==REG_MULTI_SZ)
+        lstrcpyW(type, szREG_MULTI_SZ);
+    else if (value_type==REG_EXPAND_SZ)
+        lstrcpyW(type, szREG_EXPAND_SZ);
+    else if (value_type==REG_DWORD_BIG_ENDIAN)
+        lstrcpyW(type, szREG_DWORD_BIG_ENDIAN);
+    else if (value_type==REG_DWORD_LITTLE_ENDIAN)
+        lstrcpyW(type, szREG_DWORD_LITTLE_ENDIAN);
+    else if (value_type==REG_BINARY)
+        lstrcpyW(type, szREG_BINARY);
+    else if (value_type==REG_NONE)
+        lstrcpyW(type, szREG_NONE);
+}
+
+/*convert BYTE data to string*/
+static void convert_data_to_wchar(WCHAR *data_string, const BYTE *data_byte, const DWORD value_data_size, const DWORD value_type)
+{
+    DWORD i=0;
+    DWORD wchars_copied=0;
+    LPWSTR string_pointer;
+    WCHAR print_number[]={'%','0','2','X',0};
+    WCHAR print_numbershort[]={'%','X',0};
+    WCHAR print_wchar[]={'%','c',0};
+    WCHAR pre_dword[]={'0','x',0};
+    BOOL zero;
+ 
+    if (value_type==REG_SZ)
+    {
+        lstrcpyW(data_string, (LPCWSTR)data_byte);
+    }
+    else if (value_type==REG_DWORD)
+    {
+        lstrcpyW(data_string, pre_dword);
+        string_pointer = data_string + 2;
+        zero = TRUE;
+        for (i=0; i<value_data_size; i++)
+        {
+            wchars_copied=sprintfW(string_pointer, print_numbershort, data_byte[value_data_size-1-i]);
+            if ((zero) && (string_pointer[0]!='0'))
+            {
+                string_pointer+=wchars_copied;
+            }
+            else
+            {
+                zero = FALSE;
+            }
+        }
+    }
+    else if (value_type==REG_DWORD_BIG_ENDIAN)
+    {
+        lstrcpyW(data_string, pre_dword);
+        string_pointer=data_string+2;
+        for (i=0; i<value_data_size; i++)
+        {
+            wchars_copied=sprintfW(string_pointer, print_number, data_byte[i]);
+            string_pointer+=wchars_copied;
+        }
+    }
+    else if (value_type==REG_DWORD_LITTLE_ENDIAN)
+    {
+        lstrcpyW(data_string, pre_dword);
+        string_pointer=data_string+2;
+        for (i=0; i<value_data_size; i++)
+        {
+            wchars_copied=sprintfW(string_pointer, print_number, data_byte[value_data_size-1-i]);
+            string_pointer+=wchars_copied;
+        }
+    }
+    else if (value_type==REG_BINARY)
+    {
+        string_pointer=data_string;
+        for (i=0; i<value_data_size; i++)
+        {
+            wchars_copied=sprintfW(string_pointer, print_number, data_byte[i]);
+            string_pointer+=wchars_copied;
+        }
+    }
+    else if (value_type==REG_MULTI_SZ)
+    {
+        DWORD wchar_size=sizeof(WCHAR);
+        DWORD effective_data_size=value_data_size-2*wchar_size;
+        string_pointer=data_string;
+
+        if ((value_data_size>=2*wchar_size) && (effective_data_size>0)) for (i=0; i<=effective_data_size; i+=wchar_size)
+        {
+            if (data_byte[i]==0)
+            {
+                string_pointer[0]='\\';
+                string_pointer++;
+                string_pointer[0]='0';
+                string_pointer++;
+            }
+            else
+            {
+                wchars_copied=sprintfW(string_pointer, print_wchar, data_byte[i]);
+                if (wchars_copied==0)
+                    string_pointer[0]=',';
+                string_pointer++;
+            }
+        }
+        string_pointer[0]='\\';
+        string_pointer++;
+        string_pointer[0]='0';
+        string_pointer++;
+        string_pointer[0]='\0';
+    }
+    else if (value_type==REG_EXPAND_SZ)
+    {
+        lstrcpyW(data_string, (LPCWSTR)data_byte);
+    }
+    else if (value_type==REG_NONE)
+    {
+        string_pointer=data_string;
+        for (i=0; i<value_data_size; i++)
+        {
+            wchars_copied=sprintfW(string_pointer, print_number, data_byte[i]);
+            string_pointer+=wchars_copied;
+        }
+    }
+}
+/*enumerate all values and subkeys under a key*/
+static DWORD enum_all_values_subkeys(HKEY hkey, WCHAR *key_name)
+{
+    LONG rc;
+    DWORD counter=0;
+    DWORD num_subkeys=0;
+    DWORD num_values=0;
+
+    WCHAR default_value_name[]={'(','D','e','f','a','u','l','t',')',0};
+    WCHAR value_name[MAX_VALUE_NAME];
+    DWORD value_name_length;
+
+    DWORD value_type;
+    WCHAR type[MAX_TYPE_LENGTH];
+
+    BYTE* value_data=NULL;
+    DWORD value_data_size;
+    DWORD max_data_size=256;
+    WCHAR *data=NULL;
+
+    WCHAR subkey_name[MAX_KEY_LENGTH];
+    DWORD subkey_length;
+
+    WCHAR print_keyname[]={'%','s','\n','\0'};
+//    WCHAR print_value[]={' ',' ',' ',' ','%','s',' ',' ',' ',' ','%','s',' ',' ',' ',' ','%','s','\n','\0'};
+    WCHAR print_value[]={'\t','%','s','\t','%','s','\t','%','s','\n','\0'};
+    WCHAR print_subkey[]={'%','s','\\','%','s','\n','\0'};
+
+    rc = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, &num_subkeys, NULL, NULL,
+         &num_values, NULL, NULL, NULL, NULL);
+
+    if (rc != ERROR_SUCCESS)
+    {
+        return 1;
+    }
+
+    reg_printfW(print_keyname, key_name);
+
+    value_data=HeapAlloc(GetProcessHeap(),0,max_data_size);
+    data=HeapAlloc(GetProcessHeap(),0,max_data_size*4);
+
+    /*enumerate values*/
+
+    for (counter=0; counter<num_values; counter++) 
+    {
+        value_name_length = MAX_VALUE_NAME;
+        value_data_size = max_data_size;
+
+        rc = RegEnumValueW(hkey, counter, NULL, &value_name_length, 
+             NULL, &value_type, NULL, &value_data_size);
+
+        if ((rc != ERROR_SUCCESS) || (value_name_length>MAX_VALUE_NAME))
+        {
+            HeapFree(GetProcessHeap(),0,value_data);
+            HeapFree(GetProcessHeap(),0,data);
+            return 1;
+        }
+
+        if (value_data_size>=max_data_size)
+        {
+            max_data_size=(value_data_size/256+1)*256;
+
+            value_data=HeapReAlloc(GetProcessHeap(),0,value_data,max_data_size);
+            data=HeapReAlloc(GetProcessHeap(),0,data,max_data_size*4);
+        }
+
+        rc = RegEnumValueW(hkey, counter, value_name, &value_name_length, 
+             NULL, &value_type, value_data, &value_data_size);
+
+        if (rc != ERROR_SUCCESS)
+        {
+            HeapFree(GetProcessHeap(),0,value_data);
+            HeapFree(GetProcessHeap(),0,data);
+            return 1;
+        }
+
+        value_name[value_name_length]='\0';
+        if (value_name[0]=='\0')
+            lstrcpyW(value_name, default_value_name);
+        convert_type_to_wchar(type, value_type);
+        if (value_data_size>0)
+        {
+            convert_data_to_wchar(data, value_data, value_data_size, value_type);
+        }
+        else
+        {
+            data[0] = 0;
+        }
+
+        reg_printfW(print_value, value_name, type, data);
+    }
+
+    /*enumerate subkeys*/
+    for (counter=0; counter<num_subkeys; counter++) 
+    { 
+        subkey_length = MAX_KEY_LENGTH;
+
+        rc = RegEnumKeyExW(hkey, counter, subkey_name, &subkey_length, 
+             NULL, NULL, NULL, NULL); 
+
+        if ((rc != ERROR_SUCCESS) || (subkey_length>=MAX_KEY_LENGTH)) 
+        {
+            return 1;
+        }
+
+        subkey_name[subkey_length]='\0';
+        reg_printfW(print_subkey, key_name, subkey_name);
+    }
+
+    HeapFree(GetProcessHeap(),0,value_data);
+    HeapFree(GetProcessHeap(),0,data);
+    return 0;
+}
+
+static DWORD get_value_data(HKEY hkey, WCHAR *value_name)
+{
+    LONG rc;
+
+    DWORD value_type;
+    WCHAR type[MAX_TYPE_LENGTH];
+
+    BYTE* value_data=NULL;
+    DWORD value_data_size;
+    DWORD max_data_size=256;
+    WCHAR *data=NULL;
+
+    WCHAR default_value_name[]={'(','D','e','f','a','u','l','t',')',0};
+    WCHAR print_value[]={' ',' ',' ',' ','%','s',' ',' ',' ',' ','%','s',' ',' ',' ',' ','%','s','\n','\0'};
+
+    value_data=HeapAlloc(GetProcessHeap(),0,max_data_size);
+    data=HeapAlloc(GetProcessHeap(),0,max_data_size*4);
+
+    /*enumerate value*/
+    rc = RegGetValueW(hkey, NULL, value_name, RRF_RT_ANY, &value_type,
+         NULL, &value_data_size);
+
+    if (rc != ERROR_SUCCESS)
+    {
+        HeapFree(GetProcessHeap(),0,value_data);
+        HeapFree(GetProcessHeap(),0,data);
+        return 1;
+    }
+
+    if (value_data_size>=max_data_size)
+    {
+        max_data_size=(value_data_size/256+1)*256;
+
+        value_data=HeapReAlloc(GetProcessHeap(),0,value_data,max_data_size);
+        data=HeapReAlloc(GetProcessHeap(),0,data,max_data_size*4);
+    }
+
+    rc = RegGetValueW(hkey, NULL, value_name, RRF_RT_ANY, &value_type,
+         value_data, &value_data_size);
+
+    if (rc != ERROR_SUCCESS)
+    {
+        HeapFree(GetProcessHeap(),0,value_data);
+        HeapFree(GetProcessHeap(),0,data);
+        return 1;
+    }
+
+    convert_type_to_wchar(type, value_type);
+    convert_data_to_wchar(data, value_data, value_data_size, value_type);
+
+    if (value_name==NULL)
+        reg_printfW(print_value, default_value_name, type, data);
+    else
+        reg_printfW(print_value, value_name, type, data);
+
+    HeapFree(GetProcessHeap(),0,value_data);
+    HeapFree(GetProcessHeap(),0,data);
+    return 0;
+}
+
 static int reg_add(WCHAR *key_name, WCHAR *value_name, BOOL value_empty,
     WCHAR *type, WCHAR separator, WCHAR *data, BOOL force)
 {
@@ -170,15 +498,23 @@ static int reg_add(WCHAR *key_name, WCHAR *value_name, BOOL value_empty,
         ' ','%','s',' ','%','d',' ','%','s',' ','%','s',' ','%','d','\n',0};
     LPWSTR p;
     HKEY root,subkey;
-
+    int klen;
+    
     reg_printfW(stubW, key_name, value_name, value_empty, type, data, force);
+ 
+    klen = strlenW(key_name);
 
-    if (key_name[0]=='\\' && key_name[1]=='\\')
+    if ((klen < 2) || (key_name[0]=='\\' && key_name[1]=='\\'))
     {
         reg_message(STRING_NO_REMOTE);
         return 1;
     }
 
+    if (key_name[klen-1]=='\\')
+    {
+        key_name[klen-1] = 0;
+    }
+
     p = strchrW(key_name,'\\');
     if (!p)
     {
@@ -240,18 +576,26 @@ static int reg_delete(WCHAR *key_name, WCHAR *value_name, BOOL value_empty,
 {
     LPWSTR p;
     HKEY root,subkey;
+    int klen;
 
     static const WCHAR stubW[] = {'D','E','L','E','T','E',
         ' ','-',' ','%','s',' ','%','s',' ','%','d',' ','%','d',' ','%','d','\n'
         ,0};
     reg_printfW(stubW, key_name, value_name, value_empty, value_all, force);
 
-    if (key_name[0]=='\\' && key_name[1]=='\\')
+    klen = strlenW(key_name);
+
+    if ((klen < 2) || (key_name[0]=='\\' && key_name[1]=='\\'))
     {
         reg_message(STRING_NO_REMOTE);
         return 1;
     }
 
+    if (key_name[klen-1]=='\\')
+    {
+        key_name[klen-1] = 0;
+    }
+
     p = strchrW(key_name,'\\');
     if (!p)
     {
@@ -359,11 +703,87 @@ 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)
 {
-    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);
+    LPWSTR p;
+    HKEY root,hkey;
+    int klen;
+
+    klen = strlenW(key_name);
+
+    if ((klen < 2) || (key_name[0]=='\\' && key_name[1]=='\\'))
+    {
+        reg_message(STRING_NO_REMOTE);
+        return 1;
+    }
 
-    return 1;
+    if (key_name[klen-1]=='\\')
+    {
+        key_name[klen-1] = 0;
+    }
+   
+    p = strchrW(key_name,'\\');
+    if (!p)
+    {
+        reg_message(STRING_INVALID_KEY);
+        return 1;
+    }
+    p++;
+
+    root = get_rootkey(key_name);
+    if (!root)
+    {
+        reg_message(STRING_INVALID_KEY);
+        return 1;
+    }
+
+    if (value_name && value_empty)
+    {
+        reg_message(STRING_INVALID_CMDLINE);
+        return 1;
+    }
+
+    if(RegOpenKeyW(root,p,&hkey)!=ERROR_SUCCESS)
+    {
+        reg_message(STRING_CANNOT_FIND);
+        return 1;
+    }
+
+    /* Output all subkeys and values if no /v or /ve option is given */
+    if (!value_name && !value_empty)
+    {
+        if (enum_all_values_subkeys(hkey, key_name)!=0)
+        {
+            /* FIXME: failure */
+            RegCloseKey(hkey);
+            reg_message(STRING_CANNOT_FIND);
+            return 1;
+        }
+    }
+    else if (value_name)
+    {
+	/* FIXME */
+        if (get_value_data(hkey, value_name)!=0)
+        {
+            /* FIXME: failure */
+            RegCloseKey(hkey);
+            reg_message(STRING_CANNOT_FIND);
+            return 1;
+        }
+    }
+    else if (value_empty)
+    {
+        /* FIXME */
+        if (get_value_data(hkey, value_name)!=0)
+        {
+            /* FIXME: failure */
+            RegCloseKey(hkey);
+            reg_message(STRING_CANNOT_FIND);
+            return 1;
+        }
+    }
+
+    RegCloseKey(hkey);
+
+    return 0;
 }
 
 int wmain(int argc, WCHAR *argvW[])


More information about the wine-patches mailing list