From 72db61da978d7c825dd0f413ca13c1c99d2867ed Mon Sep 17 00:00:00 2001 From: Hugh McMaster Date: Sun, 3 Dec 2017 06:50:24 +0000 Subject: [PATCH] reg: Recursively export all subkeys and data. Signed-off-by: Hugh McMaster Signed-off-by: Alexandre Julliard --- programs/reg/export.c | 33 +++++++++++++++++++++++++++++++-- programs/reg/reg.c | 2 +- programs/reg/reg.h | 1 + programs/reg/tests/reg.c | 4 ++-- 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/programs/reg/export.c b/programs/reg/export.c index b5662633a5e..ac570a65b0e 100644 --- a/programs/reg/export.c +++ b/programs/reg/export.c @@ -236,14 +236,18 @@ static void export_key_name(HANDLE hFile, WCHAR *name) heap_free(buf); } +#define MAX_SUBKEY_LEN 257 + static int export_registry_data(HANDLE hFile, HKEY key, WCHAR *path) { LONG rc; DWORD max_value_len = 256, value_len; DWORD max_data_bytes = 2048, data_size; - DWORD i, type; - WCHAR *value_name; + DWORD subkey_len; + DWORD i, type, path_len; + WCHAR *value_name, *subkey_name, *subkey_path; BYTE *data; + HKEY subkey; export_key_name(hFile, path); @@ -280,6 +284,31 @@ static int export_registry_data(HANDLE hFile, HKEY key, WCHAR *path) heap_free(data); heap_free(value_name); + + subkey_name = heap_xalloc(MAX_SUBKEY_LEN * sizeof(WCHAR)); + + path_len = lstrlenW(path); + + i = 0; + for (;;) + { + 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(hFile, subkey, subkey_path); + RegCloseKey(subkey); + } + heap_free(subkey_path); + i++; + } + else break; + } + + heap_free(subkey_name); return 0; } diff --git a/programs/reg/reg.c b/programs/reg/reg.c index a3e2cf730a5..33e381ce4a2 100644 --- a/programs/reg/reg.c +++ b/programs/reg/reg.c @@ -637,7 +637,7 @@ static void output_value(const WCHAR *value_name, DWORD type, BYTE *data, DWORD output_string(newlineW); } -static WCHAR *build_subkey_path(WCHAR *path, DWORD path_len, WCHAR *subkey_name, DWORD subkey_len) +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}; diff --git a/programs/reg/reg.h b/programs/reg/reg.h index 35f22a5db60..2132e923de3 100644 --- a/programs/reg/reg.h +++ b/programs/reg/reg.h @@ -31,6 +31,7 @@ void output_writeconsole(const WCHAR *str, DWORD wlen); void WINAPIV output_message(unsigned int id, ...); BOOL ask_confirm(unsigned int msgid, WCHAR *reg_info); HKEY path_get_rootkey(const WCHAR *path); +WCHAR *build_subkey_path(WCHAR *path, DWORD path_len, WCHAR *subkey_name, DWORD subkey_len); BOOL parse_registry_key(const WCHAR *key, HKEY *root, WCHAR **path, WCHAR **long_key); /* import.c */ diff --git a/programs/reg/tests/reg.c b/programs/reg/tests/reg.c index 1ec9ca0bd90..81c94955da8 100644 --- a/programs/reg/tests/reg.c +++ b/programs/reg/tests/reg.c @@ -4489,7 +4489,7 @@ static void test_export(void) run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg", &r); ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); - ok(compare_export("file.reg", complex_test, TODO_REG_COMPARE), "compare_export() failed\n"); + ok(compare_export("file.reg", complex_test, 0), "compare_export() failed\n"); err = delete_tree(HKEY_CURRENT_USER, KEY_BASE); ok(err == ERROR_SUCCESS, "delete_tree() failed: %d\n", err); @@ -4503,7 +4503,7 @@ static void test_export(void) run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg", &r); ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); - ok(compare_export("file.reg", key_order_test, TODO_REG_COMPARE), "compare_export() failed\n"); + ok(compare_export("file.reg", key_order_test, 0), "compare_export() failed\n"); delete_key(hkey, "Subkey1"); delete_key(hkey, "Subkey2");