* UPDATE HISTORY:
*/
+#ifdef WIN32_REGDBG
+#include "cm_win32.h"
+#else
#include <ddk/ntddk.h>
#include <ddk/ntifs.h>
#include <roscfg.h>
#include <internal/debug.h>
#include "cm.h"
+#endif
-
+#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
BOOLEAN CmiDoVerify = FALSE;
+/* FUNCTIONS ****************************************************************/
+
VOID
CmiCreateDefaultHiveHeader(PHIVE_HEADER Header)
{
{
assert(RootKeyCell);
RtlZeroMemory(RootKeyCell, sizeof(KEY_CELL));
+#ifdef WIN32_REGDBG
+ RootKeyCell->CellSize = -(LONG)sizeof(KEY_CELL);
+#else
RootKeyCell->CellSize = -sizeof(KEY_CELL);
+#endif
RootKeyCell->Id = REG_KEY_CELL_ID;
RootKeyCell->Type = REG_ROOT_KEY_CELL_TYPE;
ZwQuerySystemTime((PTIME) &RootKeyCell->LastWriteTime);
PHBIN BinCell;
PCHAR tBuf;
ULONG i;
-
+
tBuf = (PCHAR) ExAllocatePool(NonPagedPool, REG_BLOCK_SIZE);
if (tBuf == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
FileOffset.u.LowPart = (2 + i) * REG_BLOCK_SIZE;
Status = ZwWriteFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- tBuf,
- REG_BLOCK_SIZE,
- &FileOffset,
- NULL);
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ tBuf,
+ REG_BLOCK_SIZE,
+ &FileOffset,
+ NULL);
assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status));
if (!NT_SUCCESS(Status))
{
PKEY_CELL RootKeyCell;
NTSTATUS Status;
PHBIN BinCell;
- PCHAR tBuf;
-
- tBuf = (PCHAR) ExAllocatePool(NonPagedPool, 2 * REG_BLOCK_SIZE);
- if (tBuf == NULL)
+ PCHAR Buffer;
+
+ Buffer = (PCHAR) ExAllocatePool(NonPagedPool, 2 * REG_BLOCK_SIZE);
+ if (Buffer == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
-
- HiveHeader = (PHIVE_HEADER) tBuf;
- BinCell = (PHBIN) ((ULONG_PTR) tBuf + REG_BLOCK_SIZE);
- RootKeyCell = (PKEY_CELL) ((ULONG_PTR) tBuf + REG_BLOCK_SIZE + REG_HBIN_DATA_OFFSET);
- FreeCell = (PCELL_HEADER) ((ULONG_PTR) tBuf + REG_BLOCK_SIZE + REG_HBIN_DATA_OFFSET + sizeof(KEY_CELL));
+
+ HiveHeader = (PHIVE_HEADER)Buffer;
+ BinCell = (PHBIN)((ULONG_PTR)Buffer + REG_BLOCK_SIZE);
+ RootKeyCell = (PKEY_CELL)((ULONG_PTR)Buffer + REG_BLOCK_SIZE + REG_HBIN_DATA_OFFSET);
+ FreeCell = (PCELL_HEADER)((ULONG_PTR)Buffer + REG_BLOCK_SIZE + REG_HBIN_DATA_OFFSET + sizeof(KEY_CELL));
CmiCreateDefaultHiveHeader(HiveHeader);
CmiCreateDefaultBinCell(BinCell);
CmiCreateDefaultRootKeyCell(RootKeyCell);
- // First block
+ /* First block */
BinCell->BlockOffset = 0;
- // Offset to root key block
+ /* Offset to root key block */
HiveHeader->RootKeyCell = REG_HBIN_DATA_OFFSET;
- // The rest of the block is free
+ /* The rest of the block is free */
FreeCell->CellSize = REG_BLOCK_SIZE - (REG_HBIN_DATA_OFFSET + sizeof(KEY_CELL));
Status = ZwWriteFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- tBuf,
- 2 * REG_BLOCK_SIZE,
- 0,
- NULL);
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ Buffer,
+ 2 * REG_BLOCK_SIZE,
+ 0,
+ NULL);
- ExFreePool(tBuf);
+ ExFreePool(Buffer);
assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status));
#if 1
if (NT_SUCCESS(Status))
{
- CmiPopulateHive(FileHandle);
+ CmiPopulateHive(FileHandle);
}
#endif
NTSTATUS
CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive,
- PWSTR Filename,
- BOOLEAN CreateNew)
+ PWSTR Filename,
+ BOOLEAN CreateNew)
{
OBJECT_ATTRIBUTES ObjectAttributes;
FILE_STANDARD_INFORMATION fsi;
ULONG CreateDisposition;
IO_STATUS_BLOCK IoSB;
HANDLE FileHandle;
- DWORD FreeOffset;
+ ULONG FreeOffset;
NTSTATUS Status;
- //BOOLEAN Success;
PHBIN tmpBin;
ULONG i, j;
+ ULONG BitmapSize;
+ PULONG BitmapBuffer;
+
+ DPRINT1("CmiInitPermanentRegistryHive(%p, %S, %d) - Entered.\n", RegistryHive, Filename, CreateNew);
/* Duplicate Filename */
Status = RtlCreateUnicodeString(&RegistryHive->Filename, Filename);
if (!NT_SUCCESS(Status))
- return Status;
+ {
+ DPRINT1("CmiInitPermanentRegistryHive() - Failed 1.\n");
+ return Status;
+ }
InitializeObjectAttributes(&ObjectAttributes,
&RegistryHive->Filename,
NULL,
NULL);
- if (CreateNew)
+ /*
+ * Note:
+ * This is a workaround to prevent a BSOD because of missing registry hives.
+ * The workaround is only useful for developers. An implementation for the
+ * ordinary user must bail out on missing registry hives because they are
+ * essential to booting and configuring the OS.
+ */
+#if 0
+ if (CreateNew == TRUE)
CreateDisposition = FILE_OPEN_IF;
else
CreateDisposition = FILE_OPEN;
+#endif
+ CreateDisposition = FILE_OPEN_IF;
Status = NtCreateFile(&FileHandle,
- FILE_ALL_ACCESS,
- &ObjectAttributes,
- &IoSB,
- NULL,
- FILE_ATTRIBUTE_NORMAL,
- 0,
- CreateDisposition,
- FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
- NULL,
- 0);
-
- if ((CreateNew) && (IoSB.Information == FILE_CREATED))
+ FILE_ALL_ACCESS,
+ &ObjectAttributes,
+ &IoSB,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ CreateDisposition,
+ FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
{
- Status = CmiCreateNewRegFile(FileHandle);
+ RtlFreeUnicodeString(&RegistryHive->Filename);
+ DPRINT1("NtCreateFile() failed (Status %lx)\n", Status);
+ return(Status);
}
- if (!NT_SUCCESS(Status))
+ /* Note: Another workaround! See the note above! */
+#if 0
+ if ((CreateNew) && (IoSB.Information == FILE_CREATED))
+#endif
+ if (IoSB.Information != FILE_OPENED)
{
- RtlFreeUnicodeString(&RegistryHive->Filename);
- return Status;
+ Status = CmiCreateNewRegFile(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("CmiCreateNewRegFile() failed (Status %lx)\n", Status);
+ RtlFreeUnicodeString(&RegistryHive->Filename);
+ return(Status);
+ }
}
Status = ObReferenceObjectByHandle(FileHandle,
- FILE_ALL_ACCESS,
- IoFileObjectType,
- UserMode,
- (PVOID*) &RegistryHive->FileObject,
- NULL);
+ FILE_ALL_ACCESS,
+ IoFileObjectType,
+ UserMode,
+ (PVOID*)&RegistryHive->FileObject,
+ NULL);
assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status));
if (!NT_SUCCESS(Status))
{
- ZwClose(FileHandle);
+ NtClose(FileHandle);
RtlFreeUnicodeString(&RegistryHive->Filename);
+ DPRINT1("CmiInitPermanentRegistryHive() - ObReferenceObjectByHandle Failed with status %x.\n", Status);
return Status;
}
+ /* Read hive header */
FileOffset.u.HighPart = 0;
FileOffset.u.LowPart = 0;
- Status = ZwReadFile(FileHandle,
- 0,
+ DPRINT(" Attempting to ZwReadFile(%d) for %d bytes into %p\n", FileHandle, sizeof(HIVE_HEADER), RegistryHive->HiveHeader);
+ Status = NtReadFile(FileHandle,
0,
0,
0,
+ &IoSB,
RegistryHive->HiveHeader,
sizeof(HIVE_HEADER),
&FileOffset,
0);
-
assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status));
-
if (!NT_SUCCESS(Status))
{
ObDereferenceObject(RegistryHive->FileObject);
RtlFreeUnicodeString(&RegistryHive->Filename);
+ DPRINT("CmiInitPermanentRegistryHive() - Failed 4.\n");
return Status;
}
- Status = ZwQueryInformationFile(FileHandle,
- &IoSB,
- &fsi,
- sizeof(fsi),
- FileStandardInformation);
+ Status = NtQueryInformationFile(FileHandle,
+ &IoSB,
+ &fsi,
+ sizeof(fsi),
+ FileStandardInformation);
assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status));
{
ObDereferenceObject(RegistryHive->FileObject);
RtlFreeUnicodeString(&RegistryHive->Filename);
+ DPRINT("CmiInitPermanentRegistryHive() - Failed 5.\n");
return Status;
}
+
#if 0
/* We have a reference to the file object so we don't need the handle anymore */
ZwClose(FileHandle);
#endif
RegistryHive->FileSize = fsi.EndOfFile.u.LowPart;
+#ifdef WIN32_REGDBG
+// assert(RegistryHive->FileSize);
+ if (RegistryHive->FileSize)
+ {
+ RegistryHive->BlockListSize = (RegistryHive->FileSize / 4096) - 1;
+ }
+ else
+ {
+ ObDereferenceObject(RegistryHive->FileObject);
+ RtlFreeUnicodeString(&RegistryHive->Filename);
+ DPRINT("CmiInitPermanentRegistryHive() - Failed, zero length hive file.\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+#else
RegistryHive->BlockListSize = (RegistryHive->FileSize / 4096) - 1;
+#endif
DPRINT("Space needed for block list describing hive: 0x%x\n",
sizeof(PHBIN *) * RegistryHive->BlockListSize);
ExFreePool(RegistryHive->BlockList);
ObDereferenceObject(RegistryHive->FileObject);
RtlFreeUnicodeString(&RegistryHive->Filename);
+ DPRINT("CmiInitPermanentRegistryHive() - Failed 6.\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
ExFreePool(RegistryHive->BlockList);
ObDereferenceObject(RegistryHive->FileObject);
RtlFreeUnicodeString(&RegistryHive->Filename);
+ DPRINT("CmiInitPermanentRegistryHive() - Failed 7.\n");
return Status;
}
RegistryHive->BlockList[0] = ExAllocatePool(PagedPool,
RegistryHive->FileSize - 4096);
+#ifdef WIN32_REGDBG
+ RtlZeroMemory(RegistryHive->BlockList[0], RegistryHive->FileSize - 4096);
+#endif
if (RegistryHive->BlockList[0] == NULL)
{
ExFreePool(RegistryHive->BlockList);
ObDereferenceObject(RegistryHive->FileObject);
RtlFreeUnicodeString(&RegistryHive->Filename);
+ DPRINT("CmiInitPermanentRegistryHive() - Failed 8.\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
FileOffset.u.HighPart = 0;
FileOffset.u.LowPart = 4096;
- Status = ZwReadFile(FileHandle,
- 0,
- 0,
- 0,
- 0,
- (PVOID) RegistryHive->BlockList[0],
- RegistryHive->FileSize - 4096,
- &FileOffset,
- 0);
+ DPRINT(" Attempting to ZwReadFile(%d) for %d bytes into %p\n", FileHandle, RegistryHive->FileSize - 4096, (PVOID)RegistryHive->BlockList[0]);
+ Status = NtReadFile(FileHandle,
+ 0,
+ 0,
+ 0,
+ &IoSB,
+ (PVOID) RegistryHive->BlockList[0],
+ RegistryHive->FileSize - 4096,
+ &FileOffset,
+ 0);
assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status));
+ NtClose(FileHandle);
#endif
RegistryHive->FreeListSize = 0;
if (tmpBin->BlockId != REG_BIN_ID)
{
DPRINT("Bad BlockId %x, offset %x\n", tmpBin->BlockId, BlockOffset);
- KeBugCheck(0);
+ //KeBugCheck(0);
+ return STATUS_INSUFFICIENT_RESOURCES;
}
assertmsg((tmpBin->BlockSize % 4096) == 0, ("BlockSize (0x%.08x) must be multiplum of 4K\n", tmpBin->BlockSize));
BlockOffset += tmpBin->BlockSize;
}
- return STATUS_SUCCESS;
+ /* Create block bitmap and clear all bits */
+
+ /* Calculate bitmap size in bytes (always a multiple of 32 bits) */
+ BitmapSize = ROUND_UP(RegistryHive->BlockListSize, sizeof(ULONG) * 8) / 8;
+ DPRINT1("RegistryHive->BlockListSize: %lu\n", RegistryHive->BlockListSize);
+ DPRINT1("BitmapSize: %lu Bytes %lu Bits\n", BitmapSize, BitmapSize * 8);
+ BitmapBuffer = (PULONG)ExAllocatePool(PagedPool,
+ BitmapSize);
+ RtlInitializeBitMap(&RegistryHive->DirtyBitMap,
+ BitmapBuffer,
+ BitmapSize * 8);
+ RtlClearAllBits(&RegistryHive->DirtyBitMap);
+ RegistryHive->HiveDirty = FALSE;
+
+ DPRINT1("CmiInitPermanentRegistryHive(%p, %S, %d) - Finished.\n", RegistryHive, Filename, CreateNew);
+
+ return(STATUS_SUCCESS);
}
Hive = ExAllocatePool(NonPagedPool, sizeof(REGISTRY_HIVE));
if (Hive == NULL)
- return STATUS_INSUFFICIENT_RESOURCES;
+ return(STATUS_INSUFFICIENT_RESOURCES);
DPRINT("Hive %x\n", Hive);
if (Hive->HiveHeader == NULL)
{
ExFreePool(Hive);
- return STATUS_INSUFFICIENT_RESOURCES;
+ return(STATUS_INSUFFICIENT_RESOURCES);
}
if (Filename != NULL)
return(Status);
}
- KeInitializeSemaphore(&Hive->RegSem, 1, 1);
+ ExInitializeResourceLite(&Hive->HiveResource);
+
+ /* Acquire hive list lock exclusively */
+ ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE);
+
+ /* Add the new hive to the hive list */
+ InsertHeadList(&CmiHiveListHead, &Hive->HiveList);
+
+ /* Release hive list lock */
+ ExReleaseResourceLite(&CmiHiveListLock);
+
VERIFY_REGISTRY_HIVE(Hive);
*RegistryHive = Hive;
+ DPRINT("CmiCreateRegistryHive(Filename %S) - Finished.\n", Filename);
+
+ return(STATUS_SUCCESS);
+}
+
+
+NTSTATUS
+CmiRemoveRegistryHive(PREGISTRY_HIVE RegistryHive)
+{
+ /* Acquire hive list lock exclusively */
+ ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE);
+
+ /* Remove hive from hive list */
+ RemoveEntryList(&RegistryHive->HiveList);
+
+ /* Release hive list lock */
+ ExReleaseResourceLite(&CmiHiveListLock);
+
+
+ /* FIXME: Remove attached keys and values */
+
+
+ /* Release hive header */
+ ExFreePool(RegistryHive->HiveHeader);
+
+ /* Release hive */
+ ExFreePool(RegistryHive);
+
+ return(STATUS_SUCCESS);
+}
+
+
+NTSTATUS
+CmiFlushRegistryHive(PREGISTRY_HIVE RegistryHive)
+{
+ ULONG BlockIndex;
+ ULONG BlockOffset;
+ PVOID BlockPtr;
+ LARGE_INTEGER FileOffset;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+
+
+
+
+ DPRINT("CmiFlushRegistryHive() called\n");
+
+ if (RegistryHive->HiveDirty == FALSE)
+ {
+ return(STATUS_SUCCESS);
+ }
+
+ DPRINT1("Hive '%wZ' is dirty\n", &RegistryHive->Filename);
+
+
+ /* Open hive for writing */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &RegistryHive->Filename,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtCreateFile(&FileHandle,
+ FILE_ALL_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_OPEN,
+ FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtCreateFile() failed (Status %lx)\n", Status);
+ return(Status);
+ }
+
+
+
+ BlockIndex = 0;
+ while (TRUE)
+ {
+ BlockIndex = RtlFindSetBitsAndClear(&RegistryHive->DirtyBitMap,
+ 1,
+ BlockIndex);
+ if (BlockIndex == (ULONG)-1)
+ {
+ DPRINT("No more set bits\n");
+ break;
+ }
+
+ DPRINT1("Block %lu is dirty\n", BlockIndex);
+
+ BlockOffset = RegistryHive->BlockList[BlockIndex]->BlockOffset;
+ DPRINT1("Block offset %lx\n", BlockOffset);
+
+ BlockPtr = RegistryHive->BlockList[BlockIndex] + ((BlockIndex * 4096) - BlockOffset);
+ DPRINT1("BlockPtr %p\n", BlockPtr);
+
+ FileOffset.QuadPart = (ULONGLONG)(BlockIndex + 1) * 4096ULL;
+ DPRINT1("File offset %I64x\n", FileOffset.QuadPart);
+
+
+ /* Write hive block */
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ BlockPtr,
+ REG_BLOCK_SIZE,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ return(Status);
+ }
+
+
+ }
+
+ NtClose(FileHandle);
+
+
+ /* Clear dirty flag */
+ RegistryHive->HiveDirty = FALSE;
+
+ DPRINT("CmiFlushRegistryHive() done\n");
+
return(STATUS_SUCCESS);
}
{
PVALUE_LIST_CELL ValueListCell;
PVALUE_CELL CurValueCell;
- ULONG MaxValueData;
+ LONG MaxValueData;
ULONG i;
VERIFY_KEY_CELL(KeyCell);
VERIFY_KEY_CELL(KeyCell);
- DPRINT("Scanning for sub key %s\n", KeyName);
+ //DPRINT("Scanning for sub key %s\n", KeyName);
assert(RegistryHive);
if (Attributes & OBJ_CASE_INSENSITIVE)
{
if ((HashBlock->Table[i].KeyOffset != 0) &&
- (HashBlock->Table[i].KeyOffset != -1) &&
+ (HashBlock->Table[i].KeyOffset != (ULONG_PTR)-1) &&
(_strnicmp(KeyName, (PCHAR) &HashBlock->Table[i].HashValue, 4) == 0))
{
CurSubKeyCell = CmiGetBlock(RegistryHive,
else
{
if (HashBlock->Table[i].KeyOffset != 0 &&
- HashBlock->Table[i].KeyOffset != -1 &&
+ HashBlock->Table[i].KeyOffset != (ULONG_PTR) -1 &&
!strncmp(KeyName, (PCHAR) &HashBlock->Table[i].HashValue, 4))
{
CurSubKeyCell = CmiGetBlock(RegistryHive,
NTSTATUS
CmiAddSubKey(PREGISTRY_HIVE RegistryHive,
- PKEY_OBJECT Parent,
- PKEY_OBJECT SubKey,
- PWSTR NewSubKeyName,
- USHORT NewSubKeyNameSize,
- ULONG TitleIndex,
- PUNICODE_STRING Class,
- ULONG CreateOptions)
+ PKEY_OBJECT Parent,
+ PKEY_OBJECT SubKey,
+ PWSTR NewSubKeyName,
+ USHORT NewSubKeyNameSize,
+ ULONG TitleIndex,
+ PUNICODE_STRING Class,
+ ULONG CreateOptions)
{
PHASH_TABLE_CELL NewHashBlock;
PHASH_TABLE_CELL HashBlock;
}
else
{
- NewKeyCell->Id = REG_KEY_CELL_ID;
- NewKeyCell->Type = REG_KEY_CELL_TYPE;
- ZwQuerySystemTime((PTIME) &NewKeyCell->LastWriteTime);
- NewKeyCell->ParentKeyOffset = -1;
- NewKeyCell->NumberOfSubKeys = 0;
- NewKeyCell->HashTableOffset = -1;
- NewKeyCell->NumberOfValues = 0;
- NewKeyCell->ValuesOffset = -1;
- NewKeyCell->SecurityKeyOffset = -1;
- NewKeyCell->NameSize = NameSize;
- wcstombs(NewKeyCell->Name, NewSubKeyName, NameSize);
- NewKeyCell->ClassNameOffset = -1;
+ NewKeyCell->Id = REG_KEY_CELL_ID;
+ NewKeyCell->Type = REG_KEY_CELL_TYPE;
+ ZwQuerySystemTime((PTIME) &NewKeyCell->LastWriteTime);
+ NewKeyCell->ParentKeyOffset = -1;
+ NewKeyCell->NumberOfSubKeys = 0;
+ NewKeyCell->HashTableOffset = -1;
+ NewKeyCell->NumberOfValues = 0;
+ NewKeyCell->ValuesOffset = -1;
+ NewKeyCell->SecurityKeyOffset = -1;
+ NewKeyCell->NameSize = NameSize;
+ wcstombs(NewKeyCell->Name, NewSubKeyName, NameSize);
+ NewKeyCell->ClassNameOffset = -1;
VERIFY_KEY_CELL(NewKeyCell);
- if (Class)
- {
- PDATA_CELL pClass;
-
- NewKeyCell->ClassSize = Class->Length + sizeof(WCHAR);
- Status = CmiAllocateBlock(RegistryHive,
- (PVOID) &pClass,
- NewKeyCell->ClassSize,
- &NewKeyCell->ClassNameOffset);
- wcsncpy((PWSTR) pClass->Data, Class->Buffer, Class->Length);
- ((PWSTR) (pClass->Data))[Class->Length] = 0;
- }
+ if (Class)
+ {
+ PDATA_CELL pClass;
+
+ NewKeyCell->ClassSize = Class->Length + sizeof(WCHAR);
+ Status = CmiAllocateBlock(RegistryHive,
+ (PVOID) &pClass,
+ NewKeyCell->ClassSize,
+ &NewKeyCell->ClassNameOffset);
+ wcsncpy((PWSTR) pClass->Data, Class->Buffer, Class->Length);
+ ((PWSTR) (pClass->Data))[Class->Length] = 0;
+ }
}
if (!NT_SUCCESS(Status))
/* Don't modify hash table if key is volatile and parent is not */
if (IsVolatileHive(RegistryHive) && (!IsVolatileHive(Parent->RegistryHive)))
- {
- return Status;
- }
+ {
+ return(Status);
+ }
- if (KeyCell->HashTableOffset == -1)
+ if (KeyCell->HashTableOffset == (ULONG_PTR) -1)
{
Status = CmiAllocateHashTableBlock(RegistryHive,
- &HashBlock,
- &KeyCell->HashTableOffset,
- REG_INIT_HASH_TABLE_SIZE);
-
+ &HashBlock,
+ &KeyCell->HashTableOffset,
+ REG_INIT_HASH_TABLE_SIZE);
if (!NT_SUCCESS(Status))
- {
- return Status;
- }
+ {
+ return(Status);
+ }
}
else
{
HashBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL);
if (((KeyCell->NumberOfSubKeys + 1) >= HashBlock->HashTableSize))
- {
- BLOCK_OFFSET HTOffset;
-
- /* Reallocate the hash table block */
- Status = CmiAllocateHashTableBlock(RegistryHive,
- &NewHashBlock,
- &HTOffset,
- HashBlock->HashTableSize +
- REG_EXTEND_HASH_TABLE_SIZE);
-
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
+ {
+ BLOCK_OFFSET HTOffset;
+
+ /* Reallocate the hash table block */
+ Status = CmiAllocateHashTableBlock(RegistryHive,
+ &NewHashBlock,
+ &HTOffset,
+ HashBlock->HashTableSize +
+ REG_EXTEND_HASH_TABLE_SIZE);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
- RtlZeroMemory(&NewHashBlock->Table[0],
- sizeof(NewHashBlock->Table[0]) * NewHashBlock->HashTableSize);
- RtlCopyMemory(&NewHashBlock->Table[0],
- &HashBlock->Table[0],
- sizeof(NewHashBlock->Table[0]) * HashBlock->HashTableSize);
- CmiDestroyBlock(RegistryHive, HashBlock, KeyCell->HashTableOffset);
- KeyCell->HashTableOffset = HTOffset;
- HashBlock = NewHashBlock;
- }
+ RtlZeroMemory(&NewHashBlock->Table[0],
+ sizeof(NewHashBlock->Table[0]) * NewHashBlock->HashTableSize);
+ RtlCopyMemory(&NewHashBlock->Table[0],
+ &HashBlock->Table[0],
+ sizeof(NewHashBlock->Table[0]) * HashBlock->HashTableSize);
+ CmiDestroyBlock(RegistryHive,
+ HashBlock,
+ KeyCell->HashTableOffset);
+ KeyCell->HashTableOffset = HTOffset;
+ HashBlock = NewHashBlock;
+ }
}
- Status = CmiAddKeyToHashTable(RegistryHive, HashBlock, NewKeyCell, NKBOffset);
+ Status = CmiAddKeyToHashTable(RegistryHive,
+ HashBlock,
+ NewKeyCell,
+ NKBOffset);
if (NT_SUCCESS(Status))
{
KeyCell->NumberOfSubKeys++;
}
-
- return Status;
+
+ return(Status);
+}
+
+
+NTSTATUS
+CmiRemoveSubKey(PREGISTRY_HIVE RegistryHive,
+ PKEY_OBJECT ParentKey,
+ PKEY_OBJECT SubKey)
+{
+ PHASH_TABLE_CELL HashBlock;
+
+ DPRINT1("CmiRemoveSubKey() called\n");
+
+ /* Remove the key from the parent key's hash block */
+ if (ParentKey->KeyCell->HashTableOffset != -1)
+ {
+ DPRINT1("ParentKey HashTableOffset %lx\n", ParentKey->KeyCell->HashTableOffset)
+ HashBlock = CmiGetBlock(RegistryHive,
+ ParentKey->KeyCell->HashTableOffset,
+ NULL);
+ DPRINT1("ParentKey HashBlock %p\n", HashBlock)
+ if (HashBlock != NULL)
+ {
+ CmiRemoveKeyFromHashTable(RegistryHive,
+ HashBlock,
+ SubKey->BlockOffset);
+ CmiMarkBlockDirty(RegistryHive,
+ ParentKey->KeyCell->HashTableOffset);
+ }
+ }
+
+ /* Remove the key's hash block */
+ if (SubKey->KeyCell->HashTableOffset != -1)
+ {
+ DPRINT1("SubKey HashTableOffset %lx\n", SubKey->KeyCell->HashTableOffset)
+ HashBlock = CmiGetBlock(RegistryHive,
+ SubKey->KeyCell->HashTableOffset,
+ NULL);
+ DPRINT1("SubKey HashBlock %p\n", HashBlock)
+ if (HashBlock != NULL)
+ {
+ CmiDestroyBlock(RegistryHive,
+ HashBlock,
+ SubKey->KeyCell->HashTableOffset);
+ SubKey->KeyCell->HashTableOffset = -1;
+ }
+ }
+
+ /* Decrement the number of the parent key's sub keys */
+ if (ParentKey != NULL)
+ {
+ DPRINT1("ParentKey %p\n", ParentKey)
+ ParentKey->KeyCell->NumberOfSubKeys--;
+ NtQuerySystemTime((PTIME)&ParentKey->KeyCell->LastWriteTime);
+ CmiMarkBlockDirty(RegistryHive,
+ ParentKey->BlockOffset);
+
+ /* Remove the parent key's hash table */
+ if (ParentKey->KeyCell->NumberOfSubKeys == 0)
+ {
+ DPRINT1("FIXME: Remove parent key hash table\n")
+
+ }
+ }
+
+ /* Destroy key cell */
+ CmiDestroyBlock(RegistryHive,
+ SubKey->KeyCell,
+ SubKey->BlockOffset);
+ SubKey->BlockOffset = -1;
+ SubKey->KeyCell = NULL;
+
+ /* FIXME: Merge free blocks within the Bin */
+
+ return(STATUS_SUCCESS);
}
NTSTATUS
CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive,
IN PKEY_CELL KeyCell,
- IN PCHAR ValueName,
+ IN PUNICODE_STRING ValueName,
OUT PVALUE_CELL *ValueCell,
OUT BLOCK_OFFSET *VBOffset)
{
PVALUE_LIST_CELL ValueListCell;
PVALUE_CELL CurValueCell;
- ULONG Length;
ULONG i;
ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL);
for (i = 0; i < KeyCell->NumberOfValues; i++)
{
CurValueCell = CmiGetBlock(RegistryHive,
- ValueListCell->Values[i],
- NULL);
- /* FIXME: perhaps we must not ignore case if NtCreateKey has not been */
- /* called with OBJ_CASE_INSENSITIVE flag ? */
- Length = strlen(ValueName);
+ ValueListCell->Values[i],
+ NULL);
+
if ((CurValueCell != NULL) &&
- (CurValueCell->NameSize == Length) &&
- (_strnicmp(CurValueCell->Name, ValueName, Length) == 0))
+ CmiComparePackedNames(ValueName,
+ CurValueCell->Name,
+ CurValueCell->NameSize,
+ CurValueCell->Flags & REG_VALUE_NAME_PACKED))
{
*ValueCell = CurValueCell;
- if (VBOffset)
+ if (VBOffset)
*VBOffset = ValueListCell->Values[i];
- DPRINT("Found value %s\n", ValueName);
+ //DPRINT("Found value %s\n", ValueName);
break;
}
CmiReleaseBlock(RegistryHive, CurValueCell);
}
CmiReleaseBlock(RegistryHive, ValueListCell);
-
+
return STATUS_SUCCESS;
}
{
PVALUE_LIST_CELL ValueListCell;
PVALUE_CELL CurValueCell;
-
+
ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL);
*ValueCell = NULL;
CmiReleaseBlock(RegistryHive, CurValueCell);
CmiReleaseBlock(RegistryHive, ValueListCell);
-
+
return STATUS_SUCCESS;
}
NTSTATUS
CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive,
IN PKEY_CELL KeyCell,
- IN PCHAR ValueNameBuf,
+ IN PUNICODE_STRING ValueName,
OUT PVALUE_CELL *pValueCell,
OUT BLOCK_OFFSET *pVBOffset)
{
Status = CmiAllocateValueCell(RegistryHive,
&NewValueCell,
&VBOffset,
- ValueNameBuf);
+ ValueName);
*pVBOffset = VBOffset;
if (!NT_SUCCESS(Status))
KeyCell->ValuesOffset = VLBOffset;
}
else if ((KeyCell->NumberOfValues
- >= ((LONG) (ValueListCell->CellSize - 4)) / (LONG) sizeof(BLOCK_OFFSET)))
+ >= (ULONG) ((LONG) (ValueListCell->CellSize - 4)) / (LONG) sizeof(BLOCK_OFFSET)))
{
Status = CmiAllocateBlock(RegistryHive,
(PVOID) &NewValueListCell,
NTSTATUS
CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive,
IN PKEY_CELL KeyCell,
- IN PCHAR ValueName)
+ IN BLOCK_OFFSET KeyCellOffset,
+ IN PUNICODE_STRING ValueName)
{
PVALUE_LIST_CELL ValueListCell;
PVALUE_CELL CurValueCell;
for (i = 0; i < KeyCell->NumberOfValues; i++)
{
CurValueCell = CmiGetBlock(RegistryHive, ValueListCell->Values[i], NULL);
+
if ((CurValueCell != NULL) &&
- (CurValueCell->NameSize == strlen(ValueName)) &&
- (memcmp(CurValueCell->Name, ValueName, strlen(ValueName)) == 0))
+ CmiComparePackedNames(ValueName,
+ CurValueCell->Name,
+ CurValueCell->NameSize,
+ CurValueCell->Flags & REG_VALUE_NAME_PACKED))
{
if ((KeyCell->NumberOfValues - 1) < i)
{
CmiReleaseBlock(RegistryHive, ValueListCell);
+ if (KeyCell->NumberOfValues == 0)
+ {
+ CmiDestroyBlock(RegistryHive,
+ ValueListCell,
+ KeyCell->ValuesOffset);
+ }
+ else
+ {
+ CmiMarkBlockDirty(RegistryHive,
+ KeyCell->ValuesOffset);
+ }
+
+ CmiMarkBlockDirty(RegistryHive,
+ KeyCellOffset);
+
return STATUS_SUCCESS;
}
NewHashSize = sizeof(HASH_TABLE_CELL) +
(HashTableSize - 1) * sizeof(HASH_RECORD);
Status = CmiAllocateBlock(RegistryHive,
- (PVOID*) &NewHashBlock,
- NewHashSize,
- HBOffset);
+ (PVOID*) &NewHashBlock,
+ NewHashSize,
+ HBOffset);
if ((NewHashBlock == NULL) || (!NT_SUCCESS(Status)))
{
NTSTATUS
+CmiRemoveKeyFromHashTable(PREGISTRY_HIVE RegistryHive,
+ PHASH_TABLE_CELL HashBlock,
+ BLOCK_OFFSET NKBOffset)
+{
+ ULONG i;
+
+ for (i = 0; i < HashBlock->HashTableSize; i++)
+ {
+ if (HashBlock->Table[i].KeyOffset == NKBOffset)
+ {
+ HashBlock->Table[i].KeyOffset = 0;
+ RtlZeroMemory(&HashBlock->Table[i].HashValue, 4);
+ return STATUS_SUCCESS;
+ }
+ }
+
+ return STATUS_UNSUCCESSFUL;
+}
+
+
+NTSTATUS
CmiAllocateValueCell(PREGISTRY_HIVE RegistryHive,
PVALUE_CELL *ValueCell,
BLOCK_OFFSET *VBOffset,
- IN PCHAR ValueNameBuf)
+ IN PUNICODE_STRING ValueName)
{
PVALUE_CELL NewValueCell;
- ULONG NewValueSize;
NTSTATUS Status;
+ BOOLEAN Packable;
+ ULONG NameSize;
+ ULONG i;
Status = STATUS_SUCCESS;
- NewValueSize = sizeof(VALUE_CELL) + strlen(ValueNameBuf);
- Status = CmiAllocateBlock(RegistryHive,
- (PVOID*) &NewValueCell,
- NewValueSize,
- VBOffset);
+ NameSize = CmiGetPackedNameLength(ValueName,
+ &Packable);
+
+ DPRINT("ValueName->Length %lu NameSize %lu\n", ValueName->Length, NameSize);
+ Status = CmiAllocateBlock(RegistryHive,
+ (PVOID*) &NewValueCell,
+ sizeof(VALUE_CELL) + NameSize,
+ VBOffset);
if ((NewValueCell == NULL) || (!NT_SUCCESS(Status)))
{
Status = STATUS_INSUFFICIENT_RESOURCES;
else
{
NewValueCell->Id = REG_VALUE_CELL_ID;
- NewValueCell->NameSize = strlen(ValueNameBuf);
- memcpy(NewValueCell->Name, ValueNameBuf, strlen(ValueNameBuf));
+ NewValueCell->NameSize = NameSize;
+ if (Packable)
+ {
+ /* Pack the value name */
+ for (i = 0; i < NameSize; i++)
+ NewValueCell->Name[i] = (CHAR)ValueName->Buffer[i];
+ NewValueCell->Flags |= REG_VALUE_NAME_PACKED;
+ }
+ else
+ {
+ /* Copy the value name */
+ RtlCopyMemory(NewValueCell->Name,
+ ValueName->Buffer,
+ NameSize);
+ NewValueCell->Flags = 0;
+ }
NewValueCell->DataType = 0;
NewValueCell->DataSize = 0;
NewValueCell->DataOffset = 0xffffffff;
VERIFY_VALUE_CELL(ValueCell);
- /* First, release datas: */
- if (ValueCell->DataSize > 0)
+ /* First, release data: */
+ if (ValueCell->DataSize > 4)
{
pBlock = CmiGetBlock(RegistryHive, ValueCell->DataOffset, &pBin);
Status = CmiDestroyBlock(RegistryHive, pBlock, ValueCell->DataOffset);
/* Initialize a free block in this heap : */
tmpBlock = (PCELL_HEADER)((ULONG_PTR) tmpBin + REG_HBIN_DATA_OFFSET);
tmpBlock->CellSize = (REG_BLOCK_SIZE - REG_HBIN_DATA_OFFSET);
+
+ /* Grow bitmap if necessary */
+ if (IsVolatileHive(RegistryHive) &&
+ (RegistryHive->BlockListSize % (sizeof(ULONG) * 8) == 0))
+ {
+ DPRINT1("Grow hive bitmap - BlockListSize %lu\n", RegistryHive->BlockListSize);
+
+ /* FIXME */
+
+ }
+
*NewBlock = (PVOID) tmpBlock;
if (NewBlockOffset)
NTSTATUS
CmiAllocateBlock(PREGISTRY_HIVE RegistryHive,
- PVOID *Block,
- LONG BlockSize,
- BLOCK_OFFSET * pBlockOffset)
+ PVOID *Block,
+ LONG BlockSize,
+ BLOCK_OFFSET * pBlockOffset)
{
PCELL_HEADER NewBlock;
NTSTATUS Status;
{
NewBlock = ExAllocatePool(NonPagedPool, BlockSize);
- if (NewBlock == NULL)
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- }
- else
- {
- RtlZeroMemory(NewBlock, BlockSize);
- NewBlock->CellSize = BlockSize;
- CmiLockBlock(RegistryHive, NewBlock);
- *Block = NewBlock;
- if (pBlockOffset)
- *pBlockOffset = (BLOCK_OFFSET) NewBlock;
- }
+ if (NewBlock == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ else
+ {
+ RtlZeroMemory(NewBlock, BlockSize);
+ NewBlock->CellSize = BlockSize;
+ CmiLockBlock(RegistryHive, NewBlock);
+ *Block = NewBlock;
+ if (pBlockOffset)
+ *pBlockOffset = (BLOCK_OFFSET) NewBlock;
+ }
}
else
{
- ULONG i;
-
- /* first search in free blocks */
- NewBlock = NULL;
- for (i = 0; i < RegistryHive->FreeListSize; i++)
- {
- if (RegistryHive->FreeList[i]->CellSize >= BlockSize)
- {
- PVOID Temp;
- NewBlock = RegistryHive->FreeList[i];
-
- if (pBlockOffset)
- *pBlockOffset = RegistryHive->FreeListOffset[i];
-
- /* Update time of heap */
- Temp = CmiGetBlock(RegistryHive, RegistryHive->FreeListOffset[i], &pBin);
-
- if (Temp)
- ZwQuerySystemTime((PTIME) &pBin->DateModified);
-
- if ((i + 1) < RegistryHive->FreeListSize)
- {
- RtlMoveMemory(&RegistryHive->FreeList[i],
- &RegistryHive->FreeList[i + 1],
- sizeof(RegistryHive->FreeList[0])
- * (RegistryHive->FreeListSize - i - 1));
- RtlMoveMemory(&RegistryHive->FreeListOffset[i],
- &RegistryHive->FreeListOffset[i + 1],
- sizeof(RegistryHive->FreeListOffset[0])
- * (RegistryHive->FreeListSize - i - 1));
- }
- RegistryHive->FreeListSize--;
- break;
- }
- }
-
- /* Need to extend hive file : */
- if (NewBlock == NULL)
- {
- /* Add a new block */
- Status = CmiAddBin(RegistryHive, (PVOID *) &NewBlock , pBlockOffset);
- }
-
- if (NT_SUCCESS(Status))
- {
- *Block = NewBlock;
-
- /* Split the block in two parts */
- if (NewBlock->CellSize > BlockSize)
- {
- NewBlock = (PCELL_HEADER) ((ULONG_PTR) NewBlock+BlockSize);
- NewBlock->CellSize = ((PCELL_HEADER) (*Block))->CellSize - BlockSize;
- CmiAddFree(RegistryHive, NewBlock, *pBlockOffset + BlockSize);
- }
- else if (NewBlock->CellSize < BlockSize)
- {
- return STATUS_UNSUCCESSFUL;
- }
- RtlZeroMemory(*Block, BlockSize);
- ((PCELL_HEADER) (*Block))->CellSize = -BlockSize;
- CmiLockBlock(RegistryHive, *Block);
- }
- }
- return Status;
+ ULONG i;
+
+ /* first search in free blocks */
+ NewBlock = NULL;
+ for (i = 0; i < RegistryHive->FreeListSize; i++)
+ {
+ if (RegistryHive->FreeList[i]->CellSize >= BlockSize)
+ {
+ PVOID Temp;
+
+ NewBlock = RegistryHive->FreeList[i];
+ if (pBlockOffset)
+ *pBlockOffset = RegistryHive->FreeListOffset[i];
+
+ /* Update time of heap */
+ Temp = CmiGetBlock(RegistryHive, RegistryHive->FreeListOffset[i], &pBin);
+
+ if (Temp)
+ {
+ ZwQuerySystemTime((PTIME) &pBin->DateModified);
+ CmiMarkBlockDirty(RegistryHive, RegistryHive->FreeListOffset[i]);
+ }
+
+ if ((i + 1) < RegistryHive->FreeListSize)
+ {
+ RtlMoveMemory(&RegistryHive->FreeList[i],
+ &RegistryHive->FreeList[i + 1],
+ sizeof(RegistryHive->FreeList[0])
+ * (RegistryHive->FreeListSize - i - 1));
+ RtlMoveMemory(&RegistryHive->FreeListOffset[i],
+ &RegistryHive->FreeListOffset[i + 1],
+ sizeof(RegistryHive->FreeListOffset[0])
+ * (RegistryHive->FreeListSize - i - 1));
+ }
+ RegistryHive->FreeListSize--;
+ break;
+ }
+ }
+
+ /* Need to extend hive file : */
+ if (NewBlock == NULL)
+ {
+ /* Add a new block */
+ Status = CmiAddBin(RegistryHive, (PVOID *) &NewBlock , pBlockOffset);
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ *Block = NewBlock;
+
+ /* Split the block in two parts */
+ if (NewBlock->CellSize > BlockSize)
+ {
+ NewBlock = (PCELL_HEADER) ((ULONG_PTR) NewBlock+BlockSize);
+ NewBlock->CellSize = ((PCELL_HEADER) (*Block))->CellSize - BlockSize;
+ CmiAddFree(RegistryHive, NewBlock, *pBlockOffset + BlockSize);
+ CmiMarkBlockDirty(RegistryHive, *pBlockOffset + BlockSize);
+ }
+ else if (NewBlock->CellSize < BlockSize)
+ {
+ return(STATUS_UNSUCCESSFUL);
+ }
+
+ RtlZeroMemory(*Block, BlockSize);
+ ((PCELL_HEADER) (*Block))->CellSize = -BlockSize;
+ CmiLockBlock(RegistryHive, *Block);
+ }
+ }
+
+ return(Status);
}
Status = STATUS_SUCCESS;
if (IsVolatileHive(RegistryHive))
- {
- CmiReleaseBlock(RegistryHive, Block);
- ExFreePool(Block);
- }
+ {
+ CmiReleaseBlock(RegistryHive, Block);
+ ExFreePool(Block);
+ }
else
- {
- PCELL_HEADER pFree = Block;
+ {
+ PCELL_HEADER pFree = Block;
- if (pFree->CellSize < 0)
- pFree->CellSize = -pFree->CellSize;
+ if (pFree->CellSize < 0)
+ pFree->CellSize = -pFree->CellSize;
- CmiAddFree(RegistryHive, Block, Offset);
- CmiReleaseBlock(RegistryHive, Block);
+ /* Clear block (except the block size) */
+ RtlZeroMemory(((PVOID)pFree) + sizeof(ULONG),
+ pFree->CellSize - sizeof(ULONG));
- /* Update time of heap */
- if (IsPermanentHive(RegistryHive) && CmiGetBlock(RegistryHive, Offset,&pBin))
- ZwQuerySystemTime((PTIME) &pBin->DateModified);
+ CmiAddFree(RegistryHive, Block, Offset);
+ CmiReleaseBlock(RegistryHive, Block);
- /* FIXME: Set first dword to block_offset of another free block ? */
- /* FIXME: Concatenate with previous and next block if free */
- }
+ /* Update time of heap */
+ if (IsPermanentHive(RegistryHive) && CmiGetBlock(RegistryHive, Offset,&pBin))
+ ZwQuerySystemTime((PTIME) &pBin->DateModified);
+
+ CmiMarkBlockDirty(RegistryHive, Offset);
+
+ /* FIXME: Set first dword to block_offset of another free block ? */
+ /* FIXME: Concatenate with previous and next block if free */
+ }
return Status;
}
FreeBlock, FreeOffset);
DPRINT("\n");
if ((RegistryHive->FreeListSize + 1) > RegistryHive->FreeListMax)
- {
+ {
DPRINT("\n");
- tmpList = ExAllocatePool(PagedPool,
+ tmpList = ExAllocatePool(PagedPool,
sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax + 32));
DPRINT("\n");
- if (tmpList == NULL)
- return STATUS_INSUFFICIENT_RESOURCES;
+ if (tmpList == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
DPRINT("\n");
- tmpListOffset = ExAllocatePool(PagedPool,
+ tmpListOffset = ExAllocatePool(PagedPool,
sizeof(BLOCK_OFFSET *) * (RegistryHive->FreeListMax + 32));
DPRINT("\n");
- if (tmpListOffset == NULL)
- {
- ExFreePool(tmpList);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
+ if (tmpListOffset == NULL)
+ {
+ ExFreePool(tmpList);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
DPRINT("\n");
- if (RegistryHive->FreeListMax)
- {
+ if (RegistryHive->FreeListMax)
+ {
DPRINT("\n");
- RtlMoveMemory(tmpList, RegistryHive->FreeList,
- sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax));
+ RtlMoveMemory(tmpList,
+ RegistryHive->FreeList,
+ sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax));
DPRINT("\n");
- RtlMoveMemory(tmpListOffset, RegistryHive->FreeListOffset,
- sizeof(BLOCK_OFFSET *) * (RegistryHive->FreeListMax));
+ RtlMoveMemory(tmpListOffset,
+ RegistryHive->FreeListOffset,
+ sizeof(BLOCK_OFFSET *) * (RegistryHive->FreeListMax));
DPRINT("\n");
- ExFreePool(RegistryHive->FreeList);
+ ExFreePool(RegistryHive->FreeList);
DPRINT("\n");
- ExFreePool(RegistryHive->FreeListOffset);
+ ExFreePool(RegistryHive->FreeListOffset);
DPRINT("\n");
- }
+ }
DPRINT("\n");
- RegistryHive->FreeList = tmpList;
- RegistryHive->FreeListOffset = tmpListOffset;
- RegistryHive->FreeListMax += 32;
+ RegistryHive->FreeList = tmpList;
+ RegistryHive->FreeListOffset = tmpListOffset;
+ RegistryHive->FreeListMax += 32;
DPRINT("\n");
- }
+ }
DPRINT("\n");
- /* Add new offset to free list, maintaining list in ascending order */
- if ((RegistryHive->FreeListSize == 0)
- || (RegistryHive->FreeListOffset[RegistryHive->FreeListSize-1] < FreeOffset))
- {
+ /* Add new offset to free list, maintaining list in ascending order */
+ if ((RegistryHive->FreeListSize == 0)
+ || (RegistryHive->FreeListOffset[RegistryHive->FreeListSize-1] < FreeOffset))
+ {
+DPRINT("\n");
+ /* Add to end of list */
+ RegistryHive->FreeList[RegistryHive->FreeListSize] = FreeBlock;
+ RegistryHive->FreeListOffset[RegistryHive->FreeListSize++] = FreeOffset;
+ }
+ else if (RegistryHive->FreeListOffset[0] > FreeOffset)
+ {
DPRINT("\n");
- /* Add to end of list */
- RegistryHive->FreeList[RegistryHive->FreeListSize] = FreeBlock;
- RegistryHive->FreeListOffset[RegistryHive->FreeListSize++] = FreeOffset;
- }
- else if (RegistryHive->FreeListOffset[0] > FreeOffset)
- {
+ /* Add to begin of list */
+ RtlMoveMemory(&RegistryHive->FreeList[1],
+ &RegistryHive->FreeList[0],
+ sizeof(RegistryHive->FreeList[0]) * RegistryHive->FreeListSize);
+ RtlMoveMemory(&RegistryHive->FreeListOffset[1],
+ &RegistryHive->FreeListOffset[0],
+ sizeof(RegistryHive->FreeListOffset[0]) * RegistryHive->FreeListSize);
+ RegistryHive->FreeList[0] = FreeBlock;
+ RegistryHive->FreeListOffset[0] = FreeOffset;
+ RegistryHive->FreeListSize++;
+ }
+ else
+ {
DPRINT("\n");
- /* Add to begin of list */
- RtlMoveMemory(&RegistryHive->FreeList[1],
- &RegistryHive->FreeList[0],
- sizeof(RegistryHive->FreeList[0]) * RegistryHive->FreeListSize);
- RtlMoveMemory(&RegistryHive->FreeListOffset[1],
- &RegistryHive->FreeListOffset[0],
- sizeof(RegistryHive->FreeListOffset[0]) * RegistryHive->FreeListSize);
- RegistryHive->FreeList[0] = FreeBlock;
- RegistryHive->FreeListOffset[0] = FreeOffset;
- RegistryHive->FreeListSize++;
- }
+ /* Search where to insert */
+ minInd = 0;
+ maxInd = RegistryHive->FreeListSize - 1;
+ while ((maxInd - minInd) > 1)
+ {
+ medInd = (minInd + maxInd) / 2;
+ if (RegistryHive->FreeListOffset[medInd] > FreeOffset)
+ maxInd = medInd;
else
- {
-DPRINT("\n");
- /* Search where to insert */
- minInd = 0;
- maxInd = RegistryHive->FreeListSize - 1;
- while ((maxInd - minInd) > 1)
- {
- medInd = (minInd + maxInd) / 2;
- if (RegistryHive->FreeListOffset[medInd] > FreeOffset)
- maxInd = medInd;
- else
- minInd = medInd;
- }
-
- /* Insert before maxInd */
- RtlMoveMemory(&RegistryHive->FreeList[maxInd+1],
- &RegistryHive->FreeList[maxInd],
+ minInd = medInd;
+ }
+
+ /* Insert before maxInd */
+ RtlMoveMemory(&RegistryHive->FreeList[maxInd+1],
+ &RegistryHive->FreeList[maxInd],
sizeof(RegistryHive->FreeList[0]) * (RegistryHive->FreeListSize - minInd));
- RtlMoveMemory(&RegistryHive->FreeListOffset[maxInd + 1],
+ RtlMoveMemory(&RegistryHive->FreeListOffset[maxInd + 1],
&RegistryHive->FreeListOffset[maxInd],
sizeof(RegistryHive->FreeListOffset[0]) * (RegistryHive->FreeListSize-minInd));
- RegistryHive->FreeList[maxInd] = FreeBlock;
- RegistryHive->FreeListOffset[maxInd] = FreeOffset;
- RegistryHive->FreeListSize++;
- }
+ RegistryHive->FreeList[maxInd] = FreeBlock;
+ RegistryHive->FreeListOffset[maxInd] = FreeOffset;
+ RegistryHive->FreeListSize++;
+ }
DPRINT("\n");
return STATUS_SUCCESS;
PVOID
CmiGetBlock(PREGISTRY_HIVE RegistryHive,
- BLOCK_OFFSET BlockOffset,
- PHBIN * ppBin)
+ BLOCK_OFFSET BlockOffset,
+ PHBIN * ppBin)
{
if (ppBin)
*ppBin = NULL;
- if ((BlockOffset == 0) || (BlockOffset == -1))
+ if ((BlockOffset == 0) || (BlockOffset == (ULONG_PTR) -1))
return NULL;
if (IsVolatileHive(RegistryHive))
VOID
-CmiPrepareForWrite(PREGISTRY_HIVE RegistryHive,
- PHBIN pBin)
+CmiLockBlock(PREGISTRY_HIVE RegistryHive,
+ PVOID Block)
{
- if (IsVolatileHive(RegistryHive))
- {
- /* No need to do anything special for volatile hives */
- return;
- }
- else
+ if (IsPermanentHive(RegistryHive))
{
-
+ /* FIXME: Implement */
}
}
VOID
-CmiLockBlock(PREGISTRY_HIVE RegistryHive,
- PVOID Block)
+CmiReleaseBlock(PREGISTRY_HIVE RegistryHive,
+ PVOID Block)
{
if (IsPermanentHive(RegistryHive))
{
VOID
-CmiReleaseBlock(PREGISTRY_HIVE RegistryHive,
- PVOID Block)
+CmiMarkBlockDirty(PREGISTRY_HIVE RegistryHive,
+ BLOCK_OFFSET BlockOffset)
{
- if (IsPermanentHive(RegistryHive))
+ ULONG Index;
+
+ if (IsVolatileHive(RegistryHive))
+ return;
+
+ Index = (ULONG)BlockOffset / 4096;
+
+ DPRINT1("CmiMarkBlockDirty(Offset 0x%lx) Index %lu\n",
+ (ULONG)BlockOffset, Index);
+
+ RegistryHive->HiveDirty = TRUE;
+ RtlSetBits(&RegistryHive->DirtyBitMap,
+ Index,
+ 1);
+}
+
+
+ULONG
+CmiGetPackedNameLength(IN PUNICODE_STRING Name,
+ OUT PBOOLEAN Packable)
+{
+ ULONG i;
+
+ if (Packable != NULL)
+ *Packable = TRUE;
+
+ for (i = 0; i < Name->Length; i++)
{
- /* FIXME: Implement */
+ if (Name->Buffer[i] > 0xFF)
+ {
+ if (Packable != NULL)
+ *Packable = FALSE;
+ return(Name->Length);
+ }
+ }
+
+ return(Name->Length / sizeof(WCHAR));
+}
+
+
+BOOLEAN
+CmiComparePackedNames(IN PUNICODE_STRING Name,
+ IN PCHAR NameBuffer,
+ IN USHORT NameBufferSize,
+ IN BOOLEAN NamePacked)
+{
+ PWCHAR UNameBuffer;
+ ULONG i;
+
+ if (NamePacked == TRUE)
+ {
+ if (Name->Length != NameBufferSize * sizeof(WCHAR))
+ return(FALSE);
+
+ for (i = 0; i < Name->Length / sizeof(WCHAR); i++)
+ {
+ if (RtlUpcaseUnicodeChar(Name->Buffer[i]) != RtlUpcaseUnicodeChar((WCHAR)NameBuffer[i]))
+ return(FALSE);
+ }
+ }
+ else
+ {
+ if (Name->Length != NameBufferSize)
+ return(FALSE);
+
+ UNameBuffer = (PWCHAR)NameBuffer;
+
+ for (i = 0; i < Name->Length / sizeof(WCHAR); i++)
+ {
+ if (RtlUpcaseUnicodeChar(Name->Buffer[i]) != RtlUpcaseUnicodeChar(UNameBuffer[i]))
+ return(FALSE);
+ }
}
+
+ return(TRUE);
}
+
+
+VOID
+CmiCopyPackedName(PWCHAR NameBuffer,
+ PCHAR PackedNameBuffer,
+ ULONG PackedNameSize)
+{
+ ULONG i;
+
+ for (i = 0; i < PackedNameSize; i++)
+ NameBuffer[i] = (WCHAR)PackedNameBuffer[i];
+}
+
+/* EOF */