branch update for HEAD-2003021201
[reactos.git] / ntoskrnl / cm / ntfunc.c
index a419b74..8d0a316 100644 (file)
@@ -8,6 +8,9 @@
 
 /* INCLUDES *****************************************************************/
 
+#ifdef WIN32_REGDBG
+#include "cm_win32.h"
+#else
 #include <ddk/ntddk.h>
 #include <roscfg.h>
 #include <internal/ob.h>
@@ -20,6 +23,7 @@
 #include <internal/debug.h>
 
 #include "cm.h"
+#endif
 
 
 /* GLOBALS ******************************************************************/
@@ -34,12 +38,12 @@ static BOOLEAN CmiRegistryInitialized = FALSE;
 
 NTSTATUS STDCALL
 NtCreateKey(OUT PHANDLE KeyHandle,
-       IN ACCESS_MASK DesiredAccess,
-       IN POBJECT_ATTRIBUTES ObjectAttributes,
-       IN ULONG TitleIndex,
-       IN PUNICODE_STRING Class,
-       IN ULONG CreateOptions,
-       OUT PULONG Disposition)
+           IN ACCESS_MASK DesiredAccess,
+           IN POBJECT_ATTRIBUTES ObjectAttributes,
+           IN ULONG TitleIndex,
+           IN PUNICODE_STRING Class,
+           IN ULONG CreateOptions,
+           OUT PULONG Disposition)
 {
   UNICODE_STRING RemainingPath;
   PKEY_OBJECT KeyObject;
@@ -48,17 +52,19 @@ NtCreateKey(OUT PHANDLE KeyHandle,
   PWSTR End;
 
   DPRINT("NtCreateKey (Name %wZ  KeyHandle %x  Root %x)\n",
-         ObjectAttributes->ObjectName,
-         KeyHandle,
-         ObjectAttributes->RootDirectory);
+        ObjectAttributes->ObjectName,
+        KeyHandle,
+        ObjectAttributes->RootDirectory);
 
   /* FIXME: check for standard handle prefix and adjust objectAttributes accordingly */
 
-  Status = ObFindObject(ObjectAttributes, &Object, &RemainingPath, CmiKeyType);
-
+  Status = ObFindObject(ObjectAttributes,
+                       &Object,
+                       &RemainingPath,
+                       CmiKeyType);
   if (!NT_SUCCESS(Status))
     {
-      return Status;
+      return(Status);
     }
 
   DPRINT("RemainingPath %wZ\n", &RemainingPath);
@@ -69,7 +75,7 @@ NtCreateKey(OUT PHANDLE KeyHandle,
       if (((PKEY_OBJECT) Object)->Flags & KO_MARKED_FOR_DELETE)
        {
          ObDereferenceObject(Object);
-         return STATUS_UNSUCCESSFUL;
+         return(STATUS_UNSUCCESSFUL);
        }
 
       if (Disposition)
@@ -106,9 +112,10 @@ NtCreateKey(OUT PHANDLE KeyHandle,
                          NULL,
                          CmiKeyType,
                          (PVOID*)&KeyObject);
-
   if (!NT_SUCCESS(Status))
-    return(Status);
+    {
+      return(Status);
+    }
 
   KeyObject->ParentKey = Object;
 
@@ -121,7 +128,10 @@ NtCreateKey(OUT PHANDLE KeyHandle,
   KeyObject->NumberOfSubKeys = 0;
   KeyObject->SizeOfSubKeys = 0;
   KeyObject->SubKeys = NULL;
-//  KeAcquireSpinLock(&Key->RegistryHive->RegLock, &OldIrql);
+
+  /* Acquire hive lock */
+  ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+
   /* add key to subkeys of parent if needed */
   Status = CmiAddSubKey(KeyObject->RegistryHive,
                        KeyObject->ParentKey,
@@ -131,9 +141,10 @@ NtCreateKey(OUT PHANDLE KeyHandle,
                        TitleIndex,
                        Class,
                        CreateOptions);
-
   if (!NT_SUCCESS(Status))
     {
+      /* Release hive lock */
+      ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
       ObDereferenceObject(KeyObject);
       ObDereferenceObject(Object);
       return STATUS_UNSUCCESSFUL;
@@ -151,7 +162,7 @@ NtCreateKey(OUT PHANDLE KeyHandle,
     {
       KeyObject->KeyCell->ParentKeyOffset = -1;
       KeyObject->KeyCell->SecurityKeyOffset = -1;
-      /* This key must rest in memory unless it is deleted
+      /* This key must remain in memory unless it is deleted
         or file is unloaded */
       ObReferenceObjectByPointer(KeyObject,
                                 STANDARD_RIGHTS_REQUIRED,
@@ -160,7 +171,11 @@ NtCreateKey(OUT PHANDLE KeyHandle,
     }
 
   CmiAddKeyToList(KeyObject->ParentKey, KeyObject);
-//  KeReleaseSpinLock(&KeyObject->RegistryHive->RegLock, OldIrql);
+
+  VERIFY_KEY_OBJECT(KeyObject);
+
+  /* Release hive lock */
+  ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
 
   ObDereferenceObject(KeyObject);
   ObDereferenceObject(Object);
@@ -168,7 +183,7 @@ NtCreateKey(OUT PHANDLE KeyHandle,
   if (Disposition)
     *Disposition = REG_CREATED_NEW_KEY;
 
-  VERIFY_KEY_OBJECT(KeyObject);
+  CmiSyncHives();
 
   return Status;
 }
@@ -183,33 +198,50 @@ NtDeleteKey(IN HANDLE KeyHandle)
   DPRINT("KeyHandle %x\n", KeyHandle);
 
   /* Verify that the handle is valid and is a registry key */
+CHECKPOINT1;
   Status = ObReferenceObjectByHandle(KeyHandle,
-               KEY_WRITE,
-               CmiKeyType,
-               UserMode,
-               (PVOID *) &KeyObject,
-               NULL);
-
+                                    KEY_WRITE,
+                                    CmiKeyType,
+                                    UserMode,
+                                    (PVOID *)&KeyObject,
+                                    NULL);
   if (!NT_SUCCESS(Status))
     {
-      return Status;
+CHECKPOINT1;
+      return(Status);
     }
 
+CHECKPOINT1;
+  /* Acquire hive lock */
+  ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+CHECKPOINT1;
+
   VERIFY_KEY_OBJECT(KeyObject);
 
   /*  Set the marked for delete bit in the key object  */
   KeyObject->Flags |= KO_MARKED_FOR_DELETE;
+CHECKPOINT1;
+
+  /* Release hive lock */
+  ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+
+  DPRINT1("PointerCount %lu\n", ObGetObjectPointerCount((PVOID)KeyObject));
 
   /* Dereference the object */
   ObDereferenceObject(KeyObject);
   if(KeyObject->RegistryHive != KeyObject->ParentKey->RegistryHive)
     ObDereferenceObject(KeyObject);
-  /* Close the handle */
-  ObDeleteHandle(PsGetCurrentProcess(), KeyHandle);
-  /* FIXME: I think that ObDeleteHandle should dereference the object  */
-  ObDereferenceObject(KeyObject);
 
-  return STATUS_SUCCESS;
+  DPRINT1("PointerCount %lu\n", ObGetObjectPointerCount((PVOID)KeyObject));
+
+  /*
+   * Note:
+   * Hive-Synchronization will not be triggered here. This is done in
+   * CmiObjectDelete() (in regobj.c) after all key-related structures
+   * have been released.
+   */
+
+  return(STATUS_SUCCESS);
 }
 
 
@@ -234,13 +266,13 @@ NtEnumerateKey(
   PDATA_CELL pClassData;
 
   DPRINT("KH %x  I %d  KIC %x KI %x  L %d  RL %x\n",
-       KeyHandle,
-       Index,
-         KeyInformationClass,
-       KeyInformation,
-       Length,
-       ResultLength);
-    
+        KeyHandle,
+        Index,
+        KeyInformationClass,
+        KeyInformation,
+        Length,
+        ResultLength);
+
   /* Verify that the handle is valid and is a registry key */
   Status = ObReferenceObjectByHandle(KeyHandle,
                KEY_ENUMERATE_SUB_KEYS,
@@ -251,62 +283,68 @@ NtEnumerateKey(
   if (!NT_SUCCESS(Status))
     {
       DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status);
-      return Status;
+      return(Status);
     }
 
+  /* Acquire hive lock */
+  ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+
   VERIFY_KEY_OBJECT(KeyObject);
 
   /* Get pointer to KeyCell */
   KeyCell = KeyObject->KeyCell;
   RegistryHive = KeyObject->RegistryHive;
-    
+
   /* Get pointer to SubKey */
   if (Index >= KeyCell->NumberOfSubKeys)
-         {
-           if (RegistryHive == CmiVolatileHive)
-                   {
-                     ObDereferenceObject (KeyObject);
-                     DPRINT("No more volatile entries\n");
-                     return STATUS_NO_MORE_ENTRIES;
-                   }
-           else
-                   {
-                    ULONG i;
-                    PKEY_OBJECT CurKey = NULL;
-
-                     /* Search volatile keys */
-                     for (i = 0; i < KeyObject->NumberOfSubKeys; i++)
-                             {
-                               CurKey = KeyObject->SubKeys[i];
-                               if (CurKey->RegistryHive == CmiVolatileHive)
-                                                               {
-                                                                 if (Index-- == KeyObject->NumberOfSubKeys)
-                    break;
-                                                               }
-                             }
-                     if(Index >= KeyCell->NumberOfSubKeys)
-                             {
-                               ObDereferenceObject (KeyObject);
-                               DPRINT("No more non-volatile entries\n");
-                               return STATUS_NO_MORE_ENTRIES;
-                             }
-                     SubKeyCell = CurKey->KeyCell;
-                   }
-         }
+    {
+      if (RegistryHive == CmiVolatileHive)
+       {
+         ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+         ObDereferenceObject(KeyObject);
+         DPRINT("No more volatile entries\n");
+         return(STATUS_NO_MORE_ENTRIES);
+       }
+      else
+       {
+         ULONG i;
+         PKEY_OBJECT CurKey = NULL;
+
+         /* Search volatile keys */
+         for (i = 0; i < KeyObject->NumberOfSubKeys; i++)
+           {
+             CurKey = KeyObject->SubKeys[i];
+             if (CurKey->RegistryHive == CmiVolatileHive)
+               {
+                 if (Index-- == KeyObject->NumberOfSubKeys)
+                   break;
+               }
+           }
+         if (Index >= KeyCell->NumberOfSubKeys)
+           {
+             ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+             ObDereferenceObject(KeyObject);
+             DPRINT("No more non-volatile entries\n");
+             return(STATUS_NO_MORE_ENTRIES);
+           }
+         SubKeyCell = CurKey->KeyCell;
+       }
+    }
   else
-         {
-           HashTableBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL);
-           SubKeyCell = CmiGetKeyFromHashByIndex(RegistryHive, 
-                               HashTableBlock, 
-                               Index);
-         }
+    {
+      HashTableBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL);
+      SubKeyCell = CmiGetKeyFromHashByIndex(RegistryHive,
+                                           HashTableBlock,
+                                           Index);
+    }
 
   if (SubKeyCell == NULL)
-         {
-           ObDereferenceObject (KeyObject);
-           DPRINT("No more entries\n");
-           return STATUS_NO_MORE_ENTRIES;
-         }
+    {
+      ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+      ObDereferenceObject(KeyObject);
+      DPRINT("No more entries\n");
+      return(STATUS_NO_MORE_ENTRIES);
+    }
 
   Status = STATUS_SUCCESS;
   switch (KeyInformationClass)
@@ -413,11 +451,13 @@ NtEnumerateKey(
       break;
     }
   CmiReleaseBlock(RegistryHive, SubKeyCell);
-  ObDereferenceObject (KeyObject);
+
+  ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+  ObDereferenceObject(KeyObject);
 
   DPRINT("Returning status %x\n", Status);
 
-  return  Status;
+  return(Status);
 }
 
 
@@ -440,12 +480,12 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
   PKEY_VALUE_FULL_INFORMATION  ValueFullInformation;
 
   DPRINT("KH %x  I %d  KVIC %x  KVI %x  L %d  RL %x\n",
-       KeyHandle,
-       Index,
-         KeyValueInformationClass,
-       KeyValueInformation,
-       Length,
-       ResultLength);
+        KeyHandle,
+        Index,
+        KeyValueInformationClass,
+        KeyValueInformation,
+        Length,
+        ResultLength);
 
   /*  Verify that the handle is valid and is a registry key  */
   Status = ObReferenceObjectByHandle(KeyHandle,
@@ -460,12 +500,15 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
       return Status;
     }
 
+  /* Acquire hive lock */
+  ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+
   VERIFY_KEY_OBJECT(KeyObject);
 
   /* Get pointer to KeyCell */
   KeyCell = KeyObject->KeyCell;
   RegistryHive = KeyObject->RegistryHive;
-    
+
   /* Get Value block of interest */
   Status = CmiGetValueFromKeyByIndex(RegistryHive,
                KeyCell,
@@ -474,16 +517,26 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
 
   if (!NT_SUCCESS(Status))
     {
+      ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
       ObDereferenceObject(KeyObject);
       return Status;
     }
-  else if (ValueCell != NULL)
+
+  if (ValueCell != NULL)
     {
       switch (KeyValueInformationClass)
         {
         case KeyValueBasicInformation:
-          *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + 
-            (ValueCell->NameSize + 1) * sizeof(WCHAR);
+          if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
+            {
+              *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + 
+                (ValueCell->NameSize + 1) * sizeof(WCHAR);
+            }
+          else
+            {
+              *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + 
+                ValueCell->NameSize + sizeof(WCHAR);
+            }
           if (Length < *ResultLength)
             {
               Status = STATUS_BUFFER_OVERFLOW;
@@ -494,12 +547,24 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
                 KeyValueInformation;
               ValueBasicInformation->TitleIndex = 0;
               ValueBasicInformation->Type = ValueCell->DataType;
-              ValueBasicInformation->NameLength =
-                (ValueCell->NameSize + 1) * sizeof(WCHAR);
-              mbstowcs(ValueBasicInformation->Name,
-                ValueCell->Name,
-                                 ValueCell->NameSize * 2);
-              ValueBasicInformation->Name[ValueCell->NameSize] = 0;
+              if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
+                {
+                  ValueBasicInformation->NameLength =
+                    (ValueCell->NameSize + 1) * sizeof(WCHAR);
+                  CmiCopyPackedName(ValueBasicInformation->Name,
+                                    ValueCell->Name,
+                                    ValueCell->NameSize);
+                  ValueBasicInformation->Name[ValueCell->NameSize] = 0;
+                }
+              else
+                {
+                  ValueBasicInformation->NameLength =
+                    ValueCell->NameSize + sizeof(WCHAR);
+                  RtlCopyMemory(ValueBasicInformation->Name,
+                                ValueCell->Name,
+                                ValueCell->NameSize * sizeof(WCHAR));
+                  ValueBasicInformation->Name[ValueCell->NameSize / sizeof(WCHAR)] = 0;
+                }
             }
           break;
 
@@ -536,8 +601,18 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
           break;
 
         case KeyValueFullInformation:
-          *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) + 
-            ValueCell->NameSize * sizeof(WCHAR) + (ValueCell->DataSize & LONG_MAX);
+          if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
+            {
+              *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) + 
+                (ValueCell->NameSize + 1) * sizeof(WCHAR) +
+                (ValueCell->DataSize & LONG_MAX);
+            }
+          else
+            {
+              *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) + 
+                ValueCell->NameSize + sizeof(WCHAR) +
+                (ValueCell->DataSize & LONG_MAX);
+            }
           if (Length < *ResultLength)
             {
               Status = STATUS_BUFFER_OVERFLOW;
@@ -548,34 +623,47 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
                 KeyValueInformation;
               ValueFullInformation->TitleIndex = 0;
               ValueFullInformation->Type = ValueCell->DataType;
+              if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
+                {
+                  ValueFullInformation->NameLength =
+                    (ValueCell->NameSize + 1) * sizeof(WCHAR);
+
+                  CmiCopyPackedName(ValueFullInformation->Name,
+                                   ValueCell->Name,
+                                   ValueCell->NameSize);
+                  ValueFullInformation->Name[ValueCell->NameSize] = 0;
+                }
+              else
+                {
+                  ValueFullInformation->NameLength =
+                    ValueCell->NameSize + sizeof(WCHAR);
+                  RtlCopyMemory(ValueFullInformation->Name,
+                               ValueCell->Name,
+                               ValueCell->NameSize);
+                  ValueFullInformation->Name[ValueCell->NameSize / sizeof(WCHAR)] = 0;
+                }
               ValueFullInformation->DataOffset = 
-                (DWORD)ValueFullInformation->Name - (DWORD) ValueFullInformation
-                + (ValueCell->NameSize + 1) * sizeof(WCHAR);
+                (ULONG)ValueFullInformation->Name - (ULONG)ValueFullInformation +
+                ValueFullInformation->NameLength;
               ValueFullInformation->DataOffset =
-                           (ValueFullInformation->DataOffset + 3) & 0xfffffffc;
+                (ValueFullInformation->DataOffset + 3) & 0xfffffffc;
               ValueFullInformation->DataLength = ValueCell->DataSize & LONG_MAX;
-              ValueFullInformation->NameLength =
-                (ValueCell->NameSize + 1) * sizeof(WCHAR);
-              mbstowcs(ValueFullInformation->Name,
-                ValueCell->Name,
-                               ValueCell->NameSize * 2);
-              ValueFullInformation->Name[ValueCell->NameSize] = 0;
               if (ValueCell->DataSize > 0)
-                     {
-                       DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
-                       RtlCopyMemory((PCHAR) ValueFullInformation
-                                     + ValueFullInformation->DataOffset,
-                         DataCell->Data,
-                         ValueCell->DataSize & LONG_MAX);
-                       CmiReleaseBlock(RegistryHive, DataCell);
-                     }
+                {
+                  DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
+                  RtlCopyMemory((PCHAR) ValueFullInformation
+                    + ValueFullInformation->DataOffset,
+                    DataCell->Data,
+                    ValueCell->DataSize & LONG_MAX);
+                  CmiReleaseBlock(RegistryHive, DataCell);
+                }
               else
-                     {
-                       RtlCopyMemory((PCHAR) ValueFullInformation
-                                     + ValueFullInformation->DataOffset,
-                         &ValueCell->DataOffset,
-                         ValueCell->DataSize & LONG_MAX);
-                     }
+                {
+                  RtlCopyMemory((PCHAR) ValueFullInformation
+                    + ValueFullInformation->DataOffset,
+                    &ValueCell->DataOffset,
+                    ValueCell->DataSize & LONG_MAX);
+                }
             }
           break;
         }
@@ -584,6 +672,8 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
     {
       Status = STATUS_UNSUCCESSFUL;
     }
+
+  ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
   ObDereferenceObject(KeyObject);
 
   return Status;
@@ -593,47 +683,63 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
 NTSTATUS STDCALL
 NtFlushKey(IN HANDLE KeyHandle)
 {
-       NTSTATUS Status;
-       PKEY_OBJECT  KeyObject;
-       PREGISTRY_HIVE  RegistryHive;
-       WCHAR LogName[MAX_PATH];
-       UNICODE_STRING TmpFileName;
-       HANDLE FileHandle;
-       // HANDLE FileHandleLog;
-       OBJECT_ATTRIBUTES ObjectAttributes;
-       // KIRQL  OldIrql;
-       LARGE_INTEGER fileOffset;
-       DWORD * pEntDword;
-       ULONG i;
+  NTSTATUS Status;
+  PKEY_OBJECT  KeyObject;
+  PREGISTRY_HIVE  RegistryHive;
+#if 0
+  WCHAR LogName[MAX_PATH];
+  UNICODE_STRING TmpFileName;
+  HANDLE FileHandle;
+//  HANDLE FileHandleLog;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  LARGE_INTEGER fileOffset;
+  DWORD * pEntDword;
+  ULONG i;
+#endif
 
   DPRINT("KeyHandle %x\n", KeyHandle);
 
-       /* Verify that the handle is valid and is a registry key */
-       Status = ObReferenceObjectByHandle(KeyHandle,
-               KEY_QUERY_VALUE,
-               CmiKeyType,
-               UserMode,
-               (PVOID *) &KeyObject,
-               NULL);
-
+  /* Verify that the handle is valid and is a registry key */
+  Status = ObReferenceObjectByHandle(KeyHandle,
+                                    KEY_QUERY_VALUE,
+                                    CmiKeyType,
+                                    UserMode,
+                                    (PVOID *)&KeyObject,
+                                    NULL);
   if (!NT_SUCCESS(Status))
     {
-      return Status;
+      return(Status);
     }
 
   VERIFY_KEY_OBJECT(KeyObject);
 
   RegistryHive = KeyObject->RegistryHive;
-//  KeAcquireSpinLock(&RegistryHive->RegLock, &OldIrql);
+
+  /* Acquire hive lock */
+  ExAcquireResourceExclusiveLite(&RegistryHive->HiveResource,
+                                TRUE);
+
+  if (IsPermanentHive(RegistryHive))
+    {
+      /* Flush non-volatile hive */
+      Status = CmiFlushRegistryHive(RegistryHive);
+    }
+  else
+    {
+      Status = STATUS_SUCCESS;
+    }
+
+
+#if 0
   /* Then write changed blocks in .log */
   wcscpy(LogName,RegistryHive->Filename.Buffer);
   wcscat(LogName,L".log");
   RtlInitUnicodeString (&TmpFileName, LogName);
   InitializeObjectAttributes(&ObjectAttributes,
-               &TmpFileName,
-               0,
-               NULL,
-               NULL);
+                            &TmpFileName,
+                            0,
+                            NULL,
+                            NULL);
 
 /* BEGIN FIXME : actually (26 November 200) vfatfs.sys can't create new files
    so we can't create log file
@@ -717,28 +823,28 @@ END FIXME*/
                      NULL,
                      0,
                      FILE_SYNCHRONOUS_IO_NONALERT);
-
   if (!NT_SUCCESS(Status))
     {
+      ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
       ObDereferenceObject(KeyObject);
       return Status;
     }
 
   RegistryHive->HiveHeader->Version++;
 
-  Status = ZwWriteFile(FileHandle, 
-               0,
-    0,
-    0,
-    0, 
-               RegistryHive->HiveHeader, 
-               sizeof(HIVE_HEADER), 
-               0,
-    0);
-
+  Status = ZwWriteFile(FileHandle,
+                      0,
+                      0,
+                      0,
+                      0,
+                      RegistryHive->HiveHeader,
+                      sizeof(HIVE_HEADER),
+                      0,
+                      0);
   if (!NT_SUCCESS(Status))
     {
       ZwClose(FileHandle);
+      ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
       ObDereferenceObject(KeyObject);
       return Status;
     }
@@ -746,35 +852,33 @@ END FIXME*/
   /* Update changed blocks in file */
   fileOffset.u.HighPart = 0;
   for (i = 0; i < RegistryHive->BlockListSize ; i++)
-  {
-    if (RegistryHive->BlockList[i]->DateModified.dwHighDateTime
+    {
+      if (RegistryHive->BlockList[i]->DateModified.dwHighDateTime
            > RegistryHive->HiveHeader->DateModified.dwHighDateTime
-      || (RegistryHive->BlockList[i]->DateModified.dwHighDateTime
+         || (RegistryHive->BlockList[i]->DateModified.dwHighDateTime
                == RegistryHive->HiveHeader->DateModified.dwHighDateTime
-          && RegistryHive->BlockList[i]->DateModified.dwLowDateTime
-               > RegistryHive->HiveHeader->DateModified.dwLowDateTime
-         )
-       )
+             && RegistryHive->BlockList[i]->DateModified.dwLowDateTime
+                > RegistryHive->HiveHeader->DateModified.dwLowDateTime))
+       {
+         fileOffset.u.LowPart = RegistryHive->BlockList[i]->BlockOffset+4096;
+         Status = NtWriteFile(FileHandle,
+                              0,
+                              0,
+                              0,
+                              0,
+                              RegistryHive->BlockList[i],
+                              RegistryHive->BlockList[i]->BlockSize,
+                              &fileOffset,
+                              0);
+         if (!NT_SUCCESS(Status))
            {
-             fileOffset.u.LowPart = RegistryHive->BlockList[i]->BlockOffset+4096;
-             Status = NtWriteFile(FileHandle, 
-                                       0,
-               0,
-               0,
-               0, 
-                                       RegistryHive->BlockList[i],
-                                       RegistryHive->BlockList[i]->BlockSize ,
-                                       &fileOffset,
-               0);
-
-                         if (!NT_SUCCESS(Status))
-                           {
-                             ZwClose(FileHandle);
-                             ObDereferenceObject(KeyObject);
-                             return Status;
-                           }
+             ZwClose(FileHandle);
+             ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+             ObDereferenceObject(KeyObject);
+             return(Status);
            }
-  }
+       }
+    }
 
   /* Change version in header */
   RegistryHive->HiveHeader->VersionOld = RegistryHive->HiveHeader->Version;
@@ -790,26 +894,31 @@ END FIXME*/
 
   /* Write new header */
   fileOffset.u.LowPart = 0;
-  Status = ZwWriteFile(FileHandle, 
-               0,
-    0,
-    0,
-    0, 
-               RegistryHive->HiveHeader, 
-               sizeof(HIVE_HEADER), 
-               &fileOffset,
-    0);
+  Status = ZwWriteFile(FileHandle,
+                      0,
+                      0,
+                      0,
+                      0,
+                      RegistryHive->HiveHeader,
+                      sizeof(HIVE_HEADER),
+                      &fileOffset,
+                      0);
 
   if (!NT_SUCCESS(Status))
     {
       ZwClose(FileHandle);
+      ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
       ObDereferenceObject(KeyObject);
       return Status;
     }
 
   ZwClose(FileHandle);
-//  KeReleaseSpinLock(&RegistryHive->RegLock, OldIrql);
+#endif
+
+  ExReleaseResourceLite(&RegistryHive->HiveResource);
+
   ObDereferenceObject(KeyObject);
+
   return STATUS_SUCCESS;
 }
 
