Index: tools/mkhive/binhive.c =================================================================== --- tools/mkhive/binhive.c (revision 19688) +++ tools/mkhive/binhive.c (working copy) @@ -107,7 +107,7 @@ ULONG Unused7; /* Name of hive file */ - WCHAR FileName[48]; + WCHAR FileName[32]; ULONG Reserved[99]; @@ -1248,7 +1248,11 @@ Buffer = (PULONG)Hive->HiveHeader; Sum = 0; for (i = 0; i < 127; i++) - Sum += Buffer[i]; + Sum ^= Buffer[i]; + if (Sum == (ULONG)-1) + Sum = (ULONG)-2; + if (Sum == 0) + Sum = 1; Hive->HiveHeader->Checksum = Sum; } Index: boot/freeldr/freeldr/reactos/binhive.c =================================================================== --- boot/freeldr/freeldr/reactos/binhive.c (revision 19665) +++ boot/freeldr/freeldr/reactos/binhive.c (working copy) @@ -20,855 +20,74 @@ */ #include +#include #define NDEBUG #include -#define REG_HIVE_ID 0x66676572 /* "regf" */ -#define REG_BIN_ID 0x6e696268 /* "hbin" */ -#define REG_KEY_CELL_ID 0x6b6e -#define REG_HASH_TABLE_BLOCK_ID 0x666c -#define REG_VALUE_CELL_ID 0x6b76 - -#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 ABS_VALUE(V) (((V) < 0) ? -(V) : (V)) - - -/* BLOCK_OFFSET = offset in file after header block */ -typedef ULONG BLOCK_OFFSET, *PBLOCK_OFFSET; - -/* 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 */ - ULONGLONG 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[48]; - - ULONG Reserved[99]; - - /* Checksum of first 0x200 bytes */ - ULONG Checksum; -} __attribute__((packed)) 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 */ - ULONGLONG DateModified; - - /* ? (In-memory only) */ - ULONG MemAlloc; -} __attribute__((packed)) HBIN, *PHBIN; - - -typedef struct _CELL_HEADER -{ - /* <0 if used, >0 if free */ - LONG CellSize; -} __attribute__((packed)) 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 */ - ULONGLONG LastWriteTime; /* FILETIME */ - - /* ? */ - 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) */ - CHAR Name[0]; -} __attribute__((packed)) KEY_CELL, *PKEY_CELL; - - -/* KEY_CELL.Type constants */ -#define REG_LINK_KEY_CELL_TYPE 0x10 -#define REG_KEY_NAME_PACKED 0x20 -#define REG_ROOT_KEY_CELL_TYPE 0x0c - - -// hash record : -// HashValue=four letters of value's name -typedef struct _HASH_RECORD -{ - BLOCK_OFFSET KeyOffset; - ULONG HashValue; -} __attribute__((packed)) HASH_RECORD, *PHASH_RECORD; - - -typedef struct _HASH_TABLE_CELL -{ - LONG CellSize; - USHORT Id; - USHORT HashTableSize; - HASH_RECORD Table[0]; -} __attribute__((packed)) HASH_TABLE_CELL, *PHASH_TABLE_CELL; - - -typedef struct _VALUE_LIST_CELL -{ - LONG CellSize; - BLOCK_OFFSET ValueOffset[0]; -} __attribute__((packed)) 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; - CHAR Name[0]; /* warning : not zero terminated */ -} __attribute__((packed)) 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 _DATA_CELL -{ - LONG CellSize; - CHAR Data[0]; -} __attribute__((packed)) DATA_CELL, *PDATA_CELL; - - -typedef struct _REGISTRY_HIVE -{ - ULONG FileSize; - PHIVE_HEADER HiveHeader; - ULONG BlockListSize; - PHBIN *BlockList; - ULONG FreeListSize; - ULONG FreeListMax; - PCELL_HEADER *FreeList; - BLOCK_OFFSET *FreeListOffset; -} REGISTRY_HIVE, *PREGISTRY_HIVE; - - -static PVOID MbBase = NULL; -static ULONG MbSize = 0; - /* FUNCTIONS ****************************************************************/ -static VOID -InitMbMemory (PVOID ChunkBase) +void *CmpAllocate(ULONG size) { - MbBase = ChunkBase; - MbSize = 0; + return MmAllocateMemory(size); } -static PVOID -AllocateMbMemory (ULONG MemSize) +void *CmpAllocatePaged(ULONG size) { - PVOID CurBase; - - CurBase = MbBase; - - MbBase = (PVOID)((ULONG)MbBase + MemSize); - MbSize += MemSize; - - return CurBase; + return MmAllocateMemory(size); } -static VOID -FreeMbMemory (VOID) -{ - MbSize = 0; -} -static ULONG -GetMbAllocatedSize (VOID) +void CmpFree(void *ptr) { - return MbSize; + return MmFreeMemory(ptr); } -static VOID -CmiCreateDefaultHiveHeader (PHIVE_HEADER Header) +VOID +NTAPI +RtlAssert(PVOID FailedAssertion, + PVOID FileName, + ULONG LineNumber, + PCHAR Message) { - assert(Header); - memset (Header, 0, REG_BLOCK_SIZE); - Header->BlockId = REG_HIVE_ID; - Header->UpdateCounter1 = 0; - Header->UpdateCounter2 = 0; - Header->DateModified = 0; - Header->MajorVersion = 1; - Header->MinorVersion = 3; - Header->Type = 0; - Header->Format = 1; - Header->Unused7 = 1; - Header->RootKeyOffset = -1; - Header->BlockSize = REG_BLOCK_SIZE; - Header->Checksum = 0; + if (NULL != Message) + { + printf("Assertion \'%s\' failed at %s line %d: %s\n", + (PCHAR)FailedAssertion, + (PCHAR)FileName, + LineNumber, + Message); + } + else + { + printf("Assertion \'%s\' failed at %s line %d\n", + (PCHAR)FailedAssertion, + (PCHAR)FileName, + LineNumber); + } } -static VOID -CmiCreateDefaultBinCell (PHBIN BinCell) -{ - assert(BinCell); - memset (BinCell, 0, REG_BLOCK_SIZE); - BinCell->HeaderId = REG_BIN_ID; - BinCell->DateModified = 0ULL; - BinCell->BinSize = REG_BLOCK_SIZE; -} - - -static VOID -CmiCreateDefaultRootKeyCell (PKEY_CELL RootKeyCell, PCWSTR KeyName) -{ - PWCHAR BaseKeyName; - ULONG NameSize; - ULONG CellSize; - ULONG i; - BOOL Packable = TRUE; - - assert (RootKeyCell); - - BaseKeyName = wcsrchr(KeyName, L'\\') + 1; - NameSize = wcslen(BaseKeyName); - for (i = 0; i < NameSize; i++) - { - if (KeyName[i] & 0xFF00) - { - Packable = FALSE; - NameSize *= sizeof(WCHAR); - break; - } - } - - CellSize = ROUND_UP(sizeof(KEY_CELL) + NameSize, 16); - - memset (RootKeyCell, 0, CellSize); - RootKeyCell->CellSize = -CellSize; - RootKeyCell->Id = REG_KEY_CELL_ID; - RootKeyCell->Flags = REG_ROOT_KEY_CELL_TYPE; - RootKeyCell->LastWriteTime = 0ULL; - RootKeyCell->ParentKeyOffset = 0; - RootKeyCell->NumberOfSubKeys = 0; - RootKeyCell->HashTableOffset = -1; - RootKeyCell->NumberOfValues = 0; - RootKeyCell->ValueListOffset = -1; - RootKeyCell->SecurityKeyOffset = 0; - RootKeyCell->ClassNameOffset = -1; - RootKeyCell->NameSize = NameSize; - RootKeyCell->ClassSize = 0; - if (Packable) - { - for(i = 0; i < NameSize; i++) - { - ((PCHAR)RootKeyCell->Name)[i] = BaseKeyName[i]; - } - RootKeyCell->Flags |= REG_KEY_NAME_PACKED; - } - else - { - memcpy (RootKeyCell->Name, BaseKeyName, NameSize); - } -} - - -static PREGISTRY_HIVE -CmiCreateHive (PCWSTR KeyName) -{ - PREGISTRY_HIVE Hive; - PCELL_HEADER FreeCell; - PKEY_CELL RootKeyCell; - PHBIN BinCell; - - Hive = (PREGISTRY_HIVE) MmAllocateMemory (sizeof(REGISTRY_HIVE)); - if (Hive == NULL) - { - return NULL; - } - memset (Hive, 0, sizeof(REGISTRY_HIVE)); - - DbgPrint((DPRINT_REGISTRY, "Hive %x\n", Hive)); - - /* Create hive beader (aka 'base block') */ - Hive->HiveHeader = (PHIVE_HEADER) AllocateMbMemory (REG_BLOCK_SIZE); - if (Hive->HiveHeader == NULL) - { - MmFreeMemory (Hive); - return NULL; - } - CmiCreateDefaultHiveHeader(Hive->HiveHeader); - Hive->FileSize = REG_BLOCK_SIZE; - - /* Allocate block list */ - Hive->BlockListSize = 1; - Hive->BlockList = MmAllocateMemory (sizeof(PHBIN) * Hive->BlockListSize); - if (Hive->BlockList == NULL) - { - MmFreeMemory (Hive); - return NULL; - } - - /* Allocate free cell list */ - Hive->FreeListMax = 32; - Hive->FreeList = MmAllocateMemory(sizeof(PCELL_HEADER) * Hive->FreeListMax); - if (Hive->FreeList == NULL) - { - MmFreeMemory (Hive->BlockList); - MmFreeMemory (Hive); - return NULL; - } - Hive->FreeListOffset = MmAllocateMemory(sizeof(BLOCK_OFFSET) * Hive->FreeListMax); - if (Hive->FreeListOffset == NULL) - { - MmFreeMemory (Hive->FreeList); - MmFreeMemory (Hive->BlockList); - MmFreeMemory (Hive); - return NULL; - } - - /* Allocate first bin */ - Hive->BlockList[0] = (PHBIN) AllocateMbMemory (REG_BLOCK_SIZE); - if (Hive->BlockList[0] == NULL) - { - MmFreeMemory (Hive->FreeListOffset); - MmFreeMemory (Hive->FreeList); - MmFreeMemory (Hive->BlockList); - MmFreeMemory (Hive); - return NULL; - } - Hive->FileSize += REG_BLOCK_SIZE; - - /* Init first bin */ - BinCell = (PHBIN)Hive->BlockList[0]; - CmiCreateDefaultBinCell(BinCell); - BinCell->BinOffset = 0; - - /* Init root key cell */ - RootKeyCell = (PKEY_CELL)((ULONG)BinCell + REG_HBIN_DATA_OFFSET); - CmiCreateDefaultRootKeyCell(RootKeyCell, KeyName); - Hive->HiveHeader->RootKeyOffset = REG_HBIN_DATA_OFFSET; - - /* Init free cell */ - FreeCell = (PCELL_HEADER)((ULONG)RootKeyCell - RootKeyCell->CellSize); - FreeCell->CellSize = REG_BLOCK_SIZE - (REG_HBIN_DATA_OFFSET - RootKeyCell->CellSize); - - Hive->FreeList[0] = FreeCell; - Hive->FreeListOffset[0] = REG_HBIN_DATA_OFFSET - RootKeyCell->CellSize; - Hive->FreeListSize++; - - return Hive; -} - - -static VOID -CmiCleanupHive(PREGISTRY_HIVE Hive, BOOL Release) -{ - MmFreeMemory (Hive->FreeListOffset); - MmFreeMemory (Hive->FreeList); - MmFreeMemory (Hive->BlockList); - MmFreeMemory (Hive); - - if (Release) - { - FreeMbMemory (); - } -} - - -static PHBIN -CmiGetBin (PREGISTRY_HIVE Hive, - BLOCK_OFFSET BlockOffset) -{ - ULONG BlockIndex; - - if (BlockOffset == (ULONG) -1) - return NULL; - - BlockIndex = BlockOffset / REG_BLOCK_SIZE; - if (BlockIndex >= Hive->BlockListSize) - return NULL; - - return Hive->BlockList[BlockIndex]; -} - - static BOOL -CmiMergeFree(PREGISTRY_HIVE RegistryHive, - PCELL_HEADER FreeBlock, - BLOCK_OFFSET FreeOffset) -{ - BLOCK_OFFSET BlockOffset; - BLOCK_OFFSET BinOffset; - ULONG BlockSize; - ULONG BinSize; - PHBIN Bin; - ULONG i; - - DbgPrint((DPRINT_REGISTRY, "CmiMergeFree(Block %lx Offset %lx Size %lx) called\n", - FreeBlock, FreeOffset, FreeBlock->CellSize)); - - Bin = CmiGetBin (RegistryHive, FreeOffset); - if (Bin == NULL) - return FALSE; - - DbgPrint((DPRINT_REGISTRY, "Bin %p\n", Bin)); - - BinOffset = Bin->BinOffset; - BinSize = Bin->BinSize; - DbgPrint((DPRINT_REGISTRY, "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) - { - DbgPrint((DPRINT_REGISTRY, "Free block: Offset %lx Size %lx\n", - BlockOffset, BlockSize)); - - if ((i < (RegistryHive->FreeListSize - 1)) && - (BlockOffset + BlockSize == FreeOffset) && - (FreeOffset + FreeBlock->CellSize == RegistryHive->FreeListOffset[i + 1])) - { - DbgPrint((DPRINT_REGISTRY, "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) - { - memmove (&RegistryHive->FreeList[i + 1], - &RegistryHive->FreeList[i + 2], - sizeof(RegistryHive->FreeList[0]) - * (RegistryHive->FreeListSize - i - 2)); - memmove (&RegistryHive->FreeListOffset[i + 1], - &RegistryHive->FreeListOffset[i + 2], - sizeof(RegistryHive->FreeListOffset[0]) - * (RegistryHive->FreeListSize - i - 2)); - } - RegistryHive->FreeListSize--; - - return TRUE; - } - else if (BlockOffset + BlockSize == FreeOffset) - { - DbgPrint((DPRINT_REGISTRY, "Merge current block with previous block\n")); - - RegistryHive->FreeList[i]->CellSize += FreeBlock->CellSize; - FreeBlock->CellSize = 0; - - return TRUE; - } - else if (FreeOffset + FreeBlock->CellSize == BlockOffset) - { - DbgPrint((DPRINT_REGISTRY, "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; - - return TRUE; - } - } - } - - return FALSE; -} - - -static BOOL -CmiAddFree(PREGISTRY_HIVE RegistryHive, - PCELL_HEADER FreeBlock, - BLOCK_OFFSET FreeOffset, - BOOL MergeFreeBlocks) -{ - PCELL_HEADER *tmpList; - BLOCK_OFFSET *tmpListOffset; - LONG minInd; - LONG maxInd; - LONG medInd; - - assert(RegistryHive); - assert(FreeBlock); - - DbgPrint((DPRINT_REGISTRY, "FreeBlock %.08lx FreeOffset %.08lx\n", - FreeBlock, FreeOffset)); - - /* Merge free blocks */ - if (MergeFreeBlocks == TRUE) - { - if (CmiMergeFree(RegistryHive, FreeBlock, FreeOffset)) - return TRUE; - } - - if ((RegistryHive->FreeListSize + 1) > RegistryHive->FreeListMax) - { - tmpList = MmAllocateMemory (sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax + 32)); - if (tmpList == NULL) - { - return FALSE; - } - - tmpListOffset = MmAllocateMemory (sizeof(BLOCK_OFFSET) * (RegistryHive->FreeListMax + 32)); - if (tmpListOffset == NULL) - { - MmFreeMemory (tmpList); - return FALSE; - } - - if (RegistryHive->FreeListMax) - { - memmove (tmpList, - RegistryHive->FreeList, - sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax)); - memmove (tmpListOffset, - RegistryHive->FreeListOffset, - sizeof(BLOCK_OFFSET) * (RegistryHive->FreeListMax)); - MmFreeMemory (RegistryHive->FreeList); - MmFreeMemory (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 */ - memmove (&RegistryHive->FreeList[1], - &RegistryHive->FreeList[0], - sizeof(RegistryHive->FreeList[0]) * RegistryHive->FreeListSize); - memmove (&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 */ - memmove (&RegistryHive->FreeList[maxInd+1], - &RegistryHive->FreeList[maxInd], - sizeof(RegistryHive->FreeList[0]) * (RegistryHive->FreeListSize - minInd)); - memmove (&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 TRUE; -} - - -static BOOL -CmiAddBin(PREGISTRY_HIVE RegistryHive, - ULONG BlockCount, - PVOID *NewBlock, - PBLOCK_OFFSET NewBlockOffset) -{ - PCELL_HEADER tmpBlock; - PHBIN *BlockList; - PHBIN tmpBin; - ULONG BinSize; - ULONG i; - - BinSize = BlockCount * REG_BLOCK_SIZE; - tmpBin = AllocateMbMemory (BinSize); - if (tmpBin == NULL) - { - return FALSE; - } - memset (tmpBin, 0, BinSize); - - tmpBin->HeaderId = REG_BIN_ID; - tmpBin->BinOffset = RegistryHive->FileSize - REG_BLOCK_SIZE; - RegistryHive->FileSize += BinSize; - tmpBin->BinSize = BinSize; - tmpBin->DateModified = 0ULL; - tmpBin->MemAlloc = 0; - - /* Increase size of list of blocks */ - BlockList = MmAllocateMemory (sizeof(PHBIN) * (RegistryHive->BlockListSize + BlockCount)); - if (BlockList == NULL) - { - return FALSE; - } - - if (RegistryHive->BlockListSize > 0) - { - memcpy (BlockList, - RegistryHive->BlockList, - sizeof(PHBIN) * RegistryHive->BlockListSize); - MmFreeMemory (RegistryHive->BlockList); - } - - RegistryHive->BlockList = BlockList; - for (i = 0; i < BlockCount; i++) - RegistryHive->BlockList[RegistryHive->BlockListSize + i] = tmpBin; - RegistryHive->BlockListSize += BlockCount; - - /* Initialize a free block in this heap : */ - tmpBlock = (PCELL_HEADER)((ULONG) tmpBin + REG_HBIN_DATA_OFFSET); - tmpBlock->CellSize = (REG_BLOCK_SIZE - REG_HBIN_DATA_OFFSET); - - *NewBlock = (PVOID) tmpBlock; - - if (NewBlockOffset) - *NewBlockOffset = tmpBin->BinOffset + REG_HBIN_DATA_OFFSET; - - return TRUE; -} - - -static BOOL -CmiAllocateCell (PREGISTRY_HIVE RegistryHive, - LONG CellSize, - PVOID *Block, - PBLOCK_OFFSET pBlockOffset) -{ - PCELL_HEADER NewBlock; - ULONG i; - - *Block = NULL; - - /* Round to 16 bytes multiple */ - CellSize = ROUND_UP(CellSize, 16); - - /* first search in free blocks */ - NewBlock = NULL; - for (i = 0; i < RegistryHive->FreeListSize; i++) - { - if (RegistryHive->FreeList[i]->CellSize >= CellSize) - { - NewBlock = RegistryHive->FreeList[i]; - if (pBlockOffset) - *pBlockOffset = RegistryHive->FreeListOffset[i]; - - if ((i + 1) < RegistryHive->FreeListSize) - { - memmove (&RegistryHive->FreeList[i], - &RegistryHive->FreeList[i + 1], - sizeof(RegistryHive->FreeList[0]) - * (RegistryHive->FreeListSize - i - 1)); - memmove (&RegistryHive->FreeListOffset[i], - &RegistryHive->FreeListOffset[i + 1], - sizeof(RegistryHive->FreeListOffset[0]) - * (RegistryHive->FreeListSize - i - 1)); - } - RegistryHive->FreeListSize--; - break; - } - } - - /* Need to extend hive file */ - if (NewBlock == NULL) - { - /* Add a new block */ - if (!CmiAddBin(RegistryHive, - ((sizeof(HBIN) + CellSize - 1) / REG_BLOCK_SIZE) + 1, - (PVOID *)(PVOID)&NewBlock, - pBlockOffset)) - return FALSE; - } - - *Block = NewBlock; - - /* Split the block in two parts */ - if (NewBlock->CellSize > CellSize) - { - NewBlock = (PCELL_HEADER) ((ULONG)NewBlock + CellSize); - NewBlock->CellSize = ((PCELL_HEADER) (*Block))->CellSize - CellSize; - CmiAddFree (RegistryHive, - NewBlock, - *pBlockOffset + CellSize, - TRUE); - } - else if (NewBlock->CellSize < CellSize) - { - return FALSE; - } - - memset(*Block, 0, CellSize); - ((PCELL_HEADER)(*Block))->CellSize = -CellSize; - - return TRUE; -} - - -static PVOID -CmiGetCell (PREGISTRY_HIVE Hive, - BLOCK_OFFSET BlockOffset) -{ - PHBIN Bin; - ULONG BlockIndex; - - if (BlockOffset == (ULONG) -1) - return NULL; - - BlockIndex = BlockOffset / REG_BLOCK_SIZE; - if (BlockIndex >= Hive->BlockListSize) - return NULL; - - Bin = Hive->BlockList[BlockIndex]; - if (Bin == NULL) - return NULL; - - return (PVOID)((ULONG)Bin + (BlockOffset - Bin->BinOffset)); -} - - -static BOOL CmiAllocateHashTableCell (PREGISTRY_HIVE Hive, - PBLOCK_OFFSET HBOffset, + PHCELL_INDEX HBOffset, ULONG SubKeyCount) { PHASH_TABLE_CELL HashCell; ULONG NewHashSize; - BOOL Status; NewHashSize = sizeof(HASH_TABLE_CELL) + (SubKeyCount * sizeof(HASH_RECORD)); - Status = CmiAllocateCell (Hive, - NewHashSize, - (PVOID*)(PVOID)&HashCell, - HBOffset); - if ((HashCell == NULL) || (Status == FALSE)) + *HBOffset = HvAllocateCell (Hive, NewHashSize, HvStable); + if (*HBOffset == HCELL_NULL) { return FALSE; } - HashCell->Id = REG_HASH_TABLE_BLOCK_ID; + HashCell = HvGetCell (Hive, *HBOffset); + HashCell->Id = REG_HASH_TABLE_CELL_ID; HashCell->HashTableSize = SubKeyCount; return TRUE; @@ -877,28 +96,17 @@ static BOOL CmiAddKeyToParentHashTable (PREGISTRY_HIVE Hive, - BLOCK_OFFSET ParentKeyOffset, + HCELL_INDEX ParentKeyOffset, PKEY_CELL NewKeyCell, - BLOCK_OFFSET NKBOffset) + HCELL_INDEX NKBOffset) { PHASH_TABLE_CELL HashBlock; PKEY_CELL ParentKeyCell; ULONG i; - ParentKeyCell = CmiGetCell (Hive, ParentKeyOffset); - if (ParentKeyCell == NULL) - { - DbgPrint((DPRINT_REGISTRY, "CmiGetCell() failed\n")); - return FALSE; - } + ParentKeyCell = HvGetCell (Hive, ParentKeyOffset); + HashBlock = HvGetCell (Hive, ParentKeyCell->HashTableOffset[HvStable]); - HashBlock =CmiGetCell (Hive, ParentKeyCell->HashTableOffset); - if (HashBlock == NULL) - { - DbgPrint((DPRINT_REGISTRY, "CmiGetCell() failed\n")); - return FALSE; - } - for (i = 0; i < HashBlock->HashTableSize; i++) { if (HashBlock->Table[i].KeyOffset == 0) @@ -907,7 +115,7 @@ memcpy (&HashBlock->Table[i].HashValue, NewKeyCell->Name, min(NewKeyCell->NameSize, sizeof(ULONG))); - ParentKeyCell->NumberOfSubKeys++; + ParentKeyCell->NumberOfSubKeys[HvStable]++; return TRUE; } } @@ -918,22 +126,17 @@ static BOOL CmiAllocateValueListCell (PREGISTRY_HIVE Hive, - PBLOCK_OFFSET ValueListOffset, + PHCELL_INDEX ValueListOffset, ULONG ValueCount) { - PVALUE_LIST_CELL ValueListCell; ULONG ValueListSize; - BOOL Status; ValueListSize = sizeof(VALUE_LIST_CELL) + - (ValueCount * sizeof(BLOCK_OFFSET)); - Status = CmiAllocateCell (Hive, - ValueListSize, - (PVOID)&ValueListCell, - ValueListOffset); - if ((ValueListCell == NULL) || (Status == FALSE)) + (ValueCount * sizeof(HCELL_INDEX)); + *ValueListOffset = HvAllocateCell (Hive, ValueListSize, HvStable); + if (*ValueListOffset == HCELL_NULL) { - DbgPrint((DPRINT_REGISTRY, "CmiAllocateCell() failed\n")); + DbgPrint((DPRINT_REGISTRY, "HvAllocateCell() failed\n")); return FALSE; } @@ -944,12 +147,11 @@ static BOOL CmiAllocateValueCell(PREGISTRY_HIVE Hive, PVALUE_CELL *ValueCell, - BLOCK_OFFSET *ValueCellOffset, + HCELL_INDEX *ValueCellOffset, PWCHAR ValueName) { PVALUE_CELL NewValueCell; ULONG NameSize; - BOOL Status; BOOLEAN Packable = TRUE; ULONG i; @@ -963,16 +165,14 @@ break; } } - Status = CmiAllocateCell (Hive, - sizeof(VALUE_CELL) + NameSize, - (PVOID*)(PVOID)&NewValueCell, - ValueCellOffset); - if ((NewValueCell == NULL) || (Status == FALSE)) + *ValueCellOffset = HvAllocateCell (Hive, sizeof(VALUE_CELL) + NameSize, HvStable); + if (*ValueCellOffset == HCELL_NULL) { DbgPrint((DPRINT_REGISTRY, "CmiAllocateCell() failed\n")); return FALSE; } + NewValueCell = (PVALUE_CELL) HvGetCell (Hive, *ValueCellOffset); NewValueCell->Id = REG_VALUE_CELL_ID; NewValueCell->NameSize = NameSize; NewValueCell->Flags = 0; @@ -1005,23 +205,23 @@ static BOOL CmiAddValueToKeyValueList(PREGISTRY_HIVE Hive, - BLOCK_OFFSET KeyCellOffset, - BLOCK_OFFSET ValueCellOffset) + HCELL_INDEX KeyCellOffset, + HCELL_INDEX ValueCellOffset) { PVALUE_LIST_CELL ValueListCell; PKEY_CELL KeyCell; - KeyCell = CmiGetCell (Hive, KeyCellOffset); + KeyCell = HvGetCell (Hive, KeyCellOffset); if (KeyCell == NULL) { - DbgPrint((DPRINT_REGISTRY, "CmiGetCell() failed\n")); + DbgPrint((DPRINT_REGISTRY, "HvGetCell() failed\n")); return FALSE; } - ValueListCell = CmiGetCell (Hive, KeyCell->ValueListOffset); + ValueListCell = HvGetCell (Hive, KeyCell->ValueListOffset); if (ValueListCell == NULL) { - DbgPrint((DPRINT_REGISTRY, "CmiGetCell() failed\n")); + DbgPrint((DPRINT_REGISTRY, "HvGetCell() failed\n")); return FALSE; } @@ -1031,16 +231,17 @@ return TRUE; } + static BOOL CmiExportValue (PREGISTRY_HIVE Hive, - BLOCK_OFFSET KeyCellOffset, + HCELL_INDEX KeyCellOffset, FRLDRHKEY Key, PVALUE Value) { - BLOCK_OFFSET ValueCellOffset; - BLOCK_OFFSET DataCellOffset; + HCELL_INDEX ValueCellOffset; + HCELL_INDEX DataCellOffset; PVALUE_CELL ValueCell; - PDATA_CELL DataCell; + PVOID DataCell; ULONG DataSize; ULONG DataType; PCHAR Data; @@ -1074,7 +275,7 @@ Data = Value->Data; } - if (DataSize <= sizeof(BLOCK_OFFSET)) + if (DataSize <= sizeof(HCELL_INDEX)) { ValueCell->DataSize = DataSize | REG_DATA_IN_OFFSET; ValueCell->DataType = DataType; @@ -1085,10 +286,8 @@ else { /* Allocate data cell */ - if (!CmiAllocateCell (Hive, - sizeof(CELL_HEADER) + DataSize, - (PVOID *)(PVOID)&DataCell, - &DataCellOffset)) + DataCellOffset = HvAllocateCell (Hive, DataSize, HvStable); + if (DataCellOffset == HCELL_NULL) { return FALSE; } @@ -1097,7 +296,8 @@ ValueCell->DataSize = DataSize; ValueCell->DataType = DataType; - memcpy (DataCell->Data, + DataCell = HvGetCell (Hive, DataCellOffset); + memcpy (DataCell, Data, DataSize); } @@ -1108,11 +308,11 @@ static BOOL CmiExportSubKey (PREGISTRY_HIVE Hive, - BLOCK_OFFSET ParentKeyOffset, + HCELL_INDEX ParentKeyOffset, FRLDRHKEY ParentKey, FRLDRHKEY Key) { - BLOCK_OFFSET NKBOffset; + HCELL_INDEX NKBOffset; PKEY_CELL NewKeyCell; ULONG KeyCellSize; ULONG SubKeyCount; @@ -1143,19 +343,21 @@ /* Allocate key cell */ KeyCellSize = sizeof(KEY_CELL) + NameSize; - if (!CmiAllocateCell (Hive, KeyCellSize, (PVOID)&NewKeyCell, &NKBOffset)) + NKBOffset = HvAllocateCell (Hive, KeyCellSize, HvStable); + if (NKBOffset == HCELL_NULL) { - DbgPrint((DPRINT_REGISTRY, "CmiAllocateCell() failed\n")); + DbgPrint((DPRINT_REGISTRY, "HvAllocateCell() failed\n")); return FALSE; } /* Initialize key cell */ + NewKeyCell = (PKEY_CELL) HvGetCell (Hive, NKBOffset); NewKeyCell->Id = REG_KEY_CELL_ID; NewKeyCell->Flags = 0; - NewKeyCell->LastWriteTime = 0ULL; + NewKeyCell->LastWriteTime.QuadPart = 0ULL; NewKeyCell->ParentKeyOffset = ParentKeyOffset; - NewKeyCell->NumberOfSubKeys = 0; - NewKeyCell->HashTableOffset = -1; + NewKeyCell->NumberOfSubKeys[HvStable] = 0; + NewKeyCell->HashTableOffset[HvStable] = -1; NewKeyCell->NumberOfValues = 0; NewKeyCell->ValueListOffset = -1; NewKeyCell->SecurityKeyOffset = -1; @@ -1228,7 +430,7 @@ { /* Allocate hash table cell */ if (!CmiAllocateHashTableCell (Hive, - &NewKeyCell->HashTableOffset, + &NewKeyCell->HashTableOffset[HvStable], SubKeyCount)) { DbgPrint((DPRINT_REGISTRY, "CmiAllocateHashTableCell() failed\n")); @@ -1254,22 +456,6 @@ } -static VOID -CmiCalcHiveChecksum (PREGISTRY_HIVE Hive) -{ - ULONG *Buffer; - ULONG Sum; - ULONG i; - - Buffer = (ULONG*)Hive->HiveHeader; - Sum = 0; - for (i = 0; i < 127; i++) - Sum += Buffer[i]; - - Hive->HiveHeader->Checksum = Sum; -} - - static BOOL CmiExportHive (PREGISTRY_HIVE Hive, PCWSTR KeyName) @@ -1290,10 +476,10 @@ return FALSE; } - KeyCell = CmiGetCell (Hive, Hive->HiveHeader->RootKeyOffset); + KeyCell = HvGetCell (Hive, Hive->HiveHeader->RootCell); if (KeyCell == NULL) { - DbgPrint((DPRINT_REGISTRY, "CmiGetBlock() failed\n")); + DbgPrint((DPRINT_REGISTRY, "HvGetCell() failed\n")); return FALSE; } @@ -1312,7 +498,7 @@ if (Key->DataSize != 0) { - if (!CmiExportValue (Hive, Hive->HiveHeader->RootKeyOffset, Key, NULL)) + if (!CmiExportValue (Hive, Hive->HiveHeader->RootCell, Key, NULL)) return FALSE; } @@ -1324,7 +510,7 @@ VALUE, ValueList); - if (!CmiExportValue (Hive, Hive->HiveHeader->RootKeyOffset, Key, Value)) + if (!CmiExportValue (Hive, Hive->HiveHeader->RootCell, Key, Value)) return FALSE; Entry = Entry->Flink; @@ -1337,7 +523,7 @@ { /* Allocate hash table cell */ if (!CmiAllocateHashTableCell (Hive, - &KeyCell->HashTableOffset, + &KeyCell->HashTableOffset[HvStable], SubKeyCount)) { DbgPrint((DPRINT_REGISTRY, "CmiAllocateHashTableCell() failed\n")); @@ -1352,31 +538,29 @@ KEY, KeyList); - if (!CmiExportSubKey (Hive, Hive->HiveHeader->RootKeyOffset, Key, SubKey)) + if (!CmiExportSubKey (Hive, Hive->HiveHeader->RootCell, Key, SubKey)) return FALSE; Entry = Entry->Flink; } } - CmiCalcHiveChecksum (Hive); - return TRUE; } static BOOL -RegImportValue (PHBIN RootBin, +RegImportValue (PREGISTRY_HIVE Hive, PVALUE_CELL ValueCell, FRLDRHKEY Key) { - PDATA_CELL DataCell; + PVOID DataCell; PWCHAR wName; LONG Error; ULONG DataSize; ULONG i; - if (ValueCell->CellSize >= 0 || ValueCell->Id != REG_VALUE_CELL_ID) + if (ValueCell->Id != REG_VALUE_CELL_ID) { DbgPrint((DPRINT_REGISTRY, "Invalid key cell!\n")); return FALSE; @@ -1405,7 +589,7 @@ DbgPrint((DPRINT_REGISTRY, "ValueName: '%S'\n", wName)); DbgPrint((DPRINT_REGISTRY, "DataSize: %u\n", DataSize)); - if (DataSize <= sizeof(BLOCK_OFFSET) && (ValueCell->DataSize & REG_DATA_IN_OFFSET)) + if (DataSize <= sizeof(HCELL_INDEX) && (ValueCell->DataSize & REG_DATA_IN_OFFSET)) { Error = RegSetValue(Key, wName, @@ -1421,20 +605,13 @@ } else { - DataCell = (PDATA_CELL)((PUCHAR)RootBin + ValueCell->DataOffset); + DataCell = HvGetCell (Hive, ValueCell->DataOffset); DbgPrint((DPRINT_REGISTRY, "DataCell: %x\n", DataCell)); - if (DataCell->CellSize >= 0) - { - DbgPrint((DPRINT_REGISTRY, "Invalid data cell size!\n")); - MmFreeMemory (wName); - return FALSE; - } - Error = RegSetValue (Key, wName, ValueCell->DataType, - DataCell->Data, + DataCell, DataSize); if (Error != ERROR_SUCCESS) @@ -1452,7 +629,7 @@ static BOOL -RegImportSubKey(PHBIN RootBin, +RegImportSubKey(PREGISTRY_HIVE Hive, PKEY_CELL KeyCell, FRLDRHKEY ParentKey) { @@ -1467,9 +644,8 @@ DbgPrint((DPRINT_REGISTRY, "KeyCell: %x\n", KeyCell)); - DbgPrint((DPRINT_REGISTRY, "KeyCell->CellSize: %x\n", KeyCell->CellSize)); DbgPrint((DPRINT_REGISTRY, "KeyCell->Id: %x\n", KeyCell->Id)); - if (KeyCell->Id != REG_KEY_CELL_ID || KeyCell->CellSize >= 0) + if (KeyCell->Id != REG_KEY_CELL_ID) { DbgPrint((DPRINT_REGISTRY, "Invalid key cell id!\n")); return FALSE; @@ -1511,37 +687,38 @@ /* Enumerate and add values */ if (KeyCell->NumberOfValues > 0) { - ValueListCell = (PVALUE_LIST_CELL)((PUCHAR)RootBin + KeyCell->ValueListOffset); + ValueListCell = (PVALUE_LIST_CELL) HvGetCell (Hive, KeyCell->ValueListOffset); DbgPrint((DPRINT_REGISTRY, "ValueListCell: %x\n", ValueListCell)); for (i = 0; i < KeyCell->NumberOfValues; i++) { DbgPrint((DPRINT_REGISTRY, "ValueOffset[%d]: %x\n", i, ValueListCell->ValueOffset[i])); - ValueCell = (PVALUE_CELL)((PUCHAR)RootBin + ValueListCell->ValueOffset[i]); + ValueCell = (PVALUE_CELL) HvGetCell (Hive, ValueListCell->ValueOffset[i]); DbgPrint((DPRINT_REGISTRY, "ValueCell[%d]: %x\n", i, ValueCell)); - if (!RegImportValue(RootBin, ValueCell, SubKey)) + if (!RegImportValue(Hive, ValueCell, SubKey)) return FALSE; } } /* Enumerate and add subkeys */ - if (KeyCell->NumberOfSubKeys > 0) + if (KeyCell->NumberOfSubKeys[HvStable] > 0) { - HashCell = (PHASH_TABLE_CELL)((PUCHAR)RootBin + KeyCell->HashTableOffset); + HashCell = (PHASH_TABLE_CELL) HvGetCell (Hive, KeyCell->HashTableOffset[HvStable]); DbgPrint((DPRINT_REGISTRY, "HashCell: %x\n", HashCell)); + DbgPrint((DPRINT_REGISTRY, "NumberOfSubKeys: %x\n", KeyCell->NumberOfSubKeys)); - for (i = 0; i < KeyCell->NumberOfSubKeys; i++) + for (i = 0; i < KeyCell->NumberOfSubKeys[HvStable]; i++) { DbgPrint((DPRINT_REGISTRY, "KeyOffset[%d]: %x\n", i, HashCell->Table[i].KeyOffset)); - SubKeyCell = (PKEY_CELL)((PUCHAR)RootBin + HashCell->Table[i].KeyOffset); + SubKeyCell = (PKEY_CELL) HvGetCell (Hive, HashCell->Table[i].KeyOffset); DbgPrint((DPRINT_REGISTRY, "SubKeyCell[%d]: %x\n", i, SubKeyCell)); - if (!RegImportSubKey(RootBin, SubKeyCell, SubKey)) + if (!RegImportSubKey(Hive, SubKeyCell, SubKey)) return FALSE; } } @@ -1554,38 +731,30 @@ RegImportBinaryHive(PCHAR ChunkBase, ULONG ChunkSize) { - PHIVE_HEADER HiveHeader; - PHBIN RootBin; PKEY_CELL KeyCell; PHASH_TABLE_CELL HashCell; PKEY_CELL SubKeyCell; FRLDRHKEY SystemKey; ULONG i; LONG Error; + PREGISTRY_HIVE Hive; + NTSTATUS Status; DbgPrint((DPRINT_REGISTRY, "RegImportBinaryHive(%x, %u) called\n",ChunkBase,ChunkSize)); - HiveHeader = (PHIVE_HEADER)ChunkBase; - DbgPrint((DPRINT_REGISTRY, "HiveHeader: %x\n", HiveHeader)); - if (HiveHeader->BlockId != REG_HIVE_ID) + Status = HvInitialize (&Hive, HV_OPERATION_MEMORY_INPLACE, + (ULONG_PTR)ChunkBase, ChunkSize, + NULL, NULL, NULL, NULL, NULL); + if (!NT_SUCCESS(Status)) { DbgPrint((DPRINT_REGISTRY, "Invalid hive id!\n")); return FALSE; } - RootBin = (PHBIN)((ULONG)HiveHeader + REG_BLOCK_SIZE); - DbgPrint((DPRINT_REGISTRY, "RootBin: %x\n", RootBin)); - if (RootBin->HeaderId != REG_BIN_ID || RootBin->BinSize == 0) - { - DbgPrint((DPRINT_REGISTRY, "Invalid bin id!\n")); - return FALSE; - } - - KeyCell = (PKEY_CELL)((ULONG)RootBin + REG_HBIN_DATA_OFFSET); + KeyCell = HvGetCell (Hive, Hive->HiveHeader->RootCell); DbgPrint((DPRINT_REGISTRY, "KeyCell: %x\n", KeyCell)); - DbgPrint((DPRINT_REGISTRY, "KeyCell->CellSize: %x\n", KeyCell->CellSize)); DbgPrint((DPRINT_REGISTRY, "KeyCell->Id: %x\n", KeyCell->Id)); - if (KeyCell->Id != REG_KEY_CELL_ID || KeyCell->CellSize >= 0) + if (KeyCell->Id != REG_KEY_CELL_ID) { DbgPrint((DPRINT_REGISTRY, "Invalid key cell id!\n")); return FALSE; @@ -1605,20 +774,21 @@ } /* Enumerate and add subkeys */ - if (KeyCell->NumberOfSubKeys > 0) + if (KeyCell->NumberOfSubKeys[HvStable] > 0) { - HashCell = (PHASH_TABLE_CELL)((ULONG)RootBin + KeyCell->HashTableOffset); + HashCell = HvGetCell (Hive, KeyCell->HashTableOffset[HvStable]); DbgPrint((DPRINT_REGISTRY, "HashCell: %x\n", HashCell)); + DbgPrint((DPRINT_REGISTRY, "NumberOfSubKeys: %x\n", KeyCell->NumberOfSubKeys[HvStable])); - for (i = 0; i < KeyCell->NumberOfSubKeys; i++) + for (i = 0; i < KeyCell->NumberOfSubKeys[HvStable]; i++) { DbgPrint((DPRINT_REGISTRY, "KeyOffset[%d]: %x\n", i, HashCell->Table[i].KeyOffset)); - SubKeyCell = (PKEY_CELL)((ULONG)RootBin + HashCell->Table[i].KeyOffset); + SubKeyCell = HvGetCell (Hive, HashCell->Table[i].KeyOffset); DbgPrint((DPRINT_REGISTRY, "SubKeyCell[%d]: %x\n", i, SubKeyCell)); - if (!RegImportSubKey(RootBin, SubKeyCell, SystemKey)) + if (!RegImportSubKey(Hive, SubKeyCell, SystemKey)) return FALSE; } } @@ -1627,31 +797,69 @@ } +static VOID +CmiWriteHive(PREGISTRY_HIVE Hive, + PCHAR ChunkBase, + ULONG* ChunkSize) +{ + PHBIN Bin; + ULONG i, Size; + + /* Write hive header */ + memcpy (ChunkBase, Hive->HiveHeader, HV_BLOCK_SIZE); + Size = HV_BLOCK_SIZE; + + Bin = NULL; + for (i = 0; i < Hive->Storage[HvStable].BlockListSize; i++) + { + if (Hive->Storage[HvStable].BlockList[i].Bin != Bin) + { + Bin = Hive->Storage[HvStable].BlockList[i].Bin; + memcpy (ChunkBase + (i + 1) * HV_BLOCK_SIZE, + Bin, Bin->BinSize); + Size += Bin->BinSize; + } + } + + DbgPrint((DPRINT_REGISTRY, "ChunkSize: %x\n", Size)); + + *ChunkSize = Size; +} + + BOOL RegExportBinaryHive(PCWSTR KeyName, PCHAR ChunkBase, ULONG* ChunkSize) { PREGISTRY_HIVE Hive; + NTSTATUS Status; DbgPrint((DPRINT_REGISTRY, "Creating binary hardware hive\n")); - *ChunkSize = 0; - InitMbMemory (ChunkBase); + Status = HvInitialize (&Hive, HV_OPERATION_CREATE_HIVE, 0, 0, + NULL, NULL, NULL, NULL, NULL); + if (!NT_SUCCESS(Status)) + { + return FALSE; + } - Hive = CmiCreateHive (KeyName); - if (Hive == NULL) - return FALSE; + /* Init root key cell */ + if (!CmCreateRootNode (Hive, KeyName)) + { + HvFree (Hive); + return FALSE; + } if (!CmiExportHive (Hive, KeyName)) { - CmiCleanupHive (Hive, TRUE); + HvFree (Hive); return FALSE; } - CmiCleanupHive (Hive, FALSE); + CmiWriteHive (Hive, ChunkBase, ChunkSize); - *ChunkSize = GetMbAllocatedSize (); + HvFree (Hive); return TRUE; } Index: boot/freeldr/freeldr/freeldr.xml =================================================================== --- boot/freeldr/freeldr/freeldr.xml (revision 19665) +++ boot/freeldr/freeldr/freeldr.xml (working copy) @@ -6,5 +6,6 @@ freeldr_main rossym string + cmlib rtl Index: boot/freeldr/freeldr/include/arch/i386/hardware.h =================================================================== --- boot/freeldr/freeldr/include/arch/i386/hardware.h (revision 19665) +++ boot/freeldr/freeldr/include/arch/i386/hardware.h (working copy) @@ -43,7 +43,7 @@ /* CM_COMPONENT_INFORMATION.Flags */ #define Failed 0x00000001 -#define ReadOnly 0x00000002 +//#define ReadOnly 0x00000002 #define Removable 0x00000004 #define ConsoleIn 0x00000008 #define ConsoleOut 0x00000010 Index: boot/freeldr/freeldr/setupldr.xml =================================================================== --- boot/freeldr/freeldr/setupldr.xml (revision 19665) +++ boot/freeldr/freeldr/setupldr.xml (working copy) @@ -6,5 +6,6 @@ setupldr_main rossym string + cmlib rtl Index: boot/freeldr/freeldr/freeldr_base.xml =================================================================== --- boot/freeldr/freeldr/freeldr_base.xml (revision 19665) +++ boot/freeldr/freeldr/freeldr_base.xml (working copy) @@ -2,10 +2,9 @@ include cache include + . - -ffreestanding -fno-builtin -fno-inline Index: lib/directory.xml =================================================================== --- lib/directory.xml (revision 19665) +++ lib/directory.xml (working copy) @@ -29,6 +29,9 @@ + + + ndex: lib/cmlib/cmdata.h =================================================================== --- lib/cmlib/cmdata.h (revision 0) +++ lib/cmlib/cmdata.h (revision 0) @@ -0,0 +1,134 @@ +/* + * PROJECT: registry manipulation library + * LICENSE: GPL - See COPYING in the top level directory + * COPYRIGHT: Copyright 2005 Filip Navara + * Copyright 2001 - 2005 Eric Kohl + */ + +#ifndef CMLIB_CMDATA_H +#define CMLIB_CMDATA_H + +#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_KEY_CELL_ID 0x6b6e +#define REG_HASH_TABLE_CELL_ID 0x666c +#define REG_VALUE_CELL_ID 0x6b76 +#define REG_SECURITY_CELL_ID 0x6b73 + +#include + +typedef struct _KEY_CELL +{ + /* 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 */ + HCELL_INDEX ParentKeyOffset; + + /* Count of sub keys for the key in this key cell (stable & volatile) */ + ULONG NumberOfSubKeys[HvMaxStorageType]; + + /* Block offset of has table for FIXME: subkeys/values? (stable & volatile) */ + HCELL_INDEX HashTableOffset[HvMaxStorageType]; + + /* Count of values contained in this key cell */ + ULONG NumberOfValues; + + /* Block offset of VALUE_LIST_CELL */ + HCELL_INDEX ValueListOffset; + + /* Block offset of security cell */ + HCELL_INDEX SecurityKeyOffset; + + /* Block offset of registry key class */ + HCELL_INDEX 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_VOLATILE_CELL 0x01 +#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 +{ + HCELL_INDEX KeyOffset; + ULONG HashValue; +} HASH_RECORD, *PHASH_RECORD; + +typedef struct _HASH_TABLE_CELL +{ + USHORT Id; + USHORT HashTableSize; + HASH_RECORD Table[0]; +} HASH_TABLE_CELL, *PHASH_TABLE_CELL; + +typedef struct _VALUE_LIST_CELL +{ + HCELL_INDEX ValueOffset[0]; +} VALUE_LIST_CELL, *PVALUE_LIST_CELL; + +typedef struct _VALUE_CELL +{ + USHORT Id; // "kv" + USHORT NameSize; // length of Name + ULONG DataSize; // length of datas in the cell pointed by DataOffset + HCELL_INDEX 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 +{ + USHORT Id; // "sk" + USHORT Reserved; + HCELL_INDEX PrevSecurityCell; + HCELL_INDEX NextSecurityCell; + ULONG RefCount; + ULONG SdSize; + UCHAR Data[0]; +} SECURITY_CELL, *PSECURITY_CELL; + +#include + +#endif /* CMLIB_CMDATA_H */ Index: lib/cmlib/hiveinit.c =================================================================== --- lib/cmlib/hiveinit.c (revision 0) +++ lib/cmlib/hiveinit.c (revision 0) @@ -0,0 +1,370 @@ +/* + * PROJECT: registry manipulation library + * LICENSE: GPL - See COPYING in the top level directory + * COPYRIGHT: Copyright 2005 Filip Navara + * Copyright 2001 - 2005 Eric Kohl + */ + +#include "cmlib.h" +#define NDEBUG +#include + +/** + * @name HvpVerifyHiveHeader + * + * Internal function to verify that a hive header has valid format. + */ + +BOOLEAN CMAPI +HvpVerifyHiveHeader( + PHIVE_HEADER HiveHeader) +{ + if (HiveHeader->Signature != HV_SIGNATURE || + HiveHeader->Major != HV_MAJOR_VER || + HiveHeader->Minor > HV_MINOR_VER || + HiveHeader->Type != HV_TYPE_PRIMARY || + HiveHeader->Format != HV_FORMAT_MEMORY || + HiveHeader->Cluster != 1 || + HiveHeader->Sequence1 != HiveHeader->Sequence2 || + HvpHiveHeaderChecksum(HiveHeader) != HiveHeader->Checksum) + { + return FALSE; + } + + return TRUE; +} + +/** + * @name HvpFreeHiveBins + * + * Internal function to free all bin storage associated with hive + * descriptor. + */ + +VOID CMAPI +HvpFreeHiveBins( + PREGISTRY_HIVE Hive) +{ + ULONG i; + PHBIN Bin; + ULONG Storage; + + for (Storage = HvStable; Storage < HvMaxStorageType; Storage++) + { + Bin = NULL; + for (i = 0; i < Hive->Storage[Storage].BlockListSize; i++) + { + if (Hive->Storage[Storage].BlockList[i].Bin == NULL) + continue; + if (Hive->Storage[Storage].BlockList[i].Bin != Bin) + { + Bin = Hive->Storage[Storage].BlockList[i].Bin; + CmpFree(Hive->Storage[Storage].BlockList[i].Bin); + } + Hive->Storage[Storage].BlockList[i].Bin = NULL; + Hive->Storage[Storage].BlockList[i].Block = NULL; + } + + if (Hive->Storage[Storage].BlockListSize) + CmpFree(Hive->Storage[Storage].BlockList); + } +} + +/** + * @name HvpCreateHive + * + * Internal helper function to initalize hive descriptor structure for + * newly created hive. + * + * @see HvInitialize + */ + +NTSTATUS CMAPI +HvpCreateHive( + PREGISTRY_HIVE RegistryHive) +{ + PHIVE_HEADER HiveHeader; + ULONG Index; + + HiveHeader = CmpAllocate(sizeof(HIVE_HEADER)); + if (HiveHeader == NULL) + return STATUS_NO_MEMORY; + RtlZeroMemory(HiveHeader, sizeof(HIVE_HEADER)); + HiveHeader->Signature = HV_SIGNATURE; + HiveHeader->Major = HV_MAJOR_VER; + HiveHeader->Minor = HV_MINOR_VER; + HiveHeader->Type = HV_TYPE_PRIMARY; + HiveHeader->Format = HV_FORMAT_MEMORY; + HiveHeader->Cluster = 1; + HiveHeader->RootCell = HCELL_NULL; + HiveHeader->Length = HV_BLOCK_SIZE; + HiveHeader->Sequence1 = 1; + HiveHeader->Sequence2 = 1; + /* FIXME: Fill in the file name */ + HiveHeader->Checksum = HvpHiveHeaderChecksum(HiveHeader); + + RegistryHive->HiveHeader = HiveHeader; + for (Index = 0; Index < 24; Index++) + { + RegistryHive->Storage[HvStable].FreeListOffset[Index] = HCELL_NULL; + RegistryHive->Storage[HvVolatile].FreeListOffset[Index] = HCELL_NULL; + } + RtlInitializeBitMap(&RegistryHive->DirtyBitmap, NULL, 0); + + return STATUS_SUCCESS; +} + +/** + * @name HvpInitializeMemoryHive + * + * Internal helper function to initalize hive descriptor structure for + * a hive stored in memory. The data of the hive are copied and it is + * prepared for read/write access. + * + * @see HvInitialize + */ + +NTSTATUS CMAPI +HvpInitializeMemoryHive( + PREGISTRY_HIVE Hive, + ULONG_PTR ChunkBase, + SIZE_T ChunkSize) +{ + SIZE_T BlockIndex; + PHBIN Bin, NewBin; + ULONG i; + ULONG BitmapSize; + PULONG BitmapBuffer; + + if (ChunkSize < sizeof(HIVE_HEADER) || + !HvpVerifyHiveHeader((PHIVE_HEADER)ChunkBase)) + { + return STATUS_REGISTRY_CORRUPT; + } + + Hive->HiveHeader = CmpAllocate(sizeof(HIVE_HEADER)); + if (Hive->HiveHeader == NULL) + { + return STATUS_NO_MEMORY; + } + RtlCopyMemory(Hive->HiveHeader, (PVOID)ChunkBase, sizeof(HIVE_HEADER)); + + /* + * Build a block list from the in-memory chunk and copy the data as + * we go. + */ + + Hive->Storage[HvStable].BlockListSize = (ChunkSize / HV_BLOCK_SIZE) - 1; + Hive->Storage[HvStable].BlockList = + CmpAllocate(Hive->Storage[HvStable].BlockListSize * sizeof(BLOCK_LIST_ENTRY)); + if (Hive->Storage[HvStable].BlockList == NULL) + { + DPRINT1("Allocating block list failed\n"); + CmpFree(Hive->HiveHeader); + return STATUS_NO_MEMORY; + } + + for (BlockIndex = 0; BlockIndex < Hive->Storage[HvStable].BlockListSize; ) + { + Bin = (PHBIN)((ULONG_PTR)ChunkBase + (BlockIndex + 1) * HV_BLOCK_SIZE); + if (Bin->Signature != HV_BIN_SIGNATURE || + (Bin->BinSize % HV_BLOCK_SIZE) != 0) + { + CmpFree(Hive->HiveHeader); + CmpFree(Hive->Storage[HvStable].BlockList); + return STATUS_REGISTRY_CORRUPT; + } + + NewBin = CmpAllocatePaged(Bin->BinSize); + if (NewBin == NULL) + { + CmpFree(Hive->HiveHeader); + CmpFree(Hive->Storage[HvStable].BlockList); + return STATUS_NO_MEMORY; + } + + Hive->Storage[HvStable].BlockList[BlockIndex].Bin = NewBin; + Hive->Storage[HvStable].BlockList[BlockIndex].Block = NewBin; + + RtlCopyMemory(NewBin, Bin, Bin->BinSize); + + if (Bin->BinSize > HV_BLOCK_SIZE) + { + for (i = 1; i < Bin->BinSize / HV_BLOCK_SIZE; i++) + { + Hive->Storage[HvStable].BlockList[BlockIndex + i].Bin = NewBin; + Hive->Storage[HvStable].BlockList[BlockIndex + i].Block = + (PVOID)((ULONG_PTR)NewBin + (i * HV_BLOCK_SIZE)); + } + } + + BlockIndex += Bin->BinSize / HV_BLOCK_SIZE; + } + + if (HvpCreateHiveFreeCellList(Hive)) + { + HvpFreeHiveBins(Hive); + CmpFree(Hive->HiveHeader); + return STATUS_NO_MEMORY; + } + + BitmapSize = ROUND_UP(Hive->Storage[HvStable].BlockListSize, + sizeof(ULONG) * 8) / 8; + BitmapBuffer = (PULONG)CmpAllocatePaged(BitmapSize); + if (BitmapBuffer == NULL) + { + HvpFreeHiveBins(Hive); + CmpFree(Hive->HiveHeader); + return STATUS_NO_MEMORY; + } + + RtlInitializeBitMap(&Hive->DirtyBitmap, BitmapBuffer, BitmapSize * 8); + RtlClearAllBits(&Hive->DirtyBitmap); + + return STATUS_SUCCESS; +} + +/** + * @name HvpInitializeMemoryInplaceHive + * + * Internal helper function to initalize hive descriptor structure for + * a hive stored in memory. The in-memory data of the hive are directly + * used and it is read-only accessible. + * + * @see HvInitialize + */ + +NTSTATUS CMAPI +HvpInitializeMemoryInplaceHive( + PREGISTRY_HIVE Hive, + ULONG_PTR ChunkBase, + SIZE_T ChunkSize) +{ + if (ChunkSize < sizeof(HIVE_HEADER) || + !HvpVerifyHiveHeader((PHIVE_HEADER)ChunkBase)) + { + return STATUS_REGISTRY_CORRUPT; + } + + Hive->HiveHeader = (PHIVE_HEADER)ChunkBase; + Hive->ReadOnly = TRUE; + Hive->Flat = TRUE; + + return STATUS_SUCCESS; +} + +/** + * @name HvInitialize + * + * Allocate a new hive descriptor structure and intialize it. + * + * @param RegistryHive + * Output variable to store pointer to the hive descriptor. + * @param Operation + * - HV_OPERATION_CREATE_HIVE + * Create a new hive for read/write access. + * - HV_OPERATION_MEMORY + * Load and copy in-memory hive for read/write access. The + * pointer to data passed to this routine can be freed after + * the function is executed. + * - HV_OPERATION_MEMORY_INPLACE + * Load an in-memory hive for read-only access. The pointer + * to data passed to this routine MUSTN'T be freed until + * HvFree is called. + * @param ChunkBase + * Pointer to hive data. + * @param ChunkSize + * Size of passed hive data. + * + * @return + * STATUS_NO_MEMORY - A memory allocation failed. + * STATUS_REGISTRY_CORRUPT - Registry corruption was detected. + * STATUS_SUCCESS + * + * @see HvFree + */ + +NTSTATUS CMAPI +HvInitialize( + PREGISTRY_HIVE *RegistryHive, + ULONG Operation, + ULONG_PTR ChunkBase, + SIZE_T ChunkSize, + PFILE_READ FileRead, + PFILE_WRITE FileWrite, + PFILE_SET_SIZE FileSetSize, + PFILE_FLUSH FileFlush, + PVOID Opaque) +{ + NTSTATUS Status; + PREGISTRY_HIVE Hive; + + /* + * Create a new hive structure that will hold all the maintenance data. + */ + + Hive = CmpAllocate(sizeof(REGISTRY_HIVE)); + if (Hive == NULL) + return STATUS_NO_MEMORY; + RtlZeroMemory(Hive, sizeof(REGISTRY_HIVE)); + + switch (Operation) + { + case HV_OPERATION_CREATE_HIVE: + Status = HvpCreateHive(Hive); + break; + + case HV_OPERATION_MEMORY: + Status = HvpInitializeMemoryHive(Hive, ChunkBase, ChunkSize); + break; + + case HV_OPERATION_MEMORY_INPLACE: + Status = HvpInitializeMemoryInplaceHive(Hive, ChunkBase, ChunkSize); + break; + + default: + ASSERT(FALSE); + } + + if (!NT_SUCCESS(Status)) + { + CmpFree(Hive); + return Status; + } + + Hive->FileRead = FileRead; + Hive->FileWrite = FileWrite; + Hive->FileSetSize = FileSetSize; + Hive->FileFlush = FileFlush; + Hive->Opaque = Opaque; + + *RegistryHive = Hive; + + return Status; +} + +/** + * @name HvFree + * + * Free all stroage and handles associated with hive descriptor. + */ + +VOID CMAPI +HvFree( + PREGISTRY_HIVE RegistryHive) +{ + if (!RegistryHive->ReadOnly) + { + /* Release hive bitmap */ + if (RegistryHive->DirtyBitmap.Buffer) + { + CmpFree(RegistryHive->DirtyBitmap.Buffer); + } + + HvpFreeHiveBins(RegistryHive); + } + + CmpFree(RegistryHive); +} + +/* EOF */ Index: lib/cmlib/hivesum.c =================================================================== --- lib/cmlib/hivesum.c (revision 0) +++ lib/cmlib/hivesum.c (revision 0) @@ -0,0 +1,32 @@ +/* + * PROJECT: registry manipulation library + * LICENSE: GPL - See COPYING in the top level directory + * COPYRIGHT: Copyright 2005 Filip Navara + * Copyright 2001 - 2005 Eric Kohl + */ + +#include "cmlib.h" + +/** + * @name HvpHiveHeaderChecksum + * + * Compute checksum of hive header and return it. + */ + +ULONG CMAPI +HvpHiveHeaderChecksum( + PHIVE_HEADER HiveHeader) +{ + PULONG Buffer = (PULONG)HiveHeader; + 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; +} Index: lib/cmlib/cminit.c =================================================================== --- lib/cmlib/cminit.c (revision 0) +++ lib/cmlib/cminit.c (revision 0) @@ -0,0 +1,82 @@ +/* + * PROJECT: registry manipulation library + * LICENSE: GPL - See COPYING in the top level directory + * COPYRIGHT: Copyright 2005 Filip Navara + * Copyright 2001 - 2005 Eric Kohl + */ + +#include "cmlib.h" + +BOOLEAN CMAPI +CmCreateRootNode( + PREGISTRY_HIVE Hive, + PCWSTR Name) +{ + PKEY_CELL KeyCell; + HCELL_INDEX RootCellIndex; + ULONG NameSize; + + NameSize = wcslen(Name) * sizeof(WCHAR); + RootCellIndex = HvAllocateCell(Hive, sizeof(KEY_CELL) + NameSize, HvStable); + if (RootCellIndex == HCELL_NULL) + return FALSE; + + Hive->HiveHeader->RootCell = RootCellIndex; + Hive->HiveHeader->Checksum = HvpHiveHeaderChecksum(Hive->HiveHeader); + + KeyCell = (PKEY_CELL)HvGetCell(Hive, RootCellIndex); + KeyCell->Id = REG_KEY_CELL_ID; + KeyCell->Flags = REG_KEY_ROOT_CELL; + KeyCell->LastWriteTime.QuadPart = 0; + KeyCell->ParentKeyOffset = HCELL_NULL; + KeyCell->NumberOfSubKeys[0] = 0; + KeyCell->NumberOfSubKeys[1] = 0; + KeyCell->HashTableOffset[0] = HCELL_NULL; + KeyCell->HashTableOffset[1] = HCELL_NULL; + KeyCell->NumberOfValues = 0; + KeyCell->ValueListOffset = HCELL_NULL; + KeyCell->SecurityKeyOffset = HCELL_NULL; + KeyCell->ClassNameOffset = HCELL_NULL; + KeyCell->NameSize = NameSize; + KeyCell->ClassSize = 0; + memcpy(KeyCell->Name, Name, NameSize); + + return TRUE; +} + +static VOID CMAPI +CmpPrepareKey( + PREGISTRY_HIVE RegistryHive, + PKEY_CELL KeyCell) +{ + PKEY_CELL SubKeyCell; + PHASH_TABLE_CELL HashCell; + ULONG i; + + ASSERT(KeyCell->Id == REG_KEY_CELL_ID); + + KeyCell->HashTableOffset[HvVolatile] = HCELL_NULL; + KeyCell->NumberOfSubKeys[HvVolatile] = 0; + + /* Enumerate and add subkeys */ + if (KeyCell->NumberOfSubKeys[HvStable] > 0) + { + HashCell = HvGetCell(RegistryHive, KeyCell->HashTableOffset[HvStable]); + + for (i = 0; i < KeyCell->NumberOfSubKeys[HvStable]; i++) + { + SubKeyCell = HvGetCell(RegistryHive, HashCell->Table[i].KeyOffset); + CmpPrepareKey(RegistryHive, SubKeyCell); + } + } +} + +VOID CMAPI +CmPrepareHive( + PREGISTRY_HIVE RegistryHive) +{ + PKEY_CELL RootCell; + + RootCell = HvGetCell(RegistryHive, RegistryHive->HiveHeader->RootCell); + CmpPrepareKey(RegistryHive, RootCell); +} Index: lib/cmlib/cmlib.xml =================================================================== --- lib/cmlib/cmlib.xml (revision 0) +++ lib/cmlib/cmlib.xml (revision 0) @@ -0,0 +1,13 @@ + + . + + + + cmlib.h + cminit.c + hivebin.c + hivecell.c + hiveinit.c + hivesum.c + hivewrt.c + Index: lib/cmlib/hivebin.c =================================================================== --- lib/cmlib/hivebin.c (revision 0) +++ lib/cmlib/hivebin.c (revision 0) @@ -0,0 +1,98 @@ +/* + * PROJECT: registry manipulation library + * LICENSE: GPL - See COPYING in the top level directory + * COPYRIGHT: Copyright 2005 Filip Navara + * Copyright 2005 Hartmut Birr + * Copyright 2001 - 2005 Eric Kohl + */ + +#include "cmlib.h" + +PHBIN CMAPI +HvpAddBin( + PREGISTRY_HIVE RegistryHive, + ULONG Size, + HV_STORAGE_TYPE Storage) +{ + PBLOCK_LIST_ENTRY BlockList; + PHBIN Bin; + ULONG BinSize; + ULONG i; + ULONG BitmapSize; + ULONG BlockCount; + ULONG OldBlockListSize; + PCELL_HEADER Block; + + BinSize = ROUND_UP(Size + sizeof(HBIN), HV_BLOCK_SIZE); + BlockCount = BinSize / HV_BLOCK_SIZE; + + Bin = CmpAllocatePaged(BinSize); + if (Bin == NULL) + return NULL; + RtlZeroMemory(Bin, sizeof(HBIN)); + + Bin->Signature = HV_BIN_SIGNATURE; + Bin->BinOffset = RegistryHive->Storage[Storage].BlockListSize * + HV_BLOCK_SIZE; + Bin->BinSize = BinSize; + + /* Allocate new block list */ + OldBlockListSize = RegistryHive->Storage[Storage].BlockListSize; + BlockList = CmpAllocate(sizeof(BLOCK_LIST_ENTRY) * + (OldBlockListSize + BlockCount)); + if (BlockList == NULL) + { + CmpFree(Bin); + return NULL; + } + + if (OldBlockListSize > 0) + { + RtlCopyMemory(BlockList, RegistryHive->Storage[Storage].BlockList, + OldBlockListSize * sizeof(BLOCK_LIST_ENTRY)); + CmpFree(RegistryHive->Storage[Storage].BlockList); + } + + RegistryHive->Storage[Storage].BlockList = BlockList; + RegistryHive->Storage[Storage].BlockListSize += BlockCount; + + for (i = 0; i < BlockCount; i++) + { + RegistryHive->Storage[Storage].BlockList[OldBlockListSize + i].Block = + (PVOID)((ULONG_PTR)Bin + (i * HV_BLOCK_SIZE)); + RegistryHive->Storage[Storage].BlockList[OldBlockListSize + i].Bin = Bin; + } + + /* Initialize a free block in this heap. */ + Block = (PCELL_HEADER)(Bin + 1); + Block->CellSize = BinSize - sizeof(HBIN); + + if (Storage == HvStable) + { + /* Calculate bitmap size in bytes (always a multiple of 32 bits). */ + BitmapSize = ROUND_UP(RegistryHive->Storage[HvStable].BlockListSize, + sizeof(ULONG) * 8) / 8; + + /* Grow bitmap if necessary. */ + if (BitmapSize > RegistryHive->DirtyBitmap.SizeOfBitMap / 8) + { + PULONG BitmapBuffer; + + BitmapBuffer = CmpAllocatePaged(BitmapSize); + RtlZeroMemory(BitmapBuffer, BitmapSize); + RtlCopyMemory(BitmapBuffer, + RegistryHive->DirtyBitmap.Buffer, + RegistryHive->DirtyBitmap.SizeOfBitMap / 8); + CmpFree(RegistryHive->DirtyBitmap.Buffer); + RtlInitializeBitMap(&RegistryHive->DirtyBitmap, BitmapBuffer, + BitmapSize * 8); + } + + /* Mark new bin dirty. */ + RtlSetBits(&RegistryHive->DirtyBitmap, + Bin->BinOffset / HV_BLOCK_SIZE, + BlockCount); + } + + return Bin; +} Index: lib/cmlib/hivewrt.c =================================================================== --- lib/cmlib/hivewrt.c (revision 0) +++ lib/cmlib/hivewrt.c (revision 0) @@ -0,0 +1,277 @@ +/* + * PROJECT: registry manipulation library + * LICENSE: GPL - See COPYING in the top level directory + * COPYRIGHT: Copyright 2005 Filip Navara + * Copyright 2001 - 2005 Eric Kohl + */ + +#include "cmlib.h" +#define NDEBUG +#include + +static BOOLEAN CMAPI +HvpWriteLog( + PREGISTRY_HIVE RegistryHive) +{ + ULONG FileOffset; + ULONG BufferSize; + ULONG BitmapSize; + PUCHAR Buffer; + PUCHAR Ptr; + ULONG BlockIndex; + ULONG LastIndex; + PVOID BlockPtr; + BOOLEAN Success; + + ASSERT(RegistryHive->ReadOnly == FALSE); + + DPRINT("HvpWriteLog called\n"); + + if (RegistryHive->HiveHeader->Sequence1 != + RegistryHive->HiveHeader->Sequence2) + { + return FALSE; + } + + BitmapSize = RegistryHive->DirtyBitmap.SizeOfBitMap; + BufferSize = HV_LOG_HEADER_SIZE + sizeof(ULONG) + BitmapSize; + BufferSize = ROUND_UP(BufferSize, HV_BLOCK_SIZE); + + DPRINT("Bitmap size %lu buffer size: %lu\n", BitmapSize, BufferSize); + + Buffer = CmpAllocatePaged(BufferSize); + if (Buffer == NULL) + { + return FALSE; + } + + /* Update firt update counter and checksum */ + RegistryHive->HiveHeader->Type = HV_TYPE_LOG; + RegistryHive->HiveHeader->Sequence1++; + RegistryHive->HiveHeader->Checksum = + HvpHiveHeaderChecksum(RegistryHive->HiveHeader); + + /* Copy hive header */ + RtlCopyMemory(Buffer, RegistryHive->HiveHeader, HV_LOG_HEADER_SIZE); + Ptr = Buffer + HV_LOG_HEADER_SIZE; + RtlCopyMemory(Ptr, "DIRT", 4); + Ptr += 4; + RtlCopyMemory(Ptr, RegistryHive->DirtyBitmap.Buffer, BitmapSize); + + /* Write hive block and block bitmap */ + Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_LOG, + 0, Buffer, BufferSize); + if (!Success) + { + return FALSE; + } + + CmpFree(Buffer); + + /* Write dirty blocks */ + FileOffset = BufferSize; + BlockIndex = 0; + while (BlockIndex < RegistryHive->Storage[HvStable].BlockListSize) + { + LastIndex = BlockIndex; + BlockIndex = RtlFindSetBits(&RegistryHive->DirtyBitmap, 1, BlockIndex); + if (BlockIndex == ~0 || BlockIndex < LastIndex) + { + break; + } + + BlockPtr = RegistryHive->Storage[HvStable].BlockList[BlockIndex].Block; + + /* Write hive block */ + Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_LOG, + FileOffset, BlockPtr, + HV_BLOCK_SIZE); + if (!Success) + { + return FALSE; + } + + BlockIndex++; + FileOffset += HV_BLOCK_SIZE; + } + + Success = RegistryHive->FileSetSize(RegistryHive, HV_TYPE_LOG, FileOffset); + if (!Success) + { + DPRINT("FileSetSize failed\n"); + return FALSE; + } + + /* Flush the log file */ + Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_LOG); + if (!Success) + { + DPRINT("FileFlush failed\n"); + } + + /* Update first and second update counter and checksum. */ + RegistryHive->HiveHeader->Sequence2++; + RegistryHive->HiveHeader->Checksum = + HvpHiveHeaderChecksum(RegistryHive->HiveHeader); + + /* Write hive header again with updated sequence counter. */ + Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_LOG, + 0, RegistryHive->HiveHeader, + HV_LOG_HEADER_SIZE); + if (!Success) + { + return FALSE; + } + + /* Flush the log file */ + Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_LOG); + if (!Success) + { + DPRINT("FileFlush failed\n"); + } + + return TRUE; +} + +static BOOLEAN CMAPI +HvpWriteHive( + PREGISTRY_HIVE RegistryHive, + BOOLEAN OnlyDirty) +{ + ULONG FileOffset; + ULONG BlockIndex; + ULONG LastIndex; + PVOID BlockPtr; + BOOLEAN Success; + + ASSERT(RegistryHive->ReadOnly == FALSE); + + DPRINT("HvpWriteHive called\n"); + + if (RegistryHive->HiveHeader->Sequence1 != + RegistryHive->HiveHeader->Sequence2) + { + return FALSE; + } + + /* Update first update counter and checksum */ + RegistryHive->HiveHeader->Type = HV_TYPE_PRIMARY; + RegistryHive->HiveHeader->Sequence1++; + RegistryHive->HiveHeader->Checksum = + HvpHiveHeaderChecksum(RegistryHive->HiveHeader); + + /* Write hive block */ + Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_PRIMARY, + 0, RegistryHive->HiveHeader, + sizeof(HIVE_HEADER)); + if (!Success) + { + return FALSE; + } + + BlockIndex = 0; + while (BlockIndex < RegistryHive->Storage[HvStable].BlockListSize) + { + if (OnlyDirty) + { + LastIndex = BlockIndex; + BlockIndex = RtlFindSetBits(&RegistryHive->DirtyBitmap, 1, BlockIndex); + if (BlockIndex == ~0 || BlockIndex < LastIndex) + { + break; + } + } + + BlockPtr = RegistryHive->Storage[HvStable].BlockList[BlockIndex].Block; + FileOffset = (ULONGLONG)(BlockIndex + 1) * (ULONGLONG)HV_BLOCK_SIZE; + + /* Write hive block */ + Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_PRIMARY, + FileOffset, BlockPtr, + HV_BLOCK_SIZE); + if (!Success) + { + return FALSE; + } + + BlockIndex++; + } + + Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_PRIMARY); + if (!Success) + { + DPRINT("FileFlush failed\n"); + } + + /* Update second update counter and checksum */ + RegistryHive->HiveHeader->Sequence2++; + RegistryHive->HiveHeader->Checksum = + HvpHiveHeaderChecksum(RegistryHive->HiveHeader); + + /* Write hive block */ + Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_PRIMARY, + 0, RegistryHive->HiveHeader, + sizeof(HIVE_HEADER)); + if (!Success) + { + return FALSE; + } + + Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_PRIMARY); + if (!Success) + { + DPRINT("FileFlush failed\n"); + } + + return TRUE; +} + +BOOLEAN CMAPI +HvSyncHive( + PREGISTRY_HIVE RegistryHive) +{ + ASSERT(RegistryHive->ReadOnly == FALSE); + + if (RtlFindSetBits(&RegistryHive->DirtyBitmap, 1, 0) == ~0) + { + return TRUE; + } + + /* Update hive header modification time */ + KeQuerySystemTime(&RegistryHive->HiveHeader->TimeStamp); + + /* Update log file */ + if (!HvpWriteLog(RegistryHive)) + { + return FALSE; + } + + /* Update hive file */ + if (!HvpWriteHive(RegistryHive, TRUE)) + { + return FALSE; + } + + /* Clear dirty bitmap. */ + RtlClearAllBits(&RegistryHive->DirtyBitmap); + + return TRUE; +} + +BOOLEAN CMAPI +HvWriteHive( + PREGISTRY_HIVE RegistryHive) +{ + ASSERT(RegistryHive->ReadOnly == FALSE); + + /* Update hive header modification time */ + KeQuerySystemTime(&RegistryHive->HiveHeader->TimeStamp); + + /* Update hive file */ + if (!HvpWriteHive(RegistryHive, FALSE)) + { + return FALSE; + } + + return TRUE; +} Index: lib/cmlib/hivedata.h =================================================================== --- lib/cmlib/hivedata.h (revision 0) +++ lib/cmlib/hivedata.h (revision 0) @@ -0,0 +1,138 @@ +/* + * PROJECT: registry manipulation library + * LICENSE: GPL - See COPYING in the top level directory + * COPYRIGHT: Copyright 2005 Filip Navara + * Copyright 2001 - 2005 Eric Kohl + */ + +#ifndef CMLIB_HIVEDATA_H +#define CMLIB_HIVEDATA_H + +#define HV_BLOCK_SIZE 4096 +#define HV_LOG_HEADER_SIZE FIELD_OFFSET(HIVE_HEADER, Reserved2) +#define HV_SIGNATURE 0x66676572 +#define HV_BIN_SIGNATURE 0x6e696268 + +#define HV_MAJOR_VER 1 +#define HV_MINOR_VER 3 +#define HV_FORMAT_MEMORY 1 + +#define HV_TYPE_PRIMARY 0 +#define HV_TYPE_ALTERNATE 1 +#define HV_TYPE_LOG 2 +#define HV_TYPE_EXTERNAL 3 +#define HV_TYPE_MAX 4 + +/** + * @name HCELL_INDEX + * + * A handle to cell index. The highest bit specifies the cell storage and + * the other bits specify index into the hive file. The value HCELL_NULL + * (-1) is reserved for marking invalid cells. + */ + +typedef ULONG HCELL_INDEX, *PHCELL_INDEX; + +#define HCELL_NULL ((HCELL_INDEX)-1) +#define HCELL_TYPE_MASK 0x80000000 +#define HCELL_BLOCK_MASK 0x7ffff000 +#define HCELL_OFFSET_MASK 0x00000fff +#define HCELL_TYPE_SHIFT 31 +#define HCELL_BLOCK_SHIFT 12 +#define HCELL_OFFSET_SHIFT 0 + +#include + +/** + * @name HIVE_HEADER + * + * On-disk header for registry hive file. + */ + +typedef struct _HIVE_HEADER +{ + /* Hive identifier "regf" (0x66676572) */ + ULONG Signature; + + /* Update counter */ + ULONG Sequence1; + + /* Update counter */ + ULONG Sequence2; + + /* When this hive file was last modified */ + LARGE_INTEGER TimeStamp; + + /* Registry format major version (1) */ + ULONG Major; + + /* Registry format minor version (3) + Version 3 added fast indexes, version 5 has large value optimizations */ + ULONG Minor; + + /* 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 */ + HCELL_INDEX RootCell; + + /* Size of each hive block ? */ + ULONG Length; + + /* (1?) */ + ULONG Cluster; + + /* Name of hive file */ + WCHAR FileName[32]; + + ULONG Reserved1[99]; + + /* Checksum of first 0x200 bytes */ + ULONG Checksum; + + ULONG Reserved2[0x380]; +} HIVE_HEADER, *PHIVE_HEADER; + +typedef struct _BIN_HEADER +{ + /* Bin identifier "hbin" (0x6E696268) */ + ULONG Signature; + + /* Block offset of this bin */ + HCELL_INDEX 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; + +#include + +#define IsFreeCell(Cell)(Cell->CellSize >= 0) +#define IsUsedCell(Cell)(Cell->CellSize < 0) + +typedef enum _HV_STORAGE_TYPE +{ + HvStable = 0, + HvVolatile, + HvMaxStorageType +} HV_STORAGE_TYPE; + +#endif /* CMLIB_HIVEDATA_H */ Index: lib/cmlib/cmlib.h =================================================================== --- lib/cmlib/cmlib.h (revision 0) +++ lib/cmlib/cmlib.h (revision 0) @@ -0,0 +1,172 @@ +/* + * PROJECT: registry manipulation library + * LICENSE: GPL - See COPYING in the top level directory + * COPYRIGHT: Copyright 2005 Filip Navara + * Copyright 2001 - 2005 Eric Kohl + */ + +#ifndef CMLIB_H +#define CMLIB_H + +#include +#include "hivedata.h" +#include "cmdata.h" + +#ifndef ROUND_UP +#define ROUND_UP(a,b) ((((a)+(b)-1)/(b))*(b)) +#define ROUND_DOWN(a,b) (((a)/(b))*(b)) +#endif + +#define CMAPI + +typedef struct _BLOCK_LIST_ENTRY +{ + PHBIN Bin; + PVOID Block; +} BLOCK_LIST_ENTRY, *PBLOCK_LIST_ENTRY; + +struct _REGISTRY_HIVE; + +typedef BOOLEAN (CMAPI *PFILE_READ)( + struct _REGISTRY_HIVE *RegistryHive, + ULONG FileType, + ULONG FileOffset, + PVOID Buffer, + ULONG BufferLength); + +typedef BOOLEAN (CMAPI *PFILE_WRITE)( + struct _REGISTRY_HIVE *RegistryHive, + ULONG FileType, + ULONG FileOffset, + PVOID Buffer, + ULONG BufferLength); + +typedef BOOLEAN (CMAPI *PFILE_SET_SIZE)( + struct _REGISTRY_HIVE *RegistryHive, + ULONG FileType, + ULONG FileSize); + +typedef BOOLEAN (CMAPI *PFILE_FLUSH)( + struct _REGISTRY_HIVE *RegistryHive, + ULONG FileType); + +typedef struct _REGISTRY_HIVE +{ + PHIVE_HEADER HiveHeader; + BOOLEAN ReadOnly; + BOOLEAN Flat; + RTL_BITMAP DirtyBitmap; + struct + { + ULONG BlockListSize; + PBLOCK_LIST_ENTRY BlockList; + HCELL_INDEX FreeListOffset[24]; + } Storage[HvMaxStorageType]; + + PFILE_READ FileRead; + PFILE_WRITE FileWrite; + PFILE_SET_SIZE FileSetSize; + PFILE_FLUSH FileFlush; + PVOID Opaque; +} REGISTRY_HIVE, *PREGISTRY_HIVE; + +/* + * External callbacks. + */ + +void *CmpAllocate(ULONG size); +void *CmpAllocatePaged(ULONG size); +void CmpFree(void *ptr); + +/* + * Public functions. + */ + +#define HV_OPERATION_CREATE_HIVE 1 +#define HV_OPERATION_MEMORY 2 +#define HV_OPERATION_MEMORY_INPLACE 3 + +NTSTATUS CMAPI +HvInitialize( + PREGISTRY_HIVE *RegistryHive, + ULONG Operation, + ULONG_PTR ChunkBase, + SIZE_T ChunkSize, + PFILE_READ FileRead, + PFILE_WRITE FileWrite, + PFILE_SET_SIZE FileSetSize, + PFILE_FLUSH FileFlush, + PVOID Opaque); + +VOID CMAPI +HvFree( + PREGISTRY_HIVE RegistryHive); + +PVOID CMAPI +HvGetCell( + PREGISTRY_HIVE RegistryHive, + HCELL_INDEX CellOffset); + +LONG CMAPI +HvGetCellSize( + PREGISTRY_HIVE RegistryHive, + PVOID Cell); + +HCELL_INDEX CMAPI +HvAllocateCell( + PREGISTRY_HIVE RegistryHive, + ULONG Size, + HV_STORAGE_TYPE Storage); + +HCELL_INDEX CMAPI +HvReallocateCell( + PREGISTRY_HIVE RegistryHive, + HCELL_INDEX CellOffset, + ULONG Size); + +VOID CMAPI +HvFreeCell( + PREGISTRY_HIVE RegistryHive, + HCELL_INDEX CellOffset); + +VOID CMAPI +HvMarkCellDirty( + PREGISTRY_HIVE RegistryHive, + HCELL_INDEX CellOffset); + +BOOLEAN CMAPI +HvSyncHive( + PREGISTRY_HIVE RegistryHive); + +BOOLEAN CMAPI +HvWriteHive( + PREGISTRY_HIVE RegistryHive); + +BOOLEAN CMAPI +CmCreateRootNode( + PREGISTRY_HIVE Hive, + PCWSTR Name); + +VOID CMAPI +CmPrepareHive( + PREGISTRY_HIVE RegistryHive); + +/* + * Private functions. + */ + +PHBIN CMAPI +HvpAddBin( + PREGISTRY_HIVE RegistryHive, + ULONG Size, + HV_STORAGE_TYPE Storage); + +NTSTATUS CMAPI +HvpCreateHiveFreeCellList( + PREGISTRY_HIVE Hive); + +ULONG CMAPI +HvpHiveHeaderChecksum( + PHIVE_HEADER HiveHeader); + +#endif /* CMLIB_H */ Index: lib/cmlib/hivecell.c =================================================================== --- lib/cmlib/hivecell.c (revision 0) +++ lib/cmlib/hivecell.c (revision 0) @@ -0,0 +1,429 @@ +/* + * PROJECT: registry manipulation library + * LICENSE: GPL - See COPYING in the top level directory + * COPYRIGHT: Copyright 2005 Filip Navara + * Copyright 2001 - 2005 Eric Kohl + */ + +#include "cmlib.h" +#define NDEBUG +#include + +static PCELL_HEADER __inline CMAPI +HvpGetCellHeader( + PREGISTRY_HIVE RegistryHive, + HCELL_INDEX CellIndex) +{ + PVOID Block; + + ASSERT(CellIndex != HCELL_NULL); + if (!RegistryHive->Flat) + { + ULONG CellType; + ULONG CellBlock; + ULONG CellOffset; + + CellType = (CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT; + CellBlock = (CellIndex & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT; + CellOffset = (CellIndex & HCELL_OFFSET_MASK) >> HCELL_OFFSET_SHIFT; + ASSERT(CellBlock < RegistryHive->Storage[CellType].BlockListSize); + Block = RegistryHive->Storage[CellType].BlockList[CellBlock].Block; + ASSERT(Block != NULL); + return (PVOID)((ULONG_PTR)Block + CellOffset); + } + else + { + ASSERT((CellIndex & HCELL_TYPE_MASK) == HvStable); + return (PVOID)((ULONG_PTR)RegistryHive->HiveHeader + HV_BLOCK_SIZE + + CellIndex); + } +} + +PVOID CMAPI +HvGetCell( + PREGISTRY_HIVE RegistryHive, + HCELL_INDEX CellIndex) +{ + return (PVOID)(HvpGetCellHeader(RegistryHive, CellIndex) + 1); +} + +static LONG __inline CMAPI +HvpGetCellFullSize( + PREGISTRY_HIVE RegistryHive, + PVOID Cell) +{ + return ((PCELL_HEADER)Cell - 1)->CellSize; +} + +LONG CMAPI +HvGetCellSize( + PREGISTRY_HIVE RegistryHive, + PVOID Cell) +{ + PCELL_HEADER CellHeader; + + CellHeader = (PCELL_HEADER)Cell - 1; + if (CellHeader->CellSize < 0) + return CellHeader->CellSize + sizeof(CELL_HEADER); + else + return CellHeader->CellSize - sizeof(CELL_HEADER); +} + +VOID CMAPI +HvMarkCellDirty( + PREGISTRY_HIVE RegistryHive, + HCELL_INDEX CellIndex) +{ + LONG CellSize; + ULONG CellBlock; + ULONG CellLastBlock; + + ASSERT(RegistryHive->ReadOnly == FALSE); + + if ((CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT != HvStable) + return; + + CellBlock = (CellIndex & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT; + CellLastBlock = ((CellIndex + HV_BLOCK_SIZE - 1) & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT; + + CellSize = HvpGetCellFullSize(RegistryHive, HvGetCell(RegistryHive, CellIndex)); + if (CellSize < 0) + CellSize = -CellSize; + + RtlSetBits(&RegistryHive->DirtyBitmap, + CellBlock, CellLastBlock - CellBlock); +} + +static ULONG __inline CMAPI +HvpComputeFreeListIndex( + ULONG Size) +{ + ULONG Index; + static CCHAR FindFirstSet[256] = { + 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7}; + + Index = (Size >> 3) - 1; + if (Index >= 16) + { + if (Index > 255) + Index = 23; + else + Index = FindFirstSet[Index] + 7; + } + + return Index; +} + +static NTSTATUS CMAPI +HvpAddFree( + PREGISTRY_HIVE RegistryHive, + PCELL_HEADER FreeBlock, + HCELL_INDEX FreeIndex) +{ + PHCELL_INDEX FreeBlockData; + HV_STORAGE_TYPE Storage; + ULONG Index; + + ASSERT(RegistryHive != NULL); + ASSERT(FreeBlock != NULL); + + Storage = (FreeIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT; + Index = HvpComputeFreeListIndex(FreeBlock->CellSize); + + FreeBlockData = (PHCELL_INDEX)(FreeBlock + 1); + *FreeBlockData = RegistryHive->Storage[Storage].FreeListOffset[Index]; + RegistryHive->Storage[Storage].FreeListOffset[Index] = FreeIndex; + + /* FIXME: Eventually get rid of free bins. */ + + return STATUS_SUCCESS; +} + +static VOID CMAPI +HvpRemoveFree( + PREGISTRY_HIVE RegistryHive, + PCELL_HEADER CellBlock, + HCELL_INDEX CellIndex) +{ + PHCELL_INDEX FreeCellData; + PHCELL_INDEX pFreeCellOffset; + HV_STORAGE_TYPE Storage; + ULONG Index; + + ASSERT(RegistryHive->ReadOnly == FALSE); + + Storage = (CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT; + Index = HvpComputeFreeListIndex(CellBlock->CellSize); + + pFreeCellOffset = &RegistryHive->Storage[Storage].FreeListOffset[Index]; + while (*pFreeCellOffset != HCELL_NULL) + { + FreeCellData = (PHCELL_INDEX)HvGetCell(RegistryHive, *pFreeCellOffset); + if (*pFreeCellOffset == CellIndex) + { + *pFreeCellOffset = *FreeCellData; + return; + } + pFreeCellOffset = FreeCellData; + } + + ASSERT(FALSE); +} + +static HCELL_INDEX CMAPI +HvpFindFree( + PREGISTRY_HIVE RegistryHive, + ULONG Size, + HV_STORAGE_TYPE Storage) +{ + PHCELL_INDEX FreeCellData; + HCELL_INDEX FreeCellOffset; + PHCELL_INDEX pFreeCellOffset; + ULONG Index; + + for (Index = HvpComputeFreeListIndex(Size); Index < 24; Index++) + { + pFreeCellOffset = &RegistryHive->Storage[Storage].FreeListOffset[Index]; + while (*pFreeCellOffset != HCELL_NULL) + { + FreeCellData = (PHCELL_INDEX)HvGetCell(RegistryHive, *pFreeCellOffset); + if (HvpGetCellFullSize(RegistryHive, FreeCellData) >= Size) + { + FreeCellOffset = *pFreeCellOffset; + *pFreeCellOffset = *FreeCellData; + return FreeCellOffset; + } + pFreeCellOffset = FreeCellData; + } + } + + return HCELL_NULL; +} + +NTSTATUS CMAPI +HvpCreateHiveFreeCellList( + PREGISTRY_HIVE Hive) +{ + HCELL_INDEX BlockOffset; + PCELL_HEADER FreeBlock; + ULONG BlockIndex; + ULONG FreeOffset; + PHBIN Bin; + NTSTATUS Status; + ULONG Index; + + /* Initialize the free cell list */ + for (Index = 0; Index < 24; Index++) + { + Hive->Storage[HvStable].FreeListOffset[Index] = HCELL_NULL; + Hive->Storage[HvVolatile].FreeListOffset[Index] = HCELL_NULL; + } + + BlockOffset = 0; + BlockIndex = 0; + while (BlockIndex < Hive->Storage[HvStable].BlockListSize) + { + Bin = Hive->Storage[HvStable].BlockList[BlockIndex].Bin; + + /* Search free blocks and add to list */ + FreeOffset = sizeof(HBIN); + while (FreeOffset < Bin->BinSize) + { + FreeBlock = (PCELL_HEADER)((ULONG_PTR)Bin + FreeOffset); + if (FreeBlock->CellSize > 0) + { + Status = HvpAddFree(Hive, FreeBlock, Bin->BinOffset + FreeOffset); + if (!NT_SUCCESS(Status)) + return Status; + + FreeOffset += FreeBlock->CellSize; + } + else + { + FreeOffset -= FreeBlock->CellSize; + } + } + + BlockIndex += Bin->BinSize / HV_BLOCK_SIZE; + BlockOffset += Bin->BinSize; + } + + return STATUS_SUCCESS; +} + +HCELL_INDEX CMAPI +HvAllocateCell( + PREGISTRY_HIVE RegistryHive, + ULONG Size, + HV_STORAGE_TYPE Storage) +{ + PCELL_HEADER FreeCell; + HCELL_INDEX FreeCellOffset; + PCELL_HEADER NewCell; + PHBIN Bin; + + ASSERT(RegistryHive->ReadOnly == FALSE); + + /* Round to 16 bytes multiple. */ + Size = ROUND_UP(Size + sizeof(CELL_HEADER), 16); + + /* First search in free blocks. */ + FreeCellOffset = HvpFindFree(RegistryHive, Size, Storage); + + /* If no free cell was found we need to extend the hive file. */ + if (FreeCellOffset == HCELL_NULL) + { + Bin = HvpAddBin(RegistryHive, Size, Storage); + if (Bin == NULL) + return HCELL_NULL; + FreeCellOffset = Bin->BinOffset + sizeof(HBIN); + FreeCellOffset |= Storage << HCELL_TYPE_SHIFT; + } + + FreeCell = HvpGetCellHeader(RegistryHive, FreeCellOffset); + + /* Split the block in two parts */ + /* FIXME: There is some minimal cell size that we must respect. */ + if (FreeCell->CellSize > Size + sizeof(HCELL_INDEX)) + { + NewCell = (PCELL_HEADER)((ULONG_PTR)FreeCell + Size); + NewCell->CellSize = FreeCell->CellSize - Size; + FreeCell->CellSize = Size; + HvpAddFree(RegistryHive, NewCell, FreeCellOffset + Size); + if (Storage == HvStable) + HvMarkCellDirty(RegistryHive, FreeCellOffset + Size); + } + + if (Storage == HvStable) + HvMarkCellDirty(RegistryHive, FreeCellOffset); + FreeCell->CellSize = -FreeCell->CellSize; + RtlZeroMemory(FreeCell + 1, Size - sizeof(CELL_HEADER)); + + return FreeCellOffset; +} + +HCELL_INDEX CMAPI +HvReallocateCell( + PREGISTRY_HIVE RegistryHive, + HCELL_INDEX CellIndex, + ULONG Size) +{ + PVOID OldCell; + PVOID NewCell; + LONG OldCellSize; + HCELL_INDEX NewCellIndex; + HV_STORAGE_TYPE Storage; + + ASSERT(CellIndex != HCELL_NULL); + + Storage = (CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT; + + OldCell = HvGetCell(RegistryHive, CellIndex); + OldCellSize = HvGetCellSize(RegistryHive, OldCell); + ASSERT(OldCellSize < 0); + + /* + * If new data size is larger than the current, destroy current + * data block and allocate a new one. + * + * FIXME: Merge with adjacent free cell if possible. + * FIXME: Implement shrinking. + */ + if (Size > -OldCellSize) + { + NewCellIndex = HvAllocateCell(RegistryHive, Size, Storage); + if (NewCellIndex == HCELL_NULL) + return HCELL_NULL; + + NewCell = HvGetCell(RegistryHive, NewCellIndex); + RtlCopyMemory(NewCell, OldCell, -OldCellSize); + + HvFreeCell(RegistryHive, CellIndex); + + return NewCellIndex; + } + + return CellIndex; +} + +VOID CMAPI +HvFreeCell( + PREGISTRY_HIVE RegistryHive, + HCELL_INDEX CellIndex) +{ + PCELL_HEADER Free; + PCELL_HEADER Neighbor; + PHBIN Bin; + ULONG CellType; + ULONG CellBlock; + + ASSERT(RegistryHive->ReadOnly == FALSE); + + Free = HvpGetCellHeader(RegistryHive, CellIndex); + + ASSERT(Free->CellSize < 0); + + Free->CellSize = -Free->CellSize; + + CellType = (CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT; + CellBlock = (CellIndex & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT; + + /* FIXME: Merge free blocks */ + Bin = RegistryHive->Storage[CellType].BlockList[CellBlock].Bin; + + if ((CellIndex & ~HCELL_TYPE_MASK) + Free->CellSize < + Bin->BinOffset + Bin->BinSize) + { + Neighbor = (PCELL_HEADER)((ULONG_PTR)Free + Free->CellSize); + if (Neighbor->CellSize > 0) + { + HvpRemoveFree(RegistryHive, Neighbor, + ((HCELL_INDEX)Neighbor - (HCELL_INDEX)Bin + + Bin->BinOffset) | (CellIndex & HCELL_TYPE_MASK)); + Free->CellSize += Neighbor->CellSize; + } + } + + Neighbor = (PCELL_HEADER)(Bin + 1); + while (Neighbor < Free) + { + if (Neighbor->CellSize > 0) + { + if ((ULONG_PTR)Neighbor + Neighbor->CellSize == (ULONG_PTR)Free) + { + Neighbor->CellSize += Free->CellSize; + if (CellType == HvStable) + HvMarkCellDirty(RegistryHive, + (HCELL_INDEX)Neighbor - (HCELL_INDEX)Bin + + Bin->BinOffset); + return; + } + Neighbor = (PCELL_HEADER)((ULONG_PTR)Neighbor + Neighbor->CellSize); + } + else + { + Neighbor = (PCELL_HEADER)((ULONG_PTR)Neighbor - Neighbor->CellSize); + } + } + + /* Add block to the list of free blocks */ + HvpAddFree(RegistryHive, Free, CellIndex); + + if (CellType == HvStable) + HvMarkCellDirty(RegistryHive, CellIndex); +} Index: lib/cmlib/cmlib.mak =================================================================== --- lib/cmlib/cmlib.mak (revision 0) +++ lib/cmlib/cmlib.mak (revision 0) @@ -0,0 +1,55 @@ +CMLIB_BASE = $(LIB_BASE_)cmlib +CMLIB_BASE_ = $(CMLIB_BASE)$(SEP) +CMLIB_INT = $(INTERMEDIATE_)$(CMLIB_BASE)_host +CMLIB_INT_ = $(INTERMEDIATE_)$(CMLIB_BASE)_host$(SEP) +CMLIB_OUT = $(OUTPUT_)$(CMLIB_BASE)_host +CMLIB_OUT_ = $(OUTPUT_)$(CMLIB_BASE)_host$(SEP) + +$(CMLIB_INT): | $(LIB_INT) + $(ECHO_MKDIR) + ${mkdir} $@ + +ifneq ($(INTERMEDIATE),$(OUTPUT)) +$(CMLIB_OUT): | $(OUTPUT_)$(LIB_BASE) + $(ECHO_MKDIR) + ${mkdir} $@ +endif + +CMLIB_HOST_TARGET = \ + $(CMLIB_OUT)$(SEP)cmlib.a + +CMLIB_HOST_SOURCES = $(addprefix $(CMLIB_BASE_), \ + hivebin.c \ + hivecell.c \ + hiveinit.c \ + ) + +CMLIB_HOST_OBJECTS = \ + $(subst $(CMLIB_BASE), $(CMLIB_INT), $(CMLIB_HOST_SOURCES:.c=.o)) + +CMLIB_HOST_CFLAGS = -O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ + -DCMLIB_HOST -D_M_IX86 -I$(CMLIB_BASE) -Iinclude/reactos -DDBG + +$(CMLIB_HOST_TARGET): $(CMLIB_HOST_OBJECTS) | $(CMLIB_OUT) + $(ECHO_AR) + $(host_ar) -r $@ $(CMLIB_HOST_OBJECTS) + +$(CMLIB_INT_)hivebin.o: $(CMLIB_BASE_)hivebin.c | $(CMLIB_INT) + $(ECHO_CC) + ${host_gcc} $(CMLIB_HOST_CFLAGS) -c $< -o $@ + +$(CMLIB_INT_)hivecell.o: $(CMLIB_BASE_)hivecell.c | $(CMLIB_INT) + $(ECHO_CC) + ${host_gcc} $(CMLIB_HOST_CFLAGS) -c $< -o $@ + +$(CMLIB_INT_)hiveinit.o: $(CMLIB_BASE_)hiveinit.c | $(CMLIB_INT) + $(ECHO_CC) + ${host_gcc} $(CMLIB_HOST_CFLAGS) -c $< -o $@ + +.PHONY: cmlib_host +cmlib_host: $(CMLIB_HOST_TARGET) + +.PHONY: cmlib_host_clean +cmlib_host_clean: + -@$(rm) $(CMLIB_HOST_TARGET) $(CMLIB_HOST_OBJECTS) 2>$(NUL) +clean: cmlib_host_clean Index: lib/lib.mak =================================================================== --- lib/lib.mak (revision 19665) +++ lib/lib.mak (working copy) @@ -3,3 +3,4 @@ include $(LIB_BASE_)zlib/zlib.mak include $(LIB_BASE_)inflib/inflib.mak +include $(LIB_BASE_)cmlib/cmlib.mak Index: ntoskrnl/cm/cm.h =================================================================== --- ntoskrnl/cm/cm.h (revision 19665) +++ ntoskrnl/cm/cm.h (working copy) @@ -1,6 +1,8 @@ #ifndef __INCLUDE_CM_H #define __INCLUDE_CM_H +#include + #ifdef DBG #define CHECKED 1 #else @@ -35,266 +37,18 @@ #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 +typedef struct _EREGISTRY_HIVE { - /* 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[48]; - - 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 -{ 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; + ULONG Flags; + HANDLE HiveHandle; + HANDLE LogHandle; +} EREGISTRY_HIVE, *PEREGISTRY_HIVE; - 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 - /* When set, the hive is not backed by a file. Therefore, it can not be flushed to disk. */ #define HIVE_NO_FILE 0x00000002 @@ -303,22 +57,15 @@ 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 @@ 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 @@ /* 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 @@ /* 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; } KEY_OBJECT, *PKEY_OBJECT; @@ -368,8 +115,7 @@ #define CmiByteOffset(Cellndex)(CellIndex & 0x00000fff) -extern BOOLEAN CmiDoVerify; -extern PREGISTRY_HIVE CmiVolatileHive; +extern PEREGISTRY_HIVE CmiVolatileHive; extern POBJECT_TYPE CmiKeyType; extern KSPIN_LOCK CmiKeyListLock; @@ -399,34 +145,13 @@ 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, @@ -463,24 +188,7 @@ ULONG Length, PULONG ReturnLength); -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); @@ -494,7 +202,7 @@ PKEY_OBJECT* ReturnedObject); NTSTATUS -CmiCreateVolatileHive(PREGISTRY_HIVE *RegistryHive); +CmiCreateVolatileHive(PEREGISTRY_HIVE *RegistryHive); NTSTATUS CmiLoadHive(POBJECT_ATTRIBUTES KeyObjectAttributes, @@ -502,10 +210,10 @@ 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); @@ -517,24 +225,24 @@ 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, @@ -543,112 +251,80 @@ 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, + HCELL_INDEX HashCellOffset, 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); + HCELL_INDEX 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); - -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); @@ -690,16 +366,68 @@ 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); +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*/ Index: ntoskrnl/cm/registry.c =================================================================== --- ntoskrnl/cm/registry.c (revision 19665) +++ ntoskrnl/cm/registry.c (working copy) @@ -19,7 +19,7 @@ /* GLOBALS ******************************************************************/ POBJECT_TYPE CmiKeyType = NULL; -PREGISTRY_HIVE CmiVolatileHive = NULL; +PEREGISTRY_HIVE CmiVolatileHive = NULL; LIST_ENTRY CmiHiveListHead; @@ -57,193 +57,6 @@ /* 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) { @@ -305,6 +118,7 @@ } } + VOID INIT_FUNCTION STDCALL @@ -425,8 +239,8 @@ &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; @@ -688,7 +502,7 @@ NTSTATUS CmiConnectHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes, - IN PREGISTRY_HIVE RegistryHive) + IN PEREGISTRY_HIVE RegistryHive) { UNICODE_STRING RemainingPath; PKEY_OBJECT ParentKey; @@ -776,32 +590,33 @@ 0, NULL, NULL); -DPRINT("Status %x\n", Status); - NewKey->RegistryHive = RegistryHive; - NewKey->KeyCellOffset = RegistryHive->HiveHeader->RootKeyOffset; - NewKey->KeyCell = CmiGetCell (RegistryHive, NewKey->KeyCellOffset, NULL); + DPRINT("Status %x\n", Status); NewKey->Flags = 0; NewKey->NumberOfSubKeys = 0; + NewKey->SubKeys = NULL; + NewKey->SizeOfSubKeys = 0; InsertTailList(&CmiKeyObjectListHead, &NewKey->ListEntry); - if (NewKey->KeyCell->NumberOfSubKeys != 0) + + DPRINT ("SubName %S\n", SubName); + + Status = CmiAddSubKey(ParentKey->RegistryHive, + ParentKey, + NewKey, + &RemainingPath, + 0, + NULL, + REG_OPTION_VOLATILE); + if (!NT_SUCCESS(Status)) { - NewKey->SubKeys = ExAllocatePool(NonPagedPool, - NewKey->KeyCell->NumberOfSubKeys * sizeof(ULONG)); - if (NewKey->SubKeys == NULL) - { - DPRINT("ExAllocatePool() failed\n"); - ObDereferenceObject (NewKey); - ObDereferenceObject (ParentKey); - RtlFreeUnicodeString(&RemainingPath); - return STATUS_INSUFFICIENT_RESOURCES; - } + DPRINT1("CmiAddSubKey() failed (Status %lx)\n", Status); + ObDereferenceObject (NewKey); + ObDereferenceObject (ParentKey); + return STATUS_INSUFFICIENT_RESOURCES; } - else - { - NewKey->SubKeys = NULL; - } - DPRINT ("SubName %S\n", SubName); + NewKey->KeyCellOffset = RegistryHive->Hive->HiveHeader->RootCell; + NewKey->KeyCell = HvGetCell (RegistryHive->Hive, NewKey->KeyCellOffset); + NewKey->RegistryHive = RegistryHive; Status = RtlpCreateUnicodeString(&NewKey->Name, SubName, NonPagedPool); @@ -809,15 +624,14 @@ 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; } + /* FN1 */ + ObReferenceObject (NewKey); + CmiAddKeyToList (ParentKey, NewKey); ObDereferenceObject (ParentKey); @@ -831,10 +645,10 @@ NTSTATUS CmiDisconnectHive (IN POBJECT_ATTRIBUTES KeyObjectAttributes, - OUT PREGISTRY_HIVE *RegistryHive) + OUT PEREGISTRY_HIVE *RegistryHive) { PKEY_OBJECT KeyObject; - PREGISTRY_HIVE Hive; + PEREGISTRY_HIVE Hive; HANDLE KeyHandle; NTSTATUS Status; PLIST_ENTRY CurrentEntry; @@ -882,11 +696,14 @@ KeEnterCriticalRegion(); ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE); + Hive = KeyObject->RegistryHive; + CurrentEntry = CmiKeyObjectListHead.Flink; while (CurrentEntry != &CmiKeyObjectListHead) { CurrentKey = CONTAINING_RECORD(CurrentEntry, KEY_OBJECT, ListEntry); - if (1 == ObGetObjectPointerCount(CurrentKey) && + if (CurrentKey->RegistryHive == Hive && + 1 == ObGetObjectPointerCount(CurrentKey) && !(CurrentKey->Flags & KO_MARKED_FOR_DELETE)) { ObDereferenceObject(CurrentKey); @@ -898,6 +715,9 @@ } } + /* FN1 */ + ObDereferenceObject (KeyObject); + if (ObGetObjectHandleCount (KeyObject) != 0 || ObGetObjectPointerCount (KeyObject) != 2) { @@ -911,8 +731,6 @@ return STATUS_UNSUCCESSFUL; } - Hive = KeyObject->RegistryHive; - /* Dereference KeyObject twice to delete it */ ObDereferenceObject (KeyObject); ObDereferenceObject (KeyObject); @@ -1071,8 +889,6 @@ EndPtr = ConfigPath + wcslen(ConfigPath); - CmiDoVerify = TRUE; - /* FIXME: Save boot log */ /* Connect the SYSTEM hive only if it has been created */ @@ -1215,7 +1031,7 @@ VOID CmShutdownRegistry(VOID) { - PREGISTRY_HIVE Hive; + PEREGISTRY_HIVE Hive; PLIST_ENTRY Entry; DPRINT("CmShutdownRegistry() called\n"); @@ -1237,7 +1053,7 @@ 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))) { @@ -1259,7 +1075,7 @@ VOID STDCALL CmiHiveSyncRoutine(PVOID DeferredContext) { - PREGISTRY_HIVE Hive; + PEREGISTRY_HIVE Hive; PLIST_ENTRY Entry; DPRINT("CmiHiveSyncRoutine() called\n"); @@ -1273,7 +1089,7 @@ 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))) { Index: ntoskrnl/cm/regobj.c =================================================================== --- ntoskrnl/cm/regobj.c (revision 19665) +++ ntoskrnl/cm/regobj.c (working copy) @@ -18,7 +18,7 @@ extern ULONG CmiTimer; static NTSTATUS -CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive, +CmiGetLinkTarget(PEREGISTRY_HIVE RegistryHive, PKEY_CELL KeyCell, PUNICODE_STRING TargetPath); @@ -31,7 +31,7 @@ PWSTR *Path, ULONG Attributes) { - BLOCK_OFFSET BlockOffset; + HCELL_INDEX BlockOffset; PKEY_OBJECT FoundObject; PKEY_OBJECT ParsedKey; PKEY_CELL SubKeyCell; @@ -82,7 +82,6 @@ KeEnterCriticalRegion(); ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE); - Status = CmiScanKeyList(ParsedKey, &KeyName, Attributes, @@ -97,93 +96,93 @@ 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); @@ -193,8 +192,7 @@ 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); } @@ -259,7 +257,7 @@ ExReleaseResourceLite(&CmiRegistryLock); KeLeaveCriticalRegion(); - DPRINT("CmiObjectParse: %s\n", FoundObject->Name); + DPRINT("CmiObjectParse: %wZ\n", &FoundObject->Name); *Path = EndPtr; @@ -306,8 +304,8 @@ KeyObject); KeQuerySystemTime (&ParentKeyObject->KeyCell->LastWriteTime); - CmiMarkBlockDirty (ParentKeyObject->RegistryHive, - ParentKeyObject->KeyCellOffset); + HvMarkCellDirty (ParentKeyObject->RegistryHive->Hive, + ParentKeyObject->KeyCellOffset); if (!IsNoFileHive (KeyObject->RegistryHive) || !IsNoFileHive (ParentKeyObject->RegistryHive)) @@ -318,9 +316,6 @@ ObDereferenceObject (ParentKeyObject); - ExReleaseResourceLite(&CmiRegistryLock); - KeLeaveCriticalRegion(); - if (KeyObject->NumberOfSubKeys) { KEBUGCHECK(REGISTRY_ERROR); @@ -330,6 +325,9 @@ { ExFreePool(KeyObject->SubKeys); } + + ExReleaseResourceLite(&CmiRegistryLock); + KeLeaveCriticalRegion(); } @@ -415,7 +413,7 @@ PSECURITY_DESCRIPTOR SecurityDescriptor) { #if 0 - PREGISTRY_HIVE Hive; + PEREGISTRY_HIVE Hive; DPRINT1("CmiAssignSecurityDescriptor() callled\n"); @@ -550,6 +548,7 @@ } + VOID CmiAddKeyToList(PKEY_OBJECT ParentKey, PKEY_OBJECT NewKey) @@ -638,6 +637,7 @@ 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)) { @@ -658,6 +658,7 @@ { if (CurKey->Flags & KO_MARKED_FOR_DELETE) { + CHECKPOINT; *ReturnedObject = NULL; return STATUS_UNSUCCESSFUL; } @@ -673,13 +674,13 @@ 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"); @@ -715,9 +716,9 @@ 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; } Index: ntoskrnl/cm/import.c =================================================================== --- ntoskrnl/cm/import.c (revision 19665) +++ ntoskrnl/cm/import.c (working copy) @@ -20,121 +20,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, + 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)); + CmPrepareHive(Hive->Hive); - /* 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; - } - } - /* Acquire hive list lock exclusively */ KeEnterCriticalRegion(); ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE); @@ -157,7 +82,7 @@ ULONG ChunkSize) { OBJECT_ATTRIBUTES ObjectAttributes; - PREGISTRY_HIVE RegistryHive; + PEREGISTRY_HIVE RegistryHive; UNICODE_STRING KeyName; NTSTATUS Status; @@ -212,7 +137,7 @@ ULONG ChunkSize) { OBJECT_ATTRIBUTES ObjectAttributes; - PREGISTRY_HIVE RegistryHive; + PEREGISTRY_HIVE RegistryHive; UNICODE_STRING KeyName; HANDLE HardwareKey; ULONG Disposition; Index: ntoskrnl/cm/ntfunc.c =================================================================== --- ntoskrnl/cm/ntfunc.c (revision 19665) +++ ntoskrnl/cm/ntfunc.c (working copy) @@ -16,11 +16,9 @@ #include "cm.h" - /* GLOBALS ******************************************************************/ extern POBJECT_TYPE CmiKeyType; -extern PREGISTRY_HIVE CmiVolatileHive; extern LIST_ENTRY CmiKeyObjectListHead; static BOOLEAN CmiRegistryInitialized = FALSE; @@ -368,12 +366,7 @@ } 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; @@ -419,20 +412,11 @@ 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); VERIFY_KEY_OBJECT(KeyObject); @@ -524,7 +508,8 @@ 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; } @@ -576,19 +561,20 @@ 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(); @@ -639,10 +625,9 @@ 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(); @@ -654,96 +639,44 @@ } /* 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; + NameSize *= sizeof(WCHAR); } - else - { - NameSize = SubKeyCell->NameSize; - if (SubKeyCell->Flags & REG_KEY_NAME_PACKED) - { - NameSize *= sizeof(WCHAR); - } - } *ResultLength = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]) + NameSize; @@ -773,44 +706,28 @@ 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; + NameSize *= sizeof(WCHAR); } - else - { - NameSize = SubKeyCell->NameSize; - if (SubKeyCell->Flags & REG_KEY_NAME_PACKED) - { - NameSize *= sizeof(WCHAR); - } - } ClassSize = SubKeyCell->ClassSize; *ResultLength = FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) + @@ -847,35 +764,25 @@ 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); } } @@ -920,11 +827,10 @@ if (ClassSize != 0) { - ClassCell = CmiGetCell (KeyObject->RegistryHive, - SubKeyCell->ClassNameOffset, - NULL); + ClassCell = HvGetCell (KeyObject->RegistryHive->Hive, + SubKeyCell->ClassNameOffset); RtlCopyMemory (FullInformation->Class, - ClassCell->Data, + ClassCell, ClassSize); } } @@ -959,10 +865,10 @@ { 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; @@ -1091,9 +997,9 @@ 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 @@ -1164,10 +1070,10 @@ 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 { @@ -1201,7 +1107,7 @@ { NTSTATUS Status; PKEY_OBJECT KeyObject; - PREGISTRY_HIVE RegistryHive; + PEREGISTRY_HIVE RegistryHive; KPROCESSOR_MODE PreviousMode; PAGED_CODE(); @@ -1407,8 +1313,8 @@ 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; @@ -1543,11 +1449,10 @@ 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); } } @@ -1591,11 +1496,10 @@ 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; @@ -1636,10 +1540,10 @@ 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; @@ -1777,9 +1681,9 @@ 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 @@ -1852,10 +1756,10 @@ } 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 @@ -1896,12 +1800,11 @@ { 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; @@ -1982,8 +1885,8 @@ 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 { @@ -1992,19 +1895,19 @@ } - 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 { @@ -2014,15 +1917,12 @@ * 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); @@ -2037,18 +1937,18 @@ 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 */ @@ -2059,7 +1959,7 @@ } KeQuerySystemTime (&KeyCell->LastWriteTime); - CmiMarkBlockDirty (RegistryHive, KeyObject->KeyCellOffset); + HvMarkCellDirty (RegistryHive->Hive, KeyObject->KeyCellOffset); ExReleaseResourceLite(&CmiRegistryLock); KeLeaveCriticalRegion(); @@ -2135,7 +2035,7 @@ ValueName); KeQuerySystemTime (&KeyObject->KeyCell->LastWriteTime); - CmiMarkBlockDirty (KeyObject->RegistryHive, KeyObject->KeyCellOffset); + HvMarkCellDirty (KeyObject->RegistryHive->Hive, KeyObject->KeyCellOffset); /* Release hive lock */ ExReleaseResourceLite(&CmiRegistryLock); @@ -2348,10 +2248,10 @@ 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; @@ -2436,11 +2336,9 @@ 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 @@ -2504,7 +2402,7 @@ NtSaveKey (IN HANDLE KeyHandle, IN HANDLE FileHandle) { - PREGISTRY_HIVE TempHive; + PEREGISTRY_HIVE TempHive; PKEY_OBJECT KeyObject; NTSTATUS Status; @@ -2534,7 +2432,7 @@ 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); @@ -2662,8 +2560,8 @@ 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); @@ -2694,7 +2592,7 @@ NTSTATUS STDCALL NtUnloadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes) { - PREGISTRY_HIVE RegistryHive; + PEREGISTRY_HIVE RegistryHive; NTSTATUS Status; PAGED_CODE(); Index: ntoskrnl/cm/regfile.c =================================================================== --- ntoskrnl/cm/regfile.c (revision 19665) +++ ntoskrnl/cm/regfile.c (working copy) @@ -14,403 +14,178 @@ #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) +void * +CmpAllocate(ULONG size) { - 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(NonPagedPool, size, TAG('R','E','G',' ')); } -VOID -CmiCreateDefaultBinHeader(PHBIN BinHeader) +void * +CmpAllocatePaged(ULONG size) { - 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; + return ExAllocatePoolWithTag(PagedPool, size, TAG('R','E','G',' ')); } -VOID -CmiCreateDefaultRootKeyCell(PKEY_CELL RootKeyCell) +void +CmpFree(void *ptr) { - 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; + return ExFreePool(ptr); } -VOID -CmiVerifyBinHeader(PHBIN BinHeader) +BOOLEAN CMAPI +CmpFileRead( + PREGISTRY_HIVE RegistryHive, + ULONG FileType, + ULONG FileOffset, + PVOID Buffer, + ULONG BufferLength) { - if (CmiDoVerify) - { + PEREGISTRY_HIVE CmHive = RegistryHive->Opaque; + HANDLE HiveHandle = FileType == HV_TYPE_PRIMARY ? CmHive->HiveHandle : CmHive->LogHandle; + LARGE_INTEGER _FileOffset; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; - ASSERT(BinHeader); - - 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); - } - - //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); - } - - } + _FileOffset.QuadPart = FileOffset; + Status = ZwReadFile(HiveHandle, 0, 0, 0, &IoStatusBlock, + Buffer, BufferLength, &_FileOffset, 0); + return NT_SUCCESS(Status) ? TRUE : FALSE; } -VOID -CmiVerifyKeyCell(PKEY_CELL KeyCell) +BOOLEAN CMAPI +CmpFileWrite( + PREGISTRY_HIVE RegistryHive, + ULONG FileType, + ULONG FileOffset, + PVOID Buffer, + ULONG BufferLength) { - if (CmiDoVerify) - { + PEREGISTRY_HIVE CmHive = RegistryHive->Opaque; + HANDLE HiveHandle = FileType == HV_TYPE_PRIMARY ? CmHive->HiveHandle : CmHive->LogHandle; + LARGE_INTEGER _FileOffset; + 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 - - } + _FileOffset.QuadPart = FileOffset; + Status = ZwWriteFile(HiveHandle, 0, 0, 0, &IoStatusBlock, + Buffer, BufferLength, &_FileOffset, 0); + return NT_SUCCESS(Status) ? TRUE : FALSE; } -VOID -CmiVerifyRootKeyCell(PKEY_CELL RootKeyCell) +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; - CmiVerifyKeyCell(RootKeyCell); + EndOfFileInfo.EndOfFile.QuadPart = FileSize; + Status = ZwSetInformationFile(HiveHandle, &IoStatusBlock, + &EndOfFileInfo, + sizeof(FILE_END_OF_FILE_INFORMATION), + FileEndOfFileInformation); + if (!NT_SUCCESS(Status)) + return FALSE; - 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))); - } + FileAllocationInfo.AllocationSize.QuadPart = FileSize; + Status = ZwSetInformationFile(HiveHandle, &IoStatusBlock, + &FileAllocationInfo, + sizeof(FILE_ALLOCATION_INFORMATION), + FileAllocationInformation); + if (!NT_SUCCESS(Status)) + return FALSE; - } + return TRUE; } -VOID -CmiVerifyValueCell(PVALUE_CELL ValueCell) +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(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]; - } + Status = ZwFlushBuffersFile(HiveHandle, &IoStatusBlock); + return NT_SUCCESS(Status) ? TRUE : FALSE; } -VOID -CmiVerifyValueListCell(PVALUE_LIST_CELL ValueListCell) +static NTSTATUS +CmiCreateNewRegFile(HANDLE FileHandle) { - if (CmiDoVerify) - { + EREGISTRY_HIVE CmHive; + PREGISTRY_HIVE Hive; + NTSTATUS Status; - if (ValueListCell->CellSize == 0) + CmHive.HiveHandle = FileHandle; + Status = HvInitialize(&Hive, HV_OPERATION_CREATE_HIVE, 0, 0, + CmpFileRead, CmpFileWrite, CmpFileSetSize, + CmpFileFlush, &CmHive); + if (!NT_SUCCESS(Status)) { - DbgPrint("CellSize is %d (must not be 0)\n", - ValueListCell->CellSize); - ASSERT(ValueListCell->CellSize != 0); + return FALSE; } - } -} - - -VOID -CmiVerifyKeyObject(PKEY_OBJECT KeyObject) -{ - if (CmiDoVerify) + /* Init root key cell */ + if (!CmCreateRootNode(Hive, L"")) { - - if (KeyObject->RegistryHive == NULL) - { - DbgPrint("RegistryHive is NULL (must not be NULL)\n", - KeyObject->RegistryHive); - ASSERT(KeyObject->RegistryHive != NULL); + HvFree (Hive); + return FALSE; } - if (KeyObject->KeyCell == NULL) - { - DbgPrint("KeyCell is NULL (must not be NULL)\n", - KeyObject->KeyCell); - ASSERT(KeyObject->KeyCell != NULL); - } + Status = HvWriteHive(Hive) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; - if (KeyObject->ParentKey == NULL) - { - DbgPrint("ParentKey is NULL (must not be NULL)\n", - KeyObject->ParentKey); - ASSERT(KeyObject->ParentKey != NULL); - } + HvFree (Hive); - } + return(Status); } -VOID -CmiVerifyHiveHeader(PHIVE_HEADER Header) -{ - if (CmiDoVerify) - { +#ifdef HIVE_CHECK - 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) +static ULONG +CmiCalcChecksum(PULONG Buffer) { - if (CmiDoVerify) - { + ULONG Sum = 0; + ULONG i; - CmiVerifyHiveHeader(RegistryHive->HiveHeader); + 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 -CmiCreateNewRegFile(HANDLE FileHandle) +CmiCheckAndFixHive(PEREGISTRY_HIVE RegistryHive) { - IO_STATUS_BLOCK IoStatusBlock; - PCELL_HEADER FreeCell; - PHIVE_HEADER HiveHeader; - PKEY_CELL RootKeyCell; - 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); - - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - Status = ZwFlushBuffersFile(FileHandle, - &IoStatusBlock); - - return(Status); -} - - -#ifdef HIVE_CHECK -static NTSTATUS -CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive) -{ OBJECT_ATTRIBUTES ObjectAttributes; FILE_STANDARD_INFORMATION fsi; IO_STATUS_BLOCK IoStatusBlock; @@ -514,7 +289,7 @@ 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 +303,7 @@ { /* Allocate hive header */ LogHeader = ExAllocatePool(PagedPool, - sizeof(HIVE_HEADER)); + HV_LOG_HEADER_SIZE); if (LogHeader == NULL) { DPRINT("ExAllocatePool() failed\n"); @@ -544,7 +319,7 @@ 0, &IoStatusBlock, LogHeader, - sizeof(HIVE_HEADER), + HV_LOG_HEADER_SIZE, &FileOffset, 0); if (!NT_SUCCESS(Status)) @@ -555,10 +330,10 @@ /* 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 +344,8 @@ 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 +370,9 @@ 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 +404,7 @@ /* 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,187 +434,8 @@ } #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 - { - FreeOffset -= FreeBlock->CellSize; - } - } - - 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; @@ -974,37 +568,13 @@ } 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, + CmpFileRead, CmpFileWrite, CmpFileSetSize, + CmpFileFlush, RegistryHive); if (!NT_SUCCESS(Status)) { - ExFreePool(RegistryHive->BlockList); + DPRINT1("Failed to open hive\n"); MmUnmapViewOfSection(PsGetCurrentProcess(), ViewBase); ObDereferenceObject(SectionObject); @@ -1014,6 +584,8 @@ return Status; } + CmPrepareHive(RegistryHive->Hive); + /* Unmap and dereference the hive section */ MmUnmapViewOfSection(PsGetCurrentProcess(), ViewBase); @@ -1022,29 +594,6 @@ /* 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); @@ -1053,48 +602,40 @@ 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, + CmpFileRead, CmpFileWrite, CmpFileSetSize, + CmpFileFlush, Hive); + if (!NT_SUCCESS(Status)) { ExFreePool (Hive); - return STATUS_INSUFFICIENT_RESOURCES; + return Status; } - 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) + if (!CmCreateRootNode (Hive->Hive, L"")) { - ExFreePool(Hive->HiveHeader); - ExFreePool(Hive); + HvFree (Hive->Hive); + 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(); @@ -1117,123 +658,10 @@ 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(PBLOCK_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); } @@ -1242,7 +670,7 @@ IN PUNICODE_STRING FileName, IN ULONG Flags) { - PREGISTRY_HIVE Hive; + PEREGISTRY_HIVE Hive; NTSTATUS Status; DPRINT ("CmiLoadHive(Filename %wZ)\n", FileName); @@ -1251,36 +679,24 @@ 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; } @@ -1306,11 +722,8 @@ 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); @@ -1318,705 +731,119 @@ 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]; - - 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"); - - 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); - } - RtlZeroMemory (Buffer, - BufferSize); - - /* Open log file for writing */ InitializeObjectAttributes(&ObjectAttributes, - &RegistryHive->LogFileName, + &RegistryHive->HiveFileName, OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = ZwCreateFile(&FileHandle, + Status = ZwCreateFile(&RegistryHive->HiveHandle, FILE_ALL_ACCESS, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, - FILE_SUPERSEDE, - 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 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); -} - - -static NTSTATUS -CmiFinishLogUpdate(PREGISTRY_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, + Status = ZwCreateFile(&RegistryHive->LogHandle, FILE_ALL_ACCESS, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, - FILE_OPEN, + FILE_SUPERSEDE, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if (!NT_SUCCESS(Status)) { - DPRINT("ZwCreateFile() failed (Status %lx)\n", Status); + ZwClose(RegistryHive->HiveHandle); 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); + return STATUS_SUCCESS; } -static NTSTATUS -CmiStartHiveUpdate(PREGISTRY_HIVE RegistryHive) +VOID +CmCloseHiveFiles(PEREGISTRY_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); + ZwClose(RegistryHive->HiveHandle); + ZwClose(RegistryHive->LogHandle); } -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); -} - - 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; + SubKeyCount = (KeyCell == NULL) ? 0 : + KeyCell->NumberOfSubKeys[HvStable] + + KeyCell->NumberOfSubKeys[HvVolatile]; - /* 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++; - } - } - return SubKeyCount; } @@ -2025,12 +852,12 @@ 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); @@ -2038,79 +865,29 @@ 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; - } - } - } + for (i = 0; i < HashBlock->HashTableSize; i++) + { + if (HashBlock->Table[i].KeyOffset != 0) + { + 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 ("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; - } - } - } - DPRINT ("MaxName %lu\n", MaxName); return MaxName; @@ -2121,11 +898,11 @@ 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); @@ -2133,55 +910,28 @@ 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 < HashBlock->HashTableSize; i++) + { + if (HashBlock->Table[i].KeyOffset != 0) + { + 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; @@ -2189,7 +939,7 @@ ULONG -CmiGetMaxValueNameLength(PREGISTRY_HIVE RegistryHive, +CmiGetMaxValueNameLength(PEREGISTRY_HIVE RegistryHive, PKEY_CELL KeyCell) { PVALUE_LIST_CELL ValueListCell; @@ -2200,21 +950,19 @@ 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"); @@ -2239,7 +987,7 @@ ULONG -CmiGetMaxValueDataLength(PREGISTRY_HIVE RegistryHive, +CmiGetMaxValueDataLength(PEREGISTRY_HIVE RegistryHive, PKEY_CELL KeyCell) { PVALUE_LIST_CELL ValueListCell; @@ -2249,19 +997,19 @@ 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; } @@ -2272,16 +1020,17 @@ 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); @@ -2292,78 +1041,65 @@ *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 = CmiGetCell (RegistryHive, KeyCell->HashTableOffset, NULL); - if (HashBlock == NULL) - { - DPRINT("CmiGetBlock() failed\n"); - return STATUS_UNSUCCESSFUL; - } + /* Get hash table */ + HashBlock = HvGetCell (RegistryHive->Hive, KeyCell->HashTableOffset[Storage]); + ASSERT(HashBlock->Id == REG_HASH_TABLE_CELL_ID); - 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; - } + for (i = 0; (i < KeyCell->NumberOfSubKeys[Storage]) && (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 = HvGetCell (RegistryHive->Hive, + HashBlock->Table[i].KeyOffset); - 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 (CmiCompareKeyNamesI(KeyName, CurSubKeyCell)) + { + *SubKeyCell = CurSubKeyCell; + *BlockOffset = HashBlock->Table[i].KeyOffset; + return STATUS_SUCCESS; + } + } + } + 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 = HvGetCell (RegistryHive->Hive, + HashBlock->Table[i].KeyOffset); - if (CmiCompareKeyNames(KeyName, CurSubKeyCell)) - { - *SubKeyCell = CurSubKeyCell; - *BlockOffset = HashBlock->Table[i].KeyOffset; - break; - } - } - } + if (CmiCompareKeyNames(KeyName, CurSubKeyCell)) + { + *SubKeyCell = CurSubKeyCell; + *BlockOffset = HashBlock->Table[i].KeyOffset; + return STATUS_SUCCESS; + } + } + } + } } - 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, @@ -2372,15 +1108,16 @@ 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; @@ -2420,27 +1157,35 @@ 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; @@ -2461,14 +1206,15 @@ 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); } @@ -2482,18 +1228,13 @@ 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))) + if (ParentKeyCell->HashTableOffset[Storage] == HCELL_NULL) { - return(Status); - } - - if (ParentKeyCell->HashTableOffset == (ULONG_PTR) -1) - { 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); @@ -2501,26 +1242,22 @@ } 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; @@ -2531,193 +1268,126 @@ 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->HashTableOffset[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"); @@ -2726,11 +1396,11 @@ 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; @@ -2738,36 +1408,24 @@ *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))) @@ -2785,7 +1443,7 @@ NTSTATUS -CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive, +CmiGetValueFromKeyByIndex(IN PEREGISTRY_HIVE RegistryHive, IN PKEY_CELL KeyCell, IN ULONG Index, OUT PVALUE_CELL *ValueCell) @@ -2795,7 +1453,7 @@ *ValueCell = NULL; - if (KeyCell->ValueListOffset == (BLOCK_OFFSET)-1) + if (KeyCell->ValueListOffset == (HCELL_INDEX)-1) { return STATUS_NO_MORE_ENTRIES; } @@ -2806,25 +1464,12 @@ } - 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 = HvGetCell (RegistryHive->Hive, ValueListCell->ValueOffset[Index]); - CurValueCell = CmiGetCell (RegistryHive, - ValueListCell->ValueOffset[Index], - NULL); - if (CurValueCell == NULL) - { - DPRINT("CmiGetBlock() failed\n"); - return STATUS_UNSUCCESSFUL; - } - *ValueCell = CurValueCell; return STATUS_SUCCESS; @@ -2832,81 +1477,72 @@ 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; @@ -2915,9 +1551,9 @@ 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; @@ -2927,9 +1563,9 @@ 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; @@ -2937,23 +1573,13 @@ 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, @@ -2973,7 +1599,7 @@ { 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; @@ -2982,19 +1608,17 @@ 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; } @@ -3007,10 +1631,11 @@ 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; @@ -3020,18 +1645,16 @@ *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; @@ -3042,36 +1665,26 @@ 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; + KeyOffset = HashBlock->Table[Index].KeyOffset; + KeyCell = HvGetCell (RegistryHive->Hive, KeyOffset); - if (IsPointerHive(RegistryHive)) - { - KeyCell = (PKEY_CELL) HashBlock->Table[Index].KeyOffset; - } - else - { - KeyOffset = HashBlock->Table[Index].KeyOffset; - KeyCell = CmiGetCell (RegistryHive, KeyOffset, NULL); - } - return KeyCell; } NTSTATUS -CmiAddKeyToHashTable(PREGISTRY_HIVE RegistryHive, +CmiAddKeyToHashTable(PEREGISTRY_HIVE RegistryHive, PHASH_TABLE_CELL HashCell, - BLOCK_OFFSET HashCellOffset, + HCELL_INDEX HashCellOffset, PKEY_CELL NewKeyCell, - BLOCK_OFFSET NKBOffset) + HCELL_INDEX NKBOffset) { ULONG i; @@ -3087,7 +1700,7 @@ NewKeyCell->Name, min(NewKeyCell->NameSize, sizeof(ULONG))); } - CmiMarkBlockDirty(RegistryHive, HashCellOffset); + HvMarkCellDirty(RegistryHive->Hive, HashCellOffset); return STATUS_SUCCESS; } } @@ -3097,9 +1710,9 @@ NTSTATUS -CmiRemoveKeyFromHashTable(PREGISTRY_HIVE RegistryHive, +CmiRemoveKeyFromHashTable(PEREGISTRY_HIVE RegistryHive, PHASH_TABLE_CELL HashBlock, - BLOCK_OFFSET NKBOffset) + HCELL_INDEX NKBOffset) { ULONG i; @@ -3118,10 +1731,11 @@ 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; @@ -3136,17 +1750,15 @@ 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) @@ -3166,7 +1778,7 @@ } NewValueCell->DataType = 0; NewValueCell->DataSize = 0; - NewValueCell->DataOffset = (BLOCK_OFFSET)-1; + NewValueCell->DataOffset = (HCELL_INDEX)-1; *ValueCell = NewValueCell; } @@ -3175,14 +1787,10 @@ 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); @@ -3190,613 +1798,19 @@ /* 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); + HvFreeCell (RegistryHive->Hive, 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); - 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) @@ -3977,17 +1991,17 @@ 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; @@ -3997,47 +2011,38 @@ { /* Allocate and copy key cell */ NewKeyCellSize = sizeof(KEY_CELL) + SrcKeyCell->NameSize; - Status = CmiAllocateCell (DstHive, - NewKeyCellSize, - (PVOID) &NewKeyCell, - &NewKeyCellOffset); - if (!NT_SUCCESS(Status)) + NewKeyCellOffset = HvAllocateCell (DstHive->Hive, NewKeyCellSize, HvStable); + if (NewKeyCellOffset == HCELL_NULL) { - DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status); - return Status; - } - if (NewKeyCell == 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); @@ -4050,19 +2055,20 @@ } /* 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 { @@ -4076,47 +2082,46 @@ 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, @@ -4125,17 +2130,15 @@ /* 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); @@ -4145,41 +2148,32 @@ } /* 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)) + NewSubKeyCellOffset = HvAllocateCell (DstHive->Hive, NewSubKeyCellSize, HvStable); + if (NewSubKeyCellOffset == HCELL_NULL) { - DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status); - return Status; - } - if (NewKeyCell == 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; @@ -4188,27 +2182,26 @@ 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, @@ -4233,72 +2226,11 @@ 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 */ Index: ntoskrnl/ntoskrnl.xml =================================================================== --- ntoskrnl/ntoskrnl.xml (revision 19665) +++ ntoskrnl/ntoskrnl.xml (working copy) @@ -9,10 +9,12 @@ include include + . csq hal kjs pseh + cmlib rtl rossym string