[PATCH 2/8] regedit: Determine the number of values and subkeys before exporting any data

Hugh McMaster hugh.mcmaster at outlook.com
Mon Jul 17 05:41:02 CDT 2017


Signed-off-by: Hugh McMaster <hugh.mcmaster at outlook.com>
---
 programs/regedit/regproc.c | 212 +++++++++++++++++++--------------------------
 1 file changed, 91 insertions(+), 121 deletions(-)

diff --git a/programs/regedit/regproc.c b/programs/regedit/regproc.c
index 5a0d222712..26f64835db 100644
--- a/programs/regedit/regproc.c
+++ b/programs/regedit/regproc.c
@@ -35,6 +35,8 @@
 #include <wine/debug.h>
 #include "regproc.h"
 
+WINE_DEFAULT_DEBUG_CHANNEL(regedit);
+
 #define REG_VAL_BUF_SIZE        4096
 
 /* maximal number of characters in hexadecimal data line,
@@ -1093,26 +1095,6 @@ static void REGPROC_resize_char_buffer(WCHAR **buffer, DWORD *len, DWORD require
 }
 
 /******************************************************************************
- * Same as REGPROC_resize_char_buffer() but on a regular buffer.
- *
- * Parameters:
- * buffer - pointer to a buffer
- * len - current size of the buffer in bytes
- * required_size - size of the data to place in the buffer in bytes
- */
-static void REGPROC_resize_binary_buffer(BYTE **buffer, DWORD *size, DWORD required_size)
-{
-    if (required_size > *size) {
-        *size = required_size;
-        if (!*buffer)
-            *buffer = HeapAlloc(GetProcessHeap(), 0, *size);
-        else
-            *buffer = HeapReAlloc(GetProcessHeap(), 0, *buffer, *size);
-        CHECK_ENOUGH_MEMORY(*buffer);
-    }
-}
-
-/******************************************************************************
  * Prints string str to file
  */
 static void REGPROC_export_string(WCHAR **line_buf, DWORD *line_buf_size, DWORD *line_len, WCHAR *str, DWORD str_len)
@@ -1261,69 +1243,21 @@ static void REGPROC_write_line(FILE *file, const WCHAR* str, BOOL unicode)
  *      Is resized if necessary.
  * val_size - size of the buffer for storing values in bytes.
  */