@@ -823,7 +932,7 @@ NtOpenKey(OUT PHANDLE KeyHandle,
   NTSTATUS Status;
   PVOID Object;
 
-  DPRINT("KH %x  DA %x  OA %x  OA->ON %x\n",
+  DPRINT("NtOpenFile(KH %x  DA %x  OA %x  OA->ON '%wZ'\n",
         KeyHandle,
         DesiredAccess,
         ObjectAttributes,
@@ -841,7 +950,7 @@ NtOpenKey(OUT PHANDLE KeyHandle,
 
   VERIFY_KEY_OBJECT((PKEY_OBJECT) Object);
 
-  DPRINT("RemainingPath.Buffer %x\n", RemainingPath.Buffer);
+  DPRINT("RemainingPath '%wZ'\n", &RemainingPath);
 
   if ((RemainingPath.Buffer != NULL) && (RemainingPath.Buffer[0] != 0))
     {
@@ -873,11 +982,11 @@ NtOpenKey(OUT PHANDLE KeyHandle,
 
 
 NTSTATUS STDCALL
-NtQueryKey(IN  HANDLE KeyHandle,
-       IN      KEY_INFORMATION_CLASS   KeyInformationClass,
-       OUT     PVOID   KeyInformation,
-       IN      ULONG   Length,
-       OUT     PULONG ResultLength)
+NtQueryKey(IN HANDLE KeyHandle,
+          IN KEY_INFORMATION_CLASS KeyInformationClass,
+          OUT PVOID KeyInformation,
+          IN ULONG Length,
+          OUT PULONG ResultLength)
 {
   PKEY_BASIC_INFORMATION BasicInformation;
   PKEY_NODE_INFORMATION NodeInformation;
@@ -889,12 +998,12 @@ NtQueryKey(IN     HANDLE KeyHandle,
   NTSTATUS Status;
 
   DPRINT("KH %x  KIC %x  KI %x  L %d  RL %x\n",
-       KeyHandle,
-    KeyInformationClass,
-       KeyInformation,
-    Length,
-    ResultLength);
-    
+        KeyHandle,
+        KeyInformationClass,
+        KeyInformation,
+        Length,
+        ResultLength);
+
   /* Verify that the handle is valid and is a registry key */
   Status = ObReferenceObjectByHandle(KeyHandle,
                KEY_READ,
@@ -902,22 +1011,28 @@ NtQueryKey(IN    HANDLE KeyHandle,
                UserMode,
                (PVOID *) &KeyObject,
                NULL);
-
   if (!NT_SUCCESS(Status))
     {
+CHECKPOINT1;
       return Status;
     }
+CHECKPOINT1;
+
+  /* Acquire hive lock */
+  ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+CHECKPOINT1;
 
   VERIFY_KEY_OBJECT(KeyObject);
 
   /* Get pointer to KeyCell */
   KeyCell = KeyObject->KeyCell;
   RegistryHive = KeyObject->RegistryHive;
-    
+
   Status = STATUS_SUCCESS;
   switch (KeyInformationClass)
     {
     case KeyBasicInformation:
+CHECKPOINT1;
       /* Check size of buffer */
       if (Length < sizeof(KEY_BASIC_INFORMATION) + 
           KeyObject->NameSize * sizeof(WCHAR))
@@ -938,8 +1053,9 @@ NtQueryKey(IN      HANDLE KeyHandle,
           *ResultLength = sizeof(KEY_BASIC_INFORMATION) + 
             KeyObject->NameSize * sizeof(WCHAR);
         }
+CHECKPOINT1;
       break;
-      
+
     case KeyNodeInformation:
       /* Check size of buffer */
       if (Length < sizeof(KEY_NODE_INFORMATION)
@@ -1019,11 +1135,16 @@ NtQueryKey(IN   HANDLE KeyHandle,
       break;
     }
 
+CHECKPOINT1;
+  ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+CHECKPOINT1;
   ObDereferenceObject(KeyObject);
+CHECKPOINT1;
 
-  return Status;
+  return(Status);
 }
 
+
 NTSTATUS STDCALL
 NtQueryValueKey(IN HANDLE KeyHandle,
        IN PUNICODE_STRING ValueName,
@@ -1041,14 +1162,10 @@ NtQueryValueKey(IN HANDLE KeyHandle,
   PKEY_VALUE_BASIC_INFORMATION  ValueBasicInformation;
   PKEY_VALUE_PARTIAL_INFORMATION  ValuePartialInformation;
   PKEY_VALUE_FULL_INFORMATION  ValueFullInformation;
-  char ValueName2[MAX_PATH];
 
   DPRINT("NtQueryValueKey(KeyHandle %x  ValueName %S  Length %x)\n",
     KeyHandle, ValueName->Buffer, Length);
 
-  wcstombs(ValueName2, ValueName->Buffer, ValueName->Length >> 1);
-  ValueName2[ValueName->Length >> 1] = 0;
-
   /* Verify that the handle is valid and is a registry key */
   Status = ObReferenceObjectByHandle(KeyHandle,
                KEY_QUERY_VALUE,
@@ -1063,30 +1180,43 @@ NtQueryValueKey(IN HANDLE KeyHandle,
       return Status;
     }
 
+  /* Acquire hive lock */
+  ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+
   VERIFY_KEY_OBJECT(KeyObject);
 
   /* Get pointer to KeyCell */
   KeyCell = KeyObject->KeyCell;
   RegistryHive = KeyObject->RegistryHive;
-  /* Get Value block of interest */
-  Status = CmiScanKeyForValue(RegistryHive, 
-               KeyCell,
-               ValueName2,
-               &ValueCell,NULL);
 
+  /* Get Value block of interest */
+  Status = CmiScanKeyForValue(RegistryHive,
+                             KeyCell,
+                             ValueName,
+                             &ValueCell,
+                             NULL);
   if (!NT_SUCCESS(Status))
     {
       DPRINT("CmiScanKeyForValue() failed with status %x\n", Status);
+      ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
       ObDereferenceObject(KeyObject);
-      return Status;
+      return(Status);
     }
   else if (ValueCell != NULL)
     {
       switch (KeyValueInformationClass)
         {
         case KeyValueBasicInformation:
-          *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION)
-            + ValueCell->NameSize * sizeof(WCHAR);
+          if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
+            {
+              *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + 
+                (ValueCell->NameSize + 1) * sizeof(WCHAR);
+            }
+          else
+            {
+              *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + 
+                ValueCell->NameSize + sizeof(WCHAR);
+            }
           if (Length < *ResultLength)
             {
               Status = STATUS_BUFFER_TOO_SMALL;
@@ -1097,11 +1227,24 @@ NtQueryValueKey(IN HANDLE KeyHandle,
                 KeyValueInformation;
               ValueBasicInformation->TitleIndex = 0;
               ValueBasicInformation->Type = ValueCell->DataType;
-              ValueBasicInformation->NameLength = 
-                (ValueCell->NameSize + 1) * sizeof(WCHAR);
-              mbstowcs(ValueBasicInformation->Name,
-                ValueCell->Name,ValueCell->NameSize * 2);
-              ValueBasicInformation->Name[ValueCell->NameSize] = 0;
+              if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
+                {
+                  ValueBasicInformation->NameLength =
+                    (ValueCell->NameSize + 1) * sizeof(WCHAR);
+                  CmiCopyPackedName(ValueBasicInformation->Name,
+                                    ValueCell->Name,
+                                    ValueCell->NameSize);
+                  ValueBasicInformation->Name[ValueCell->NameSize] = 0;
+                }
+              else
+                {
+                  ValueBasicInformation->NameLength =
+                    ValueCell->NameSize + sizeof(WCHAR);
+                  RtlCopyMemory(ValueBasicInformation->Name,
+                                ValueCell->Name,
+                                ValueCell->NameSize * sizeof(WCHAR));
+                  ValueBasicInformation->Name[ValueCell->NameSize / sizeof(WCHAR)] = 0;
+                }
             }
           break;
 
@@ -1114,68 +1257,91 @@ NtQueryValueKey(IN HANDLE KeyHandle,
             }
           else
             {
-              ValuePartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION) 
+              ValuePartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)
                 KeyValueInformation;
               ValuePartialInformation->TitleIndex = 0;
               ValuePartialInformation->Type = ValueCell->DataType;
               ValuePartialInformation->DataLength = ValueCell->DataSize & LONG_MAX;
               if (ValueCell->DataSize > 0)
-                     {
-                       DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
-                       RtlCopyMemory(ValuePartialInformation->Data, 
+                {
+                  DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
+                  RtlCopyMemory(ValuePartialInformation->Data,
                     DataCell->Data,
                     ValueCell->DataSize & LONG_MAX);
-                       CmiReleaseBlock(RegistryHive, DataCell);
-                     }
+                  CmiReleaseBlock(RegistryHive, DataCell);
+                }
               else
-                     {
-                       RtlCopyMemory(ValuePartialInformation->Data, 
-                    &ValueCell->DataOffset, 
+                {
+                  RtlCopyMemory(ValuePartialInformation->Data,
+                    &ValueCell->DataOffset,
                     ValueCell->DataSize & LONG_MAX);
-                     }
+                }
             }
           break;
 
         case KeyValueFullInformation:
-          *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION)
-                                               + (ValueCell->NameSize -1) * sizeof(WCHAR)
-                                               + (ValueCell->DataSize & LONG_MAX);
+          if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
+            {
+              *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) + 
+                (ValueCell->NameSize + 1) * sizeof(WCHAR) +
+                (ValueCell->DataSize & LONG_MAX);
+            }
+          else
+            {
+              *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) + 
+                ValueCell->NameSize + sizeof(WCHAR) +
+                (ValueCell->DataSize & LONG_MAX);
+            }
           if (Length < *ResultLength)
             {
               Status = STATUS_BUFFER_TOO_SMALL;
             }
           else
             {
-              ValueFullInformation = (PKEY_VALUE_FULL_INFORMATION) 
+              ValueFullInformation = (PKEY_VALUE_FULL_INFORMATION)
                 KeyValueInformation;
               ValueFullInformation->TitleIndex = 0;
               ValueFullInformation->Type = ValueCell->DataType;
+              if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
+                {
+                  ValueFullInformation->NameLength =
+                    (ValueCell->NameSize + 1) * sizeof(WCHAR);
+                  CmiCopyPackedName(ValueFullInformation->Name,
+                                    ValueCell->Name,
+                                    ValueCell->NameSize);
+                  ValueFullInformation->Name[ValueCell->NameSize] = 0;
+                }
+              else
+                {
+                  ValueFullInformation->NameLength =
+                    ValueCell->NameSize + sizeof(WCHAR);
+                  RtlCopyMemory(ValueFullInformation->Name,
+                                ValueCell->Name,
+                                ValueCell->NameSize);
+                  ValueFullInformation->Name[ValueCell->NameSize / sizeof(WCHAR)] = 0;
+                }
               ValueFullInformation->DataOffset = 
-                (DWORD)ValueFullInformation->Name - (DWORD)ValueFullInformation
-                + (ValueCell->NameSize + 1) * sizeof(WCHAR);
+                (ULONG)ValueFullInformation->Name - (ULONG)ValueFullInformation +
+                ValueFullInformation->NameLength;
               ValueFullInformation->DataOffset =
-                (ValueFullInformation->DataOffset + 3) &0xfffffffc;
+                (ValueFullInformation->DataOffset + 3) & 0xfffffffc;
               ValueFullInformation->DataLength = ValueCell->DataSize & LONG_MAX;
-              ValueFullInformation->NameLength =
-                (ValueCell->NameSize + 1) * sizeof(WCHAR);
-              mbstowcs(ValueFullInformation->Name, ValueCell->Name,ValueCell->NameSize*2);
-              ValueFullInformation->Name[ValueCell->NameSize] = 0;
               if (ValueCell->DataSize > 0)
-                     {
-                       DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
-                       RtlCopyMemory((PCHAR) ValueFullInformation
-                                     + ValueFullInformation->DataOffset,
-                         DataCell->Data, 
-                         ValueCell->DataSize & LONG_MAX);
-                       CmiReleaseBlock(RegistryHive, DataCell);
-                     }
+                {
+                  DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
+                  RtlCopyMemory((PCHAR) ValueFullInformation
+                                + ValueFullInformation->DataOffset,
+                                DataCell->Data,
+                                ValueCell->DataSize & LONG_MAX);
+                  CmiReleaseBlock(RegistryHive, DataCell);
+                }
               else
-                     {
-                       RtlCopyMemory((PCHAR) ValueFullInformation
-                                     + ValueFullInformation->DataOffset,
-                    &ValueCell->DataOffset, 
-                    ValueCell->DataSize & LONG_MAX);
-                     }
+                {
+                  RtlCopyMemory((PCHAR) ValueFullInformation
+                                + ValueFullInformation->DataOffset,
+                                &ValueCell->DataOffset,
+                  ValueCell->DataSize & LONG_MAX);
+                }
             }
           break;
         }
@@ -1185,8 +1351,9 @@ NtQueryValueKey(IN HANDLE KeyHandle,
       Status = STATUS_OBJECT_NAME_NOT_FOUND;
     }
 
+  ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
   ObDereferenceObject(KeyObject);
-  
+
   return Status;
 }
 
@@ -1205,18 +1372,13 @@ NtSetValueKey(IN HANDLE KeyHandle,
   PKEY_CELL  KeyCell;
   PVALUE_CELL  ValueCell;
   BLOCK_OFFSET VBOffset;
-  char ValueName2[MAX_PATH];
   PDATA_CELL DataCell;
   PDATA_CELL NewDataCell;
   PHBIN pBin;
   ULONG DesiredAccess;
-// KIRQL  OldIrql;
 
-  DPRINT("KeyHandle %x  ValueName %S  Type %d\n",
-    KeyHandle, ValueName? ValueName->Buffer : NULL, Type);
-
-  wcstombs(ValueName2,ValueName->Buffer, ValueName->Length >> 1);
-  ValueName2[ValueName->Length>>1] = 0;
+  DPRINT("NtSetValueKey(KeyHandle %x  ValueName %S  Type %d)\n",
+        KeyHandle, ValueName? ValueName->Buffer : NULL, Type);
 
   DesiredAccess = KEY_SET_VALUE;
   if (Type == REG_LINK)
@@ -1232,6 +1394,9 @@ NtSetValueKey(IN HANDLE KeyHandle,
   if (!NT_SUCCESS(Status))
     return(Status);
 
+  /* Acquire hive lock exclucively */
+  ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+
   VERIFY_KEY_OBJECT(KeyObject);
 
   /* Get pointer to key cell */
@@ -1239,105 +1404,138 @@ NtSetValueKey(IN HANDLE KeyHandle,
   RegistryHive = KeyObject->RegistryHive;
   Status = CmiScanKeyForValue(RegistryHive,
                              KeyCell,
-                             ValueName2,
+                             ValueName,
                              &ValueCell,
                              &VBOffset);
   if (!NT_SUCCESS(Status))
     {
       DPRINT1("Value not found. Status 0x%X\n", Status);
 
+      ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
       ObDereferenceObject(KeyObject);
       return(Status);
     }
 
-//  KeAcquireSpinLock(&RegistryHive->RegLock, &OldIrql);
-
   if (ValueCell == NULL)
     {
+      DPRINT("Allocate new value cell\n");
       Status = CmiAddValueToKey(RegistryHive,
                                KeyCell,
-                               ValueName2,
+                               ValueName,
                                &ValueCell,
                                &VBOffset);
+      if (NT_SUCCESS(Status))
+       {
+         CmiMarkBlockDirty(RegistryHive, VBOffset);
+       }
     }
 
   if (!NT_SUCCESS(Status))
     {
       DPRINT1("Cannot add value. Status 0x%X\n", Status);
 
+      ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
       ObDereferenceObject(KeyObject);
       return(Status);
     }
-  else
-    {
-      DPRINT("DataSize (%d)\n", DataSize);
 
+  DPRINT("DataSize %lu\n", DataSize);
+  DPRINT("ValueCell %p\n", ValueCell);
+  DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
+
+  if (DataSize <= 4)
+    {
       /* If datasize <= 4 then write in valueblock directly */
-      if (DataSize <= 4)
+      DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
+      if ((ValueCell->DataSize >= 0) &&
+         (DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL)))
        {
-         DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
-         if ((ValueCell->DataSize >= 0) &&
-             (DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL)))
-           {
-             CmiDestroyBlock(RegistryHive, DataCell, ValueCell->DataOffset);
-           }
-
-         RtlCopyMemory(&ValueCell->DataOffset, Data, DataSize);
-         ValueCell->DataSize = DataSize | 0x80000000;
-         ValueCell->DataType = Type;
-         RtlMoveMemory(&ValueCell->DataOffset, Data, DataSize);
+         CmiDestroyBlock(RegistryHive, DataCell, ValueCell->DataOffset);
        }
+
+      RtlCopyMemory(&ValueCell->DataOffset, Data, DataSize);
+      ValueCell->DataSize = DataSize | 0x80000000;
+      ValueCell->DataType = Type;
+      RtlMoveMemory(&ValueCell->DataOffset, Data, DataSize);
+      CmiMarkBlockDirty(RegistryHive, VBOffset);
+    }
+  else if (DataSize <= (ULONG) (ValueCell->DataSize & 0x7fffffff))
+    {
       /* If new data size is <= current then overwrite current data */
-      else if (DataSize <= (ValueCell->DataSize & 0x7fffffff))
+      DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset,&pBin);
+      RtlZeroMemory(DataCell->Data, ValueCell->DataSize);
+      RtlCopyMemory(DataCell->Data, Data, DataSize);
+      ValueCell->DataSize = DataSize;
+      ValueCell->DataType = Type;
+      CmiReleaseBlock(RegistryHive, DataCell);
+
+      /* Update time of heap */
+      if (IsPermanentHive(RegistryHive))
        {
-         DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset,&pBin);
-         RtlCopyMemory(DataCell->Data, Data, DataSize);
-         ValueCell->DataSize = DataSize;
-         ValueCell->DataType = Type;
-         CmiReleaseBlock(RegistryHive, DataCell);
-         /* Update time of heap */
-         if (IsPermanentHive(RegistryHive))
-           {
-             ZwQuerySystemTime((PTIME) &pBin->DateModified);
-           }
+         ZwQuerySystemTime((PTIME) &pBin->DateModified);
        }
-      else
-       {
-         BLOCK_OFFSET NewOffset;
+      CmiMarkBlockDirty(RegistryHive, ValueCell->DataOffset);
+    }
+  else
+    {
+      /*
+       * New data size is larger than the current, destroy current
+       * data block and allocate a new one.
+       */
+      BLOCK_OFFSET NewOffset;
 
-         /* Destroy current data block and allocate a new one */
-         if ((ValueCell->DataSize >= 0) &&
-             (DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL)))
-           {
-             CmiDestroyBlock(RegistryHive, DataCell, ValueCell->DataOffset);
-           }
-         Status = CmiAllocateBlock(RegistryHive,
-                                   (PVOID *)&NewDataCell,
-                                   DataSize,
-                                   &NewOffset);
-         RtlCopyMemory(&NewDataCell->Data[0], Data, DataSize);
-         ValueCell->DataSize = DataSize;
-         ValueCell->DataType = Type;
-         CmiReleaseBlock(RegistryHive, NewDataCell);
-         ValueCell->DataOffset = NewOffset;
-       }
+      DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
 
-      if (strcmp(ValueName2, "SymbolicLinkValue") == 0)
+      if ((ValueCell->DataSize >= 0) &&
+         (DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL)))
        {
-         KeyCell->Type = REG_LINK_KEY_CELL_TYPE;
+         CmiDestroyBlock(RegistryHive, DataCell, ValueCell->DataOffset);
+         ValueCell->DataSize = 0;
+         ValueCell->DataType = 0;
+         ValueCell->DataOffset = 0xffffffff;
        }
 
-      /* Update time of heap */
-      if (IsPermanentHive(RegistryHive) && CmiGetBlock(RegistryHive, VBOffset, &pBin))
+      Status = CmiAllocateBlock(RegistryHive,
+                               (PVOID *)&NewDataCell,
+                               DataSize,
+                               &NewOffset);
+      if (!NT_SUCCESS(Status))
        {
-         ZwQuerySystemTime((PTIME) &pBin->DateModified);
+         DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status);
+
+         ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+         ObDereferenceObject(KeyObject);
+
+         return(Status);
        }
+
+      RtlCopyMemory(&NewDataCell->Data[0], Data, DataSize);
+      ValueCell->DataSize = DataSize;
+      ValueCell->DataType = Type;
+      CmiReleaseBlock(RegistryHive, NewDataCell);
+      ValueCell->DataOffset = NewOffset;
+      CmiMarkBlockDirty(RegistryHive, ValueCell->DataOffset);
+    }
+
+  /* Mark link key */
+  if ((_wcsicmp(ValueName->Buffer, L"SymbolicLinkValue") == 0) &&
+      (Type == REG_LINK))
+    {
+      KeyCell->Type = REG_LINK_KEY_CELL_TYPE;
+      CmiMarkBlockDirty(RegistryHive, KeyObject->BlockOffset);
     }
 
-//  KeReleaseSpinLock(&RegistryHive->RegLock, OldIrql);
+  /* Update time of heap */
+  if (IsPermanentHive(RegistryHive) && CmiGetBlock(RegistryHive, VBOffset, &pBin))
+    {
+      ZwQuerySystemTime((PTIME) &pBin->DateModified);
+    }
 
+  ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
   ObDereferenceObject(KeyObject);
 
+  CmiSyncHives();
+
   DPRINT("Return Status 0x%X\n", Status);
 
   return(Status);
@@ -1346,17 +1544,10 @@ NtSetValueKey(IN HANDLE KeyHandle,
 
 NTSTATUS STDCALL
 NtDeleteValueKey(IN HANDLE KeyHandle,
-  IN PUNICODE_STRING ValueName)
+                IN PUNICODE_STRING ValueName)
 {
-  PREGISTRY_HIVE RegistryHive;
-  CHAR ValueName2[MAX_PATH];
   PKEY_OBJECT KeyObject;
-  PKEY_CELL KeyCell;
   NTSTATUS Status;
-//  KIRQL  OldIrql;
-
-  wcstombs(ValueName2, ValueName->Buffer, ValueName->Length >> 1);
-  ValueName2[ValueName->Length>>1] = 0;
 
   /* Verify that the handle is valid and is a registry key */
   Status = ObReferenceObjectByHandle(KeyHandle,
@@ -1365,22 +1556,28 @@ NtDeleteValueKey(IN HANDLE KeyHandle,
                UserMode,
                (PVOID *)&KeyObject,
                NULL);
-
   if (!NT_SUCCESS(Status))
     {
       return Status;
     }
 
+  /* Acquire hive lock */
+  ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+
   VERIFY_KEY_OBJECT(KeyObject);
 
-  /* Get pointer to KeyCell */
-  KeyCell = KeyObject->KeyCell;
-  RegistryHive = KeyObject->RegistryHive;
-//  KeAcquireSpinLock(&RegistryHive->RegLock, &OldIrql);
-  Status = CmiDeleteValueFromKey(RegistryHive, KeyCell, ValueName2);
-//  KeReleaseSpinLock(&RegistryHive->RegLock, OldIrql);
+  Status = CmiDeleteValueFromKey(KeyObject->RegistryHive,
+                                KeyObject->KeyCell,
+                                KeyObject->BlockOffset,
+                                ValueName);
+
+  /* Release hive lock */
+  ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+
   ObDereferenceObject(KeyObject);
 
+  CmiSyncHives();
+
   return Status;
 }
 
@@ -1405,12 +1602,12 @@ NtLoadKey2(IN PHANDLE KeyHandle,
 NTSTATUS STDCALL
 NtNotifyChangeKey(
        IN      HANDLE  KeyHandle,
-       IN      HANDLE  Event,
-       IN      PIO_APC_ROUTINE  ApcRoutine  OPTIONAL, 
-       IN      PVOID    ApcContext  OPTIONAL, 
+       IN      HANDLE  Event,
+       IN      PIO_APC_ROUTINE  ApcRoutine  OPTIONAL,
+       IN      PVOID  ApcContext  OPTIONAL,
        OUT     PIO_STATUS_BLOCK  IoStatusBlock,
        IN      ULONG  CompletionFilter,
-       IN      BOOLEAN  Asynchroneous, 
+       IN      BOOLEAN  Asynchroneous,
        OUT     PVOID  ChangeBuffer,
        IN      ULONG  Length,
        IN      BOOLEAN  WatchSubtree)
@@ -1421,14 +1618,13 @@ NtNotifyChangeKey(
 
 NTSTATUS STDCALL
 NtQueryMultipleValueKey(IN HANDLE KeyHandle,
-       IN OUT PKEY_VALUE_ENTRY ValueList,
-       IN ULONG NumberOfValues,
-       OUT PVOID Buffer,
-       IN OUT PULONG Length,
-       OUT PULONG ReturnLength)
+                       IN OUT PKEY_VALUE_ENTRY ValueList,
+                       IN ULONG NumberOfValues,
+                       OUT PVOID Buffer,
+                       IN OUT PULONG Length,
+                       OUT PULONG ReturnLength)
 {
   PREGISTRY_HIVE RegistryHive;
-  UCHAR ValueName[MAX_PATH];
   PVALUE_CELL ValueCell;
   PKEY_OBJECT KeyObject;
   PDATA_CELL DataCell;
@@ -1451,6 +1647,9 @@ NtQueryMultipleValueKey(IN HANDLE KeyHandle,
       return(Status);
     }
 
+  /* Acquire hive lock */
+  ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+
   VERIFY_KEY_OBJECT(KeyObject);
 
   /* Get pointer to KeyCell */
@@ -1461,17 +1660,12 @@ NtQueryMultipleValueKey(IN HANDLE KeyHandle,
 
   for (i = 0; i < NumberOfValues; i++)
     {
-      wcstombs(ValueName,
-              ValueList[i].ValueName->Buffer,
-              ValueList[i].ValueName->Length >> 1);
-      ValueName[ValueList[i].ValueName->Length >> 1] = 0;
-
-      DPRINT("ValueName: '%s'\n", ValueName);
+      DPRINT("ValueName: '%wZ'\n", ValueList[i].ValueName);
 
       /* Get Value block of interest */
       Status = CmiScanKeyForValue(RegistryHive,
                          KeyCell,
-                         ValueName,
+                         ValueList[i].ValueName,
                          &ValueCell,
                          NULL);
 
@@ -1524,11 +1718,14 @@ NtQueryMultipleValueKey(IN HANDLE KeyHandle,
 
   *ReturnLength = BufferLength;
 
+  /* Release hive lock */
+  ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+
   ObDereferenceObject(KeyObject);
 
   DPRINT("Return Status 0x%X\n", Status);
 
-  return Status;
+  return(Status);
 }