Configuration manager cleanup.

Added consistency checks.

svn path=/trunk/; revision=2716
This commit is contained in:
Casper Hornstrup 2002-03-15 19:46:07 +00:00
parent bcc0a8a082
commit 190f4b2256
5 changed files with 3770 additions and 2415 deletions

View file

@ -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*/

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -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 */

View file

@ -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;