-static void export_hkey(FILE *file, HKEY key,
-                 WCHAR **reg_key_name_buf, DWORD *reg_key_name_size,
-                 WCHAR **val_name_buf, DWORD *val_name_size,
-                 BYTE **val_buf, DWORD *val_size,
-                 WCHAR **line_buf, DWORD *line_buf_size,
-                 BOOL unicode)
+static void export_hkey(FILE *file, WCHAR **val_name_buf, DWORD *val_name_size,
+                        DWORD value_type, BYTE **val_buf, DWORD *val_size,
+                        WCHAR **line_buf, DWORD *line_buf_size, BOOL unicode)
 {
-    DWORD max_sub_key_len;
-    DWORD max_val_name_len;
-    DWORD max_val_size;
-    DWORD curr_len;
-    DWORD i;
-    LONG ret;
-    WCHAR key_format[] = {'\r','\n','[','%','s',']','\r','\n',0};
-
-    /* get size information and resize the buffers if necessary */
-    if (RegQueryInfoKeyW(key, NULL, NULL, NULL, NULL,
-                        &max_sub_key_len, NULL,
-                        NULL, &max_val_name_len, &max_val_size, NULL, NULL
-                       ) != ERROR_SUCCESS)
-        return;
-    curr_len = strlenW(*reg_key_name_buf);
-    REGPROC_resize_char_buffer(reg_key_name_buf, reg_key_name_size,
-                               max_sub_key_len + curr_len + 1);
-    REGPROC_resize_char_buffer(val_name_buf, val_name_size,
-                               max_val_name_len);
-    REGPROC_resize_binary_buffer(val_buf, val_size, max_val_size);
-    REGPROC_resize_char_buffer(line_buf, line_buf_size, lstrlenW(*reg_key_name_buf) + 4);
-    /* output data for the current key */
-    sprintfW(*line_buf, key_format, *reg_key_name_buf);
-    REGPROC_write_line(file, *line_buf, unicode);
-
-    /* print all the values */
-    i = 0;
-    for (;;) {
-        DWORD value_type;
-        DWORD val_name_size1 = *val_name_size;
-        DWORD val_size1 = *val_size;
-        ret = RegEnumValueW(key, i, *val_name_buf, &val_name_size1, NULL,
-                           &value_type, *val_buf, &val_size1);
-        if (ret == ERROR_MORE_DATA) {
-            /* Increase the size of the buffers and retry */
-            REGPROC_resize_char_buffer(val_name_buf, val_name_size, val_name_size1);
-            REGPROC_resize_binary_buffer(val_buf, val_size, val_size1);
-        } else if (ret == ERROR_SUCCESS) {
-            DWORD line_len;
-            i++;
-
-            if ((*val_name_buf)[0]) {
+    DWORD line_len = 0;
+    DWORD val_size1 = *val_size;
+
+            if (*val_name_buf && (*val_name_buf)[0]) {
                 const WCHAR val_start[] = {'"','%','s','"','=',0};
 
-                line_len = 0;
                 REGPROC_export_string(line_buf, line_buf_size, &line_len, *val_name_buf, lstrlenW(*val_name_buf));
-                REGPROC_resize_char_buffer(val_name_buf, val_name_size, lstrlenW(*line_buf) + 1);
-                lstrcpyW(*val_name_buf, *line_buf);
-
-                line_len = 3 + lstrlenW(*val_name_buf);
-                REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len);
-                sprintfW(*line_buf, val_start, *val_name_buf);
+                line_len = sprintfW(*line_buf, val_start, *val_name_buf);
             } else {
                 const WCHAR std_val[] = {'@','=',0};
                 line_len = 2;
-                REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len);
                 lstrcpyW(*line_buf, std_val);
             }
 
@@ -1370,36 +1304,6 @@ static void export_hkey(FILE *file, HKEY key,
                 REGPROC_export_binary(line_buf, line_buf_size, &line_len, value_type, *val_buf, val_size1, unicode);
             }
             REGPROC_write_line(file, *line_buf, unicode);
-        }
-        else break;
-    }
-
-    i = 0;
-    (*reg_key_name_buf)[curr_len] = '\\';
-    for (;;) {
-        DWORD buf_size = *reg_key_name_size - curr_len - 1;
-
-        ret = RegEnumKeyExW(key, i, *reg_key_name_buf + curr_len + 1, &buf_size,
-                           NULL, NULL, NULL, NULL);
-        if (ret == ERROR_MORE_DATA) {
-            /* Increase the size of the buffer and retry */
-            REGPROC_resize_char_buffer(reg_key_name_buf, reg_key_name_size, curr_len + 1 + buf_size);
-        } else if (ret == ERROR_SUCCESS) {
-            HKEY subkey;
-
-            i++;
-            if (RegOpenKeyW(key, *reg_key_name_buf + curr_len + 1,
-                           &subkey) == ERROR_SUCCESS) {
-                export_hkey(file, subkey, reg_key_name_buf, reg_key_name_size,
-                            val_name_buf, val_name_size, val_buf, val_size,
-                            line_buf, line_buf_size, unicode);
-                RegCloseKey(subkey);
-            }
-            else break;
-        }
-        else break;
-    }
-    (*reg_key_name_buf)[curr_len] = '\0';
 }
 
 /******************************************************************************
@@ -1473,31 +1377,97 @@ void delete_registry_key(WCHAR *reg_key_name)
     RegDeleteTreeW(key_class, key_name);
 }
 
+static WCHAR *build_subkey_path(WCHAR *path, DWORD path_len, WCHAR *subkey_name, DWORD subkey_len)
+{
+    WCHAR *subkey_path;
+    static const WCHAR fmt[] = {'%','s','\\','%','s',0};
+
+    subkey_path = resize_buffer(NULL, (path_len + subkey_len + 2) * sizeof(WCHAR));
+    sprintfW(subkey_path, fmt, path, subkey_name);
+
+    return subkey_path;
+}
+
+static void export_key_name(FILE *fp, WCHAR *name, BOOL unicode)
+{
+    static const WCHAR fmt[] = {'\r','\n','[','%','s',']','\r','\n',0};
+    WCHAR *buf;
+
+    buf = resize_buffer(NULL, (lstrlenW(name) + 7) * sizeof(WCHAR));
+    sprintfW(buf, fmt, name);
+    REGPROC_write_line(fp, buf, unicode);
+    HeapFree(GetProcessHeap(), 0, buf);
+}
+
 static int export_registry_data(FILE *fp, HKEY key, WCHAR *path, BOOL unicode)
 {
-    WCHAR *reg_key_name_buf, *val_name_buf, *line_buf;
-    BYTE *val_buf;
-    DWORD reg_key_name_size = KEY_MAX_LEN;
-    DWORD val_name_size = KEY_MAX_LEN;
-    DWORD val_size = REG_VAL_BUF_SIZE;
+    WCHAR *line_buf;
     DWORD line_buf_size = KEY_MAX_LEN + REG_VAL_BUF_SIZE;
+    LONG rc;
+    DWORD num_subkeys, max_subkey_len, subkey_len;
+    DWORD num_values, max_value_len, value_len;
+    DWORD max_data_bytes, data_size;
+    DWORD i, type, path_len;
+    WCHAR *value_name, *subkey_name, *subkey_path;
+    BYTE *data;
+    HKEY subkey;
+
+    rc = RegQueryInfoKeyW(key, NULL, NULL, NULL, &num_subkeys, &max_subkey_len, NULL,
+                          &num_values, &max_value_len, &max_data_bytes, NULL, NULL);
+    if (rc != ERROR_SUCCESS)
+    {
+        ERR("RegQueryInfoKey failed: %u\n", rc);
+        return 1;
+    }
 
-    reg_key_name_buf = HeapAlloc(GetProcessHeap(), 0, reg_key_name_size * sizeof(WCHAR));
-    val_name_buf = HeapAlloc(GetProcessHeap(), 0, val_name_size * sizeof(WCHAR));
-    val_buf = HeapAlloc(GetProcessHeap(), 0, val_size);
     line_buf = HeapAlloc(GetProcessHeap(), 0, line_buf_size * sizeof(WCHAR));
-    CHECK_ENOUGH_MEMORY(reg_key_name_buf && val_name_buf && val_buf && line_buf);
+    CHECK_ENOUGH_MEMORY(line_buf);
+
+    export_key_name(fp, path, unicode);
 
-    lstrcpyW(reg_key_name_buf, path);
+    max_value_len++;
+    value_name = resize_buffer(NULL, max_value_len * sizeof(WCHAR));
 
-    export_hkey(fp, key, &reg_key_name_buf, &reg_key_name_size, &val_name_buf, &val_name_size,
-                &val_buf, &val_size, &line_buf, &line_buf_size, unicode);
+    data = resize_buffer(NULL, max_data_bytes);
+
+    for (i = 0; i < num_values; i++)
+    {
+        value_len = max_value_len;
+        data_size = max_data_bytes;
+        rc = RegEnumValueW(key, i, value_name, &value_len, NULL, &type, data, &data_size);
+        if (rc == ERROR_SUCCESS)
+        {
+            export_hkey(fp, &value_name, &value_len, type, &data, &data_size,
+                        &line_buf, &line_buf_size, unicode);
+        }
+    }
 
-    HeapFree(GetProcessHeap(), 0, reg_key_name_buf);
-    HeapFree(GetProcessHeap(), 0, val_name_buf);
-    HeapFree(GetProcessHeap(), 0, val_buf);
+    HeapFree(GetProcessHeap(), 0, data);
+    HeapFree(GetProcessHeap(), 0, value_name);
     HeapFree(GetProcessHeap(), 0, line_buf);
 
+    max_subkey_len++;
+    subkey_name = resize_buffer(NULL, max_subkey_len * sizeof(WCHAR));
+
+    path_len = lstrlenW(path);
+
+    for (i = 0; i < num_subkeys; i++)
+    {
+        subkey_len = max_subkey_len;
+        rc = RegEnumKeyExW(key, i, subkey_name, &subkey_len, NULL, NULL, NULL, NULL);
+        if (rc == ERROR_SUCCESS)
+        {
+            subkey_path = build_subkey_path(path, path_len, subkey_name, subkey_len);
+            if (!RegOpenKeyExW(key, subkey_name, 0, KEY_READ, &subkey))
+            {
+                export_registry_data(fp, subkey, subkey_path, unicode);
+                RegCloseKey(subkey);
+            }
+            HeapFree(GetProcessHeap(), 0, subkey_path);
+        }
+    }
+
+    HeapFree(GetProcessHeap(), 0, subkey_name);
     return 0;
 }
 
-- 
2.11.0




More information about the wine-patches mailing list