diff --git a/reactos/ntoskrnl/cm/cm.h b/reactos/ntoskrnl/cm/cm.h index 36431d93ddc..46b94d76089 100644 --- a/reactos/ntoskrnl/cm/cm.h +++ b/reactos/ntoskrnl/cm/cm.h @@ -1,7 +1,12 @@ - #ifndef __INCLUDE_CM_H #define __INCLUDE_CM_H +#ifdef DBG +#define CHECKED 1 +#else +#define CHECKED 0 +#endif + #define REG_ROOT_KEY_NAME L"\\Registry" #define REG_MACHINE_KEY_NAME L"\\Registry\\Machine" #define REG_HARDWARE_KEY_NAME L"\\Registry\\Machine\\HARDWARE" @@ -31,68 +36,139 @@ #define REG_DYN_STD_HANDLE_NAME "HKEY_DYN_DATA" #define MAX_REG_STD_HANDLE_NAME 19 -#define KO_MARKED_FOR_DELETE 0x00000001 - // BLOCK_OFFSET = offset in file after header block -typedef DWORD BLOCK_OFFSET; +typedef DWORD BLOCK_OFFSET; /* header for registry hive file : */ -typedef struct _HEADER_BLOCK +typedef struct _HIVE_HEADER { - ULONG BlockId; /* ="regf" */ - ULONG Version; /* file version ?*/ - ULONG VersionOld; /* file version ?*/ - FILETIME DateModified; /* please don't replace with LARGE_INTEGER !*/ - ULONG Unused3; /* registry format version ? */ - ULONG Unused4; /* registry format version ? */ - ULONG Unused5; /* registry format version ? */ - ULONG Unused6; /* registry format version ? */ - BLOCK_OFFSET RootKeyBlock; + /* Hive identifier "regf" (0x66676572) */ + ULONG BlockId; + + /* File version ? */ + ULONG Version; + + /* File version ? - same as Version */ + ULONG VersionOld; + + /* When this hive file was last modified */ + FILETIME DateModified; + + /* Registry format version ? (1?) */ + ULONG Unused3; + + /* Registry format version ? (3?) */ + ULONG Unused4; + + /* Registry format version ? (0?) */ + ULONG Unused5; + + /* Registry format version ? (1?) */ + ULONG Unused6; + + /* 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 RootKeyCell; + + /* Size of each hive block ? */ ULONG BlockSize; + + /* (1?) */ ULONG Unused7; - WCHAR FileName[64]; /* end of file name */ + + /* Name of hive file */ + WCHAR FileName[64]; + + /* ? */ ULONG Unused8[83]; + + /* Checksum of first 0x200 bytes */ ULONG Checksum; -} HEADER_BLOCK, *PHEADER_BLOCK; +} __attribute__((packed)) HIVE_HEADER, *PHIVE_HEADER; -typedef struct _HEAP_BLOCK +typedef struct _HBIN { - ULONG BlockId; /* = "hbin" */ - BLOCK_OFFSET BlockOffset; /* block offset of this heap */ - ULONG BlockSize; /* size in bytes, 4k multiple */ + /* Bin identifier "hbin" (0x6E696268) */ + ULONG BlockId; + + /* Block offset of this bin */ + BLOCK_OFFSET BlockOffset; + + /* Size in bytes, multiple of the block size (4KB) */ + ULONG BlockSize; + + /* ? */ ULONG Unused1; - FILETIME DateModified; /* please don't replace with LARGE_INTEGER !*/ + + /* When this bin was last modified */ + FILETIME DateModified; + + /* ? */ ULONG Unused2; -} HEAP_BLOCK, *PHEAP_BLOCK; +} __attribute__((packed)) HBIN, *PHBIN; -// each sub_block begin with this struct : -// in a free subblock, higher bit of SubBlockSize is set -typedef struct _FREE_SUB_BLOCK +typedef struct _CELL_HEADER { - LONG SubBlockSize;/* <0 if used, >0 if free */ -} FREE_SUB_BLOCK, *PFREE_SUB_BLOCK; + /* <0 if used, >0 if free */ + LONG CellSize; +} __attribute__((packed)) CELL_HEADER, *PCELL_HEADER; -typedef struct _KEY_BLOCK +typedef struct _KEY_CELL { - LONG SubBlockSize; - USHORT SubBlockId; - USHORT Type; - FILETIME LastWriteTime; /* please don't replace with LARGE_INTEGER !*/ + /* Size of this cell */ + LONG CellSize; + + /* Key cell identifier "kn" (0x6b6e) */ + USHORT Id; + + /* ? */ + USHORT Type; + + /* Time of last flush */ + FILETIME 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 ValuesOffset; + + /* 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; - USHORT ClassSize; /* size of ClassName in bytes */ - UCHAR Name[0]; /* warning : not zero terminated */ -} KEY_BLOCK, *PKEY_BLOCK; + + /* Size of class name in bytes */ + USHORT ClassSize; + + /* Name of key (not zero terminated) */ + UCHAR Name[0]; +} __attribute__((packed)) KEY_CELL, *PKEY_CELL; // hash record : // HashValue=four letters of value's name @@ -100,88 +176,158 @@ typedef struct _HASH_RECORD { BLOCK_OFFSET KeyOffset; ULONG HashValue; -} HASH_RECORD, *PHASH_RECORD; +} __attribute__((packed)) HASH_RECORD, *PHASH_RECORD; -typedef struct _HASH_TABLE_BLOCK +typedef struct _HASH_TABLE_CELL { - LONG SubBlockSize; - USHORT SubBlockId; - USHORT HashTableSize; + LONG CellSize; + USHORT Id; + USHORT HashTableSize; HASH_RECORD Table[0]; -} HASH_TABLE_BLOCK, *PHASH_TABLE_BLOCK; +} __attribute__((packed)) HASH_TABLE_CELL, *PHASH_TABLE_CELL; -typedef struct _VALUE_LIST_BLOCK +typedef struct _VALUE_LIST_CELL { - LONG SubBlockSize; + LONG CellSize; BLOCK_OFFSET Values[0]; -} VALUE_LIST_BLOCK, *PVALUE_LIST_BLOCK; +} __attribute__((packed)) VALUE_LIST_CELL, *PVALUE_LIST_CELL; -typedef struct _VALUE_BLOCK +typedef struct _VALUE_CELL { - LONG SubBlockSize; - USHORT SubBlockId; // "kv" + LONG CellSize; + USHORT Id; // "kv" USHORT NameSize; // length of Name - LONG DataSize; // length of datas in the subblock pointed by DataOffset + LONG 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_BLOCK, *PVALUE_BLOCK; +} __attribute__((packed)) VALUE_CELL, *PVALUE_CELL; -typedef struct _DATA_BLOCK +typedef struct _DATA_CELL { - LONG SubBlockSize; + LONG CellSize; UCHAR Data[0]; -} DATA_BLOCK, *PDATA_BLOCK; +} __attribute__((packed)) DATA_CELL, *PDATA_CELL; -typedef struct _REGISTRY_FILE +typedef struct _REGISTRY_HIVE { - PWSTR Filename; + ULONG Flags; + UNICODE_STRING Filename; ULONG FileSize; - PFILE_OBJECT FileObject; - PHEADER_BLOCK HeaderBlock; -// ULONG NumberOfBlocks; + PFILE_OBJECT FileObject; + PVOID Bcb; + PHIVE_HEADER HiveHeader; ULONG BlockListSize; - PHEAP_BLOCK *BlockList; + PHBIN *BlockList; ULONG FreeListSize; ULONG FreeListMax; - PFREE_SUB_BLOCK *FreeList; + PCELL_HEADER *FreeList; BLOCK_OFFSET *FreeListOffset; // KSPIN_LOCK RegLock; KSEMAPHORE RegSem; - - // NTSTATUS (*Extend)(ULONG NewSize); // PVOID (*Flush)(VOID); -} REGISTRY_FILE, *PREGISTRY_FILE; +} REGISTRY_HIVE, *PREGISTRY_HIVE; -/* Type defining the Object Manager Key Object */ +/* REGISTRY_HIVE.Flags constants */ +#define HIVE_VOLATILE 0x00000001 + +#define IsVolatileHive(Hive)(Hive->Flags & HIVE_VOLATILE) +#define IsPermanentHive(Hive)(!(Hive->Flags & HIVE_VOLATILE)) + +#define IsFreeCell(Cell)(Cell->CellSize >= 0) +#define IsUsedCell(Cell)(Cell->CellSize < 0) + + +/* KEY_OBJECT.Flags */ + +/* When set, the key is sheduled for deletion, and all + atempts to access the key must not succeed */ +#define KO_MARKED_FOR_DELETE 0x00000001 + +/* Type defining the Object Manager Key Object */ typedef struct _KEY_OBJECT { - CSHORT Type; - CSHORT Size; - - ULONG Flags; - USHORT NameSize; // length of Name - UCHAR *Name; - PREGISTRY_FILE RegistryFile; + /* Fields used by the Object Manager */ + CSHORT Type; + CSHORT Size; + + /* Key flags */ + ULONG Flags; + + /* Length of Name */ + USHORT NameSize; + + /* Name of key */ + PCHAR Name; + + /* Registry hive the key belong to */ + PREGISTRY_HIVE RegistryHive; + + /* Block offset of the key cell this key belong in */ BLOCK_OFFSET BlockOffset; - PKEY_BLOCK KeyBlock; - struct _KEY_OBJECT *ParentKey; - ULONG NumberOfSubKeys; /* subkeys loaded in SubKeys */ - ULONG SizeOfSubKeys; /* space allocated in SubKeys */ - struct _KEY_OBJECT **SubKeys; /* list of subkeys loaded */ + + /* KEY_CELL this key belong in */ + PKEY_CELL KeyCell; + + /* Link to the parent KEY_OBJECT for this key */ + struct _KEY_OBJECT *ParentKey; + + /* Subkeys loaded in SubKeys */ + ULONG NumberOfSubKeys; + + /* Space allocated in SubKeys */ + ULONG SizeOfSubKeys; + + /* List of subkeys loaded */ + struct _KEY_OBJECT **SubKeys; } KEY_OBJECT, *PKEY_OBJECT; +/* Bits 31-22 (top 10 bits) of the cell index is the directory index */ +#define CmiDirectoryIndex(CellIndex)(CellIndex & 0xffc000000) +/* Bits 21-12 (middle 10 bits) of the cell index is the table index */ +#define CmiTableIndex(Cellndex)(CellIndex & 0x003ff000) +/* Bits 11-0 (bottom 12 bits) of the cell index is the byte offset */ +#define CmiByteOffset(Cellndex)(CellIndex & 0x00000fff) + +VOID +CmiVerifyBinCell(PHBIN BinCell); +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_CELL CmiVerifyBinCell +#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_CELL(x) +#define VERIFY_KEY_CELL(x) +#define VERIFY_ROOT_KEY_CELL(x) +#define VERIFY_VALUE_CELL(x) +#define VERIFY_VALUE_LIST_CELL(x) +#define VERIFY_KEY_OBJECT(x) +#define VERIFY_REGISTRY_HIVE(x) +#endif NTSTATUS STDCALL -CmiObjectParse(PVOID ParsedObject, - PVOID *NextObject, - PUNICODE_STRING FullPath, - PWSTR *Path, - POBJECT_TYPE ObjectType, - ULONG Attribute); +CmiObjectParse(IN PVOID ParsedObject, + OUT PVOID *NextObject, + IN PUNICODE_STRING FullPath, + IN OUT PWSTR *Path, + IN POBJECT_TYPE ObjectType, + IN ULONG Attribute); NTSTATUS STDCALL CmiObjectCreate(PVOID ObjectBody, @@ -192,91 +338,135 @@ CmiObjectCreate(PVOID ObjectBody, VOID STDCALL CmiObjectDelete(PVOID DeletedObject); -VOID CmiAddKeyToList(PKEY_OBJECT ParentKey,PKEY_OBJECT NewKey); -NTSTATUS CmiRemoveKeyFromList(PKEY_OBJECT NewKey); -PKEY_OBJECT CmiScanKeyList(PKEY_OBJECT Parent, - PCHAR KeyNameBuf, - ULONG Attributes); +VOID +CmiAddKeyToList(PKEY_OBJECT ParentKey, + IN PKEY_OBJECT NewKey); -PREGISTRY_FILE CmiCreateRegistry(PWSTR Filename); - -ULONG CmiGetMaxNameLength(PREGISTRY_FILE RegistryFile, - PKEY_BLOCK KeyBlock); -ULONG CmiGetMaxClassLength(PREGISTRY_FILE RegistryFile, - PKEY_BLOCK KeyBlock); -ULONG CmiGetMaxValueNameLength(PREGISTRY_FILE RegistryFile, - PKEY_BLOCK KeyBlock); -ULONG CmiGetMaxValueDataLength(PREGISTRY_FILE RegistryFile, - PKEY_BLOCK KeyBlock); - -NTSTATUS CmiScanForSubKey(IN PREGISTRY_FILE RegistryFile, - IN PKEY_BLOCK KeyBlock, - OUT PKEY_BLOCK *SubKeyBlock, - OUT BLOCK_OFFSET *BlockOffset, - IN PCHAR KeyName, - IN ACCESS_MASK DesiredAccess, - IN ULONG Attributes); -NTSTATUS CmiAddSubKey(IN PREGISTRY_FILE RegistryFile, - IN PKEY_OBJECT Parent, - OUT PKEY_OBJECT SubKey, - IN PWSTR NewSubKeyName, - IN USHORT NewSubKeyNameSize, - IN ULONG TitleIndex, - IN PUNICODE_STRING Class, - IN ULONG CreateOptions); - -NTSTATUS CmiScanKeyForValue(IN PREGISTRY_FILE RegistryFile, - IN PKEY_BLOCK KeyBlock, - IN PCHAR ValueName, - OUT PVALUE_BLOCK *ValueBlock, - OUT BLOCK_OFFSET *VBOffset); -NTSTATUS CmiGetValueFromKeyByIndex(IN PREGISTRY_FILE RegistryFile, - IN PKEY_BLOCK KeyBlock, - IN ULONG Index, - OUT PVALUE_BLOCK *ValueBlock); -NTSTATUS CmiAddValueToKey(IN PREGISTRY_FILE RegistryFile, - IN PKEY_BLOCK KeyBlock, - IN PCHAR ValueNameBuf, - OUT PVALUE_BLOCK *pValueBlock, - OUT BLOCK_OFFSET *pVBOffset); -NTSTATUS CmiDeleteValueFromKey(IN PREGISTRY_FILE RegistryFile, - IN PKEY_BLOCK KeyBlock, - IN PCHAR ValueName); - -NTSTATUS CmiAllocateHashTableBlock(IN PREGISTRY_FILE RegistryFile, - OUT PHASH_TABLE_BLOCK *HashBlock, - OUT BLOCK_OFFSET *HBOffset, - IN ULONG HashTableSize); -PKEY_BLOCK CmiGetKeyFromHashByIndex(PREGISTRY_FILE RegistryFile, - PHASH_TABLE_BLOCK HashBlock, - ULONG Index); -NTSTATUS CmiAddKeyToHashTable(PREGISTRY_FILE RegistryFile, - PHASH_TABLE_BLOCK HashBlock, - PKEY_BLOCK NewKeyBlock, - BLOCK_OFFSET NKBOffset); - -NTSTATUS CmiAllocateValueBlock(IN PREGISTRY_FILE RegistryFile, - OUT PVALUE_BLOCK *ValueBlock, - OUT BLOCK_OFFSET *VBOffset, - IN PCHAR ValueNameBuf); -NTSTATUS CmiDestroyValueBlock(PREGISTRY_FILE RegistryFile, - PVALUE_BLOCK ValueBlock, BLOCK_OFFSET VBOffset); - -NTSTATUS CmiAllocateBlock(PREGISTRY_FILE RegistryFile, - PVOID *Block, - LONG BlockSize, - BLOCK_OFFSET * pBlockOffset); -NTSTATUS CmiDestroyBlock(PREGISTRY_FILE RegistryFile, - PVOID Block,BLOCK_OFFSET Offset); -PVOID CmiGetBlock(PREGISTRY_FILE RegistryFile, - BLOCK_OFFSET BlockOffset, - OUT PHEAP_BLOCK * ppHeap); -VOID CmiLockBlock(PREGISTRY_FILE RegistryFile, - PVOID Block); -VOID CmiReleaseBlock(PREGISTRY_FILE RegistryFile, - PVOID Block); NTSTATUS -CmiAddFree(PREGISTRY_FILE RegistryFile, - PFREE_SUB_BLOCK FreeBlock,BLOCK_OFFSET FreeOffset); +CmiRemoveKeyFromList(IN PKEY_OBJECT NewKey); + +PKEY_OBJECT CmiScanKeyList(IN PKEY_OBJECT Parent, + IN PCHAR KeyNameBuf, + IN ULONG Attributes); + +PREGISTRY_HIVE +CmiCreateRegistryHive(IN PWSTR Filename, + IN BOOLEAN CreateNew); + +ULONG CmiGetMaxNameLength(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell); + +ULONG +CmiGetMaxClassLength(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell); + +ULONG +CmiGetMaxValueNameLength(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell); + +ULONG +CmiGetMaxValueDataLength(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell); + +NTSTATUS +CmiScanForSubKey(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell, + OUT PKEY_CELL *SubKeyCell, + OUT BLOCK_OFFSET *BlockOffset, + IN PCHAR KeyName, + IN ACCESS_MASK DesiredAccess, + IN ULONG Attributes); + +NTSTATUS +CmiAddSubKey(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_OBJECT Parent, + OUT PKEY_OBJECT SubKey, + IN PWSTR NewSubKeyName, + IN USHORT NewSubKeyNameSize, + IN ULONG TitleIndex, + IN PUNICODE_STRING Class, + IN ULONG CreateOptions); + +NTSTATUS +CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell, + IN PCHAR ValueName, + OUT PVALUE_CELL *ValueCell, + OUT BLOCK_OFFSET *VBOffset); + +NTSTATUS +CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell, + IN ULONG Index, + OUT PVALUE_CELL *ValueCell); + +NTSTATUS +CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell, + IN PCHAR ValueNameBuf, + OUT PVALUE_CELL *pValueCell, + OUT BLOCK_OFFSET *pVBOffset); + +NTSTATUS +CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell, + IN PCHAR ValueName); + +NTSTATUS +CmiAllocateHashTableBlock(IN PREGISTRY_HIVE RegistryHive, + OUT PHASH_TABLE_CELL *HashBlock, + OUT BLOCK_OFFSET *HBOffset, + IN ULONG HashTableSize); + +PKEY_CELL +CmiGetKeyFromHashByIndex(PREGISTRY_HIVE RegistryHive, +PHASH_TABLE_CELL HashBlock, +ULONG Index); + +NTSTATUS +CmiAddKeyToHashTable(PREGISTRY_HIVE RegistryHive, + PHASH_TABLE_CELL HashBlock, + PKEY_CELL NewKeyCell, + BLOCK_OFFSET NKBOffset); + +NTSTATUS +CmiAllocateValueCell(IN PREGISTRY_HIVE RegistryHive, + OUT PVALUE_CELL *ValueCell, + OUT BLOCK_OFFSET *VBOffset, + IN PCHAR ValueNameBuf); + +NTSTATUS +CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive, + PVALUE_CELL ValueCell, + BLOCK_OFFSET VBOffset); + +NTSTATUS +CmiAllocateBlock(PREGISTRY_HIVE RegistryHive, + PVOID *Block, + LONG BlockSize, + BLOCK_OFFSET * pBlockOffset); + +NTSTATUS +CmiDestroyBlock(PREGISTRY_HIVE RegistryHive, + PVOID Block, + BLOCK_OFFSET Offset); + +PVOID +CmiGetBlock(PREGISTRY_HIVE RegistryHive, + BLOCK_OFFSET BlockOffset, + OUT PHBIN * ppBin); + +VOID +CmiLockBlock(PREGISTRY_HIVE RegistryHive, + PVOID Block); + +VOID +CmiReleaseBlock(PREGISTRY_HIVE RegistryHive, + PVOID Block); + +NTSTATUS +CmiAddFree(PREGISTRY_HIVE RegistryHive, + PCELL_HEADER FreeBlock, + BLOCK_OFFSET FreeOffset); #endif /*__INCLUDE_CM_H*/ diff --git a/reactos/ntoskrnl/cm/ntfunc.c b/reactos/ntoskrnl/cm/ntfunc.c index cf1c5a312eb..68668f27a83 100644 --- a/reactos/ntoskrnl/cm/ntfunc.c +++ b/reactos/ntoskrnl/cm/ntfunc.c @@ -20,307 +20,344 @@ #include "cm.h" extern POBJECT_TYPE CmiKeyType; -extern PREGISTRY_FILE CmiVolatileFile; +extern PREGISTRY_HIVE CmiVolatileHive; NTSTATUS STDCALL NtCreateKey(OUT PHANDLE KeyHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN ULONG TitleIndex, - IN PUNICODE_STRING Class, - IN ULONG CreateOptions, - OUT PULONG Disposition) + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG TitleIndex, + IN PUNICODE_STRING Class, + IN ULONG CreateOptions, + OUT PULONG Disposition) { - NTSTATUS Status; - PVOID Object; - PKEY_OBJECT key; - UNICODE_STRING RemainingPath; - PWSTR end; -// KIRQL OldIrql; + UNICODE_STRING RemainingPath; + PKEY_OBJECT KeyObject; + NTSTATUS Status; + PVOID Object; + PWSTR End; -// DPRINT("NtCreateKey (Name %wZ),KeyHandle=%x,Root=%x\n", -// ObjectAttributes->ObjectName,KeyHandle -// ,ObjectAttributes->RootDirectory); + DPRINT("NtCreateKey (Name %wZ KeyHandle %x Root %x)\n", + ObjectAttributes->ObjectName, + KeyHandle, + ObjectAttributes->RootDirectory); - /*FIXME: check for standard handle prefix and adjust objectAttributes accordingly */ + /* FIXME: check for standard handle prefix and adjust objectAttributes accordingly */ + + Status = ObFindObject(ObjectAttributes, &Object, &RemainingPath, CmiKeyType); - Status = ObFindObject(ObjectAttributes,&Object,&RemainingPath,CmiKeyType); if (!NT_SUCCESS(Status)) - { - return Status; - } -DPRINT("RP=%wZ\n",&RemainingPath); - if ((RemainingPath.Buffer == NULL) || (RemainingPath.Buffer[0] ==0)) - { - /* Fail if the key has been deleted */ - if (((PKEY_OBJECT)Object)->Flags & KO_MARKED_FOR_DELETE) - { - ObDereferenceObject(Object); - return STATUS_UNSUCCESSFUL; + { + return Status; } - if (Disposition) - *Disposition = REG_OPENED_EXISTING_KEY; - Status = ObCreateHandle(PsGetCurrentProcess(), - Object, - DesiredAccess, - FALSE, - KeyHandle); -DPRINT("Status=%x\n",Status); - ObDereferenceObject(Object); - return Status; - } - /* if RemainingPath contains \ : must return error */ - if((RemainingPath.Buffer[0])=='\\') - end = wcschr((RemainingPath.Buffer)+1, '\\'); - else - end = wcschr((RemainingPath.Buffer), '\\'); - if (end != NULL) - { - ObDereferenceObject(Object); - return STATUS_UNSUCCESSFUL; - } - /* because NtCreateKey don't create tree */ -DPRINT("NCK %S parent=%x\n",RemainingPath.Buffer,Object); + DPRINT("RemainingPath %wZ\n", &RemainingPath); + + if ((RemainingPath.Buffer == NULL) || (RemainingPath.Buffer[0] == 0)) + { + /* Fail if the key has been deleted */ + if (((PKEY_OBJECT) Object)->Flags & KO_MARKED_FOR_DELETE) + { + ObDereferenceObject(Object); + return STATUS_UNSUCCESSFUL; + } + + if (Disposition) + *Disposition = REG_OPENED_EXISTING_KEY; + + Status = ObCreateHandle(PsGetCurrentProcess(), + Object, + DesiredAccess, + FALSE, + KeyHandle); + + DPRINT("Status %x\n", Status); + ObDereferenceObject(Object); + return Status; + } + + /* If RemainingPath contains \ we must return error + because NtCreateKey don't create trees */ + if (RemainingPath.Buffer[0] == '\\') + End = wcschr(RemainingPath.Buffer + 1, '\\'); + else + End = wcschr(RemainingPath.Buffer, '\\'); + + if (End != NULL) + { + ObDereferenceObject(Object); + return STATUS_UNSUCCESSFUL; + } + + DPRINT("RemainingPath %S ParentObject %x\n", RemainingPath.Buffer, Object); + Status = ObCreateObject(KeyHandle, - DesiredAccess, - NULL, - CmiKeyType, - (PVOID*)&key); + DesiredAccess, + NULL, + CmiKeyType, + (PVOID*) &KeyObject); if (!NT_SUCCESS(Status)) - return(Status); - key->ParentKey = Object; -// if ( (key->ParentKey ==NULL)) -// key->ParentKey = ObjectAttributes->RootDirectory; + return(Status); + + KeyObject->ParentKey = Object; + if (CreateOptions & REG_OPTION_VOLATILE) - key->RegistryFile=CmiVolatileFile; + KeyObject->RegistryHive = CmiVolatileHive; else - key->RegistryFile=key->ParentKey->RegistryFile; - key->Flags = 0; - key->NumberOfSubKeys = 0; - key->SizeOfSubKeys = 0; - key->SubKeys = NULL; -// KeAcquireSpinLock(&key->RegistryFile->RegLock, &OldIrql); + KeyObject->RegistryHive = KeyObject->ParentKey->RegistryHive; + + KeyObject->Flags = 0; + KeyObject->NumberOfSubKeys = 0; + KeyObject->SizeOfSubKeys = 0; + KeyObject->SubKeys = NULL; +// KeAcquireSpinLock(&Key->RegistryHive->RegLock, &OldIrql); /* add key to subkeys of parent if needed */ - Status = CmiAddSubKey(key->RegistryFile, - key->ParentKey, - key, - RemainingPath.Buffer, - RemainingPath.Length, - TitleIndex, - Class, - CreateOptions); - key->Name = key->KeyBlock->Name; - key->NameSize = key->KeyBlock->NameSize; - if (key->RegistryFile == key->ParentKey->RegistryFile) - { - key->KeyBlock->ParentKeyOffset = key->ParentKey->BlockOffset; - key->KeyBlock->SecurityKeyOffset = key->ParentKey->KeyBlock->SecurityKeyOffset; - } - else - { - key->KeyBlock->ParentKeyOffset = -1; - key->KeyBlock->SecurityKeyOffset = -1; - /* this key must rest in memory unless it is deleted */ - /* , or file is unloaded*/ - ObReferenceObjectByPointer(key, - STANDARD_RIGHTS_REQUIRED, - NULL, - UserMode); - } - CmiAddKeyToList(key->ParentKey,key); -// KeReleaseSpinLock(&key->RegistryFile->RegLock, OldIrql); - ObDereferenceObject(key); - ObDereferenceObject(Object); - if (Disposition) *Disposition = REG_CREATED_NEW_KEY; + Status = CmiAddSubKey(KeyObject->RegistryHive, + KeyObject->ParentKey, + KeyObject, + RemainingPath.Buffer, + RemainingPath.Length, + TitleIndex, + Class, + CreateOptions); if (!NT_SUCCESS(Status)) - { - return Status; - } + { + ObDereferenceObject(KeyObject); + ObDereferenceObject(Object); + return STATUS_UNSUCCESSFUL; + } - return STATUS_SUCCESS; + KeyObject->Name = KeyObject->KeyCell->Name; + KeyObject->NameSize = KeyObject->KeyCell->NameSize; + + if (KeyObject->RegistryHive == KeyObject->ParentKey->RegistryHive) + { + KeyObject->KeyCell->ParentKeyOffset = KeyObject->ParentKey->BlockOffset; + KeyObject->KeyCell->SecurityKeyOffset = KeyObject->ParentKey->KeyCell->SecurityKeyOffset; + } + else + { + KeyObject->KeyCell->ParentKeyOffset = -1; + KeyObject->KeyCell->SecurityKeyOffset = -1; + /* This key must rest in memory unless it is deleted + or file is unloaded */ + ObReferenceObjectByPointer(KeyObject, + STANDARD_RIGHTS_REQUIRED, + NULL, + UserMode); + } + + CmiAddKeyToList(KeyObject->ParentKey, KeyObject); +// KeReleaseSpinLock(&KeyObject->RegistryHive->RegLock, OldIrql); + + ObDereferenceObject(KeyObject); + ObDereferenceObject(Object); + + if (Disposition) + *Disposition = REG_CREATED_NEW_KEY; + + VERIFY_KEY_OBJECT(KeyObject); + + return Status; } NTSTATUS STDCALL NtDeleteKey(IN HANDLE KeyHandle) { - NTSTATUS Status; - PKEY_OBJECT KeyObject; - - /* Verify that the handle is valid and is a registry key */ + PKEY_OBJECT KeyObject; + NTSTATUS Status; + + DPRINT("KeyHandle %x\n", KeyHandle); + + /* Verify that the handle is valid and is a registry key */ Status = ObReferenceObjectByHandle(KeyHandle, - KEY_WRITE, - CmiKeyType, - UserMode, - (PVOID *)&KeyObject, - NULL); + KEY_WRITE, + CmiKeyType, + UserMode, + (PVOID *) &KeyObject, + NULL); + if (!NT_SUCCESS(Status)) { - return Status; + return Status; } - + + VERIFY_KEY_OBJECT(KeyObject); + /* Set the marked for delete bit in the key object */ KeyObject->Flags |= KO_MARKED_FOR_DELETE; - - /* Dereference the object */ + + /* Dereference the object */ ObDereferenceObject(KeyObject); - if(KeyObject->RegistryFile != KeyObject->ParentKey->RegistryFile) + if(KeyObject->RegistryHive != KeyObject->ParentKey->RegistryHive) ObDereferenceObject(KeyObject); - /* close the handle */ - ObDeleteHandle(PsGetCurrentProcess(),KeyHandle); + /* Close the handle */ + ObDeleteHandle(PsGetCurrentProcess(), KeyHandle); /* FIXME: I think that ObDeleteHandle should dereference the object */ ObDereferenceObject(KeyObject); - - return STATUS_SUCCESS; + return STATUS_SUCCESS; } -NTSTATUS -STDCALL -NtEnumerateKey ( +NTSTATUS STDCALL +NtEnumerateKey( IN HANDLE KeyHandle, - IN ULONG Index, + IN ULONG Index, IN KEY_INFORMATION_CLASS KeyInformationClass, - OUT PVOID KeyInformation, - IN ULONG Length, + OUT PVOID KeyInformation, + IN ULONG Length, OUT PULONG ResultLength ) { NTSTATUS Status; PKEY_OBJECT KeyObject; - PREGISTRY_FILE RegistryFile; - PKEY_BLOCK KeyBlock, SubKeyBlock; - PHASH_TABLE_BLOCK HashTableBlock; + PREGISTRY_HIVE RegistryHive; + PKEY_CELL KeyCell, SubKeyCell; + PHASH_TABLE_CELL HashTableBlock; PKEY_BASIC_INFORMATION BasicInformation; PKEY_NODE_INFORMATION NodeInformation; PKEY_FULL_INFORMATION FullInformation; - PDATA_BLOCK pClassData; + PDATA_CELL pClassData; + + DPRINT("KH %x I %d KIC %x KI %x L %d RL %x\n", + KeyHandle, + Index, + KeyInformationClass, + KeyInformation, + Length, + ResultLength); - /* Verify that the handle is valid and is a registry key */ + /* Verify that the handle is valid and is a registry key */ Status = ObReferenceObjectByHandle(KeyHandle, - KEY_ENUMERATE_SUB_KEYS, - CmiKeyType, - UserMode, - (PVOID *)&KeyObject, - NULL); + KEY_ENUMERATE_SUB_KEYS, + CmiKeyType, + UserMode, + (PVOID *) &KeyObject, + NULL); if (!NT_SUCCESS(Status)) { DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status); - return Status; + return Status; } - /* Get pointer to KeyBlock */ - KeyBlock = KeyObject->KeyBlock; - RegistryFile = KeyObject->RegistryFile; + VERIFY_KEY_OBJECT(KeyObject); + + /* Get pointer to KeyCell */ + KeyCell = KeyObject->KeyCell; + RegistryHive = KeyObject->RegistryHive; - /* Get pointer to SubKey */ - if(Index >= KeyBlock->NumberOfSubKeys) - { - if (RegistryFile == CmiVolatileFile) - { - ObDereferenceObject (KeyObject); - DPRINT("No more volatile entries\n"); - return STATUS_NO_MORE_ENTRIES; - } - else - { - int i; - PKEY_OBJECT CurKey=NULL; - /* search volatile keys */ - for (i=0; i < KeyObject->NumberOfSubKeys; i++) - { - CurKey=KeyObject->SubKeys[i]; - if (CurKey->RegistryFile == CmiVolatileFile) - { - if ( Index-- == KeyObject->NumberOfSubKeys) break; - } - } - if(Index >= KeyBlock->NumberOfSubKeys) - { - ObDereferenceObject (KeyObject); - DPRINT("No more non-volatile entries\n"); - return STATUS_NO_MORE_ENTRIES; - } - SubKeyBlock = CurKey->KeyBlock; - } - } + /* Get pointer to SubKey */ + if (Index >= KeyCell->NumberOfSubKeys) + { + if (RegistryHive == CmiVolatileHive) + { + ObDereferenceObject (KeyObject); + DPRINT("No more volatile entries\n"); + return STATUS_NO_MORE_ENTRIES; + } + else + { + ULONG i; + PKEY_OBJECT CurKey = NULL; + + /* Search volatile keys */ + for (i = 0; i < KeyObject->NumberOfSubKeys; i++) + { + CurKey = KeyObject->SubKeys[i]; + if (CurKey->RegistryHive == CmiVolatileHive) + { + if (Index-- == KeyObject->NumberOfSubKeys) + break; + } + } + if(Index >= KeyCell->NumberOfSubKeys) + { + ObDereferenceObject (KeyObject); + DPRINT("No more non-volatile entries\n"); + return STATUS_NO_MORE_ENTRIES; + } + SubKeyCell = CurKey->KeyCell; + } + } else - { - HashTableBlock = CmiGetBlock(RegistryFile, KeyBlock->HashTableOffset,NULL); - SubKeyBlock = CmiGetKeyFromHashByIndex(RegistryFile, - HashTableBlock, - Index); - } - if (SubKeyBlock == NULL) - { - ObDereferenceObject (KeyObject); - DPRINT("No more entries\n"); - return STATUS_NO_MORE_ENTRIES; - } + { + HashTableBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL); + SubKeyCell = CmiGetKeyFromHashByIndex(RegistryHive, + HashTableBlock, + Index); + } + + if (SubKeyCell == NULL) + { + ObDereferenceObject (KeyObject); + DPRINT("No more entries\n"); + return STATUS_NO_MORE_ENTRIES; + } Status = STATUS_SUCCESS; switch (KeyInformationClass) { case KeyBasicInformation: - /* Check size of buffer */ + /* Check size of buffer */ *ResultLength = sizeof(KEY_BASIC_INFORMATION) + - (SubKeyBlock->NameSize ) * sizeof(WCHAR); + (SubKeyCell->NameSize ) * sizeof(WCHAR); if (Length < *ResultLength) { Status = STATUS_BUFFER_OVERFLOW; } else { - /* Fill buffer with requested info */ + /* Fill buffer with requested info */ BasicInformation = (PKEY_BASIC_INFORMATION) KeyInformation; - BasicInformation->LastWriteTime.u.LowPart = SubKeyBlock->LastWriteTime.dwLowDateTime; - BasicInformation->LastWriteTime.u.HighPart = SubKeyBlock->LastWriteTime.dwHighDateTime; + BasicInformation->LastWriteTime.u.LowPart = SubKeyCell->LastWriteTime.dwLowDateTime; + BasicInformation->LastWriteTime.u.HighPart = SubKeyCell->LastWriteTime.dwHighDateTime; BasicInformation->TitleIndex = Index; - BasicInformation->NameLength = (SubKeyBlock->NameSize ) * sizeof(WCHAR); + BasicInformation->NameLength = SubKeyCell->NameSize * sizeof(WCHAR); mbstowcs(BasicInformation->Name, - SubKeyBlock->Name, - SubKeyBlock->NameSize*2); -// BasicInformation->Name[SubKeyBlock->NameSize] = 0; + SubKeyCell->Name, + SubKeyCell->NameSize * 2); +// BasicInformation->Name[SubKeyCell->NameSize] = 0; } break; case KeyNodeInformation: - /* Check size of buffer */ + /* Check size of buffer */ *ResultLength = sizeof(KEY_NODE_INFORMATION) + - (SubKeyBlock->NameSize ) * sizeof(WCHAR) + - (SubKeyBlock->ClassSize ); + SubKeyCell->NameSize * sizeof(WCHAR) + + SubKeyCell->ClassSize; if (Length < *ResultLength) { Status = STATUS_BUFFER_OVERFLOW; } else { - /* Fill buffer with requested info */ + /* Fill buffer with requested info */ NodeInformation = (PKEY_NODE_INFORMATION) KeyInformation; - NodeInformation->LastWriteTime.u.LowPart = SubKeyBlock->LastWriteTime.dwLowDateTime; - NodeInformation->LastWriteTime.u.HighPart = SubKeyBlock->LastWriteTime.dwHighDateTime; + NodeInformation->LastWriteTime.u.LowPart = SubKeyCell->LastWriteTime.dwLowDateTime; + NodeInformation->LastWriteTime.u.HighPart = SubKeyCell->LastWriteTime.dwHighDateTime; NodeInformation->TitleIndex = Index; NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) + - SubKeyBlock->NameSize * sizeof(WCHAR); - NodeInformation->ClassLength = SubKeyBlock->ClassSize; - NodeInformation->NameLength = (SubKeyBlock->NameSize ) * sizeof(WCHAR); + SubKeyCell->NameSize * sizeof(WCHAR); + NodeInformation->ClassLength = SubKeyCell->ClassSize; + NodeInformation->NameLength = SubKeyCell->NameSize * sizeof(WCHAR); mbstowcs(NodeInformation->Name, - SubKeyBlock->Name, - SubKeyBlock->NameSize*2); -// NodeInformation->Name[SubKeyBlock->NameSize] = 0; - if (SubKeyBlock->ClassSize != 0) + SubKeyCell->Name, + SubKeyCell->NameSize * 2); +// NodeInformation->Name[SubKeyCell->NameSize] = 0; + if (SubKeyCell->ClassSize != 0) { - pClassData=CmiGetBlock(KeyObject->RegistryFile - ,SubKeyBlock->ClassNameOffset,NULL); - wcsncpy(NodeInformation->Name + SubKeyBlock->NameSize , - (PWCHAR)pClassData->Data, - SubKeyBlock->ClassSize); - CmiReleaseBlock(RegistryFile, pClassData); + pClassData=CmiGetBlock(KeyObject->RegistryHive, + SubKeyCell->ClassNameOffset, + NULL); + wcsncpy(NodeInformation->Name + SubKeyCell->NameSize , + (PWCHAR) pClassData->Data, + SubKeyCell->ClassSize); + CmiReleaseBlock(RegistryHive, pClassData); } } break; @@ -328,7 +365,7 @@ NtEnumerateKey ( case KeyFullInformation: /* check size of buffer */ *ResultLength = sizeof(KEY_FULL_INFORMATION) + - SubKeyBlock->ClassSize; + SubKeyCell->ClassSize; if (Length < *ResultLength) { Status = STATUS_BUFFER_OVERFLOW; @@ -337,35 +374,36 @@ NtEnumerateKey ( { /* fill buffer with requested info */ FullInformation = (PKEY_FULL_INFORMATION) KeyInformation; - FullInformation->LastWriteTime.u.LowPart = SubKeyBlock->LastWriteTime.dwLowDateTime; - FullInformation->LastWriteTime.u.HighPart = SubKeyBlock->LastWriteTime.dwHighDateTime; + FullInformation->LastWriteTime.u.LowPart = SubKeyCell->LastWriteTime.dwLowDateTime; + FullInformation->LastWriteTime.u.HighPart = SubKeyCell->LastWriteTime.dwHighDateTime; FullInformation->TitleIndex = Index; FullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR); - FullInformation->ClassLength = SubKeyBlock->ClassSize; - FullInformation->SubKeys = SubKeyBlock->NumberOfSubKeys; + FullInformation->ClassLength = SubKeyCell->ClassSize; + FullInformation->SubKeys = SubKeyCell->NumberOfSubKeys; FullInformation->MaxNameLen = - CmiGetMaxNameLength(RegistryFile, SubKeyBlock); + CmiGetMaxNameLength(RegistryHive, SubKeyCell); FullInformation->MaxClassLen = - CmiGetMaxClassLength(RegistryFile, SubKeyBlock); - FullInformation->Values = SubKeyBlock->NumberOfValues; + CmiGetMaxClassLength(RegistryHive, SubKeyCell); + FullInformation->Values = SubKeyCell->NumberOfValues; FullInformation->MaxValueNameLen = - CmiGetMaxValueNameLength(RegistryFile, SubKeyBlock); + CmiGetMaxValueNameLength(RegistryHive, SubKeyCell); FullInformation->MaxValueDataLen = - CmiGetMaxValueDataLength(RegistryFile, SubKeyBlock); - if (SubKeyBlock->ClassSize != 0) + CmiGetMaxValueDataLength(RegistryHive, SubKeyCell); + if (SubKeyCell->ClassSize != 0) { - pClassData=CmiGetBlock(KeyObject->RegistryFile - ,SubKeyBlock->ClassNameOffset,NULL); + pClassData = CmiGetBlock(KeyObject->RegistryHive, + SubKeyCell->ClassNameOffset, + NULL); wcsncpy(FullInformation->Class, - (PWCHAR)pClassData->Data, - SubKeyBlock->ClassSize); - CmiReleaseBlock(RegistryFile, pClassData); + (PWCHAR) pClassData->Data, + SubKeyCell->ClassSize); + CmiReleaseBlock(RegistryHive, pClassData); } } break; } - CmiReleaseBlock(RegistryFile, SubKeyBlock); + CmiReleaseBlock(RegistryHive, SubKeyCell); ObDereferenceObject (KeyObject); DPRINT("Returning status %x\n", Status); @@ -376,56 +414,67 @@ NtEnumerateKey ( NTSTATUS STDCALL NtEnumerateValueKey(IN HANDLE KeyHandle, - IN ULONG Index, - IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, - OUT PVOID KeyValueInformation, - IN ULONG Length, - OUT PULONG ResultLength) + IN ULONG Index, + IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + OUT PVOID KeyValueInformation, + IN ULONG Length, + OUT PULONG ResultLength) { NTSTATUS Status; PKEY_OBJECT KeyObject; - PREGISTRY_FILE RegistryFile; - PKEY_BLOCK KeyBlock; - PVALUE_BLOCK ValueBlock; - PDATA_BLOCK DataBlock; + PREGISTRY_HIVE RegistryHive; + PKEY_CELL KeyCell; + PVALUE_CELL ValueCell; + PDATA_CELL DataCell; PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation; PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation; PKEY_VALUE_FULL_INFORMATION ValueFullInformation; + DPRINT("KH %x I %d KVIC %x KVI %x L %d RL %x\n", + KeyHandle, + Index, + KeyValueInformationClass, + KeyValueInformation, + Length, + ResultLength); /* Verify that the handle is valid and is a registry key */ Status = ObReferenceObjectByHandle(KeyHandle, - KEY_QUERY_VALUE, - CmiKeyType, - UserMode, - (PVOID *)&KeyObject, - NULL); + KEY_QUERY_VALUE, + CmiKeyType, + UserMode, + (PVOID *) &KeyObject, + NULL); + if (!NT_SUCCESS(Status)) { - return Status; + return Status; } - /* Get pointer to KeyBlock */ - KeyBlock = KeyObject->KeyBlock; - RegistryFile = KeyObject->RegistryFile; + VERIFY_KEY_OBJECT(KeyObject); + + /* Get pointer to KeyCell */ + KeyCell = KeyObject->KeyCell; + RegistryHive = KeyObject->RegistryHive; - /* Get Value block of interest */ - Status = CmiGetValueFromKeyByIndex(RegistryFile, - KeyBlock, - Index, - &ValueBlock); + /* Get Value block of interest */ + Status = CmiGetValueFromKeyByIndex(RegistryHive, + KeyCell, + Index, + &ValueCell); + if (!NT_SUCCESS(Status)) { ObDereferenceObject(KeyObject); - return Status; + return Status; } - else if (ValueBlock != NULL) + else if (ValueCell != NULL) { switch (KeyValueInformationClass) { case KeyValueBasicInformation: *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + - (ValueBlock->NameSize + 1) * sizeof(WCHAR); + (ValueCell->NameSize + 1) * sizeof(WCHAR); if (Length < *ResultLength) { Status = STATUS_BUFFER_OVERFLOW; @@ -435,18 +484,19 @@ NtEnumerateValueKey(IN HANDLE KeyHandle, ValueBasicInformation = (PKEY_VALUE_BASIC_INFORMATION) KeyValueInformation; ValueBasicInformation->TitleIndex = 0; - ValueBasicInformation->Type = ValueBlock->DataType; + ValueBasicInformation->Type = ValueCell->DataType; ValueBasicInformation->NameLength = - (ValueBlock->NameSize + 1) * sizeof(WCHAR); - mbstowcs(ValueBasicInformation->Name, ValueBlock->Name - ,ValueBlock->NameSize*2); - ValueBasicInformation->Name[ValueBlock->NameSize]=0; + (ValueCell->NameSize + 1) * sizeof(WCHAR); + mbstowcs(ValueBasicInformation->Name, + ValueCell->Name, + ValueCell->NameSize * 2); + ValueBasicInformation->Name[ValueCell->NameSize] = 0; } break; case KeyValuePartialInformation: *ResultLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + - (ValueBlock->DataSize & LONG_MAX); + (ValueCell->DataSize & LONG_MAX); if (Length < *ResultLength) { Status = STATUS_BUFFER_OVERFLOW; @@ -456,29 +506,29 @@ NtEnumerateValueKey(IN HANDLE KeyHandle, ValuePartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION) KeyValueInformation; ValuePartialInformation->TitleIndex = 0; - ValuePartialInformation->Type = ValueBlock->DataType; - ValuePartialInformation->DataLength = ValueBlock->DataSize & LONG_MAX; - if(ValueBlock->DataSize >0) + ValuePartialInformation->Type = ValueCell->DataType; + ValuePartialInformation->DataLength = ValueCell->DataSize & LONG_MAX; + if(ValueCell->DataSize >0) { - DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,NULL); + DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL); RtlCopyMemory(ValuePartialInformation->Data, - DataBlock->Data, - ValueBlock->DataSize & LONG_MAX); - CmiReleaseBlock(RegistryFile, DataBlock); + DataCell->Data, + ValueCell->DataSize & LONG_MAX); + CmiReleaseBlock(RegistryHive, DataCell); } else { RtlCopyMemory(ValuePartialInformation->Data, - &ValueBlock->DataOffset, - ValueBlock->DataSize & LONG_MAX); + &ValueCell->DataOffset, + ValueCell->DataSize & LONG_MAX); } - DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,NULL); + DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL); } break; case KeyValueFullInformation: *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) + - (ValueBlock->NameSize ) * sizeof(WCHAR) + (ValueBlock->DataSize & LONG_MAX); + ValueCell->NameSize * sizeof(WCHAR) + (ValueCell->DataSize & LONG_MAX); if (Length < *ResultLength) { Status = STATUS_BUFFER_OVERFLOW; @@ -488,34 +538,35 @@ NtEnumerateValueKey(IN HANDLE KeyHandle, ValueFullInformation = (PKEY_VALUE_FULL_INFORMATION) KeyValueInformation; ValueFullInformation->TitleIndex = 0; - ValueFullInformation->Type = ValueBlock->DataType; + ValueFullInformation->Type = ValueCell->DataType; ValueFullInformation->DataOffset = - (DWORD)ValueFullInformation->Name - (DWORD)ValueFullInformation - + (ValueBlock->NameSize + 1) * sizeof(WCHAR); + (DWORD)ValueFullInformation->Name - (DWORD) ValueFullInformation + + (ValueCell->NameSize + 1) * sizeof(WCHAR); ValueFullInformation->DataOffset = - (ValueFullInformation->DataOffset +3) &0xfffffffc; - ValueFullInformation->DataLength = ValueBlock->DataSize & LONG_MAX; + (ValueFullInformation->DataOffset + 3) & 0xfffffffc; + ValueFullInformation->DataLength = ValueCell->DataSize & LONG_MAX; ValueFullInformation->NameLength = - (ValueBlock->NameSize + 1) * sizeof(WCHAR); - mbstowcs(ValueFullInformation->Name, ValueBlock->Name - ,ValueBlock->NameSize*2); - ValueFullInformation->Name[ValueBlock->NameSize]=0; - if(ValueBlock->DataSize >0) - { - DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,NULL); - RtlCopyMemory((char *)(ValueFullInformation) - + ValueFullInformation->DataOffset, - DataBlock->Data, - ValueBlock->DataSize & LONG_MAX); - CmiReleaseBlock(RegistryFile, DataBlock); - } + (ValueCell->NameSize + 1) * sizeof(WCHAR); + mbstowcs(ValueFullInformation->Name, + ValueCell->Name, + ValueCell->NameSize * 2); + ValueFullInformation->Name[ValueCell->NameSize] = 0; + if (ValueCell->DataSize > 0) + { + DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL); + RtlCopyMemory((PCHAR) ValueFullInformation + + ValueFullInformation->DataOffset, + DataCell->Data, + ValueCell->DataSize & LONG_MAX); + CmiReleaseBlock(RegistryHive, DataCell); + } else - { - RtlCopyMemory((char *)(ValueFullInformation) - + ValueFullInformation->DataOffset, - &ValueBlock->DataOffset, - ValueBlock->DataSize & LONG_MAX); - } + { + RtlCopyMemory((PCHAR) ValueFullInformation + + ValueFullInformation->DataOffset, + &ValueCell->DataOffset, + ValueCell->DataSize & LONG_MAX); + } } break; } @@ -526,221 +577,341 @@ NtEnumerateValueKey(IN HANDLE KeyHandle, } ObDereferenceObject(KeyObject); - return Status; + return Status; } NTSTATUS STDCALL NtFlushKey(IN HANDLE KeyHandle) { - NTSTATUS Status; - PKEY_OBJECT KeyObject; - PREGISTRY_FILE RegistryFile; - WCHAR LogName[MAX_PATH]; - HANDLE FileHandle; -// HANDLE FileHandleLog; - OBJECT_ATTRIBUTES ObjectAttributes; -// KIRQL OldIrql; - UNICODE_STRING TmpFileName; - int i; - LARGE_INTEGER fileOffset; - DWORD * pEntDword; - /* Verify that the handle is valid and is a registry key */ - Status = ObReferenceObjectByHandle(KeyHandle, - KEY_QUERY_VALUE, - CmiKeyType, - UserMode, - (PVOID *)&KeyObject, - NULL); + NTSTATUS Status; + PKEY_OBJECT KeyObject; + PREGISTRY_HIVE RegistryHive; + WCHAR LogName[MAX_PATH]; + UNICODE_STRING TmpFileName; + HANDLE FileHandle; + // HANDLE FileHandleLog; + OBJECT_ATTRIBUTES ObjectAttributes; + // KIRQL OldIrql; + LARGE_INTEGER fileOffset; + DWORD * pEntDword; + ULONG i; + + DPRINT("KeyHandle %x\n", KeyHandle); + + /* Verify that the handle is valid and is a registry key */ + Status = ObReferenceObjectByHandle(KeyHandle, + KEY_QUERY_VALUE, + CmiKeyType, + UserMode, + (PVOID *) &KeyObject, + NULL); + if (!NT_SUCCESS(Status)) { - return Status; + return Status; } - RegistryFile = KeyObject->RegistryFile; -// KeAcquireSpinLock(&RegistryFile->RegLock, &OldIrql); - /* then write changed blocks in .log */ - wcscpy(LogName,RegistryFile->Filename ); + + VERIFY_KEY_OBJECT(KeyObject); + + RegistryHive = KeyObject->RegistryHive; +// KeAcquireSpinLock(&RegistryHive->RegLock, &OldIrql); + /* Then write changed blocks in .log */ + wcscpy(LogName,RegistryHive->Filename.Buffer); wcscat(LogName,L".log"); RtlInitUnicodeString (&TmpFileName, LogName); InitializeObjectAttributes(&ObjectAttributes, - &TmpFileName, - 0, - NULL, - NULL); + &TmpFileName, + 0, + NULL, + NULL); + /* BEGIN FIXME : actually (26 November 200) vfatfs.sys can't create new files so we can't create log file Status = ZwCreateFile(&FileHandleLog, - FILE_ALL_ACCESS, - &ObjectAttributes, - NULL, 0, FILE_ATTRIBUTE_NORMAL, - 0, FILE_SUPERSEDE, 0, NULL, 0); + FILE_ALL_ACCESS, + &ObjectAttributes, + NULL, + 0, + FILE_ATTRIBUTE_NORMAL, + 0, + FILE_SUPERSEDE, + 0, + NULL, + 0); + + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(KeyObject); + return Status; + } + Status = ZwWriteFile(FileHandleLog, - 0, 0, 0, 0, - RegistryFile->HeaderBlock, - sizeof(HEADER_BLOCK), - 0, 0); - for (i=0; i < RegistryFile->BlockListSize ; i++) + 0, + 0, + 0, + 0, + RegistryHive->HiveHeader, + sizeof(HIVE_HEADER), + 0, + 0); + + if (!NT_SUCCESS(Status)) + { + ZwClose(FileHandleLog); + ObDereferenceObject(KeyObject); + return Status; + } + + for (i = 0; i < RegistryHive->BlockListSize ; i++) { - if( RegistryFile->BlockList[i]->DateModified.dwHighDateTime - > RegistryFile->HeaderBlock->DateModified.dwHighDateTime - ||( RegistryFile->BlockList[i]->DateModified.dwHighDateTime - == RegistryFile->HeaderBlock->DateModified.dwHighDateTime - && RegistryFile->BlockList[i]->DateModified.dwLowDateTime - > RegistryFile->HeaderBlock->DateModified.dwLowDateTime) + if ( RegistryHive->BlockList[i]->DateModified.dwHighDateTime + > RegistryHive->HiveHeader->DateModified.dwHighDateTime + || (RegistryHive->BlockList[i]->DateModified.dwHighDateTime + == RegistryHive->HiveHeader->DateModified.dwHighDateTime + && RegistryHive->BlockList[i]->DateModified.dwLowDateTime + > RegistryHive->HiveHeader->DateModified.dwLowDateTime + ) ) + Status = ZwWriteFile(FileHandleLog, - 0, 0, 0, 0, - RegistryFile->BlockList[i], - RegistryFile->BlockList[i]->BlockSize , - 0, 0); + 0, + 0, + 0, + 0, + RegistryHive->BlockList[i], + RegistryHive->BlockList[i]->BlockSize , + 0, + 0); + + if (!NT_SUCCESS(Status)) + { + ZwClose(FileHandleLog); + ObDereferenceObject(KeyObject); + return Status; + } } ZwClose(FileHandleLog); END FIXME*/ - /* update header of registryfile with Version >VersionOld */ + + /* Update header of RegistryHive with Version >VersionOld */ /* this allow recover if system crash while updating hove file */ - RtlInitUnicodeString (&TmpFileName, RegistryFile->Filename); InitializeObjectAttributes(&ObjectAttributes, - &TmpFileName, - 0, - NULL, - NULL); + &RegistryHive->Filename, + 0, + NULL, + NULL); + Status = NtOpenFile(&FileHandle, - FILE_ALL_ACCESS, - &ObjectAttributes, - NULL, 0, 0); - RegistryFile->HeaderBlock->Version++; + FILE_ALL_ACCESS, + &ObjectAttributes, + NULL, + 0, + 0); + + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(KeyObject); + return Status; + } + + RegistryHive->HiveHeader->Version++; Status = ZwWriteFile(FileHandle, - 0, 0, 0, 0, - RegistryFile->HeaderBlock, - sizeof(HEADER_BLOCK), - 0, 0); + 0, + 0, + 0, + 0, + RegistryHive->HiveHeader, + sizeof(HIVE_HEADER), + 0, + 0); - /* update changed blocks in file */ - fileOffset.u.HighPart = 0; - for (i=0; i < RegistryFile->BlockListSize ; i++) - { - if( RegistryFile->BlockList[i]->DateModified.dwHighDateTime - > RegistryFile->HeaderBlock->DateModified.dwHighDateTime - ||( RegistryFile->BlockList[i]->DateModified.dwHighDateTime - == RegistryFile->HeaderBlock->DateModified.dwHighDateTime - && RegistryFile->BlockList[i]->DateModified.dwLowDateTime - > RegistryFile->HeaderBlock->DateModified.dwLowDateTime) - ) + if (!NT_SUCCESS(Status)) { - fileOffset.u.LowPart = RegistryFile->BlockList[i]->BlockOffset+4096; - Status = NtWriteFile(FileHandle, - 0, 0, 0, 0, - RegistryFile->BlockList[i], - RegistryFile->BlockList[i]->BlockSize , - &fileOffset, 0); + ZwClose(FileHandle); + ObDereferenceObject(KeyObject); + return Status; } - } - /* change version in header */ - RegistryFile->HeaderBlock->VersionOld = RegistryFile->HeaderBlock->Version; - ZwQuerySystemTime((PTIME) &RegistryFile->HeaderBlock->DateModified); - /* calculate checksum */ - RegistryFile->HeaderBlock->Checksum = 0; - pEntDword = (DWORD *) RegistryFile->HeaderBlock; - for (i=0 ; i <127 ; i++) + + /* Update changed blocks in file */ + fileOffset.u.HighPart = 0; + for (i = 0; i < RegistryHive->BlockListSize ; i++) { - RegistryFile->HeaderBlock->Checksum ^= pEntDword[i]; + if (RegistryHive->BlockList[i]->DateModified.dwHighDateTime + > RegistryHive->HiveHeader->DateModified.dwHighDateTime + || (RegistryHive->BlockList[i]->DateModified.dwHighDateTime + == RegistryHive->HiveHeader->DateModified.dwHighDateTime + && RegistryHive->BlockList[i]->DateModified.dwLowDateTime + > RegistryHive->HiveHeader->DateModified.dwLowDateTime + ) + ) + { + fileOffset.u.LowPart = RegistryHive->BlockList[i]->BlockOffset+4096; + Status = NtWriteFile(FileHandle, + 0, + 0, + 0, + 0, + RegistryHive->BlockList[i], + RegistryHive->BlockList[i]->BlockSize , + &fileOffset, + 0); + + if (!NT_SUCCESS(Status)) + { + ZwClose(FileHandle); + ObDereferenceObject(KeyObject); + return Status; + } + } } - /* write new header */ + + /* Change version in header */ + RegistryHive->HiveHeader->VersionOld = RegistryHive->HiveHeader->Version; + ZwQuerySystemTime((PTIME) &RegistryHive->HiveHeader->DateModified); + + /* Calculate checksum */ + RegistryHive->HiveHeader->Checksum = 0; + pEntDword = (DWORD *) RegistryHive->HiveHeader; + for (i = 0; i < 127 ; i++) + { + RegistryHive->HiveHeader->Checksum ^= pEntDword[i]; + } + + /* Write new header */ fileOffset.u.LowPart = 0; Status = ZwWriteFile(FileHandle, - 0, 0, 0, 0, - RegistryFile->HeaderBlock, - sizeof(HEADER_BLOCK), - &fileOffset, 0); - ZwClose(FileHandle); -// KeReleaseSpinLock(&RegistryFile->RegLock, OldIrql); - return STATUS_SUCCESS; -} + 0, + 0, + 0, + 0, + RegistryHive->HiveHeader, + sizeof(HIVE_HEADER), + &fileOffset, + 0); - -NTSTATUS STDCALL -NtOpenKey(OUT PHANDLE KeyHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes) -{ - NTSTATUS Status; - PVOID Object; - UNICODE_STRING RemainingPath; - - RemainingPath.Buffer=NULL; - Status = ObFindObject(ObjectAttributes,&Object,&RemainingPath,CmiKeyType); -DPRINT("NTOpenKey : after ObFindObject\n"); -DPRINT("RB.B=%x\n",RemainingPath.Buffer); - if(RemainingPath.Buffer != 0 && RemainingPath.Buffer[0] !=0) - { -DPRINT("NTOpenKey3 : after ObFindObject\n"); - ObDereferenceObject(Object); -DPRINT("RP=%wZ\n",&RemainingPath); - return STATUS_UNSUCCESSFUL; - } -DPRINT("NTOpenKey2 : after ObFindObject\n"); - /* Fail if the key has been deleted */ - if (((PKEY_OBJECT)Object)->Flags & KO_MARKED_FOR_DELETE) - { - ObDereferenceObject(Object); - return STATUS_UNSUCCESSFUL; - } - - Status = ObCreateHandle( - PsGetCurrentProcess(), - Object, - DesiredAccess, - FALSE, - KeyHandle - ); - ObDereferenceObject(Object); if (!NT_SUCCESS(Status)) - { - return Status; - } + { + ZwClose(FileHandle); + ObDereferenceObject(KeyObject); + return Status; + } + ZwClose(FileHandle); +// KeReleaseSpinLock(&RegistryHive->RegLock, OldIrql); + ObDereferenceObject(KeyObject); return STATUS_SUCCESS; } NTSTATUS STDCALL -NtQueryKey(IN HANDLE KeyHandle, - IN KEY_INFORMATION_CLASS KeyInformationClass, - OUT PVOID KeyInformation, - IN ULONG Length, - OUT PULONG ResultLength) +NtOpenKey(OUT PHANDLE KeyHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes) { - NTSTATUS Status; - PKEY_OBJECT KeyObject; - PREGISTRY_FILE RegistryFile; - PKEY_BLOCK KeyBlock; - PKEY_BASIC_INFORMATION BasicInformation; - PKEY_NODE_INFORMATION NodeInformation; - PKEY_FULL_INFORMATION FullInformation; - PDATA_BLOCK pClassData; + UNICODE_STRING RemainingPath; + NTSTATUS Status; + PVOID Object; + + DPRINT("KH %x DA %x OA %x OA->ON %x\n", + KeyHandle, + DesiredAccess, + ObjectAttributes, + ObjectAttributes ? ObjectAttributes->ObjectName : NULL); + + RemainingPath.Buffer = NULL; + Status = ObFindObject(ObjectAttributes, + &Object, + &RemainingPath, + CmiKeyType); + + if (!NT_SUCCESS(Status)) + { + return Status; + } + + VERIFY_KEY_OBJECT((PKEY_OBJECT) Object); + + DPRINT("RemainingPath.Buffer %x\n", RemainingPath.Buffer); + + if ((RemainingPath.Buffer != NULL) && (RemainingPath.Buffer[0] != 0)) + { + ObDereferenceObject(Object); + return STATUS_UNSUCCESSFUL; + } + + /* Fail if the key has been deleted */ + if (((PKEY_OBJECT)Object)->Flags & KO_MARKED_FOR_DELETE) + { + ObDereferenceObject(Object); + return STATUS_UNSUCCESSFUL; + } + + Status = ObCreateHandle( + PsGetCurrentProcess(), + Object, + DesiredAccess, + FALSE, + KeyHandle); + ObDereferenceObject(Object); + + if (!NT_SUCCESS(Status)) + { + return Status; + } + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +NtQueryKey(IN HANDLE KeyHandle, + IN KEY_INFORMATION_CLASS KeyInformationClass, + OUT PVOID KeyInformation, + IN ULONG Length, + OUT PULONG ResultLength) +{ + PKEY_BASIC_INFORMATION BasicInformation; + PKEY_NODE_INFORMATION NodeInformation; + PKEY_FULL_INFORMATION FullInformation; + PREGISTRY_HIVE RegistryHive; + PDATA_CELL pClassData; + PKEY_OBJECT KeyObject; + PKEY_CELL KeyCell; + NTSTATUS Status; + + DPRINT("KH %x KIC %x KI %x L %d RL %x\n", + KeyHandle, + KeyInformationClass, + KeyInformation, + Length, + ResultLength); - /* Verify that the handle is valid and is a registry key */ + /* Verify that the handle is valid and is a registry key */ Status = ObReferenceObjectByHandle(KeyHandle, - KEY_READ, - CmiKeyType, - UserMode, - (PVOID *)&KeyObject, - NULL); + KEY_READ, + CmiKeyType, + UserMode, + (PVOID *) &KeyObject, + NULL); + if (!NT_SUCCESS(Status)) { - return Status; + return Status; } - /* Get pointer to KeyBlock */ - KeyBlock = KeyObject->KeyBlock; - RegistryFile = KeyObject->RegistryFile; + VERIFY_KEY_OBJECT(KeyObject); + + /* Get pointer to KeyCell */ + KeyCell = KeyObject->KeyCell; + RegistryHive = KeyObject->RegistryHive; Status = STATUS_SUCCESS; switch (KeyInformationClass) { case KeyBasicInformation: - /* Check size of buffer */ + /* Check size of buffer */ if (Length < sizeof(KEY_BASIC_INFORMATION) + KeyObject->NameSize * sizeof(WCHAR)) { @@ -748,165 +919,167 @@ NtQueryKey(IN HANDLE KeyHandle, } else { - /* Fill buffer with requested info */ + /* Fill buffer with requested info */ BasicInformation = (PKEY_BASIC_INFORMATION) KeyInformation; - BasicInformation->LastWriteTime.u.LowPart = KeyBlock->LastWriteTime.dwLowDateTime; - BasicInformation->LastWriteTime.u.HighPart = KeyBlock->LastWriteTime.dwHighDateTime; + BasicInformation->LastWriteTime.u.LowPart = KeyCell->LastWriteTime.dwLowDateTime; + BasicInformation->LastWriteTime.u.HighPart = KeyCell->LastWriteTime.dwHighDateTime; BasicInformation->TitleIndex = 0; - BasicInformation->NameLength = - (KeyObject->NameSize ) * sizeof(WCHAR); - mbstowcs(BasicInformation->Name, - KeyObject->Name, - KeyObject->NameSize*sizeof(WCHAR)); + BasicInformation->NameLength = (KeyObject->NameSize) * sizeof(WCHAR); + mbstowcs(BasicInformation->Name, + KeyObject->Name, + KeyObject->NameSize*sizeof(WCHAR)); *ResultLength = sizeof(KEY_BASIC_INFORMATION) + KeyObject->NameSize * sizeof(WCHAR); } break; case KeyNodeInformation: - /* Check size of buffer */ - if (Length < sizeof(KEY_NODE_INFORMATION) + - (KeyObject->NameSize ) * sizeof(WCHAR) + - KeyBlock->ClassSize ) + /* Check size of buffer */ + if (Length < sizeof(KEY_NODE_INFORMATION) + + KeyObject->NameSize * sizeof(WCHAR) + + KeyCell->ClassSize) { Status = STATUS_BUFFER_OVERFLOW; } else { - /* Fill buffer with requested info */ + /* Fill buffer with requested info */ NodeInformation = (PKEY_NODE_INFORMATION) KeyInformation; - NodeInformation->LastWriteTime.u.LowPart = KeyBlock->LastWriteTime.dwLowDateTime; - NodeInformation->LastWriteTime.u.HighPart = KeyBlock->LastWriteTime.dwHighDateTime; + NodeInformation->LastWriteTime.u.LowPart = KeyCell->LastWriteTime.dwLowDateTime; + NodeInformation->LastWriteTime.u.HighPart = KeyCell->LastWriteTime.dwHighDateTime; NodeInformation->TitleIndex = 0; NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) + KeyObject->NameSize * sizeof(WCHAR); - NodeInformation->ClassLength = KeyBlock->ClassSize; - NodeInformation->NameLength = - (KeyObject->NameSize ) * sizeof(WCHAR); - mbstowcs(NodeInformation->Name, - KeyObject->Name, - KeyObject->NameSize*2); - if (KeyBlock->ClassSize != 0) + NodeInformation->ClassLength = KeyCell->ClassSize; + NodeInformation->NameLength = KeyObject->NameSize * sizeof(WCHAR); + mbstowcs(NodeInformation->Name, + KeyObject->Name, + KeyObject->NameSize * sizeof(WCHAR)); + + if (KeyCell->ClassSize != 0) { - pClassData=CmiGetBlock(KeyObject->RegistryFile - ,KeyBlock->ClassNameOffset,NULL); - wcsncpy(NodeInformation->Name + (KeyObject->NameSize )*sizeof(WCHAR), - (PWCHAR)pClassData->Data, - KeyBlock->ClassSize); - CmiReleaseBlock(RegistryFile, pClassData); + pClassData = CmiGetBlock(KeyObject->RegistryHive, + KeyCell->ClassNameOffset, + NULL); + wcsncpy(NodeInformation->Name + KeyObject->NameSize * sizeof(WCHAR), + (PWCHAR)pClassData->Data, + KeyCell->ClassSize); + CmiReleaseBlock(RegistryHive, pClassData); } - *ResultLength = sizeof(KEY_NODE_INFORMATION) + - (KeyObject->NameSize ) * sizeof(WCHAR) + - KeyBlock->ClassSize; + *ResultLength = sizeof(KEY_NODE_INFORMATION) + + KeyObject->NameSize * sizeof(WCHAR) + + KeyCell->ClassSize; } break; - + case KeyFullInformation: - /* Check size of buffer */ - if (Length < sizeof(KEY_FULL_INFORMATION) + - KeyBlock->ClassSize ) + /* Check size of buffer */ + if (Length < sizeof(KEY_FULL_INFORMATION) + KeyCell->ClassSize) { Status = STATUS_BUFFER_OVERFLOW; } else { - /* Fill buffer with requested info */ + /* Fill buffer with requested info */ FullInformation = (PKEY_FULL_INFORMATION) KeyInformation; - FullInformation->LastWriteTime.u.LowPart = KeyBlock->LastWriteTime.dwLowDateTime; - FullInformation->LastWriteTime.u.HighPart = KeyBlock->LastWriteTime.dwHighDateTime; + FullInformation->LastWriteTime.u.LowPart = KeyCell->LastWriteTime.dwLowDateTime; + FullInformation->LastWriteTime.u.HighPart = KeyCell->LastWriteTime.dwHighDateTime; FullInformation->TitleIndex = 0; - FullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) - - sizeof(WCHAR); - FullInformation->ClassLength = KeyBlock->ClassSize; - FullInformation->SubKeys = KeyBlock->NumberOfSubKeys; - FullInformation->MaxNameLen = - CmiGetMaxNameLength(RegistryFile, KeyBlock); - FullInformation->MaxClassLen = - CmiGetMaxClassLength(RegistryFile, KeyBlock); - FullInformation->Values = KeyBlock->NumberOfValues; - FullInformation->MaxValueNameLen = - CmiGetMaxValueNameLength(RegistryFile, KeyBlock); + FullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR); + FullInformation->ClassLength = KeyCell->ClassSize; + FullInformation->SubKeys = KeyCell->NumberOfSubKeys; + FullInformation->MaxNameLen = + CmiGetMaxNameLength(RegistryHive, KeyCell); + FullInformation->MaxClassLen = + CmiGetMaxClassLength(RegistryHive, KeyCell); + FullInformation->Values = KeyCell->NumberOfValues; + FullInformation->MaxValueNameLen = + CmiGetMaxValueNameLength(RegistryHive, KeyCell); FullInformation->MaxValueDataLen = - CmiGetMaxValueDataLength(RegistryFile, KeyBlock); - if (KeyBlock->ClassSize != 0) + CmiGetMaxValueDataLength(RegistryHive, KeyCell); + if (KeyCell->ClassSize != 0) { - pClassData=CmiGetBlock(KeyObject->RegistryFile - ,KeyBlock->ClassNameOffset,NULL); + pClassData=CmiGetBlock(KeyObject->RegistryHive, + KeyCell->ClassNameOffset, + NULL); wcsncpy(FullInformation->Class, - (PWCHAR)pClassData->Data, - KeyBlock->ClassSize); - CmiReleaseBlock(RegistryFile, pClassData); + (PWCHAR)pClassData->Data, + KeyCell->ClassSize); + CmiReleaseBlock(RegistryHive, pClassData); } - *ResultLength = sizeof(KEY_FULL_INFORMATION) + - KeyBlock->ClassSize ; + *ResultLength = sizeof(KEY_FULL_INFORMATION) + KeyCell->ClassSize; } break; } - ObDereferenceObject (KeyObject); - return Status; + ObDereferenceObject(KeyObject); + + return Status; } - NTSTATUS STDCALL NtQueryValueKey(IN HANDLE KeyHandle, - IN PUNICODE_STRING ValueName, - IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, - OUT PVOID KeyValueInformation, - IN ULONG Length, - OUT PULONG ResultLength) + IN PUNICODE_STRING ValueName, + IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + OUT PVOID KeyValueInformation, + IN ULONG Length, + OUT PULONG ResultLength) { NTSTATUS Status; PKEY_OBJECT KeyObject; - PREGISTRY_FILE RegistryFile; - PKEY_BLOCK KeyBlock; - PVALUE_BLOCK ValueBlock; - PDATA_BLOCK DataBlock; + PREGISTRY_HIVE RegistryHive; + PKEY_CELL KeyCell; + PVALUE_CELL ValueCell; + PDATA_CELL DataCell; PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation; PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation; PKEY_VALUE_FULL_INFORMATION ValueFullInformation; char ValueName2[MAX_PATH]; - DPRINT("NtQueryValueKey(KeyHandle %x ValueName %S Length %x )\n", + DPRINT("NtQueryValueKey(KeyHandle %x ValueName %S Length %x)\n", KeyHandle, ValueName->Buffer, Length); - wcstombs(ValueName2,ValueName->Buffer,ValueName->Length>>1); - ValueName2[ValueName->Length>>1]=0; + wcstombs(ValueName2, ValueName->Buffer, ValueName->Length >> 1); + ValueName2[ValueName->Length >> 1] = 0; - /* Verify that the handle is valid and is a registry key */ + /* Verify that the handle is valid and is a registry key */ Status = ObReferenceObjectByHandle(KeyHandle, - KEY_QUERY_VALUE, - CmiKeyType, - UserMode, - (PVOID *)&KeyObject, - NULL); + KEY_QUERY_VALUE, + CmiKeyType, + UserMode, + (PVOID *)&KeyObject, + NULL); + if (!NT_SUCCESS(Status)) { DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status); - return Status; + return Status; } - /* Get pointer to KeyBlock */ - KeyBlock = KeyObject->KeyBlock; - RegistryFile = KeyObject->RegistryFile; - /* Get Value block of interest */ - Status = CmiScanKeyForValue(RegistryFile, - KeyBlock, - ValueName2, - &ValueBlock,NULL); + VERIFY_KEY_OBJECT(KeyObject); + + /* Get pointer to KeyCell */ + KeyCell = KeyObject->KeyCell; + RegistryHive = KeyObject->RegistryHive; + /* Get Value block of interest */ + Status = CmiScanKeyForValue(RegistryHive, + KeyCell, + ValueName2, + &ValueCell,NULL); + if (!NT_SUCCESS(Status)) { DPRINT("CmiScanKeyForValue() failed with status %x\n", Status); ObDereferenceObject(KeyObject); - return Status; + return Status; } - else if (ValueBlock != NULL) + else if (ValueCell != NULL) { switch (KeyValueInformationClass) { case KeyValueBasicInformation: - *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + - ValueBlock->NameSize * sizeof(WCHAR); + *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + + ValueCell->NameSize * sizeof(WCHAR); if (Length < *ResultLength) { Status = STATUS_BUFFER_TOO_SMALL; @@ -916,17 +1089,18 @@ NtQueryValueKey(IN HANDLE KeyHandle, ValueBasicInformation = (PKEY_VALUE_BASIC_INFORMATION) KeyValueInformation; ValueBasicInformation->TitleIndex = 0; - ValueBasicInformation->Type = ValueBlock->DataType; + ValueBasicInformation->Type = ValueCell->DataType; ValueBasicInformation->NameLength = - (ValueBlock->NameSize + 1) * sizeof(WCHAR); - mbstowcs(ValueBasicInformation->Name, ValueBlock->Name,ValueBlock->NameSize*2); - ValueBasicInformation->Name[ValueBlock->NameSize]=0; + (ValueCell->NameSize + 1) * sizeof(WCHAR); + mbstowcs(ValueBasicInformation->Name, + ValueCell->Name,ValueCell->NameSize * 2); + ValueBasicInformation->Name[ValueCell->NameSize] = 0; } break; case KeyValuePartialInformation: - *ResultLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + - (ValueBlock->DataSize & LONG_MAX); + *ResultLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + + (ValueCell->DataSize & LONG_MAX); if (Length < *ResultLength) { Status = STATUS_BUFFER_TOO_SMALL; @@ -936,29 +1110,29 @@ NtQueryValueKey(IN HANDLE KeyHandle, ValuePartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION) KeyValueInformation; ValuePartialInformation->TitleIndex = 0; - ValuePartialInformation->Type = ValueBlock->DataType; - ValuePartialInformation->DataLength = ValueBlock->DataSize & LONG_MAX; - if(ValueBlock->DataSize >0) - { - DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,NULL); - RtlCopyMemory(ValuePartialInformation->Data, - DataBlock->Data, - ValueBlock->DataSize & LONG_MAX); - CmiReleaseBlock(RegistryFile, DataBlock); - } + ValuePartialInformation->Type = ValueCell->DataType; + ValuePartialInformation->DataLength = ValueCell->DataSize & LONG_MAX; + if (ValueCell->DataSize > 0) + { + DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL); + RtlCopyMemory(ValuePartialInformation->Data, + DataCell->Data, + ValueCell->DataSize & LONG_MAX); + CmiReleaseBlock(RegistryHive, DataCell); + } else - { - RtlCopyMemory(ValuePartialInformation->Data, - &ValueBlock->DataOffset, - ValueBlock->DataSize & LONG_MAX); - } + { + RtlCopyMemory(ValuePartialInformation->Data, + &ValueCell->DataOffset, + ValueCell->DataSize & LONG_MAX); + } } break; case KeyValueFullInformation: *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) - + (ValueBlock->NameSize -1) * sizeof(WCHAR) - + (ValueBlock->DataSize & LONG_MAX); + + (ValueCell->NameSize -1) * sizeof(WCHAR) + + (ValueCell->DataSize & LONG_MAX); if (Length < *ResultLength) { Status = STATUS_BUFFER_TOO_SMALL; @@ -968,33 +1142,33 @@ NtQueryValueKey(IN HANDLE KeyHandle, ValueFullInformation = (PKEY_VALUE_FULL_INFORMATION) KeyValueInformation; ValueFullInformation->TitleIndex = 0; - ValueFullInformation->Type = ValueBlock->DataType; + ValueFullInformation->Type = ValueCell->DataType; ValueFullInformation->DataOffset = (DWORD)ValueFullInformation->Name - (DWORD)ValueFullInformation - + (ValueBlock->NameSize + 1) * sizeof(WCHAR); + + (ValueCell->NameSize + 1) * sizeof(WCHAR); ValueFullInformation->DataOffset = - (ValueFullInformation->DataOffset +3) &0xfffffffc; - ValueFullInformation->DataLength = ValueBlock->DataSize & LONG_MAX; + (ValueFullInformation->DataOffset + 3) &0xfffffffc; + ValueFullInformation->DataLength = ValueCell->DataSize & LONG_MAX; ValueFullInformation->NameLength = - (ValueBlock->NameSize + 1) * sizeof(WCHAR); - mbstowcs(ValueFullInformation->Name, ValueBlock->Name,ValueBlock->NameSize*2); - ValueFullInformation->Name[ValueBlock->NameSize] = 0; - if(ValueBlock->DataSize >0) - { - DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,NULL); - RtlCopyMemory((char *)(ValueFullInformation) - + ValueFullInformation->DataOffset, - DataBlock->Data, - ValueBlock->DataSize & LONG_MAX); - CmiReleaseBlock(RegistryFile, DataBlock); - } + (ValueCell->NameSize + 1) * sizeof(WCHAR); + mbstowcs(ValueFullInformation->Name, ValueCell->Name,ValueCell->NameSize*2); + ValueFullInformation->Name[ValueCell->NameSize] = 0; + if (ValueCell->DataSize > 0) + { + DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL); + RtlCopyMemory((PCHAR) ValueFullInformation + + ValueFullInformation->DataOffset, + DataCell->Data, + ValueCell->DataSize & LONG_MAX); + CmiReleaseBlock(RegistryHive, DataCell); + } else - { - RtlCopyMemory((char *)(ValueFullInformation) - + ValueFullInformation->DataOffset, - &ValueBlock->DataOffset, - ValueBlock->DataSize & LONG_MAX); - } + { + RtlCopyMemory((PCHAR) ValueFullInformation + + ValueFullInformation->DataOffset, + &ValueCell->DataOffset, + ValueCell->DataSize & LONG_MAX); + } } break; } @@ -1003,210 +1177,227 @@ NtQueryValueKey(IN HANDLE KeyHandle, { Status = STATUS_OBJECT_NAME_NOT_FOUND; } + ObDereferenceObject(KeyObject); - return Status; + return Status; } NTSTATUS STDCALL -NtSetValueKey ( +NtSetValueKey( IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName, IN ULONG TitleIndex, IN ULONG Type, IN PVOID Data, - IN ULONG DataSize - ) + IN ULONG DataSize) { - NTSTATUS Status; - PKEY_OBJECT KeyObject; - PREGISTRY_FILE RegistryFile; - PKEY_BLOCK KeyBlock; - PVALUE_BLOCK ValueBlock; - BLOCK_OFFSET VBOffset; - char ValueName2[MAX_PATH]; - PDATA_BLOCK DataBlock, NewDataBlock; - PHEAP_BLOCK pHeap; + NTSTATUS Status; + PKEY_OBJECT KeyObject; + PREGISTRY_HIVE RegistryHive; + PKEY_CELL KeyCell; + PVALUE_CELL ValueCell; + BLOCK_OFFSET VBOffset; + char ValueName2[MAX_PATH]; + PDATA_CELL DataCell; + PDATA_CELL NewDataCell; + PHBIN pBin; // KIRQL OldIrql; DPRINT("KeyHandle %x ValueName %S Type %d\n", - KeyHandle, ValueName->Buffer, Type); + KeyHandle, ValueName? ValueName->Buffer : NULL, Type); - wcstombs(ValueName2,ValueName->Buffer,ValueName->Length>>1); - ValueName2[ValueName->Length>>1]=0; + wcstombs(ValueName2,ValueName->Buffer, ValueName->Length >> 1); + ValueName2[ValueName->Length>>1] = 0; - /* Verify that the handle is valid and is a registry key */ + /* Verify that the handle is valid and is a registry key */ Status = ObReferenceObjectByHandle(KeyHandle, - KEY_SET_VALUE, - CmiKeyType, - UserMode, - (PVOID *)&KeyObject, - NULL); - if (!NT_SUCCESS(Status)) - return Status; + KEY_SET_VALUE, + CmiKeyType, + UserMode, + (PVOID *) &KeyObject, + NULL); - /* Get pointer to KeyBlock */ - KeyBlock = KeyObject->KeyBlock; - RegistryFile = KeyObject->RegistryFile; - Status = CmiScanKeyForValue(RegistryFile, - KeyBlock, - ValueName2, - &ValueBlock, &VBOffset); if (!NT_SUCCESS(Status)) - { - DPRINT1("Not found Status 0x%X\n", Status); + return Status; + + VERIFY_KEY_OBJECT(KeyObject); + + /* Get pointer to key cell */ + KeyCell = KeyObject->KeyCell; + RegistryHive = KeyObject->RegistryHive; + Status = CmiScanKeyForValue(RegistryHive, + KeyCell, + ValueName2, + &ValueCell, + &VBOffset); - ObDereferenceObject (KeyObject); - return Status; - } -// KeAcquireSpinLock(&RegistryFile->RegLock, &OldIrql); - if (ValueBlock == NULL) - { - Status = CmiAddValueToKey(RegistryFile, - KeyBlock, - ValueName2, - &ValueBlock, - &VBOffset); - } if (!NT_SUCCESS(Status)) - { - DPRINT1("Cannot Add Status 0x%X\n", Status); - ObDereferenceObject (KeyObject); - return Status; - } + { + DPRINT1("Value not found. Status 0x%X\n", Status); + + ObDereferenceObject(KeyObject); + return Status; + } + +// KeAcquireSpinLock(&RegistryHive->RegLock, &OldIrql); + + if (ValueCell == NULL) + { + Status = CmiAddValueToKey(RegistryHive, + KeyCell, + ValueName2, + &ValueCell, + &VBOffset); + } + + if (!NT_SUCCESS(Status)) + { + DPRINT1("Cannot add value. Status 0x%X\n", Status); + ObDereferenceObject(KeyObject); + return Status; + } else - { - /* FIXME if datasize <=4 then write in valueblock directly */ - if (DataSize <= 4) - { - if (( ValueBlock->DataSize <0 ) - && (DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,NULL))) - { - CmiDestroyBlock(RegistryFile, DataBlock, ValueBlock->DataOffset); - } - RtlCopyMemory(&ValueBlock->DataOffset, Data, DataSize); - ValueBlock->DataSize = DataSize | 0x80000000; - ValueBlock->DataType = Type; - memcpy(&ValueBlock->DataOffset, Data, DataSize); - } - /* If new data size is <= current then overwrite current data */ - else if (DataSize <= (ValueBlock->DataSize & 0x7fffffff)) - { - DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,&pHeap); - RtlCopyMemory(DataBlock->Data, Data, DataSize); - ValueBlock->DataSize = DataSize; - ValueBlock->DataType = Type; - CmiReleaseBlock(RegistryFile, DataBlock); - /* update time of heap */ - if(RegistryFile->Filename) - ZwQuerySystemTime((PTIME) &pHeap->DateModified); - } - else - { - BLOCK_OFFSET NewOffset; - /* Destroy current data block and allocate a new one */ - if (( ValueBlock->DataSize <0 ) - && (DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,NULL))) - { - CmiDestroyBlock(RegistryFile, DataBlock, ValueBlock->DataOffset); - } - Status = CmiAllocateBlock(RegistryFile, - (PVOID *)&NewDataBlock, - DataSize,&NewOffset); - RtlCopyMemory(&NewDataBlock->Data[0], Data, DataSize); - ValueBlock->DataSize = DataSize; - ValueBlock->DataType = Type; - CmiReleaseBlock(RegistryFile, NewDataBlock); - ValueBlock->DataOffset = NewOffset; - } - /* update time of heap */ - if(RegistryFile->Filename && CmiGetBlock(RegistryFile, VBOffset,&pHeap)) - ZwQuerySystemTime((PTIME) &pHeap->DateModified); + { + DPRINT("DataSize (%d)\n", DataSize); + + /* If datasize <= 4 then write in valueblock directly */ + if (DataSize <= 4) + { + if ((ValueCell->DataSize < 0) + && (DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL))) + { + CmiDestroyBlock(RegistryHive, DataCell, ValueCell->DataOffset); + } + + RtlCopyMemory(&ValueCell->DataOffset, Data, DataSize); + ValueCell->DataSize = DataSize | 0x80000000; + ValueCell->DataType = Type; + RtlMoveMemory(&ValueCell->DataOffset, Data, DataSize); + } + /* If new data size is <= current then overwrite current data */ + else if (DataSize <= (ValueCell->DataSize & 0x7fffffff)) + { + DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset,&pBin); + RtlCopyMemory(DataCell->Data, Data, DataSize); + ValueCell->DataSize = DataSize; + ValueCell->DataType = Type; + CmiReleaseBlock(RegistryHive, DataCell); + /* Update time of heap */ + if (IsPermanentHive(RegistryHive)) + { + ZwQuerySystemTime((PTIME) &pBin->DateModified); + } + } + else + { + BLOCK_OFFSET NewOffset; + + /* Destroy current data block and allocate a new one */ + if ((ValueCell->DataSize < 0) + && (DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL))) + { + CmiDestroyBlock(RegistryHive, DataCell, ValueCell->DataOffset); + } + Status = CmiAllocateBlock(RegistryHive, + (PVOID *) &NewDataCell, + DataSize, + &NewOffset); + RtlCopyMemory(&NewDataCell->Data[0], Data, DataSize); + ValueCell->DataSize = DataSize; + ValueCell->DataType = Type; + CmiReleaseBlock(RegistryHive, NewDataCell); + ValueCell->DataOffset = NewOffset; + } + + /* Update time of heap */ + if (IsPermanentHive(RegistryHive) && CmiGetBlock(RegistryHive, VBOffset, &pBin)) + { + ZwQuerySystemTime((PTIME) &pBin->DateModified); + } + } + +// KeReleaseSpinLock(&RegistryHive->RegLock, OldIrql); - } -// KeReleaseSpinLock(&RegistryFile->RegLock, OldIrql); ObDereferenceObject (KeyObject); DPRINT("Return Status 0x%X\n", Status); - return Status; + return Status; } NTSTATUS STDCALL NtDeleteValueKey(IN HANDLE KeyHandle, - IN PUNICODE_STRING ValueName) + IN PUNICODE_STRING ValueName) { - NTSTATUS Status; - PKEY_OBJECT KeyObject; - PREGISTRY_FILE RegistryFile; - PKEY_BLOCK KeyBlock; - char ValueName2[MAX_PATH]; + PREGISTRY_HIVE RegistryHive; + CHAR ValueName2[MAX_PATH]; + PKEY_OBJECT KeyObject; + PKEY_CELL KeyCell; + NTSTATUS Status; // KIRQL OldIrql; - wcstombs(ValueName2,ValueName->Buffer,ValueName->Length>>1); - ValueName2[ValueName->Length>>1]=0; + wcstombs(ValueName2, ValueName->Buffer, ValueName->Length >> 1); + ValueName2[ValueName->Length>>1] = 0; - /* Verify that the handle is valid and is a registry key */ + /* Verify that the handle is valid and is a registry key */ Status = ObReferenceObjectByHandle(KeyHandle, - KEY_QUERY_VALUE, - CmiKeyType, - UserMode, - (PVOID *)&KeyObject, - NULL); + KEY_QUERY_VALUE, + CmiKeyType, + UserMode, + (PVOID *)&KeyObject, + NULL); + if (!NT_SUCCESS(Status)) { - return Status; + return Status; } - /* Get pointer to KeyBlock */ - KeyBlock = KeyObject->KeyBlock; - RegistryFile = KeyObject->RegistryFile; -// KeAcquireSpinLock(&RegistryFile->RegLock, &OldIrql); - Status = CmiDeleteValueFromKey(RegistryFile, - KeyBlock, - ValueName2); -// KeReleaseSpinLock(&RegistryFile->RegLock, OldIrql); + VERIFY_KEY_OBJECT(KeyObject); + + /* Get pointer to KeyCell */ + KeyCell = KeyObject->KeyCell; + RegistryHive = KeyObject->RegistryHive; +// KeAcquireSpinLock(&RegistryHive->RegLock, &OldIrql); + Status = CmiDeleteValueFromKey(RegistryHive, KeyCell, ValueName2); +// KeReleaseSpinLock(&RegistryHive->RegLock, OldIrql); ObDereferenceObject(KeyObject); - return Status; + return Status; } NTSTATUS STDCALL NtLoadKey(PHANDLE KeyHandle, - POBJECT_ATTRIBUTES ObjectAttributes) + POBJECT_ATTRIBUTES ObjectAttributes) { - return(NtLoadKey2(KeyHandle, - ObjectAttributes, - 0)); + return NtLoadKey2(KeyHandle, ObjectAttributes, 0); } NTSTATUS STDCALL NtLoadKey2(IN PHANDLE KeyHandle, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN ULONG Flags) + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG Flags) { UNIMPLEMENTED; } -NTSTATUS -STDCALL -NtNotifyChangeKey ( - IN HANDLE KeyHandle, - IN HANDLE Event, - IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, - IN PVOID ApcContext OPTIONAL, - OUT PIO_STATUS_BLOCK IoStatusBlock, - IN ULONG CompletionFilter, - IN BOOLEAN Asynchroneous, - OUT PVOID ChangeBuffer, - IN ULONG Length, - IN BOOLEAN WatchSubtree - ) +NTSTATUS STDCALL +NtNotifyChangeKey( + IN HANDLE KeyHandle, + IN HANDLE Event, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG CompletionFilter, + IN BOOLEAN Asynchroneous, + OUT PVOID ChangeBuffer, + IN ULONG Length, + IN BOOLEAN WatchSubtree) { UNIMPLEMENTED; } @@ -1214,41 +1405,44 @@ NtNotifyChangeKey ( NTSTATUS STDCALL NtQueryMultipleValueKey(IN HANDLE KeyHandle, - IN OUT PKEY_VALUE_ENTRY ValueList, - IN ULONG NumberOfValues, - OUT PVOID Buffer, - IN OUT PULONG Length, - OUT PULONG ReturnLength) + IN OUT PKEY_VALUE_ENTRY ValueList, + IN ULONG NumberOfValues, + OUT PVOID Buffer, + IN OUT PULONG Length, + OUT PULONG ReturnLength) { - PKEY_OBJECT KeyObject; - PREGISTRY_FILE RegistryFile; - PKEY_BLOCK KeyBlock; - PVALUE_BLOCK ValueBlock; - PDATA_BLOCK DataBlock; + PREGISTRY_HIVE RegistryHive; UCHAR ValueName[MAX_PATH]; - PUCHAR DataPtr; + PVALUE_CELL ValueCell; + PKEY_OBJECT KeyObject; + PDATA_CELL DataCell; ULONG BufferLength; - ULONG i; + PKEY_CELL KeyCell; NTSTATUS Status; + PUCHAR DataPtr; + ULONG i; /* Verify that the handle is valid and is a registry key */ Status = ObReferenceObjectByHandle(KeyHandle, - KEY_QUERY_VALUE, - CmiKeyType, - UserMode, - (PVOID *)&KeyObject, - NULL); + KEY_QUERY_VALUE, + CmiKeyType, + UserMode, + (PVOID *) &KeyObject, + NULL); + if (!NT_SUCCESS(Status)) { DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status); return(Status); } - /* Get pointer to KeyBlock */ - KeyBlock = KeyObject->KeyBlock; - RegistryFile = KeyObject->RegistryFile; + VERIFY_KEY_OBJECT(KeyObject); - DataPtr = (PUCHAR)Buffer; + /* Get pointer to KeyCell */ + KeyCell = KeyObject->KeyCell; + RegistryHive = KeyObject->RegistryHive; + + DataPtr = (PUCHAR) Buffer; for (i = 0; i < NumberOfValues; i++) { @@ -1259,59 +1453,55 @@ NtQueryMultipleValueKey(IN HANDLE KeyHandle, DPRINT("ValueName: '%s'\n", ValueName); - /* Get Value block of interest */ - Status = CmiScanKeyForValue(RegistryFile, - KeyBlock, - ValueName, - &ValueBlock, - NULL); + /* Get Value block of interest */ + Status = CmiScanKeyForValue(RegistryHive, + KeyCell, + ValueName, + &ValueCell, + NULL); + if (!NT_SUCCESS(Status)) - { - DPRINT("CmiScanKeyForValue() failed with status %x\n", Status); - break; - } - else if (ValueBlock == NULL) - { - Status = STATUS_OBJECT_NAME_NOT_FOUND; - break; - } + { + DPRINT("CmiScanKeyForValue() failed with status %x\n", Status); + break; + } + else if (ValueCell == NULL) + { + Status = STATUS_OBJECT_NAME_NOT_FOUND; + break; + } BufferLength = (BufferLength + 3) & 0xfffffffc; - if (BufferLength + (ValueBlock->DataSize & LONG_MAX) <= *Length) - { - DataPtr = (PUCHAR)(((ULONG)DataPtr + 3) & 0xfffffffc); - - ValueList[i].Type = ValueBlock->DataType; - ValueList[i].DataLength = ValueBlock->DataSize & LONG_MAX; - ValueList[i].DataOffset = (ULONG)DataPtr - (ULONG)Buffer; - - if (ValueBlock->DataSize >0) - { - DataBlock = CmiGetBlock(RegistryFile, - ValueBlock->DataOffset, - NULL); - RtlCopyMemory(DataPtr, - DataBlock->Data, - ValueBlock->DataSize & LONG_MAX); - CmiReleaseBlock(RegistryFile, - DataBlock); - } - else - { - RtlCopyMemory(DataPtr, - &ValueBlock->DataOffset, - ValueBlock->DataSize & LONG_MAX); - } - - DataPtr += ValueBlock->DataSize & LONG_MAX; - } + if (BufferLength + (ValueCell->DataSize & LONG_MAX) <= *Length) + { + DataPtr = (PUCHAR)(((ULONG)DataPtr + 3) & 0xfffffffc); + + ValueList[i].Type = ValueCell->DataType; + ValueList[i].DataLength = ValueCell->DataSize & LONG_MAX; + ValueList[i].DataOffset = (ULONG) DataPtr - (ULONG) Buffer; + + if (ValueCell->DataSize > 0) + { + DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL); + RtlCopyMemory(DataPtr, DataCell->Data, ValueCell->DataSize & LONG_MAX); + CmiReleaseBlock(RegistryHive, DataCell); + } + else + { + RtlCopyMemory(DataPtr, + &ValueCell->DataOffset, + ValueCell->DataSize & LONG_MAX); + } + + DataPtr += ValueCell->DataSize & LONG_MAX; + } else - { - Status = STATUS_BUFFER_TOO_SMALL; - } + { + Status = STATUS_BUFFER_TOO_SMALL; + } - BufferLength += ValueBlock->DataSize & LONG_MAX; + BufferLength += ValueCell->DataSize & LONG_MAX; } if (NT_SUCCESS(Status)) @@ -1323,15 +1513,14 @@ NtQueryMultipleValueKey(IN HANDLE KeyHandle, DPRINT("Return Status 0x%X\n", Status); - return(Status); + return Status; } -NTSTATUS -STDCALL -NtReplaceKey ( +NTSTATUS STDCALL +NtReplaceKey( IN POBJECT_ATTRIBUTES ObjectAttributes, - IN HANDLE Key, + IN HANDLE Key, IN POBJECT_ATTRIBUTES ReplacedObjectAttributes ) { @@ -1339,9 +1528,8 @@ NtReplaceKey ( } -NTSTATUS -STDCALL -NtRestoreKey ( +NTSTATUS STDCALL +NtRestoreKey( IN HANDLE KeyHandle, IN HANDLE FileHandle, IN ULONG RestoreFlags @@ -1351,39 +1539,35 @@ NtRestoreKey ( } -NTSTATUS -STDCALL -NtSaveKey ( +NTSTATUS STDCALL +NtSaveKey( IN HANDLE KeyHandle, - IN HANDLE FileHandle - ) + IN HANDLE FileHandle) { UNIMPLEMENTED; } -NTSTATUS -STDCALL -NtSetInformationKey ( +NTSTATUS STDCALL +NtSetInformationKey( IN HANDLE KeyHandle, IN CINT KeyInformationClass, - IN PVOID KeyInformation, - IN ULONG KeyInformationLength - ) + IN PVOID KeyInformation, + IN ULONG KeyInformationLength) { UNIMPLEMENTED; } NTSTATUS STDCALL -NtUnloadKey(IN HANDLE KeyHandle) +NtUnloadKey(IN HANDLE KeyHandle) { UNIMPLEMENTED; } NTSTATUS STDCALL -NtInitializeRegistry(IN BOOLEAN SetUpBoot) +NtInitializeRegistry(IN BOOLEAN SetUpBoot) { - return(STATUS_SUCCESS); + return STATUS_SUCCESS; } diff --git a/reactos/ntoskrnl/cm/regfile.c b/reactos/ntoskrnl/cm/regfile.c index 02be4bc45da..df7a4fba1b3 100644 --- a/reactos/ntoskrnl/cm/regfile.c +++ b/reactos/ntoskrnl/cm/regfile.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -20,1225 +21,1897 @@ #include "cm.h" -#define REG_BLOCK_SIZE 4096 -#define REG_HEAP_BLOCK_DATA_OFFSET 32 -#define REG_HEAP_ID 0x6e696268 -#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_BLOCK_MULTIPLE 4 -#define REG_KEY_BLOCK_ID 0x6b6e -#define REG_HASH_TABLE_BLOCK_ID 0x666c -#define REG_VALUE_BLOCK_ID 0x6b76 -#define REG_KEY_BLOCK_TYPE 0x20 -#define REG_ROOT_KEY_BLOCK_TYPE 0x2c +#define REG_BLOCK_SIZE 4096 +#define REG_HBIN_DATA_OFFSET 32 +#define REG_BIN_ID 0x6e696268 +#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_BLOCK_ID 0x666c +#define REG_VALUE_CELL_ID 0x6b76 +#define REG_KEY_CELL_TYPE 0x20 +#define REG_ROOT_KEY_CELL_TYPE 0x2c -extern PREGISTRY_FILE CmiVolatileFile; +extern PREGISTRY_HIVE CmiVolatileHive; -void CmiCreateDefaultHeaderBlock(PHEADER_BLOCK HeaderBlock) +BOOLEAN CmiDoVerify = FALSE; + +VOID +CmiCreateDefaultHiveHeader(PHIVE_HEADER Header) { - RtlZeroMemory(HeaderBlock, sizeof(HEADER_BLOCK)); - HeaderBlock->BlockId = 0x66676572; - HeaderBlock->DateModified.dwLowDateTime = 0; - HeaderBlock->DateModified.dwHighDateTime = 0; - HeaderBlock->Version = 1; - HeaderBlock->Unused3 = 3; - HeaderBlock->Unused5 = 1; - HeaderBlock->RootKeyBlock = 0; - HeaderBlock->BlockSize = REG_BLOCK_SIZE; - HeaderBlock->Unused6 = 1; - HeaderBlock->Checksum = 0; + assert(Header); + RtlZeroMemory(Header, sizeof(HIVE_HEADER)); + Header->BlockId = 0x66676572; + Header->DateModified.dwLowDateTime = 0; + Header->DateModified.dwHighDateTime = 0; + Header->Version = 1; + Header->Unused3 = 1; + Header->Unused4 = 3; + Header->Unused5 = 0; + Header->Unused6 = 1; + Header->Unused7 = 1; + Header->RootKeyCell = 0; + Header->BlockSize = REG_BLOCK_SIZE; + Header->Unused6 = 1; + Header->Checksum = 0; } -void CmiCreateDefaultHeapBlock(PHEAP_BLOCK HeapBlock) + +VOID +CmiCreateDefaultBinCell(PHBIN BinCell) { - RtlZeroMemory(HeapBlock, sizeof(HEAP_BLOCK)); - HeapBlock->BlockId = REG_HEAP_ID; - HeapBlock->DateModified.dwLowDateTime = 0; - HeapBlock->DateModified.dwHighDateTime = 0; - HeapBlock->BlockSize = REG_BLOCK_SIZE; + assert(BinCell); + RtlZeroMemory(BinCell, sizeof(HBIN)); + BinCell->BlockId = REG_BIN_ID; + BinCell->DateModified.dwLowDateTime = 0; + BinCell->DateModified.dwHighDateTime = 0; + BinCell->BlockSize = REG_BLOCK_SIZE; } -void CmiCreateDefaultRootKeyBlock(PKEY_BLOCK RootKeyBlock) + +VOID +CmiCreateDefaultRootKeyCell(PKEY_CELL RootKeyCell) { - RtlZeroMemory(RootKeyBlock, sizeof(KEY_BLOCK)); - RootKeyBlock->SubBlockSize=-sizeof(KEY_BLOCK); - RootKeyBlock->SubBlockId = REG_KEY_BLOCK_ID; - RootKeyBlock->Type = REG_ROOT_KEY_BLOCK_TYPE; - ZwQuerySystemTime((PTIME) &RootKeyBlock->LastWriteTime); - RootKeyBlock->ParentKeyOffset = 0; - RootKeyBlock->NumberOfSubKeys = 0; - RootKeyBlock->HashTableOffset = -1; - RootKeyBlock->NumberOfValues = 0; - RootKeyBlock->ValuesOffset = -1; - RootKeyBlock->SecurityKeyOffset = 0; - RootKeyBlock->ClassNameOffset = -1; - RootKeyBlock->NameSize = 0; - RootKeyBlock->ClassSize = 0; + assert(RootKeyCell); + RtlZeroMemory(RootKeyCell, sizeof(KEY_CELL)); + RootKeyCell->CellSize = -sizeof(KEY_CELL); + RootKeyCell->Id = REG_KEY_CELL_ID; + RootKeyCell->Type = REG_ROOT_KEY_CELL_TYPE; + ZwQuerySystemTime((PTIME) &RootKeyCell->LastWriteTime); + RootKeyCell->ParentKeyOffset = 0; + RootKeyCell->NumberOfSubKeys = 0; + RootKeyCell->HashTableOffset = -1; + RootKeyCell->NumberOfValues = 0; + RootKeyCell->ValuesOffset = -1; + RootKeyCell->SecurityKeyOffset = 0; + RootKeyCell->ClassNameOffset = -1; + RootKeyCell->NameSize = 0; + RootKeyCell->ClassSize = 0; } -NTSTATUS CmiCreateNewRegFile( HANDLE FileHandle ) + +VOID +CmiVerifyBinCell(PHBIN BinCell) { - NTSTATUS Status; - PHEADER_BLOCK HeaderBlock; - PHEAP_BLOCK HeapBlock; - PKEY_BLOCK RootKeyBlock; - PFREE_SUB_BLOCK FreeSubBlock; + if (CmiDoVerify) + { + + assert(BinCell); + + if (BinCell->BlockId != REG_BIN_ID) + { + DbgPrint("BlockId is %.08x (should be %.08x)\n", + BinCell->BlockId, REG_BIN_ID); + assert(BinCell->BlockId == REG_BIN_ID); + } + + //BinCell->DateModified.dwLowDateTime + + //BinCell->DateModified.dwHighDateTime + + if (BinCell->BlockSize != REG_BLOCK_SIZE) + { + DbgPrint("BlockSize is %.08x (should be %.08x)\n", + BinCell->BlockSize, REG_BLOCK_SIZE); + assert(BinCell->BlockSize == REG_BLOCK_SIZE); + } + + } +} + + +VOID +CmiVerifyKeyCell(PKEY_CELL KeyCell) +{ + if (CmiDoVerify) + { + + 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); + } + + if ((KeyCell->Type != REG_KEY_CELL_TYPE) + && (KeyCell->Type != REG_ROOT_KEY_CELL_TYPE)) + { + DbgPrint("Type is %.08x (should be %.08x or %.08x)\n", + KeyCell->Type, REG_KEY_CELL_TYPE, REG_ROOT_KEY_CELL_TYPE); + assert(FALSE); + } + + //KeyCell->LastWriteTime; + + if (KeyCell->ParentKeyOffset < 0) + { + DbgPrint("ParentKeyOffset is %d (must not be < 0)\n", + KeyCell->ParentKeyOffset); + assert(KeyCell->ParentKeyOffset >= 0); + } + + if (KeyCell->NumberOfSubKeys < 0) + { + DbgPrint("NumberOfSubKeys is %d (must not be < 0)\n", + KeyCell->NumberOfSubKeys); + assert(KeyCell->NumberOfSubKeys >= 0); + } + + //KeyCell->HashTableOffset; + + if (KeyCell->NumberOfValues < 0) + { + DbgPrint("NumberOfValues is %d (must not be < 0)\n", + KeyCell->NumberOfValues); + assert(KeyCell->NumberOfValues >= 0); + } + + //KeyCell->ValuesOffset = -1; + + if (KeyCell->SecurityKeyOffset < 0) + { + DbgPrint("SecurityKeyOffset is %d (must not be < 0)\n", + KeyCell->SecurityKeyOffset); + assert(KeyCell->SecurityKeyOffset >= 0); + } + + //KeyCell->ClassNameOffset = -1; + + //KeyCell->NameSize + + //KeyCell->ClassSize + + } +} + + +VOID +CmiVerifyRootKeyCell(PKEY_CELL RootKeyCell) +{ + if (CmiDoVerify) + { + + CmiVerifyKeyCell(RootKeyCell); + + if (RootKeyCell->Type != REG_ROOT_KEY_CELL_TYPE) + { + DbgPrint("Type is %.08x (should be %.08x)\n", + RootKeyCell->Type, REG_ROOT_KEY_CELL_TYPE); + assert(RootKeyCell->Type == REG_ROOT_KEY_CELL_TYPE); + } + + } +} + + +VOID +CmiVerifyValueCell(PVALUE_CELL ValueCell) +{ + if (CmiDoVerify) + { + + assert(ValueCell); + + if (ValueCell->CellSize == 0) + { + DbgPrint("CellSize is %d (must not be 0)\n", + ValueCell->CellSize); + assert(ValueCell->CellSize != 0); + } + + if (ValueCell->Id != REG_VALUE_CELL_ID) + { + DbgPrint("Id is %.08x (should be %.08x)\n", + ValueCell->Id, REG_VALUE_CELL_ID); + assert(ValueCell->Id == REG_VALUE_CELL_ID); + } + + //ValueCell->NameSize; + //ValueCell->LONG DataSize; + //ValueCell->DataOffset; + //ValueCell->ULONG DataType; + //ValueCell->USHORT Flags; + //ValueCell->USHORT Unused1; + //ValueCell->UCHAR Name[0]; + } +} + + +VOID +CmiVerifyValueListCell(PVALUE_LIST_CELL ValueListCell) +{ + if (CmiDoVerify) + { + + if (ValueListCell->CellSize == 0) + { + DbgPrint("CellSize is %d (must not be 0)\n", + ValueListCell->CellSize); + assert(ValueListCell->CellSize != 0); + } + + } +} + + +VOID +CmiVerifyKeyObject(PKEY_OBJECT KeyObject) +{ + if (CmiDoVerify) + { + + if (KeyObject->RegistryHive == NULL) + { + DbgPrint("RegistryHive is NULL (must not be NULL)\n", + KeyObject->RegistryHive); + assert(KeyObject->RegistryHive != NULL); + } + + if (KeyObject->KeyCell == NULL) + { + DbgPrint("KeyCell is NULL (must not be NULL)\n", + KeyObject->KeyCell); + assert(KeyObject->KeyCell != NULL); + } + + if (KeyObject->ParentKey == NULL) + { + DbgPrint("ParentKey is NULL (must not be NULL)\n", + KeyObject->ParentKey); + assert(KeyObject->ParentKey != NULL); + } + + } +} + + +VOID +CmiVerifyHiveHeader(PHIVE_HEADER Header) +{ + if (CmiDoVerify) + { + + if (Header->BlockId != 0x66676572) + { + DbgPrint("BlockId is %.08x (must be 66676572)\n", + Header->BlockId); + assert(Header->BlockId == 0x66676572); + } + + if (Header->Unused3 != 1) + { + DbgPrint("Unused3 is %.08x (must be 1)\n", + Header->Unused3); + assert(Header->Unused3 == 1); + } + + if (Header->Unused4 != 3) + { + DbgPrint("Unused4 is %.08x (must be 3)\n", + Header->Unused4); + assert(Header->Unused4 == 3); + } + + if (Header->Unused5 != 0) + { + DbgPrint("Unused5 is %.08x (must be 0)\n", + Header->Unused5); + assert(Header->Unused5 == 0); + } + + if (Header->Unused6 != 1) + { + DbgPrint("Unused6 is %.08x (must be 1)\n", + Header->Unused6); + assert(Header->Unused6 == 1); + } + + if (Header->Unused7 != 1) + { + DbgPrint("Unused7 is %.08x (must be 1)\n", + Header->Unused7); + assert(Header->Unused7 == 1); + } + + } +} + + +VOID +CmiVerifyRegistryHive(PREGISTRY_HIVE RegistryHive) +{ + if (CmiDoVerify) + { + + CmiVerifyHiveHeader(RegistryHive->HiveHeader); + + } +} + + +NTSTATUS +CmiPopulateHive(HANDLE FileHandle) +{ IO_STATUS_BLOCK IoStatusBlock; - char* tBuf; + LARGE_INTEGER FileOffset; + PCELL_HEADER FreeCell; + NTSTATUS Status; + PHBIN BinCell; + PCHAR tBuf; + ULONG i; - tBuf = (char*) ExAllocatePool(NonPagedPool, 2*REG_BLOCK_SIZE); - if( tBuf == NULL ) + tBuf = (PCHAR) ExAllocatePool(NonPagedPool, REG_BLOCK_SIZE); + if (tBuf == NULL) return STATUS_INSUFFICIENT_RESOURCES; - - HeaderBlock = (PHEADER_BLOCK)tBuf; - HeapBlock = (PHEAP_BLOCK) (tBuf+REG_BLOCK_SIZE); - RootKeyBlock = (PKEY_BLOCK) (tBuf+REG_BLOCK_SIZE+REG_HEAP_BLOCK_DATA_OFFSET); - FreeSubBlock = (PFREE_SUB_BLOCK) (tBuf+REG_BLOCK_SIZE+REG_HEAP_BLOCK_DATA_OFFSET+sizeof(KEY_BLOCK)); - - CmiCreateDefaultHeaderBlock(HeaderBlock); - CmiCreateDefaultHeapBlock(HeapBlock); - CmiCreateDefaultRootKeyBlock(RootKeyBlock); - - HeapBlock->BlockOffset = 0; //First block. - HeaderBlock->RootKeyBlock = REG_HEAP_BLOCK_DATA_OFFSET; //Offset to root key block. - //The rest of the block is free - FreeSubBlock->SubBlockSize = REG_BLOCK_SIZE-(REG_HEAP_BLOCK_DATA_OFFSET+sizeof(KEY_BLOCK)); - - Status = ZwWriteFile( FileHandle, NULL, NULL, NULL, - &IoStatusBlock, tBuf, 2*REG_BLOCK_SIZE, 0, NULL ); - - ExFreePool( tBuf ); + + BinCell = (PHBIN) tBuf; + FreeCell = (PCELL_HEADER) (tBuf + REG_HBIN_DATA_OFFSET); + + CmiCreateDefaultBinCell(BinCell); + + // The whole block is free + FreeCell->CellSize = REG_BLOCK_SIZE - REG_HBIN_DATA_OFFSET; + + // Add free blocks so we don't need to expand + // the file for a while + for (i = 0; i < 50; i++) + { + // Block offset of this bin + BinCell->BlockOffset = (2 + i) * REG_BLOCK_SIZE; + + FileOffset.u.HighPart = 0; + FileOffset.u.LowPart = (2 + i) * REG_BLOCK_SIZE; + + Status = ZwWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + tBuf, + REG_BLOCK_SIZE, + &FileOffset, + NULL); + assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status)); + if (!NT_SUCCESS(Status)) + { + ExFreePool(tBuf); + return Status; + } + } + + ExFreePool(tBuf); + return Status; } -PREGISTRY_FILE -CmiCreateRegistry(PWSTR Filename) -{ - PREGISTRY_FILE RegistryFile; - HANDLE FileHandle; - PKEY_BLOCK RootKeyBlock; - PHEAP_BLOCK tmpHeap; - LARGE_INTEGER fileOffset; - PFREE_SUB_BLOCK FreeBlock; - DWORD FreeOffset; - int i, j; - BLOCK_OFFSET BlockOffset; -DPRINT("CmiCreateRegistry() Filename '%S'\n", Filename); - RegistryFile = ExAllocatePool(NonPagedPool, sizeof(REGISTRY_FILE)); - - if (RegistryFile == NULL) - return NULL; - - if (Filename != NULL) - { - UNICODE_STRING TmpFileName; - OBJECT_ATTRIBUTES ObjectAttributes; - NTSTATUS Status; - FILE_STANDARD_INFORMATION fsi; - IO_STATUS_BLOCK IoSB; - - /* Duplicate Filename */ - RegistryFile->Filename = ExAllocatePool(NonPagedPool, MAX_PATH); - wcscpy(RegistryFile->Filename , Filename); - - RtlInitUnicodeString (&TmpFileName, Filename); - InitializeObjectAttributes(&ObjectAttributes, - &TmpFileName, - 0, - NULL, - NULL); - - Status = NtCreateFile( &FileHandle, - FILE_ALL_ACCESS, - &ObjectAttributes, - &IoSB, - NULL, - FILE_ATTRIBUTE_NORMAL, - 0, - FILE_OPEN_IF, - FILE_NON_DIRECTORY_FILE, - NULL, - 0 ); - - /* FIXME: create directory if IoSB.Status == STATUS_OBJECT_PATH_NOT_FOUND */ - if( !NT_SUCCESS(Status) ) - { - ExFreePool(RegistryFile->Filename); - RegistryFile->Filename = NULL; - return NULL; - } - /*if file did not exist*/ - if( IoSB.Information == FILE_CREATED ){ - Status = CmiCreateNewRegFile( FileHandle ); - if( !NT_SUCCESS(Status) ) - { - ExFreePool(RegistryFile->Filename); - RegistryFile->Filename = NULL; - return NULL; - } - } - - RegistryFile->HeaderBlock = (PHEADER_BLOCK) - ExAllocatePool(NonPagedPool, sizeof(HEADER_BLOCK)); - - fileOffset.u.HighPart = 0; - fileOffset.u.LowPart = 0; - Status = ZwReadFile(FileHandle, - 0, 0, 0, 0, - RegistryFile->HeaderBlock, - sizeof(HEADER_BLOCK), - &fileOffset, 0); - if (!NT_SUCCESS(Status)) - { - ExFreePool(RegistryFile->Filename); - RegistryFile->Filename = NULL; - return NULL; - } - - Status = ZwQueryInformationFile(FileHandle,&IoSB,&fsi - ,sizeof(fsi),FileStandardInformation); - if (!NT_SUCCESS(Status)) - { - ExFreePool(RegistryFile->Filename); - RegistryFile->Filename = NULL; - return NULL; - } - RegistryFile->FileSize = fsi.EndOfFile.u.LowPart; - RegistryFile->BlockListSize = RegistryFile->FileSize / 4096 -1; -// RegistryFile->NumberOfBlocks = RegistryFile->BlockListSize; - RegistryFile->BlockList = ExAllocatePool(NonPagedPool, - sizeof(PHEAP_BLOCK *) * (RegistryFile->BlockListSize )); - BlockOffset=0; - fileOffset.u.HighPart = 0; - fileOffset.u.LowPart = 4096; - RegistryFile->BlockList [0] - = ExAllocatePool(NonPagedPool,RegistryFile->FileSize-4096); - if (RegistryFile->BlockList[0] == NULL) - { -// Status = STATUS_INSUFFICIENT_RESOURCES; - DPRINT("error allocating %d bytes for registry\n" - ,RegistryFile->FileSize-4096); - ZwClose(FileHandle); - return NULL; - } - Status = ZwReadFile(FileHandle, - 0, 0, 0, 0, - RegistryFile->BlockList [0], - RegistryFile->FileSize-4096, - &fileOffset, 0); - ZwClose(FileHandle); - if (!NT_SUCCESS(Status)) - { - DPRINT("error %x reading registry file at offset %x\n" - ,Status,fileOffset.u.LowPart); - return NULL; - } - RegistryFile->FreeListSize = 0; - RegistryFile->FreeListMax = 0; - RegistryFile->FreeList = NULL; - for(i=0 ; i BlockListSize; i++) - { - tmpHeap = (PHEAP_BLOCK)(((char *)RegistryFile->BlockList [0])+BlockOffset); - if (tmpHeap->BlockId != REG_HEAP_ID ) - { - DPRINT("bad BlockId %x,offset %x\n",tmpHeap->BlockId,fileOffset.u.LowPart); - } - RegistryFile->BlockList [i] - = tmpHeap; - if (tmpHeap->BlockSize >4096) - { - for(j=1;jBlockSize/4096;j++) - RegistryFile->BlockList[i+j] = RegistryFile->BlockList[i]; - i = i+j-1; - } - /* search free blocks and add to list */ - FreeOffset=REG_HEAP_BLOCK_DATA_OFFSET; - while(FreeOffset < tmpHeap->BlockSize) - { - FreeBlock = (PFREE_SUB_BLOCK)((char *)RegistryFile->BlockList[i] - +FreeOffset); - if ( FreeBlock->SubBlockSize>0) - { - CmiAddFree(RegistryFile,FreeBlock - ,RegistryFile->BlockList[i]->BlockOffset+FreeOffset); - FreeOffset += FreeBlock->SubBlockSize; - } - else - FreeOffset -= FreeBlock->SubBlockSize; - } - BlockOffset += tmpHeap->BlockSize; - } - Status = ObReferenceObjectByHandle(FileHandle, - FILE_ALL_ACCESS, - IoFileObjectType, - UserMode, - (PVOID*)&RegistryFile->FileObject, - NULL); - } - else - { - RegistryFile->Filename = NULL; - RegistryFile->FileObject = NULL; - - RegistryFile->HeaderBlock = (PHEADER_BLOCK) - ExAllocatePool(NonPagedPool, sizeof(HEADER_BLOCK)); - CmiCreateDefaultHeaderBlock(RegistryFile->HeaderBlock); - - RootKeyBlock = (PKEY_BLOCK) ExAllocatePool(NonPagedPool, sizeof(KEY_BLOCK)); - CmiCreateDefaultRootKeyBlock(RootKeyBlock); - - RegistryFile->HeaderBlock->RootKeyBlock = (BLOCK_OFFSET) RootKeyBlock; - } - KeInitializeSemaphore(&RegistryFile->RegSem, 1, 1); - - return RegistryFile; -} - -ULONG -CmiGetMaxNameLength(PREGISTRY_FILE RegistryFile, - PKEY_BLOCK KeyBlock) -{ - ULONG Idx, MaxName; - PHASH_TABLE_BLOCK HashBlock; - PKEY_BLOCK CurSubKeyBlock; - - MaxName = 0; - HashBlock = CmiGetBlock(RegistryFile, KeyBlock->HashTableOffset,NULL); - if (HashBlock == 0) - { - return 0; - } - for (Idx = 0; Idx < HashBlock->HashTableSize; Idx++) - { - if (HashBlock->Table[Idx].KeyOffset != 0) - { - CurSubKeyBlock = CmiGetBlock(RegistryFile, - HashBlock->Table[Idx].KeyOffset,NULL); - if (MaxName < CurSubKeyBlock->NameSize) - { - MaxName = CurSubKeyBlock->NameSize; - } - CmiReleaseBlock(RegistryFile, CurSubKeyBlock); - } - } - - CmiReleaseBlock(RegistryFile, HashBlock); - - return MaxName; -} - -ULONG -CmiGetMaxClassLength(PREGISTRY_FILE RegistryFile, - PKEY_BLOCK KeyBlock) -{ - ULONG Idx, MaxClass; - PHASH_TABLE_BLOCK HashBlock; - PKEY_BLOCK CurSubKeyBlock; - - MaxClass = 0; - HashBlock = CmiGetBlock(RegistryFile, KeyBlock->HashTableOffset,NULL); - if (HashBlock == 0) - { - return 0; - } - for (Idx = 0; Idx < HashBlock->HashTableSize; Idx++) - { - if (HashBlock->Table[Idx].KeyOffset != 0) - { - CurSubKeyBlock = CmiGetBlock(RegistryFile, - HashBlock->Table[Idx].KeyOffset,NULL); - if (MaxClass < CurSubKeyBlock->ClassSize) - { - MaxClass = CurSubKeyBlock->ClassSize; - } - CmiReleaseBlock(RegistryFile, CurSubKeyBlock); - } - } - - CmiReleaseBlock(RegistryFile, HashBlock); - - return MaxClass; -} - -ULONG -CmiGetMaxValueNameLength(PREGISTRY_FILE RegistryFile, - PKEY_BLOCK KeyBlock) -{ - ULONG Idx, MaxValueName; - PVALUE_LIST_BLOCK ValueListBlock; - PVALUE_BLOCK CurValueBlock; - - ValueListBlock = CmiGetBlock(RegistryFile, - KeyBlock->ValuesOffset,NULL); - MaxValueName = 0; - if (ValueListBlock == 0) - { - return 0; - } - for (Idx = 0; Idx < KeyBlock->NumberOfValues; Idx++) - { - CurValueBlock = CmiGetBlock(RegistryFile, - ValueListBlock->Values[Idx],NULL); - if (CurValueBlock != NULL && - MaxValueName < CurValueBlock->NameSize) - { - MaxValueName = CurValueBlock->NameSize; - } - CmiReleaseBlock(RegistryFile, CurValueBlock); - } - - CmiReleaseBlock(RegistryFile, ValueListBlock); - - return MaxValueName; -} - -ULONG -CmiGetMaxValueDataLength(PREGISTRY_FILE RegistryFile, - PKEY_BLOCK KeyBlock) -{ - ULONG Idx, MaxValueData; - PVALUE_LIST_BLOCK ValueListBlock; - PVALUE_BLOCK CurValueBlock; - - ValueListBlock = CmiGetBlock(RegistryFile, - KeyBlock->ValuesOffset,NULL); - MaxValueData = 0; - if (ValueListBlock == 0) - { - return 0; - } - for (Idx = 0; Idx < KeyBlock->NumberOfValues; Idx++) - { - CurValueBlock = CmiGetBlock(RegistryFile, - ValueListBlock->Values[Idx],NULL); - if (CurValueBlock != NULL && - MaxValueData < (CurValueBlock->DataSize & LONG_MAX) ) - { - MaxValueData = CurValueBlock->DataSize & LONG_MAX; - } - CmiReleaseBlock(RegistryFile, CurValueBlock); - } - - CmiReleaseBlock(RegistryFile, ValueListBlock); - - return MaxValueData; -} NTSTATUS -CmiScanForSubKey(IN PREGISTRY_FILE RegistryFile, - IN PKEY_BLOCK KeyBlock, - OUT PKEY_BLOCK *SubKeyBlock, - OUT BLOCK_OFFSET *BlockOffset, - IN PCHAR KeyName, - IN ACCESS_MASK DesiredAccess, - IN ULONG Attributes) +CmiCreateNewRegFile(HANDLE FileHandle) { - ULONG Idx; - PHASH_TABLE_BLOCK HashBlock; - PKEY_BLOCK CurSubKeyBlock; - WORD KeyLength = strlen(KeyName); + IO_STATUS_BLOCK IoStatusBlock; + PCELL_HEADER FreeCell; + PHIVE_HEADER HiveHeader; + PKEY_CELL RootKeyCell; + NTSTATUS Status; + PHBIN BinCell; + PCHAR tBuf; + + tBuf = (PCHAR) ExAllocatePool(NonPagedPool, 2 * REG_BLOCK_SIZE); + if (tBuf == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + + HiveHeader = (PHIVE_HEADER) tBuf; + BinCell = (PHBIN) ((ULONG_PTR) tBuf + REG_BLOCK_SIZE); + RootKeyCell = (PKEY_CELL) ((ULONG_PTR) tBuf + REG_BLOCK_SIZE + REG_HBIN_DATA_OFFSET); + FreeCell = (PCELL_HEADER) ((ULONG_PTR) tBuf + REG_BLOCK_SIZE + REG_HBIN_DATA_OFFSET + sizeof(KEY_CELL)); - HashBlock = CmiGetBlock(RegistryFile, KeyBlock->HashTableOffset,NULL); - *SubKeyBlock = NULL; + CmiCreateDefaultHiveHeader(HiveHeader); + CmiCreateDefaultBinCell(BinCell); + CmiCreateDefaultRootKeyCell(RootKeyCell); + + // First block + BinCell->BlockOffset = 0; + + // Offset to root key block + HiveHeader->RootKeyCell = 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, + tBuf, + 2 * REG_BLOCK_SIZE, + 0, + NULL); + + ExFreePool(tBuf); + + assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status)); + +#if 1 + if (NT_SUCCESS(Status)) + { + CmiPopulateHive(FileHandle); + } +#endif + + return Status; +} + + +NTSTATUS +CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive, + PWSTR Filename, + BOOLEAN CreateNew) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + FILE_STANDARD_INFORMATION fsi; + PCELL_HEADER FreeBlock; + LARGE_INTEGER FileOffset; + BLOCK_OFFSET BlockOffset; + ULONG CreateDisposition; + IO_STATUS_BLOCK IoSB; + HANDLE FileHandle; + DWORD FreeOffset; + NTSTATUS Status; + //BOOLEAN Success; + PHBIN tmpBin; + ULONG i, j; + + /* Duplicate Filename */ + Status = RtlCreateUnicodeString(&RegistryHive->Filename, Filename); + if (!NT_SUCCESS(Status)) + return Status; + + InitializeObjectAttributes(&ObjectAttributes, + &RegistryHive->Filename, + 0, + NULL, + NULL); + + if (CreateNew) + CreateDisposition = FILE_OPEN_IF; + else + CreateDisposition = FILE_OPEN; + + Status = NtCreateFile(&FileHandle, + FILE_ALL_ACCESS, + &ObjectAttributes, + &IoSB, + NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + CreateDisposition, + FILE_NON_DIRECTORY_FILE, + NULL, + 0); + + if ((CreateNew) && (IoSB.Information == FILE_CREATED)) + { + Status = CmiCreateNewRegFile(FileHandle); + } + + if (!NT_SUCCESS(Status)) + { + RtlFreeUnicodeString(&RegistryHive->Filename); + return Status; + } + + Status = ObReferenceObjectByHandle(FileHandle, + FILE_ALL_ACCESS, + IoFileObjectType, + UserMode, + (PVOID*) &RegistryHive->FileObject, + NULL); + + assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status)); + + if (!NT_SUCCESS(Status)) + { + ZwClose(FileHandle); + RtlFreeUnicodeString(&RegistryHive->Filename); + return Status; + } + + FileOffset.u.HighPart = 0; + FileOffset.u.LowPart = 0; + Status = ZwReadFile(FileHandle, + 0, + 0, + 0, + 0, + RegistryHive->HiveHeader, + sizeof(HIVE_HEADER), + &FileOffset, + 0); + + assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status)); + + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(RegistryHive->FileObject); + RtlFreeUnicodeString(&RegistryHive->Filename); + return Status; + } + + Status = ZwQueryInformationFile(FileHandle, + &IoSB, + &fsi, + sizeof(fsi), + FileStandardInformation); + + assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status)); + + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(RegistryHive->FileObject); + RtlFreeUnicodeString(&RegistryHive->Filename); + return Status; + } +#if 0 + /* We have a reference to the file object so we don't need the handle anymore */ + ZwClose(FileHandle); +#endif + + RegistryHive->FileSize = fsi.EndOfFile.u.LowPart; + RegistryHive->BlockListSize = (RegistryHive->FileSize / 4096) - 1; + + DPRINT("Space needed for block list describing hive: 0x%x\n", + sizeof(PHBIN *) * RegistryHive->BlockListSize); + + RegistryHive->BlockList = ExAllocatePool(NonPagedPool, + sizeof(PHBIN *) * RegistryHive->BlockListSize); + + if (RegistryHive->BlockList == NULL) + { + ExFreePool(RegistryHive->BlockList); + ObDereferenceObject(RegistryHive->FileObject); + RtlFreeUnicodeString(&RegistryHive->Filename); + return STATUS_INSUFFICIENT_RESOURCES; + } + +#if 0 + /* Map hive into cache memory (readonly) (skip the base block) */ + FileOffset.u.HighPart = 0; + FileOffset.u.LowPart = 4096; + Success = CcMapData(RegistryHive->FileObject, /* File object */ + &FileOffset, /* File offset */ + RegistryHive->FileSize - 4096, /* Region length */ + TRUE, /* Wait if needed */ + &RegistryHive->Bcb, /* OUT: Buffer Control Block */ + (PVOID*) &RegistryHive->BlockList[0]); /* OUT: Mapped data pointer */ + + assertmsg(Success, ("Success: %d\n", Success)); + + if (!Success) + { + ExFreePool(RegistryHive->BlockList); + ObDereferenceObject(RegistryHive->FileObject); + RtlFreeUnicodeString(&RegistryHive->Filename); + return Status; + } + +#else + + RegistryHive->BlockList[0] = ExAllocatePool(PagedPool, + RegistryHive->FileSize - 4096); + + if (RegistryHive->BlockList == NULL) + { + ExFreePool(RegistryHive->BlockList); + ObDereferenceObject(RegistryHive->FileObject); + RtlFreeUnicodeString(&RegistryHive->Filename); + return STATUS_INSUFFICIENT_RESOURCES; + } + + FileOffset.u.HighPart = 0; + FileOffset.u.LowPart = 4096; + Status = ZwReadFile(FileHandle, + 0, + 0, + 0, + 0, + (PVOID) RegistryHive->BlockList[0], + RegistryHive->FileSize - 4096, + &FileOffset, + 0); + + assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status)); + +#endif + + RegistryHive->FreeListSize = 0; + RegistryHive->FreeListMax = 0; + RegistryHive->FreeList = NULL; + + BlockOffset = 0; + for (i = 0; i < RegistryHive->BlockListSize; i++) + { + RegistryHive->BlockList[i] = (PHBIN) (((ULONG_PTR) RegistryHive->BlockList[0]) + BlockOffset); + tmpBin = (PHBIN) (((ULONG_PTR) RegistryHive->BlockList[i])); + if (tmpBin->BlockId != REG_BIN_ID) + { + DPRINT("Bad BlockId %x, offset %x\n", tmpBin->BlockId, BlockOffset); + KeBugCheck(0); + } + + assertmsg((tmpBin->BlockSize % 4096) == 0, ("BlockSize (0x%.08x) must be multiplum of 4K\n", tmpBin->BlockSize)); + + if (tmpBin->BlockSize > 4096) + { + for (j = 1; j < tmpBin->BlockSize / 4096; j++) + { + RegistryHive->BlockList[i + j] = RegistryHive->BlockList[i]; + } + i = i + j - 1; + } + + /* Search free blocks and add to list */ + FreeOffset = REG_HBIN_DATA_OFFSET; + while (FreeOffset < tmpBin->BlockSize) + { + FreeBlock = (PCELL_HEADER) ((ULONG_PTR) RegistryHive->BlockList[i] + FreeOffset); + if (FreeBlock->CellSize > 0) + { + Status = CmiAddFree(RegistryHive, + FreeBlock, + RegistryHive->BlockList[i]->BlockOffset + FreeOffset); + + if (!NT_SUCCESS(Status)) + { + /* FIXME: */ + assert(FALSE); + } + + FreeOffset += FreeBlock->CellSize; + } + else + { + FreeOffset -= FreeBlock->CellSize; + } + } + BlockOffset += tmpBin->BlockSize; + } + + return STATUS_SUCCESS; +} + + +NTSTATUS +CmiInitVolatileRegistryHive(PREGISTRY_HIVE RegistryHive) +{ + PKEY_CELL RootKeyCell; + + RegistryHive->Flags |= HIVE_VOLATILE; + + CmiCreateDefaultHiveHeader(RegistryHive->HiveHeader); + + RootKeyCell = (PKEY_CELL) ExAllocatePool(NonPagedPool, sizeof(KEY_CELL)); + + if (RootKeyCell == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + + CmiCreateDefaultRootKeyCell(RootKeyCell); + + RegistryHive->HiveHeader->RootKeyCell = (BLOCK_OFFSET) RootKeyCell; + + return STATUS_SUCCESS; +} + + +PREGISTRY_HIVE +CmiCreateRegistryHive(PWSTR Filename, + BOOLEAN CreateNew) +{ + PREGISTRY_HIVE RegistryHive; + NTSTATUS Status; + + DPRINT("Filename %S\n", Filename); + + RegistryHive = ExAllocatePool(NonPagedPool, sizeof(REGISTRY_HIVE)); + if (RegistryHive == NULL) + return NULL; + + DPRINT("RegistryHive %x\n", RegistryHive); + + RtlZeroMemory(RegistryHive, sizeof(REGISTRY_HIVE)); + + RegistryHive->HiveHeader = (PHIVE_HEADER) + ExAllocatePool(NonPagedPool, sizeof(HIVE_HEADER)); + + if (RegistryHive->HiveHeader == NULL) + { + ExFreePool(RegistryHive); + return NULL; + } + + if (Filename != NULL) + { + Status = CmiInitPermanentRegistryHive(RegistryHive, Filename, CreateNew); + } + else + { + Status = CmiInitVolatileRegistryHive(RegistryHive); + } + + if (NT_SUCCESS(Status)) + { + KeInitializeSemaphore(&RegistryHive->RegSem, 1, 1); + + VERIFY_REGISTRY_HIVE(RegistryHive); + } + else + { + ExFreePool(RegistryHive->HiveHeader); + ExFreePool(RegistryHive); + RegistryHive = NULL; + } + + return RegistryHive; +} + + +ULONG +CmiGetMaxNameLength(PREGISTRY_HIVE RegistryHive, + PKEY_CELL KeyCell) +{ + PHASH_TABLE_CELL HashBlock; + PKEY_CELL CurSubKeyCell; + ULONG MaxName; + ULONG i; + + VERIFY_KEY_CELL(KeyCell); + + MaxName = 0; + HashBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL); if (HashBlock == NULL) { - return STATUS_SUCCESS; + return 0; } -// for (Idx = 0; Idx < HashBlock->HashTableSize; Idx++) - for (Idx = 0; Idx < KeyBlock->NumberOfSubKeys - && Idx < HashBlock->HashTableSize; Idx++) + + for (i = 0; i < HashBlock->HashTableSize; i++) + { + if (HashBlock->Table[i].KeyOffset != 0) + { + CurSubKeyCell = CmiGetBlock(RegistryHive, + HashBlock->Table[i].KeyOffset, + NULL); + if (MaxName < CurSubKeyCell->NameSize) + { + MaxName = CurSubKeyCell->NameSize; + } + CmiReleaseBlock(RegistryHive, CurSubKeyCell); + } + } + + CmiReleaseBlock(RegistryHive, HashBlock); + + return MaxName; +} + + +ULONG +CmiGetMaxClassLength(PREGISTRY_HIVE RegistryHive, + PKEY_CELL KeyCell) +{ + PHASH_TABLE_CELL HashBlock; + PKEY_CELL CurSubKeyCell; + ULONG MaxClass; + ULONG i; + + VERIFY_KEY_CELL(KeyCell); + + MaxClass = 0; + HashBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL); + if (HashBlock == NULL) + { + return 0; + } + + for (i = 0; i < HashBlock->HashTableSize; i++) + { + if (HashBlock->Table[i].KeyOffset != 0) + { + CurSubKeyCell = CmiGetBlock(RegistryHive, + HashBlock->Table[i].KeyOffset, + NULL); + if (MaxClass < CurSubKeyCell->ClassSize) + { + MaxClass = CurSubKeyCell->ClassSize; + } + CmiReleaseBlock(RegistryHive, CurSubKeyCell); + } + } + + CmiReleaseBlock(RegistryHive, HashBlock); + + return MaxClass; +} + + +ULONG +CmiGetMaxValueNameLength(PREGISTRY_HIVE RegistryHive, + PKEY_CELL KeyCell) +{ + PVALUE_LIST_CELL ValueListCell; + PVALUE_CELL CurValueCell; + ULONG MaxValueName; + ULONG i; + + VERIFY_KEY_CELL(KeyCell); + + ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL); + MaxValueName = 0; + if (ValueListCell == NULL) + { + return 0; + } + + for (i = 0; i < KeyCell->NumberOfValues; i++) + { + CurValueCell = CmiGetBlock(RegistryHive, + ValueListCell->Values[i], + NULL); + if (CurValueCell != NULL && + MaxValueName < CurValueCell->NameSize) + { + MaxValueName = CurValueCell->NameSize; + } + CmiReleaseBlock(RegistryHive, CurValueCell); + } + + CmiReleaseBlock(RegistryHive, ValueListCell); + + return MaxValueName; +} + + +ULONG +CmiGetMaxValueDataLength(PREGISTRY_HIVE RegistryHive, + PKEY_CELL KeyCell) +{ + PVALUE_LIST_CELL ValueListCell; + PVALUE_CELL CurValueCell; + ULONG MaxValueData; + ULONG i; + + VERIFY_KEY_CELL(KeyCell); + + ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL); + MaxValueData = 0; + if (ValueListCell == NULL) + { + return 0; + } + + for (i = 0; i < KeyCell->NumberOfValues; i++) + { + CurValueCell = CmiGetBlock(RegistryHive, + ValueListCell->Values[i],NULL); + if ((CurValueCell != NULL) && + (MaxValueData < (CurValueCell->DataSize & LONG_MAX))) + { + MaxValueData = CurValueCell->DataSize & LONG_MAX; + } + CmiReleaseBlock(RegistryHive, CurValueCell); + } + + CmiReleaseBlock(RegistryHive, ValueListCell); + + return MaxValueData; +} + + +NTSTATUS +CmiScanForSubKey(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell, + OUT PKEY_CELL *SubKeyCell, + OUT BLOCK_OFFSET *BlockOffset, + IN PCHAR KeyName, + IN ACCESS_MASK DesiredAccess, + IN ULONG Attributes) +{ + PHASH_TABLE_CELL HashBlock; + PKEY_CELL CurSubKeyCell; + WORD KeyLength; + ULONG i; + + VERIFY_KEY_CELL(KeyCell); + + DPRINT("Scanning for sub key %s\n", KeyName); + + assert(RegistryHive); + + KeyLength = strlen(KeyName); + + HashBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL); + *SubKeyCell = NULL; + if (HashBlock == NULL) + { + return STATUS_SUCCESS; + } + + for (i = 0; (i < KeyCell->NumberOfSubKeys) + && (i < HashBlock->HashTableSize); i++) { if (Attributes & OBJ_CASE_INSENSITIVE) { - if (HashBlock->Table[Idx].KeyOffset != 0 && - HashBlock->Table[Idx].KeyOffset != -1 && - !_strnicmp(KeyName, (PCHAR) &HashBlock->Table[Idx].HashValue, 4)) + if ((HashBlock->Table[i].KeyOffset != 0) && + (HashBlock->Table[i].KeyOffset != -1) && + (_strnicmp(KeyName, (PCHAR) &HashBlock->Table[i].HashValue, 4) == 0)) { - CurSubKeyBlock = CmiGetBlock(RegistryFile, - HashBlock->Table[Idx].KeyOffset,NULL); - if ( CurSubKeyBlock->NameSize == KeyLength - && !_strnicmp(KeyName, CurSubKeyBlock->Name, KeyLength)) + CurSubKeyCell = CmiGetBlock(RegistryHive, + HashBlock->Table[i].KeyOffset, + NULL); + if ((CurSubKeyCell->NameSize == KeyLength) + && (_strnicmp(KeyName, CurSubKeyCell->Name, KeyLength) == 0)) { - *SubKeyBlock = CurSubKeyBlock; - *BlockOffset = HashBlock->Table[Idx].KeyOffset; + *SubKeyCell = CurSubKeyCell; + *BlockOffset = HashBlock->Table[i].KeyOffset; break; } else { - CmiReleaseBlock(RegistryFile, CurSubKeyBlock); + CmiReleaseBlock(RegistryHive, CurSubKeyCell); } } } else { - if (HashBlock->Table[Idx].KeyOffset != 0 && - HashBlock->Table[Idx].KeyOffset != -1 && - !strncmp(KeyName, (PCHAR) &HashBlock->Table[Idx].HashValue, 4)) + if (HashBlock->Table[i].KeyOffset != 0 && + HashBlock->Table[i].KeyOffset != -1 && + !strncmp(KeyName, (PCHAR) &HashBlock->Table[i].HashValue, 4)) { - CurSubKeyBlock = CmiGetBlock(RegistryFile, - HashBlock->Table[Idx].KeyOffset,NULL); - if ( CurSubKeyBlock->NameSize == KeyLength - && !_strnicmp(KeyName, CurSubKeyBlock->Name, KeyLength)) + CurSubKeyCell = CmiGetBlock(RegistryHive, + HashBlock->Table[i].KeyOffset,NULL); + if (CurSubKeyCell->NameSize == KeyLength + && !_strnicmp(KeyName, CurSubKeyCell->Name, KeyLength)) { - *SubKeyBlock = CurSubKeyBlock; - *BlockOffset = HashBlock->Table[Idx].KeyOffset; + *SubKeyCell = CurSubKeyCell; + *BlockOffset = HashBlock->Table[i].KeyOffset; break; } else { - CmiReleaseBlock(RegistryFile, CurSubKeyBlock); + CmiReleaseBlock(RegistryHive, CurSubKeyCell); } } } } - CmiReleaseBlock(RegistryFile, HashBlock); + CmiReleaseBlock(RegistryHive, HashBlock); - return STATUS_SUCCESS; + return STATUS_SUCCESS; } + NTSTATUS -CmiAddSubKey(PREGISTRY_FILE RegistryFile, - PKEY_OBJECT Parent, - PKEY_OBJECT SubKey, - PWSTR NewSubKeyName, - USHORT NewSubKeyNameSize, - ULONG TitleIndex, - PUNICODE_STRING Class, - ULONG CreateOptions) +CmiAddSubKey(PREGISTRY_HIVE RegistryHive, + PKEY_OBJECT Parent, + PKEY_OBJECT SubKey, + PWSTR NewSubKeyName, + USHORT NewSubKeyNameSize, + ULONG TitleIndex, + PUNICODE_STRING Class, + ULONG CreateOptions) { - PKEY_BLOCK KeyBlock = Parent->KeyBlock; - NTSTATUS Status; - PHASH_TABLE_BLOCK HashBlock, NewHashBlock; - PKEY_BLOCK NewKeyBlock; + PHASH_TABLE_CELL NewHashBlock; + PHASH_TABLE_CELL HashBlock; BLOCK_OFFSET NKBOffset; - ULONG NewBlockSize; + PKEY_CELL NewKeyCell; + ULONG NewBlockSize; + PKEY_CELL KeyCell; + NTSTATUS Status; USHORT NameSize; + KeyCell = Parent->KeyCell; + + VERIFY_KEY_CELL(KeyCell); + if (NewSubKeyName[0] == L'\\') - { - NewSubKeyName++; - NameSize = NewSubKeyNameSize/2-1; - } + { + NewSubKeyName++; + NameSize = NewSubKeyNameSize / 2 - 1; + } else - NameSize = NewSubKeyNameSize/2; + { + NameSize = NewSubKeyNameSize / 2; + } Status = STATUS_SUCCESS; - NewBlockSize = sizeof(KEY_BLOCK) + NameSize; - Status = CmiAllocateBlock(RegistryFile, (PVOID) &NewKeyBlock - , NewBlockSize,&NKBOffset); - if (NewKeyBlock == NULL) - { - Status = STATUS_INSUFFICIENT_RESOURCES; - } + NewBlockSize = sizeof(KEY_CELL) + NameSize; + Status = CmiAllocateBlock(RegistryHive, + (PVOID) &NewKeyCell, + NewBlockSize, + &NKBOffset); + + if (NewKeyCell == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } else - { - NewKeyBlock->SubBlockId = REG_KEY_BLOCK_ID; - NewKeyBlock->Type = REG_KEY_BLOCK_TYPE; - ZwQuerySystemTime((PTIME) &NewKeyBlock->LastWriteTime); - NewKeyBlock->ParentKeyOffset = -1; - NewKeyBlock->NumberOfSubKeys = 0; - NewKeyBlock->HashTableOffset = -1; - NewKeyBlock->NumberOfValues = 0; - NewKeyBlock->ValuesOffset = -1; - NewKeyBlock->SecurityKeyOffset = -1; - NewKeyBlock->NameSize = NameSize; - wcstombs(NewKeyBlock->Name,NewSubKeyName,NameSize); - NewKeyBlock->ClassNameOffset = -1; - if (Class) - { - PDATA_BLOCK pClass; - NewKeyBlock->ClassSize = Class->Length+sizeof(WCHAR); - Status = CmiAllocateBlock(RegistryFile - ,(PVOID)&pClass - ,NewKeyBlock->ClassSize - ,&NewKeyBlock->ClassNameOffset ); - wcsncpy((PWSTR)pClass->Data,Class->Buffer,Class->Length); - ( (PWSTR)(pClass->Data))[Class->Length]=0; + { + NewKeyCell->Id = REG_KEY_CELL_ID; + NewKeyCell->Type = REG_KEY_CELL_TYPE; + ZwQuerySystemTime((PTIME) &NewKeyCell->LastWriteTime); + NewKeyCell->ParentKeyOffset = -1; + NewKeyCell->NumberOfSubKeys = 0; + NewKeyCell->HashTableOffset = -1; + NewKeyCell->NumberOfValues = 0; + NewKeyCell->ValuesOffset = -1; + NewKeyCell->SecurityKeyOffset = -1; + NewKeyCell->NameSize = NameSize; + wcstombs(NewKeyCell->Name, NewSubKeyName, NameSize); + NewKeyCell->ClassNameOffset = -1; + + VERIFY_KEY_CELL(NewKeyCell); + + if (Class) + { + PDATA_CELL pClass; + + NewKeyCell->ClassSize = Class->Length + sizeof(WCHAR); + Status = CmiAllocateBlock(RegistryHive, + (PVOID) &pClass, + NewKeyCell->ClassSize, + &NewKeyCell->ClassNameOffset); + wcsncpy((PWSTR) pClass->Data, Class->Buffer, Class->Length); + ((PWSTR) (pClass->Data))[Class->Length] = 0; + } } - } if (!NT_SUCCESS(Status)) { - return Status; + return Status; } - SubKey->KeyBlock = NewKeyBlock; + + SubKey->KeyCell = NewKeyCell; SubKey->BlockOffset = NKBOffset; - /* don't modify hash table if key is volatile and parent is not */ - if (RegistryFile == CmiVolatileFile && Parent->RegistryFile != RegistryFile) - { - return Status; - } - if (KeyBlock->HashTableOffset == -1) + + /* Don't modify hash table if key is volatile and parent is not */ + if (IsVolatileHive(RegistryHive) && (!IsVolatileHive(Parent->RegistryHive))) + { + return Status; + } + + if (KeyCell->HashTableOffset == -1) { - Status = CmiAllocateHashTableBlock(RegistryFile, - &HashBlock, - &KeyBlock->HashTableOffset, - REG_INIT_HASH_TABLE_SIZE); + Status = CmiAllocateHashTableBlock(RegistryHive, + &HashBlock, + &KeyCell->HashTableOffset, + REG_INIT_HASH_TABLE_SIZE); + if (!NT_SUCCESS(Status)) { - return Status; + return Status; } } else { - HashBlock = CmiGetBlock(RegistryFile, KeyBlock->HashTableOffset,NULL); - if (KeyBlock->NumberOfSubKeys + 1 >= HashBlock->HashTableSize) + HashBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL); + if (((KeyCell->NumberOfSubKeys + 1) >= HashBlock->HashTableSize)) { - BLOCK_OFFSET HTOffset; + BLOCK_OFFSET HTOffset; + + /* Reallocate the hash table block */ + Status = CmiAllocateHashTableBlock(RegistryHive, + &NewHashBlock, + &HTOffset, + HashBlock->HashTableSize + + REG_EXTEND_HASH_TABLE_SIZE); - /* Reallocate the hash table block */ - Status = CmiAllocateHashTableBlock(RegistryFile, - &NewHashBlock, - &HTOffset, - HashBlock->HashTableSize + - REG_EXTEND_HASH_TABLE_SIZE); if (!NT_SUCCESS(Status)) { - return Status; + return Status; } + RtlZeroMemory(&NewHashBlock->Table[0], - sizeof(NewHashBlock->Table[0]) * NewHashBlock->HashTableSize); + sizeof(NewHashBlock->Table[0]) * NewHashBlock->HashTableSize); RtlCopyMemory(&NewHashBlock->Table[0], - &HashBlock->Table[0], - sizeof(NewHashBlock->Table[0]) * HashBlock->HashTableSize); - CmiDestroyBlock(RegistryFile, HashBlock - , KeyBlock->HashTableOffset); - KeyBlock->HashTableOffset = HTOffset; + &HashBlock->Table[0], + sizeof(NewHashBlock->Table[0]) * HashBlock->HashTableSize); + CmiDestroyBlock(RegistryHive, HashBlock, KeyCell->HashTableOffset); + KeyCell->HashTableOffset = HTOffset; HashBlock = NewHashBlock; } } - Status = CmiAddKeyToHashTable(RegistryFile, HashBlock, NewKeyBlock,NKBOffset); + + Status = CmiAddKeyToHashTable(RegistryHive, HashBlock, NewKeyCell, NKBOffset); if (NT_SUCCESS(Status)) { - KeyBlock->NumberOfSubKeys++; + KeyCell->NumberOfSubKeys++; } - return Status; + return Status; } + NTSTATUS -CmiScanKeyForValue(IN PREGISTRY_FILE RegistryFile, - IN PKEY_BLOCK KeyBlock, - IN PCHAR ValueName, - OUT PVALUE_BLOCK *ValueBlock, - OUT BLOCK_OFFSET *VBOffset) +CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell, + IN PCHAR ValueName, + OUT PVALUE_CELL *ValueCell, + OUT BLOCK_OFFSET *VBOffset) { + PVALUE_LIST_CELL ValueListCell; + PVALUE_CELL CurValueCell; ULONG Length; - ULONG Idx; - PVALUE_LIST_BLOCK ValueListBlock; - PVALUE_BLOCK CurValueBlock; - - ValueListBlock = CmiGetBlock(RegistryFile, - KeyBlock->ValuesOffset,NULL); - *ValueBlock = NULL; - if (ValueListBlock == NULL) + ULONG i; + + ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL); + + *ValueCell = NULL; + + if (ValueListCell == NULL) { - DPRINT("ValueListBlock is NULL\n"); - return STATUS_SUCCESS; + DPRINT("ValueListCell is NULL\n"); + return STATUS_SUCCESS; } - for (Idx = 0; Idx < KeyBlock->NumberOfValues; Idx++) + + VERIFY_VALUE_LIST_CELL(ValueListCell); + + for (i = 0; i < KeyCell->NumberOfValues; i++) { - CurValueBlock = CmiGetBlock(RegistryFile, - ValueListBlock->Values[Idx],NULL); - /* FIXME : perhaps we must not ignore case if NtCreateKey has not been */ - /* called with OBJ_CASE_INSENSITIVE flag ? */ + CurValueCell = CmiGetBlock(RegistryHive, + ValueListCell->Values[i], + NULL); + /* FIXME: perhaps we must not ignore case if NtCreateKey has not been */ + /* called with OBJ_CASE_INSENSITIVE flag ? */ Length = strlen(ValueName); - if ((CurValueBlock != NULL) && - (CurValueBlock->NameSize == Length) && - (_strnicmp(CurValueBlock->Name, ValueName, Length) == 0)) + if ((CurValueCell != NULL) && + (CurValueCell->NameSize == Length) && + (_strnicmp(CurValueCell->Name, ValueName, Length) == 0)) { - *ValueBlock = CurValueBlock; - if(VBOffset) *VBOffset = ValueListBlock->Values[Idx]; - DPRINT("Found value %s\n", ValueName); + *ValueCell = CurValueCell; + if (VBOffset) + *VBOffset = ValueListCell->Values[i]; + DPRINT("Found value %s\n", ValueName); break; } - CmiReleaseBlock(RegistryFile, CurValueBlock); + CmiReleaseBlock(RegistryHive, CurValueCell); } - CmiReleaseBlock(RegistryFile, ValueListBlock); + CmiReleaseBlock(RegistryHive, ValueListCell); - return STATUS_SUCCESS; + return STATUS_SUCCESS; } NTSTATUS -CmiGetValueFromKeyByIndex(IN PREGISTRY_FILE RegistryFile, - IN PKEY_BLOCK KeyBlock, - IN ULONG Index, - OUT PVALUE_BLOCK *ValueBlock) +CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell, + IN ULONG Index, + OUT PVALUE_CELL *ValueCell) { - PVALUE_LIST_BLOCK ValueListBlock; - PVALUE_BLOCK CurValueBlock; - - ValueListBlock = CmiGetBlock(RegistryFile, - KeyBlock->ValuesOffset,NULL); - *ValueBlock = NULL; - if (ValueListBlock == NULL) + PVALUE_LIST_CELL ValueListCell; + PVALUE_CELL CurValueCell; + + ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL); + + *ValueCell = NULL; + + if (ValueListCell == NULL) { return STATUS_NO_MORE_ENTRIES; } - if (Index >= KeyBlock->NumberOfValues) + + VERIFY_VALUE_LIST_CELL(ValueListCell); + + if (Index >= KeyCell->NumberOfValues) { return STATUS_NO_MORE_ENTRIES; } - CurValueBlock = CmiGetBlock(RegistryFile, - ValueListBlock->Values[Index],NULL); - if (CurValueBlock != NULL) + + CurValueCell = CmiGetBlock(RegistryHive, + ValueListCell->Values[Index], + NULL); + + if (CurValueCell != NULL) { - *ValueBlock = CurValueBlock; + *ValueCell = CurValueCell; } - CmiReleaseBlock(RegistryFile, CurValueBlock); - CmiReleaseBlock(RegistryFile, ValueListBlock); + + CmiReleaseBlock(RegistryHive, CurValueCell); + CmiReleaseBlock(RegistryHive, ValueListCell); - return STATUS_SUCCESS; + return STATUS_SUCCESS; } -NTSTATUS -CmiAddValueToKey(IN PREGISTRY_FILE RegistryFile, - IN PKEY_BLOCK KeyBlock, - IN PCHAR ValueNameBuf, - OUT PVALUE_BLOCK *pValueBlock, - OUT BLOCK_OFFSET *pVBOffset) -{ - NTSTATUS Status; - PVALUE_LIST_BLOCK ValueListBlock, NewValueListBlock; - BLOCK_OFFSET VBOffset; - BLOCK_OFFSET VLBOffset; - PVALUE_BLOCK NewValueBlock; - Status = CmiAllocateValueBlock(RegistryFile, - &NewValueBlock, - &VBOffset, - ValueNameBuf); - *pVBOffset=VBOffset; +NTSTATUS +CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell, + IN PCHAR ValueNameBuf, + OUT PVALUE_CELL *pValueCell, + OUT BLOCK_OFFSET *pVBOffset) +{ + PVALUE_LIST_CELL NewValueListCell; + PVALUE_LIST_CELL ValueListCell; + PVALUE_CELL NewValueCell; + BLOCK_OFFSET VLBOffset; + BLOCK_OFFSET VBOffset; + NTSTATUS Status; + + Status = CmiAllocateValueCell(RegistryHive, + &NewValueCell, + &VBOffset, + ValueNameBuf); + *pVBOffset = VBOffset; + if (!NT_SUCCESS(Status)) { - return Status; + return Status; } - ValueListBlock = CmiGetBlock(RegistryFile, - KeyBlock->ValuesOffset,NULL); - if (ValueListBlock == NULL) - { - Status = CmiAllocateBlock(RegistryFile, - (PVOID) &ValueListBlock, - sizeof(BLOCK_OFFSET) * 3, - &VLBOffset); - if (!NT_SUCCESS(Status)) - { - CmiDestroyValueBlock(RegistryFile, - NewValueBlock,VBOffset); - return Status; - } - KeyBlock->ValuesOffset = VLBOffset; - } - else if (KeyBlock->NumberOfValues - >= ((LONG)(ValueListBlock->SubBlockSize-4))/(LONG)sizeof(BLOCK_OFFSET)) -// >= -(ValueListBlock->SubBlockSize-4)/sizeof(BLOCK_OFFSET)) - { - Status = CmiAllocateBlock(RegistryFile, - (PVOID) &NewValueListBlock, - sizeof(BLOCK_OFFSET) * - (KeyBlock->NumberOfValues + - REG_VALUE_LIST_BLOCK_MULTIPLE), - &VLBOffset); - if (!NT_SUCCESS(Status)) - { - CmiDestroyValueBlock(RegistryFile, - NewValueBlock, - VBOffset); - return(Status); - } - RtlCopyMemory(&NewValueListBlock->Values[0], - &ValueListBlock->Values[0], - sizeof(BLOCK_OFFSET) * KeyBlock->NumberOfValues); - CmiDestroyBlock(RegistryFile, ValueListBlock,KeyBlock->ValuesOffset); - KeyBlock->ValuesOffset = VLBOffset; - ValueListBlock = NewValueListBlock; - } - DPRINT("KeyBlock->NumberOfValues %d, ValueListBlock->SubBlockSize %d (%d %x)\n", - KeyBlock->NumberOfValues, ValueListBlock->SubBlockSize, - -(ValueListBlock->SubBlockSize-4)/sizeof(BLOCK_OFFSET), - -(ValueListBlock->SubBlockSize-4)/sizeof(BLOCK_OFFSET)); - ValueListBlock->Values[KeyBlock->NumberOfValues] = VBOffset; - KeyBlock->NumberOfValues++; - CmiReleaseBlock(RegistryFile, ValueListBlock); - CmiReleaseBlock(RegistryFile, NewValueBlock); - *pValueBlock = NewValueBlock; - return(STATUS_SUCCESS); + ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL); + + if (ValueListCell == NULL) + { + Status = CmiAllocateBlock(RegistryHive, + (PVOID) &ValueListCell, + sizeof(BLOCK_OFFSET) * 3, + &VLBOffset); + + if (!NT_SUCCESS(Status)) + { + CmiDestroyValueCell(RegistryHive, NewValueCell, VBOffset); + return Status; + } + KeyCell->ValuesOffset = VLBOffset; + } + else if ((KeyCell->NumberOfValues + >= ((LONG) (ValueListCell->CellSize - 4)) / (LONG) sizeof(BLOCK_OFFSET))) + { + Status = CmiAllocateBlock(RegistryHive, + (PVOID) &NewValueListCell, + sizeof(BLOCK_OFFSET) * (KeyCell->NumberOfValues + REG_VALUE_LIST_CELL_MULTIPLE), + &VLBOffset); + + if (!NT_SUCCESS(Status)) + { + CmiDestroyValueCell(RegistryHive, NewValueCell, VBOffset); + return Status; + } + + RtlCopyMemory(&NewValueListCell->Values[0], + &ValueListCell->Values[0], + sizeof(BLOCK_OFFSET) * KeyCell->NumberOfValues); + CmiDestroyBlock(RegistryHive, ValueListCell, KeyCell->ValuesOffset); + KeyCell->ValuesOffset = VLBOffset; + ValueListCell = NewValueListCell; + } + + DPRINT("KeyCell->NumberOfValues %d, ValueListCell->CellSize %d (%d %x)\n", + KeyCell->NumberOfValues, ValueListCell->CellSize, + -(ValueListCell->CellSize - 4) / sizeof(BLOCK_OFFSET), + -(ValueListCell->CellSize - 4) / sizeof(BLOCK_OFFSET)); + + ValueListCell->Values[KeyCell->NumberOfValues] = VBOffset; + KeyCell->NumberOfValues++; + CmiReleaseBlock(RegistryHive, ValueListCell); + CmiReleaseBlock(RegistryHive, NewValueCell); + *pValueCell = NewValueCell; + + return STATUS_SUCCESS; } -NTSTATUS -CmiDeleteValueFromKey(IN PREGISTRY_FILE RegistryFile, - IN PKEY_BLOCK KeyBlock, - IN PCHAR ValueName) -{ - ULONG Idx; - PVALUE_LIST_BLOCK ValueListBlock; - PVALUE_BLOCK CurValueBlock; - PHEAP_BLOCK pHeap; - ValueListBlock = CmiGetBlock(RegistryFile, - KeyBlock->ValuesOffset,NULL); - if (ValueListBlock == 0) +NTSTATUS +CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell, + IN PCHAR ValueName) +{ + PVALUE_LIST_CELL ValueListCell; + PVALUE_CELL CurValueCell; + PHBIN pBin; + ULONG i; + + ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL); + + if (ValueListCell == NULL) { - return STATUS_SUCCESS; + return STATUS_SUCCESS; } - for (Idx = 0; Idx < KeyBlock->NumberOfValues; Idx++) + + VERIFY_VALUE_LIST_CELL(ValueListCell); + + for (i = 0; i < KeyCell->NumberOfValues; i++) { - CurValueBlock = CmiGetBlock(RegistryFile, - ValueListBlock->Values[Idx],&pHeap); - if (CurValueBlock != NULL && - CurValueBlock->NameSize == strlen(ValueName) && - !memcmp(CurValueBlock->Name, ValueName,strlen(ValueName))) + CurValueCell = CmiGetBlock(RegistryHive, ValueListCell->Values[i], &pBin); + if ((CurValueCell != NULL) && + (CurValueCell->NameSize == strlen(ValueName)) && + (memcmp(CurValueCell->Name, ValueName, strlen(ValueName)) == 0)) { - if (KeyBlock->NumberOfValues - 1 < Idx) + if ((KeyCell->NumberOfValues - 1) < i) { - RtlCopyMemory(&ValueListBlock->Values[Idx], - &ValueListBlock->Values[Idx + 1], - sizeof(BLOCK_OFFSET) * - (KeyBlock->NumberOfValues - 1 - Idx)); + RtlCopyMemory(&ValueListCell->Values[i], + &ValueListCell->Values[i + 1], + sizeof(BLOCK_OFFSET) * (KeyCell->NumberOfValues - 1 - i)); } else { - RtlZeroMemory(&ValueListBlock->Values[Idx], - sizeof(BLOCK_OFFSET)); + RtlZeroMemory(&ValueListCell->Values[i], sizeof(BLOCK_OFFSET)); } - KeyBlock->NumberOfValues -= 1; - CmiDestroyValueBlock(RegistryFile, CurValueBlock, ValueListBlock->Values[Idx]); - /* update time of heap */ - ZwQuerySystemTime((PTIME) &pHeap->DateModified); + KeyCell->NumberOfValues -= 1; + CmiDestroyValueCell(RegistryHive, CurValueCell, ValueListCell->Values[i]); + /* update time of heap */ + ZwQuerySystemTime((PTIME) &pBin->DateModified); break; } - CmiReleaseBlock(RegistryFile, CurValueBlock); + CmiReleaseBlock(RegistryHive, CurValueCell); } - CmiReleaseBlock(RegistryFile, ValueListBlock); - - return STATUS_SUCCESS; + CmiReleaseBlock(RegistryHive, ValueListCell); + + return STATUS_SUCCESS; } + NTSTATUS -CmiAllocateHashTableBlock(IN PREGISTRY_FILE RegistryFile, - OUT PHASH_TABLE_BLOCK *HashBlock, - OUT BLOCK_OFFSET *HBOffset, - IN ULONG HashTableSize) +CmiAllocateHashTableBlock(IN PREGISTRY_HIVE RegistryHive, + OUT PHASH_TABLE_CELL *HashBlock, + OUT BLOCK_OFFSET *HBOffset, + IN ULONG HashTableSize) { - NTSTATUS Status; - ULONG NewHashSize; - PHASH_TABLE_BLOCK NewHashBlock; + PHASH_TABLE_CELL NewHashBlock; + ULONG NewHashSize; + NTSTATUS Status; Status = STATUS_SUCCESS; *HashBlock = NULL; - NewHashSize = sizeof(HASH_TABLE_BLOCK) + - (HashTableSize - 1) * sizeof(HASH_RECORD); - Status = CmiAllocateBlock(RegistryFile, - (PVOID*)&NewHashBlock, - NewHashSize,HBOffset); - if (NewHashBlock == NULL || !NT_SUCCESS(Status) ) - { - Status = STATUS_INSUFFICIENT_RESOURCES; - } - else - { - NewHashBlock->SubBlockId = REG_HASH_TABLE_BLOCK_ID; - NewHashBlock->HashTableSize = HashTableSize; - *HashBlock = NewHashBlock; - } + NewHashSize = sizeof(HASH_TABLE_CELL) + + (HashTableSize - 1) * sizeof(HASH_RECORD); + Status = CmiAllocateBlock(RegistryHive, + (PVOID*) &NewHashBlock, + NewHashSize, + HBOffset); - return Status; + if ((NewHashBlock == NULL) || (!NT_SUCCESS(Status))) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + else + { + NewHashBlock->Id = REG_HASH_TABLE_BLOCK_ID; + NewHashBlock->HashTableSize = HashTableSize; + *HashBlock = NewHashBlock; + } + + return Status; } -PKEY_BLOCK -CmiGetKeyFromHashByIndex(PREGISTRY_FILE RegistryFile, - PHASH_TABLE_BLOCK HashBlock, - ULONG Index) -{ - PKEY_BLOCK KeyBlock; - BLOCK_OFFSET KeyOffset; - if( HashBlock == NULL) +PKEY_CELL +CmiGetKeyFromHashByIndex(PREGISTRY_HIVE RegistryHive, + PHASH_TABLE_CELL HashBlock, + ULONG Index) +{ + BLOCK_OFFSET KeyOffset; + PKEY_CELL KeyCell; + + if (HashBlock == NULL) return NULL; - if (RegistryFile->Filename == NULL) + + if (IsVolatileHive(RegistryHive)) { - KeyBlock = (PKEY_BLOCK) HashBlock->Table[Index].KeyOffset; + KeyCell = (PKEY_CELL) HashBlock->Table[Index].KeyOffset; } else { KeyOffset = HashBlock->Table[Index].KeyOffset; - KeyBlock = CmiGetBlock(RegistryFile,KeyOffset,NULL); + KeyCell = CmiGetBlock(RegistryHive, KeyOffset, NULL); } - CmiLockBlock(RegistryFile, KeyBlock); + CmiLockBlock(RegistryHive, KeyCell); - return KeyBlock; + return KeyCell; } + NTSTATUS -CmiAddKeyToHashTable(PREGISTRY_FILE RegistryFile, - PHASH_TABLE_BLOCK HashBlock, - PKEY_BLOCK NewKeyBlock, - BLOCK_OFFSET NKBOffset) +CmiAddKeyToHashTable(PREGISTRY_HIVE RegistryHive, + PHASH_TABLE_CELL HashBlock, + PKEY_CELL NewKeyCell, + BLOCK_OFFSET NKBOffset) { ULONG i; for (i = 0; i < HashBlock->HashTableSize; i++) { - if (HashBlock->Table[i].KeyOffset == 0) - { - HashBlock->Table[i].KeyOffset = NKBOffset; - RtlCopyMemory(&HashBlock->Table[i].HashValue, - NewKeyBlock->Name, - 4); - return STATUS_SUCCESS; - } + if (HashBlock->Table[i].KeyOffset == 0) + { + HashBlock->Table[i].KeyOffset = NKBOffset; + RtlCopyMemory(&HashBlock->Table[i].HashValue, NewKeyCell->Name, 4); + return STATUS_SUCCESS; + } } + return STATUS_UNSUCCESSFUL; } + NTSTATUS -CmiAllocateValueBlock(PREGISTRY_FILE RegistryFile, - PVALUE_BLOCK *ValueBlock, - BLOCK_OFFSET *VBOffset, - IN PCHAR ValueNameBuf) +CmiAllocateValueCell(PREGISTRY_HIVE RegistryHive, + PVALUE_CELL *ValueCell, + BLOCK_OFFSET *VBOffset, + IN PCHAR ValueNameBuf) { - NTSTATUS Status; - ULONG NewValueSize; - PVALUE_BLOCK NewValueBlock; + PVALUE_CELL NewValueCell; + ULONG NewValueSize; + NTSTATUS Status; Status = STATUS_SUCCESS; - NewValueSize = sizeof(VALUE_BLOCK) + strlen(ValueNameBuf); - Status = CmiAllocateBlock(RegistryFile, - (PVOID*)&NewValueBlock, - NewValueSize,VBOffset); - if (NewValueBlock == NULL || !NT_SUCCESS(Status)) - { - Status = STATUS_INSUFFICIENT_RESOURCES; - } - else - { - NewValueBlock->SubBlockId = REG_VALUE_BLOCK_ID; - NewValueBlock->NameSize = strlen(ValueNameBuf); - memcpy(NewValueBlock->Name, ValueNameBuf,strlen(ValueNameBuf)); - NewValueBlock->DataType = 0; - NewValueBlock->DataSize = 0; - NewValueBlock->DataOffset = 0xffffffff; - *ValueBlock = NewValueBlock; - } + NewValueSize = sizeof(VALUE_CELL) + strlen(ValueNameBuf); + Status = CmiAllocateBlock(RegistryHive, + (PVOID*) &NewValueCell, + NewValueSize, + VBOffset); - return Status; + if ((NewValueCell == NULL) || (!NT_SUCCESS(Status))) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + else + { + NewValueCell->Id = REG_VALUE_CELL_ID; + NewValueCell->NameSize = strlen(ValueNameBuf); + memcpy(NewValueCell->Name, ValueNameBuf, strlen(ValueNameBuf)); + NewValueCell->DataType = 0; + NewValueCell->DataSize = 0; + NewValueCell->DataOffset = 0xffffffff; + *ValueCell = NewValueCell; + } + + return Status; } -NTSTATUS -CmiDestroyValueBlock(PREGISTRY_FILE RegistryFile, - PVALUE_BLOCK ValueBlock, BLOCK_OFFSET VBOffset) -{ - NTSTATUS Status; - PHEAP_BLOCK pHeap; - PVOID pBlock; - /* first, release datas : */ - if (ValueBlock->DataSize >0) - { - pBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,&pHeap); - Status = CmiDestroyBlock(RegistryFile, pBlock, ValueBlock->DataOffset); - if (!NT_SUCCESS(Status)) +NTSTATUS +CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive, + PVALUE_CELL ValueCell, + BLOCK_OFFSET VBOffset) +{ + NTSTATUS Status; + PVOID pBlock; + PHBIN pBin; + + VERIFY_VALUE_CELL(ValueCell); + + /* First, release datas: */ + if (ValueCell->DataSize > 0) + { + pBlock = CmiGetBlock(RegistryHive, ValueCell->DataOffset, &pBin); + Status = CmiDestroyBlock(RegistryHive, pBlock, ValueCell->DataOffset); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + /* Update time of heap */ + if (IsPermanentHive(RegistryHive)) + ZwQuerySystemTime((PTIME) &pBin->DateModified); + } + + Status = CmiDestroyBlock(RegistryHive, ValueCell, VBOffset); + + /* Update time of heap */ + if (IsPermanentHive(RegistryHive) && CmiGetBlock(RegistryHive, VBOffset, &pBin)) { - return Status; + ZwQuerySystemTime((PTIME) &pBin->DateModified); } - /* update time of heap */ - if(RegistryFile->Filename) - ZwQuerySystemTime((PTIME) &pHeap->DateModified); - } - Status = CmiDestroyBlock(RegistryFile, ValueBlock, VBOffset); - /* update time of heap */ - if(RegistryFile->Filename && CmiGetBlock(RegistryFile, VBOffset,&pHeap)) - ZwQuerySystemTime((PTIME) &pHeap->DateModified); - return Status; + return Status; } + NTSTATUS -CmiAddHeap(PREGISTRY_FILE RegistryFile,PVOID *NewBlock,BLOCK_OFFSET *NewBlockOffset) +CmiAddBin(PREGISTRY_HIVE RegistryHive, + PVOID *NewBlock, + BLOCK_OFFSET *NewBlockOffset) { - PHEAP_BLOCK tmpHeap; - PHEAP_BLOCK * tmpBlockList; - PFREE_SUB_BLOCK tmpBlock; - tmpHeap=ExAllocatePool(PagedPool, REG_BLOCK_SIZE); - tmpHeap->BlockId = REG_HEAP_ID; - tmpHeap->BlockOffset = RegistryFile->FileSize - REG_BLOCK_SIZE; - RegistryFile->FileSize += REG_BLOCK_SIZE; - tmpHeap->BlockSize = REG_BLOCK_SIZE; - tmpHeap->Unused1 = 0; - ZwQuerySystemTime((PTIME) &tmpHeap->DateModified); - tmpHeap->Unused2 = 0; - /* increase size of list of blocks */ - tmpBlockList=ExAllocatePool(NonPagedPool, - sizeof(PHEAP_BLOCK *) * (RegistryFile->BlockListSize +1)); + PCELL_HEADER tmpBlock; + PHBIN * tmpBlockList; + PHBIN tmpBin; + + tmpBin = ExAllocatePool(PagedPool, REG_BLOCK_SIZE); + + if (tmpBin == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + tmpBin->BlockId = REG_BIN_ID; + tmpBin->BlockOffset = RegistryHive->FileSize - REG_BLOCK_SIZE; + RegistryHive->FileSize += REG_BLOCK_SIZE; + tmpBin->BlockSize = REG_BLOCK_SIZE; + tmpBin->Unused1 = 0; + ZwQuerySystemTime((PTIME) &tmpBin->DateModified); + tmpBin->Unused2 = 0; + /* Increase size of list of blocks */ + tmpBlockList = ExAllocatePool(NonPagedPool, + sizeof(PHBIN *) * (RegistryHive->BlockListSize + 1)); + if (tmpBlockList == NULL) - { - KeBugCheck(0); - return(STATUS_INSUFFICIENT_RESOURCES); - } - if(RegistryFile->BlockListSize > 0) - { - memcpy(tmpBlockList,RegistryFile->BlockList, - sizeof(PHEAP_BLOCK *)*(RegistryFile->BlockListSize )); - ExFreePool(RegistryFile->BlockList); - } - RegistryFile->BlockList = tmpBlockList; - RegistryFile->BlockList [RegistryFile->BlockListSize++] = tmpHeap; - /* initialize a free block in this heap : */ - tmpBlock = (PFREE_SUB_BLOCK)((char *) tmpHeap + REG_HEAP_BLOCK_DATA_OFFSET); - tmpBlock-> SubBlockSize = (REG_BLOCK_SIZE - REG_HEAP_BLOCK_DATA_OFFSET) ; - *NewBlock = (PVOID)tmpBlock; + { + ExFreePool(tmpBin); + return STATUS_INSUFFICIENT_RESOURCES; + } + + if(RegistryHive->BlockListSize > 0) + { + memcpy(tmpBlockList, RegistryHive->BlockList, + sizeof(PHBIN *)*(RegistryHive->BlockListSize)); + ExFreePool(RegistryHive->BlockList); + } + + RegistryHive->BlockList = tmpBlockList; + RegistryHive->BlockList[RegistryHive->BlockListSize++] = tmpBin; + + /* Initialize a free block in this heap : */ + tmpBlock = (PCELL_HEADER)((ULONG_PTR) tmpBin + REG_HBIN_DATA_OFFSET); + tmpBlock->CellSize = (REG_BLOCK_SIZE - REG_HBIN_DATA_OFFSET); + *NewBlock = (PVOID) tmpBlock; + if (NewBlockOffset) - *NewBlockOffset = tmpHeap->BlockOffset + REG_HEAP_BLOCK_DATA_OFFSET; - /* FIXME : set first dword to block_offset of another free bloc */ + *NewBlockOffset = tmpBin->BlockOffset + REG_HBIN_DATA_OFFSET; + + /* FIXME: set first dword to block_offset of another free bloc */ + return STATUS_SUCCESS; } + NTSTATUS -CmiAllocateBlock(PREGISTRY_FILE RegistryFile, - PVOID *Block, - LONG BlockSize, - BLOCK_OFFSET * pBlockOffset) +CmiAllocateBlock(PREGISTRY_HIVE RegistryHive, + PVOID *Block, + LONG BlockSize, + BLOCK_OFFSET * pBlockOffset) { - NTSTATUS Status; - PFREE_SUB_BLOCK NewBlock; - PHEAP_BLOCK pHeap; + PCELL_HEADER NewBlock; + NTSTATUS Status; + PHBIN pBin; Status = STATUS_SUCCESS; - /* round to 16 bytes multiple */ + + /* Round to 16 bytes multiple */ BlockSize = (BlockSize + sizeof(DWORD) + 15) & 0xfffffff0; - /* Handle volatile files first */ - if (RegistryFile->Filename == NULL) - { - NewBlock = ExAllocatePool(NonPagedPool, BlockSize); - if (NewBlock == NULL) - { - Status = STATUS_INSUFFICIENT_RESOURCES; - } - else - { - RtlZeroMemory(NewBlock, BlockSize); - NewBlock->SubBlockSize = BlockSize; - CmiLockBlock(RegistryFile, NewBlock); - *Block = NewBlock; - if (pBlockOffset) *pBlockOffset = (BLOCK_OFFSET)NewBlock; - } - } + /* Handle volatile hives first */ + if (IsVolatileHive(RegistryHive)) + { + NewBlock = ExAllocatePool(NonPagedPool, BlockSize); + + if (NewBlock == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + else + { + RtlZeroMemory(NewBlock, BlockSize); + NewBlock->CellSize = BlockSize; + CmiLockBlock(RegistryHive, NewBlock); + *Block = NewBlock; + if (pBlockOffset) + *pBlockOffset = (BLOCK_OFFSET) NewBlock; + } + } else - { - int i; - /* first search in free blocks */ - NewBlock = NULL; - for (i=0 ; iFreeListSize ; i++) - { - if(RegistryFile->FreeList[i]->SubBlockSize >=BlockSize) - { - NewBlock = RegistryFile->FreeList[i]; - if(pBlockOffset) - *pBlockOffset = RegistryFile->FreeListOffset[i]; - /* update time of heap */ - if(RegistryFile->Filename - && CmiGetBlock(RegistryFile, RegistryFile->FreeListOffset[i],&pHeap)) - ZwQuerySystemTime((PTIME) &pHeap->DateModified); - if( (i+1) FreeListSize) - { - memmove( &RegistryFile->FreeList[i] - ,&RegistryFile->FreeList[i+1] - ,sizeof(RegistryFile->FreeList[0]) - *(RegistryFile->FreeListSize-i-1)); - memmove( &RegistryFile->FreeListOffset[i] - ,&RegistryFile->FreeListOffset[i+1] - ,sizeof(RegistryFile->FreeListOffset[0]) - *(RegistryFile->FreeListSize-i-1)); - } - RegistryFile->FreeListSize--; - break; - } - } - /* need to extend hive file : */ - if (NewBlock == NULL) - { - /* add a new block : */ - Status = CmiAddHeap(RegistryFile, (PVOID *)&NewBlock , pBlockOffset); - } - if (NT_SUCCESS(Status)) - { - *Block = NewBlock; - /* split the block in two parts */ - if(NewBlock->SubBlockSize > BlockSize) - { - NewBlock = (PFREE_SUB_BLOCK)((char *)NewBlock+BlockSize); - NewBlock->SubBlockSize=((PFREE_SUB_BLOCK) (*Block))->SubBlockSize-BlockSize; - CmiAddFree(RegistryFile,NewBlock,*pBlockOffset+BlockSize); - } - else if(NewBlock->SubBlockSize < BlockSize) - return STATUS_UNSUCCESSFUL; - RtlZeroMemory(*Block, BlockSize); - ((PFREE_SUB_BLOCK)(*Block)) ->SubBlockSize = - BlockSize; - CmiLockBlock(RegistryFile, *Block); - } - } + { + ULONG i; + + /* first search in free blocks */ + NewBlock = NULL; + for (i = 0; i < RegistryHive->FreeListSize; i++) + { + if (RegistryHive->FreeList[i]->CellSize >= BlockSize) + { + PVOID Temp; + NewBlock = RegistryHive->FreeList[i]; + + if (pBlockOffset) + *pBlockOffset = RegistryHive->FreeListOffset[i]; + + /* Update time of heap */ + Temp = CmiGetBlock(RegistryHive, RegistryHive->FreeListOffset[i], &pBin); + + if (Temp) + ZwQuerySystemTime((PTIME) &pBin->DateModified); + + if ((i + 1) < RegistryHive->FreeListSize) + { + RtlMoveMemory(&RegistryHive->FreeList[i], + &RegistryHive->FreeList[i + 1], + sizeof(RegistryHive->FreeList[0]) + * (RegistryHive->FreeListSize - i - 1)); + RtlMoveMemory(&RegistryHive->FreeListOffset[i], + &RegistryHive->FreeListOffset[i + 1], + sizeof(RegistryHive->FreeListOffset[0]) + * (RegistryHive->FreeListSize - i - 1)); + } + RegistryHive->FreeListSize--; + break; + } + } + + /* Need to extend hive file : */ + if (NewBlock == NULL) + { + /* Add a new block */ + Status = CmiAddBin(RegistryHive, (PVOID *) &NewBlock , pBlockOffset); + } + + if (NT_SUCCESS(Status)) + { + *Block = NewBlock; + + /* Split the block in two parts */ + if (NewBlock->CellSize > BlockSize) + { + NewBlock = (PCELL_HEADER) ((ULONG_PTR) NewBlock+BlockSize); + NewBlock->CellSize = ((PCELL_HEADER) (*Block))->CellSize - BlockSize; + CmiAddFree(RegistryHive, NewBlock, *pBlockOffset + BlockSize); + } + else if (NewBlock->CellSize < BlockSize) + { + return STATUS_UNSUCCESSFUL; + } + RtlZeroMemory(*Block, BlockSize); + ((PCELL_HEADER) (*Block))->CellSize = -BlockSize; + CmiLockBlock(RegistryHive, *Block); + } + } return Status; } + NTSTATUS -CmiDestroyBlock(PREGISTRY_FILE RegistryFile, - PVOID Block,BLOCK_OFFSET Offset) +CmiDestroyBlock(PREGISTRY_HIVE RegistryHive, + PVOID Block, + BLOCK_OFFSET Offset) { - NTSTATUS Status; - PHEAP_BLOCK pHeap; + NTSTATUS Status; + PHBIN pBin; Status = STATUS_SUCCESS; - if (RegistryFile->Filename == NULL) - { - CmiReleaseBlock(RegistryFile, Block); - ExFreePool(Block); - } + if (IsVolatileHive(RegistryHive)) + { + CmiReleaseBlock(RegistryHive, Block); + ExFreePool(Block); + } else - { - PFREE_SUB_BLOCK pFree = Block; - - if (pFree->SubBlockSize <0) - pFree->SubBlockSize = -pFree->SubBlockSize; - CmiAddFree(RegistryFile,Block,Offset); - CmiReleaseBlock(RegistryFile, Block); - /* update time of heap */ - if(RegistryFile->Filename && CmiGetBlock(RegistryFile, Offset,&pHeap)) - ZwQuerySystemTime((PTIME) &pHeap->DateModified); - /* FIXME : set first dword to block_offset of another free block ? */ - /* FIXME : concatenate with previous and next block if free */ - } + { + PCELL_HEADER pFree = Block; - return Status; + if (pFree->CellSize < 0) + pFree->CellSize = -pFree->CellSize; + + CmiAddFree(RegistryHive, Block, Offset); + CmiReleaseBlock(RegistryHive, Block); + + /* Update time of heap */ + if (IsPermanentHive(RegistryHive) && CmiGetBlock(RegistryHive, Offset,&pBin)) + ZwQuerySystemTime((PTIME) &pBin->DateModified); + + /* FIXME: Set first dword to block_offset of another free block ? */ + /* FIXME: Concatenate with previous and next block if free */ + } + + return Status; } + NTSTATUS -CmiAddFree(PREGISTRY_FILE RegistryFile, - PFREE_SUB_BLOCK FreeBlock,BLOCK_OFFSET FreeOffset) +CmiAddFree(PREGISTRY_HIVE RegistryHive, + PCELL_HEADER FreeBlock, + BLOCK_OFFSET FreeOffset) { - PFREE_SUB_BLOCK *tmpList; - BLOCK_OFFSET *tmpListOffset; - int minInd,maxInd,medInd; - if( (RegistryFile->FreeListSize+1) > RegistryFile->FreeListMax) - { - tmpList=ExAllocatePool(PagedPool - ,sizeof(PFREE_SUB_BLOCK)*(RegistryFile->FreeListMax+32)); - if (tmpList == NULL) - return STATUS_INSUFFICIENT_RESOURCES; - tmpListOffset=ExAllocatePool(PagedPool - ,sizeof(BLOCK_OFFSET *)*(RegistryFile->FreeListMax+32)); - if (tmpListOffset == NULL) - return STATUS_INSUFFICIENT_RESOURCES; - if (RegistryFile->FreeListMax) - { - memcpy(tmpList,RegistryFile->FreeList - ,sizeof(PFREE_SUB_BLOCK)*(RegistryFile->FreeListMax)); - memcpy(tmpListOffset,RegistryFile->FreeListOffset - ,sizeof(BLOCK_OFFSET *)*(RegistryFile->FreeListMax)); - ExFreePool(RegistryFile->FreeList); - ExFreePool(RegistryFile->FreeListOffset); - } - RegistryFile->FreeList = tmpList; - RegistryFile->FreeListOffset = tmpListOffset; - RegistryFile->FreeListMax +=32; - } - /* add new offset to free list, maintening list in ascending order */ - if ( RegistryFile->FreeListSize==0 - || RegistryFile->FreeListOffset[RegistryFile->FreeListSize-1] < FreeOffset) - { - /* add to end of list : */ - RegistryFile->FreeList[RegistryFile->FreeListSize] = FreeBlock; - RegistryFile->FreeListOffset[RegistryFile->FreeListSize ++] = FreeOffset; - } - else if (RegistryFile->FreeListOffset[0] > FreeOffset) - { - /* add to begin of list : */ - memmove( &RegistryFile->FreeList[1],&RegistryFile->FreeList[0] - ,sizeof(RegistryFile->FreeList[0])*RegistryFile->FreeListSize); - memmove( &RegistryFile->FreeListOffset[1],&RegistryFile->FreeListOffset[0] - ,sizeof(RegistryFile->FreeListOffset[0])*RegistryFile->FreeListSize); - RegistryFile->FreeList[0] = FreeBlock; - RegistryFile->FreeListOffset[0] = FreeOffset; - RegistryFile->FreeListSize ++; - } - else - { - /* search where to insert : */ - minInd=0; - maxInd=RegistryFile->FreeListSize-1; - while( (maxInd-minInd) >1) - { - medInd=(minInd+maxInd)/2; - if (RegistryFile->FreeListOffset[medInd] > FreeOffset) - maxInd=medInd; - else - minInd=medInd; - } - /* insert before maxInd : */ - memmove( &RegistryFile->FreeList[maxInd+1],&RegistryFile->FreeList[maxInd] - ,sizeof(RegistryFile->FreeList[0]) - *(RegistryFile->FreeListSize-minInd)); - memmove( &RegistryFile->FreeListOffset[maxInd+1] - , &RegistryFile->FreeListOffset[maxInd] - , sizeof(RegistryFile->FreeListOffset[0]) - *(RegistryFile->FreeListSize-minInd)); - RegistryFile->FreeList[maxInd] = FreeBlock; - RegistryFile->FreeListOffset[maxInd] = FreeOffset; - RegistryFile->FreeListSize ++; - } + PCELL_HEADER *tmpList; + BLOCK_OFFSET *tmpListOffset; + LONG minInd; + LONG maxInd; + LONG medInd; + + assert(RegistryHive); + assert(FreeBlock); + + DPRINT("FreeBlock %.08x FreeOffset %.08x\n", + FreeBlock, FreeOffset); +DPRINT("\n"); + if ((RegistryHive->FreeListSize + 1) > RegistryHive->FreeListMax) + { +DPRINT("\n"); + tmpList = ExAllocatePool(PagedPool, + sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax + 32)); +DPRINT("\n"); + + if (tmpList == NULL) + return STATUS_INSUFFICIENT_RESOURCES; +DPRINT("\n"); + + tmpListOffset = ExAllocatePool(PagedPool, + sizeof(BLOCK_OFFSET *) * (RegistryHive->FreeListMax + 32)); +DPRINT("\n"); + + if (tmpListOffset == NULL) + { + ExFreePool(tmpList); + return STATUS_INSUFFICIENT_RESOURCES; + } +DPRINT("\n"); + + if (RegistryHive->FreeListMax) + { +DPRINT("\n"); + RtlMoveMemory(tmpList, RegistryHive->FreeList, + sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax)); +DPRINT("\n"); + RtlMoveMemory(tmpListOffset, RegistryHive->FreeListOffset, + sizeof(BLOCK_OFFSET *) * (RegistryHive->FreeListMax)); +DPRINT("\n"); + ExFreePool(RegistryHive->FreeList); +DPRINT("\n"); + ExFreePool(RegistryHive->FreeListOffset); +DPRINT("\n"); + } +DPRINT("\n"); + RegistryHive->FreeList = tmpList; + RegistryHive->FreeListOffset = tmpListOffset; + RegistryHive->FreeListMax += 32; +DPRINT("\n"); + } +DPRINT("\n"); + + /* Add new offset to free list, maintaining list in ascending order */ + if ((RegistryHive->FreeListSize == 0) + || (RegistryHive->FreeListOffset[RegistryHive->FreeListSize-1] < FreeOffset)) + { +DPRINT("\n"); + /* Add to end of list */ + RegistryHive->FreeList[RegistryHive->FreeListSize] = FreeBlock; + RegistryHive->FreeListOffset[RegistryHive->FreeListSize++] = FreeOffset; + } + else if (RegistryHive->FreeListOffset[0] > FreeOffset) + { +DPRINT("\n"); + /* Add to begin of list */ + RtlMoveMemory(&RegistryHive->FreeList[1], + &RegistryHive->FreeList[0], + sizeof(RegistryHive->FreeList[0]) * RegistryHive->FreeListSize); + RtlMoveMemory(&RegistryHive->FreeListOffset[1], + &RegistryHive->FreeListOffset[0], + sizeof(RegistryHive->FreeListOffset[0]) * RegistryHive->FreeListSize); + RegistryHive->FreeList[0] = FreeBlock; + RegistryHive->FreeListOffset[0] = FreeOffset; + RegistryHive->FreeListSize++; + } + else + { +DPRINT("\n"); + /* 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++; + } +DPRINT("\n"); + return STATUS_SUCCESS; } + PVOID -CmiGetBlock(PREGISTRY_FILE RegistryFile, - BLOCK_OFFSET BlockOffset, - OUT PHEAP_BLOCK * ppHeap) +CmiGetBlock(PREGISTRY_HIVE RegistryHive, + BLOCK_OFFSET BlockOffset, + PHBIN * ppBin) { - if( BlockOffset == 0 || BlockOffset == -1) + if ((BlockOffset == 0) || (BlockOffset == -1)) return NULL; - if (RegistryFile->Filename == NULL) - { - return (PVOID)BlockOffset; - } + if (IsVolatileHive(RegistryHive)) + { + return (PVOID) BlockOffset; + } else - { - PHEAP_BLOCK pHeap; - - pHeap = RegistryFile->BlockList[BlockOffset/4096]; - if(ppHeap) *ppHeap = pHeap; - return ((char *)pHeap - +(BlockOffset - pHeap->BlockOffset)); - } + { + PHBIN pBin; + + pBin = RegistryHive->BlockList[BlockOffset / 4096]; + if (ppBin) + *ppBin = pBin; + return ((PVOID) ((ULONG_PTR) pBin + (BlockOffset - pBin->BlockOffset))); + } } + VOID -CmiLockBlock(PREGISTRY_FILE RegistryFile, - PVOID Block) +CmiPrepareForWrite(PREGISTRY_HIVE RegistryHive, + PHBIN pBin) { - if (RegistryFile->Filename != NULL) + if (IsVolatileHive(RegistryHive)) + { + /* No need to do anything special for volatile hives */ + return; + } + else + { + + } +} + + +VOID +CmiLockBlock(PREGISTRY_HIVE RegistryHive, + PVOID Block) +{ + if (IsPermanentHive(RegistryHive)) { - /* FIXME : implement */ + /* FIXME: Implement */ } } + VOID -CmiReleaseBlock(PREGISTRY_FILE RegistryFile, - PVOID Block) +CmiReleaseBlock(PREGISTRY_HIVE RegistryHive, + PVOID Block) { - if (RegistryFile->Filename != NULL) + if (IsPermanentHive(RegistryHive)) { - /* FIXME : implement */ + /* FIXME: Implement */ } } diff --git a/reactos/ntoskrnl/cm/registry.c b/reactos/ntoskrnl/cm/registry.c index 120880d97c9..f0546ed83f6 100644 --- a/reactos/ntoskrnl/cm/registry.c +++ b/reactos/ntoskrnl/cm/registry.c @@ -1,4 +1,4 @@ -/* $Id: registry.c,v 1.68 2002/02/19 00:09:22 ekohl Exp $ +/* $Id: registry.c,v 1.69 2002/03/15 19:46:07 chorns Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -26,7 +26,7 @@ /* ------------------------------------------------- File Statics */ POBJECT_TYPE CmiKeyType = NULL; -PREGISTRY_FILE CmiVolatileFile = NULL; +PREGISTRY_HIVE CmiVolatileHive = NULL; KSPIN_LOCK CmiKeyListLock; static PKEY_OBJECT CmiRootKey = NULL; @@ -38,18 +38,212 @@ static GENERIC_MAPPING CmiKeyMapping = {KEY_READ, KEY_WRITE, KEY_EXECUTE, KEY_ALL_ACCESS}; +VOID +CmiCheckKey(BOOLEAN Verbose, + HANDLE Key); + + +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 = NtEnumerateKey(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 = NtOpenKey(&SubKey, + KEY_ALL_ACCESS, + &ObjectAttributes); + + assert(NT_SUCCESS(Status)); + + CmiCheckKey(Verbose, SubKey); + + NtClose(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 = NtEnumerateValueKey(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 = NtOpenKey(&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); + + NtClose(Key); +} + + +VOID +CmiCheckRegistry(BOOLEAN Verbose) +{ + if (Verbose) + DbgPrint("Checking registry internals\n"); + + CmiCheckByName(Verbose, L"Machine"); + CmiCheckByName(Verbose, L"User"); +} + + VOID CmInitializeRegistry(VOID) { - NTSTATUS Status; - HANDLE RootKeyHandle; - UNICODE_STRING RootKeyName; - OBJECT_ATTRIBUTES ObjectAttributes; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING RootKeyName; + HANDLE RootKeyHandle; PKEY_OBJECT NewKey; - HANDLE KeyHandle; + HANDLE KeyHandle; + NTSTATUS Status; /* Initialize the Key object type */ CmiKeyType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); + assert(CmiKeyType); CmiKeyType->TotalObjects = 0; CmiKeyType->TotalHandles = 0; CmiKeyType->MaxObjects = LONG_MAX; @@ -70,294 +264,363 @@ CmInitializeRegistry(VOID) RtlInitUnicodeString(&CmiKeyType->TypeName, L"Key"); /* Build volitile registry store */ - CmiVolatileFile = CmiCreateRegistry(NULL); + CmiVolatileHive = CmiCreateRegistryHive(NULL, FALSE); + assert(CmiVolatileHive != NULL); - /* Build the Root Key Object */ + /* Build the Root Key Object */ RtlInitUnicodeString(&RootKeyName, REG_ROOT_KEY_NAME); -DPRINT("Creating root\n"); InitializeObjectAttributes(&ObjectAttributes, &RootKeyName, 0, NULL, NULL); Status = ObCreateObject(&RootKeyHandle, - STANDARD_RIGHTS_REQUIRED, - &ObjectAttributes, - CmiKeyType, - (PVOID*)&NewKey); + STANDARD_RIGHTS_REQUIRED, + &ObjectAttributes, + CmiKeyType, + (PVOID *) &NewKey); + assert(NT_SUCCESS(Status)); CmiRootKey = NewKey; Status = ObReferenceObjectByHandle(RootKeyHandle, - STANDARD_RIGHTS_REQUIRED, - CmiKeyType, - UserMode, - (PVOID*)&CmiRootKey, - NULL); - CmiRootKey->RegistryFile = CmiVolatileFile; - CmiRootKey->KeyBlock = CmiGetBlock(CmiVolatileFile,CmiVolatileFile->HeaderBlock->RootKeyBlock,NULL); - - CmiRootKey->BlockOffset = CmiVolatileFile->HeaderBlock->RootKeyBlock; - CmiRootKey->Flags = 0; - CmiRootKey->NumberOfSubKeys=0; - CmiRootKey->SubKeys= NULL; - CmiRootKey->SizeOfSubKeys= 0; - CmiRootKey->Name=ExAllocatePool(PagedPool,strlen("Registry")); - CmiRootKey->NameSize=strlen("Registry"); - memcpy(CmiRootKey->Name,"Registry",strlen("Registry")); + STANDARD_RIGHTS_REQUIRED, + CmiKeyType, + KernelMode, + (PVOID *) &CmiRootKey, + NULL); + assert(NT_SUCCESS(Status)); + CmiRootKey->RegistryHive = CmiVolatileHive; + NewKey->BlockOffset = CmiVolatileHive->HiveHeader->RootKeyCell; + NewKey->KeyCell = CmiGetBlock(CmiVolatileHive, NewKey->BlockOffset, NULL); + CmiRootKey->Flags = 0; + CmiRootKey->NumberOfSubKeys = 0; + CmiRootKey->SubKeys = NULL; + CmiRootKey->SizeOfSubKeys = 0; + CmiRootKey->Name = ExAllocatePool(PagedPool, strlen("Registry")); + CmiRootKey->NameSize = strlen("Registry"); + memcpy(CmiRootKey->Name, "Registry", strlen("Registry")); KeInitializeSpinLock(&CmiKeyListLock); - /* Create initial predefined symbolic links */ - /* HKEY_LOCAL_MACHINE */ -DPRINT("Creating HKLM\n"); - Status=ObCreateObject(&KeyHandle, - STANDARD_RIGHTS_REQUIRED, - NULL, - CmiKeyType, - (PVOID*)&NewKey); - Status = CmiAddSubKey(CmiVolatileFile, - CmiRootKey, - NewKey, - L"Machine", - 14, - 0, - NULL, - 0); - NewKey->RegistryFile = CmiVolatileFile; - NewKey->Flags = 0; - NewKey->NumberOfSubKeys=0; - NewKey->SubKeys= NULL; - NewKey->SizeOfSubKeys= NewKey->KeyBlock->NumberOfSubKeys; - NewKey->Name=ExAllocatePool(PagedPool,strlen("Machine")); - NewKey->NameSize=strlen("Machine"); - memcpy(NewKey->Name,"Machine",strlen("Machine")); - CmiAddKeyToList(CmiRootKey,NewKey); - CmiMachineKey=NewKey; + /* Create initial predefined symbolic links */ - /* HKEY_USERS */ -DPRINT("Creating HKU\n"); - Status=ObCreateObject(&KeyHandle, - STANDARD_RIGHTS_REQUIRED, - NULL, - CmiKeyType, - (PVOID*)&NewKey); - Status = CmiAddSubKey(CmiVolatileFile, - CmiRootKey, - NewKey, - L"User", - 8, - 0, - NULL, - 0); - NewKey->RegistryFile = CmiVolatileFile; - NewKey->Flags = 0; - NewKey->NumberOfSubKeys=0; - NewKey->SubKeys= NULL; - NewKey->SizeOfSubKeys= NewKey->KeyBlock->NumberOfSubKeys; - NewKey->Name=ExAllocatePool(PagedPool,strlen("User")); - NewKey->NameSize=strlen("User"); - memcpy(NewKey->Name,"User",strlen("User")); - CmiAddKeyToList(CmiRootKey,NewKey); - CmiUserKey=NewKey; + /* HKEY_LOCAL_MACHINE */ + Status = ObCreateObject(&KeyHandle, + STANDARD_RIGHTS_REQUIRED, + NULL, + CmiKeyType, + (PVOID*) &NewKey); + assert(NT_SUCCESS(Status)); + Status = CmiAddSubKey(CmiVolatileHive, + CmiRootKey, + NewKey, + L"Machine", + wcslen(L"Machine") * sizeof(WCHAR), + 0, + NULL, + 0); + assert(NT_SUCCESS(Status)); + NewKey->RegistryHive = CmiVolatileHive; + NewKey->Flags = 0; + NewKey->NumberOfSubKeys = 0; + NewKey->SubKeys = NULL; + NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys; + NewKey->Name = ExAllocatePool(PagedPool, strlen("Machine")); + NewKey->NameSize = strlen("Machine"); + memcpy(NewKey->Name, "Machine", strlen("Machine")); + CmiAddKeyToList(CmiRootKey, NewKey); + CmiMachineKey = NewKey; + + /* HKEY_USERS */ + Status = ObCreateObject(&KeyHandle, + STANDARD_RIGHTS_REQUIRED, + NULL, + CmiKeyType, + (PVOID*) &NewKey); + assert(NT_SUCCESS(Status)); + Status = CmiAddSubKey(CmiVolatileHive, + CmiRootKey, + NewKey, + L"User", + wcslen(L"User") * sizeof(WCHAR), + 0, + NULL, + 0); + assert(NT_SUCCESS(Status)); + NewKey->RegistryHive = CmiVolatileHive; + NewKey->Flags = 0; + NewKey->NumberOfSubKeys = 0; + NewKey->SubKeys = NULL; + NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys; + NewKey->Name = ExAllocatePool(PagedPool, strlen("User")); + NewKey->NameSize = strlen("User"); + memcpy(NewKey->Name, "User", strlen("User")); + CmiAddKeyToList(CmiRootKey, NewKey); + CmiUserKey = NewKey; /* Create '\\Registry\\Machine\\HARDWARE' key. */ - Status=ObCreateObject(&KeyHandle, - STANDARD_RIGHTS_REQUIRED, - NULL, - CmiKeyType, - (PVOID*)&NewKey); - Status = CmiAddSubKey(CmiVolatileFile, - CmiMachineKey, - NewKey, - L"HARDWARE", - 16, - 0, - NULL, - 0); - NewKey->RegistryFile = CmiVolatileFile; + Status = ObCreateObject(&KeyHandle, + STANDARD_RIGHTS_REQUIRED, + NULL, + CmiKeyType, + (PVOID*)&NewKey); + assert(NT_SUCCESS(Status)); + Status = CmiAddSubKey(CmiVolatileHive, + CmiMachineKey, + NewKey, + L"HARDWARE", + wcslen(L"HARDWARE") * sizeof(WCHAR), + 0, + NULL, + 0); + assert(NT_SUCCESS(Status)); + NewKey->RegistryHive = CmiVolatileHive; NewKey->Flags = 0; - NewKey->NumberOfSubKeys=0; - NewKey->SubKeys= NULL; - NewKey->SizeOfSubKeys= NewKey->KeyBlock->NumberOfSubKeys; - NewKey->Name=ExAllocatePool(PagedPool,strlen("HARDWARE")); - NewKey->NameSize=strlen("HARDWARE"); - memcpy(NewKey->Name,"HARDWARE",strlen("HARDWARE")); - CmiAddKeyToList(CmiMachineKey,NewKey); - CmiHardwareKey=NewKey; + NewKey->NumberOfSubKeys = 0; + NewKey->SubKeys = NULL; + NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys; + NewKey->Name = ExAllocatePool(PagedPool, strlen("HARDWARE")); + NewKey->NameSize = strlen("HARDWARE"); + memcpy(NewKey->Name, "HARDWARE", strlen("HARDWARE")); + CmiAddKeyToList(CmiMachineKey, NewKey); + CmiHardwareKey = NewKey; /* Create '\\Registry\\Machine\\HARDWARE\\DESCRIPTION' key. */ - Status=ObCreateObject(&KeyHandle, - STANDARD_RIGHTS_REQUIRED, - NULL, - CmiKeyType, - (PVOID*)&NewKey); - Status = CmiAddSubKey(CmiVolatileFile, - CmiHardwareKey, - NewKey, - L"DESCRIPTION", - 22, - 0, - NULL, - 0); - NewKey->RegistryFile = CmiVolatileFile; + Status = ObCreateObject(&KeyHandle, + STANDARD_RIGHTS_REQUIRED, + NULL, + CmiKeyType, + (PVOID*) &NewKey); + assert(NT_SUCCESS(Status)); + Status = CmiAddSubKey(CmiVolatileHive, + CmiHardwareKey, + NewKey, + L"DESCRIPTION", + wcslen(L"DESCRIPTION") * sizeof(WCHAR), + 0, + NULL, + 0); + assert(NT_SUCCESS(Status)); + NewKey->RegistryHive = CmiVolatileHive; NewKey->Flags = 0; - NewKey->NumberOfSubKeys=0; - NewKey->SubKeys= NULL; - NewKey->SizeOfSubKeys= NewKey->KeyBlock->NumberOfSubKeys; - NewKey->Name=ExAllocatePool(PagedPool,strlen("DESCRIPTION")); - NewKey->NameSize=strlen("DESCRIPTION"); - memcpy(NewKey->Name,"DESCRIPTION",strlen("DESCRIPTION")); - CmiAddKeyToList(CmiHardwareKey,NewKey); + NewKey->NumberOfSubKeys = 0; + NewKey->SubKeys = NULL; + NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys; + NewKey->Name = ExAllocatePool(PagedPool, strlen("DESCRIPTION")); + NewKey->NameSize = strlen("DESCRIPTION"); + memcpy(NewKey->Name, "DESCRIPTION", strlen("DESCRIPTION")); + CmiAddKeyToList(CmiHardwareKey, NewKey); /* Create '\\Registry\\Machine\\HARDWARE\\DEVICEMAP' key. */ - Status=ObCreateObject(&KeyHandle, - STANDARD_RIGHTS_REQUIRED, - NULL, - CmiKeyType, - (PVOID*)&NewKey); - Status = CmiAddSubKey(CmiVolatileFile, - CmiHardwareKey, - NewKey, - L"DEVICEMAP", - 18, - 0, - NULL, - 0); - NewKey->RegistryFile = CmiVolatileFile; + Status = ObCreateObject(&KeyHandle, + STANDARD_RIGHTS_REQUIRED, + NULL, + CmiKeyType, + (PVOID*) &NewKey); + assert(NT_SUCCESS(Status)); + Status = CmiAddSubKey(CmiVolatileHive, + CmiHardwareKey, + NewKey, + L"DEVICEMAP", + wcslen(L"DEVICEMAP") * sizeof(WCHAR), + 0, + NULL, + 0); + assert(NT_SUCCESS(Status)); + NewKey->RegistryHive = CmiVolatileHive; NewKey->Flags = 0; - NewKey->NumberOfSubKeys=0; - NewKey->SubKeys= NULL; - NewKey->SizeOfSubKeys= NewKey->KeyBlock->NumberOfSubKeys; - NewKey->Name=ExAllocatePool(PagedPool,strlen("DEVICEMAP")); - NewKey->NameSize=strlen("DEVICEMAP"); - memcpy(NewKey->Name,"DEVICEMAP",strlen("DEVICEMAP")); + NewKey->NumberOfSubKeys = 0; + NewKey->SubKeys = NULL; + NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys; + NewKey->Name = ExAllocatePool(PagedPool, strlen("DEVICEMAP")); + NewKey->NameSize = strlen("DEVICEMAP"); + memcpy(NewKey->Name, "DEVICEMAP", strlen("DEVICEMAP")); CmiAddKeyToList(CmiHardwareKey,NewKey); /* Create '\\Registry\\Machine\\HARDWARE\\RESOURCEMAP' key. */ - Status=ObCreateObject(&KeyHandle, - STANDARD_RIGHTS_REQUIRED, - NULL, //&ObjectAttributes, - CmiKeyType, - (PVOID*)&NewKey); - Status = CmiAddSubKey(CmiVolatileFile, - CmiHardwareKey, - NewKey, - L"RESOURCEMAP", - 22, - 0, - NULL, - 0); - NewKey->RegistryFile = CmiVolatileFile; + Status = ObCreateObject(&KeyHandle, + STANDARD_RIGHTS_REQUIRED, + NULL, + CmiKeyType, + (PVOID*) &NewKey); + assert(NT_SUCCESS(Status)); + Status = CmiAddSubKey(CmiVolatileHive, + CmiHardwareKey, + NewKey, + L"RESOURCEMAP", + wcslen(L"RESOURCEMAP") * sizeof(WCHAR), + 0, + NULL, + 0); + assert(NT_SUCCESS(Status)); + NewKey->RegistryHive = CmiVolatileHive; NewKey->Flags = 0; - NewKey->NumberOfSubKeys=0; - NewKey->SubKeys= NULL; - NewKey->SizeOfSubKeys= NewKey->KeyBlock->NumberOfSubKeys; - NewKey->Name=ExAllocatePool(PagedPool,strlen("RESOURCEMAP")); - NewKey->NameSize=strlen("RESOURCEMAP"); - memcpy(NewKey->Name,"RESOURCEMAP",strlen("RESOURCEMAP")); - CmiAddKeyToList(CmiHardwareKey,NewKey); + NewKey->NumberOfSubKeys = 0; + NewKey->SubKeys = NULL; + NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys; + NewKey->Name = ExAllocatePool(PagedPool, strlen("RESOURCEMAP")); + NewKey->NameSize = strlen("RESOURCEMAP"); + memcpy(NewKey->Name, "RESOURCEMAP", strlen("RESOURCEMAP")); + CmiAddKeyToList(CmiHardwareKey, NewKey); /* FIXME: create remaining structure needed for default handles */ /* FIXME: load volatile registry data from ROSDTECT */ - } -NTSTATUS CmConnectHive(PWSTR FileName,PWSTR FullName,CHAR *KeyName,PKEY_OBJECT Parent) + +NTSTATUS +CmiConnectHive(PWSTR FileName, + PWSTR FullName, + PCHAR KeyName, + PKEY_OBJECT Parent, + BOOLEAN CreateNew) { - OBJECT_ATTRIBUTES ObjectAttributes; - PKEY_OBJECT NewKey; - HANDLE KeyHandle; - UNICODE_STRING uKeyName; - PREGISTRY_FILE RegistryFile = NULL; - NTSTATUS Status; - RegistryFile = CmiCreateRegistry(FileName); - if( RegistryFile ) - { - RtlInitUnicodeString(&uKeyName, FullName); -DPRINT("CCH %S ;",FullName); - InitializeObjectAttributes(&ObjectAttributes, &uKeyName, 0, NULL, NULL); - Status=ObCreateObject(&KeyHandle, - STANDARD_RIGHTS_REQUIRED, - &ObjectAttributes, - CmiKeyType, - (PVOID*)&NewKey); - if (!NT_SUCCESS(Status)) - return (Status); - NewKey->RegistryFile = RegistryFile; - NewKey->BlockOffset = RegistryFile->HeaderBlock->RootKeyBlock; - NewKey->KeyBlock = CmiGetBlock(RegistryFile,NewKey->BlockOffset,NULL); - NewKey->Flags = 0; - NewKey->NumberOfSubKeys=0; - NewKey->SubKeys= ExAllocatePool(PagedPool - , NewKey->KeyBlock->NumberOfSubKeys * sizeof(DWORD)); - NewKey->SizeOfSubKeys= NewKey->KeyBlock->NumberOfSubKeys; - NewKey->Name=ExAllocatePool(PagedPool,strlen(KeyName)); - NewKey->NameSize=strlen(KeyName); - memcpy(NewKey->Name,KeyName,strlen(KeyName)); - CmiAddKeyToList(Parent,NewKey); - } + OBJECT_ATTRIBUTES ObjectAttributes; + PREGISTRY_HIVE RegistryHive = NULL; + UNICODE_STRING uKeyName; + PKEY_OBJECT NewKey; + HANDLE KeyHandle; + NTSTATUS Status; + + DPRINT("Called. FileName %S\n", FullName); + + RegistryHive = CmiCreateRegistryHive(FileName, CreateNew); + if (RegistryHive) + { + RtlInitUnicodeString(&uKeyName, FullName); + + InitializeObjectAttributes(&ObjectAttributes, + &uKeyName, + 0, + NULL, + NULL); + + Status = ObCreateObject(&KeyHandle, + STANDARD_RIGHTS_REQUIRED, + &ObjectAttributes, + CmiKeyType, + (PVOID*) &NewKey); + + if (!NT_SUCCESS(Status)) + return Status; + + NewKey->RegistryHive = RegistryHive; + NewKey->BlockOffset = RegistryHive->HiveHeader->RootKeyCell; + NewKey->KeyCell = CmiGetBlock(RegistryHive, NewKey->BlockOffset, NULL); + NewKey->Flags = 0; + NewKey->NumberOfSubKeys = 0; + NewKey->SubKeys = ExAllocatePool(PagedPool, + NewKey->KeyCell->NumberOfSubKeys * sizeof(DWORD)); + + if ((NewKey->SubKeys == NULL) && (NewKey->KeyCell->NumberOfSubKeys != 0)) + { + /* FIXME: Cleanup from CmiCreateRegistryHive() */ + DPRINT("NumberOfSubKeys %d\n", NewKey->KeyCell->NumberOfSubKeys); + ZwClose(NewKey); + return STATUS_INSUFFICIENT_RESOURCES; + } + + NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys; + NewKey->Name = ExAllocatePool(PagedPool, strlen(KeyName)); + + if ((NewKey->Name == NULL) && (strlen(KeyName) != 0)) + { + /* FIXME: Cleanup from CmiCreateRegistryHive() */ + DPRINT("strlen(KeyName) %d\n", strlen(KeyName)); + if (NewKey->SubKeys != NULL) + ExFreePool(NewKey->SubKeys); + ZwClose(NewKey); + return STATUS_INSUFFICIENT_RESOURCES; + } + + NewKey->NameSize = strlen(KeyName); + memcpy(NewKey->Name, KeyName, strlen(KeyName)); + CmiAddKeyToList(Parent, NewKey); + + VERIFY_KEY_OBJECT(NewKey); + } else - return STATUS_UNSUCCESSFUL; + { + return STATUS_UNSUCCESSFUL; + } return STATUS_SUCCESS; } + +NTSTATUS +CmiInitializeHive(PWSTR FileName, + PWSTR FullName, + PCHAR KeyName, + PKEY_OBJECT Parent) +{ + NTSTATUS Status; + + /* Try to connect the hive */ + //Status = CmiConnectHive(FileName, FullName, KeyName, Parent, FALSE); + Status = CmiConnectHive(FileName, FullName, KeyName, Parent, TRUE); + + if (!NT_SUCCESS(Status)) + { + DPRINT("Status %.08x\n", Status); +#if 0 + WCHAR AltFileName[MAX_PATH]; + + CPRINT("WARNING! Registry file %S not found\n", FileName); + + wcscpy(AltFileName, FileName); + wcscat(AltFileName, L".alt"); + + /* Try to connect the alternative hive */ + Status = CmiConnectHive(AltFileName, FullName, KeyName, Parent, TRUE); + + if (!NT_SUCCESS(Status)) + { + CPRINT("WARNING! Alternative registry file %S not found\n", AltFileName); + DPRINT("Status %.08x\n", Status); + } +#endif + } + + return Status; +} + + +extern BOOLEAN CmiDoVerify; + VOID CmInitializeRegistry2(VOID) { - NTSTATUS Status; - /* FIXME : delete temporary \Registry\Machine\System */ - /* connect the SYSTEM Hive */ - Status=CmConnectHive(SYSTEM_REG_FILE,REG_SYSTEM_KEY_NAME - ,"System",CmiMachineKey); - if (!NT_SUCCESS(Status)) - { - /* FIXME : search SYSTEM.alt, or create new */ - CPRINT(" warning : registry file %S not found\n",SYSTEM_REG_FILE); - } - /* connect the SOFTWARE Hive */ - Status=CmConnectHive(SOFTWARE_REG_FILE,REG_SOFTWARE_KEY_NAME - ,"Software",CmiMachineKey); - if (!NT_SUCCESS(Status)) - { - /* FIXME : search SOFTWARE.alt, or create new */ - CPRINT(" warning : registry file %S not found\n",SOFTWARE_REG_FILE); - } - /* connect the SAM Hive */ - Status=CmConnectHive(SAM_REG_FILE,REG_SAM_KEY_NAME - ,"Sam",CmiMachineKey); - if (!NT_SUCCESS(Status)) - { - /* FIXME : search SAM.alt, or create new */ - CPRINT(" warning : registry file %S not found\n",SAM_REG_FILE); - } - /* connect the SECURITY Hive */ - Status=CmConnectHive(SEC_REG_FILE,REG_SEC_KEY_NAME - ,"Security",CmiMachineKey); - if (!NT_SUCCESS(Status)) - { - /* FIXME : search SECURITY.alt, or create new */ - CPRINT(" warning : registry file %S not found\n",SEC_REG_FILE); - } - /* connect the DEFAULT Hive */ - Status=CmConnectHive(USER_REG_FILE,REG_USER_KEY_NAME - ,".Default",CmiUserKey); - if (!NT_SUCCESS(Status)) - { - /* FIXME : search DEFAULT.alt, or create new */ - CPRINT(" warning : registry file %S not found\n",USER_REG_FILE); - } + NTSTATUS Status; + + CmiDoVerify = TRUE; + + /* FIXME: Delete temporary \Registry\Machine\System */ + + /* Connect the SYSTEM hive */ + Status = CmiInitializeHive(SYSTEM_REG_FILE, REG_SYSTEM_KEY_NAME, "System", CmiMachineKey); + assert(NT_SUCCESS(Status)); + + /* Connect the SOFTWARE hive */ + Status = CmiInitializeHive(SOFTWARE_REG_FILE, REG_SOFTWARE_KEY_NAME, "Software", CmiMachineKey); + assert(NT_SUCCESS(Status)); + + /* Connect the SAM hive */ + Status = CmiInitializeHive(SAM_REG_FILE,REG_SAM_KEY_NAME, "Sam", CmiMachineKey); + assert(NT_SUCCESS(Status)); + + /* Connect the SECURITY hive */ + Status = CmiInitializeHive(SEC_REG_FILE, REG_SEC_KEY_NAME, "Security", CmiMachineKey); + assert(NT_SUCCESS(Status)); + + /* Connect the DEFAULT hive */ + Status = CmiInitializeHive(USER_REG_FILE, REG_USER_KEY_NAME, ".Default", CmiUserKey); + assert(NT_SUCCESS(Status)); + /* FIXME : initialize standards symbolic links */ -/* -for(;;) -{ -__asm__ ("hlt\n\t"); -} -*/ + +// CmiCheckRegistry(TRUE); } + VOID CmShutdownRegistry(VOID) { - DPRINT("CmShutdownRegistry()...\n"); + UNIMPLEMENTED } - - - - /* EOF */ diff --git a/reactos/ntoskrnl/cm/regobj.c b/reactos/ntoskrnl/cm/regobj.c index 398e67ff9f3..5ceeb3df664 100644 --- a/reactos/ntoskrnl/cm/regobj.c +++ b/reactos/ntoskrnl/cm/regobj.c @@ -24,245 +24,290 @@ extern KSPIN_LOCK CmiKeyListLock; NTSTATUS STDCALL CmiObjectParse(PVOID ParsedObject, - PVOID *NextObject, - PUNICODE_STRING FullPath, - PWSTR *Path, - POBJECT_TYPE ObjectType, - ULONG Attributes) + PVOID *NextObject, + PUNICODE_STRING FullPath, + PWSTR *Path, + POBJECT_TYPE ObjectType, + ULONG Attributes) { - CHAR cPath[MAX_PATH]; - PWSTR end; - PKEY_OBJECT FoundObject; - PKEY_OBJECT ParsedKey=ParsedObject; - PKEY_BLOCK SubKeyBlock; - BLOCK_OFFSET BlockOffset; - NTSTATUS Status; - *NextObject = NULL; - if ((*Path) == NULL) - { - return STATUS_UNSUCCESSFUL; - } - - if((*Path[0])=='\\') - { - end = wcschr((*Path)+1, '\\'); - if (end != NULL) - *end = 0; - wcstombs(cPath,(*Path)+1,wcslen((*Path)+1)); - cPath[wcslen( (*Path)+1)]=0; - } - else - { - end = wcschr((*Path), '\\'); - if (end != NULL) - *end = 0; - wcstombs(cPath,(*Path),wcslen((*Path))); - cPath[wcslen( (*Path))]=0; - } - - FoundObject = CmiScanKeyList(ParsedKey,cPath,Attributes); - if (FoundObject == NULL) - { - Status = CmiScanForSubKey(ParsedKey->RegistryFile, - ParsedKey->KeyBlock, - &SubKeyBlock, - &BlockOffset, - cPath, - 0, - Attributes); - if(!NT_SUCCESS(Status) || SubKeyBlock == NULL) - { + BLOCK_OFFSET BlockOffset; + PKEY_OBJECT FoundObject; + PKEY_OBJECT ParsedKey; + PKEY_CELL SubKeyCell; + CHAR cPath[MAX_PATH]; + NTSTATUS Status; + PWSTR end; + + ParsedKey = ParsedObject; + + VERIFY_KEY_OBJECT(ParsedKey); + + *NextObject = NULL; + + if ((*Path) == NULL) + { + DPRINT("*Path is NULL\n"); + return STATUS_UNSUCCESSFUL; + } + + if ((*Path[0]) == '\\') + { + end = wcschr((*Path) + 1, '\\'); + if (end != NULL) + *end = 0; + wcstombs(cPath, (*Path) + 1, wcslen((*Path) + 1)); + cPath[wcslen((*Path) + 1)] = 0; + } + else + { + end = wcschr((*Path), '\\'); + if (end != NULL) + *end = 0; + wcstombs(cPath, (*Path), wcslen((*Path))); + cPath[wcslen((*Path))] = 0; + } + + FoundObject = CmiScanKeyList(ParsedKey, cPath, Attributes); + if (FoundObject == NULL) + { + Status = CmiScanForSubKey(ParsedKey->RegistryHive, + ParsedKey->KeyCell, + &SubKeyCell, + &BlockOffset, + cPath, + 0, + Attributes); + + if (!NT_SUCCESS(Status) || (SubKeyCell == NULL)) + { + if (end != NULL) + { + *end = '\\'; + } + return STATUS_UNSUCCESSFUL; + } + + /* Create new key object and put into linked list */ + DPRINT("CmiObjectParse %s\n", cPath); + Status = ObCreateObject(NULL, + STANDARD_RIGHTS_REQUIRED, + NULL, + CmiKeyType, + (PVOID*) &FoundObject); + + if (!NT_SUCCESS(Status)) + { + return Status; + } + + FoundObject->Flags = 0; + FoundObject->Name = SubKeyCell->Name; + FoundObject->NameSize = SubKeyCell->NameSize; + FoundObject->KeyCell = SubKeyCell; + FoundObject->BlockOffset = BlockOffset; + FoundObject->RegistryHive = ParsedKey->RegistryHive; + CmiAddKeyToList(ParsedKey, FoundObject); + DPRINT("Created object 0x%x\n", FoundObject); + } + else + { + ObReferenceObjectByPointer(FoundObject, + STANDARD_RIGHTS_REQUIRED, + NULL, + UserMode); + } + + DPRINT("CmiObjectParse %s\n", FoundObject->Name); + if (end != NULL) - { - *end = '\\'; - } - return STATUS_UNSUCCESSFUL; - } - /* Create new key object and put into linked list */ -DPRINT("CmiObjectParse %s\n",cPath); - Status = ObCreateObject(NULL, - STANDARD_RIGHTS_REQUIRED, - NULL, - CmiKeyType, - (PVOID*)&FoundObject); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - FoundObject->Flags = 0; - FoundObject->Name = SubKeyBlock->Name; - FoundObject->NameSize = SubKeyBlock->NameSize; - FoundObject->KeyBlock = SubKeyBlock; - FoundObject->BlockOffset = BlockOffset; - FoundObject->RegistryFile = ParsedKey->RegistryFile; - CmiAddKeyToList(ParsedKey,FoundObject); -DPRINT("CmiObjectParse(): created object 0x%x\n",FoundObject); - } - else - ObReferenceObjectByPointer(FoundObject, - STANDARD_RIGHTS_REQUIRED, - NULL, - UserMode); -DPRINT("CmiObjectParse %s\n",FoundObject->Name); - if (end != NULL) - { - *end = '\\'; - *Path = end; - } - else - { - *Path = NULL; - } + { + *end = '\\'; + *Path = end; + } + else + { + *Path = NULL; + } - *NextObject = FoundObject; - - return STATUS_SUCCESS; +VERIFY_KEY_OBJECT(FoundObject); + + *NextObject = FoundObject; + + return STATUS_SUCCESS; } + NTSTATUS STDCALL CmiObjectCreate(PVOID ObjectBody, - PVOID Parent, - PWSTR RemainingPath, - struct _OBJECT_ATTRIBUTES* ObjectAttributes) + PVOID Parent, + PWSTR RemainingPath, + struct _OBJECT_ATTRIBUTES* ObjectAttributes) { - PKEY_OBJECT pKey=ObjectBody; - pKey->ParentKey = Parent; - if (RemainingPath) - { - if(RemainingPath[0]== L'\\') - { - pKey->Name = (PCHAR) (&RemainingPath[1]); - pKey->NameSize = wcslen(RemainingPath)-1; - } - else - { - pKey->Name = (PCHAR) RemainingPath; - pKey->NameSize = wcslen(RemainingPath); - } - } + PKEY_OBJECT pKey = ObjectBody; + pKey->ParentKey = Parent; + if (RemainingPath) + { + if(RemainingPath[0]== L'\\') + { + pKey->Name = (PCHAR) (&RemainingPath[1]); + pKey->NameSize = wcslen(RemainingPath) - 1; + } + else + { + pKey->Name = (PCHAR) RemainingPath; + pKey->NameSize = wcslen(RemainingPath); + } + } else - pKey->NameSize = 0; + { + pKey->NameSize = 0; + } - return STATUS_SUCCESS; + return STATUS_SUCCESS; } + VOID STDCALL CmiObjectDelete(PVOID DeletedObject) { - PKEY_OBJECT KeyObject; + PKEY_OBJECT KeyObject; + + DPRINT("Delete object key\n"); - DPRINT("delete object key\n"); KeyObject = (PKEY_OBJECT) DeletedObject; - if(!NT_SUCCESS(CmiRemoveKeyFromList(KeyObject))) - { - DPRINT1("Key not found in parent list ???\n"); - } + + if (!NT_SUCCESS(CmiRemoveKeyFromList(KeyObject))) + { + DPRINT1("Key not found in parent list ???\n"); + } + if (KeyObject->Flags & KO_MARKED_FOR_DELETE) { DPRINT("delete really key\n"); - CmiDestroyBlock(KeyObject->RegistryFile, - KeyObject->KeyBlock, - KeyObject->BlockOffset); + CmiDestroyBlock(KeyObject->RegistryHive, + KeyObject->KeyCell, + KeyObject->BlockOffset); } else { - CmiReleaseBlock(KeyObject->RegistryFile, - KeyObject->KeyBlock); + CmiReleaseBlock(KeyObject->RegistryHive, KeyObject->KeyCell); } } -void -CmiAddKeyToList(PKEY_OBJECT ParentKey,PKEY_OBJECT NewKey) +VOID +CmiAddKeyToList(PKEY_OBJECT ParentKey, + PKEY_OBJECT NewKey) { - KIRQL OldIrql; + KIRQL OldIrql; + + DPRINT("ParentKey %.08x\n", ParentKey); KeAcquireSpinLock(&CmiKeyListLock, &OldIrql); + if (ParentKey->SizeOfSubKeys <= ParentKey->NumberOfSubKeys) - { - PKEY_OBJECT *tmpSubKeys = ExAllocatePool(PagedPool - , (ParentKey->NumberOfSubKeys+1) * sizeof(DWORD)); - if(ParentKey->NumberOfSubKeys > 0) - memcpy(tmpSubKeys,ParentKey->SubKeys - ,ParentKey->NumberOfSubKeys*sizeof(DWORD)); - if(ParentKey->SubKeys) ExFreePool(ParentKey->SubKeys); - ParentKey->SubKeys=tmpSubKeys; - ParentKey->SizeOfSubKeys = ParentKey->NumberOfSubKeys+1; - } - /* FIXME : please maintain the list in alphabetic order */ + { + PKEY_OBJECT *tmpSubKeys = ExAllocatePool(PagedPool, + (ParentKey->NumberOfSubKeys + 1) * sizeof(DWORD)); + + if (ParentKey->NumberOfSubKeys > 0) + { + memcpy(tmpSubKeys, + ParentKey->SubKeys, + ParentKey->NumberOfSubKeys * sizeof(DWORD)); + } + + if (ParentKey->SubKeys) + ExFreePool(ParentKey->SubKeys); + + ParentKey->SubKeys = tmpSubKeys; + ParentKey->SizeOfSubKeys = ParentKey->NumberOfSubKeys + 1; + } + + /* FIXME: Please maintain the list in alphabetic order */ /* to allow a dichotomic search */ ParentKey->SubKeys[ParentKey->NumberOfSubKeys++] = NewKey; + DPRINT("Reference parent key: 0x%x\n", ParentKey); + ObReferenceObjectByPointer(ParentKey, - STANDARD_RIGHTS_REQUIRED, - NULL, - UserMode); + STANDARD_RIGHTS_REQUIRED, + NULL, + UserMode); NewKey->ParentKey = ParentKey; KeReleaseSpinLock(&CmiKeyListLock, OldIrql); } + NTSTATUS -CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove) +CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove) { - KIRQL OldIrql; - PKEY_OBJECT ParentKey; + PKEY_OBJECT ParentKey; + KIRQL OldIrql; DWORD Index; - ParentKey=KeyToRemove->ParentKey; + ParentKey = KeyToRemove->ParentKey; KeAcquireSpinLock(&CmiKeyListLock, &OldIrql); - /* FIXME : if list maintained in alphabetic order, use dichotomic search */ - for (Index=0; Index < ParentKey->NumberOfSubKeys; Index++) - { - if(ParentKey->SubKeys[Index] == KeyToRemove) - { - if (Index < ParentKey->NumberOfSubKeys-1) - memmove(&ParentKey->SubKeys[Index] - ,&ParentKey->SubKeys[Index+1] - ,(ParentKey->NumberOfSubKeys-Index-1)*sizeof(PKEY_OBJECT)); - ParentKey->NumberOfSubKeys--; - KeReleaseSpinLock(&CmiKeyListLock, OldIrql); -DPRINT("Dereference parent key: 0x%x\n",ParentKey); - ObDereferenceObject(ParentKey); - return STATUS_SUCCESS; - } - } + /* FIXME: If list maintained in alphabetic order, use dichotomic search */ + for (Index = 0; Index < ParentKey->NumberOfSubKeys; Index++) + { + if (ParentKey->SubKeys[Index] == KeyToRemove) + { + if (Index < ParentKey->NumberOfSubKeys-1) + RtlMoveMemory(&ParentKey->SubKeys[Index], + &ParentKey->SubKeys[Index + 1], + (ParentKey->NumberOfSubKeys - Index - 1) * sizeof(PKEY_OBJECT)); + ParentKey->NumberOfSubKeys--; + KeReleaseSpinLock(&CmiKeyListLock, OldIrql); + +DPRINT("Dereference parent key: 0x%x\n", ParentKey); + + ObDereferenceObject(ParentKey); + return STATUS_SUCCESS; + } + } KeReleaseSpinLock(&CmiKeyListLock, OldIrql); return STATUS_UNSUCCESSFUL; } + PKEY_OBJECT CmiScanKeyList(PKEY_OBJECT Parent, - PCHAR KeyName, - ULONG Attributes) + PCHAR KeyName, + ULONG Attributes) { - KIRQL OldIrql; - PKEY_OBJECT CurKey; - DWORD Index; - WORD NameSize; - NameSize=strlen(KeyName); + PKEY_OBJECT CurKey; + KIRQL OldIrql; + WORD NameSize; + DWORD Index; + + DPRINT("Scanning key list for %s (Parent %s)\n", + KeyName, Parent->Name); + + NameSize = strlen(KeyName); KeAcquireSpinLock(&CmiKeyListLock, &OldIrql); - /* FIXME : if list maintained in alphabetic order, use dichotomic search */ + /* FIXME: if list maintained in alphabetic order, use dichotomic search */ for (Index=0; Index < Parent->NumberOfSubKeys; Index++) - { - CurKey=Parent->SubKeys[Index]; - if (Attributes & OBJ_CASE_INSENSITIVE) - { - if( NameSize == CurKey->NameSize - && !_strnicmp(KeyName,CurKey->Name,NameSize)) - { - KeReleaseSpinLock(&CmiKeyListLock, OldIrql); - return CurKey; - } - } - else - { - if( NameSize == CurKey->NameSize - && !strncmp(KeyName,CurKey->Name,NameSize)) - { - KeReleaseSpinLock(&CmiKeyListLock, OldIrql); - return CurKey; - } - } - } + { + CurKey = Parent->SubKeys[Index]; + if (Attributes & OBJ_CASE_INSENSITIVE) + { + if ((NameSize == CurKey->NameSize) + && (_strnicmp(KeyName, CurKey->Name, NameSize) == 0)) + { + KeReleaseSpinLock(&CmiKeyListLock, OldIrql); + return CurKey; + } + } + else + { + if ((NameSize == CurKey->NameSize) + && (strncmp(KeyName,CurKey->Name,NameSize) == 0)) + { + KeReleaseSpinLock(&CmiKeyListLock, OldIrql); + return CurKey; + } + } + } KeReleaseSpinLock(&CmiKeyListLock, OldIrql); return NULL;