From bcd159805ce8b33c8180ea0e72706b1f6d27dc3c Mon Sep 17 00:00:00 2001 From: Aleksey Bragin Date: Sat, 29 Jul 2006 14:43:32 +0000 Subject: [PATCH] Add 2nd half of the Filip Navara's cmlib. Now both freeldr and ntoskrnl utilise the same base library to access the registry. Remember that you need to recreate binary hives, your old reactos registry isn't compatible (due to slight difference in the on-disk structure). svn path=/trunk/; revision=23348 --- reactos/lib/cmlib/hiveinit.c | 12 + reactos/ntoskrnl/cm/cm.h | 502 ++--- reactos/ntoskrnl/cm/import.c | 102 +- reactos/ntoskrnl/cm/ntfunc.c | 314 +-- reactos/ntoskrnl/cm/regfile.c | 3245 ++++++------------------------ reactos/ntoskrnl/cm/registry.c | 331 +-- reactos/ntoskrnl/cm/regobj.c | 167 +- reactos/ntoskrnl/ntoskrnl.rbuild | 2 + 8 files changed, 1001 insertions(+), 3674 deletions(-) diff --git a/reactos/lib/cmlib/hiveinit.c b/reactos/lib/cmlib/hiveinit.c index df9a8247e72..9b64b56795f 100644 --- a/reactos/lib/cmlib/hiveinit.c +++ b/reactos/lib/cmlib/hiveinit.c @@ -28,6 +28,16 @@ HvpVerifyHiveHeader( HiveHeader->Sequence1 != HiveHeader->Sequence2 || HvpHiveHeaderChecksum(HiveHeader) != HiveHeader->Checksum) { + DPRINT1("Verify Hive Header failed: \n"); + DPRINT1(" Signature: 0x%x and not 0x%x, Major: 0x%x and not 0x%x\n", + HiveHeader->Signature, HV_SIGNATURE, HiveHeader->Major, HV_MAJOR_VER); + DPRINT1(" Minor: 0x%x is not > 0x%x, Type: 0x%x and not 0x%x\n", + HiveHeader->Minor, HV_MINOR_VER, HiveHeader->Type, HV_TYPE_PRIMARY); + DPRINT1(" Format: 0x%x and not 0x%x, Cluster: 0x%x and not 1\n", + HiveHeader->Format, HV_FORMAT_MEMORY, HiveHeader->Cluster); + DPRINT1(" Sequence: 0x%x and not 0x%x, Checksum: 0x%x and not 0x%x\n", + HiveHeader->Sequence1, HiveHeader->Sequence2, + HvpHiveHeaderChecksum(HiveHeader), HiveHeader->Checksum); return FALSE; } @@ -139,6 +149,8 @@ HvpInitializeMemoryHive( if (ChunkSize < sizeof(HIVE_HEADER) || !HvpVerifyHiveHeader((PHIVE_HEADER)ChunkBase)) { + DPRINT1("Registry is corrupt: ChunkSize %d < sizeof(HIVE_HEADER) %d, " + "or HvpVerifyHiveHeader() failed\n", ChunkSize, sizeof(HIVE_HEADER)); return STATUS_REGISTRY_CORRUPT; } diff --git a/reactos/ntoskrnl/cm/cm.h b/reactos/ntoskrnl/cm/cm.h index 907d9ab2892..0af16c03990 100644 --- a/reactos/ntoskrnl/cm/cm.h +++ b/reactos/ntoskrnl/cm/cm.h @@ -1,6 +1,8 @@ #ifndef __INCLUDE_CM_H #define __INCLUDE_CM_H +#include + #ifdef DBG #define CHECKED 1 #else @@ -35,265 +37,17 @@ #define REG_SAM_FILE_NAME L"\\sam" #define REG_SEC_FILE_NAME L"\\security" -#define REG_BLOCK_SIZE 4096 -#define REG_HBIN_DATA_OFFSET 32 -#define REG_INIT_BLOCK_LIST_SIZE 32 -#define REG_INIT_HASH_TABLE_SIZE 3 -#define REG_EXTEND_HASH_TABLE_SIZE 4 -#define REG_VALUE_LIST_CELL_MULTIPLE 4 - -#define REG_HIVE_ID 0x66676572 -#define REG_BIN_ID 0x6e696268 -#define REG_KEY_CELL_ID 0x6b6e -#define REG_HASH_TABLE_CELL_ID 0x666c -#define REG_VALUE_CELL_ID 0x6b76 -#define REG_SECURITY_CELL_ID 0x6b73 - - -// BLOCK_OFFSET = offset in file after header block -typedef ULONG BLOCK_OFFSET, *PBLOCK_OFFSET; - -#include - -/* header for registry hive file : */ -typedef struct _HIVE_HEADER -{ - /* Hive identifier "regf" (0x66676572) */ - ULONG BlockId; - - /* Update counter */ - ULONG UpdateCounter1; - - /* Update counter */ - ULONG UpdateCounter2; - - /* When this hive file was last modified */ - LARGE_INTEGER DateModified; - - /* Registry format major version (1) */ - ULONG MajorVersion; - - /* Registry format minor version (3) - Version 3 added fast indexes, version 5 has large value optimizations */ - ULONG MinorVersion; - - /* Registry file type (0 - Primary, 1 - Log) */ - ULONG Type; - - /* 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 */ - BLOCK_OFFSET RootKeyOffset; - - /* Size of each hive block ? */ - ULONG BlockSize; - - /* (1?) */ - ULONG Unused7; - - /* Name of hive file */ - WCHAR FileName[32]; - - ULONG Reserved[99]; - - /* Checksum of first 0x200 bytes */ - ULONG Checksum; -} HIVE_HEADER, *PHIVE_HEADER; - -typedef struct _BIN_HEADER -{ - /* Bin identifier "hbin" (0x6E696268) */ - ULONG HeaderId; - - /* Block offset of this bin */ - BLOCK_OFFSET BinOffset; - - /* Size in bytes, multiple of the block size (4KB) */ - ULONG BinSize; - - ULONG Reserved[2]; - - /* When this bin was last modified */ - LARGE_INTEGER DateModified; - - /* ? (In-memory only) */ - ULONG MemAlloc; -} HBIN, *PHBIN; - -typedef struct _CELL_HEADER -{ - /* <0 if used, >0 if free */ - LONG CellSize; -} CELL_HEADER, *PCELL_HEADER; - -typedef struct _KEY_CELL -{ - /* Size of this cell */ - LONG CellSize; - - /* Key cell identifier "kn" (0x6b6e) */ - USHORT Id; - - /* Flags */ - USHORT Flags; - - /* Time of last flush */ - LARGE_INTEGER LastWriteTime; - - /* ? */ - ULONG UnUsed1; - - /* Block offset of parent key cell */ - BLOCK_OFFSET ParentKeyOffset; - - /* Count of sub keys for the key in this key cell */ - ULONG NumberOfSubKeys; - - /* ? */ - ULONG UnUsed2; - - /* Block offset of has table for FIXME: subkeys/values? */ - BLOCK_OFFSET HashTableOffset; - - /* ? */ - ULONG UnUsed3; - - /* Count of values contained in this key cell */ - ULONG NumberOfValues; - - /* Block offset of VALUE_LIST_CELL */ - BLOCK_OFFSET ValueListOffset; - - /* Block offset of security cell */ - BLOCK_OFFSET SecurityKeyOffset; - - /* Block offset of registry key class */ - BLOCK_OFFSET ClassNameOffset; - - /* ? */ - ULONG Unused4[5]; - - /* Size in bytes of key name */ - USHORT NameSize; - - /* Size of class name in bytes */ - USHORT ClassSize; - - /* Name of key (not zero terminated) */ - UCHAR Name[0]; -} KEY_CELL, *PKEY_CELL; - -/* KEY_CELL.Flags constants */ -#define REG_KEY_ROOT_CELL 0x0C -#define REG_KEY_LINK_CELL 0x10 -#define REG_KEY_NAME_PACKED 0x20 - -/* - * Hash record - * - * HashValue: - * packed name: four letters of value's name - * otherwise: Zero! - */ -typedef struct _HASH_RECORD -{ - BLOCK_OFFSET KeyOffset; - ULONG HashValue; -} HASH_RECORD, *PHASH_RECORD; - -typedef struct _HASH_TABLE_CELL -{ - LONG CellSize; - USHORT Id; - USHORT HashTableSize; - HASH_RECORD Table[0]; -} HASH_TABLE_CELL, *PHASH_TABLE_CELL; - - -typedef struct _VALUE_LIST_CELL -{ - LONG CellSize; - BLOCK_OFFSET ValueOffset[0]; -} VALUE_LIST_CELL, *PVALUE_LIST_CELL; - -typedef struct _VALUE_CELL -{ - LONG CellSize; - USHORT Id; // "kv" - USHORT NameSize; // length of Name - ULONG DataSize; // length of datas in the cell pointed by DataOffset - BLOCK_OFFSET DataOffset;// datas are here if high bit of DataSize is set - ULONG DataType; - USHORT Flags; - USHORT Unused1; - UCHAR Name[0]; /* warning : not zero terminated */ -} VALUE_CELL, *PVALUE_CELL; - -/* VALUE_CELL.Flags constants */ -#define REG_VALUE_NAME_PACKED 0x0001 - -/* VALUE_CELL.DataSize mask constants */ -#define REG_DATA_SIZE_MASK 0x7FFFFFFF -#define REG_DATA_IN_OFFSET 0x80000000 - - -typedef struct _SECURITY_CELL -{ - LONG CellSize; - USHORT Id; // "sk" - USHORT Reserved; - BLOCK_OFFSET PrevSecurityCell; - BLOCK_OFFSET NextSecurityCell; - ULONG RefCount; - ULONG SdSize; - UCHAR Data[0]; -} SECURITY_CELL, *PSECURITY_CELL; - - -typedef struct _DATA_CELL -{ - LONG CellSize; - UCHAR Data[0]; -} DATA_CELL, *PDATA_CELL; - -#include - - -typedef struct _BLOCK_LIST_ENTRY -{ - PHBIN Bin; - PVOID Block; -} BLOCK_LIST_ENTRY, *PBLOCK_LIST_ENTRY; - - -typedef struct _REGISTRY_HIVE +typedef struct _EREGISTRY_HIVE { LIST_ENTRY HiveList; - ULONG Flags; + PREGISTRY_HIVE Hive; UNICODE_STRING HiveFileName; UNICODE_STRING LogFileName; - ULONG FileSize; - PHIVE_HEADER HiveHeader; - ULONG UpdateCounter; - ULONG BlockListSize; - PBLOCK_LIST_ENTRY BlockList; - ULONG FreeListSize; - ULONG FreeListMax; - PCELL_HEADER *FreeList; - BLOCK_OFFSET *FreeListOffset; - - PSECURITY_CELL RootSecurityCell; - - PULONG BitmapBuffer; - RTL_BITMAP DirtyBitMap; - BOOLEAN HiveDirty; -} REGISTRY_HIVE, *PREGISTRY_HIVE; - -/* REGISTRY_HIVE.Flags constants */ -/* When set, the hive uses pointers instead of offsets. */ -#define HIVE_POINTER 0x00000001 + PSECURITY_CELL RootSecurityCell; + ULONG Flags; + HANDLE HiveHandle; + HANDLE LogHandle; +} EREGISTRY_HIVE, *PEREGISTRY_HIVE; /* When set, the hive is not backed by a file. Therefore, it can not be flushed to disk. */ @@ -303,22 +57,15 @@ typedef struct _REGISTRY_HIVE Explicit synchronization (save/flush) works. */ #define HIVE_NO_SYNCH 0x00000004 -#define IsPointerHive(Hive) ((Hive)->Flags & HIVE_POINTER) #define IsNoFileHive(Hive) ((Hive)->Flags & HIVE_NO_FILE) #define IsNoSynchHive(Hive) ((Hive)->Flags & HIVE_NO_SYNCH) - -#define IsFreeCell(Cell)(Cell->CellSize >= 0) -#define IsUsedCell(Cell)(Cell->CellSize < 0) - - /* KEY_OBJECT.Flags */ /* When set, the key is scheduled for deletion, and all attempts to access the key must not succeed */ #define KO_MARKED_FOR_DELETE 0x00000001 - /* Type defining the Object Manager Key Object */ typedef struct _KEY_OBJECT { @@ -333,10 +80,10 @@ typedef struct _KEY_OBJECT UNICODE_STRING Name; /* Registry hive the key belongs to */ - PREGISTRY_HIVE RegistryHive; + PEREGISTRY_HIVE RegistryHive; /* Block offset of the key cell this key belongs in */ - BLOCK_OFFSET KeyCellOffset; + HCELL_INDEX KeyCellOffset; /* KEY_CELL this key belong in */ PKEY_CELL KeyCell; @@ -344,6 +91,9 @@ typedef struct _KEY_OBJECT /* Link to the parent KEY_OBJECT for this key */ struct _KEY_OBJECT *ParentKey; + /* List entry into the global key object list */ + LIST_ENTRY ListEntry; + /* Subkeys loaded in SubKeys */ ULONG NumberOfSubKeys; @@ -353,9 +103,6 @@ typedef struct _KEY_OBJECT /* List of subkeys loaded */ struct _KEY_OBJECT **SubKeys; - /* List entry into the global key object list */ - LIST_ENTRY ListEntry; - /* Time stamp for the last access by the parse routine */ ULONG TimeStamp; @@ -371,8 +118,7 @@ typedef struct _KEY_OBJECT #define CmiByteOffset(Cellndex)(CellIndex & 0x00000fff) -extern BOOLEAN CmiDoVerify; -extern PREGISTRY_HIVE CmiVolatileHive; +extern PEREGISTRY_HIVE CmiVolatileHive; extern POBJECT_TYPE CmiKeyType; extern KSPIN_LOCK CmiKeyListLock; @@ -402,34 +148,13 @@ NTSTATUS CmiCallRegisteredCallbacks(IN REG_NOTIFY_CLASS Argument1, IN PVOID Argument2); -VOID -CmiVerifyBinHeader(PHBIN BinHeader); -VOID -CmiVerifyKeyCell(PKEY_CELL KeyCell); -VOID -CmiVerifyRootKeyCell(PKEY_CELL RootKeyCell); -VOID -CmiVerifyKeyObject(PKEY_OBJECT KeyObject); -VOID -CmiVerifyRegistryHive(PREGISTRY_HIVE RegistryHive); - -#ifdef DBG -#define VERIFY_BIN_HEADER CmiVerifyBinHeader -#define VERIFY_KEY_CELL CmiVerifyKeyCell -#define VERIFY_ROOT_KEY_CELL CmiVerifyRootKeyCell -#define VERIFY_VALUE_CELL CmiVerifyValueCell -#define VERIFY_VALUE_LIST_CELL CmiVerifyValueListCell -#define VERIFY_KEY_OBJECT CmiVerifyKeyObject -#define VERIFY_REGISTRY_HIVE CmiVerifyRegistryHive -#else -#define VERIFY_BIN_HEADER(x) -#define VERIFY_KEY_CELL(x) -#define VERIFY_ROOT_KEY_CELL(x) -#define VERIFY_VALUE_CELL(x) +#define VERIFY_BIN_HEADER(x) ASSERT(x->HeaderId == REG_BIN_ID) +#define VERIFY_KEY_CELL(x) ASSERT(x->Id == REG_KEY_CELL_ID) +#define VERIFY_ROOT_KEY_CELL(x) ASSERT(x->Id == REG_KEY_CELL_ID) +#define VERIFY_VALUE_CELL(x) ASSERT(x->Id == REG_VALUE_CELL_ID) #define VERIFY_VALUE_LIST_CELL(x) #define VERIFY_KEY_OBJECT(x) #define VERIFY_REGISTRY_HIVE(x) -#endif NTSTATUS STDCALL CmRegisterCallback(IN PEX_CALLBACK_FUNCTION Function, @@ -473,23 +198,6 @@ CmiObjectQueryName (PVOID ObjectBody, PULONG ReturnLength, IN KPROCESSOR_MODE PreviousMode); -NTSTATUS -CmiImportHiveBins(PREGISTRY_HIVE Hive, - PUCHAR ChunkPtr); - -VOID -CmiFreeHiveBins(PREGISTRY_HIVE Hive); - -NTSTATUS -CmiCreateHiveFreeCellList(PREGISTRY_HIVE Hive); - -VOID -CmiFreeHiveFreeCellList(PREGISTRY_HIVE Hive); - -NTSTATUS -CmiCreateHiveBitmap(PREGISTRY_HIVE Hive); - - VOID CmiAddKeyToList(IN PKEY_OBJECT ParentKey, IN PKEY_OBJECT NewKey); @@ -504,7 +212,7 @@ CmiScanKeyList(IN PKEY_OBJECT Parent, PKEY_OBJECT* ReturnedObject); NTSTATUS -CmiCreateVolatileHive(PREGISTRY_HIVE *RegistryHive); +CmiCreateVolatileHive(PEREGISTRY_HIVE *RegistryHive); NTSTATUS CmiLoadHive(POBJECT_ATTRIBUTES KeyObjectAttributes, @@ -512,10 +220,10 @@ CmiLoadHive(POBJECT_ATTRIBUTES KeyObjectAttributes, ULONG Flags); NTSTATUS -CmiRemoveRegistryHive(PREGISTRY_HIVE RegistryHive); +CmiRemoveRegistryHive(PEREGISTRY_HIVE RegistryHive); NTSTATUS -CmiFlushRegistryHive(PREGISTRY_HIVE RegistryHive); +CmiFlushRegistryHive(PEREGISTRY_HIVE RegistryHive); ULONG CmiGetNumberOfSubKeys(PKEY_OBJECT KeyObject); @@ -527,24 +235,24 @@ ULONG CmiGetMaxClassLength(IN PKEY_OBJECT KeyObject); ULONG -CmiGetMaxValueNameLength(IN PREGISTRY_HIVE RegistryHive, +CmiGetMaxValueNameLength(IN PEREGISTRY_HIVE RegistryHive, IN PKEY_CELL KeyCell); ULONG -CmiGetMaxValueDataLength(IN PREGISTRY_HIVE RegistryHive, +CmiGetMaxValueDataLength(IN PEREGISTRY_HIVE RegistryHive, IN PKEY_CELL KeyCell); NTSTATUS -CmiScanForSubKey(IN PREGISTRY_HIVE RegistryHive, +CmiScanForSubKey(IN PEREGISTRY_HIVE RegistryHive, IN PKEY_CELL KeyCell, OUT PKEY_CELL *SubKeyCell, - OUT BLOCK_OFFSET *BlockOffset, + OUT HCELL_INDEX *BlockOffset, IN PUNICODE_STRING KeyName, IN ACCESS_MASK DesiredAccess, IN ULONG Attributes); NTSTATUS -CmiAddSubKey(IN PREGISTRY_HIVE RegistryHive, +CmiAddSubKey(IN PEREGISTRY_HIVE RegistryHive, IN PKEY_OBJECT ParentKey, OUT PKEY_OBJECT SubKey, IN PUNICODE_STRING SubKeyName, @@ -553,112 +261,81 @@ CmiAddSubKey(IN PREGISTRY_HIVE RegistryHive, IN ULONG CreateOptions); NTSTATUS -CmiRemoveSubKey(IN PREGISTRY_HIVE RegistryHive, +CmiRemoveSubKey(IN PEREGISTRY_HIVE RegistryHive, IN PKEY_OBJECT Parent, IN PKEY_OBJECT SubKey); NTSTATUS -CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive, +CmiScanKeyForValue(IN PEREGISTRY_HIVE RegistryHive, IN PKEY_CELL KeyCell, IN PUNICODE_STRING ValueName, OUT PVALUE_CELL *ValueCell, - OUT BLOCK_OFFSET *VBOffset); + OUT HCELL_INDEX *VBOffset); NTSTATUS -CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive, +CmiGetValueFromKeyByIndex(IN PEREGISTRY_HIVE RegistryHive, IN PKEY_CELL KeyCell, IN ULONG Index, OUT PVALUE_CELL *ValueCell); NTSTATUS -CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive, +CmiAddValueToKey(IN PEREGISTRY_HIVE RegistryHive, IN PKEY_CELL KeyCell, - IN BLOCK_OFFSET KeyCellOffset, + IN HCELL_INDEX KeyCellOffset, IN PUNICODE_STRING ValueName, OUT PVALUE_CELL *pValueCell, - OUT BLOCK_OFFSET *pValueCellOffset); + OUT HCELL_INDEX *pValueCellOffset); NTSTATUS -CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive, +CmiDeleteValueFromKey(IN PEREGISTRY_HIVE RegistryHive, IN PKEY_CELL KeyCell, - IN BLOCK_OFFSET KeyCellOffset, + IN HCELL_INDEX KeyCellOffset, IN PUNICODE_STRING ValueName); NTSTATUS -CmiAllocateHashTableCell(IN PREGISTRY_HIVE RegistryHive, +CmiAllocateHashTableCell(IN PEREGISTRY_HIVE RegistryHive, OUT PHASH_TABLE_CELL *HashBlock, - OUT BLOCK_OFFSET *HBOffset, - IN ULONG HashTableSize); + OUT HCELL_INDEX *HBOffset, + IN ULONG HashTableSize, + IN HV_STORAGE_TYPE Storage); PKEY_CELL -CmiGetKeyFromHashByIndex(PREGISTRY_HIVE RegistryHive, +CmiGetKeyFromHashByIndex(PEREGISTRY_HIVE RegistryHive, PHASH_TABLE_CELL HashBlock, ULONG Index); NTSTATUS -CmiAddKeyToHashTable(PREGISTRY_HIVE RegistryHive, +CmiAddKeyToHashTable(PEREGISTRY_HIVE RegistryHive, PHASH_TABLE_CELL HashCell, - BLOCK_OFFSET HashCellOffset, + PKEY_CELL KeyCell, + HV_STORAGE_TYPE StorageType, PKEY_CELL NewKeyCell, - BLOCK_OFFSET NKBOffset); + HCELL_INDEX NKBOffset); NTSTATUS -CmiRemoveKeyFromHashTable(PREGISTRY_HIVE RegistryHive, +CmiRemoveKeyFromHashTable(PEREGISTRY_HIVE RegistryHive, PHASH_TABLE_CELL HashBlock, - BLOCK_OFFSET NKBOffset); + HCELL_INDEX NKBOffset); NTSTATUS -CmiAllocateValueCell(IN PREGISTRY_HIVE RegistryHive, +CmiAllocateValueCell(IN PEREGISTRY_HIVE RegistryHive, OUT PVALUE_CELL *ValueCell, - OUT BLOCK_OFFSET *VBOffset, - IN PUNICODE_STRING ValueName); + OUT HCELL_INDEX *VBOffset, + IN PUNICODE_STRING ValueName, + IN HV_STORAGE_TYPE Storage); NTSTATUS -CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive, +CmiDestroyValueCell(PEREGISTRY_HIVE RegistryHive, PVALUE_CELL ValueCell, - BLOCK_OFFSET VBOffset); - -NTSTATUS -CmiAllocateCell(PREGISTRY_HIVE RegistryHive, - LONG CellSize, - PVOID *Cell, - BLOCK_OFFSET *CellOffset); - -NTSTATUS -CmiDestroyCell(PREGISTRY_HIVE RegistryHive, - PVOID Cell, - BLOCK_OFFSET CellOffset); - -PHBIN -CmiGetBin (PREGISTRY_HIVE RegistryHive, - BLOCK_OFFSET CellOffset); - -PVOID -CmiGetCell (PREGISTRY_HIVE RegistryHive, - BLOCK_OFFSET CellOffset, - OUT PHBIN *Bin); - -VOID -CmiMarkBlockDirty(PREGISTRY_HIVE RegistryHive, - BLOCK_OFFSET BlockOffset); - -VOID -CmiMarkBinDirty(PREGISTRY_HIVE RegistryHive, - BLOCK_OFFSET BinOffset); - -NTSTATUS -CmiAddFree(PREGISTRY_HIVE RegistryHive, - PCELL_HEADER FreeBlock, - BLOCK_OFFSET FreeOffset, - BOOLEAN MergeFreeBlocks); + HCELL_INDEX VBOffset); NTSTATUS CmiConnectHive(POBJECT_ATTRIBUTES KeyObjectAttributes, - PREGISTRY_HIVE RegistryHive); + PEREGISTRY_HIVE RegistryHive); NTSTATUS CmiDisconnectHive (POBJECT_ATTRIBUTES KeyObjectAttributes, - PREGISTRY_HIVE *RegistryHive); + PEREGISTRY_HIVE *RegistryHive); NTSTATUS CmiInitHives(BOOLEAN SetupBoot); @@ -700,16 +377,16 @@ CmiSyncHives(VOID); NTSTATUS -CmiCreateTempHive(PREGISTRY_HIVE *RegistryHive); +CmiCreateTempHive(PEREGISTRY_HIVE *RegistryHive); NTSTATUS -CmiCopyKey (PREGISTRY_HIVE DstHive, +CmiCopyKey (PEREGISTRY_HIVE DstHive, PKEY_CELL DstKeyCell, - PREGISTRY_HIVE SrcHive, + PEREGISTRY_HIVE SrcHive, PKEY_CELL SrcKeyCell); NTSTATUS -CmiSaveTempHive (PREGISTRY_HIVE Hive, +CmiSaveTempHive (PEREGISTRY_HIVE Hive, HANDLE FileHandle); NTSTATUS @@ -723,4 +400,65 @@ CmFindObject( IN PACCESS_STATE AccessState, IN PVOID ParseContext ); +PVOID CMAPI +CmpAllocate( + ULONG Size, + BOOLEAN Paged); + +VOID CMAPI +CmpFree( + PVOID Ptr); + +BOOLEAN CMAPI +CmpFileRead( + PREGISTRY_HIVE RegistryHive, + ULONG FileType, + ULONG FileOffset, + PVOID Buffer, + ULONG BufferLength); + +BOOLEAN CMAPI +CmpFileWrite( + PREGISTRY_HIVE RegistryHive, + ULONG FileType, + ULONG FileOffset, + PVOID Buffer, + ULONG BufferLength); + +BOOLEAN CMAPI +CmpFileSetSize( + PREGISTRY_HIVE RegistryHive, + ULONG FileType, + ULONG FileSize); + +BOOLEAN CMAPI +CmpFileFlush( + PREGISTRY_HIVE RegistryHive, + ULONG FileType); + +#if 0 +static __inline PVOID xHvGetCell(char *file, int line, PREGISTRY_HIVE Hive, HCELL_INDEX Cell) +{ + DPRINT1("xHvGetCell @ %s:%d %x @ %x\n", file, line, Cell, Hive); + return HvGetCell(Hive, Cell); +} + +static __inline VOID xHvFreeCell(char *file, int line, PREGISTRY_HIVE Hive, HCELL_INDEX Cell) +{ + DPRINT1("xHvFreeCell @ %s:%d %x @ %x\n", file, line, Cell, Hive); + HvFreeCell(Hive, Cell); +} + +static __inline HCELL_INDEX xHvAllocateCell(char *file, int line, PREGISTRY_HIVE Hive, SIZE_T Size) +{ + HCELL_INDEX Offset = HvAllocateCell(Hive, Size); + DPRINT1("xHvAllocateCell @ %s:%d (%x) %x @ %x\n", file, line, Size, Offset, Hive); + return Offset; +} + +#define HvGetCell(hive, cell) xHvGetCell(__FILE__, __LINE__, hive, cell) +#define HvFreeCell(hive, cell) xHvFreeCell(__FILE__, __LINE__, hive, cell) +#define HvAllocateCell(hive, size) xHvAllocateCell(__FILE__, __LINE__, hive, size) +#endif + #endif /*__INCLUDE_CM_H*/ diff --git a/reactos/ntoskrnl/cm/import.c b/reactos/ntoskrnl/cm/import.c index b0b23d1078f..f6f7b7e7ede 100644 --- a/reactos/ntoskrnl/cm/import.c +++ b/reactos/ntoskrnl/cm/import.c @@ -24,120 +24,46 @@ static BOOLEAN CmiHardwareHiveImported = FALSE; - /* FUNCTIONS ****************************************************************/ static BOOLEAN CmImportBinaryHive (PCHAR ChunkBase, ULONG ChunkSize, ULONG Flags, - PREGISTRY_HIVE *RegistryHive) + PEREGISTRY_HIVE *RegistryHive) { - PREGISTRY_HIVE Hive; + PEREGISTRY_HIVE Hive; NTSTATUS Status; *RegistryHive = NULL; - if (strncmp (ChunkBase, "regf", 4)) - { - DPRINT1 ("Found invalid '%*s' magic\n", 4, ChunkBase); - return FALSE; - } - /* Create a new hive */ Hive = ExAllocatePool (NonPagedPool, - sizeof(REGISTRY_HIVE)); + sizeof(EREGISTRY_HIVE)); if (Hive == NULL) { return FALSE; } RtlZeroMemory (Hive, - sizeof(REGISTRY_HIVE)); + sizeof(EREGISTRY_HIVE)); /* Set hive flags */ Hive->Flags = Flags; /* Allocate hive header */ - Hive->HiveHeader = (PHIVE_HEADER)ExAllocatePool (NonPagedPool, - sizeof(HIVE_HEADER)); - if (Hive->HiveHeader == NULL) + Status = HvInitialize(&Hive->Hive, HV_OPERATION_MEMORY, + (ULONG_PTR)ChunkBase, ChunkSize, + CmpAllocate, CmpFree, + CmpFileRead, CmpFileWrite, CmpFileSetSize, + CmpFileFlush, Hive); + if (!NT_SUCCESS(Status)) { - DPRINT1 ("Allocating hive header failed\n"); + DPRINT1 ("Opening hive failed (%x)\n", Status); ExFreePool (Hive); return FALSE; } - /* Import the hive header */ - RtlCopyMemory (Hive->HiveHeader, - ChunkBase, - sizeof(HIVE_HEADER)); - - /* Read update counter */ - Hive->UpdateCounter = Hive->HiveHeader->UpdateCounter1; - - /* Set the hive's size */ - Hive->FileSize = ChunkSize; - - /* Set the size of the block list */ - Hive->BlockListSize = (Hive->FileSize / 4096) - 1; - - /* Allocate block list */ - DPRINT("Space needed for block list describing hive: 0x%x\n", - Hive->BlockListSize * sizeof(BLOCK_LIST_ENTRY)); - Hive->BlockList = ExAllocatePool (NonPagedPool, - Hive->BlockListSize * sizeof(BLOCK_LIST_ENTRY)); - if (Hive->BlockList == NULL) - { - DPRINT1 ("Allocating block list failed\n"); - ExFreePool (Hive->HiveHeader); - ExFreePool (Hive); - return FALSE; - } - RtlZeroMemory (Hive->BlockList, - Hive->BlockListSize * sizeof(BLOCK_LIST_ENTRY)); - - /* Import the bins */ - Status = CmiImportHiveBins(Hive, - (PUCHAR)((ULONG_PTR)ChunkBase + 4096)); - if (!NT_SUCCESS(Status)) - { - DPRINT1 ("CmiImportHiveBins() failed (Status %lx)\n", Status); - CmiFreeHiveBins (Hive); - ExFreePool (Hive->BlockList); - ExFreePool (Hive->HiveHeader); - ExFreePool (Hive); - return (BOOLEAN)Status; - } - - /* Initialize the free cell list */ - Status = CmiCreateHiveFreeCellList (Hive); - if (!NT_SUCCESS(Status)) - { - DPRINT1 ("CmiCreateHiveFreeCellList() failed (Status %lx)\n", Status); - CmiFreeHiveBins (Hive); - ExFreePool (Hive->BlockList); - ExFreePool (Hive->HiveHeader); - ExFreePool (Hive); - - return (BOOLEAN)Status; - } - - if (!(Hive->Flags & HIVE_NO_FILE)) - { - /* Create the block bitmap */ - Status = CmiCreateHiveBitmap (Hive); - if (!NT_SUCCESS(Status)) - { - DPRINT1 ("CmiCreateHiveBitmap() failed (Status %lx)\n", Status); - CmiFreeHiveFreeCellList (Hive); - CmiFreeHiveBins (Hive); - ExFreePool (Hive->BlockList); - ExFreePool (Hive->HiveHeader); - ExFreePool (Hive); - - return (BOOLEAN)Status; - } - } + CmPrepareHive(Hive->Hive); /* Acquire hive list lock exclusively */ KeEnterCriticalRegion(); @@ -163,7 +89,7 @@ CmImportSystemHive(PCHAR ChunkBase, ULONG ChunkSize) { OBJECT_ATTRIBUTES ObjectAttributes; - PREGISTRY_HIVE RegistryHive; + PEREGISTRY_HIVE RegistryHive; UNICODE_STRING KeyName; NTSTATUS Status; @@ -217,7 +143,7 @@ CmImportHardwareHive(PCHAR ChunkBase, ULONG ChunkSize) { OBJECT_ATTRIBUTES ObjectAttributes; - PREGISTRY_HIVE RegistryHive; + PEREGISTRY_HIVE RegistryHive; UNICODE_STRING KeyName; HANDLE HardwareKey; ULONG Disposition; diff --git a/reactos/ntoskrnl/cm/ntfunc.c b/reactos/ntoskrnl/cm/ntfunc.c index 9601f5b105e..4f4e0a58b1f 100644 --- a/reactos/ntoskrnl/cm/ntfunc.c +++ b/reactos/ntoskrnl/cm/ntfunc.c @@ -16,11 +16,9 @@ #include "cm.h" - /* GLOBALS ******************************************************************/ extern POBJECT_TYPE CmiKeyType; -extern PREGISTRY_HIVE CmiVolatileHive; extern LIST_ENTRY CmiKeyObjectListHead; static BOOLEAN CmiRegistryInitialized = FALSE; @@ -481,12 +479,7 @@ NtCreateKey(OUT PHANDLE KeyHandle, } KeyObject->ParentKey = Object; - - if (CreateOptions & REG_OPTION_VOLATILE) - KeyObject->RegistryHive = CmiVolatileHive; - else - KeyObject->RegistryHive = KeyObject->ParentKey->RegistryHive; - + KeyObject->RegistryHive = KeyObject->ParentKey->RegistryHive; KeyObject->Flags = 0; KeyObject->NumberOfSubKeys = 0; KeyObject->SizeOfSubKeys = 0; @@ -532,19 +525,10 @@ NtCreateKey(OUT PHANDLE KeyHandle, RtlpCreateUnicodeString(&KeyObject->Name, Start, NonPagedPool); } - if (KeyObject->RegistryHive == KeyObject->ParentKey->RegistryHive) - { - KeyObject->KeyCell->ParentKeyOffset = KeyObject->ParentKey->KeyCellOffset; - KeyObject->KeyCell->SecurityKeyOffset = KeyObject->ParentKey->KeyCell->SecurityKeyOffset; - } - else - { - KeyObject->KeyCell->ParentKeyOffset = -1; - KeyObject->KeyCell->SecurityKeyOffset = -1; - /* This key must remain in memory unless it is deleted - or file is unloaded */ - ObReferenceObject(KeyObject); - } + KeyObject->KeyCell->ParentKeyOffset = KeyObject->ParentKey->KeyCellOffset; + KeyObject->KeyCell->SecurityKeyOffset = KeyObject->ParentKey->KeyCell->SecurityKeyOffset; + + DPRINT("RemainingPath: %wZ\n", &RemainingPath); CmiAddKeyToList(KeyObject->ParentKey, KeyObject); @@ -638,7 +622,8 @@ NtDeleteKey(IN HANDLE KeyHandle) VERIFY_KEY_OBJECT(KeyObject); /* Check for subkeys */ - if (KeyObject->NumberOfSubKeys != 0) + if (KeyObject->KeyCell->NumberOfSubKeys[HvStable] != 0 || + KeyObject->KeyCell->NumberOfSubKeys[HvVolatile] != 0) { Status = STATUS_CANNOT_DELETE; } @@ -653,7 +638,7 @@ NtDeleteKey(IN HANDLE KeyHandle) ExReleaseResourceLite(&CmiRegistryLock); KeLeaveCriticalRegion(); - DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID)KeyObject)); + //DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID)KeyObject)); /* Remove the keep-alive reference */ ObDereferenceObject(KeyObject); @@ -667,8 +652,8 @@ NtDeleteKey(IN HANDLE KeyHandle) /* Dereference the object */ ObDereferenceObject(KeyObject); - DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID)KeyObject)); - DPRINT("HandleCount %lu\n", ObGetObjectHandleCount((PVOID)KeyObject)); + //DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID)KeyObject)); + //DPRINT("HandleCount %lu\n", ObGetObjectHandleCount((PVOID)KeyObject)); /* * Note: @@ -690,19 +675,20 @@ NtEnumerateKey(IN HANDLE KeyHandle, OUT PULONG ResultLength) { PKEY_OBJECT KeyObject; - PKEY_OBJECT SubKeyObject; - PREGISTRY_HIVE RegistryHive; + PEREGISTRY_HIVE RegistryHive; PKEY_CELL KeyCell, SubKeyCell; PHASH_TABLE_CELL HashTableBlock; PKEY_BASIC_INFORMATION BasicInformation; PKEY_NODE_INFORMATION NodeInformation; PKEY_FULL_INFORMATION FullInformation; - PDATA_CELL ClassCell; + PVOID ClassCell; ULONG NameSize, ClassSize; KPROCESSOR_MODE PreviousMode; NTSTATUS Status; REG_ENUMERATE_KEY_INFORMATION EnumerateKeyInfo; REG_POST_OPERATION_INFORMATION PostOperationInfo; + HV_STORAGE_TYPE Storage; + ULONG BaseIndex; PAGED_CODE(); @@ -753,10 +739,9 @@ NtEnumerateKey(IN HANDLE KeyHandle, KeyCell = KeyObject->KeyCell; RegistryHive = KeyObject->RegistryHive; - SubKeyObject = NULL; - /* Check for hightest possible sub key index */ - if (Index >= KeyCell->NumberOfSubKeys + KeyObject->NumberOfSubKeys) + if (Index >= KeyCell->NumberOfSubKeys[HvStable] + + KeyCell->NumberOfSubKeys[HvVolatile]) { ExReleaseResourceLite(&CmiRegistryLock); KeLeaveCriticalRegion(); @@ -768,95 +753,43 @@ NtEnumerateKey(IN HANDLE KeyHandle, } /* Get pointer to SubKey */ - if (Index >= KeyCell->NumberOfSubKeys) + if (Index >= KeyCell->NumberOfSubKeys[HvStable]) { - PKEY_OBJECT CurKey = NULL; - ULONG i; - ULONG j; - - /* Search for volatile or 'foreign' keys */ - j = KeyCell->NumberOfSubKeys; - for (i = 0; i < KeyObject->NumberOfSubKeys; i++) - { - CurKey = KeyObject->SubKeys[i]; - if (CurKey->RegistryHive != RegistryHive) - { - if (j == Index) - break; - j++; - } - } - - if (i >= KeyObject->NumberOfSubKeys) - { - ExReleaseResourceLite(&CmiRegistryLock); - KeLeaveCriticalRegion(); - PostOperationInfo.Status = STATUS_NO_MORE_ENTRIES; - CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo); - ObDereferenceObject(KeyObject); - DPRINT("No more non-volatile entries\n"); - return STATUS_NO_MORE_ENTRIES; - } - - SubKeyObject = CurKey; - SubKeyCell = CurKey->KeyCell; + Storage = HvVolatile; + BaseIndex = Index - KeyCell->NumberOfSubKeys[HvStable]; } else { - if (KeyCell->HashTableOffset == (BLOCK_OFFSET)-1) - { - ExReleaseResourceLite(&CmiRegistryLock); - KeLeaveCriticalRegion(); - PostOperationInfo.Status = STATUS_NO_MORE_ENTRIES; - CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo); - ObDereferenceObject(KeyObject); - return STATUS_NO_MORE_ENTRIES; - } - - HashTableBlock = CmiGetCell (RegistryHive, KeyCell->HashTableOffset, NULL); - if (HashTableBlock == NULL) - { - DPRINT("CmiGetBlock() failed\n"); - ExReleaseResourceLite(&CmiRegistryLock); - KeLeaveCriticalRegion(); - PostOperationInfo.Status = STATUS_UNSUCCESSFUL; - CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo); - ObDereferenceObject(KeyObject); - return STATUS_UNSUCCESSFUL; - } - - SubKeyCell = CmiGetKeyFromHashByIndex(RegistryHive, - HashTableBlock, - Index); + Storage = HvStable; + BaseIndex = Index; } - if (SubKeyCell == NULL) + if (KeyCell->HashTableOffset[Storage] == HCELL_NULL) { ExReleaseResourceLite(&CmiRegistryLock); KeLeaveCriticalRegion(); PostOperationInfo.Status = STATUS_NO_MORE_ENTRIES; CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo); ObDereferenceObject(KeyObject); - DPRINT("No more entries\n"); return STATUS_NO_MORE_ENTRIES; } + ASSERT(KeyCell->HashTableOffset[Storage] != HCELL_NULL); + HashTableBlock = HvGetCell (RegistryHive->Hive, KeyCell->HashTableOffset[Storage]); + + SubKeyCell = CmiGetKeyFromHashByIndex(RegistryHive, + HashTableBlock, + BaseIndex); + Status = STATUS_SUCCESS; switch (KeyInformationClass) { case KeyBasicInformation: /* Check size of buffer */ - if (SubKeyObject != NULL) + NameSize = SubKeyCell->NameSize; + if (SubKeyCell->Flags & REG_KEY_NAME_PACKED) { - NameSize = SubKeyObject->Name.Length; - } - else - { - NameSize = SubKeyCell->NameSize; - if (SubKeyCell->Flags & REG_KEY_NAME_PACKED) - { - NameSize *= sizeof(WCHAR); - } + NameSize *= sizeof(WCHAR); } *ResultLength = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]) + NameSize; @@ -887,43 +820,27 @@ NtEnumerateKey(IN HANDLE KeyHandle, CHECKPOINT; } - if (SubKeyObject != NULL) + if (SubKeyCell->Flags & REG_KEY_NAME_PACKED) { - RtlCopyMemory(BasicInformation->Name, - SubKeyObject->Name.Buffer, - NameSize); + CmiCopyPackedName(BasicInformation->Name, + SubKeyCell->Name, + NameSize / sizeof(WCHAR)); } else { - if (SubKeyCell->Flags & REG_KEY_NAME_PACKED) - { - CmiCopyPackedName(BasicInformation->Name, - SubKeyCell->Name, - NameSize / sizeof(WCHAR)); - } - else - { - RtlCopyMemory(BasicInformation->Name, - SubKeyCell->Name, - NameSize); - } + RtlCopyMemory(BasicInformation->Name, + SubKeyCell->Name, + NameSize); } } break; case KeyNodeInformation: /* Check size of buffer */ - if (SubKeyObject != NULL) + NameSize = SubKeyCell->NameSize; + if (SubKeyCell->Flags & REG_KEY_NAME_PACKED) { - NameSize = SubKeyObject->Name.Length; - } - else - { - NameSize = SubKeyCell->NameSize; - if (SubKeyCell->Flags & REG_KEY_NAME_PACKED) - { - NameSize *= sizeof(WCHAR); - } + NameSize *= sizeof(WCHAR); } ClassSize = SubKeyCell->ClassSize; @@ -961,35 +878,25 @@ NtEnumerateKey(IN HANDLE KeyHandle, CHECKPOINT; } - if (SubKeyObject != NULL) + if (SubKeyCell->Flags & REG_KEY_NAME_PACKED) { - RtlCopyMemory(NodeInformation->Name, - SubKeyObject->Name.Buffer, - NameSize); + CmiCopyPackedName(NodeInformation->Name, + SubKeyCell->Name, + NameSize / sizeof(WCHAR)); } else { - if (SubKeyCell->Flags & REG_KEY_NAME_PACKED) - { - CmiCopyPackedName(NodeInformation->Name, - SubKeyCell->Name, - NameSize / sizeof(WCHAR)); - } - else - { - RtlCopyMemory(NodeInformation->Name, - SubKeyCell->Name, - NameSize); - } - } + RtlCopyMemory(NodeInformation->Name, + SubKeyCell->Name, + NameSize); + } if (ClassSize != 0) { - ClassCell = CmiGetCell (KeyObject->RegistryHive, - SubKeyCell->ClassNameOffset, - NULL); + ClassCell = HvGetCell (KeyObject->RegistryHive->Hive, + SubKeyCell->ClassNameOffset); RtlCopyMemory (NodeInformation->Name + SubKeyCell->NameSize, - ClassCell->Data, + ClassCell, ClassSize); } } @@ -1034,11 +941,10 @@ NtEnumerateKey(IN HANDLE KeyHandle, if (ClassSize != 0) { - ClassCell = CmiGetCell (KeyObject->RegistryHive, - SubKeyCell->ClassNameOffset, - NULL); + ClassCell = HvGetCell (KeyObject->RegistryHive->Hive, + SubKeyCell->ClassNameOffset); RtlCopyMemory (FullInformation->Class, - ClassCell->Data, + ClassCell, ClassSize); } } @@ -1073,10 +979,10 @@ NtEnumerateValueKey(IN HANDLE KeyHandle, { NTSTATUS Status; PKEY_OBJECT KeyObject; - PREGISTRY_HIVE RegistryHive; + PEREGISTRY_HIVE RegistryHive; PKEY_CELL KeyCell; PVALUE_CELL ValueCell; - PDATA_CELL DataCell; + PVOID DataCell; ULONG NameSize, DataSize; PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation; PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation; @@ -1205,9 +1111,9 @@ NtEnumerateValueKey(IN HANDLE KeyHandle, if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET)) { - DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL); + DataCell = HvGetCell (RegistryHive->Hive, ValueCell->DataOffset); RtlCopyMemory(ValuePartialInformation->Data, - DataCell->Data, + DataCell, DataSize); } else @@ -1278,10 +1184,10 @@ NtEnumerateValueKey(IN HANDLE KeyHandle, if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET)) { - DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL); + DataCell = HvGetCell (RegistryHive->Hive, ValueCell->DataOffset); RtlCopyMemory((PCHAR) ValueFullInformation + ValueFullInformation->DataOffset, - DataCell->Data, DataSize); + DataCell, DataSize); } else { @@ -1315,7 +1221,7 @@ NtFlushKey(IN HANDLE KeyHandle) { NTSTATUS Status; PKEY_OBJECT KeyObject; - PREGISTRY_HIVE RegistryHive; + PEREGISTRY_HIVE RegistryHive; KPROCESSOR_MODE PreviousMode; PAGED_CODE(); @@ -1526,8 +1432,8 @@ NtQueryKey(IN HANDLE KeyHandle, PKEY_BASIC_INFORMATION BasicInformation; PKEY_NODE_INFORMATION NodeInformation; PKEY_FULL_INFORMATION FullInformation; - PREGISTRY_HIVE RegistryHive; - PDATA_CELL ClassCell; + PEREGISTRY_HIVE RegistryHive; + PVOID ClassCell; PKEY_OBJECT KeyObject; PKEY_CELL KeyCell; ULONG NameSize, ClassSize; @@ -1662,11 +1568,10 @@ NtQueryKey(IN HANDLE KeyHandle, if (ClassSize != 0) { - ClassCell = CmiGetCell (KeyObject->RegistryHive, - KeyCell->ClassNameOffset, - NULL); + ClassCell = HvGetCell (KeyObject->RegistryHive->Hive, + KeyCell->ClassNameOffset); RtlCopyMemory (NodeInformation->Name + KeyObject->Name.Length, - ClassCell->Data, + ClassCell, ClassSize); } } @@ -1710,11 +1615,10 @@ NtQueryKey(IN HANDLE KeyHandle, if (ClassSize) { - ClassCell = CmiGetCell (KeyObject->RegistryHive, - KeyCell->ClassNameOffset, - NULL); + ClassCell = HvGetCell (KeyObject->RegistryHive->Hive, + KeyCell->ClassNameOffset); RtlCopyMemory (FullInformation->Class, - ClassCell->Data, ClassSize); + ClassCell, ClassSize); } } break; @@ -1755,10 +1659,10 @@ NtQueryValueKey(IN HANDLE KeyHandle, NTSTATUS Status; ULONG NameSize, DataSize; PKEY_OBJECT KeyObject; - PREGISTRY_HIVE RegistryHive; + PEREGISTRY_HIVE RegistryHive; PKEY_CELL KeyCell; PVALUE_CELL ValueCell; - PDATA_CELL DataCell; + PVOID DataCell; PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation; PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation; PKEY_VALUE_FULL_INFORMATION ValueFullInformation; @@ -1896,9 +1800,9 @@ NtQueryValueKey(IN HANDLE KeyHandle, if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET)) { - DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL); + DataCell = HvGetCell (RegistryHive->Hive, ValueCell->DataOffset); RtlCopyMemory(ValuePartialInformation->Data, - DataCell->Data, + DataCell, DataSize); } else @@ -1971,10 +1875,10 @@ NtQueryValueKey(IN HANDLE KeyHandle, } if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET)) { - DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL); + DataCell = HvGetCell (RegistryHive->Hive, ValueCell->DataOffset); RtlCopyMemory((PCHAR) ValueFullInformation + ValueFullInformation->DataOffset, - DataCell->Data, + DataCell, DataSize); } else @@ -2015,12 +1919,11 @@ NtSetValueKey(IN HANDLE KeyHandle, { NTSTATUS Status; PKEY_OBJECT KeyObject; - PREGISTRY_HIVE RegistryHive; + PEREGISTRY_HIVE RegistryHive; PKEY_CELL KeyCell; PVALUE_CELL ValueCell; - BLOCK_OFFSET ValueCellOffset; - PDATA_CELL DataCell; - PDATA_CELL NewDataCell; + HCELL_INDEX ValueCellOffset; + PVOID DataCell; ULONG DesiredAccess; REG_SET_VALUE_KEY_INFORMATION SetValueKeyInfo; REG_POST_OPERATION_INFORMATION PostOperationInfo; @@ -2101,8 +2004,8 @@ NtSetValueKey(IN HANDLE KeyHandle, if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET) && (ValueCell->DataSize & REG_DATA_SIZE_MASK) != 0) { - DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL); - DataCellSize = (DataCell->CellSize < 0 ? -DataCell->CellSize : DataCell->CellSize) - sizeof(CELL_HEADER); + DataCell = HvGetCell (RegistryHive->Hive, ValueCell->DataOffset); + DataCellSize = -HvGetCellSize (RegistryHive->Hive, DataCell); } else { @@ -2111,19 +2014,19 @@ NtSetValueKey(IN HANDLE KeyHandle, } - if (DataSize <= sizeof(BLOCK_OFFSET)) + if (DataSize <= sizeof(HCELL_INDEX)) { - /* If data size <= sizeof(BLOCK_OFFSET) then store data in the data offset */ + /* If data size <= sizeof(HCELL_INDEX) then store data in the data offset */ DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize); if (DataCell) { - CmiDestroyCell(RegistryHive, DataCell, ValueCell->DataOffset); + HvFreeCell(RegistryHive->Hive, ValueCell->DataOffset); } RtlCopyMemory(&ValueCell->DataOffset, Data, DataSize); ValueCell->DataSize = DataSize | REG_DATA_IN_OFFSET; ValueCell->DataType = Type; - CmiMarkBlockDirty(RegistryHive, ValueCellOffset); + HvMarkCellDirty(RegistryHive->Hive, ValueCellOffset); } else { @@ -2133,15 +2036,12 @@ NtSetValueKey(IN HANDLE KeyHandle, * New data size is larger than the current, destroy current * data block and allocate a new one. */ - BLOCK_OFFSET NewOffset; + HCELL_INDEX NewOffset; DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize); - Status = CmiAllocateCell (RegistryHive, - sizeof(CELL_HEADER) + DataSize, - (PVOID *)&NewDataCell, - &NewOffset); - if (!NT_SUCCESS(Status)) + NewOffset = HvAllocateCell (RegistryHive->Hive, DataSize, HvStable); + if (NewOffset == HCELL_NULL) { DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status); @@ -2156,18 +2056,18 @@ NtSetValueKey(IN HANDLE KeyHandle, if (DataCell) { - CmiDestroyCell(RegistryHive, DataCell, ValueCell->DataOffset); + HvFreeCell(RegistryHive->Hive, ValueCell->DataOffset); } ValueCell->DataOffset = NewOffset; - DataCell = NewDataCell; + DataCell = HvGetCell(RegistryHive->Hive, NewOffset); } - RtlCopyMemory(DataCell->Data, Data, DataSize); + RtlCopyMemory(DataCell, Data, DataSize); ValueCell->DataSize = DataSize & REG_DATA_SIZE_MASK; ValueCell->DataType = Type; - CmiMarkBlockDirty(RegistryHive, ValueCell->DataOffset); - CmiMarkBlockDirty(RegistryHive, ValueCellOffset); + HvMarkCellDirty(RegistryHive->Hive, ValueCell->DataOffset); + HvMarkCellDirty(RegistryHive->Hive, ValueCellOffset); } /* Mark link key */ @@ -2178,7 +2078,7 @@ NtSetValueKey(IN HANDLE KeyHandle, } KeQuerySystemTime (&KeyCell->LastWriteTime); - CmiMarkBlockDirty (RegistryHive, KeyObject->KeyCellOffset); + HvMarkCellDirty (RegistryHive->Hive, KeyObject->KeyCellOffset); ExReleaseResourceLite(&CmiRegistryLock); KeLeaveCriticalRegion(); @@ -2254,7 +2154,7 @@ Fail: ValueName); KeQuerySystemTime (&KeyObject->KeyCell->LastWriteTime); - CmiMarkBlockDirty (KeyObject->RegistryHive, KeyObject->KeyCellOffset); + HvMarkCellDirty (KeyObject->RegistryHive->Hive, KeyObject->KeyCellOffset); /* Release hive lock */ ExReleaseResourceLite(&CmiRegistryLock); @@ -2467,10 +2367,10 @@ NtQueryMultipleValueKey (IN HANDLE KeyHandle, IN OUT PULONG Length, OUT PULONG ReturnLength) { - PREGISTRY_HIVE RegistryHive; + PEREGISTRY_HIVE RegistryHive; PVALUE_CELL ValueCell; PKEY_OBJECT KeyObject; - PDATA_CELL DataCell; + PVOID DataCell; ULONG BufferLength = 0; PKEY_CELL KeyCell; NTSTATUS Status; @@ -2555,11 +2455,9 @@ NtQueryMultipleValueKey (IN HANDLE KeyHandle, if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET)) { - DataCell = CmiGetCell (RegistryHive, - ValueCell->DataOffset, - NULL); - RtlCopyMemory(DataPtr, - DataCell->Data, + DataCell = HvGetCell (RegistryHive->Hive, + ValueCell->DataOffset); + RtlCopyMemory(DataPtr, DataCell, ValueCell->DataSize & REG_DATA_SIZE_MASK); } else @@ -2623,7 +2521,7 @@ NTSTATUS STDCALL NtSaveKey (IN HANDLE KeyHandle, IN HANDLE FileHandle) { - PREGISTRY_HIVE TempHive; + PEREGISTRY_HIVE TempHive; PKEY_OBJECT KeyObject; NTSTATUS Status; @@ -2653,7 +2551,7 @@ NtSaveKey (IN HANDLE KeyHandle, ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE); /* Refuse to save a volatile key */ - if (KeyObject->RegistryHive == CmiVolatileHive) + if (KeyObject->KeyCell->Flags & REG_KEY_VOLATILE_CELL) { DPRINT1 ("Cannot save a volatile key\n"); ExReleaseResourceLite(&CmiRegistryLock); @@ -2781,8 +2679,8 @@ NtSetInformationKey (IN HANDLE KeyHandle, KeyObject->KeyCell->LastWriteTime.QuadPart = ((PKEY_WRITE_TIME_INFORMATION)KeyInformation)->LastWriteTime.QuadPart; - CmiMarkBlockDirty (KeyObject->RegistryHive, - KeyObject->KeyCellOffset); + HvMarkCellDirty (KeyObject->RegistryHive->Hive, + KeyObject->KeyCellOffset); /* Release hive lock */ ExReleaseResourceLite(&CmiRegistryLock); @@ -2813,7 +2711,7 @@ NtSetInformationKey (IN HANDLE KeyHandle, NTSTATUS STDCALL NtUnloadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes) { - PREGISTRY_HIVE RegistryHive; + PEREGISTRY_HIVE RegistryHive; NTSTATUS Status; PAGED_CODE(); diff --git a/reactos/ntoskrnl/cm/regfile.c b/reactos/ntoskrnl/cm/regfile.c index 289007d0ec4..4975826379a 100644 --- a/reactos/ntoskrnl/cm/regfile.c +++ b/reactos/ntoskrnl/cm/regfile.c @@ -14,402 +14,174 @@ #include "cm.h" - /* uncomment to enable hive checks (incomplete and probably buggy) */ -// #define HIVE_CHECK +//#define HIVE_CHECK /* LOCAL MACROS *************************************************************/ #define ABS_VALUE(V) (((V) < 0) ? -(V) : (V)) -BOOLEAN CmiDoVerify = FALSE; - -static ULONG -CmiCalcChecksum(PULONG Buffer); - /* FUNCTIONS ****************************************************************/ -VOID -CmiCreateDefaultHiveHeader(PHIVE_HEADER Header) +PVOID CMAPI +CmpAllocate( + ULONG Size, + BOOLEAN Paged) { - ASSERT(Header); - RtlZeroMemory(Header, sizeof(HIVE_HEADER)); - Header->BlockId = REG_HIVE_ID; - Header->UpdateCounter1 = 0; - Header->UpdateCounter2 = 0; - Header->DateModified.u.LowPart = 0; - Header->DateModified.u.HighPart = 0; - Header->MajorVersion = 1; - Header->MinorVersion = 3; - Header->Type = 0; - Header->Format = 1; - Header->Unused7 = 1; - Header->RootKeyOffset = (BLOCK_OFFSET)-1; - Header->BlockSize = REG_BLOCK_SIZE; - Header->Checksum = 0; + return ExAllocatePoolWithTag(Paged ? PagedPool : NonPagedPool, + Size, TAG('R','E','G',' ')); +} + +VOID CMAPI +CmpFree( + PVOID Ptr) +{ + ExFreePool(Ptr); } -VOID -CmiCreateDefaultBinHeader(PHBIN BinHeader) +BOOLEAN CMAPI +CmpFileRead( + PREGISTRY_HIVE RegistryHive, + ULONG FileType, + ULONG FileOffset, + PVOID Buffer, + ULONG BufferLength) { - ASSERT(BinHeader); - RtlZeroMemory(BinHeader, sizeof(HBIN)); - BinHeader->HeaderId = REG_BIN_ID; - BinHeader->DateModified.u.LowPart = 0; - BinHeader->DateModified.u.HighPart = 0; - BinHeader->BinSize = REG_BLOCK_SIZE; + PEREGISTRY_HIVE CmHive = RegistryHive->Opaque; + HANDLE HiveHandle = FileType == HV_TYPE_PRIMARY ? CmHive->HiveHandle : CmHive->LogHandle; + LARGE_INTEGER _FileOffset; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + _FileOffset.QuadPart = FileOffset; + Status = ZwReadFile(HiveHandle, 0, 0, 0, &IoStatusBlock, + Buffer, BufferLength, &_FileOffset, 0); + return NT_SUCCESS(Status) ? TRUE : FALSE; } -VOID -CmiCreateDefaultRootKeyCell(PKEY_CELL RootKeyCell) +BOOLEAN CMAPI +CmpFileWrite( + PREGISTRY_HIVE RegistryHive, + ULONG FileType, + ULONG FileOffset, + PVOID Buffer, + ULONG BufferLength) { - ASSERT(RootKeyCell); - RtlZeroMemory(RootKeyCell, sizeof(KEY_CELL)); - RootKeyCell->CellSize = -sizeof(KEY_CELL); - RootKeyCell->Id = REG_KEY_CELL_ID; - RootKeyCell->Flags = REG_KEY_ROOT_CELL | REG_KEY_NAME_PACKED; - KeQuerySystemTime(&RootKeyCell->LastWriteTime); - RootKeyCell->ParentKeyOffset = 0; - RootKeyCell->NumberOfSubKeys = 0; - RootKeyCell->HashTableOffset = -1; - RootKeyCell->NumberOfValues = 0; - RootKeyCell->ValueListOffset = -1; - RootKeyCell->SecurityKeyOffset = 0; - RootKeyCell->ClassNameOffset = -1; - RootKeyCell->NameSize = 0; - RootKeyCell->ClassSize = 0; + PEREGISTRY_HIVE CmHive = RegistryHive->Opaque; + HANDLE HiveHandle = FileType == HV_TYPE_PRIMARY ? CmHive->HiveHandle : CmHive->LogHandle; + LARGE_INTEGER _FileOffset; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + _FileOffset.QuadPart = FileOffset; + Status = ZwWriteFile(HiveHandle, 0, 0, 0, &IoStatusBlock, + Buffer, BufferLength, &_FileOffset, 0); + return NT_SUCCESS(Status) ? TRUE : FALSE; } -VOID -CmiVerifyBinHeader(PHBIN BinHeader) +BOOLEAN CMAPI +CmpFileSetSize( + PREGISTRY_HIVE RegistryHive, + ULONG FileType, + ULONG FileSize) { - if (CmiDoVerify) - { + PEREGISTRY_HIVE CmHive = RegistryHive->Opaque; + HANDLE HiveHandle = FileType == HV_TYPE_PRIMARY ? CmHive->HiveHandle : CmHive->LogHandle; + FILE_END_OF_FILE_INFORMATION EndOfFileInfo; + FILE_ALLOCATION_INFORMATION FileAllocationInfo; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; - ASSERT(BinHeader); + EndOfFileInfo.EndOfFile.QuadPart = FileSize; + Status = ZwSetInformationFile(HiveHandle, &IoStatusBlock, + &EndOfFileInfo, + sizeof(FILE_END_OF_FILE_INFORMATION), + FileEndOfFileInformation); + if (!NT_SUCCESS(Status)) + return FALSE; - if (BinHeader->HeaderId != REG_BIN_ID) - { - DbgPrint("Bin header ID is %.08x (should be %.08x)\n", - BinHeader->HeaderId, REG_BIN_ID); - ASSERT(BinHeader->HeaderId == REG_BIN_ID); - } + FileAllocationInfo.AllocationSize.QuadPart = FileSize; + Status = ZwSetInformationFile(HiveHandle, &IoStatusBlock, + &FileAllocationInfo, + sizeof(FILE_ALLOCATION_INFORMATION), + FileAllocationInformation); + if (!NT_SUCCESS(Status)) + return FALSE; - //BinHeader->DateModified.dwLowDateTime - - //BinHeader->DateModified.dwHighDateTime - - - if (BinHeader->BinSize != REG_BLOCK_SIZE) - { - DbgPrint("BinSize is %.08x (should be a multiple of %.08x)\n", - BinHeader->BinSize, REG_BLOCK_SIZE); - ASSERT(BinHeader->BinSize % REG_BLOCK_SIZE == 0); - } - - } + return TRUE; } -VOID -CmiVerifyKeyCell(PKEY_CELL KeyCell) +BOOLEAN CMAPI +CmpFileFlush( + PREGISTRY_HIVE RegistryHive, + ULONG FileType) { - if (CmiDoVerify) - { + PEREGISTRY_HIVE CmHive = RegistryHive->Opaque; + HANDLE HiveHandle = FileType == HV_TYPE_PRIMARY ? CmHive->HiveHandle : CmHive->LogHandle; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; - ASSERT(KeyCell); - - if (KeyCell->CellSize == 0) - { - DbgPrint("CellSize is %d (must not be 0)\n", - KeyCell->CellSize); - ASSERT(KeyCell->CellSize != 0); - } - - if (KeyCell->Id != REG_KEY_CELL_ID) - { - DbgPrint("Id is %.08x (should be %.08x)\n", - KeyCell->Id, REG_KEY_CELL_ID); - ASSERT(KeyCell->Id == REG_KEY_CELL_ID); - } - - //KeyCell->Flags; - - //KeyCell->LastWriteTime; - - if (KeyCell->ParentKeyOffset < 0) - { - DbgPrint("ParentKeyOffset is %d (must not be < 0)\n", - KeyCell->ParentKeyOffset); - ASSERT(KeyCell->ParentKeyOffset >= 0); - } - - if (KeyCell->NumberOfSubKeys < 0) - { - DbgPrint("NumberOfSubKeys is %d (must not be < 0)\n", - KeyCell->NumberOfSubKeys); - ASSERT(KeyCell->NumberOfSubKeys >= 0); - } - - //KeyCell->HashTableOffset; - - if (KeyCell->NumberOfValues < 0) - { - DbgPrint("NumberOfValues is %d (must not be < 0)\n", - KeyCell->NumberOfValues); - ASSERT(KeyCell->NumberOfValues >= 0); - } - - //KeyCell->ValuesOffset = -1; - - if (KeyCell->SecurityKeyOffset < 0) - { - DbgPrint("SecurityKeyOffset is %d (must not be < 0)\n", - KeyCell->SecurityKeyOffset); - ASSERT(KeyCell->SecurityKeyOffset >= 0); - } - - //KeyCell->ClassNameOffset = -1; - - //KeyCell->NameSize - - //KeyCell->ClassSize - - } -} - - -VOID -CmiVerifyRootKeyCell(PKEY_CELL RootKeyCell) -{ - if (CmiDoVerify) - { - - CmiVerifyKeyCell(RootKeyCell); - - if (!(RootKeyCell->Flags & REG_KEY_ROOT_CELL)) - { - DbgPrint("Flags is %.08x (should be %.08x)\n", - RootKeyCell->Flags, REG_KEY_ROOT_CELL | REG_KEY_NAME_PACKED); - ASSERT(!(RootKeyCell->Flags & (REG_KEY_ROOT_CELL | REG_KEY_NAME_PACKED))); - } - - } -} - - -VOID -CmiVerifyValueCell(PVALUE_CELL ValueCell) -{ - if (CmiDoVerify) - { - - ASSERT(ValueCell); - - if (ValueCell->CellSize == 0) - { - DbgPrint("CellSize is %d (must not be 0)\n", - ValueCell->CellSize); - ASSERT(ValueCell->CellSize != 0); - } - - if (ValueCell->Id != REG_VALUE_CELL_ID) - { - DbgPrint("Id is %.08x (should be %.08x)\n", - ValueCell->Id, REG_VALUE_CELL_ID); - ASSERT(ValueCell->Id == REG_VALUE_CELL_ID); - } - - //ValueCell->NameSize; - //ValueCell->LONG DataSize; - //ValueCell->DataOffset; - //ValueCell->ULONG DataType; - //ValueCell->USHORT Flags; - //ValueCell->USHORT Unused1; - //ValueCell->UCHAR Name[0]; - } -} - - -VOID -CmiVerifyValueListCell(PVALUE_LIST_CELL ValueListCell) -{ - if (CmiDoVerify) - { - - if (ValueListCell->CellSize == 0) - { - DbgPrint("CellSize is %d (must not be 0)\n", - ValueListCell->CellSize); - ASSERT(ValueListCell->CellSize != 0); - } - - } -} - - -VOID -CmiVerifyKeyObject(PKEY_OBJECT KeyObject) -{ - if (CmiDoVerify) - { - - if (KeyObject->RegistryHive == NULL) - { - DbgPrint("RegistryHive is NULL (must not be NULL)\n", - KeyObject->RegistryHive); - ASSERT(KeyObject->RegistryHive != NULL); - } - - if (KeyObject->KeyCell == NULL) - { - DbgPrint("KeyCell is NULL (must not be NULL)\n", - KeyObject->KeyCell); - ASSERT(KeyObject->KeyCell != NULL); - } - - if (KeyObject->ParentKey == NULL) - { - DbgPrint("ParentKey is NULL (must not be NULL)\n", - KeyObject->ParentKey); - ASSERT(KeyObject->ParentKey != NULL); - } - - } -} - - -VOID -CmiVerifyHiveHeader(PHIVE_HEADER Header) -{ - if (CmiDoVerify) - { - - if (Header->BlockId != REG_HIVE_ID) - { - DbgPrint("BlockId is %.08x (must be %.08x)\n", - Header->BlockId, - REG_HIVE_ID); - ASSERT(Header->BlockId == REG_HIVE_ID); - } - - if (Header->MajorVersion != 1) - { - DbgPrint("MajorVersion is %.08x (must be 1)\n", - Header->MajorVersion); - ASSERT(Header->MajorVersion == 1); - } - - if (Header->MinorVersion != 3) - { - DbgPrint("MinorVersion is %.08x (must be 3)\n", - Header->MajorVersion); - ASSERT(Header->MajorVersion == 3); - } - - if (Header->Type != 0) - { - DbgPrint("Type is %.08x (must be 0)\n", - Header->Type); - ASSERT(Header->Type == 0); - } - - if (Header->Format != 1) - { - DbgPrint("Format is %.08x (must be 1)\n", - Header->Format); - ASSERT(Header->Format == 1); - } - - if (Header->Unused7 != 1) - { - DbgPrint("Unused7 is %.08x (must be 1)\n", - Header->Unused7); - ASSERT(Header->Unused7 == 1); - } - - } -} - - -VOID -CmiVerifyRegistryHive(PREGISTRY_HIVE RegistryHive) -{ - if (CmiDoVerify) - { - - CmiVerifyHiveHeader(RegistryHive->HiveHeader); - - } + Status = ZwFlushBuffersFile(HiveHandle, &IoStatusBlock); + return NT_SUCCESS(Status) ? TRUE : FALSE; } static NTSTATUS CmiCreateNewRegFile(HANDLE FileHandle) { - IO_STATUS_BLOCK IoStatusBlock; - PCELL_HEADER FreeCell; - PHIVE_HEADER HiveHeader; - PKEY_CELL RootKeyCell; + EREGISTRY_HIVE CmHive; + PREGISTRY_HIVE Hive; NTSTATUS Status; - PHBIN BinHeader; - PCHAR Buffer; - - Buffer = (PCHAR) ExAllocatePool(NonPagedPool, 2 * REG_BLOCK_SIZE); - if (Buffer == NULL) - return STATUS_INSUFFICIENT_RESOURCES; - - RtlZeroMemory (Buffer, - 2 * REG_BLOCK_SIZE); - - HiveHeader = (PHIVE_HEADER)Buffer; - BinHeader = (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); - CmiCreateDefaultBinHeader(BinHeader); - CmiCreateDefaultRootKeyCell(RootKeyCell); - - /* First block */ - BinHeader->BinOffset = 0; - - /* Offset to root key block */ - HiveHeader->RootKeyOffset = REG_HBIN_DATA_OFFSET; - - /* 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, - Buffer, - 2 * REG_BLOCK_SIZE, - 0, - NULL); - - ExFreePool(Buffer); + CmHive.HiveHandle = FileHandle; + Status = HvInitialize(&Hive, HV_OPERATION_CREATE_HIVE, 0, 0, + CmpAllocate, CmpFree, + CmpFileRead, CmpFileWrite, CmpFileSetSize, + CmpFileFlush, &CmHive); if (!NT_SUCCESS(Status)) { - return(Status); + return FALSE; } - Status = ZwFlushBuffersFile(FileHandle, - &IoStatusBlock); + /* Init root key cell */ + if (!CmCreateRootNode(Hive, L"")) + { + HvFree (Hive); + return FALSE; + } + + Status = HvWriteHive(Hive) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; + + HvFree (Hive); return(Status); } #ifdef HIVE_CHECK + +static ULONG +CmiCalcChecksum(PULONG Buffer) +{ + ULONG Sum = 0; + ULONG i; + + for (i = 0; i < 127; i++) + Sum ^= Buffer[i]; + if (Sum == (ULONG)-1) + Sum = (ULONG)-2; + if (Sum == 0) + Sum = 1; + + return(Sum); +} + static NTSTATUS -CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive) +CmiCheckAndFixHive(PEREGISTRY_HIVE RegistryHive) { OBJECT_ATTRIBUTES ObjectAttributes; FILE_STANDARD_INFORMATION fsi; @@ -514,7 +286,7 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive) if (LogHandle == INVALID_HANDLE_VALUE) { if (HiveHeader->Checksum != CmiCalcChecksum((PULONG)HiveHeader) || - HiveHeader->UpdateCounter1 != HiveHeader->UpdateCounter2) + HiveHeader->Sequence1 != HiveHeader->Sequence2) { /* There is no way to fix the hive without log file - BSOD! */ DPRINT("Hive header inconsistent and no log file available!\n"); @@ -528,7 +300,7 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive) { /* Allocate hive header */ LogHeader = ExAllocatePool(PagedPool, - sizeof(HIVE_HEADER)); + HV_LOG_HEADER_SIZE); if (LogHeader == NULL) { DPRINT("ExAllocatePool() failed\n"); @@ -544,7 +316,7 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive) 0, &IoStatusBlock, LogHeader, - sizeof(HIVE_HEADER), + HV_LOG_HEADER_SIZE, &FileOffset, 0); if (!NT_SUCCESS(Status)) @@ -555,10 +327,10 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive) /* Check log file header integrity */ if (LogHeader->Checksum != CmiCalcChecksum((PULONG)LogHeader) || - LogHeader->UpdateCounter1 != LogHeader->UpdateCounter2) + LogHeader->Sequence1 != LogHeader->Sequence2) { if (HiveHeader->Checksum != CmiCalcChecksum((PULONG)HiveHeader) || - HiveHeader->UpdateCounter1 != HiveHeader->UpdateCounter2) + HiveHeader->Sequence1 != HiveHeader->Sequence2) { DPRINT("Hive file and log file are inconsistent!\n"); KEBUGCHECK(CONFIG_LIST_FAILED); @@ -569,8 +341,8 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive) goto ByeBye; } - if (HiveHeader->UpdateCounter1 == HiveHeader->UpdateCounter2 && - HiveHeader->UpdateCounter1 == LogHeader->UpdateCounter1) + if (HiveHeader->Sequence1 == HiveHeader->Sequence2 && + HiveHeader->Sequence1 == LogHeader->Sequence1) { /* Hive and log file are up-to-date */ Status = STATUS_SUCCESS; @@ -595,11 +367,9 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive) FileSize = fsi.EndOfFile.u.LowPart; /* Calculate bitmap and block size */ - BitmapSize = ROUND_UP((FileSize / REG_BLOCK_SIZE) - 1, sizeof(ULONG) * 8) / 8; - BufferSize = sizeof(HIVE_HEADER) + - sizeof(ULONG) + - BitmapSize; - BufferSize = ROUND_UP(BufferSize, REG_BLOCK_SIZE); + BitmapSize = ROUND_UP((FileSize / HV_BLOCK_SIZE) - 1, sizeof(ULONG) * 8) / 8; + BufferSize = HV_LOG_HEADER_SIZE + sizeof(ULONG) + BitmapSize; + BufferSize = ROUND_UP(BufferSize, HV_BLOCK_SIZE); /* Reallocate log header block */ ExFreePool(LogHeader); @@ -631,7 +401,7 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive) /* Initialize bitmap */ RtlInitializeBitMap(&BlockBitMap, - (PVOID)((ULONG_PTR)LogHeader + REG_BLOCK_SIZE + sizeof(ULONG)), + (PVOID)((ULONG_PTR)LogHeader + HV_BLOCK_SIZE + sizeof(ULONG)), BitmapSize * 8); /* FIXME: Update dirty blocks */ @@ -661,201 +431,8 @@ ByeBye: } #endif - -NTSTATUS -CmiImportHiveBins(PREGISTRY_HIVE Hive, - PUCHAR ChunkPtr) -{ - BLOCK_OFFSET BlockOffset; - ULONG BlockIndex; - PHBIN Bin; - ULONG j; - - BlockIndex = 0; - BlockOffset = 0; - while (BlockIndex < Hive->BlockListSize) - { - Bin = (PHBIN)((ULONG_PTR)ChunkPtr + BlockOffset); - - if (Bin->HeaderId != REG_BIN_ID) - { - DPRINT1 ("Bad bin header id %x, offset %x\n", Bin->HeaderId, BlockOffset); - return STATUS_REGISTRY_CORRUPT; - } - - ASSERTMSG("Bin size must be multiple of 4K\n", - (Bin->BinSize % REG_BLOCK_SIZE) == 0); - - /* Allocate the hive block */ - Hive->BlockList[BlockIndex].Bin = ExAllocatePool (PagedPool, - Bin->BinSize); - if (Hive->BlockList[BlockIndex].Bin == NULL) - { - DPRINT1 ("ExAllocatePool() failed\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - Hive->BlockList[BlockIndex].Block = (PVOID)Hive->BlockList[BlockIndex].Bin; - - /* Import the Bin */ - RtlCopyMemory (Hive->BlockList[BlockIndex].Bin, - Bin, - Bin->BinSize); - - if (Bin->BinSize > REG_BLOCK_SIZE) - { - for (j = 1; j < Bin->BinSize / REG_BLOCK_SIZE; j++) - { - Hive->BlockList[BlockIndex + j].Bin = Hive->BlockList[BlockIndex].Bin; - Hive->BlockList[BlockIndex + j].Block = - (PVOID)((ULONG_PTR)Hive->BlockList[BlockIndex].Bin + (j * REG_BLOCK_SIZE)); - } - } - - BlockIndex += Bin->BinSize / REG_BLOCK_SIZE; - BlockOffset += Bin->BinSize; - } - - return STATUS_SUCCESS; -} - - -VOID -CmiFreeHiveBins (PREGISTRY_HIVE Hive) -{ - ULONG i; - PHBIN Bin; - - Bin = NULL; - for (i = 0; i < Hive->BlockListSize; i++) - { - if (Hive->BlockList[i].Bin == NULL) - continue; - - if (Hive->BlockList[i].Bin != Bin) - { - Bin = Hive->BlockList[i].Bin; - ExFreePool (Hive->BlockList[i].Bin); - } - Hive->BlockList[i].Bin = NULL; - Hive->BlockList[i].Block = NULL; - } -} - - -NTSTATUS -CmiCreateHiveFreeCellList(PREGISTRY_HIVE Hive) -{ - BLOCK_OFFSET BlockOffset; - PCELL_HEADER FreeBlock; - ULONG BlockIndex; - ULONG FreeOffset; - PHBIN Bin; - NTSTATUS Status; - - /* Initialize the free cell list */ - Hive->FreeListSize = 0; - Hive->FreeListMax = 0; - Hive->FreeList = NULL; - Hive->FreeListOffset = NULL; - - BlockOffset = 0; - BlockIndex = 0; - while (BlockIndex < Hive->BlockListSize) - { - Bin = Hive->BlockList[BlockIndex].Bin; - - /* Search free blocks and add to list */ - FreeOffset = REG_HBIN_DATA_OFFSET; - while (FreeOffset < Bin->BinSize) - { - FreeBlock = (PCELL_HEADER) ((ULONG_PTR) Bin + FreeOffset); - if (FreeBlock->CellSize > 0) - { - Status = CmiAddFree(Hive, - FreeBlock, - Bin->BinOffset + FreeOffset, - FALSE); - - if (!NT_SUCCESS(Status)) - { - return Status; - } - - FreeOffset += FreeBlock->CellSize; - } - else if (FreeBlock->CellSize < 0) - { - FreeOffset -= FreeBlock->CellSize; - } - else - { -#ifdef HIVE_CHECK - /* Check and eventually fix a hive */ - Status = CmiCheckAndFixHive(Hive); - if (!NT_SUCCESS(Status)) - { - DPRINT1("CmiCheckAndFixHive() failed (Status %lx)\n", Status); - return(Status); - } -#else - break; -#endif - } - } - - BlockIndex += Bin->BinSize / REG_BLOCK_SIZE; - BlockOffset += Bin->BinSize; - } - - return STATUS_SUCCESS; -} - - -VOID -CmiFreeHiveFreeCellList(PREGISTRY_HIVE Hive) -{ - ExFreePool (Hive->FreeList); - ExFreePool (Hive->FreeListOffset); - - Hive->FreeListSize = 0; - Hive->FreeListMax = 0; - Hive->FreeList = NULL; - Hive->FreeListOffset = NULL; -} - - -NTSTATUS -CmiCreateHiveBitmap(PREGISTRY_HIVE Hive) -{ - ULONG BitmapSize; - - /* Calculate bitmap size in bytes (always a multiple of 32 bits) */ - BitmapSize = ROUND_UP(Hive->BlockListSize, sizeof(ULONG) * 8) / 8; - DPRINT("Hive->BlockListSize: %lu\n", Hive->BlockListSize); - DPRINT("BitmapSize: %lu Bytes %lu Bits\n", BitmapSize, BitmapSize * 8); - - /* Allocate bitmap */ - Hive->BitmapBuffer = (PULONG)ExAllocatePool(PagedPool, - BitmapSize); - if (Hive->BitmapBuffer == NULL) - { - return STATUS_INSUFFICIENT_RESOURCES; - } - - RtlInitializeBitMap(&Hive->DirtyBitMap, - Hive->BitmapBuffer, - BitmapSize * 8); - - /* Initialize bitmap */ - RtlClearAllBits(&Hive->DirtyBitMap); - Hive->HiveDirty = FALSE; - - return STATUS_SUCCESS; -} - - static NTSTATUS -CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive, +CmiInitNonVolatileRegistryHive (PEREGISTRY_HIVE RegistryHive, PWSTR Filename) { OBJECT_ATTRIBUTES ObjectAttributes; @@ -988,37 +565,14 @@ CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive, } DPRINT("ViewBase %p ViewSize %lx\n", ViewBase, ViewSize); - /* Copy hive header and initalize hive */ - RtlCopyMemory (RegistryHive->HiveHeader, - ViewBase, - sizeof(HIVE_HEADER)); - RegistryHive->FileSize = ViewSize; - RegistryHive->BlockListSize = (RegistryHive->FileSize / REG_BLOCK_SIZE) - 1; - RegistryHive->UpdateCounter = RegistryHive->HiveHeader->UpdateCounter1; - - /* Allocate hive block list */ - RegistryHive->BlockList = ExAllocatePool(NonPagedPool, - RegistryHive->BlockListSize * sizeof(BLOCK_LIST_ENTRY)); - if (RegistryHive->BlockList == NULL) - { - DPRINT1("Failed to allocate the hive block list\n"); - MmUnmapViewOfSection(PsGetCurrentProcess(), - ViewBase); - ObDereferenceObject(SectionObject); - RtlFreeUnicodeString(&RegistryHive->HiveFileName); - RtlFreeUnicodeString(&RegistryHive->LogFileName); - ZwClose(FileHandle); - return STATUS_INSUFFICIENT_RESOURCES; - } - RtlZeroMemory (RegistryHive->BlockList, - RegistryHive->BlockListSize * sizeof(BLOCK_LIST_ENTRY)); - - /* Import the hive bins */ - Status = CmiImportHiveBins (RegistryHive, - ViewBase + REG_BLOCK_SIZE); + Status = HvInitialize(&RegistryHive->Hive, HV_OPERATION_MEMORY, + (ULONG_PTR)ViewBase, ViewSize, + CmpAllocate, CmpFree, + CmpFileRead, CmpFileWrite, CmpFileSetSize, + CmpFileFlush, RegistryHive); if (!NT_SUCCESS(Status)) { - ExFreePool(RegistryHive->BlockList); + DPRINT1("Failed to open hive\n"); MmUnmapViewOfSection(PsGetCurrentProcess(), ViewBase); ObDereferenceObject(SectionObject); @@ -1028,6 +582,8 @@ CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive, return Status; } + CmPrepareHive(RegistryHive->Hive); + /* Unmap and dereference the hive section */ MmUnmapViewOfSection(PsGetCurrentProcess(), ViewBase); @@ -1036,29 +592,6 @@ CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive, /* Close the hive file */ ZwClose(FileHandle); - /* Initialize the free cell list */ - Status = CmiCreateHiveFreeCellList (RegistryHive); - if (!NT_SUCCESS(Status)) - { - CmiFreeHiveBins(RegistryHive); - ExFreePool(RegistryHive->BlockList); - RtlFreeUnicodeString(&RegistryHive->HiveFileName); - RtlFreeUnicodeString(&RegistryHive->LogFileName); - return Status; - } - - /* Create the block bitmap */ - Status = CmiCreateHiveBitmap (RegistryHive); - if (!NT_SUCCESS(Status)) - { - CmiFreeHiveFreeCellList(RegistryHive); - CmiFreeHiveBins(RegistryHive); - ExFreePool(RegistryHive->BlockList); - RtlFreeUnicodeString(&RegistryHive->HiveFileName); - RtlFreeUnicodeString(&RegistryHive->LogFileName); - return Status; - } - DPRINT("CmiInitNonVolatileRegistryHive(%p, %S) - Finished.\n", RegistryHive, Filename); @@ -1067,48 +600,41 @@ CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive, NTSTATUS -CmiCreateVolatileHive(PREGISTRY_HIVE *RegistryHive) +CmiCreateTempHive(PEREGISTRY_HIVE *RegistryHive) { - PKEY_CELL RootKeyCell; - PREGISTRY_HIVE Hive; + PEREGISTRY_HIVE Hive; + NTSTATUS Status; *RegistryHive = NULL; Hive = ExAllocatePool (NonPagedPool, - sizeof(REGISTRY_HIVE)); + sizeof(EREGISTRY_HIVE)); if (Hive == NULL) return STATUS_INSUFFICIENT_RESOURCES; RtlZeroMemory (Hive, - sizeof(REGISTRY_HIVE)); + sizeof(EREGISTRY_HIVE)); DPRINT("Hive 0x%p\n", Hive); - Hive->HiveHeader = (PHIVE_HEADER)ExAllocatePool (NonPagedPool, - sizeof(HIVE_HEADER)); - if (Hive->HiveHeader == NULL) + Status = HvInitialize(&Hive->Hive, HV_OPERATION_CREATE_HIVE, 0, 0, + CmpAllocate, CmpFree, + CmpFileRead, CmpFileWrite, CmpFileSetSize, + CmpFileFlush, Hive); + if (!NT_SUCCESS(Status)) { + ExFreePool (Hive); + return Status; + } + + if (!CmCreateRootNode (Hive->Hive, L"")) + { + HvFree (Hive->Hive); ExFreePool (Hive); return STATUS_INSUFFICIENT_RESOURCES; } - RtlZeroMemory (Hive->HiveHeader, - sizeof(HIVE_HEADER)); - Hive->Flags = (HIVE_NO_FILE | HIVE_POINTER); - - CmiCreateDefaultHiveHeader (Hive->HiveHeader); - - RootKeyCell = (PKEY_CELL)ExAllocatePool (NonPagedPool, - sizeof(KEY_CELL)); - if (RootKeyCell == NULL) - { - ExFreePool(Hive->HiveHeader); - ExFreePool(Hive); - return STATUS_INSUFFICIENT_RESOURCES; - } - - CmiCreateDefaultRootKeyCell (RootKeyCell); - Hive->HiveHeader->RootKeyOffset = (BLOCK_OFFSET)RootKeyCell; + Hive->Flags = HIVE_NO_FILE; /* Acquire hive list lock exclusively */ KeEnterCriticalRegion(); @@ -1131,123 +657,10 @@ CmiCreateVolatileHive(PREGISTRY_HIVE *RegistryHive) NTSTATUS -CmiCreateTempHive(PREGISTRY_HIVE *RegistryHive) +CmiCreateVolatileHive(PEREGISTRY_HIVE *RegistryHive) { - PHBIN BinHeader; - PCELL_HEADER FreeCell; - PREGISTRY_HIVE Hive; - NTSTATUS Status; - - DPRINT ("CmiCreateTempHive() called\n"); - - *RegistryHive = NULL; - - Hive = ExAllocatePool (NonPagedPool, - sizeof(REGISTRY_HIVE)); - if (Hive == NULL) - { - DPRINT1 ("Failed to allocate registry hive block\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - RtlZeroMemory (Hive, - sizeof(REGISTRY_HIVE)); - - DPRINT ("Hive 0x%p\n", Hive); - - Hive->HiveHeader = (PHIVE_HEADER)ExAllocatePool (NonPagedPool, - REG_BLOCK_SIZE); - if (Hive->HiveHeader == NULL) - { - DPRINT1 ("Failed to allocate hive header block\n"); - ExFreePool (Hive); - return STATUS_INSUFFICIENT_RESOURCES; - } - RtlZeroMemory (Hive->HiveHeader, - REG_BLOCK_SIZE); - - DPRINT ("HiveHeader 0x%p\n", Hive->HiveHeader); - - Hive->Flags = HIVE_NO_FILE; - - RtlInitUnicodeString (&Hive->HiveFileName, - NULL); - RtlInitUnicodeString (&Hive->LogFileName, - NULL); - - CmiCreateDefaultHiveHeader (Hive->HiveHeader); - - /* Allocate hive block list */ - Hive->BlockList = ExAllocatePool (NonPagedPool, - sizeof(BLOCK_LIST_ENTRY)); - if (Hive->BlockList == NULL) - { - DPRINT1 ("Failed to allocate hive block list\n"); - ExFreePool(Hive->HiveHeader); - ExFreePool(Hive); - return STATUS_INSUFFICIENT_RESOURCES; - } - - /* Allocate first Bin */ - Hive->BlockList[0].Bin = ExAllocatePool (NonPagedPool, - REG_BLOCK_SIZE); - if (Hive->BlockList[0].Bin == NULL) - { - DPRINT1 ("Failed to allocate first bin\n"); - ExFreePool(Hive->BlockList); - ExFreePool(Hive->HiveHeader); - ExFreePool(Hive); - return STATUS_INSUFFICIENT_RESOURCES; - } - Hive->BlockList[0].Block = (PVOID)Hive->BlockList[0].Bin; - - Hive->FileSize = 2* REG_BLOCK_SIZE; - Hive->BlockListSize = 1; - Hive->UpdateCounter = Hive->HiveHeader->UpdateCounter1; - - - BinHeader = Hive->BlockList[0].Bin; - FreeCell = (PCELL_HEADER)((ULONG_PTR)BinHeader + REG_HBIN_DATA_OFFSET); - - CmiCreateDefaultBinHeader (BinHeader); - - /* First block */ - BinHeader->BinOffset = 0; - - /* Offset to root key block */ - Hive->HiveHeader->RootKeyOffset = (BLOCK_OFFSET)-1; - - /* The rest of the block is free */ - FreeCell->CellSize = REG_BLOCK_SIZE - REG_HBIN_DATA_OFFSET; - - /* Create the free cell list */ - Status = CmiCreateHiveFreeCellList (Hive); - if (Hive->BlockList[0].Bin == NULL) - { - DPRINT1 ("CmiCreateHiveFreeCellList() failed (Status %lx)\n", Status); - ExFreePool(Hive->BlockList[0].Bin); - ExFreePool(Hive->BlockList); - ExFreePool(Hive->HiveHeader); - ExFreePool(Hive); - return Status; - } - - /* Acquire hive list lock exclusively */ - KeEnterCriticalRegion(); - ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE); - - /* Add the new hive to the hive list */ - InsertTailList (&CmiHiveListHead, - &Hive->HiveList); - - /* Release hive list lock */ - ExReleaseResourceLite(&CmiRegistryLock); - KeLeaveCriticalRegion(); - - VERIFY_REGISTRY_HIVE (Hive); - - *RegistryHive = Hive; - - return STATUS_SUCCESS; + DPRINT ("CmiCreateVolatileHive() called\n"); + return CmiCreateTempHive(RegistryHive); } @@ -1256,7 +669,7 @@ CmiLoadHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes, IN PUNICODE_STRING FileName, IN ULONG Flags) { - PREGISTRY_HIVE Hive; + PEREGISTRY_HIVE Hive; NTSTATUS Status; DPRINT ("CmiLoadHive(Filename %wZ)\n", FileName); @@ -1265,36 +678,24 @@ CmiLoadHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes, return STATUS_INVALID_PARAMETER; Hive = ExAllocatePool (NonPagedPool, - sizeof(REGISTRY_HIVE)); + sizeof(EREGISTRY_HIVE)); if (Hive == NULL) { DPRINT1 ("Failed to allocate hive header.\n"); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory (Hive, - sizeof(REGISTRY_HIVE)); + sizeof(EREGISTRY_HIVE)); DPRINT ("Hive 0x%p\n", Hive); Hive->Flags = (Flags & REG_NO_LAZY_FLUSH) ? HIVE_NO_SYNCH : 0; - Hive->HiveHeader = (PHIVE_HEADER)ExAllocatePool(NonPagedPool, - sizeof(HIVE_HEADER)); - if (Hive->HiveHeader == NULL) - { - DPRINT1 ("Failed to allocate hive header.\n"); - ExFreePool (Hive); - return STATUS_INSUFFICIENT_RESOURCES; - } - - RtlZeroMemory (Hive->HiveHeader, - sizeof(HIVE_HEADER)); - Status = CmiInitNonVolatileRegistryHive (Hive, FileName->Buffer); if (!NT_SUCCESS (Status)) { DPRINT1 ("CmiInitNonVolatileRegistryHive() failed (Status %lx)\n", Status); - ExFreePool (Hive->HiveHeader); + HvFree (Hive->Hive); ExFreePool (Hive); return Status; } @@ -1320,11 +721,8 @@ CmiLoadHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes, NTSTATUS -CmiRemoveRegistryHive(PREGISTRY_HIVE RegistryHive) +CmiRemoveRegistryHive(PEREGISTRY_HIVE RegistryHive) { - if (RegistryHive->Flags & HIVE_POINTER) - return STATUS_UNSUCCESSFUL; - /* Remove hive from hive list */ RemoveEntryList (&RegistryHive->HiveList); @@ -1332,90 +730,49 @@ CmiRemoveRegistryHive(PREGISTRY_HIVE RegistryHive) RtlFreeUnicodeString (&RegistryHive->HiveFileName); RtlFreeUnicodeString (&RegistryHive->LogFileName); - /* Release hive bitmap */ - ExFreePool (RegistryHive->BitmapBuffer); - - /* Release free cell list */ - ExFreePool (RegistryHive->FreeList); - ExFreePool (RegistryHive->FreeListOffset); - - /* Release bins and bin list */ - CmiFreeHiveBins (RegistryHive); - ExFreePool (RegistryHive->BlockList); - - /* Release hive header */ - ExFreePool (RegistryHive->HiveHeader); - /* Release hive */ - ExFreePool (RegistryHive); + HvFree (RegistryHive->Hive); return STATUS_SUCCESS; } -static ULONG -CmiCalcChecksum(PULONG Buffer) +NTSTATUS +CmOpenHiveFiles(PEREGISTRY_HIVE RegistryHive) { - ULONG Sum = 0; - ULONG i; - - for (i = 0; i < 127; i++) - Sum ^= Buffer[i]; - if (Sum == (ULONG)-1) - Sum = (ULONG)-2; - if (Sum == 0) - Sum = 1; - - return(Sum); -} - - -static NTSTATUS -CmiStartLogUpdate(PREGISTRY_HIVE RegistryHive) -{ - FILE_END_OF_FILE_INFORMATION EndOfFileInfo; - FILE_ALLOCATION_INFORMATION FileAllocationInfo; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; - HANDLE FileHandle; - LARGE_INTEGER FileOffset; - ULONG BufferSize; - ULONG BitmapSize; - PUCHAR Buffer; - PUCHAR Ptr; - ULONG BlockIndex; - ULONG LastIndex; - PVOID BlockPtr; NTSTATUS Status; - DPRINT("CmiStartLogUpdate() called\n"); + InitializeObjectAttributes(&ObjectAttributes, + &RegistryHive->HiveFileName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); - BitmapSize = ROUND_UP(RegistryHive->BlockListSize, sizeof(ULONG) * 8) / 8; - BufferSize = sizeof(HIVE_HEADER) + - sizeof(ULONG) + - BitmapSize; - BufferSize = ROUND_UP(BufferSize, REG_BLOCK_SIZE); - - DPRINT("Bitmap size %lu buffer size: %lu\n", BitmapSize, BufferSize); - - Buffer = (PUCHAR)ExAllocatePool(NonPagedPool, - BufferSize); - if (Buffer == NULL) + Status = ZwCreateFile(&RegistryHive->HiveHandle, + 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)) { - DPRINT("ExAllocatePool() failed\n"); - return(STATUS_INSUFFICIENT_RESOURCES); + return(Status); } - RtlZeroMemory (Buffer, - BufferSize); - /* Open log file for writing */ InitializeObjectAttributes(&ObjectAttributes, &RegistryHive->LogFileName, OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = ZwCreateFile(&FileHandle, + Status = ZwCreateFile(&RegistryHive->LogHandle, FILE_ALL_ACCESS, &ObjectAttributes, &IoStatusBlock, @@ -1428,612 +785,63 @@ CmiStartLogUpdate(PREGISTRY_HIVE RegistryHive) 0); if (!NT_SUCCESS(Status)) { - DPRINT("ZwCreateFile() failed (Status %lx)\n", Status); - ExFreePool(Buffer); + ZwClose(RegistryHive->HiveHandle); return(Status); } - /* Update firt update counter and checksum */ - RegistryHive->HiveHeader->UpdateCounter1 = RegistryHive->UpdateCounter + 1; - RegistryHive->HiveHeader->Checksum = CmiCalcChecksum((PULONG)RegistryHive->HiveHeader); - - /* Copy hive header */ - RtlCopyMemory(Buffer, - RegistryHive->HiveHeader, - sizeof(HIVE_HEADER)); - Ptr = Buffer + sizeof(HIVE_HEADER); - - RtlCopyMemory(Ptr, - "DIRT", - 4); - Ptr += 4; - RtlCopyMemory(Ptr, - RegistryHive->DirtyBitMap.Buffer, - BitmapSize); - - /* Write hive block and block bitmap */ - FileOffset.QuadPart = (ULONGLONG)0; - Status = ZwWriteFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - Buffer, - BufferSize, - &FileOffset, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwWriteFile() failed (Status %lx)\n", Status); - ZwClose(FileHandle); - ExFreePool(Buffer); - return(Status); - } - ExFreePool(Buffer); - - /* Write dirty blocks */ - FileOffset.QuadPart = (ULONGLONG)BufferSize; - BlockIndex = 0; - while (BlockIndex < RegistryHive->BlockListSize) - { - LastIndex = BlockIndex; - BlockIndex = RtlFindSetBits(&RegistryHive->DirtyBitMap, - 1, - BlockIndex); - if (BlockIndex == (ULONG)-1 || BlockIndex < LastIndex) - { - DPRINT("No more set bits\n"); - Status = STATUS_SUCCESS; - break; - } - - DPRINT("Block %lu is dirty\n", BlockIndex); - - BlockPtr = RegistryHive->BlockList[BlockIndex].Block; - DPRINT("BlockPtr %p\n", BlockPtr); - DPRINT("File offset %I64x\n", FileOffset.QuadPart); - - /* Write hive block */ - Status = ZwWriteFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - BlockPtr, - REG_BLOCK_SIZE, - &FileOffset, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("ZwWriteFile() failed (Status %lx)\n", Status); - ZwClose(FileHandle); - return(Status); - } - - BlockIndex++; - FileOffset.QuadPart += (ULONGLONG)REG_BLOCK_SIZE; - } - - /* Truncate log file */ - EndOfFileInfo.EndOfFile.QuadPart = FileOffset.QuadPart; - Status = ZwSetInformationFile(FileHandle, - &IoStatusBlock, - &EndOfFileInfo, - sizeof(FILE_END_OF_FILE_INFORMATION), - FileEndOfFileInformation); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwSetInformationFile() failed (Status %lx)\n", Status); - ZwClose(FileHandle); - return(Status); - } - - FileAllocationInfo.AllocationSize.QuadPart = FileOffset.QuadPart; - Status = ZwSetInformationFile(FileHandle, - &IoStatusBlock, - &FileAllocationInfo, - sizeof(FILE_ALLOCATION_INFORMATION), - FileAllocationInformation); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwSetInformationFile() failed (Status %lx)\n", Status); - ZwClose(FileHandle); - return(Status); - } - - /* Flush the log file */ - Status = ZwFlushBuffersFile(FileHandle, - &IoStatusBlock); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwFlushBuffersFile() failed (Status %lx)\n", Status); - } - - ZwClose(FileHandle); - - return(Status); + return STATUS_SUCCESS; } -static NTSTATUS -CmiFinishLogUpdate(PREGISTRY_HIVE RegistryHive) +VOID +CmCloseHiveFiles(PEREGISTRY_HIVE RegistryHive) { - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - HANDLE FileHandle; - LARGE_INTEGER FileOffset; - ULONG BufferSize; - ULONG BitmapSize; - PUCHAR Buffer; - PUCHAR Ptr; - NTSTATUS Status; - - DPRINT("CmiFinishLogUpdate() called\n"); - - BitmapSize = ROUND_UP(RegistryHive->BlockListSize, sizeof(ULONG) * 8) / 8; - BufferSize = sizeof(HIVE_HEADER) + - sizeof(ULONG) + - BitmapSize; - BufferSize = ROUND_UP(BufferSize, REG_BLOCK_SIZE); - - DPRINT("Bitmap size %lu buffer size: %lu\n", BitmapSize, BufferSize); - - Buffer = (PUCHAR)ExAllocatePool(NonPagedPool, BufferSize); - if (Buffer == NULL) - { - DPRINT("ExAllocatePool() failed\n"); - return(STATUS_INSUFFICIENT_RESOURCES); - } - - /* Open log file for writing */ - InitializeObjectAttributes(&ObjectAttributes, - &RegistryHive->LogFileName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = ZwCreateFile(&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)) - { - DPRINT("ZwCreateFile() failed (Status %lx)\n", Status); - ExFreePool(Buffer); - return(Status); - } - - /* Update first and second update counter and checksum */ - RegistryHive->HiveHeader->UpdateCounter1 = RegistryHive->UpdateCounter + 1; - RegistryHive->HiveHeader->UpdateCounter2 = RegistryHive->UpdateCounter + 1; - RegistryHive->HiveHeader->Checksum = CmiCalcChecksum((PULONG)RegistryHive->HiveHeader); - - /* Copy hive header */ - RtlCopyMemory(Buffer, - RegistryHive->HiveHeader, - sizeof(HIVE_HEADER)); - Ptr = Buffer + sizeof(HIVE_HEADER); - - /* Write empty block bitmap */ - RtlCopyMemory(Ptr, - "DIRT", - 4); - Ptr += 4; - RtlZeroMemory(Ptr, - BitmapSize); - - /* Write hive block and block bitmap */ - FileOffset.QuadPart = (ULONGLONG)0; - Status = ZwWriteFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - Buffer, - BufferSize, - &FileOffset, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwWriteFile() failed (Status %lx)\n", Status); - ZwClose(FileHandle); - ExFreePool(Buffer); - return(Status); - } - - ExFreePool(Buffer); - - /* Flush the log file */ - Status = ZwFlushBuffersFile(FileHandle, - &IoStatusBlock); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwFlushBuffersFile() failed (Status %lx)\n", Status); - } - - ZwClose(FileHandle); - - return(Status); -} - - -static NTSTATUS -CmiCleanupLogUpdate(PREGISTRY_HIVE RegistryHive) -{ - FILE_END_OF_FILE_INFORMATION EndOfFileInfo; - FILE_ALLOCATION_INFORMATION FileAllocationInfo; - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - HANDLE FileHandle; - ULONG BufferSize; - ULONG BitmapSize; - NTSTATUS Status; - - DPRINT("CmiCleanupLogUpdate() called\n"); - - BitmapSize = ROUND_UP(RegistryHive->BlockListSize, sizeof(ULONG) * 8) / 8; - BufferSize = sizeof(HIVE_HEADER) + - sizeof(ULONG) + - BitmapSize; - BufferSize = ROUND_UP(BufferSize, REG_BLOCK_SIZE); - - DPRINT("Bitmap size %lu buffer size: %lu\n", BitmapSize, BufferSize); - - /* Open log file for writing */ - InitializeObjectAttributes(&ObjectAttributes, - &RegistryHive->LogFileName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = ZwCreateFile(&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)) - { - DPRINT("ZwCreateFile() failed (Status %lx)\n", Status); - return(Status); - } - - /* Truncate log file */ - EndOfFileInfo.EndOfFile.QuadPart = (ULONGLONG)BufferSize; - Status = ZwSetInformationFile(FileHandle, - &IoStatusBlock, - &EndOfFileInfo, - sizeof(FILE_END_OF_FILE_INFORMATION), - FileEndOfFileInformation); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwSetInformationFile() failed (Status %lx)\n", Status); - ZwClose(FileHandle); - return(Status); - } - - FileAllocationInfo.AllocationSize.QuadPart = (ULONGLONG)BufferSize; - Status = ZwSetInformationFile(FileHandle, - &IoStatusBlock, - &FileAllocationInfo, - sizeof(FILE_ALLOCATION_INFORMATION), - FileAllocationInformation); - if (!NT_SUCCESS(Status)) - { - DPRINT("NtSetInformationFile() failed (Status %lx)\n", Status); - ZwClose(FileHandle); - return(Status); - } - - /* Flush the log file */ - Status = ZwFlushBuffersFile(FileHandle, - &IoStatusBlock); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwFlushBuffersFile() failed (Status %lx)\n", Status); - } - - ZwClose(FileHandle); - - return(Status); -} - - -static NTSTATUS -CmiStartHiveUpdate(PREGISTRY_HIVE RegistryHive) -{ - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - HANDLE FileHandle; - LARGE_INTEGER FileOffset; - ULONG BlockIndex; - ULONG LastIndex; - PVOID BlockPtr; - NTSTATUS Status; - - DPRINT("CmiStartHiveUpdate() called\n"); - - /* Open hive for writing */ - InitializeObjectAttributes(&ObjectAttributes, - &RegistryHive->HiveFileName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = ZwCreateFile(&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)) - { - DPRINT("ZwCreateFile() failed (Status %lx)\n", Status); - return(Status); - } - - /* Update firt update counter and checksum */ - RegistryHive->HiveHeader->UpdateCounter1 = RegistryHive->UpdateCounter + 1; - RegistryHive->HiveHeader->Checksum = CmiCalcChecksum((PULONG)RegistryHive->HiveHeader); - - /* Write hive block */ - FileOffset.QuadPart = (ULONGLONG)0; - Status = ZwWriteFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - RegistryHive->HiveHeader, - sizeof(HIVE_HEADER), - &FileOffset, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwWriteFile() failed (Status %lx)\n", Status); - ZwClose(FileHandle); - return(Status); - } - - BlockIndex = 0; - while (BlockIndex < RegistryHive->BlockListSize) - { - LastIndex = BlockIndex; - BlockIndex = RtlFindSetBits(&RegistryHive->DirtyBitMap, - 1, - BlockIndex); - if (BlockIndex == (ULONG)-1 || BlockIndex < LastIndex) - { - DPRINT("No more set bits\n"); - Status = STATUS_SUCCESS; - break; - } - - DPRINT("Block %lu is dirty\n", BlockIndex); - - BlockPtr = RegistryHive->BlockList[BlockIndex].Block; - DPRINT(" BlockPtr %p\n", BlockPtr); - - FileOffset.QuadPart = (ULONGLONG)(BlockIndex + 1) * (ULONGLONG)REG_BLOCK_SIZE; - DPRINT(" File offset %I64x\n", FileOffset.QuadPart); - - /* Write hive block */ - Status = ZwWriteFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - BlockPtr, - REG_BLOCK_SIZE, - &FileOffset, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwWriteFile() failed (Status %lx)\n", Status); - ZwClose(FileHandle); - return(Status); - } - - BlockIndex++; - } - - Status = ZwFlushBuffersFile(FileHandle, - &IoStatusBlock); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwFlushBuffersFile() failed (Status %lx)\n", Status); - } - - ZwClose(FileHandle); - - return(Status); -} - - -static NTSTATUS -CmiFinishHiveUpdate(PREGISTRY_HIVE RegistryHive) -{ - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - LARGE_INTEGER FileOffset; - HANDLE FileHandle; - NTSTATUS Status; - - DPRINT("CmiFinishHiveUpdate() called\n"); - - InitializeObjectAttributes(&ObjectAttributes, - &RegistryHive->HiveFileName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = ZwCreateFile(&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)) - { - DPRINT("ZwCreateFile() failed (Status %lx)\n", Status); - return(Status); - } - - /* Update second update counter and checksum */ - RegistryHive->HiveHeader->UpdateCounter1 = RegistryHive->UpdateCounter + 1; - RegistryHive->HiveHeader->UpdateCounter2 = RegistryHive->UpdateCounter + 1; - RegistryHive->HiveHeader->Checksum = CmiCalcChecksum((PULONG)RegistryHive->HiveHeader); - - /* Write hive block */ - FileOffset.QuadPart = (ULONGLONG)0; - Status = ZwWriteFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - RegistryHive->HiveHeader, - sizeof(HIVE_HEADER), - &FileOffset, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwWriteFile() failed (Status %lx)\n", Status); - ZwClose(FileHandle); - return(Status); - } - - Status = ZwFlushBuffersFile(FileHandle, - &IoStatusBlock); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwFlushBuffersFile() failed (Status %lx)\n", Status); - } - - ZwClose(FileHandle); - - return(Status); + ZwClose(RegistryHive->HiveHandle); + ZwClose(RegistryHive->LogHandle); } NTSTATUS -CmiFlushRegistryHive(PREGISTRY_HIVE RegistryHive) +CmiFlushRegistryHive(PEREGISTRY_HIVE RegistryHive) { + BOOLEAN Success; NTSTATUS Status; - DPRINT("CmiFlushRegistryHive() called\n"); + ASSERT(!IsNoFileHive(RegistryHive)); - if (RegistryHive->HiveDirty == FALSE) + if (RtlFindSetBits(&RegistryHive->Hive->DirtyBitmap, 1, 0) == ~0) { return(STATUS_SUCCESS); } - DPRINT("Hive '%wZ' is dirty\n", - &RegistryHive->HiveFileName); - DPRINT("Log file: '%wZ'\n", - &RegistryHive->LogFileName); - - /* Update hive header modification time */ - KeQuerySystemTime(&RegistryHive->HiveHeader->DateModified); - - /* Start log update */ - Status = CmiStartLogUpdate(RegistryHive); + Status = CmOpenHiveFiles(RegistryHive); if (!NT_SUCCESS(Status)) { - DPRINT("CmiStartLogUpdate() failed (Status %lx)\n", Status); - return(Status); + return Status; } - /* Finish log update */ - Status = CmiFinishLogUpdate(RegistryHive); - if (!NT_SUCCESS(Status)) - { - DPRINT("CmiFinishLogUpdate() failed (Status %lx)\n", Status); - return(Status); - } + Success = HvSyncHive(RegistryHive->Hive); - /* Start hive update */ - Status = CmiStartHiveUpdate(RegistryHive); - if (!NT_SUCCESS(Status)) - { - DPRINT("CmiStartHiveUpdate() failed (Status %lx)\n", Status); - return(Status); - } + CmCloseHiveFiles(RegistryHive); - /* Finish the hive update */ - Status = CmiFinishHiveUpdate(RegistryHive); - if (!NT_SUCCESS(Status)) - { - DPRINT("CmiFinishHiveUpdate() failed (Status %lx)\n", Status); - return(Status); - } - - /* Cleanup log update */ - Status = CmiCleanupLogUpdate(RegistryHive); - if (!NT_SUCCESS(Status)) - { - DPRINT("CmiFinishLogUpdate() failed (Status %lx)\n", Status); - return(Status); - } - - /* Increment hive update counter */ - RegistryHive->UpdateCounter++; - - /* Clear dirty bitmap and dirty flag */ - RtlClearAllBits(&RegistryHive->DirtyBitMap); - RegistryHive->HiveDirty = FALSE; - - DPRINT("CmiFlushRegistryHive() done\n"); - - return(STATUS_SUCCESS); + return Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; } ULONG CmiGetNumberOfSubKeys(PKEY_OBJECT KeyObject) { - PKEY_OBJECT CurKey; PKEY_CELL KeyCell; ULONG SubKeyCount; - ULONG i; VERIFY_KEY_OBJECT(KeyObject); KeyCell = KeyObject->KeyCell; VERIFY_KEY_CELL(KeyCell); - SubKeyCount = (KeyCell == NULL) ? 0 : KeyCell->NumberOfSubKeys; - - /* Search for volatile or 'foreign' keys */ - for (i = 0; i < KeyObject->NumberOfSubKeys; i++) - { - CurKey = KeyObject->SubKeys[i]; - if (CurKey->RegistryHive == CmiVolatileHive || - CurKey->RegistryHive != KeyObject->RegistryHive) - { - SubKeyCount++; - } - } + SubKeyCount = (KeyCell == NULL) ? 0 : + KeyCell->NumberOfSubKeys[HvStable] + + KeyCell->NumberOfSubKeys[HvVolatile]; return SubKeyCount; } @@ -2043,12 +851,12 @@ ULONG CmiGetMaxNameLength(PKEY_OBJECT KeyObject) { PHASH_TABLE_CELL HashBlock; - PKEY_OBJECT CurKey; PKEY_CELL CurSubKeyCell; PKEY_CELL KeyCell; ULONG MaxName; ULONG NameSize; ULONG i; + ULONG Storage; VERIFY_KEY_OBJECT(KeyObject); @@ -2056,77 +864,24 @@ CmiGetMaxNameLength(PKEY_OBJECT KeyObject) VERIFY_KEY_CELL(KeyCell); MaxName = 0; - HashBlock = CmiGetCell (KeyObject->RegistryHive, - KeyCell->HashTableOffset, - NULL); - if (HashBlock == NULL) + for (Storage = HvStable; Storage < HvMaxStorageType; Storage++) { - DPRINT("CmiGetBlock() failed\n"); - } - else - { - for (i = 0; i < HashBlock->HashTableSize; i++) - { - if (HashBlock->Table[i].KeyOffset != 0) - { - CurSubKeyCell = CmiGetCell (KeyObject->RegistryHive, - HashBlock->Table[i].KeyOffset, - NULL); - if (CurSubKeyCell == NULL) - { - DPRINT("CmiGetBlock() failed\n"); - continue; - } + if (KeyCell->HashTableOffset[Storage] != HCELL_NULL) + { + HashBlock = HvGetCell (KeyObject->RegistryHive->Hive, KeyCell->HashTableOffset[Storage]); + ASSERT(HashBlock->Id == REG_HASH_TABLE_CELL_ID); - NameSize = CurSubKeyCell->NameSize; - if (CurSubKeyCell->Flags & REG_KEY_NAME_PACKED) - { - NameSize *= sizeof(WCHAR); - } - - if (NameSize > MaxName) - { - MaxName = NameSize; - } - } - } - } - - DPRINT ("KeyObject->NumberOfSubKeys %d\n", KeyObject->NumberOfSubKeys); - for (i = 0; i < KeyObject->NumberOfSubKeys; i++) - { - CurKey = KeyObject->SubKeys[i]; - if (CurKey->RegistryHive == CmiVolatileHive || - CurKey->RegistryHive != KeyObject->RegistryHive) - { - CurSubKeyCell = CurKey->KeyCell; - if (CurSubKeyCell == NULL) - { - DPRINT("CmiGetBlock() failed\n"); - continue; - } - - if ((CurSubKeyCell->Flags & REG_KEY_ROOT_CELL) == REG_KEY_ROOT_CELL) - { - /* Use name of the key object */ - NameSize = CurKey->Name.Length; - } - else - { - /* Use name of the key cell */ - NameSize = CurSubKeyCell->NameSize; - if (CurSubKeyCell->Flags & REG_KEY_NAME_PACKED) - { - NameSize *= sizeof(WCHAR); - } - } - DPRINT ("NameSize %lu\n", NameSize); - - if (NameSize > MaxName) - { - MaxName = NameSize; - } - } + for (i = 0; i < KeyCell->NumberOfSubKeys[Storage]; i++) + { + CurSubKeyCell = HvGetCell (KeyObject->RegistryHive->Hive, + HashBlock->Table[i].KeyOffset); + NameSize = CurSubKeyCell->NameSize; + if (CurSubKeyCell->Flags & REG_KEY_NAME_PACKED) + NameSize *= sizeof(WCHAR); + if (NameSize > MaxName) + MaxName = NameSize; + } + } } DPRINT ("MaxName %lu\n", MaxName); @@ -2139,11 +894,11 @@ ULONG CmiGetMaxClassLength(PKEY_OBJECT KeyObject) { PHASH_TABLE_CELL HashBlock; - PKEY_OBJECT CurKey; PKEY_CELL CurSubKeyCell; PKEY_CELL KeyCell; ULONG MaxClass; ULONG i; + ULONG Storage; VERIFY_KEY_OBJECT(KeyObject); @@ -2151,55 +906,25 @@ CmiGetMaxClassLength(PKEY_OBJECT KeyObject) VERIFY_KEY_CELL(KeyCell); MaxClass = 0; - HashBlock = CmiGetCell (KeyObject->RegistryHive, - KeyCell->HashTableOffset, - NULL); - if (HashBlock == NULL) + for (Storage = HvStable; Storage < HvMaxStorageType; Storage++) { - DPRINT("CmiGetBlock() failed\n"); - } - else - { - for (i = 0; i < HashBlock->HashTableSize; i++) - { - if (HashBlock->Table[i].KeyOffset != 0) - { - CurSubKeyCell = CmiGetCell (KeyObject->RegistryHive, - HashBlock->Table[i].KeyOffset, - NULL); - if (CurSubKeyCell == NULL) - { - DPRINT("CmiGetBlock() failed\n"); - continue; - } + if (KeyCell->HashTableOffset[Storage] != HCELL_NULL) + { + HashBlock = HvGetCell (KeyObject->RegistryHive->Hive, + KeyCell->HashTableOffset[Storage]); + ASSERT(HashBlock->Id == REG_HASH_TABLE_CELL_ID); - if (MaxClass < CurSubKeyCell->ClassSize) - { - MaxClass = CurSubKeyCell->ClassSize; - } - } - } - } + for (i = 0; i < KeyCell->NumberOfSubKeys[Storage]; i++) + { + CurSubKeyCell = HvGetCell (KeyObject->RegistryHive->Hive, + HashBlock->Table[i].KeyOffset); - DPRINT("KeyObject->NumberOfSubKeys %d\n", KeyObject->NumberOfSubKeys); - for (i = 0; i < KeyObject->NumberOfSubKeys; i++) - { - CurKey = KeyObject->SubKeys[i]; - if (CurKey->RegistryHive == CmiVolatileHive || - CurKey->RegistryHive != KeyObject->RegistryHive) - { - CurSubKeyCell = CurKey->KeyCell; - if (CurSubKeyCell == NULL) - { - DPRINT("CmiGetBlock() failed\n"); - continue; - } - - if (MaxClass < CurSubKeyCell->ClassSize) - { - MaxClass = CurSubKeyCell->ClassSize; - } - } + if (MaxClass < CurSubKeyCell->ClassSize) + { + MaxClass = CurSubKeyCell->ClassSize; + } + } + } } return MaxClass; @@ -2207,7 +932,7 @@ CmiGetMaxClassLength(PKEY_OBJECT KeyObject) ULONG -CmiGetMaxValueNameLength(PREGISTRY_HIVE RegistryHive, +CmiGetMaxValueNameLength(PEREGISTRY_HIVE RegistryHive, PKEY_CELL KeyCell) { PVALUE_LIST_CELL ValueListCell; @@ -2218,21 +943,19 @@ CmiGetMaxValueNameLength(PREGISTRY_HIVE RegistryHive, VERIFY_KEY_CELL(KeyCell); - MaxValueName = 0; - ValueListCell = CmiGetCell (RegistryHive, - KeyCell->ValueListOffset, - NULL); - if (ValueListCell == NULL) + if (KeyCell->ValueListOffset == HCELL_NULL) { - DPRINT("CmiGetBlock() failed\n"); return 0; } + MaxValueName = 0; + ValueListCell = HvGetCell (RegistryHive->Hive, + KeyCell->ValueListOffset); + for (i = 0; i < KeyCell->NumberOfValues; i++) { - CurValueCell = CmiGetCell (RegistryHive, - ValueListCell->ValueOffset[i], - NULL); + CurValueCell = HvGetCell (RegistryHive->Hive, + ValueListCell->ValueOffset[i]); if (CurValueCell == NULL) { DPRINT("CmiGetBlock() failed\n"); @@ -2257,7 +980,7 @@ CmiGetMaxValueNameLength(PREGISTRY_HIVE RegistryHive, ULONG -CmiGetMaxValueDataLength(PREGISTRY_HIVE RegistryHive, +CmiGetMaxValueDataLength(PEREGISTRY_HIVE RegistryHive, PKEY_CELL KeyCell) { PVALUE_LIST_CELL ValueListCell; @@ -2267,19 +990,19 @@ CmiGetMaxValueDataLength(PREGISTRY_HIVE RegistryHive, VERIFY_KEY_CELL(KeyCell); - MaxValueData = 0; - ValueListCell = CmiGetCell (RegistryHive, KeyCell->ValueListOffset, NULL); - if (ValueListCell == NULL) + if (KeyCell->ValueListOffset == HCELL_NULL) { return 0; } + MaxValueData = 0; + ValueListCell = HvGetCell (RegistryHive->Hive, KeyCell->ValueListOffset); + for (i = 0; i < KeyCell->NumberOfValues; i++) { - CurValueCell = CmiGetCell (RegistryHive, - ValueListCell->ValueOffset[i],NULL); - if ((CurValueCell != NULL) && - (MaxValueData < (LONG)(CurValueCell->DataSize & REG_DATA_SIZE_MASK))) + CurValueCell = HvGetCell (RegistryHive->Hive, + ValueListCell->ValueOffset[i]); + if ((MaxValueData < (LONG)(CurValueCell->DataSize & REG_DATA_SIZE_MASK))) { MaxValueData = CurValueCell->DataSize & REG_DATA_SIZE_MASK; } @@ -2290,16 +1013,17 @@ CmiGetMaxValueDataLength(PREGISTRY_HIVE RegistryHive, NTSTATUS -CmiScanForSubKey(IN PREGISTRY_HIVE RegistryHive, +CmiScanForSubKey(IN PEREGISTRY_HIVE RegistryHive, IN PKEY_CELL KeyCell, OUT PKEY_CELL *SubKeyCell, - OUT BLOCK_OFFSET *BlockOffset, + OUT HCELL_INDEX *BlockOffset, IN PUNICODE_STRING KeyName, IN ACCESS_MASK DesiredAccess, IN ULONG Attributes) { PHASH_TABLE_CELL HashBlock; PKEY_CELL CurSubKeyCell; + ULONG Storage; ULONG i; VERIFY_KEY_CELL(KeyCell); @@ -2310,78 +1034,61 @@ CmiScanForSubKey(IN PREGISTRY_HIVE RegistryHive, *SubKeyCell = NULL; - /* The key does not have any subkeys */ - if (KeyCell->HashTableOffset == (BLOCK_OFFSET)-1) + for (Storage = HvStable; Storage < HvMaxStorageType; Storage++) { - return STATUS_SUCCESS; + /* The key does not have any subkeys */ + if (KeyCell->HashTableOffset[Storage] == HCELL_NULL) + { + continue; + } + + /* Get hash table */ + HashBlock = HvGetCell (RegistryHive->Hive, KeyCell->HashTableOffset[Storage]); + ASSERT(HashBlock->Id == REG_HASH_TABLE_CELL_ID); + + for (i = 0; i < KeyCell->NumberOfSubKeys[Storage]; i++) + { + if (Attributes & OBJ_CASE_INSENSITIVE) + { + if ((HashBlock->Table[i].HashValue == 0 || + CmiCompareHashI(KeyName, (PCHAR)&HashBlock->Table[i].HashValue))) + { + CurSubKeyCell = HvGetCell (RegistryHive->Hive, + HashBlock->Table[i].KeyOffset); + + if (CmiCompareKeyNamesI(KeyName, CurSubKeyCell)) + { + *SubKeyCell = CurSubKeyCell; + *BlockOffset = HashBlock->Table[i].KeyOffset; + return STATUS_SUCCESS; + } + } + } + else + { + if ((HashBlock->Table[i].HashValue == 0 || + CmiCompareHash(KeyName, (PCHAR)&HashBlock->Table[i].HashValue))) + { + CurSubKeyCell = HvGetCell (RegistryHive->Hive, + HashBlock->Table[i].KeyOffset); + + if (CmiCompareKeyNames(KeyName, CurSubKeyCell)) + { + *SubKeyCell = CurSubKeyCell; + *BlockOffset = HashBlock->Table[i].KeyOffset; + return STATUS_SUCCESS; + } + } + } + } } - /* Get hash table */ - HashBlock = CmiGetCell (RegistryHive, KeyCell->HashTableOffset, NULL); - if (HashBlock == NULL) - { - DPRINT("CmiGetBlock() failed\n"); - return STATUS_UNSUCCESSFUL; - } - - for (i = 0; (i < KeyCell->NumberOfSubKeys) && (i < HashBlock->HashTableSize); i++) - { - if (Attributes & OBJ_CASE_INSENSITIVE) - { - if (HashBlock->Table[i].KeyOffset != 0 && - HashBlock->Table[i].KeyOffset != (ULONG_PTR)-1 && - (HashBlock->Table[i].HashValue == 0 || - CmiCompareHashI(KeyName, (PCHAR)&HashBlock->Table[i].HashValue))) - { - CurSubKeyCell = CmiGetCell (RegistryHive, - HashBlock->Table[i].KeyOffset, - NULL); - if (CurSubKeyCell == NULL) - { - DPRINT("CmiGetBlock() failed\n"); - return STATUS_UNSUCCESSFUL; - } - - if (CmiCompareKeyNamesI(KeyName, CurSubKeyCell)) - { - *SubKeyCell = CurSubKeyCell; - *BlockOffset = HashBlock->Table[i].KeyOffset; - break; - } - } - } - else - { - if (HashBlock->Table[i].KeyOffset != 0 && - HashBlock->Table[i].KeyOffset != (ULONG_PTR) -1 && - (HashBlock->Table[i].HashValue == 0 || - CmiCompareHash(KeyName, (PCHAR)&HashBlock->Table[i].HashValue))) - { - CurSubKeyCell = CmiGetCell (RegistryHive, - HashBlock->Table[i].KeyOffset, - NULL); - if (CurSubKeyCell == NULL) - { - DPRINT("CmiGetBlock() failed\n"); - return STATUS_UNSUCCESSFUL; - } - - if (CmiCompareKeyNames(KeyName, CurSubKeyCell)) - { - *SubKeyCell = CurSubKeyCell; - *BlockOffset = HashBlock->Table[i].KeyOffset; - break; - } - } - } - } - - return STATUS_SUCCESS; + return STATUS_OBJECT_NAME_NOT_FOUND; } NTSTATUS -CmiAddSubKey(PREGISTRY_HIVE RegistryHive, +CmiAddSubKey(PEREGISTRY_HIVE RegistryHive, PKEY_OBJECT ParentKey, PKEY_OBJECT SubKey, PUNICODE_STRING SubKeyName, @@ -2390,15 +1097,16 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive, ULONG CreateOptions) { PHASH_TABLE_CELL HashBlock; - BLOCK_OFFSET NKBOffset; + HCELL_INDEX NKBOffset; PKEY_CELL NewKeyCell; ULONG NewBlockSize; PKEY_CELL ParentKeyCell; - PDATA_CELL ClassCell; + PVOID ClassCell; NTSTATUS Status; USHORT NameSize; PWSTR NamePtr; BOOLEAN Packable; + HV_STORAGE_TYPE Storage; ULONG i; ParentKeyCell = ParentKey->KeyCell; @@ -2438,27 +1146,35 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive, Status = STATUS_SUCCESS; + Storage = (CreateOptions & REG_OPTION_VOLATILE) ? HvVolatile : HvStable; NewBlockSize = sizeof(KEY_CELL) + NameSize; - Status = CmiAllocateCell (RegistryHive, - NewBlockSize, - (PVOID) &NewKeyCell, - &NKBOffset); - if (NewKeyCell == NULL) + NKBOffset = HvAllocateCell (RegistryHive->Hive, NewBlockSize, Storage); + if (NKBOffset == HCELL_NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; } else { + NewKeyCell = HvGetCell (RegistryHive->Hive, NKBOffset); NewKeyCell->Id = REG_KEY_CELL_ID; - NewKeyCell->Flags = 0; + if (CreateOptions & REG_OPTION_VOLATILE) + { + NewKeyCell->Flags = REG_KEY_VOLATILE_CELL; + } + else + { + NewKeyCell->Flags = 0; + } KeQuerySystemTime(&NewKeyCell->LastWriteTime); - NewKeyCell->ParentKeyOffset = -1; - NewKeyCell->NumberOfSubKeys = 0; - NewKeyCell->HashTableOffset = -1; + NewKeyCell->ParentKeyOffset = HCELL_NULL; + NewKeyCell->NumberOfSubKeys[HvStable] = 0; + NewKeyCell->NumberOfSubKeys[HvVolatile] = 0; + NewKeyCell->HashTableOffset[HvStable] = HCELL_NULL; + NewKeyCell->HashTableOffset[HvVolatile] = HCELL_NULL; NewKeyCell->NumberOfValues = 0; - NewKeyCell->ValueListOffset = -1; - NewKeyCell->SecurityKeyOffset = -1; - NewKeyCell->ClassNameOffset = -1; + NewKeyCell->ValueListOffset = HCELL_NULL; + NewKeyCell->SecurityKeyOffset = HCELL_NULL; + NewKeyCell->ClassNameOffset = HCELL_NULL; /* Pack the key name */ NewKeyCell->NameSize = NameSize; @@ -2479,14 +1195,15 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive, VERIFY_KEY_CELL(NewKeyCell); - if (Class != NULL) + if (Class != NULL && Class->Length) { NewKeyCell->ClassSize = Class->Length; - Status = CmiAllocateCell (RegistryHive, - sizeof(CELL_HEADER) + NewKeyCell->ClassSize, - (PVOID)&ClassCell, - &NewKeyCell->ClassNameOffset); - RtlCopyMemory (ClassCell->Data, + NewKeyCell->ClassNameOffset = HvAllocateCell( + RegistryHive->Hive, NewKeyCell->ClassSize, HvStable); + ASSERT(NewKeyCell->ClassNameOffset != HCELL_NULL); /* FIXME */ + + ClassCell = HvGetCell(RegistryHive->Hive, NewKeyCell->ClassNameOffset); + RtlCopyMemory (ClassCell, Class->Buffer, Class->Length); } @@ -2500,18 +1217,13 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive, SubKey->KeyCell = NewKeyCell; SubKey->KeyCellOffset = NKBOffset; - /* Don't modify hash table if key is located in a pointer-based hive and parent key is not */ - if (IsPointerHive(RegistryHive) && (!IsPointerHive(ParentKey->RegistryHive))) - { - return(Status); - } - - if (ParentKeyCell->HashTableOffset == (ULONG_PTR) -1) + if (ParentKeyCell->HashTableOffset[Storage] == HCELL_NULL) { Status = CmiAllocateHashTableCell (RegistryHive, &HashBlock, - &ParentKeyCell->HashTableOffset, - REG_INIT_HASH_TABLE_SIZE); + &ParentKeyCell->HashTableOffset[Storage], + REG_INIT_HASH_TABLE_SIZE, + Storage); if (!NT_SUCCESS(Status)) { return(Status); @@ -2519,26 +1231,22 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive, } else { - HashBlock = CmiGetCell (RegistryHive, - ParentKeyCell->HashTableOffset, - NULL); - if (HashBlock == NULL) - { - DPRINT("CmiGetCell() failed\n"); - return STATUS_UNSUCCESSFUL; - } + HashBlock = HvGetCell (RegistryHive->Hive, + ParentKeyCell->HashTableOffset[Storage]); + ASSERT(HashBlock->Id == REG_HASH_TABLE_CELL_ID); - if (((ParentKeyCell->NumberOfSubKeys + 1) >= HashBlock->HashTableSize)) + if (((ParentKeyCell->NumberOfSubKeys[Storage] + 1) >= HashBlock->HashTableSize)) { PHASH_TABLE_CELL NewHashBlock; - BLOCK_OFFSET HTOffset; + HCELL_INDEX HTOffset; /* Reallocate the hash table cell */ Status = CmiAllocateHashTableCell (RegistryHive, &NewHashBlock, &HTOffset, HashBlock->HashTableSize + - REG_EXTEND_HASH_TABLE_SIZE); + REG_EXTEND_HASH_TABLE_SIZE, + Storage); if (!NT_SUCCESS(Status)) { return Status; @@ -2549,193 +1257,127 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive, RtlCopyMemory(&NewHashBlock->Table[0], &HashBlock->Table[0], sizeof(NewHashBlock->Table[0]) * HashBlock->HashTableSize); - CmiDestroyCell (RegistryHive, - HashBlock, - ParentKeyCell->HashTableOffset); - ParentKeyCell->HashTableOffset = HTOffset; + HvFreeCell (RegistryHive->Hive, ParentKeyCell->HashTableOffset[Storage]); + ParentKeyCell->HashTableOffset[Storage] = HTOffset; HashBlock = NewHashBlock; } } Status = CmiAddKeyToHashTable(RegistryHive, HashBlock, - ParentKeyCell->HashTableOffset, + ParentKeyCell, + Storage, NewKeyCell, NKBOffset); if (NT_SUCCESS(Status)) { - ParentKeyCell->NumberOfSubKeys++; + ParentKeyCell->NumberOfSubKeys[Storage]++; } KeQuerySystemTime (&ParentKeyCell->LastWriteTime); - CmiMarkBlockDirty (RegistryHive, ParentKey->KeyCellOffset); + HvMarkCellDirty (RegistryHive->Hive, ParentKey->KeyCellOffset); return(Status); } NTSTATUS -CmiRemoveSubKey(PREGISTRY_HIVE RegistryHive, +CmiRemoveSubKey(PEREGISTRY_HIVE RegistryHive, PKEY_OBJECT ParentKey, PKEY_OBJECT SubKey) { PHASH_TABLE_CELL HashBlock; PVALUE_LIST_CELL ValueList; PVALUE_CELL ValueCell; - PDATA_CELL DataCell; + HV_STORAGE_TYPE Storage; ULONG i; DPRINT("CmiRemoveSubKey() called\n"); + Storage = (SubKey->KeyCell->Flags & REG_KEY_VOLATILE_CELL) ? HvVolatile : HvStable; + /* Remove all values */ if (SubKey->KeyCell->NumberOfValues != 0) { /* Get pointer to the value list cell */ - ValueList = CmiGetCell (RegistryHive, - SubKey->KeyCell->ValueListOffset, - NULL); - if (ValueList == NULL) - { - DPRINT("CmiGetCell() failed\n"); - return STATUS_UNSUCCESSFUL; - } + ValueList = HvGetCell (RegistryHive->Hive, SubKey->KeyCell->ValueListOffset); /* Enumerate all values */ for (i = 0; i < SubKey->KeyCell->NumberOfValues; i++) { /* Get pointer to value cell */ - ValueCell = CmiGetCell(RegistryHive, - ValueList->ValueOffset[i], - NULL); - if (ValueCell == NULL) - { - DPRINT("CmiGetCell() failed\n"); - return STATUS_UNSUCCESSFUL; - } + ValueCell = HvGetCell(RegistryHive->Hive, + ValueList->ValueOffset[i]); if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET) - && ValueCell->DataSize > sizeof(BLOCK_OFFSET)) + && ValueCell->DataSize > sizeof(HCELL_INDEX) + && ValueCell->DataOffset != HCELL_NULL) { - DataCell = CmiGetCell (RegistryHive, - ValueCell->DataOffset, - NULL); - if (DataCell == NULL) - { - DPRINT("CmiGetCell() failed\n"); - return STATUS_UNSUCCESSFUL; - } - - if (DataCell != NULL) - { - /* Destroy data cell */ - CmiDestroyCell (RegistryHive, - DataCell, - ValueCell->DataOffset); - } + /* Destroy data cell */ + HvFreeCell (RegistryHive->Hive, ValueCell->DataOffset); } /* Destroy value cell */ - CmiDestroyCell (RegistryHive, - ValueCell, - ValueList->ValueOffset[i]); + HvFreeCell (RegistryHive->Hive, ValueList->ValueOffset[i]); } /* Destroy value list cell */ - CmiDestroyCell (RegistryHive, - ValueList, - SubKey->KeyCell->ValueListOffset); + HvFreeCell (RegistryHive->Hive, SubKey->KeyCell->ValueListOffset); SubKey->KeyCell->NumberOfValues = 0; - SubKey->KeyCell->ValueListOffset = (BLOCK_OFFSET)-1; + SubKey->KeyCell->ValueListOffset = (HCELL_INDEX)-1; - CmiMarkBlockDirty(RegistryHive, - SubKey->KeyCellOffset); + HvMarkCellDirty(RegistryHive->Hive, SubKey->KeyCellOffset); } /* Remove the key from the parent key's hash block */ - if (ParentKey->KeyCell->HashTableOffset != (BLOCK_OFFSET) -1) + if (ParentKey->KeyCell->HashTableOffset[Storage] != HCELL_NULL) { - DPRINT("ParentKey HashTableOffset %lx\n", ParentKey->KeyCell->HashTableOffset); - HashBlock = CmiGetCell (ParentKey->RegistryHive, - ParentKey->KeyCell->HashTableOffset, - NULL); - if (HashBlock == NULL) - { - DPRINT("CmiGetCell() failed\n"); - return STATUS_UNSUCCESSFUL; - } + DPRINT("ParentKey HashTableOffset %lx\n", ParentKey->KeyCell->HashTableOffset[Storage]); + HashBlock = HvGetCell (ParentKey->RegistryHive->Hive, + ParentKey->KeyCell->HashTableOffset[Storage]); + ASSERT(HashBlock->Id == REG_HASH_TABLE_CELL_ID); DPRINT("ParentKey HashBlock %p\n", HashBlock); - if (HashBlock != NULL) - { - CmiRemoveKeyFromHashTable(ParentKey->RegistryHive, - HashBlock, - SubKey->KeyCellOffset); - CmiMarkBlockDirty(ParentKey->RegistryHive, - ParentKey->KeyCell->HashTableOffset); - } + CmiRemoveKeyFromHashTable(ParentKey->RegistryHive, + HashBlock, + SubKey->KeyCellOffset); + HvMarkCellDirty(ParentKey->RegistryHive->Hive, + ParentKey->KeyCell->HashTableOffset[Storage]); } /* Remove the key's hash block */ - if (SubKey->KeyCell->HashTableOffset != (BLOCK_OFFSET) -1) + if (SubKey->KeyCell->HashTableOffset[Storage] != HCELL_NULL) { - DPRINT("SubKey HashTableOffset %lx\n", SubKey->KeyCell->HashTableOffset); - HashBlock = CmiGetCell (RegistryHive, - SubKey->KeyCell->HashTableOffset, - NULL); - if (HashBlock == NULL) - { - DPRINT("CmiGetCell() failed\n"); - return STATUS_UNSUCCESSFUL; - } - DPRINT("SubKey HashBlock %p\n", HashBlock); - if (HashBlock != NULL) - { - CmiDestroyCell (RegistryHive, - HashBlock, - SubKey->KeyCell->HashTableOffset); - SubKey->KeyCell->HashTableOffset = -1; - } + DPRINT("SubKey HashTableOffset %lx\n", SubKey->KeyCell->HashTableOffset[Storage]); + HvFreeCell (RegistryHive->Hive, SubKey->KeyCell->HashTableOffset[Storage]); + SubKey->KeyCell->HashTableOffset[Storage] = HCELL_NULL; } /* Decrement the number of the parent key's sub keys */ if (ParentKey != NULL) { DPRINT("ParentKey %p\n", ParentKey); - ParentKey->KeyCell->NumberOfSubKeys--; + ParentKey->KeyCell->NumberOfSubKeys[Storage]--; /* Remove the parent key's hash table */ - if (ParentKey->KeyCell->NumberOfSubKeys == 0) + if (ParentKey->KeyCell->NumberOfSubKeys[Storage] == 0 && + ParentKey->KeyCell->HashTableOffset[Storage] != HCELL_NULL) { DPRINT("ParentKey HashTableOffset %lx\n", ParentKey->KeyCell->HashTableOffset); - HashBlock = CmiGetCell (ParentKey->RegistryHive, - ParentKey->KeyCell->HashTableOffset, - NULL); - if (HashBlock == NULL) - { - DPRINT("CmiGetCell() failed\n"); - return STATUS_UNSUCCESSFUL; - } - DPRINT("ParentKey HashBlock %p\n", HashBlock); - if (HashBlock != NULL) - { - CmiDestroyCell (ParentKey->RegistryHive, - HashBlock, - ParentKey->KeyCell->HashTableOffset); - ParentKey->KeyCell->HashTableOffset = (BLOCK_OFFSET)-1; - } + HvFreeCell (ParentKey->RegistryHive->Hive, + ParentKey->KeyCell->HashTableOffset[Storage]); + ParentKey->KeyCell->HashTableOffset[Storage] = HCELL_NULL; } KeQuerySystemTime(&ParentKey->KeyCell->LastWriteTime); - CmiMarkBlockDirty(ParentKey->RegistryHive, - ParentKey->KeyCellOffset); + HvMarkCellDirty(ParentKey->RegistryHive->Hive, + ParentKey->KeyCellOffset); } /* Destroy key cell */ - CmiDestroyCell (RegistryHive, - SubKey->KeyCell, - SubKey->KeyCellOffset); + HvFreeCell (RegistryHive->Hive, SubKey->KeyCellOffset); SubKey->KeyCell = NULL; - SubKey->KeyCellOffset = (BLOCK_OFFSET)-1; + SubKey->KeyCellOffset = (HCELL_INDEX)-1; DPRINT("CmiRemoveSubKey() done\n"); @@ -2744,11 +1386,11 @@ CmiRemoveSubKey(PREGISTRY_HIVE RegistryHive, NTSTATUS -CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive, +CmiScanKeyForValue(IN PEREGISTRY_HIVE RegistryHive, IN PKEY_CELL KeyCell, IN PUNICODE_STRING ValueName, OUT PVALUE_CELL *ValueCell, - OUT BLOCK_OFFSET *ValueCellOffset) + OUT HCELL_INDEX *ValueCellOffset) { PVALUE_LIST_CELL ValueListCell; PVALUE_CELL CurValueCell; @@ -2756,36 +1398,24 @@ CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive, *ValueCell = NULL; if (ValueCellOffset != NULL) - *ValueCellOffset = (BLOCK_OFFSET)-1; + *ValueCellOffset = (HCELL_INDEX)-1; /* The key does not have any values */ - if (KeyCell->ValueListOffset == (BLOCK_OFFSET)-1) + if (KeyCell->ValueListOffset == (HCELL_INDEX)-1) { return STATUS_OBJECT_NAME_NOT_FOUND; } - ValueListCell = CmiGetCell (RegistryHive, KeyCell->ValueListOffset, NULL); - if (ValueListCell == NULL) - { - DPRINT("ValueListCell is NULL\n"); - return STATUS_UNSUCCESSFUL; - } + ValueListCell = HvGetCell (RegistryHive->Hive, KeyCell->ValueListOffset); VERIFY_VALUE_LIST_CELL(ValueListCell); for (i = 0; i < KeyCell->NumberOfValues; i++) { - CurValueCell = CmiGetCell (RegistryHive, - ValueListCell->ValueOffset[i], - NULL); - if (CurValueCell == NULL) - { - DPRINT("CmiGetBlock() failed\n"); - return STATUS_UNSUCCESSFUL; - } + CurValueCell = HvGetCell (RegistryHive->Hive, + ValueListCell->ValueOffset[i]); - if ((CurValueCell != NULL) && - CmiComparePackedNames(ValueName, + if (CmiComparePackedNames(ValueName, CurValueCell->Name, CurValueCell->NameSize, (BOOLEAN)((CurValueCell->Flags & REG_VALUE_NAME_PACKED) ? TRUE : FALSE))) @@ -2803,7 +1433,7 @@ CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive, NTSTATUS -CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive, +CmiGetValueFromKeyByIndex(IN PEREGISTRY_HIVE RegistryHive, IN PKEY_CELL KeyCell, IN ULONG Index, OUT PVALUE_CELL *ValueCell) @@ -2813,7 +1443,7 @@ CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive, *ValueCell = NULL; - if (KeyCell->ValueListOffset == (BLOCK_OFFSET)-1) + if (KeyCell->ValueListOffset == (HCELL_INDEX)-1) { return STATUS_NO_MORE_ENTRIES; } @@ -2824,24 +1454,11 @@ CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive, } - ValueListCell = CmiGetCell (RegistryHive, KeyCell->ValueListOffset, NULL); - if (ValueListCell == NULL) - { - DPRINT("CmiGetBlock() failed\n"); - return STATUS_UNSUCCESSFUL; - } + ValueListCell = HvGetCell (RegistryHive->Hive, KeyCell->ValueListOffset); VERIFY_VALUE_LIST_CELL(ValueListCell); - - CurValueCell = CmiGetCell (RegistryHive, - ValueListCell->ValueOffset[Index], - NULL); - if (CurValueCell == NULL) - { - DPRINT("CmiGetBlock() failed\n"); - return STATUS_UNSUCCESSFUL; - } + CurValueCell = HvGetCell (RegistryHive->Hive, ValueListCell->ValueOffset[Index]); *ValueCell = CurValueCell; @@ -2850,81 +1467,72 @@ CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive, NTSTATUS -CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive, +CmiAddValueToKey(IN PEREGISTRY_HIVE RegistryHive, IN PKEY_CELL KeyCell, - IN BLOCK_OFFSET KeyCellOffset, + IN HCELL_INDEX KeyCellOffset, IN PUNICODE_STRING ValueName, OUT PVALUE_CELL *pValueCell, - OUT BLOCK_OFFSET *pValueCellOffset) + OUT HCELL_INDEX *pValueCellOffset) { - PVALUE_LIST_CELL NewValueListCell; PVALUE_LIST_CELL ValueListCell; PVALUE_CELL NewValueCell; - BLOCK_OFFSET NewValueListCellOffset; - BLOCK_OFFSET ValueListCellOffset; - BLOCK_OFFSET NewValueCellOffset; + HCELL_INDEX ValueListCellOffset; + HCELL_INDEX NewValueCellOffset; ULONG CellSize; + HV_STORAGE_TYPE Storage; NTSTATUS Status; DPRINT("KeyCell->ValuesOffset %lu\n", (ULONG)KeyCell->ValueListOffset); - ValueListCell = CmiGetCell (RegistryHive, KeyCell->ValueListOffset, NULL); - if (ValueListCell == NULL) + Storage = (KeyCell->Flags & REG_KEY_VOLATILE_CELL) ? HvVolatile : HvStable; + if (KeyCell->ValueListOffset == HCELL_NULL) { CellSize = sizeof(VALUE_LIST_CELL) + - (3 * sizeof(BLOCK_OFFSET)); - Status = CmiAllocateCell (RegistryHive, - CellSize, - (PVOID) &ValueListCell, - &ValueListCellOffset); - if (!NT_SUCCESS(Status)) + (3 * sizeof(HCELL_INDEX)); + ValueListCellOffset = HvAllocateCell (RegistryHive->Hive, CellSize, Storage); + if (ValueListCellOffset == HCELL_NULL) { - return Status; + return STATUS_INSUFFICIENT_RESOURCES; } + ValueListCell = HvGetCell (RegistryHive->Hive, ValueListCellOffset); KeyCell->ValueListOffset = ValueListCellOffset; - CmiMarkBlockDirty(RegistryHive, KeyCellOffset); - CmiMarkBlockDirty(RegistryHive, ValueListCellOffset); + HvMarkCellDirty(RegistryHive->Hive, KeyCellOffset); } - else if (KeyCell->NumberOfValues >= - (((ULONG)ABS_VALUE(ValueListCell->CellSize) - sizeof(VALUE_LIST_CELL)) / sizeof(BLOCK_OFFSET))) + else { -#if 0 - CellSize = sizeof(VALUE_LIST_CELL) + - ((KeyCell->NumberOfValues + REG_VALUE_LIST_CELL_MULTIPLE) * sizeof(BLOCK_OFFSET)); -#endif - CellSize = 2 * (ULONG)ABS_VALUE(ValueListCell->CellSize); - Status = CmiAllocateCell (RegistryHive, - CellSize, - (PVOID) &NewValueListCell, - &NewValueListCellOffset); - if (!NT_SUCCESS(Status)) - { - return Status; - } + ValueListCell = (PVALUE_LIST_CELL) HvGetCell (RegistryHive->Hive, KeyCell->ValueListOffset); + CellSize = ABS_VALUE(HvGetCellSize(RegistryHive->Hive, ValueListCell)); - RtlCopyMemory(&NewValueListCell->ValueOffset[0], - &ValueListCell->ValueOffset[0], - sizeof(BLOCK_OFFSET) * KeyCell->NumberOfValues); - CmiDestroyCell (RegistryHive, ValueListCell, KeyCell->ValueListOffset); - CmiMarkBlockDirty (RegistryHive, KeyCell->ValueListOffset); + if (KeyCell->NumberOfValues >= + (CellSize / sizeof(HCELL_INDEX))) + { + CellSize *= 2; + ValueListCellOffset = HvReallocateCell (RegistryHive->Hive, KeyCell->ValueListOffset, CellSize); + if (ValueListCellOffset == HCELL_NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } - KeyCell->ValueListOffset = NewValueListCellOffset; - ValueListCell = NewValueListCell; - CmiMarkBlockDirty (RegistryHive, KeyCellOffset); - CmiMarkBlockDirty (RegistryHive, NewValueListCellOffset); + ValueListCell = HvGetCell (RegistryHive->Hive, ValueListCellOffset); + KeyCell->ValueListOffset = ValueListCellOffset; + HvMarkCellDirty (RegistryHive->Hive, KeyCellOffset); + } } +#if 0 DPRINT("KeyCell->NumberOfValues %lu, ValueListCell->CellSize %lu (%lu %lx)\n", KeyCell->NumberOfValues, (ULONG)ABS_VALUE(ValueListCell->CellSize), - ((ULONG)ABS_VALUE(ValueListCell->CellSize) - sizeof(VALUE_LIST_CELL)) / sizeof(BLOCK_OFFSET), - ((ULONG)ABS_VALUE(ValueListCell->CellSize) - sizeof(VALUE_LIST_CELL)) / sizeof(BLOCK_OFFSET)); + ((ULONG)ABS_VALUE(ValueListCell->CellSize) - sizeof(CELL_HEADER)) / sizeof(HCELL_INDEX), + ((ULONG)ABS_VALUE(ValueListCell->CellSize) - sizeof(CELL_HEADER)) / sizeof(HCELL_INDEX)); +#endif Status = CmiAllocateValueCell(RegistryHive, &NewValueCell, &NewValueCellOffset, - ValueName); + ValueName, + Storage); if (!NT_SUCCESS(Status)) { return Status; @@ -2933,9 +1541,9 @@ CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive, ValueListCell->ValueOffset[KeyCell->NumberOfValues] = NewValueCellOffset; KeyCell->NumberOfValues++; - CmiMarkBlockDirty(RegistryHive, KeyCellOffset); - CmiMarkBlockDirty(RegistryHive, KeyCell->ValueListOffset); - CmiMarkBlockDirty(RegistryHive, NewValueCellOffset); + HvMarkCellDirty(RegistryHive->Hive, KeyCellOffset); + HvMarkCellDirty(RegistryHive->Hive, KeyCell->ValueListOffset); + HvMarkCellDirty(RegistryHive->Hive, NewValueCellOffset); *pValueCell = NewValueCell; *pValueCellOffset = NewValueCellOffset; @@ -2945,9 +1553,9 @@ CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive, NTSTATUS -CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive, +CmiDeleteValueFromKey(IN PEREGISTRY_HIVE RegistryHive, IN PKEY_CELL KeyCell, - IN BLOCK_OFFSET KeyCellOffset, + IN HCELL_INDEX KeyCellOffset, IN PUNICODE_STRING ValueName) { PVALUE_LIST_CELL ValueListCell; @@ -2955,23 +1563,13 @@ CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive, ULONG i; NTSTATUS Status; - ValueListCell = CmiGetCell (RegistryHive, KeyCell->ValueListOffset, NULL); - if (ValueListCell == NULL) - { - DPRINT1("CmiGetBlock() failed\n"); - return STATUS_SUCCESS; - } + ValueListCell = HvGetCell (RegistryHive->Hive, KeyCell->ValueListOffset); VERIFY_VALUE_LIST_CELL(ValueListCell); for (i = 0; i < KeyCell->NumberOfValues; i++) { - CurValueCell = CmiGetCell (RegistryHive, ValueListCell->ValueOffset[i], NULL); - if (CurValueCell == NULL) - { - DPRINT1("CmiGetBlock() failed\n"); - return STATUS_UNSUCCESSFUL; - } + CurValueCell = HvGetCell (RegistryHive->Hive, ValueListCell->ValueOffset[i]); if (CmiComparePackedNames(ValueName, CurValueCell->Name, @@ -2991,7 +1589,7 @@ CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive, { RtlMoveMemory(&ValueListCell->ValueOffset[i], &ValueListCell->ValueOffset[i + 1], - sizeof(BLOCK_OFFSET) * (KeyCell->NumberOfValues - 1 - i)); + sizeof(HCELL_INDEX) * (KeyCell->NumberOfValues - 1 - i)); } ValueListCell->ValueOffset[KeyCell->NumberOfValues - 1] = 0; @@ -3000,19 +1598,17 @@ CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive, if (KeyCell->NumberOfValues == 0) { - CmiDestroyCell(RegistryHive, - ValueListCell, - KeyCell->ValueListOffset); + HvFreeCell(RegistryHive->Hive, KeyCell->ValueListOffset); KeyCell->ValueListOffset = -1; } else { - CmiMarkBlockDirty(RegistryHive, - KeyCell->ValueListOffset); + HvMarkCellDirty(RegistryHive->Hive, + KeyCell->ValueListOffset); } - CmiMarkBlockDirty(RegistryHive, - KeyCellOffset); + HvMarkCellDirty(RegistryHive->Hive, + KeyCellOffset); return STATUS_SUCCESS; } @@ -3025,10 +1621,11 @@ CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive, NTSTATUS -CmiAllocateHashTableCell (IN PREGISTRY_HIVE RegistryHive, +CmiAllocateHashTableCell (IN PEREGISTRY_HIVE RegistryHive, OUT PHASH_TABLE_CELL *HashBlock, - OUT BLOCK_OFFSET *HBOffset, - IN ULONG SubKeyCount) + OUT HCELL_INDEX *HBOffset, + IN ULONG SubKeyCount, + IN HV_STORAGE_TYPE Storage) { PHASH_TABLE_CELL NewHashBlock; ULONG NewHashSize; @@ -3038,18 +1635,16 @@ CmiAllocateHashTableCell (IN PREGISTRY_HIVE RegistryHive, *HashBlock = NULL; NewHashSize = sizeof(HASH_TABLE_CELL) + (SubKeyCount * sizeof(HASH_RECORD)); - Status = CmiAllocateCell (RegistryHive, - NewHashSize, - (PVOID*) &NewHashBlock, - HBOffset); + *HBOffset = HvAllocateCell (RegistryHive->Hive, NewHashSize, Storage); - if ((NewHashBlock == NULL) || (!NT_SUCCESS(Status))) + if (*HBOffset == HCELL_NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; } else { ASSERT(SubKeyCount <= 0xffff); /* should really be USHORT_MAX or similar */ + NewHashBlock = HvGetCell (RegistryHive->Hive, *HBOffset); NewHashBlock->Id = REG_HASH_TABLE_CELL_ID; NewHashBlock->HashTableSize = (USHORT)SubKeyCount; *HashBlock = NewHashBlock; @@ -3060,64 +1655,47 @@ CmiAllocateHashTableCell (IN PREGISTRY_HIVE RegistryHive, PKEY_CELL -CmiGetKeyFromHashByIndex(PREGISTRY_HIVE RegistryHive, +CmiGetKeyFromHashByIndex(PEREGISTRY_HIVE RegistryHive, PHASH_TABLE_CELL HashBlock, ULONG Index) { - BLOCK_OFFSET KeyOffset; + HCELL_INDEX KeyOffset; PKEY_CELL KeyCell; - if (HashBlock == NULL) - return NULL; - - if (IsPointerHive(RegistryHive)) - { - KeyCell = (PKEY_CELL) HashBlock->Table[Index].KeyOffset; - } - else - { - KeyOffset = HashBlock->Table[Index].KeyOffset; - KeyCell = CmiGetCell (RegistryHive, KeyOffset, NULL); - } + KeyOffset = HashBlock->Table[Index].KeyOffset; + KeyCell = HvGetCell (RegistryHive->Hive, KeyOffset); return KeyCell; } NTSTATUS -CmiAddKeyToHashTable(PREGISTRY_HIVE RegistryHive, +CmiAddKeyToHashTable(PEREGISTRY_HIVE RegistryHive, PHASH_TABLE_CELL HashCell, - BLOCK_OFFSET HashCellOffset, + PKEY_CELL KeyCell, + HV_STORAGE_TYPE StorageType, PKEY_CELL NewKeyCell, - BLOCK_OFFSET NKBOffset) + HCELL_INDEX NKBOffset) { - ULONG i; + ULONG i = KeyCell->NumberOfSubKeys[StorageType]; - for (i = 0; i < HashCell->HashTableSize; i++) + HashCell->Table[i].KeyOffset = NKBOffset; + HashCell->Table[i].HashValue = 0; + if (NewKeyCell->Flags & REG_KEY_NAME_PACKED) { - if (HashCell->Table[i].KeyOffset == 0) - { - HashCell->Table[i].KeyOffset = NKBOffset; - HashCell->Table[i].HashValue = 0; - if (NewKeyCell->Flags & REG_KEY_NAME_PACKED) - { - RtlCopyMemory(&HashCell->Table[i].HashValue, - NewKeyCell->Name, - min(NewKeyCell->NameSize, sizeof(ULONG))); - } - CmiMarkBlockDirty(RegistryHive, HashCellOffset); - return STATUS_SUCCESS; - } + RtlCopyMemory(&HashCell->Table[i].HashValue, + NewKeyCell->Name, + min(NewKeyCell->NameSize, sizeof(ULONG))); } - - return STATUS_UNSUCCESSFUL; + HvMarkCellDirty(RegistryHive->Hive, KeyCell->HashTableOffset[StorageType]); + return STATUS_SUCCESS; } NTSTATUS -CmiRemoveKeyFromHashTable(PREGISTRY_HIVE RegistryHive, +CmiRemoveKeyFromHashTable(PEREGISTRY_HIVE RegistryHive, PHASH_TABLE_CELL HashBlock, - BLOCK_OFFSET NKBOffset) + HCELL_INDEX NKBOffset) { ULONG i; @@ -3125,8 +1703,10 @@ CmiRemoveKeyFromHashTable(PREGISTRY_HIVE RegistryHive, { if (HashBlock->Table[i].KeyOffset == NKBOffset) { - HashBlock->Table[i].KeyOffset = 0; - HashBlock->Table[i].HashValue = 0; + RtlMoveMemory(HashBlock->Table + i, + HashBlock->Table + i + 1, + (HashBlock->HashTableSize - i - 1) * + sizeof(HashBlock->Table[0])); return STATUS_SUCCESS; } } @@ -3136,10 +1716,11 @@ CmiRemoveKeyFromHashTable(PREGISTRY_HIVE RegistryHive, NTSTATUS -CmiAllocateValueCell(PREGISTRY_HIVE RegistryHive, +CmiAllocateValueCell(PEREGISTRY_HIVE RegistryHive, PVALUE_CELL *ValueCell, - BLOCK_OFFSET *VBOffset, - IN PUNICODE_STRING ValueName) + HCELL_INDEX *VBOffset, + IN PUNICODE_STRING ValueName, + IN HV_STORAGE_TYPE Storage) { PVALUE_CELL NewValueCell; NTSTATUS Status; @@ -3154,17 +1735,15 @@ CmiAllocateValueCell(PREGISTRY_HIVE RegistryHive, DPRINT("ValueName->Length %lu NameSize %lu\n", ValueName->Length, NameSize); - Status = CmiAllocateCell (RegistryHive, - sizeof(VALUE_CELL) + NameSize, - (PVOID*) &NewValueCell, - VBOffset); - if ((NewValueCell == NULL) || (!NT_SUCCESS(Status))) + *VBOffset = HvAllocateCell (RegistryHive->Hive, sizeof(VALUE_CELL) + NameSize, Storage); + if (*VBOffset == HCELL_NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; } else { ASSERT(NameSize <= 0xffff); /* should really be USHORT_MAX or similar */ + NewValueCell = HvGetCell (RegistryHive->Hive, *VBOffset); NewValueCell->Id = REG_VALUE_CELL_ID; NewValueCell->NameSize = (USHORT)NameSize; if (Packable) @@ -3184,7 +1763,7 @@ CmiAllocateValueCell(PREGISTRY_HIVE RegistryHive, } NewValueCell->DataType = 0; NewValueCell->DataSize = 0; - NewValueCell->DataOffset = (BLOCK_OFFSET)-1; + NewValueCell->DataOffset = (HCELL_INDEX)-1; *ValueCell = NewValueCell; } @@ -3193,14 +1772,10 @@ CmiAllocateValueCell(PREGISTRY_HIVE RegistryHive, NTSTATUS -CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive, +CmiDestroyValueCell(PEREGISTRY_HIVE RegistryHive, PVALUE_CELL ValueCell, - BLOCK_OFFSET ValueCellOffset) + HCELL_INDEX ValueCellOffset) { - NTSTATUS Status; - PVOID DataCell; - PHBIN Bin; - DPRINT("CmiDestroyValueCell(Cell %p Offset %lx)\n", ValueCell, ValueCellOffset); @@ -3208,613 +1783,19 @@ CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive, /* Destroy the data cell */ if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET) - && ValueCell->DataSize > sizeof(BLOCK_OFFSET)) + && ValueCell->DataSize > sizeof(HCELL_INDEX) + && ValueCell->DataOffset != HCELL_NULL) { - DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, &Bin); - if (DataCell == NULL) - { - DPRINT("CmiGetCell() failed\n"); - return STATUS_UNSUCCESSFUL; - } - - Status = CmiDestroyCell (RegistryHive, DataCell, ValueCell->DataOffset); - if (!NT_SUCCESS(Status)) - { - return Status; - } - - /* Update time of heap */ - if (!IsNoFileHive(RegistryHive)) - KeQuerySystemTime(&Bin->DateModified); + HvFreeCell (RegistryHive->Hive, ValueCell->DataOffset); } /* Destroy the value cell */ - Status = CmiDestroyCell (RegistryHive, ValueCell, ValueCellOffset); - - /* Update time of heap */ - if (!IsNoFileHive(RegistryHive) && CmiGetCell (RegistryHive, ValueCellOffset, &Bin)) - { - KeQuerySystemTime(&Bin->DateModified); - } - - return Status; -} - - -NTSTATUS -CmiAddBin(PREGISTRY_HIVE RegistryHive, - ULONG BlockCount, - PVOID *NewBlock, - BLOCK_OFFSET *NewBlockOffset) -{ - PBLOCK_LIST_ENTRY BlockList; - PCELL_HEADER tmpBlock; - PHBIN tmpBin; - ULONG BinSize; - ULONG i; - ULONG BitmapSize; - - DPRINT ("CmiAddBin (BlockCount %lu)\n", BlockCount); - - BinSize = BlockCount * REG_BLOCK_SIZE; - tmpBin = ExAllocatePool(PagedPool, BinSize); - if (tmpBin == NULL) - { - return STATUS_INSUFFICIENT_RESOURCES; - } - RtlZeroMemory (tmpBin, - BinSize); - - tmpBin->HeaderId = REG_BIN_ID; - tmpBin->BinOffset = RegistryHive->FileSize - REG_BLOCK_SIZE; - RegistryHive->FileSize += BinSize; - tmpBin->BinSize = BinSize; - KeQuerySystemTime(&tmpBin->DateModified); - tmpBin->MemAlloc = 0; - - DPRINT (" BinOffset %lx BinSize %lx\n", tmpBin->BinOffset,tmpBin->BinSize); - - /* Allocate new block list */ - BlockList = ExAllocatePool(NonPagedPool, - sizeof(BLOCK_LIST_ENTRY) * (RegistryHive->BlockListSize + BlockCount)); - if (BlockList == NULL) - { - ExFreePool(tmpBin); - return STATUS_INSUFFICIENT_RESOURCES; - } - - if (RegistryHive->BlockListSize > 0) - { - RtlCopyMemory (BlockList, - RegistryHive->BlockList, - sizeof(BLOCK_LIST_ENTRY) * RegistryHive->BlockListSize); - ExFreePool(RegistryHive->BlockList); - } - - RegistryHive->BlockList = BlockList; - for (i = 0; i < BlockCount; i++) - { - RegistryHive->BlockList[RegistryHive->BlockListSize + i].Block = - (PVOID)((ULONG_PTR)tmpBin + (i * REG_BLOCK_SIZE)); - RegistryHive->BlockList[RegistryHive->BlockListSize + i].Bin = tmpBin; - } - RegistryHive->BlockListSize += BlockCount; - - /* Initialize a free block in this heap : */ - tmpBlock = (PCELL_HEADER)((ULONG_PTR) tmpBin + REG_HBIN_DATA_OFFSET); - tmpBlock->CellSize = (BinSize - REG_HBIN_DATA_OFFSET); - - /* Calculate bitmap size in bytes (always a multiple of 32 bits) */ - BitmapSize = ROUND_UP(RegistryHive->BlockListSize, sizeof(ULONG) * 8) / 8; - - /* Grow bitmap if necessary */ - if (!IsNoFileHive(RegistryHive) && - BitmapSize > RegistryHive->DirtyBitMap.SizeOfBitMap / 8) - { - PULONG BitmapBuffer; - - DPRINT("Grow hive bitmap\n"); - - DPRINT("RegistryHive->BlockListSize: %lu\n", RegistryHive->BlockListSize); - DPRINT("BitmapSize: %lu Bytes %lu Bits\n", BitmapSize, BitmapSize * 8); - BitmapBuffer = (PULONG)ExAllocatePool(PagedPool, - BitmapSize); - RtlZeroMemory(BitmapBuffer, BitmapSize); - RtlCopyMemory(BitmapBuffer, - RegistryHive->DirtyBitMap.Buffer, - RegistryHive->DirtyBitMap.SizeOfBitMap / 8); - ExFreePool(RegistryHive->BitmapBuffer); - RegistryHive->BitmapBuffer = BitmapBuffer; - RtlInitializeBitMap(&RegistryHive->DirtyBitMap, - RegistryHive->BitmapBuffer, - BitmapSize * 8); - } - - *NewBlock = (PVOID) tmpBlock; - - if (NewBlockOffset) - *NewBlockOffset = tmpBin->BinOffset + REG_HBIN_DATA_OFFSET; - - /* Mark new bin dirty */ - CmiMarkBinDirty(RegistryHive, - tmpBin->BinOffset); + HvFreeCell (RegistryHive->Hive, ValueCellOffset); return STATUS_SUCCESS; } -NTSTATUS -CmiAllocateCell (PREGISTRY_HIVE RegistryHive, - LONG CellSize, - PVOID *Cell, - BLOCK_OFFSET *CellOffset) -{ - PCELL_HEADER NewCell; - PHBIN Bin; - ULONG i; - PVOID Temp; - NTSTATUS Status; - - /* Round to 16 bytes multiple */ - CellSize = ROUND_UP(CellSize, 16); - - /* Handle volatile hives first */ - if (IsPointerHive(RegistryHive)) - { - NewCell = ExAllocatePool(NonPagedPool, CellSize); - if (NewCell == NULL) - { - return STATUS_INSUFFICIENT_RESOURCES; - } - - RtlZeroMemory (NewCell, - CellSize); - NewCell->CellSize = -CellSize; - - *Cell = NewCell; - if (CellOffset != NULL) - *CellOffset = (BLOCK_OFFSET) NewCell; - } - else - { - /* first search in free blocks */ - NewCell = NULL; - for (i = 0; i < RegistryHive->FreeListSize; i++) - { - if (RegistryHive->FreeList[i]->CellSize >= CellSize) - { - NewCell = RegistryHive->FreeList[i]; - if (CellOffset != NULL) - *CellOffset = RegistryHive->FreeListOffset[i]; - - /* Update time of heap */ - Temp = CmiGetCell (RegistryHive, - RegistryHive->FreeListOffset[i], - &Bin); - if (Temp == NULL) - { - DPRINT("CmiGetBlock() failed\n"); - return STATUS_UNSUCCESSFUL; - } - - KeQuerySystemTime(&Bin->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 (NewCell == NULL) - { - /* Add a new bin */ - Status = CmiAddBin(RegistryHive, - ((CellSize + sizeof(HBIN) - 1) / REG_BLOCK_SIZE) + 1, - (PVOID *)&NewCell, - CellOffset); - if (!NT_SUCCESS(Status)) - return Status; - } - - *Cell = NewCell; - - /* Split the block in two parts */ - if (NewCell->CellSize > CellSize) - { - NewCell = (PCELL_HEADER) ((ULONG_PTR) NewCell + CellSize); - NewCell->CellSize = ((PCELL_HEADER) (*Cell))->CellSize - CellSize; - CmiAddFree(RegistryHive, - NewCell, - *CellOffset + CellSize, - TRUE); - CmiMarkBlockDirty(RegistryHive, - *CellOffset + CellSize); - } - else if (NewCell->CellSize < CellSize) - { - return STATUS_UNSUCCESSFUL; - } - - RtlZeroMemory(*Cell, - CellSize); - ((PCELL_HEADER) (*Cell))->CellSize = -CellSize; - } - - return STATUS_SUCCESS; -} - - -NTSTATUS -CmiDestroyCell (PREGISTRY_HIVE RegistryHive, - PVOID Cell, - BLOCK_OFFSET CellOffset) -{ - NTSTATUS Status; - PHBIN pBin; - - Status = STATUS_SUCCESS; - - if (IsPointerHive(RegistryHive)) - { - ExFreePool(Cell); - } - else - { - PCELL_HEADER pFree = Cell; - - if (pFree->CellSize < 0) - pFree->CellSize = -pFree->CellSize; - - /* Clear block (except the block size) */ - RtlZeroMemory(((char*)pFree) + sizeof(ULONG), - pFree->CellSize - sizeof(ULONG)); - - /* Add block to the list of free blocks */ - CmiAddFree(RegistryHive, Cell, CellOffset, TRUE); - - /* Update time of heap */ - if (!IsNoFileHive(RegistryHive) && CmiGetCell (RegistryHive, CellOffset,&pBin)) - KeQuerySystemTime(&pBin->DateModified); - - CmiMarkBlockDirty(RegistryHive, CellOffset); - } - - return Status; -} - - -PVOID -CmiGetCell (PREGISTRY_HIVE RegistryHive, - BLOCK_OFFSET CellOffset, - PHBIN *Bin) -{ - PHBIN pBin; - - if (Bin != NULL) - { - *Bin = NULL; - } - - if (CellOffset == (BLOCK_OFFSET)-1) - { - return NULL; - } - - if (IsPointerHive (RegistryHive)) - { - return (PVOID)CellOffset; - } - - if (CellOffset > RegistryHive->BlockListSize * REG_BLOCK_SIZE) - { - DPRINT1("CellOffset exceeds valid range (%lu > %lu)\n", - CellOffset, RegistryHive->BlockListSize * REG_BLOCK_SIZE); - return NULL; - } - - pBin = RegistryHive->BlockList[CellOffset / REG_BLOCK_SIZE].Bin; - if (pBin == NULL) - { - return NULL; - } - - if (Bin != NULL) - { - *Bin = pBin; - } - - return((PVOID)((ULONG_PTR)pBin + (CellOffset - pBin->BinOffset))); -} - - -static BOOLEAN -CmiMergeFree(PREGISTRY_HIVE RegistryHive, - PCELL_HEADER FreeBlock, - BLOCK_OFFSET FreeOffset) -{ - BLOCK_OFFSET BlockOffset; - BLOCK_OFFSET BinOffset; - ULONG BlockSize; - ULONG BinSize; - PHBIN Bin; - ULONG i; - - DPRINT("CmiMergeFree(Block %lx Offset %lx Size %lx) called\n", - FreeBlock, FreeOffset, FreeBlock->CellSize); - - CmiGetCell (RegistryHive, - FreeOffset, - &Bin); - DPRINT("Bin %p\n", Bin); - if (Bin == NULL) - return(FALSE); - - BinOffset = Bin->BinOffset; - BinSize = Bin->BinSize; - DPRINT("Bin %p Offset %lx Size %lx\n", Bin, BinOffset, BinSize); - - for (i = 0; i < RegistryHive->FreeListSize; i++) - { - BlockOffset = RegistryHive->FreeListOffset[i]; - BlockSize = RegistryHive->FreeList[i]->CellSize; - if (BlockOffset > BinOffset && - BlockOffset < BinOffset + BinSize) - { - DPRINT("Free block: Offset %lx Size %lx\n", - BlockOffset, BlockSize); - - if ((i < (RegistryHive->FreeListSize - 1)) && - (BlockOffset + BlockSize == FreeOffset) && - (FreeOffset + FreeBlock->CellSize == RegistryHive->FreeListOffset[i + 1])) - { - DPRINT("Merge current block with previous and next block\n"); - - RegistryHive->FreeList[i]->CellSize += - (FreeBlock->CellSize + RegistryHive->FreeList[i + 1]->CellSize); - - FreeBlock->CellSize = 0; - RegistryHive->FreeList[i + 1]->CellSize = 0; - - - if ((i + 2) < RegistryHive->FreeListSize) - { - RtlMoveMemory(&RegistryHive->FreeList[i + 1], - &RegistryHive->FreeList[i + 2], - sizeof(RegistryHive->FreeList[0]) - * (RegistryHive->FreeListSize - i - 2)); - RtlMoveMemory(&RegistryHive->FreeListOffset[i + 1], - &RegistryHive->FreeListOffset[i + 2], - sizeof(RegistryHive->FreeListOffset[0]) - * (RegistryHive->FreeListSize - i - 2)); - } - RegistryHive->FreeListSize--; - - CmiMarkBlockDirty(RegistryHive, BlockOffset); - - return(TRUE); - } - else if (BlockOffset + BlockSize == FreeOffset) - { - DPRINT("Merge current block with previous block\n"); - - RegistryHive->FreeList[i]->CellSize += FreeBlock->CellSize; - FreeBlock->CellSize = 0; - - CmiMarkBlockDirty(RegistryHive, BlockOffset); - - return(TRUE); - } - else if (FreeOffset + FreeBlock->CellSize == BlockOffset) - { - DPRINT("Merge current block with next block\n"); - - FreeBlock->CellSize += RegistryHive->FreeList[i]->CellSize; - RegistryHive->FreeList[i]->CellSize = 0; - RegistryHive->FreeList[i] = FreeBlock; - RegistryHive->FreeListOffset[i] = FreeOffset; - - CmiMarkBlockDirty(RegistryHive, FreeOffset); - - return(TRUE); - } - } - } - - return(FALSE); -} - - -NTSTATUS -CmiAddFree(PREGISTRY_HIVE RegistryHive, - PCELL_HEADER FreeBlock, - BLOCK_OFFSET FreeOffset, - BOOLEAN MergeFreeBlocks) -{ - PCELL_HEADER *tmpList; - BLOCK_OFFSET *tmpListOffset; - LONG minInd; - LONG maxInd; - LONG medInd; - - ASSERT(RegistryHive); - ASSERT(FreeBlock); - - DPRINT("FreeBlock %.08lx FreeOffset %.08lx\n", - FreeBlock, FreeOffset); - - /* Merge free blocks */ - if (MergeFreeBlocks == TRUE) - { - if (CmiMergeFree(RegistryHive, FreeBlock, FreeOffset)) - return(STATUS_SUCCESS); - } - - if ((RegistryHive->FreeListSize + 1) > RegistryHive->FreeListMax) - { - tmpList = ExAllocatePool(PagedPool, - sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax + 32)); - if (tmpList == NULL) - return STATUS_INSUFFICIENT_RESOURCES; - - tmpListOffset = ExAllocatePool(PagedPool, - sizeof(BLOCK_OFFSET) * (RegistryHive->FreeListMax + 32)); - - if (tmpListOffset == NULL) - { - ExFreePool(tmpList); - return STATUS_INSUFFICIENT_RESOURCES; - } - - if (RegistryHive->FreeListMax) - { - RtlMoveMemory(tmpList, - RegistryHive->FreeList, - sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax)); - RtlMoveMemory(tmpListOffset, - RegistryHive->FreeListOffset, - sizeof(BLOCK_OFFSET) * (RegistryHive->FreeListMax)); - ExFreePool(RegistryHive->FreeList); - ExFreePool(RegistryHive->FreeListOffset); - } - RegistryHive->FreeList = tmpList; - RegistryHive->FreeListOffset = tmpListOffset; - RegistryHive->FreeListMax += 32; - } - - /* Add new offset to free list, maintaining list in ascending order */ - if ((RegistryHive->FreeListSize == 0) - || (RegistryHive->FreeListOffset[RegistryHive->FreeListSize-1] < FreeOffset)) - { - /* 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 - { - /* 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], - sizeof(RegistryHive->FreeList[0]) * (RegistryHive->FreeListSize - minInd)); - 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++; - } - - return STATUS_SUCCESS; -} - - -VOID -CmiMarkBlockDirty(PREGISTRY_HIVE RegistryHive, - BLOCK_OFFSET BlockOffset) -{ - PDATA_CELL Cell; - LONG CellSize; - ULONG BlockNumber; - ULONG BlockCount; - - if (IsNoFileHive(RegistryHive)) - return; - - DPRINT("CmiMarkBlockDirty(Offset 0x%lx)\n", (ULONG)BlockOffset); - - BlockNumber = (ULONG)BlockOffset / REG_BLOCK_SIZE; - - Cell = CmiGetCell (RegistryHive, - BlockOffset, - NULL); - - CellSize = Cell->CellSize; - if (CellSize < 0) - CellSize = -CellSize; - - BlockCount = (ROUND_UP(BlockOffset + CellSize, REG_BLOCK_SIZE) - - ROUND_DOWN(BlockOffset, REG_BLOCK_SIZE)) / REG_BLOCK_SIZE; - - DPRINT(" BlockNumber %lu Size %lu (%s) BlockCount %lu\n", - BlockNumber, - CellSize, - (Cell->CellSize < 0) ? "used" : "free", - BlockCount); - - RegistryHive->HiveDirty = TRUE; - RtlSetBits(&RegistryHive->DirtyBitMap, - BlockNumber, - BlockCount); -} - - -VOID -CmiMarkBinDirty(PREGISTRY_HIVE RegistryHive, - BLOCK_OFFSET BinOffset) -{ - ULONG BlockNumber; - ULONG BlockCount; - PHBIN Bin; - - if (IsNoFileHive(RegistryHive)) - return; - - DPRINT("CmiMarkBinDirty(Offset 0x%lx)\n", (ULONG)BinOffset); - - BlockNumber = (ULONG)BinOffset / REG_BLOCK_SIZE; - - Bin = RegistryHive->BlockList[BlockNumber].Bin; - - BlockCount = Bin->BinSize / REG_BLOCK_SIZE; - - DPRINT(" BlockNumber %lu BinSize %lu BlockCount %lu\n", - BlockNumber, - Bin->BinSize, - BlockCount); - - RegistryHive->HiveDirty = TRUE; - RtlSetBits(&RegistryHive->DirtyBitMap, - BlockNumber, - BlockCount); -} - - ULONG CmiGetPackedNameLength(IN PUNICODE_STRING Name, OUT PBOOLEAN Packable) @@ -3995,19 +1976,19 @@ CmiCompareKeyNamesI(PUNICODE_STRING KeyName, NTSTATUS -CmiCopyKey (PREGISTRY_HIVE DstHive, +CmiCopyKey (PEREGISTRY_HIVE DstHive, PKEY_CELL DstKeyCell, - PREGISTRY_HIVE SrcHive, + PEREGISTRY_HIVE SrcHive, PKEY_CELL SrcKeyCell) { PKEY_CELL NewKeyCell; ULONG NewKeyCellSize; - BLOCK_OFFSET NewKeyCellOffset; + HCELL_INDEX NewKeyCellOffset; PHASH_TABLE_CELL NewHashTableCell; ULONG NewHashTableSize; - BLOCK_OFFSET NewHashTableOffset; + HCELL_INDEX NewHashTableOffset; ULONG i; - NTSTATUS Status; + NTSTATUS Status = STATUS_SUCCESS; DPRINT ("CmiCopyKey() called\n"); @@ -4015,47 +1996,38 @@ CmiCopyKey (PREGISTRY_HIVE DstHive, { /* Allocate and copy key cell */ NewKeyCellSize = sizeof(KEY_CELL) + SrcKeyCell->NameSize; - Status = CmiAllocateCell (DstHive, - NewKeyCellSize, - (PVOID) &NewKeyCell, - &NewKeyCellOffset); - if (!NT_SUCCESS(Status)) - { - DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status); - return Status; - } - if (NewKeyCell == NULL) + NewKeyCellOffset = HvAllocateCell (DstHive->Hive, NewKeyCellSize, HvStable); + if (NewKeyCellOffset == HCELL_NULL) { DPRINT1 ("Failed to allocate a key cell\n"); return STATUS_INSUFFICIENT_RESOURCES; } + NewKeyCell = HvGetCell (DstHive->Hive, NewKeyCellOffset); RtlCopyMemory (NewKeyCell, SrcKeyCell, NewKeyCellSize); - DstHive->HiveHeader->RootKeyOffset = NewKeyCellOffset; + DstHive->Hive->HiveHeader->RootCell = NewKeyCellOffset; /* Copy class name */ - if (SrcKeyCell->ClassNameOffset != (BLOCK_OFFSET) -1) + if (SrcKeyCell->ClassNameOffset != (HCELL_INDEX) -1) { - PDATA_CELL SrcClassNameCell; - PDATA_CELL NewClassNameCell; - BLOCK_OFFSET NewClassNameOffset; + PVOID SrcClassNameCell; + PVOID NewClassNameCell; + HCELL_INDEX NewClassNameOffset; - SrcClassNameCell = CmiGetCell (SrcHive, SrcKeyCell->ClassNameOffset, NULL), + SrcClassNameCell = HvGetCell (SrcHive->Hive, SrcKeyCell->ClassNameOffset); NewKeyCell->ClassSize = SrcKeyCell->ClassSize; - Status = CmiAllocateCell (DstHive, - sizeof(CELL_HEADER) + NewKeyCell->ClassSize, - (PVOID)&NewClassNameCell, - &NewClassNameOffset); - if (!NT_SUCCESS(Status)) + NewClassNameOffset = HvAllocateCell (DstHive->Hive, NewKeyCell->ClassSize, HvStable); + if (NewClassNameOffset == HCELL_NULL) { - DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status); - return Status; + DPRINT1 ("CmiAllocateBlock() failed\n"); + return STATUS_INSUFFICIENT_RESOURCES; } + NewClassNameCell = HvGetCell (DstHive->Hive, NewClassNameOffset); RtlCopyMemory (NewClassNameCell, SrcClassNameCell, NewKeyCell->ClassSize); @@ -4068,19 +2040,20 @@ CmiCopyKey (PREGISTRY_HIVE DstHive, } /* Allocate hash table */ - if (SrcKeyCell->NumberOfSubKeys > 0) + if (SrcKeyCell->NumberOfSubKeys[HvStable] > 0) { - NewHashTableSize = ROUND_UP(SrcKeyCell->NumberOfSubKeys + 1, 4) - 1; + NewHashTableSize = ROUND_UP(SrcKeyCell->NumberOfSubKeys[HvStable] + 1, 4) - 1; Status = CmiAllocateHashTableCell (DstHive, &NewHashTableCell, &NewHashTableOffset, - NewHashTableSize); + NewHashTableSize, + HvStable); if (!NT_SUCCESS(Status)) { DPRINT1 ("CmiAllocateHashTableBlock() failed (Status %lx)\n", Status); return Status; } - NewKeyCell->HashTableOffset = NewHashTableOffset; + NewKeyCell->HashTableOffset[HvStable] = NewHashTableOffset; } else { @@ -4094,47 +2067,46 @@ CmiCopyKey (PREGISTRY_HIVE DstHive, PVALUE_LIST_CELL SrcValueListCell; PVALUE_CELL NewValueCell; PVALUE_CELL SrcValueCell; - PDATA_CELL SrcValueDataCell; - PDATA_CELL NewValueDataCell; - BLOCK_OFFSET ValueCellOffset; - BLOCK_OFFSET ValueDataCellOffset; + PVOID SrcValueDataCell; + PVOID NewValueDataCell; + HCELL_INDEX ValueCellOffset; + HCELL_INDEX ValueDataCellOffset; ULONG NewValueListCellSize; ULONG NewValueCellSize; NewValueListCellSize = - ROUND_UP(SrcKeyCell->NumberOfValues, 4) * sizeof(BLOCK_OFFSET); - Status = CmiAllocateCell (DstHive, - NewValueListCellSize, - (PVOID)&NewValueListCell, - &NewKeyCell->ValueListOffset); - if (!NT_SUCCESS(Status)) + ROUND_UP(SrcKeyCell->NumberOfValues, 4) * sizeof(HCELL_INDEX); + NewKeyCell->ValueListOffset = HvAllocateCell (DstHive->Hive, + NewValueListCellSize, + HvStable); + if (NewKeyCell->ValueListOffset == HCELL_NULL) { - DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status); - return Status; + DPRINT1 ("HvAllocateCell() failed\n"); + return STATUS_INSUFFICIENT_RESOURCES; } + DPRINT1("KeyCell->ValueListOffset: %x\n", NewKeyCell->ValueListOffset); + NewValueListCell = HvGetCell (DstHive->Hive, NewKeyCell->ValueListOffset); RtlZeroMemory (NewValueListCell, NewValueListCellSize); /* Copy values */ - SrcValueListCell = CmiGetCell (SrcHive, SrcKeyCell->ValueListOffset, NULL); + SrcValueListCell = HvGetCell (SrcHive->Hive, SrcKeyCell->ValueListOffset); for (i = 0; i < SrcKeyCell->NumberOfValues; i++) { /* Copy value cell */ - SrcValueCell = CmiGetCell (SrcHive, SrcValueListCell->ValueOffset[i], NULL); + SrcValueCell = HvGetCell (SrcHive->Hive, SrcValueListCell->ValueOffset[i]); NewValueCellSize = sizeof(VALUE_CELL) + SrcValueCell->NameSize; - Status = CmiAllocateCell (DstHive, - NewValueCellSize, - (PVOID*) &NewValueCell, - &ValueCellOffset); - if (!NT_SUCCESS(Status)) + ValueCellOffset = HvAllocateCell (DstHive->Hive, NewValueCellSize, HvStable); + if (ValueCellOffset == HCELL_NULL) { - DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status); - return Status; + DPRINT1 ("HvAllocateCell() failed (Status %lx)\n", Status); + return STATUS_INSUFFICIENT_RESOURCES; } + NewValueCell = HvGetCell (DstHive->Hive, ValueCellOffset); NewValueListCell->ValueOffset[i] = ValueCellOffset; RtlCopyMemory (NewValueCell, SrcValueCell, @@ -4143,17 +2115,15 @@ CmiCopyKey (PREGISTRY_HIVE DstHive, /* Copy value data cell */ if (SrcValueCell->DataSize > (LONG) sizeof(PVOID)) { - SrcValueDataCell = CmiGetCell (SrcHive, SrcValueCell->DataOffset, NULL); + SrcValueDataCell = HvGetCell (SrcHive->Hive, SrcValueCell->DataOffset); - Status = CmiAllocateCell (DstHive, - sizeof(CELL_HEADER) + SrcValueCell->DataSize, - (PVOID*) &NewValueDataCell, - &ValueDataCellOffset); - if (!NT_SUCCESS(Status)) + ValueDataCellOffset = HvAllocateCell (DstHive->Hive, SrcValueCell->DataSize, HvStable); + if (ValueDataCellOffset == HCELL_NULL) { - DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status); - return Status; + DPRINT1 ("HvAllocateCell() failed\n"); + return STATUS_INSUFFICIENT_RESOURCES; } + NewValueDataCell = HvGetCell (DstHive->Hive, ValueDataCellOffset); RtlCopyMemory (NewValueDataCell, SrcValueDataCell, SrcValueCell->DataSize); @@ -4163,41 +2133,32 @@ CmiCopyKey (PREGISTRY_HIVE DstHive, } /* Copy subkeys */ - if (SrcKeyCell->NumberOfSubKeys > 0) + if (SrcKeyCell->NumberOfSubKeys[HvStable] > 0) { PHASH_TABLE_CELL SrcHashTableCell; PKEY_CELL SrcSubKeyCell; PKEY_CELL NewSubKeyCell; ULONG NewSubKeyCellSize; - BLOCK_OFFSET NewSubKeyCellOffset; + HCELL_INDEX NewSubKeyCellOffset; PHASH_RECORD SrcHashRecord; - SrcHashTableCell = CmiGetCell (SrcHive, - SrcKeyCell->HashTableOffset, - NULL); + SrcHashTableCell = HvGetCell (SrcHive->Hive, SrcKeyCell->HashTableOffset[HvStable]); - for (i = 0; i < SrcKeyCell->NumberOfSubKeys; i++) + for (i = 0; i < SrcKeyCell->NumberOfSubKeys[HvStable]; i++) { SrcHashRecord = &SrcHashTableCell->Table[i]; - SrcSubKeyCell = CmiGetCell (SrcHive, SrcHashRecord->KeyOffset, NULL); + SrcSubKeyCell = HvGetCell (SrcHive->Hive, SrcHashRecord->KeyOffset); /* Allocate and copy key cell */ NewSubKeyCellSize = sizeof(KEY_CELL) + SrcSubKeyCell->NameSize; - Status = CmiAllocateCell (DstHive, - NewSubKeyCellSize, - (PVOID)&NewSubKeyCell, - &NewSubKeyCellOffset); - if (!NT_SUCCESS(Status)) - { - DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status); - return Status; - } - if (NewKeyCell == NULL) + NewSubKeyCellOffset = HvAllocateCell (DstHive->Hive, NewSubKeyCellSize, HvStable); + if (NewSubKeyCellOffset == HCELL_NULL) { DPRINT1 ("Failed to allocate a sub key cell\n"); return STATUS_INSUFFICIENT_RESOURCES; } + NewSubKeyCell = HvGetCell (DstHive->Hive, NewSubKeyCellOffset); NewHashTableCell->Table[i].KeyOffset = NewSubKeyCellOffset; NewHashTableCell->Table[i].HashValue = SrcHashRecord->HashValue; @@ -4206,27 +2167,26 @@ CmiCopyKey (PREGISTRY_HIVE DstHive, NewSubKeyCellSize); /* Copy class name */ - if (SrcSubKeyCell->ClassNameOffset != (BLOCK_OFFSET) -1) + if (SrcSubKeyCell->ClassNameOffset != (HCELL_INDEX) -1) { - PDATA_CELL SrcClassNameCell; - PDATA_CELL NewClassNameCell; - BLOCK_OFFSET NewClassNameOffset; + PVOID SrcClassNameCell; + PVOID NewClassNameCell; + HCELL_INDEX NewClassNameOffset; - SrcClassNameCell = CmiGetCell (SrcHive, - SrcSubKeyCell->ClassNameOffset, - NULL), + SrcClassNameCell = HvGetCell (SrcHive->Hive, + SrcSubKeyCell->ClassNameOffset); NewSubKeyCell->ClassSize = SrcSubKeyCell->ClassSize; - Status = CmiAllocateCell (DstHive, - sizeof(CELL_HEADER) + NewSubKeyCell->ClassSize, - (PVOID)&NewClassNameCell, - &NewClassNameOffset); - if (!NT_SUCCESS(Status)) + NewClassNameOffset = HvAllocateCell (DstHive->Hive, + NewSubKeyCell->ClassSize, + HvStable); + if (NewClassNameOffset == HCELL_NULL) { - DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status); - return Status; + DPRINT1 ("HvAllocateCell() failed (Status %lx)\n", Status); + return STATUS_INSUFFICIENT_RESOURCES; } + NewClassNameCell = HvGetCell (DstHive->Hive, NewClassNameOffset); NewSubKeyCell->ClassNameOffset = NewClassNameOffset; RtlCopyMemory (NewClassNameCell, SrcClassNameCell, @@ -4251,72 +2211,11 @@ CmiCopyKey (PREGISTRY_HIVE DstHive, NTSTATUS -CmiSaveTempHive (PREGISTRY_HIVE Hive, +CmiSaveTempHive (PEREGISTRY_HIVE Hive, HANDLE FileHandle) { - IO_STATUS_BLOCK IoStatusBlock; - LARGE_INTEGER FileOffset; - ULONG BlockIndex; - PVOID BlockPtr; - NTSTATUS Status; - - DPRINT ("CmiSaveTempHive() called\n"); - - Hive->HiveHeader->Checksum = CmiCalcChecksum ((PULONG)Hive->HiveHeader); - - /* Write hive block */ - FileOffset.QuadPart = (ULONGLONG)0; - Status = ZwWriteFile (FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - Hive->HiveHeader, - sizeof(HIVE_HEADER), - &FileOffset, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1 ("ZwWriteFile() failed (Status %lx)\n", Status); - return Status; - } - - DPRINT ("Saving %lu blocks\n", Hive->BlockListSize); - for (BlockIndex = 0; BlockIndex < Hive->BlockListSize; BlockIndex++) - { - BlockPtr = Hive->BlockList[BlockIndex].Block; - DPRINT ("BlockPtr %p\n", BlockPtr); - - FileOffset.QuadPart = (ULONGLONG)(BlockIndex + 1) * (ULONGLONG)REG_BLOCK_SIZE; - DPRINT ("File offset %I64x\n", FileOffset.QuadPart); - - /* Write hive block */ - Status = ZwWriteFile (FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - BlockPtr, - REG_BLOCK_SIZE, - &FileOffset, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1 ("ZwWriteFile() failed (Status %lx)\n", Status); - return Status; - } - } - - Status = ZwFlushBuffersFile (FileHandle, - &IoStatusBlock); - if (!NT_SUCCESS(Status)) - { - DPRINT1 ("ZwFlushBuffersFile() failed (Status %lx)\n", Status); - } - - DPRINT ("CmiSaveTempHive() done\n"); - - return Status; + Hive->HiveHandle = FileHandle; + return HvWriteHive(Hive->Hive) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; } /* EOF */ diff --git a/reactos/ntoskrnl/cm/registry.c b/reactos/ntoskrnl/cm/registry.c index 66ad3a19fac..b47b6b8f1bb 100644 --- a/reactos/ntoskrnl/cm/registry.c +++ b/reactos/ntoskrnl/cm/registry.c @@ -28,7 +28,7 @@ /* GLOBALS ******************************************************************/ POBJECT_TYPE CmiKeyType = NULL; -PREGISTRY_HIVE CmiVolatileHive = NULL; +PEREGISTRY_HIVE CmiVolatileHive = NULL; LIST_ENTRY CmiHiveListHead; @@ -67,193 +67,6 @@ extern FAST_MUTEX CmiCallbackLock; /* FUNCTIONS ****************************************************************/ -VOID -CmiCheckSubKeys(BOOLEAN Verbose, - HANDLE Key) -{ - OBJECT_ATTRIBUTES ObjectAttributes; - PKEY_NODE_INFORMATION KeyInfo; - WCHAR KeyBuffer[MAX_PATH]; - UNICODE_STRING KeyPath; - WCHAR Name[MAX_PATH]; - ULONG BufferSize; - ULONG ResultSize; - NTSTATUS Status; - HANDLE SubKey; - ULONG Index; - - Index = 0; - while (TRUE) - { - BufferSize = sizeof(KEY_NODE_INFORMATION) + 4096; - KeyInfo = ExAllocatePool(PagedPool, BufferSize); - - Status = ZwEnumerateKey(Key, - Index, - KeyNodeInformation, - KeyInfo, - BufferSize, - &ResultSize); - if (!NT_SUCCESS(Status)) - { - ExFreePool(KeyInfo); - if (Status == STATUS_NO_MORE_ENTRIES) - Status = STATUS_SUCCESS; - break; - } - - wcsncpy(Name, - KeyInfo->Name, - KeyInfo->NameLength / sizeof(WCHAR)); - - if (Verbose) - { - DbgPrint("Key: %S\n", Name); - } - - /* FIXME: Check info. */ - - ExFreePool(KeyInfo); - - wcscpy(KeyBuffer, L"\\Registry\\"); - wcscat(KeyBuffer, Name); - - RtlInitUnicodeString(&KeyPath, KeyBuffer); - - InitializeObjectAttributes(&ObjectAttributes, - &KeyPath, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = ZwOpenKey(&SubKey, - KEY_ALL_ACCESS, - &ObjectAttributes); - - ASSERT(NT_SUCCESS(Status)); - - CmiCheckKey(Verbose, SubKey); - - ZwClose(SubKey); - - Index++; - } - - ASSERT(NT_SUCCESS(Status)); -} - - -VOID -CmiCheckValues(BOOLEAN Verbose, - HANDLE Key) -{ - PKEY_NODE_INFORMATION ValueInfo; - WCHAR Name[MAX_PATH]; - ULONG BufferSize; - ULONG ResultSize; - NTSTATUS Status; - ULONG Index; - - Index = 0; - while (TRUE) - { - BufferSize = sizeof(KEY_NODE_INFORMATION) + 4096; - ValueInfo = ExAllocatePool(PagedPool, BufferSize); - - Status = ZwEnumerateValueKey(Key, - Index, - KeyNodeInformation, - ValueInfo, - BufferSize, - &ResultSize); - if (!NT_SUCCESS(Status)) - { - ExFreePool(ValueInfo); - if (Status == STATUS_NO_MORE_ENTRIES) - Status = STATUS_SUCCESS; - break; - } - - wcsncpy(Name, - ValueInfo->Name, - ValueInfo->NameLength / sizeof(WCHAR)); - - if (Verbose) - { - DbgPrint("Value: %S\n", Name); - } - - /* FIXME: Check info. */ - - ExFreePool(ValueInfo); - - Index++; - } - - ASSERT(NT_SUCCESS(Status)); -} - - -VOID -CmiCheckKey(BOOLEAN Verbose, - HANDLE Key) -{ - CmiCheckValues(Verbose, Key); - CmiCheckSubKeys(Verbose, Key); -} - - -VOID -CmiCheckByName(BOOLEAN Verbose, - PWSTR KeyName) -{ - OBJECT_ATTRIBUTES ObjectAttributes; - WCHAR KeyPathBuffer[MAX_PATH]; - UNICODE_STRING KeyPath; - NTSTATUS Status; - HANDLE Key; - - wcscpy(KeyPathBuffer, L"\\Registry\\"); - wcscat(KeyPathBuffer, KeyName); - - RtlInitUnicodeString(&KeyPath, KeyPathBuffer); - - InitializeObjectAttributes(&ObjectAttributes, - &KeyPath, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = ZwOpenKey(&Key, - KEY_ALL_ACCESS, - &ObjectAttributes); - - if (CHECKED) - { - if (!NT_SUCCESS(Status)) - { - DbgPrint("KeyPath %wZ Status: %.08x", KeyPath, Status); - DbgPrint("KeyPath %S Status: %.08x", KeyPath.Buffer, Status); - ASSERT(NT_SUCCESS(Status)); - } - } - - CmiCheckKey(Verbose, Key); - - ZwClose(Key); -} - - -VOID -CmiCheckRegistry(BOOLEAN Verbose) -{ - if (Verbose) - DbgPrint("Checking registry internals\n"); - - CmiCheckByName(Verbose, L"Machine"); - CmiCheckByName(Verbose, L"User"); -} - VOID STDCALL CmiWorkerThread(PVOID Param) { @@ -315,6 +128,7 @@ CmiWorkerThread(PVOID Param) } } + VOID INIT_FUNCTION STDCALL @@ -436,8 +250,8 @@ CmInitializeRegistry(VOID) &RootKeyHandle); ASSERT(NT_SUCCESS(Status)); RootKey->RegistryHive = CmiVolatileHive; - RootKey->KeyCellOffset = CmiVolatileHive->HiveHeader->RootKeyOffset; - RootKey->KeyCell = CmiGetCell (CmiVolatileHive, RootKey->KeyCellOffset, NULL); + RootKey->KeyCellOffset = CmiVolatileHive->Hive->HiveHeader->RootCell; + RootKey->KeyCell = HvGetCell (CmiVolatileHive->Hive, RootKey->KeyCellOffset); RootKey->ParentKey = RootKey; RootKey->Flags = 0; RootKey->NumberOfSubKeys = 0; @@ -698,7 +512,7 @@ CmiCreateCurrentControlSetLink(VOID) NTSTATUS CmiConnectHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes, - IN PREGISTRY_HIVE RegistryHive) + IN PEREGISTRY_HIVE RegistryHive) { UNICODE_STRING RemainingPath; PKEY_OBJECT ParentKey; @@ -791,34 +605,50 @@ CmiConnectHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes, 0, NULL, NULL); - DPRINT("Status %x\n", Status); - NewKey->RegistryHive = RegistryHive; - NewKey->KeyCellOffset = RegistryHive->HiveHeader->RootKeyOffset; - NewKey->KeyCell = CmiGetCell (RegistryHive, NewKey->KeyCellOffset, NULL); - NewKey->Flags = 0; - NewKey->NumberOfSubKeys = 0; - NewKey->SubKeys = NULL; - InsertTailList(&CmiKeyObjectListHead, &NewKey->ListEntry); - InsertTailList(&CmiConnectedHiveList, &NewKey->HiveList); + DPRINT("Status %x\n", Status); + NewKey->Flags = 0; + NewKey->NumberOfSubKeys = 0; + NewKey->SubKeys = NULL; + NewKey->SizeOfSubKeys = 0; + InsertTailList(&CmiKeyObjectListHead, &NewKey->ListEntry); - DPRINT ("SubName %S\n", SubName); + DPRINT ("SubName %S\n", SubName); - Status = RtlpCreateUnicodeString(&NewKey->Name, - SubName, NonPagedPool); - RtlFreeUnicodeString(&RemainingPath); - if (!NT_SUCCESS(Status)) - { - DPRINT1("RtlpCreateUnicodeString() failed (Status %lx)\n", Status); - if (NewKey->SubKeys != NULL) - { - ExFreePool (NewKey->SubKeys); - } - ObDereferenceObject (NewKey); - ObDereferenceObject (ParentKey); - return STATUS_INSUFFICIENT_RESOURCES; - } + Status = CmiAddSubKey(ParentKey->RegistryHive, + ParentKey, + NewKey, + &RemainingPath, + 0, + NULL, + REG_OPTION_VOLATILE); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CmiAddSubKey() failed (Status %lx)\n", Status); + ObDereferenceObject (NewKey); + ObDereferenceObject (ParentKey); + return STATUS_INSUFFICIENT_RESOURCES; + } - CmiAddKeyToList (ParentKey, NewKey); + NewKey->KeyCellOffset = RegistryHive->Hive->HiveHeader->RootCell; + NewKey->KeyCell = HvGetCell (RegistryHive->Hive, NewKey->KeyCellOffset); + NewKey->RegistryHive = RegistryHive; + + Status = RtlpCreateUnicodeString(&NewKey->Name, + SubName, NonPagedPool); + RtlFreeUnicodeString(&RemainingPath); + if (!NT_SUCCESS(Status)) + { + DPRINT1("RtlpCreateUnicodeString() failed (Status %lx)\n", Status); + ObDereferenceObject (NewKey); + ObDereferenceObject (ParentKey); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* FN1 */ + ObReferenceObject (NewKey); + + CmiAddKeyToList (ParentKey, NewKey); + ObDereferenceObject (ParentKey); VERIFY_KEY_OBJECT(NewKey); @@ -832,9 +662,10 @@ CmiConnectHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes, NTSTATUS CmiDisconnectHive (IN POBJECT_ATTRIBUTES KeyObjectAttributes, - OUT PREGISTRY_HIVE *RegistryHive) + OUT PEREGISTRY_HIVE *RegistryHive) { PKEY_OBJECT KeyObject; + PEREGISTRY_HIVE Hive; HANDLE KeyHandle; NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND; PLIST_ENTRY CurrentEntry; @@ -876,25 +707,47 @@ CmiDisconnectHive (IN POBJECT_ATTRIBUTES KeyObjectAttributes, KeEnterCriticalRegion(); ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE); - /* Find out if we represent a connected hive. */ - for( CurrentEntry = CmiConnectedHiveList.Flink; - CurrentEntry != &CmiConnectedHiveList; - CurrentEntry = CurrentEntry->Flink ) { - CurrentKey = CONTAINING_RECORD(CurrentEntry, KEY_OBJECT, HiveList); - if( CurrentKey == KeyObject ) { - /* Remove the connected hive from the connected hive list */ - RemoveEntryList(CurrentEntry); - /* found ourselves in the connected hive list */ - *RegistryHive = KeyObject->RegistryHive; - Status = STATUS_SUCCESS; + Hive = KeyObject->RegistryHive; - /* Release references captured in CmiConnectHive */ - ObDereferenceObject (KeyObject->ParentKey); - ObDereferenceObject (KeyObject); - break; - } + CurrentEntry = CmiKeyObjectListHead.Flink; + while (CurrentEntry != &CmiKeyObjectListHead) + { + CurrentKey = CONTAINING_RECORD(CurrentEntry, KEY_OBJECT, ListEntry); + if (CurrentKey->RegistryHive == Hive && + 1 == ObGetObjectPointerCount(CurrentKey) && + !(CurrentKey->Flags & KO_MARKED_FOR_DELETE)) + { + ObDereferenceObject(CurrentKey); + CurrentEntry = CmiKeyObjectListHead.Flink; + } + else + { + CurrentEntry = CurrentEntry->Flink; + } } - + + /* FN1 */ + ObDereferenceObject (KeyObject); + + if (ObGetObjectHandleCount (KeyObject) != 0 || + ObGetObjectPointerCount (KeyObject) != 2) + { + DPRINT1 ("Hive is still in use (hc %d, rc %d)\n", ObGetObjectHandleCount (KeyObject), ObGetObjectPointerCount (KeyObject)); + ObDereferenceObject (KeyObject); + + /* Release registry lock */ + ExReleaseResourceLite (&CmiRegistryLock); + KeLeaveCriticalRegion(); + + return STATUS_UNSUCCESSFUL; + } + + /* Dereference KeyObject twice to delete it */ + ObDereferenceObject (KeyObject); + ObDereferenceObject (KeyObject); + + *RegistryHive = Hive; + /* Release registry lock */ ExReleaseResourceLite (&CmiRegistryLock); KeLeaveCriticalRegion(); @@ -1050,8 +903,6 @@ CmiInitHives(BOOLEAN SetupBoot) EndPtr = ConfigPath + wcslen(ConfigPath); - CmiDoVerify = TRUE; - /* FIXME: Save boot log */ /* Connect the SYSTEM hive only if it has been created */ @@ -1194,7 +1045,7 @@ CmiInitHives(BOOLEAN SetupBoot) VOID CmShutdownRegistry(VOID) { - PREGISTRY_HIVE Hive; + PEREGISTRY_HIVE Hive; PLIST_ENTRY Entry; DPRINT("CmShutdownRegistry() called\n"); @@ -1216,7 +1067,7 @@ CmShutdownRegistry(VOID) Entry = CmiHiveListHead.Flink; while (Entry != &CmiHiveListHead) { - Hive = CONTAINING_RECORD(Entry, REGISTRY_HIVE, HiveList); + Hive = CONTAINING_RECORD(Entry, EREGISTRY_HIVE, HiveList); if (!(IsNoFileHive(Hive) || IsNoSynchHive(Hive))) { @@ -1238,7 +1089,7 @@ CmShutdownRegistry(VOID) VOID STDCALL CmiHiveSyncRoutine(PVOID DeferredContext) { - PREGISTRY_HIVE Hive; + PEREGISTRY_HIVE Hive; PLIST_ENTRY Entry; DPRINT("CmiHiveSyncRoutine() called\n"); @@ -1252,7 +1103,7 @@ CmiHiveSyncRoutine(PVOID DeferredContext) Entry = CmiHiveListHead.Flink; while (Entry != &CmiHiveListHead) { - Hive = CONTAINING_RECORD(Entry, REGISTRY_HIVE, HiveList); + Hive = CONTAINING_RECORD(Entry, EREGISTRY_HIVE, HiveList); if (!(IsNoFileHive(Hive) || IsNoSynchHive(Hive))) { diff --git a/reactos/ntoskrnl/cm/regobj.c b/reactos/ntoskrnl/cm/regobj.c index 290f1d5232c..e96f1480614 100644 --- a/reactos/ntoskrnl/cm/regobj.c +++ b/reactos/ntoskrnl/cm/regobj.c @@ -18,7 +18,7 @@ extern LIST_ENTRY CmiKeyObjectListHead; extern ULONG CmiTimer; static NTSTATUS -CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive, +CmiGetLinkTarget(PEREGISTRY_HIVE RegistryHive, PKEY_CELL KeyCell, PUNICODE_STRING TargetPath); @@ -233,7 +233,7 @@ CmiObjectParse(IN PVOID ParsedObject, IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL, OUT PVOID *NextObject) { - BLOCK_OFFSET BlockOffset; + HCELL_INDEX BlockOffset; PKEY_OBJECT FoundObject; PKEY_OBJECT ParsedKey; PKEY_CELL SubKeyCell; @@ -285,7 +285,6 @@ CmiObjectParse(IN PVOID ParsedObject, KeEnterCriticalRegion(); ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE); - Status = CmiScanKeyList(ParsedKey, &KeyName, Attributes, @@ -300,93 +299,93 @@ CmiObjectParse(IN PVOID ParsedObject, if (FoundObject == NULL) { Status = CmiScanForSubKey(ParsedKey->RegistryHive, - ParsedKey->KeyCell, - &SubKeyCell, - &BlockOffset, - &KeyName, - 0, - Attributes); - if (!NT_SUCCESS(Status) || (SubKeyCell == NULL)) - { + ParsedKey->KeyCell, + &SubKeyCell, + &BlockOffset, + &KeyName, + 0, + Attributes); + if (!NT_SUCCESS(Status)) + { ExReleaseResourceLite(&CmiRegistryLock); KeLeaveCriticalRegion(); - RtlFreeUnicodeString(&KeyName); - return(STATUS_UNSUCCESSFUL); - } + RtlFreeUnicodeString(&KeyName); + return(STATUS_UNSUCCESSFUL); + } if ((SubKeyCell->Flags & REG_KEY_LINK_CELL) && - !((Attributes & OBJ_OPENLINK) && (EndPtr == NULL))) - { - RtlInitUnicodeString(&LinkPath, NULL); - Status = CmiGetLinkTarget(ParsedKey->RegistryHive, - SubKeyCell, - &LinkPath); - if (NT_SUCCESS(Status)) - { + !((Attributes & OBJ_OPENLINK) && (EndPtr == NULL))) + { + RtlInitUnicodeString(&LinkPath, NULL); + Status = CmiGetLinkTarget(ParsedKey->RegistryHive, + SubKeyCell, + &LinkPath); + if (NT_SUCCESS(Status)) + { ExReleaseResourceLite(&CmiRegistryLock); KeLeaveCriticalRegion(); - DPRINT("LinkPath '%wZ'\n", &LinkPath); + DPRINT("LinkPath '%wZ'\n", &LinkPath); - /* build new FullPath for reparsing */ - TargetPath.MaximumLength = LinkPath.MaximumLength; - if (EndPtr != NULL) - { - TargetPath.MaximumLength += (wcslen(EndPtr) * sizeof(WCHAR)); - } - TargetPath.Length = TargetPath.MaximumLength - sizeof(WCHAR); - TargetPath.Buffer = ExAllocatePool(NonPagedPool, - TargetPath.MaximumLength); - wcscpy(TargetPath.Buffer, LinkPath.Buffer); - if (EndPtr != NULL) - { - wcscat(TargetPath.Buffer, EndPtr); - } + /* build new FullPath for reparsing */ + TargetPath.MaximumLength = LinkPath.MaximumLength; + if (EndPtr != NULL) + { + TargetPath.MaximumLength += (wcslen(EndPtr) * sizeof(WCHAR)); + } + TargetPath.Length = TargetPath.MaximumLength - sizeof(WCHAR); + TargetPath.Buffer = ExAllocatePool(NonPagedPool, + TargetPath.MaximumLength); + wcscpy(TargetPath.Buffer, LinkPath.Buffer); + if (EndPtr != NULL) + { + wcscat(TargetPath.Buffer, EndPtr); + } - RtlFreeUnicodeString(FullPath); - RtlFreeUnicodeString(&LinkPath); - FullPath->Length = TargetPath.Length; - FullPath->MaximumLength = TargetPath.MaximumLength; - FullPath->Buffer = TargetPath.Buffer; + RtlFreeUnicodeString(FullPath); + RtlFreeUnicodeString(&LinkPath); + FullPath->Length = TargetPath.Length; + FullPath->MaximumLength = TargetPath.MaximumLength; + FullPath->Buffer = TargetPath.Buffer; - DPRINT("FullPath '%wZ'\n", FullPath); + DPRINT("FullPath '%wZ'\n", FullPath); - /* reinitialize Path for reparsing */ - *Path = FullPath->Buffer; + /* reinitialize Path for reparsing */ + *Path = FullPath->Buffer; - *NextObject = NULL; + *NextObject = NULL; - RtlFreeUnicodeString(&KeyName); - return(STATUS_REPARSE); - } - } + RtlFreeUnicodeString(&KeyName); + return(STATUS_REPARSE); + } + } /* Create new key object and put into linked list */ DPRINT("CmiObjectParse: %S\n", *Path); Status = ObCreateObject(KernelMode, - CmiKeyType, - NULL, - KernelMode, - NULL, - sizeof(KEY_OBJECT), - 0, - 0, - (PVOID*)&FoundObject); + CmiKeyType, + NULL, + KernelMode, + NULL, + sizeof(KEY_OBJECT), + 0, + 0, + (PVOID*)&FoundObject); if (!NT_SUCCESS(Status)) - { + { ExReleaseResourceLite(&CmiRegistryLock); KeLeaveCriticalRegion(); - RtlFreeUnicodeString(&KeyName); - return(Status); - } - DPRINT("Inserting Key into Object Tree\n"); - Status = ObInsertObject((PVOID)FoundObject, - NULL, - KEY_ALL_ACCESS, - 0, - NULL, - NULL); - DPRINT("Status %x\n", Status); + RtlFreeUnicodeString(&KeyName); + return(Status); + } + DPRINT("Inserting Key into Object Tree\n"); + Status = ObInsertObject((PVOID)FoundObject, + NULL, + KEY_ALL_ACCESS, + 0, + NULL, + NULL); + DPRINT("Status %x\n", Status); /* Add the keep-alive reference */ ObReferenceObject(FoundObject); @@ -396,8 +395,7 @@ CmiObjectParse(IN PVOID ParsedObject, FoundObject->KeyCellOffset = BlockOffset; FoundObject->RegistryHive = ParsedKey->RegistryHive; InsertTailList(&CmiKeyObjectListHead, &FoundObject->ListEntry); - RtlpCreateUnicodeString(&FoundObject->Name, - KeyName.Buffer, NonPagedPool); + RtlpCreateUnicodeString(&FoundObject->Name, KeyName.Buffer, NonPagedPool); CmiAddKeyToList(ParsedKey, FoundObject); DPRINT("Created object 0x%p\n", FoundObject); } @@ -462,7 +460,7 @@ CmiObjectParse(IN PVOID ParsedObject, ExReleaseResourceLite(&CmiRegistryLock); KeLeaveCriticalRegion(); - //DPRINT("CmiObjectParse: %s\n", FoundObject->Name); + DPRINT("CmiObjectParse: %wZ\n", &FoundObject->Name); *Path = EndPtr; @@ -509,8 +507,8 @@ CmiObjectDelete(PVOID DeletedObject) KeyObject); KeQuerySystemTime (&ParentKeyObject->KeyCell->LastWriteTime); - CmiMarkBlockDirty (ParentKeyObject->RegistryHive, - ParentKeyObject->KeyCellOffset); + HvMarkCellDirty (ParentKeyObject->RegistryHive->Hive, + ParentKeyObject->KeyCellOffset); if (!IsNoFileHive (KeyObject->RegistryHive) || !IsNoFileHive (ParentKeyObject->RegistryHive)) @@ -521,9 +519,6 @@ CmiObjectDelete(PVOID DeletedObject) ObDereferenceObject (ParentKeyObject); - ExReleaseResourceLite(&CmiRegistryLock); - KeLeaveCriticalRegion(); - if (KeyObject->NumberOfSubKeys) { KEBUGCHECK(REGISTRY_ERROR); @@ -533,6 +528,9 @@ CmiObjectDelete(PVOID DeletedObject) { ExFreePool(KeyObject->SubKeys); } + + ExReleaseResourceLite(&CmiRegistryLock); + KeLeaveCriticalRegion(); } @@ -618,7 +616,7 @@ CmiAssignSecurityDescriptor(PKEY_OBJECT KeyObject, PSECURITY_DESCRIPTOR SecurityDescriptor) { #if 0 - PREGISTRY_HIVE Hive; + PEREGISTRY_HIVE Hive; DPRINT1("CmiAssignSecurityDescriptor() callled\n"); @@ -755,6 +753,7 @@ CmiObjectQueryName (PVOID ObjectBody, } + VOID CmiAddKeyToList(PKEY_OBJECT ParentKey, PKEY_OBJECT NewKey) @@ -843,6 +842,7 @@ CmiScanKeyList(PKEY_OBJECT Parent, CurKey = Parent->SubKeys[Index]; if (Attributes & OBJ_CASE_INSENSITIVE) { + DPRINT("Comparing %wZ and %wZ\n", KeyName, &CurKey->Name); if ((KeyName->Length == CurKey->Name.Length) && (_wcsicmp(KeyName->Buffer, CurKey->Name.Buffer) == 0)) { @@ -863,6 +863,7 @@ CmiScanKeyList(PKEY_OBJECT Parent, { if (CurKey->Flags & KO_MARKED_FOR_DELETE) { + CHECKPOINT; *ReturnedObject = NULL; return STATUS_UNSUCCESSFUL; } @@ -878,13 +879,13 @@ CmiScanKeyList(PKEY_OBJECT Parent, static NTSTATUS -CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive, +CmiGetLinkTarget(PEREGISTRY_HIVE RegistryHive, PKEY_CELL KeyCell, PUNICODE_STRING TargetPath) { UNICODE_STRING LinkName = RTL_CONSTANT_STRING(L"SymbolicLinkValue"); PVALUE_CELL ValueCell; - PDATA_CELL DataCell; + PVOID DataCell; NTSTATUS Status; DPRINT("CmiGetLinkTarget() called\n"); @@ -920,9 +921,9 @@ CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive, if (ValueCell->DataSize > 0) { - DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL); + DataCell = HvGetCell (RegistryHive->Hive, ValueCell->DataOffset); RtlCopyMemory(TargetPath->Buffer, - DataCell->Data, + DataCell, TargetPath->Length); TargetPath->Buffer[TargetPath->Length / sizeof(WCHAR)] = 0; } diff --git a/reactos/ntoskrnl/ntoskrnl.rbuild b/reactos/ntoskrnl/ntoskrnl.rbuild index 5b031e23711..c88613b5b8d 100644 --- a/reactos/ntoskrnl/ntoskrnl.rbuild +++ b/reactos/ntoskrnl/ntoskrnl.rbuild @@ -8,12 +8,14 @@ include + . include include/reactos/drivers csq hal kjs pseh + cmlib rtl rossym string