Alexandre Julliard : advapi32: Create keys recursively if necessary.

Alexandre Julliard julliard at winehq.org
Mon Mar 1 09:27:38 CST 2010


Module: wine
Branch: master
Commit: 972f96d6c4c743659f3d6337241cacb4ce7e1d56
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=972f96d6c4c743659f3d6337241cacb4ce7e1d56

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Mar  1 14:12:12 2010 +0100

advapi32: Create keys recursively if necessary.

---

 dlls/advapi32/registry.c |   43 +++++++++++++++++++++++++++++++++++++------
 1 files changed, 37 insertions(+), 6 deletions(-)

diff --git a/dlls/advapi32/registry.c b/dlls/advapi32/registry.c
index faae2b1..dd3f516 100644
--- a/dlls/advapi32/registry.c
+++ b/dlls/advapi32/registry.c
@@ -91,15 +91,47 @@ static inline int is_version_nt(void)
     return !(GetVersion() & 0x80000000);
 }
 
+/* wrapper for NtCreateKey that creates the key recursively if necessary */
+static NTSTATUS create_key( HKEY *retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr,
+                            const UNICODE_STRING *class, ULONG options, PULONG dispos )
+{
+    NTSTATUS status = NtCreateKey( (HANDLE *)retkey, access, attr, 0, class, options, dispos );
+
+    if (status == STATUS_OBJECT_NAME_NOT_FOUND)
+    {
+        DWORD attrs, i = 0, len = attr->ObjectName->Length / sizeof(WCHAR);
+
+        while (i < len && attr->ObjectName->Buffer[i] != '\\') i++;
+        if (i == len) return status;
+        attrs = attr->Attributes;
+        attr->Attributes &= ~OBJ_OPENLINK;
+
+        while (i < len)
+        {
+            attr->ObjectName->Length = i * sizeof(WCHAR);
+            status = NtCreateKey( (HANDLE *)retkey, access, attr, 0, class,
+                                  options & ~REG_OPTION_CREATE_LINK, dispos );
+            if (status) return status;
+            NtClose( *retkey );
+            while (i < len && attr->ObjectName->Buffer[i] == '\\') i++;
+            while (i < len && attr->ObjectName->Buffer[i] != '\\') i++;
+        }
+        attr->Attributes = attrs;
+        attr->ObjectName->Length = len * sizeof(WCHAR);
+        status = NtCreateKey( (PHANDLE)retkey, access, attr, 0, class, options, dispos );
+    }
+    return status;
+}
+
 /* create one of the HKEY_* special root keys */
-static HKEY create_special_root_hkey( HANDLE hkey, DWORD access )
+static HKEY create_special_root_hkey( HKEY hkey, DWORD access )
 {
     HKEY ret = 0;
     int idx = (UINT_PTR)hkey - (UINT_PTR)HKEY_SPECIAL_ROOT_FIRST;
 
     if (hkey == HKEY_CURRENT_USER)
     {
-        if (RtlOpenCurrentUser( access, &hkey )) return 0;
+        if (RtlOpenCurrentUser( access, (HANDLE *)&hkey )) return 0;
         TRACE( "HKEY_CURRENT_USER -> %p\n", hkey );
 
         /* don't cache the key in the table if caching is disabled */
@@ -118,7 +150,7 @@ static HKEY create_special_root_hkey( HANDLE hkey, DWORD access )
         attr.SecurityDescriptor = NULL;
         attr.SecurityQualityOfService = NULL;
         RtlInitUnicodeString( &name, root_key_names[idx] );
-        if (NtCreateKey( &hkey, access, &attr, 0, NULL, 0, NULL )) return 0;
+        if (create_key( &hkey, access, &attr, NULL, 0, NULL )) return 0;
         TRACE( "%s -> %p\n", debugstr_w(attr.ObjectName->Buffer), hkey );
     }
 
@@ -194,8 +226,7 @@ LSTATUS WINAPI RegCreateKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, LPWSTR
     RtlInitUnicodeString( &nameW, name );
     RtlInitUnicodeString( &classW, class );
 
-    return RtlNtStatusToDosError( NtCreateKey( (PHANDLE)retkey, access, &attr, 0,
-                                               &classW, options, dispos ) );
+    return RtlNtStatusToDosError( create_key( retkey, access, &attr, &classW, options, dispos ) );
 }
 
 
@@ -254,7 +285,7 @@ LSTATUS WINAPI RegCreateKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, LPSTR cl
     {
         if (!(status = RtlAnsiStringToUnicodeString( &classW, &classA, TRUE )))
         {
-            status = NtCreateKey( (PHANDLE)retkey, access, &attr, 0, &classW, options, dispos );
+            status = create_key( retkey, access, &attr, &classW, options, dispos );
             RtlFreeUnicodeString( &classW );
         }
     }




More information about the wine-cvs mailing list