Revert Filip's last 4 changes on his request as they break booting
[reactos.git] / reactos / boot / freeldr / freeldr / reactos / binhive.c
index 8a94e81..f9ea51f 100644 (file)
  */
 
 #include <freeldr.h>
-#include <rtl.h>
-#include <mm.h>
-#include <debug.h>
-
-#include "registry.h"
 
+#define NDEBUG
+#include <debug.h>
 
 #define  REG_HIVE_ID                   0x66676572 /* "regf" */
 #define  REG_BIN_ID                    0x6e696268 /* "hbin" */
@@ -60,19 +57,20 @@ typedef struct _HIVE_HEADER
   ULONG  UpdateCounter2;
 
   /* When this hive file was last modified */
-  ULONGLONG  DateModified;     /* FILETIME */
+  ULONGLONG  DateModified;
 
-  /* Registry format version ? (1?) */
-  ULONG  Unused3;
+  /* Registry format major version (1) */
+  ULONG  MajorVersion;
 
-  /* Registry format version ? (3?) */
-  ULONG  Unused4;
+  /* Registry format minor version (3)
+     Version 3 added fast indexes, version 5 has large value optimizations */
+  ULONG  MinorVersion;
 
-  /* Registry format version ? (0?) */
-  ULONG  Unused5;
+  /* Registry file type (0 - Primary, 1 - Log) */
+  ULONG  Type;
 
-  /* Registry format version ? (1?) */
-  ULONG  Unused6;
+  /* Registry format (1 is the only defined value so far) */
+  ULONG  Format;
 
   /* Offset into file from the byte after the end of the base block.
      If the hive is volatile, this is the actual pointer to the KEY_CELL */
@@ -85,10 +83,9 @@ typedef struct _HIVE_HEADER
   ULONG  Unused7;
 
   /* Name of hive file */
-  WCHAR  FileName[64];
+  WCHAR  FileName[48];
 
-  /* ? */
-  ULONG  Unused8[83];
+  ULONG  Reserved[99];
 
   /* Checksum of first 0x200 bytes */
   ULONG  Checksum;
@@ -100,20 +97,19 @@ typedef struct _BIN_HEADER
   /* Bin identifier "hbin" (0x6E696268) */
   ULONG  HeaderId;
 
-  /* Bin offset */
+  /* Block offset of this bin */
   BLOCK_OFFSET  BinOffset;
 
   /* Size in bytes, multiple of the block size (4KB) */
   ULONG  BinSize;
 
-  /* ? */
-  ULONG  Unused1;
+  ULONG  Reserved[2];
 
   /* When this bin was last modified */
-  ULONGLONG  DateModified;             /* FILETIME */
+  ULONGLONG  DateModified;
 
-  /* ? */
-  ULONG  Unused2;
+  /* ? (In-memory only) */
+  ULONG  MemAlloc;
 } __attribute__((packed)) HBIN, *PHBIN;
 
 
@@ -132,8 +128,8 @@ typedef struct _KEY_CELL
   /* Key cell identifier "kn" (0x6b6e) */
   USHORT  Id;
 
-  /* ? */
-  USHORT  Type;
+  /* Flags */
+  USHORT  Flags;
 
   /* Time of last flush */
   ULONGLONG  LastWriteTime;            /* FILETIME */
@@ -178,14 +174,14 @@ typedef struct _KEY_CELL
   USHORT ClassSize;
 
   /* Name of key (not zero terminated) */
-  UCHAR  Name[0];
+  CHAR  Name[0];
 } __attribute__((packed)) KEY_CELL, *PKEY_CELL;
 
 
 /* KEY_CELL.Type constants */
 #define  REG_LINK_KEY_CELL_TYPE        0x10
-#define  REG_KEY_CELL_TYPE             0x20
-#define  REG_ROOT_KEY_CELL_TYPE        0x2c
+#define  REG_KEY_NAME_PACKED           0x20
+#define  REG_ROOT_KEY_CELL_TYPE        0x0c
 
 
 // hash record :
