- Fix registry lock leakages in CmpDoOpen in failure cases.
authorAleksey Bragin <aleksey@reactos.org>
Mon, 22 Dec 2008 18:47:38 +0000 (18:47 +0000)
committerAleksey Bragin <aleksey@reactos.org>
Mon, 22 Dec 2008 18:47:38 +0000 (18:47 +0000)
- Add support for a special case of opening existing (cached) KCBs by CmpDoOpen.
- Specify a flag for that case in one specific case inside CmpParseKey, which allows us to get rid of the "\\REGISTRY" hack inside the code, fixes the 'Kcb->RefCount == 1' assertion failure, and certainly fixes registry-related regression tests. There might be some side effects in theory, but since this hack only applied to the root key, they shouldn't happen. Thanks to Stefan for helping in debugging and a testcase.

svn path=/trunk/; revision=38272

reactos/ntoskrnl/config/cmparse.c

index 2757fbb..5b960f0 100644 (file)
@@ -599,38 +599,74 @@ CmpDoOpen(IN PHHIVE Hive,
     /* If we have a KCB, make sure it's locked */
     //ASSERT(CmpIsKcbLockedExclusive(*CachedKcb));
 
-    /* Check if this is a symlink */
-    if ((Node->Flags & KEY_SYM_LINK) && !(Attributes & OBJ_OPENLINK))
+    /* Check if caller doesn't want to create a KCB */
+    if (ControlFlags & CMP_OPEN_KCB_NO_CREATE)
     {
-        /* Create the KCB for the symlink */
+        /* Check if this is a symlink */
+        if ((Node->Flags & KEY_SYM_LINK) && !(Attributes & OBJ_OPENLINK))
+        {
+            /* This case for a cached KCB is not implemented yet */
+            ASSERT(FALSE);
+        }
+
+        /* The caller wants to open a cached KCB */
+        if (!CmpReferenceKeyControlBlock(*CachedKcb))
+        {
+            /* Release the registry lock */
+            CmpUnlockRegistry();
+
+            /* Return failure code */
+            return STATUS_INSUFFICIENT_RESOURCES;
+        }
+
+        /* Our kcb is that one */
+        Kcb = *CachedKcb;
+    }
+    else
+    {
+        /* Check if this is a symlink */
+        if ((Node->Flags & KEY_SYM_LINK) && !(Attributes & OBJ_OPENLINK))
+        {
+            /* Create the KCB for the symlink */
+            Kcb = CmpCreateKeyControlBlock(Hive,
+                                           Cell,
+                                           Node,
+                                           *CachedKcb,
+                                           0,
+                                           KeyName);
+            if (!Kcb)
+            {
+                /* Release registry lock and return failure */
+                CmpUnlockRegistry();
+                return STATUS_INSUFFICIENT_RESOURCES;
+            }
+
+            /* Make sure it's also locked, and set the pointer */
+            //ASSERT(CmpIsKcbLockedExclusive(Kcb));
+            *CachedKcb = Kcb;
+
+            /* Release the registry lock */
+            CmpUnlockRegistry();
+
+            /* Return reparse required */
+            return STATUS_REPARSE;
+        }
+
+        /* Create the KCB. FIXME: Use lock flag */
         Kcb = CmpCreateKeyControlBlock(Hive,
                                        Cell,
                                        Node,
                                        *CachedKcb,
                                        0,
                                        KeyName);
-        if (!Kcb) return STATUS_INSUFFICIENT_RESOURCES;
-
-        /* Make sure it's also locked, and set the pointer */
-        //ASSERT(CmpIsKcbLockedExclusive(Kcb));
-        *CachedKcb = Kcb;
-
-        /* Release the registry lock */
-        CmpUnlockRegistry();
-
-        /* Return reparse required */
-        return STATUS_REPARSE;
+        if (!Kcb)
+        {
+            /* Release registry lock and return failure */
+            CmpUnlockRegistry();
+            return STATUS_INSUFFICIENT_RESOURCES;
+        }
     }
 
-    /* Create the KCB. FIXME: Use lock flag */
-    Kcb = CmpCreateKeyControlBlock(Hive,
-                                   Cell,
-                                   Node,
-                                   *CachedKcb,
-                                   0,
-                                   KeyName);
-    if (!Kcb) return STATUS_INSUFFICIENT_RESOURCES;
-
     /* Make sure it's also locked, and set the pointer */
     //ASSERT(CmpIsKcbLockedExclusive(Kcb));
     *CachedKcb = Kcb;
@@ -1308,10 +1344,7 @@ CmpParseKey(IN PVOID ParseObject,
                                   &CellToRelease);
                 if (!Node) ASSERT(FALSE);
             }
-            
-            /* FIXME: This hack seems required? */
-            RtlInitUnicodeString(&NextName, L"\\REGISTRY");
-            
+
             /* Do the open */
             Status = CmpDoOpen(Hive,
                                Cell,
@@ -1320,7 +1353,7 @@ CmpParseKey(IN PVOID ParseObject,
                                AccessMode,
                                Attributes,
                                ParseContext,
-                               0,
+                               CMP_OPEN_KCB_NO_CREATE /* | CMP_CREATE_KCB_KCB_LOCKED */,
                                &Kcb,
                                &NextName,
                                Object);