wine-staging/patches/advapi32-RegCopyTree/0003-advapi32-Implement-RegCopyTreeA-W.patch
2016-02-15 09:22:18 +01:00

194 lines
6.9 KiB
Diff

From 8303376b344d5525f7124016fef073da747c6acd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Mon, 15 Feb 2016 06:27:10 +0100
Subject: advapi32: Implement RegCopyTreeA/W.
---
dlls/advapi32/advapi32.spec | 4 +-
dlls/advapi32/registry.c | 114 +++++++++++++++++++++
dlls/advapi32/tests/registry.c | 2 +-
.../api-ms-win-core-registry-l1-1-0.spec | 2 +-
.../api-ms-win-downlevel-advapi32-l1-1-0.spec | 2 +-
5 files changed, 119 insertions(+), 5 deletions(-)
diff --git a/dlls/advapi32/advapi32.spec b/dlls/advapi32/advapi32.spec
index 36f176b..e3c7c4b 100644
--- a/dlls/advapi32/advapi32.spec
+++ b/dlls/advapi32/advapi32.spec
@@ -575,8 +575,8 @@
@ stdcall RegConnectRegistryW(wstr long ptr)
# @ stub RegConnectRegistryExA
# @ stub RegConnectRegistryExW
-# @ stub RegCopyTreeA
-# @ stub RegCopyTreeW
+@ stdcall RegCopyTreeA(long str long)
+@ stdcall RegCopyTreeW(long wstr long)
@ stdcall RegCreateKeyA(long str ptr)
@ stdcall RegCreateKeyExA(long str long ptr long long ptr ptr ptr)
@ stdcall RegCreateKeyExW(long wstr long ptr long long ptr ptr ptr)
diff --git a/dlls/advapi32/registry.c b/dlls/advapi32/registry.c
index 3508407..faca66c 100644
--- a/dlls/advapi32/registry.c
+++ b/dlls/advapi32/registry.c
@@ -3104,6 +3104,120 @@ LSTATUS WINAPI RegDeleteTreeA(HKEY hKey, LPCSTR lpszSubKey)
return ret;
}
+
+static LONG reg_get_buffers( HKEY hkey, WCHAR **name_buf, DWORD *name_size,
+ BYTE **value_buf, DWORD *value_size )
+{
+ DWORD ret, max_subkey, max_name, max_value;
+
+ ret = RegQueryInfoKeyW( hkey, NULL, NULL, NULL, NULL, &max_subkey,
+ NULL, NULL, &max_name, &max_value, NULL, NULL );
+ if (ret)
+ return ret;
+
+ /* allocate buffer for subkeys / names */
+ max_name = max( max_subkey, max_name ) + 1;
+ if (max_name > *name_size)
+ {
+ if (!(*name_buf = heap_alloc( max_name * sizeof(WCHAR) )))
+ return ERROR_NOT_ENOUGH_MEMORY;
+ *name_size = max_name;
+ }
+
+ /* allocate buffer for values */
+ if (max_value > *value_size)
+ {
+ if (!(*value_buf = heap_alloc( max_value )))
+ return ERROR_NOT_ENOUGH_MEMORY;
+ *value_size = max_value;
+ }
+
+ return ERROR_SUCCESS;
+}
+
+
+/******************************************************************************
+ * RegCopyTreeW [ADVAPI32.@]
+ *
+ */
+LONG WINAPI RegCopyTreeW( HKEY hsrc, const WCHAR *subkey, HKEY hdst )
+{
+ WCHAR buf1[MAX_PATH], *name_buf = buf1;
+ BYTE buf2[MAX_PATH], *value_buf = buf2;
+ DWORD name_size, max_name = sizeof(buf1) / sizeof(WCHAR);
+ DWORD value_size, max_value = sizeof(buf2);
+ DWORD i, type;
+ HKEY hkey;
+ LONG ret;
+
+ TRACE( "(%p, %s, %p)\n", hsrc, debugstr_w(subkey), hdst );
+
+ if (subkey)
+ {
+ ret = RegOpenKeyExW( hsrc, subkey, 0, KEY_READ, &hsrc );
+ if (ret) return ret;
+ }
+
+ /* Allocate required buffers */
+ ret = reg_get_buffers( hsrc, &name_buf, &max_name, &value_buf, &max_value );
+ if (ret) goto cleanup;
+
+ /* Copy all the values */
+ for (i = 0;; i++)
+ {
+ name_size = max_name;
+ value_size = max_value;
+ ret = RegEnumValueW( hsrc, i, name_buf, &name_size, NULL, &type, value_buf, &value_size );
+ if (ret == ERROR_NO_MORE_ITEMS) break;
+ if (ret) goto cleanup;
+ ret = RegSetValueExW( hdst, name_buf, 0, type, value_buf, value_size );
+ if (ret) goto cleanup;
+ }
+
+ /* Recursively copy all the subkeys */
+ for (i = 0;; i++)
+ {
+ name_size = max_name;
+ ret = RegEnumKeyExW( hsrc, i, name_buf, &name_size, NULL, NULL, NULL, NULL );
+ if (ret == ERROR_NO_MORE_ITEMS) break;
+ if (ret) goto cleanup;
+ ret = RegCreateKeyExW( hdst, name_buf, 0, NULL, 0, KEY_WRITE, NULL, &hkey, NULL );
+ if (ret) goto cleanup;
+ ret = RegCopyTreeW( hsrc, name_buf, hkey );
+ RegCloseKey( hkey );
+ if (ret) goto cleanup;
+ }
+
+ ret = ERROR_SUCCESS;
+
+cleanup:
+ if (name_buf != buf1)
+ heap_free( name_buf );
+ if (value_buf != buf2)
+ heap_free( value_buf );
+ if (subkey)
+ RegCloseKey( hsrc );
+ return ret;
+}
+
+
+/******************************************************************************
+ * RegCopyTreeA [ADVAPI32.@]
+ *
+ */
+LONG WINAPI RegCopyTreeA( HKEY hsrc, const char *subkey, HKEY hdst )
+{
+ UNICODE_STRING subkeyW;
+ LONG ret;
+
+ if (subkey) RtlCreateUnicodeStringFromAsciiz( &subkeyW, subkey );
+ else subkeyW.Buffer = NULL;
+ ret = RegCopyTreeW( hsrc, subkeyW.Buffer, hdst );
+ RtlFreeUnicodeString( &subkeyW );
+ return ret;
+}
+
+
/******************************************************************************
* RegDisableReflectionKey [ADVAPI32.@]
*
diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c
index d29e131..658b356 100644
--- a/dlls/advapi32/tests/registry.c
+++ b/dlls/advapi32/tests/registry.c
@@ -2090,7 +2090,7 @@ static void test_reg_copy_tree(void)
if (!pRegCopyTreeA)
{
- skip("Skipping RegCopyTreeA tests, function not present\n");
+ win_skip("Skipping RegCopyTreeA tests, function not present\n");
return;
}
diff --git a/dlls/api-ms-win-core-registry-l1-1-0/api-ms-win-core-registry-l1-1-0.spec b/dlls/api-ms-win-core-registry-l1-1-0/api-ms-win-core-registry-l1-1-0.spec
index d83fbdd..91b1a94 100644
--- a/dlls/api-ms-win-core-registry-l1-1-0/api-ms-win-core-registry-l1-1-0.spec
+++ b/dlls/api-ms-win-core-registry-l1-1-0/api-ms-win-core-registry-l1-1-0.spec
@@ -1,5 +1,5 @@
@ stdcall RegCloseKey(long) advapi32.RegCloseKey
-@ stub RegCopyTreeW
+@ stdcall RegCopyTreeW(long wstr long) advapi32.RegCopyTreeW
@ stdcall RegCreateKeyExA(long str long ptr long long ptr ptr ptr) advapi32.RegCreateKeyExA
@ stdcall RegCreateKeyExW(long wstr long ptr long long ptr ptr ptr) advapi32.RegCreateKeyExW
@ stdcall RegDeleteKeyExA(long str long long) advapi32.RegDeleteKeyExA
diff --git a/dlls/api-ms-win-downlevel-advapi32-l1-1-0/api-ms-win-downlevel-advapi32-l1-1-0.spec b/dlls/api-ms-win-downlevel-advapi32-l1-1-0/api-ms-win-downlevel-advapi32-l1-1-0.spec
index 4105e59..e1b4663 100644
--- a/dlls/api-ms-win-downlevel-advapi32-l1-1-0/api-ms-win-downlevel-advapi32-l1-1-0.spec
+++ b/dlls/api-ms-win-downlevel-advapi32-l1-1-0/api-ms-win-downlevel-advapi32-l1-1-0.spec
@@ -84,7 +84,7 @@
@ stdcall PrivilegedServiceAuditAlarmW(wstr wstr long ptr long) advapi32.PrivilegedServiceAuditAlarmW
@ stub QuerySecurityAccessMask
@ stdcall RegCloseKey(long) advapi32.RegCloseKey
-@ stub RegCopyTreeW
+@ stdcall RegCopyTreeW(long wstr long) advapi32.RegCopyTreeW
@ stdcall RegCreateKeyExA(long str long ptr long long ptr ptr ptr) advapi32.RegCreateKeyExA
@ stdcall RegCreateKeyExW(long wstr long ptr long long ptr ptr ptr) advapi32.RegCreateKeyExW
@ stdcall RegDeleteKeyExA(long str long long) advapi32.RegDeleteKeyExA
--
2.7.1