From 6293712b33073907bcaf0ef824a651e30c851458 Mon Sep 17 00:00:00 2001
From: George Stephanos <gaf.stephanos@gmail.com>
Date: Sun, 25 Aug 2013 01:36:30 +0200
Subject: [PATCH 2/2] advapi32: Path management for HKCR merge

---
 dlls/advapi32/registry.c | 71 ++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 62 insertions(+), 9 deletions(-)

diff --git a/dlls/advapi32/registry.c b/dlls/advapi32/registry.c
index d9135e1..ef2ed9a 100644
--- a/dlls/advapi32/registry.c
+++ b/dlls/advapi32/registry.c
@@ -44,10 +44,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(reg);
 #define HKEY_SPECIAL_ROOT_FIRST   HKEY_CLASSES_ROOT
 #define HKEY_SPECIAL_ROOT_LAST    HKEY_DYN_DATA
 
-static const WCHAR name_CLASSES_ROOT[] =
-    {'M','a','c','h','i','n','e','\\',
-     'S','o','f','t','w','a','r','e','\\',
-     'C','l','a','s','s','e','s',0};
 static const WCHAR name_LOCAL_MACHINE[] =
     {'M','a','c','h','i','n','e',0};
 static const WCHAR name_USERS[] =
@@ -82,6 +78,8 @@ static BOOL hkcu_cache_disabled;
 typedef struct {
     BOOL  init;
     HKEY  hklm;
+    DWORD samDesired;
+    WCHAR *path;
 } opened_hkcr_t;
 
 /* ############################### */
@@ -326,12 +324,58 @@ static HKEY resolve_hkcr( HKEY hkey )
     if (!hkcr) return NULL;
 
     EnterCriticalSection( &hkcr_handles_cs );
+    if (!hkcr->hklm) RegOpenKeyExW( HKEY_LOCAL_MACHINE, hkcr->path, 0, hkcr->samDesired, &hkcr->hklm );
     ret = hkcr->hklm;
     LeaveCriticalSection( &hkcr_handles_cs );
 
     return ret;
 }
 
+static LSTATUS get_hkcr_path( HKEY hkey, CONST WCHAR *path, WCHAR **buf )
+{
+    LSTATUS ret = ERROR_SUCCESS;
+    const static WCHAR root[] = {'S','o','f','t','w','a','r','e','\\','C','l','a','s','s','e','s',0};
+    opened_hkcr_t *hkcr = NULL;
+    int len = 0;
+    WCHAR *s;
+
+    if (path && *path == '\\') path++;
+
+    /* calculate len */
+    if (hkey)
+    {
+        hkcr = get_opened_hkcr( hkey );
+        if (!hkcr) return ERROR_INVALID_HANDLE;
+        EnterCriticalSection( &hkcr_handles_cs );
+    }
+
+    len += hkcr ? lstrlenW(hkcr->path) + 1 : sizeof(root);
+
+    if (path && *path) len += lstrlenW(path)+1;
+
+    /* allocate string */
+    *buf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len*sizeof(WCHAR) );
+    if (!*buf)
+    {
+        ret = ERROR_NOT_ENOUGH_MEMORY;
+        goto end;
+    }
+
+    /* copy */
+    lstrcpyW( *buf, hkcr ? hkcr->path : root );
+
+    if (path && *path) 
+    {
+        s = *buf + lstrlenW(*buf);
+        *s++ = '\\';
+        lstrcpyW( s, path );
+    }
+
+end:
+    if (hkcr) LeaveCriticalSection( &hkcr_handles_cs );
+    return ret;
+}
+
 static LSTATUS WINAPI create_hkcr( HKEY hkey, CONST WCHAR *name, WCHAR *class,
                                    DWORD options, REGSAM samDesired,
                                    SECURITY_ATTRIBUTES *sa, HKEY *retkey, DWORD *dispos )
@@ -339,10 +383,12 @@ static LSTATUS WINAPI create_hkcr( HKEY hkey, CONST WCHAR *name, WCHAR *class,
     HKEY hklm;
     opened_hkcr_t *hkcr = NULL;
     LSTATUS res;
+    WCHAR *buf = NULL;
     *retkey = 0;
 
-    if (hkey != HKEY_LOCAL_MACHINE) hkey = resolve_hkcr( hkey );
-    res = RegCreateKeyExW( hkey, name, 0, class, options, samDesired, sa, &hklm, dispos );
+    if ((res = get_hkcr_path( hkey, name, &buf ))) return res;
+
+    res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, buf, 0, class, options, samDesired, sa, &hklm, dispos );
     if (res) return res;
 
     if ((res = create_hkcr_struct(retkey, &hkcr)))
@@ -353,6 +399,8 @@ static LSTATUS WINAPI create_hkcr( HKEY hkey, CONST WCHAR *name, WCHAR *class,
 
     EnterCriticalSection( &hkcr_handles_cs );
     hkcr->hklm = hklm;
+    hkcr->path = buf;
+    hkcr->samDesired = samDesired;
     LeaveCriticalSection( &hkcr_handles_cs );
 
     return res;
@@ -363,10 +411,12 @@ static LSTATUS WINAPI open_hkcr( HKEY hkey, CONST WCHAR *name, REGSAM samDesired
     HKEY hklm;
     opened_hkcr_t *hkcr = NULL;
     LSTATUS res;
+    WCHAR *buf = NULL;
     *retkey = 0;
 
-    hkey = resolve_hkcr( hkey );
-    res = RegOpenKeyExW( hkey, name, 0, samDesired, &hklm );
+    if ((res = get_hkcr_path( hkey, name, &buf ))) return res;
+
+    res = RegOpenKeyExW( HKEY_LOCAL_MACHINE, buf, 0, samDesired, &hklm );
     if (res) return res;
 
     if ((res = create_hkcr_struct(retkey, &hkcr)))
@@ -377,6 +427,8 @@ static LSTATUS WINAPI open_hkcr( HKEY hkey, CONST WCHAR *name, REGSAM samDesired
 
     EnterCriticalSection( &hkcr_handles_cs );
     hkcr->hklm = hklm;
+    hkcr->path = buf;
+    hkcr->samDesired = samDesired;
     LeaveCriticalSection( &hkcr_handles_cs );
 
     return res;
@@ -391,7 +443,7 @@ static HKEY create_special_root_hkey( HKEY hkey, DWORD access )
 
     if (HandleToUlong(hkey) == HandleToUlong(HKEY_CLASSES_ROOT))
     {
-        if (create_hkcr( HKEY_LOCAL_MACHINE, name_CLASSES_ROOT + 8, NULL, 0, access, NULL, &hkey, NULL )) return 0;
+        if (create_hkcr( NULL, NULL, NULL, 0, access, NULL, &hkey, NULL )) return 0;
     }
     else if (HandleToUlong(hkey) == HandleToUlong(HKEY_CURRENT_USER))
     {
@@ -448,6 +500,7 @@ static LSTATUS close_hkcr( HKEY hkey )
 
     EnterCriticalSection( &hkcr_handles_cs );
     RegCloseKey( hkcr->hklm );
+    HeapFree( GetProcessHeap(), 0, hkcr->path );
     hkcr->init = FALSE;
     hkcr_handles_free[nb_hkcr_handles_free++] = (UINT_PTR)hkey >> 2;
     LeaveCriticalSection( &hkcr_handles_cs );
-- 
1.8.2.3

