*/
#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" */
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 */
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;
/* 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;
/* Key cell identifier "kn" (0x6b6e) */
USHORT Id;
- /* ? */
- USHORT Type;
+ /* Flags */
+ USHORT Flags;
/* Time of last flush */
ULONGLONG LastWriteTime; /* FILETIME */
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 :
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 */
typedef struct _DATA_CELL
{
LONG CellSize;
- UCHAR Data[0];
+ CHAR Data[0];
} __attribute__((packed)) DATA_CELL, *PDATA_CELL;
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;
}
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;
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;
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));
ULONG NewHashSize;
BOOL Status;
- NewHashSize = sizeof(HASH_TABLE_CELL) +
+ NewHashSize = sizeof(HASH_TABLE_CELL) +
(SubKeyCount * sizeof(HASH_RECORD));
Status = CmiAllocateCell (Hive,
NewHashSize,
HashBlock->Table[i].KeyOffset = NKBOffset;
memcpy (&HashBlock->Table[i].HashValue,
NewKeyCell->Name,
- 4);
+ min(NewKeyCell->NameSize, sizeof(ULONG)));
ParentKeyCell->NumberOfSubKeys++;
return TRUE;
}
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,
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;
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,
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));
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))
{
}
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;
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"));
/* 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;
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,
}
-BOOL
+static BOOL
CmiExportHive (PREGISTRY_HIVE Hive,
- PCHAR KeyName)
+ PCWSTR KeyName)
{
PKEY_CELL KeyCell;
FRLDRHKEY Key;
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)
{
{
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)
{
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;
}
}
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;
}
PKEY_CELL SubKeyCell;
PVALUE_LIST_CELL ValueListCell;
PVALUE_CELL ValueCell = NULL;
- PCHAR cName;
+ PWCHAR wName;
FRLDRHKEY SubKey;
LONG Error;
ULONG i;
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"));
/* Open 'System' key */
Error = RegOpenKey(NULL,
- "\\Registry\\Machine\\SYSTEM",
+ L"\\Registry\\Machine\\SYSTEM",
&SystemKey);
if (Error != ERROR_SUCCESS)
{
BOOL
-RegExportBinaryHive(PCHAR KeyName,
+RegExportBinaryHive(PCWSTR KeyName,
PCHAR ChunkBase,
ULONG* ChunkSize)
{