forget update de.rc
[reactos.git] / reactos / ntoskrnl / cm / regobj.c
index 9a6d9cb..b824c85 100644 (file)
@@ -1,25 +1,21 @@
-/*
- * COPYRIGHT:        See COPYING in the top level directory
- * PROJECT:          ReactOS kernel
- * FILE:             ntoskrnl/cm/regobj.c
- * PURPOSE:          Registry object manipulation routines.
- * UPDATE HISTORY:
+/* $Id$
+ *
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/cm/regobj.c
+ * PURPOSE:         Registry object manipulation routines.
+ *
+ * PROGRAMMERS:     No programmer listed.
 */
 
-#include <ddk/ntddk.h>
-#include <roscfg.h>
-#include <internal/ob.h>
-#include <limits.h>
-#include <string.h>
-#include <internal/pool.h>
-#include <internal/registry.h>
-#include <ntos/minmax.h>
-
+#include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
 
 #include "cm.h"
 
+extern LIST_ENTRY CmiKeyObjectListHead;
+extern ULONG CmiTimer;
 
 static NTSTATUS
 CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive,
@@ -39,13 +35,13 @@ CmiObjectParse(PVOID ParsedObject,
   PKEY_OBJECT FoundObject;
   PKEY_OBJECT ParsedKey;
   PKEY_CELL SubKeyCell;
-  CHAR cPath[MAX_PATH];
   NTSTATUS Status;
   PWSTR StartPtr;
   PWSTR EndPtr;
   ULONG Length;
   UNICODE_STRING LinkPath;
   UNICODE_STRING TargetPath;
+  UNICODE_STRING KeyName;
 
   ParsedKey = ParsedObject;
 
@@ -72,27 +68,51 @@ CmiObjectParse(PVOID ParsedObject,
   else
     Length = wcslen(StartPtr);
 
-  wcstombs(cPath, StartPtr, Length);
-  cPath[Length] = 0;
+
+  KeyName.Length = Length * sizeof(WCHAR);
+  KeyName.MaximumLength = KeyName.Length + sizeof(WCHAR);
+  KeyName.Buffer = ExAllocatePool(NonPagedPool,
+                                 KeyName.MaximumLength);
+  RtlCopyMemory(KeyName.Buffer,
+               StartPtr,
+               KeyName.Length);
+  KeyName.Buffer[KeyName.Length / sizeof(WCHAR)] = 0;
+
+  /* Acquire hive lock */
+  KeEnterCriticalRegion();
+  ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
 
 
-  FoundObject = CmiScanKeyList(ParsedKey, cPath, Attributes);
+  Status = CmiScanKeyList(ParsedKey,
+                         &KeyName,
+                         Attributes,
+                         &FoundObject);
+  if (!NT_SUCCESS(Status))
+  {
+     ExReleaseResourceLite(&CmiRegistryLock);
+     KeLeaveCriticalRegion();
+     RtlFreeUnicodeString(&KeyName);
+     return Status;
+  }
   if (FoundObject == NULL)
     {
       Status = CmiScanForSubKey(ParsedKey->RegistryHive,
                                ParsedKey->KeyCell,
                                &SubKeyCell,
                                &BlockOffset,
-                               cPath,
+                               &KeyName,
                                0,
                                Attributes);
       if (!NT_SUCCESS(Status) || (SubKeyCell == NULL))
        {
+          ExReleaseResourceLite(&CmiRegistryLock);
+          KeLeaveCriticalRegion();
+         RtlFreeUnicodeString(&KeyName);
          return(STATUS_UNSUCCESSFUL);
        }
 
-      if ((SubKeyCell->Type == REG_LINK_KEY_CELL_TYPE) &&
-         !((Attributes & OBJ_OPENLINK) && (EndPtr == NULL) /*(end == NULL)*/))
+      if ((SubKeyCell->Flags & REG_KEY_LINK_CELL) &&
+         !((Attributes & OBJ_OPENLINK) && (EndPtr == NULL)))
        {
          RtlInitUnicodeString(&LinkPath, NULL);
          Status = CmiGetLinkTarget(ParsedKey->RegistryHive,
@@ -100,6 +120,9 @@ CmiObjectParse(PVOID ParsedObject,
                                    &LinkPath);
          if (NT_SUCCESS(Status))
            {
+              ExReleaseResourceLite(&CmiRegistryLock);
+              KeLeaveCriticalRegion();
+
              DPRINT("LinkPath '%wZ'\n", &LinkPath);
 
              /* build new FullPath for reparsing */
@@ -129,35 +152,56 @@ CmiObjectParse(PVOID ParsedObject,
              *Path = FullPath->Buffer;
 
              *NextObject = NULL;
+
+             RtlFreeUnicodeString(&KeyName);
              return(STATUS_REPARSE);
            }
        }
 
       /* Create new key object and put into linked list */
-      DPRINT("CmiObjectParse: %s\n", cPath);
-      Status = ObCreateObject(NULL,
-                             STANDARD_RIGHTS_REQUIRED,
-                             NULL,
+      DPRINT("CmiObjectParse: %S\n", *Path);
+      Status = ObCreateObject(KernelMode,
                              CmiKeyType,
+                             NULL,
+                             KernelMode,
+                             NULL,
+                             sizeof(KEY_OBJECT),
+                             0,
+                             0,
                              (PVOID*)&FoundObject);
       if (!NT_SUCCESS(Status))
        {
+          ExReleaseResourceLite(&CmiRegistryLock);
+          KeLeaveCriticalRegion();
+         RtlFreeUnicodeString(&KeyName);
          return(Status);
        }
+    DPRINT("Inserting Key into Object Tree\n");
+    Status =  ObInsertObject((PVOID)FoundObject,
+                             NULL,
+                             KEY_ALL_ACCESS,
+                             0,
+                             NULL,
+                             NULL);
+    DPRINT("Status %x\n", Status);
+
+      /* Add the keep-alive reference */
+      ObReferenceObject(FoundObject);
 
       FoundObject->Flags = 0;
-      FoundObject->Name = SubKeyCell->Name;
-      FoundObject->NameSize = SubKeyCell->NameSize;
       FoundObject->KeyCell = SubKeyCell;
-      FoundObject->BlockOffset = BlockOffset;
+      FoundObject->KeyCellOffset = BlockOffset;
       FoundObject->RegistryHive = ParsedKey->RegistryHive;
+      InsertTailList(&CmiKeyObjectListHead, &FoundObject->ListEntry);
+      RtlpCreateUnicodeString(&FoundObject->Name,
+              KeyName.Buffer, NonPagedPool);
       CmiAddKeyToList(ParsedKey, FoundObject);
-      DPRINT("Created object 0x%x\n", FoundObject);
+      DPRINT("Created object 0x%p\n", FoundObject);
     }
   else
     {
-      if ((FoundObject->KeyCell->Type == REG_LINK_KEY_CELL_TYPE) &&
-         !((Attributes & OBJ_OPENLINK) && (EndPtr == NULL)/*(end == NULL)*/))
+      if ((FoundObject->KeyCell->Flags & REG_KEY_LINK_CELL) &&
+         !((Attributes & OBJ_OPENLINK) && (EndPtr == NULL)))
        {
          DPRINT("Found link\n");
 
@@ -169,6 +213,11 @@ CmiObjectParse(PVOID ParsedObject,
            {
              DPRINT("LinkPath '%wZ'\n", &LinkPath);
 
+              ExReleaseResourceLite(&CmiRegistryLock);
+              KeLeaveCriticalRegion();
+
+             ObDereferenceObject(FoundObject);
+
              /* build new FullPath for reparsing */
              TargetPath.MaximumLength = LinkPath.MaximumLength;
              if (EndPtr != NULL)
@@ -196,16 +245,20 @@ CmiObjectParse(PVOID ParsedObject,
              *Path = FullPath->Buffer;
 
              *NextObject = NULL;
+
+             RtlFreeUnicodeString(&KeyName);
              return(STATUS_REPARSE);
            }
        }
-
-      ObReferenceObjectByPointer(FoundObject,
-                                STANDARD_RIGHTS_REQUIRED,
-                                NULL,
-                                UserMode);
     }
 
+  RemoveEntryList(&FoundObject->ListEntry);
+  InsertHeadList(&CmiKeyObjectListHead, &FoundObject->ListEntry);
+  FoundObject->TimeStamp = CmiTimer;
+
+  ExReleaseResourceLite(&CmiRegistryLock);
+  KeLeaveCriticalRegion();
+
   DPRINT("CmiObjectParse: %s\n", FoundObject->Name);
 
   *Path = EndPtr;
@@ -214,68 +267,181 @@ CmiObjectParse(PVOID ParsedObject,
 
   *NextObject = FoundObject;
 
+  RtlFreeUnicodeString(&KeyName);
+
   return(STATUS_SUCCESS);
 }
 
-
-NTSTATUS STDCALL
-CmiObjectCreate(PVOID ObjectBody,
-               PVOID Parent,
-               PWSTR RemainingPath,
-               POBJECT_ATTRIBUTES ObjectAttributes)
+VOID STDCALL
+CmiObjectDelete(PVOID DeletedObject)
 {
-  PKEY_OBJECT pKey = ObjectBody;
+  PKEY_OBJECT ParentKeyObject;
+  PKEY_OBJECT KeyObject;
+
+  DPRINT("Delete key object (%p)\n", DeletedObject);
+
+  KeyObject = (PKEY_OBJECT) DeletedObject;
+  ParentKeyObject = KeyObject->ParentKey;
+
+  ObReferenceObject (ParentKeyObject);
+
+  /* Acquire hive lock */
+  KeEnterCriticalRegion();
+  ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
+
+  if (!NT_SUCCESS(CmiRemoveKeyFromList(KeyObject)))
+    {
+      DPRINT1("Key not found in parent list ???\n");
+    }
+
+  RemoveEntryList(&KeyObject->ListEntry);
+  RtlFreeUnicodeString(&KeyObject->Name);
 
-  pKey->ParentKey = Parent;
-  if (RemainingPath)
+  if (KeyObject->Flags & KO_MARKED_FOR_DELETE)
     {
-      if(RemainingPath[0]== L'\\')
-       {
-         pKey->Name = (PCHAR)(&RemainingPath[1]);
-         pKey->NameSize = wcslen(RemainingPath) - 1;
-       }
-      else
+      DPRINT("delete really key\n");
+
+      CmiRemoveSubKey(KeyObject->RegistryHive,
+                     ParentKeyObject,
+                     KeyObject);
+
+      KeQuerySystemTime (&ParentKeyObject->KeyCell->LastWriteTime);
+      CmiMarkBlockDirty (ParentKeyObject->RegistryHive,
+                        ParentKeyObject->KeyCellOffset);
+
+      if (!IsNoFileHive (KeyObject->RegistryHive) ||
+         !IsNoFileHive (ParentKeyObject->RegistryHive))
        {
-         pKey->Name = (PCHAR)RemainingPath;
-         pKey->NameSize = wcslen(RemainingPath);
+         CmiSyncHives ();
        }
     }
-   else
+
+  ObDereferenceObject (ParentKeyObject);
+
+  ExReleaseResourceLite(&CmiRegistryLock);
+  KeLeaveCriticalRegion();
+
+  if (KeyObject->NumberOfSubKeys)
+    {
+      KEBUGCHECK(REGISTRY_ERROR);
+    }
+
+  if (KeyObject->SizeOfSubKeys)
     {
-      pKey->NameSize = 0;
+      ExFreePool(KeyObject->SubKeys);
+    }
+}
+
+
+static NTSTATUS
+CmiQuerySecurityDescriptor(PKEY_OBJECT KeyObject,
+                          SECURITY_INFORMATION SecurityInformation,
+                          PISECURITY_DESCRIPTOR SecurityDescriptor,
+                          PULONG BufferLength)
+{
+  ULONG_PTR Current;
+  ULONG SidSize;
+  ULONG SdSize;
+  NTSTATUS Status;
+
+  DPRINT("CmiQuerySecurityDescriptor() called\n");
+
+  /*
+   * FIXME:
+   * This is a big hack!!
+   * We need to retrieve the security descriptor from the keys security cell!
+   */
+
+  if (SecurityInformation == 0)
+    {
+      return STATUS_ACCESS_DENIED;
+    }
+
+  SidSize = RtlLengthSid(SeWorldSid);
+  SdSize = sizeof(SECURITY_DESCRIPTOR) + (2 * SidSize);
+
+  if (*BufferLength < SdSize)
+    {
+      *BufferLength = SdSize;
+      return STATUS_BUFFER_TOO_SMALL;
+    }
+
+  *BufferLength = SdSize;
+
+  Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
+                                      SECURITY_DESCRIPTOR_REVISION);
+  if (!NT_SUCCESS(Status))
+    {
+      return Status;
+    }
+
+  SecurityDescriptor->Control |= SE_SELF_RELATIVE;
+  Current = (ULONG_PTR)SecurityDescriptor + sizeof(SECURITY_DESCRIPTOR);
+
+  if (SecurityInformation & OWNER_SECURITY_INFORMATION)
+    {
+      RtlCopyMemory((PVOID)Current,
+                   SeWorldSid,
+                   SidSize);
+      SecurityDescriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)SecurityDescriptor);
+      Current += SidSize;
+    }
+
+  if (SecurityInformation & GROUP_SECURITY_INFORMATION)
+    {
+      RtlCopyMemory((PVOID)Current,
+                   SeWorldSid,
+                   SidSize);
+      SecurityDescriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)SecurityDescriptor);
+      Current += SidSize;
+    }
+
+  if (SecurityInformation & DACL_SECURITY_INFORMATION)
+    {
+      SecurityDescriptor->Control |= SE_DACL_PRESENT;
+    }
+
+  if (SecurityInformation & SACL_SECURITY_INFORMATION)
+    {
+      SecurityDescriptor->Control |= SE_SACL_PRESENT;
     }
 
   return STATUS_SUCCESS;
 }
 
 
-VOID STDCALL
-CmiObjectDelete(PVOID DeletedObject)
+static NTSTATUS
+CmiAssignSecurityDescriptor(PKEY_OBJECT KeyObject,
+                           PSECURITY_DESCRIPTOR SecurityDescriptor)
 {
-  PKEY_OBJECT KeyObject;
+#if 0
+  PREGISTRY_HIVE Hive;
 
-  DPRINT("Delete object key\n");
+  DPRINT1("CmiAssignSecurityDescriptor() callled\n");
 
-  KeyObject = (PKEY_OBJECT) DeletedObject;
+  DPRINT1("KeyObject %p\n", KeyObject);
+  DPRINT1("KeyObject->RegistryHive %p\n", KeyObject->RegistryHive);
 
-  if (!NT_SUCCESS(CmiRemoveKeyFromList(KeyObject)))
+  Hive = KeyObject->RegistryHive;
+  if (Hive == NULL)
     {
-      DPRINT1("Key not found in parent list ???\n");
+      DPRINT1("Create new root security cell\n");
+      return STATUS_SUCCESS;
     }
 
-  if (KeyObject->Flags & KO_MARKED_FOR_DELETE)
+  if (Hive->RootSecurityCell == NULL)
     {
-      DPRINT("delete really key\n");
+      DPRINT1("Create new root security cell\n");
 
-      CmiRemoveSubKey(KeyObject->RegistryHive,
-                     KeyObject->ParentKey,
-                     KeyObject);
+    }
+  else
+    {
+      DPRINT1("Search for security cell\n");
 
-      if (!IsVolatileHive(KeyObject->RegistryHive))
-       {
-         CmiSyncHives();
-       }
     }
+#endif
+
+  return STATUS_SUCCESS;
 }
 
 
@@ -284,11 +450,103 @@ CmiObjectSecurity(PVOID ObjectBody,
                  SECURITY_OPERATION_CODE OperationCode,
                  SECURITY_INFORMATION SecurityInformation,
                  PSECURITY_DESCRIPTOR SecurityDescriptor,
-                 PULONG BufferLength)
+                 PULONG BufferLength,
+                 PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
+                 POOL_TYPE PoolType,
+                 PGENERIC_MAPPING GenericMapping)
 {
-  DPRINT1("CmiObjectSecurity() called\n");
+  DPRINT("CmiObjectSecurity() called\n");
 
-  return(STATUS_SUCCESS);
+  switch (OperationCode)
+    {
+      case SetSecurityDescriptor:
+        DPRINT("Set security descriptor\n");
+        return STATUS_SUCCESS;
+
+      case QuerySecurityDescriptor:
+        DPRINT("Query security descriptor\n");
+        return CmiQuerySecurityDescriptor((PKEY_OBJECT)ObjectBody,
+                                         SecurityInformation,
+                                         SecurityDescriptor,
+                                         BufferLength);
+
+      case DeleteSecurityDescriptor:
+        DPRINT("Delete security descriptor\n");
+        return STATUS_SUCCESS;
+
+      case AssignSecurityDescriptor:
+        DPRINT("Assign security descriptor\n");
+        return CmiAssignSecurityDescriptor((PKEY_OBJECT)ObjectBody,
+                                          SecurityDescriptor);
+    }
+
+  return STATUS_UNSUCCESSFUL;
+}
+
+
+NTSTATUS STDCALL
+CmiObjectQueryName (PVOID ObjectBody,
+                   POBJECT_NAME_INFORMATION ObjectNameInfo,
+                   ULONG Length,
+                   PULONG ReturnLength)
+{
+  PKEY_OBJECT KeyObject;
+  NTSTATUS Status;
+
+  DPRINT ("CmiObjectQueryName() called\n");
+
+  KeyObject = (PKEY_OBJECT)ObjectBody;
+
+  if (KeyObject->ParentKey != KeyObject)
+    {
+      Status = ObQueryNameString (KeyObject->ParentKey,
+                                 ObjectNameInfo,
+                                 Length,
+                                 ReturnLength);
+    }
+  else
+    {
+      /* KeyObject is the root key */
+      Status = ObQueryNameString (HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(KeyObject))->Directory,
+                                 ObjectNameInfo,
+                                 Length,
+                                 ReturnLength);
+    }
+
+  if (!NT_SUCCESS(Status) && Status != STATUS_INFO_LENGTH_MISMATCH)
+    {
+      return Status;
+    }
+  (*ReturnLength) += sizeof(WCHAR) + KeyObject->Name.Length;
+
+  if (Status == STATUS_INFO_LENGTH_MISMATCH || *ReturnLength > Length)
+    {
+      return STATUS_INFO_LENGTH_MISMATCH;
+    }
+
+  if (ObjectNameInfo->Name.Buffer == NULL)
+    {
+      ObjectNameInfo->Name.Buffer = (PWCHAR)(ObjectNameInfo + 1);
+      ObjectNameInfo->Name.Length = 0;
+      ObjectNameInfo->Name.MaximumLength = Length - sizeof(OBJECT_NAME_INFORMATION);
+    }
+
+
+  DPRINT ("Parent path: %wZ\n", ObjectNameInfo->Name);
+
+  Status = RtlAppendUnicodeToString (&ObjectNameInfo->Name,
+                                    L"\\");
+  if (!NT_SUCCESS (Status))
+    return Status;
+
+  Status = RtlAppendUnicodeStringToString (&ObjectNameInfo->Name,
+                                          &KeyObject->Name);
+  if (NT_SUCCESS (Status))
+    {
+      DPRINT ("Total path: %wZ\n", &ObjectNameInfo->Name);
+    }
+
+  return Status;
 }
 
 