@@ -223,7 +219,7 @@ typedef struct _VALUE_CELL
   ULONG  DataType;
   USHORT  Flags;
   USHORT Unused1;
-  UCHAR  Name[0]; /* warning : not zero terminated */
+  CHAR  Name[0]; /* warning : not zero terminated */
 } __attribute__((packed)) VALUE_CELL, *PVALUE_CELL;
 
 /* VALUE_CELL.Flags constants */
@@ -237,7 +233,7 @@ typedef struct _VALUE_CELL
 typedef struct _DATA_CELL
 {
   LONG  CellSize;
-  UCHAR  Data[0];
+  CHAR  Data[0];
 } __attribute__((packed)) DATA_CELL, *PDATA_CELL;
 
 
@@ -301,15 +297,14 @@ CmiCreateDefaultHiveHeader (PHIVE_HEADER Header)
   Header->BlockId = REG_HIVE_ID;
   Header->UpdateCounter1 = 0;
   Header->UpdateCounter2 = 0;
-  Header->DateModified = 0ULL;
-  Header->Unused3 = 1;
-  Header->Unused4 = 3;
-  Header->Unused5 = 0;
-  Header->Unused6 = 1;
+  Header->DateModified = 0;
+  Header->MajorVersion = 1;
+  Header->MinorVersion = 3;
+  Header->Type = 0;
+  Header->Format = 1;
   Header->Unused7 = 1;
   Header->RootKeyOffset = -1;
   Header->BlockSize = REG_BLOCK_SIZE;
-  Header->Unused6 = 1;
   Header->Checksum = 0;
 }
 
@@ -326,22 +321,34 @@ CmiCreateDefaultBinCell (PHBIN BinCell)
 
 
 static VOID
-CmiCreateDefaultRootKeyCell (PKEY_CELL RootKeyCell, PCHAR KeyName)
+CmiCreateDefaultRootKeyCell (PKEY_CELL RootKeyCell, PCWSTR KeyName)
 {
-  PCHAR BaseKeyName;
+  PWCHAR BaseKeyName;
   ULONG NameSize;
   ULONG CellSize;
+  ULONG i;
+  BOOL Packable = TRUE;
 
   assert (RootKeyCell);
 
-  BaseKeyName = strrchr(KeyName, '\\') + 1;
-  NameSize = strlen(BaseKeyName);
-  CellSize = ROUND_UP(sizeof(KEY_CELL) + NameSize - 1, 16);
+  BaseKeyName = wcsrchr(KeyName, L'\\') + 1;
+  NameSize = wcslen(BaseKeyName);
+  for (i = 0; i < NameSize; i++)
+    {
+      if (KeyName[i] & 0xFF00)
+        {
+          Packable = FALSE;
+          NameSize *= sizeof(WCHAR);
+          break;
+        }
+    }
+
+  CellSize = ROUND_UP(sizeof(KEY_CELL) + NameSize, 16);
 
   memset (RootKeyCell, 0, CellSize);
   RootKeyCell->CellSize = -CellSize;
   RootKeyCell->Id = REG_KEY_CELL_ID;
-  RootKeyCell->Type = REG_ROOT_KEY_CELL_TYPE;
+  RootKeyCell->Flags = REG_ROOT_KEY_CELL_TYPE;
   RootKeyCell->LastWriteTime = 0ULL;
   RootKeyCell->ParentKeyOffset = 0;
   RootKeyCell->NumberOfSubKeys = 0;
@@ -352,12 +359,23 @@ CmiCreateDefaultRootKeyCell (PKEY_CELL RootKeyCell, PCHAR KeyName)
   RootKeyCell->ClassNameOffset = -1;
   RootKeyCell->NameSize = NameSize;
   RootKeyCell->ClassSize = 0;
-  memcpy (RootKeyCell->Name, BaseKeyName, NameSize);
+  if (Packable)
+    {
+      for(i = 0; i < NameSize; i++)
+        {
+          ((PCHAR)RootKeyCell->Name)[i] = BaseKeyName[i];
+        }
+      RootKeyCell->Flags |= REG_KEY_NAME_PACKED;
+    }
+  else
+    {
+      memcpy (RootKeyCell->Name, BaseKeyName, NameSize);
+    }
 }
 
 
 static PREGISTRY_HIVE