@@ -296,22 +554,20 @@ VOID
 CmiAddKeyToList(PKEY_OBJECT ParentKey,
                PKEY_OBJECT NewKey)
 {
-  KIRQL OldIrql;
 
   DPRINT("ParentKey %.08x\n", ParentKey);
 
-  KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
 
   if (ParentKey->SizeOfSubKeys <= ParentKey->NumberOfSubKeys)
     {
       PKEY_OBJECT *tmpSubKeys = ExAllocatePool(NonPagedPool,
-       (ParentKey->NumberOfSubKeys + 1) * sizeof(DWORD));
+       (ParentKey->NumberOfSubKeys + 1) * sizeof(ULONG));
 
       if (ParentKey->NumberOfSubKeys > 0)
        {
-         memcpy(tmpSubKeys,
-                ParentKey->SubKeys,
-                ParentKey->NumberOfSubKeys * sizeof(DWORD));
+         RtlCopyMemory (tmpSubKeys,
+                        ParentKey->SubKeys,
+                        ParentKey->NumberOfSubKeys * sizeof(ULONG));
        }
 
       if (ParentKey->SubKeys)
@@ -325,14 +581,13 @@ CmiAddKeyToList(PKEY_OBJECT ParentKey,
   /*      to allow a dichotomic search */
   ParentKey->SubKeys[ParentKey->NumberOfSubKeys++] = NewKey;
 
-  DPRINT("Reference parent key: 0x%x\n", ParentKey);
+  DPRINT("Reference parent key: 0x%p\n", ParentKey);
 
   ObReferenceObjectByPointer(ParentKey,
                STANDARD_RIGHTS_REQUIRED,
                NULL,
                UserMode);
   NewKey->ParentKey = ParentKey;
-  KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
 }
 
 
@@ -340,11 +595,9 @@ NTSTATUS
 CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove)
 {
   PKEY_OBJECT ParentKey;
-  KIRQL OldIrql;
   DWORD Index;
 
   ParentKey = KeyToRemove->ParentKey;
-  KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
   /* FIXME: If list maintained in alphabetic order, use dichotomic search */
   for (Index = 0; Index < ParentKey->NumberOfSubKeys; Index++)
     {
@@ -355,61 +608,67 @@ CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove)
                          &ParentKey->SubKeys[Index + 1],
                          (ParentKey->NumberOfSubKeys - Index - 1) * sizeof(PKEY_OBJECT));
          ParentKey->NumberOfSubKeys--;
-         KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
 
          DPRINT("Dereference parent key: 0x%x\n", ParentKey);
-       
+
          ObDereferenceObject(ParentKey);
          return STATUS_SUCCESS;
        }
     }
-  KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
 
   return STATUS_UNSUCCESSFUL;
 }
 
 
-PKEY_OBJECT
+NTSTATUS
 CmiScanKeyList(PKEY_OBJECT Parent,
-              PCHAR KeyName,
-              ULONG Attributes)
+              PUNICODE_STRING KeyName,
+              ULONG Attributes,
+              PKEY_OBJECT* ReturnedObject)
 {
   PKEY_OBJECT CurKey;
-  KIRQL OldIrql;
-  WORD NameSize;
-  DWORD Index;
+  ULONG Index;
 
-  DPRINT("Scanning key list for: %s (Parent: %s)\n",
-    KeyName, Parent->Name);
+  DPRINT("Scanning key list for: %wZ (Parent: %wZ)\n",
+        KeyName, &Parent->Name);
 
-  NameSize = strlen(KeyName);
-  KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
   /* FIXME: if list maintained in alphabetic order, use dichotomic search */
   for (Index=0; Index < Parent->NumberOfSubKeys; Index++)
     {
       CurKey = Parent->SubKeys[Index];
       if (Attributes & OBJ_CASE_INSENSITIVE)
        {
-         if ((NameSize == CurKey->NameSize)
-             && (_strnicmp(KeyName, CurKey->Name, NameSize) == 0))
+         if ((KeyName->Length == CurKey->Name.Length)
+             && (_wcsicmp(KeyName->Buffer, CurKey->Name.Buffer) == 0))
            {
-             KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
-             return CurKey;
+             break;
            }
        }
       else
        {
-         if ((NameSize == CurKey->NameSize)
-             && (strncmp(KeyName,CurKey->Name,NameSize) == 0))
+         if ((KeyName->Length == CurKey->Name.Length)
+             && (wcscmp(KeyName->Buffer, CurKey->Name.Buffer) == 0))
            {
-             KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
-             return CurKey;
+             break;
            }
        }
     }
-  KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
 
-  return NULL;
+  if (Index < Parent->NumberOfSubKeys)
+  {
+     if (CurKey->Flags & KO_MARKED_FOR_DELETE)
+     {
+        *ReturnedObject = NULL;
+       return STATUS_UNSUCCESSFUL;
+     }
+     ObReferenceObject(CurKey);
+     *ReturnedObject = CurKey;
+  }
+  else
+  {
+     *ReturnedObject = NULL;
+  }
+  return STATUS_SUCCESS;
 }
 
 
@@ -418,7 +677,7 @@ CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive,
                 PKEY_CELL KeyCell,
                 PUNICODE_STRING TargetPath)
 {
-  UNICODE_STRING LinkName = UNICODE_STRING_INITIALIZER(L"SymbolicLinkValue");
+  UNICODE_STRING LinkName = RTL_CONSTANT_STRING(L"SymbolicLinkValue");
   PVALUE_CELL ValueCell;
   PDATA_CELL DataCell;
   NTSTATUS Status;
@@ -456,7 +715,7 @@ CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive,
 
   if (ValueCell->DataSize > 0)
     {
-      DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
+      DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
       RtlCopyMemory(TargetPath->Buffer,
                    DataCell->Data,
                    TargetPath->Length);