-CmiCreateHive (PCHAR KeyName)
+CmiCreateHive (PCWSTR KeyName)
 {
   PREGISTRY_HIVE Hive;
   PCELL_HEADER FreeCell;
@@ -697,9 +715,8 @@ CmiAddBin(PREGISTRY_HIVE RegistryHive,
   tmpBin->BinOffset = RegistryHive->FileSize - REG_BLOCK_SIZE;
   RegistryHive->FileSize += BinSize;
   tmpBin->BinSize = BinSize;
-  tmpBin->Unused1 = 0;
   tmpBin->DateModified = 0ULL;
-  tmpBin->Unused2 = 0;
+  tmpBin->MemAlloc = 0;
 
   /* Increase size of list of blocks */
   BlockList = MmAllocateMemory (sizeof(PHBIN) * (RegistryHive->BlockListSize + BlockCount));
@@ -840,7 +857,7 @@ CmiAllocateHashTableCell (PREGISTRY_HIVE Hive,
   ULONG NewHashSize;
   BOOL Status;
 
-  NewHashSize = sizeof(HASH_TABLE_CELL) + 
+  NewHashSize = sizeof(HASH_TABLE_CELL) +
                (SubKeyCount * sizeof(HASH_RECORD));
   Status = CmiAllocateCell (Hive,
                            NewHashSize,
@@ -889,7 +906,7 @@ CmiAddKeyToParentHashTable (PREGISTRY_HIVE Hive,
          HashBlock->Table[i].KeyOffset = NKBOffset;
          memcpy (&HashBlock->Table[i].HashValue,
                  NewKeyCell->Name,
-                 4);
+                 min(NewKeyCell->NameSize, sizeof(ULONG)));
          ParentKeyCell->NumberOfSubKeys++;
          return TRUE;
        }
@@ -928,13 +945,24 @@ static BOOL
 CmiAllocateValueCell(PREGISTRY_HIVE Hive,
                     PVALUE_CELL *ValueCell,
                     BLOCK_OFFSET *ValueCellOffset,
-                    PCHAR ValueName)
+                    PWCHAR ValueName)
 {
   PVALUE_CELL NewValueCell;
   ULONG NameSize;
   BOOL Status;
+  BOOLEAN Packable = TRUE;
+  ULONG i;
 
-  NameSize = (ValueName == NULL) ? 0 : strlen (ValueName);
+  NameSize = (ValueName == NULL) ? 0 : wcslen (ValueName);
+  for (i = 0; i < NameSize; i++)
+    {
+      if (ValueName[i] & 0xFF00)
+        {
+          NameSize *= sizeof(WCHAR);
+          Packable = FALSE;
+          break;
+        }
+    }
   Status = CmiAllocateCell (Hive,
                            sizeof(VALUE_CELL) + NameSize,
                            (PVOID*)(PVOID)&NewValueCell,
@@ -947,12 +975,23 @@ CmiAllocateValueCell(PREGISTRY_HIVE Hive,
 
   NewValueCell->Id = REG_VALUE_CELL_ID;
   NewValueCell->NameSize = NameSize;
+  NewValueCell->Flags = 0;
   if (NameSize > 0)
     {
-      memcpy (NewValueCell->Name,
-             ValueName,
-             NameSize);
-      NewValueCell->Flags = REG_VALUE_NAME_PACKED;
+      if (Packable)
+        {
+          for (i = 0; i < NameSize; i++)
+            {
+              ((PCHAR)NewValueCell->Name)[i] = (CHAR)ValueName[i];
+            }
+          NewValueCell->Flags |= REG_VALUE_NAME_PACKED;
+        }
+      else
+        {
+          memcpy (NewValueCell->Name,
+                 ValueName,
+                 NameSize);
+        }
     }
   NewValueCell->DataType = 0;
   NewValueCell->DataSize = 0;
@@ -992,19 +1031,6 @@ CmiAddValueToKeyValueList(PREGISTRY_HIVE Hive,
   return TRUE;
 }
 
-
-static VOID
-memexpand (PWCHAR Dst,
-          PCHAR Src,
-          ULONG Length)
-{
-  ULONG i;
-
-  for (i = 0; i < Length; i++)
-    Dst[i] = (WCHAR)Src[i];
-}
-
-
 static BOOL
 CmiExportValue (PREGISTRY_HIVE Hive,
                BLOCK_OFFSET KeyCellOffset,
@@ -1015,13 +1041,11 @@ CmiExportValue (PREGISTRY_HIVE Hive,
   BLOCK_OFFSET DataCellOffset;
   PVALUE_CELL ValueCell;
   PDATA_CELL DataCell;
-  ULONG SrcDataSize;
-  ULONG DstDataSize;
+  ULONG DataSize;
   ULONG DataType;
-  PUCHAR Data;
-  BOOL Expand = FALSE;
+  PCHAR Data;
 
-  DbgPrint((DPRINT_REGISTRY, "CmiExportValue('%s') called\n",
+  DbgPrint((DPRINT_REGISTRY, "CmiExportValue('%S') called\n",
           (Value == NULL) ? "<default>" : (PCHAR)Value->Name));
   DbgPrint((DPRINT_REGISTRY, "DataSize %lu\n",
           (Value == NULL) ? Key->DataSize : Value->DataSize));
@@ -1040,47 +1064,29 @@ CmiExportValue (PREGISTRY_HIVE Hive,
   if (Value == NULL)
     {
       DataType = Key->DataType;
-      SrcDataSize = Key->DataSize;
+      DataSize = Key->DataSize;
       Data = Key->Data;
     }
   else
     {
       DataType = Value->DataType;
-      SrcDataSize = Value->DataSize;
+      DataSize = Value->DataSize;
       Data = Value->Data;
     }
 
-  DstDataSize = SrcDataSize;
-  if (DataType == REG_SZ ||
-      DataType == REG_EXPAND_SZ ||
-      DataType == REG_MULTI_SZ)
+  if (DataSize <= sizeof(BLOCK_OFFSET))
     {
-      DstDataSize *= sizeof(WCHAR);
-      Expand = TRUE;
-    }
-
-  if (DstDataSize <= sizeof(BLOCK_OFFSET))
-    {
-      ValueCell->DataSize = DstDataSize | REG_DATA_IN_OFFSET;
+      ValueCell->DataSize = DataSize | REG_DATA_IN_OFFSET;
       ValueCell->DataType = DataType;
-      if (Expand)
-       {
-         memexpand ((PWCHAR)&ValueCell->DataOffset,
-                    (PCHAR)&Data,
-                    SrcDataSize);
-       }
-      else
-       {
-         memcpy (&ValueCell->DataOffset,
-                 &Data,
-                 SrcDataSize);
-       }
+      memcpy (&ValueCell->DataOffset,
+             Data,
+             DataSize);
     }
   else
     {
       /* Allocate data cell */
       if (!CmiAllocateCell (Hive,
-                           sizeof(CELL_HEADER) + DstDataSize,
+                           sizeof(CELL_HEADER) + DataSize,
                            (PVOID *)(PVOID)&DataCell,
                            &DataCellOffset))
        {
@@ -1088,30 +1094,12 @@ CmiExportValue (PREGISTRY_HIVE Hive,
        }
 
       ValueCell->DataOffset = DataCellOffset;
-      ValueCell->DataSize = DstDataSize;
+      ValueCell->DataSize = DataSize;
       ValueCell->DataType = DataType;
 
-      if (Expand)
-       {
-         if (SrcDataSize <= sizeof(BLOCK_OFFSET))
-           {
-             memexpand ((PWCHAR)DataCell->Data,
-                        (PCHAR)&Data,
-                        SrcDataSize);
-           }
-         else
-           {
-             memexpand ((PWCHAR)DataCell->Data,
-                        Data,
-                        SrcDataSize);
-           }
-       }
-      else
-       {
-         memcpy (DataCell->Data,
-                 Data,
-                 SrcDataSize);
-       }
+      memcpy (DataCell->Data,
+             Data,
+             DataSize);
     }
 
   return TRUE;
@@ -1132,15 +1120,29 @@ CmiExportSubKey (PREGISTRY_HIVE Hive,
   PLIST_ENTRY Entry;
   FRLDRHKEY SubKey;
   PVALUE Value;
+  BOOLEAN Packable = TRUE;
+  ULONG i;
+  ULONG NameSize;
 
-  DbgPrint((DPRINT_REGISTRY, "CmiExportSubKey('%s') called\n", Key->Name));
+  DbgPrint((DPRINT_REGISTRY, "CmiExportSubKey('%S') called\n", Key->Name));
 
   /* Don't export links */
   if (Key->DataType == REG_LINK)
     return TRUE;
 
+  NameSize = (Key->NameSize - sizeof(WCHAR)) / sizeof(WCHAR);
+  for (i = 0; i < NameSize; i++)
+    {
+      if (Key->Name[i] & 0xFF00)
+        {
+          Packable = FALSE;
+          NameSize *= sizeof(WCHAR);
+          break;
+        }
+    }
+          
   /* Allocate key cell */
-  KeyCellSize = sizeof(KEY_CELL) + Key->NameSize - 1;
+  KeyCellSize = sizeof(KEY_CELL) + NameSize;
   if (!CmiAllocateCell (Hive, KeyCellSize, (PVOID)&NewKeyCell, &NKBOffset))
     {
       DbgPrint((DPRINT_REGISTRY, "CmiAllocateCell() failed\n"));
@@ -1149,7 +1151,7 @@ CmiExportSubKey (PREGISTRY_HIVE Hive,
 
   /* Initialize key cell */
   NewKeyCell->Id = REG_KEY_CELL_ID;
-  NewKeyCell->Type = REG_KEY_CELL_TYPE;
+  NewKeyCell->Flags = 0;
   NewKeyCell->LastWriteTime = 0ULL;
   NewKeyCell->ParentKeyOffset = ParentKeyOffset;
   NewKeyCell->NumberOfSubKeys = 0;
@@ -1158,11 +1160,23 @@ CmiExportSubKey (PREGISTRY_HIVE Hive,
   NewKeyCell->ValueListOffset = -1;
   NewKeyCell->SecurityKeyOffset = -1;
   NewKeyCell->ClassNameOffset = -1;
-  NewKeyCell->NameSize = Key->NameSize - 1;
+  NewKeyCell->NameSize = NameSize;
   NewKeyCell->ClassSize = 0;
-  memcpy (NewKeyCell->Name,
-         Key->Name,
-         Key->NameSize - 1);
+  if (Packable)
+    {
+      for (i = 0; i < NameSize; i++)
+        {
+          ((PCHAR)NewKeyCell->Name)[i] = (CHAR)Key->Name[i];
+        }
+      NewKeyCell->Flags |= REG_KEY_NAME_PACKED;
+
+    }
+  else
+    {
+      memcpy (NewKeyCell->Name,
+             Key->Name,
+             NameSize);
+    }
 
   /* Add key cell to the parent key's hash table */
   if (!CmiAddKeyToParentHashTable (Hive,
@@ -1256,9 +1270,9 @@ CmiCalcHiveChecksum (PREGISTRY_HIVE Hive)
 }
 
 
-BOOL
+static BOOL
 CmiExportHive (PREGISTRY_HIVE Hive,
-              PCHAR KeyName)
+              PCWSTR KeyName)
 {
   PKEY_CELL KeyCell;
   FRLDRHKEY Key;
@@ -1268,7 +1282,7 @@ CmiExportHive (PREGISTRY_HIVE Hive,
   FRLDRHKEY SubKey;
   PVALUE Value;
 
-  DbgPrint((DPRINT_REGISTRY, "CmiExportHive(%x, '%s') called\n", Hive, KeyName));
+  DbgPrint((DPRINT_REGISTRY, "CmiExportHive(%x, '%S') called\n", Hive, KeyName));
 
   if (RegOpenKey (NULL, KeyName, &Key) != ERROR_SUCCESS)
     {
@@ -1358,12 +1372,9 @@ RegImportValue (PHBIN RootBin,
 {
   PDATA_CELL DataCell;
   PWCHAR wName;
-  PCHAR cName;
   LONG Error;
-  LONG DataSize;
-  PCHAR cBuffer;
-  PWCHAR wBuffer;
-  LONG i;
+  ULONG DataSize;
+  ULONG i;
 
   if (ValueCell->CellSize >= 0 || ValueCell->Id != REG_VALUE_CELL_ID)
     {
@@ -1373,37 +1384,38 @@ RegImportValue (PHBIN RootBin,
 
   if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
     {
-      cName = MmAllocateMemory (ValueCell->NameSize + 1);
-      memcpy (cName,
-             ValueCell->Name,
-             ValueCell->NameSize);
-      cName[ValueCell->NameSize] = 0;
+      wName = MmAllocateMemory ((ValueCell->NameSize + 1)*sizeof(WCHAR));
+      for (i = 0; i < ValueCell->NameSize; i++)
+        {
+          wName[i] = ((PCHAR)ValueCell->Name)[i];
+        }
+      wName[ValueCell->NameSize] = 0;
     }
   else
     {
-      wName = (PWCHAR)ValueCell->Name;
-      cName = MmAllocateMemory (ValueCell->NameSize / 2 + 1);
-      for (i = 0; i < ValueCell->NameSize / 2; i++)
-       cName[i] = (CHAR)wName[i];
-      cName[ValueCell->NameSize / 2] = 0;
+      wName = MmAllocateMemory (ValueCell->NameSize + sizeof(WCHAR));
+      memcpy (wName,
+             ValueCell->Name,
+             ValueCell->NameSize);
+      wName[ValueCell->NameSize / sizeof(WCHAR)] = 0;
     }
 
   DataSize = ValueCell->DataSize & REG_DATA_SIZE_MASK;
 
-  DbgPrint((DPRINT_REGISTRY, "ValueName: '%s'\n", cName));
+  DbgPrint((DPRINT_REGISTRY, "ValueName: '%S'\n", wName));
   DbgPrint((DPRINT_REGISTRY, "DataSize: %u\n", DataSize));
 
   if (DataSize <= sizeof(BLOCK_OFFSET) && (ValueCell->DataSize & REG_DATA_IN_OFFSET))
     {
       Error = RegSetValue(Key,
-                         cName,
+                         wName,
                          ValueCell->DataType,
-                         (PUCHAR)&ValueCell->DataOffset,
+                         (PCHAR)&ValueCell->DataOffset,
                          DataSize);
       if (Error != ERROR_SUCCESS)
        {
          DbgPrint((DPRINT_REGISTRY, "RegSetValue() failed!\n"));
-         MmFreeMemory (cName);
+         MmFreeMemory (wName);
          return FALSE;
        }
     }
@@ -1415,44 +1427,25 @@ RegImportValue (PHBIN RootBin,
       if (DataCell->CellSize >= 0)
        {
          DbgPrint((DPRINT_REGISTRY, "Invalid data cell size!\n"));
-         MmFreeMemory (cName);
+         MmFreeMemory (wName);
          return FALSE;
        }
 
-      if (ValueCell->DataType == REG_SZ ||
-         ValueCell->DataType == REG_EXPAND_SZ ||
-         ValueCell->DataType == REG_MULTI_SZ)
-       {
-         wBuffer = (PWCHAR)DataCell->Data;
-         cBuffer = MmAllocateMemory(DataSize/2);
-         for (i = 0; i < DataSize / 2; i++)
-           cBuffer[i] = (CHAR)wBuffer[i];
-
-         Error = RegSetValue (Key,
-                              cName,
-                              ValueCell->DataType,
-                              cBuffer,
-                              DataSize/2);
-
-         MmFreeMemory(cBuffer);
-       }
-      else
-       {
-         Error = RegSetValue (Key,
-                              cName,
-                              ValueCell->DataType,
-                              (PUCHAR)DataCell->Data,
-                              DataSize);
-       }
+      Error = RegSetValue (Key,
+                          wName,
+                          ValueCell->DataType,
+                          DataCell->Data,
+                          DataSize);
+       
       if (Error != ERROR_SUCCESS)
        {
          DbgPrint((DPRINT_REGISTRY, "RegSetValue() failed!\n"));
-         MmFreeMemory (cName);
+         MmFreeMemory (wName);
          return FALSE;
        }
     }
 
-  MmFreeMemory (cName);
+  MmFreeMemory (wName);
 
   return TRUE;
 }
@@ -1467,7 +1460,7 @@ RegImportSubKey(PHBIN RootBin,
   PKEY_CELL SubKeyCell;
   PVALUE_LIST_CELL ValueListCell;
   PVALUE_CELL ValueCell = NULL;
-  PCHAR cName;
+  PWCHAR wName;
   FRLDRHKEY SubKey;
   LONG Error;
   ULONG i;
@@ -1482,20 +1475,31 @@ RegImportSubKey(PHBIN RootBin,
       return FALSE;
     }
 
-  /* FIXME: implement packed key names */
-  cName = MmAllocateMemory (KeyCell->NameSize + 1);
-  memcpy (cName,
-         KeyCell->Name,
-         KeyCell->NameSize);
-  cName[KeyCell->NameSize] = 0;
+  if (KeyCell->Flags & REG_KEY_NAME_PACKED)
+    {
+      wName = MmAllocateMemory ((KeyCell->NameSize + 1) * sizeof(WCHAR));
+      for (i = 0; i < KeyCell->NameSize; i++)
+        {
+          wName[i] = ((PCHAR)KeyCell->Name)[i];
+        }
+      wName[KeyCell->NameSize] = 0;
+    }
+  else
+    {
+      wName = MmAllocateMemory (KeyCell->NameSize + sizeof(WCHAR));
+      memcpy (wName,
+             KeyCell->Name,
+             KeyCell->NameSize);
+      wName[KeyCell->NameSize/sizeof(WCHAR)] = 0;
+    }
 
-  DbgPrint((DPRINT_REGISTRY, "KeyName: '%s'\n", cName));
+  DbgPrint((DPRINT_REGISTRY, "KeyName: '%S'\n", wName));
 
   /* Create new sub key */
   Error = RegCreateKey (ParentKey,
-                       cName,
+                       wName,
                        &SubKey);
-  MmFreeMemory (cName);
+  MmFreeMemory (wName);
   if (Error != ERROR_SUCCESS)
     {
       DbgPrint((DPRINT_REGISTRY, "RegCreateKey() failed!\n"));
@@ -1592,7 +1596,7 @@ RegImportBinaryHive(PCHAR ChunkBase,
 
   /* Open 'System' key */
   Error = RegOpenKey(NULL,
-                    "\\Registry\\Machine\\SYSTEM",
+                    L"\\Registry\\Machine\\SYSTEM",
                     &SystemKey);
   if (Error != ERROR_SUCCESS)
     {
@@ -1624,7 +1628,7 @@ RegImportBinaryHive(PCHAR ChunkBase,
 
 
 BOOL
-RegExportBinaryHive(PCHAR KeyName,
+RegExportBinaryHive(PCWSTR KeyName,
                    PCHAR ChunkBase,
                    ULONG* ChunkSize)
 {