mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 23:13:04 +00:00
work on ntopenkey forkeys insystem hive
svn path=/trunk/; revision=1368
This commit is contained in:
parent
56cd5f816c
commit
572b3bf901
1 changed files with 315 additions and 223 deletions
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: registry.c,v 1.35 2000/09/18 09:39:18 jean Exp $
|
/* $Id: registry.c,v 1.36 2000/09/21 13:45:42 jean Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -56,17 +56,18 @@ typedef DWORD BLOCK_OFFSET;
|
||||||
typedef struct _HEADER_BLOCK
|
typedef struct _HEADER_BLOCK
|
||||||
{
|
{
|
||||||
DWORD BlockId;
|
DWORD BlockId;
|
||||||
DWORD Unused1;
|
DWORD Unused1; /* file version ?*/
|
||||||
DWORD Unused2;
|
DWORD Unused2; /* file version ?*/
|
||||||
LARGE_INTEGER DateModified;
|
LARGE_INTEGER DateModified;
|
||||||
DWORD Unused3;
|
DWORD Unused3; /* registry format version ? */
|
||||||
DWORD Unused4;
|
DWORD Unused4; /* registry format version ? */
|
||||||
DWORD Unused5;
|
DWORD Unused5; /* registry format version ? */
|
||||||
DWORD Unused6;
|
DWORD Unused6; /* registry format version ? */
|
||||||
BLOCK_OFFSET RootKeyBlock;
|
BLOCK_OFFSET RootKeyBlock;
|
||||||
DWORD BlockSize;
|
DWORD BlockSize;
|
||||||
DWORD Unused7;
|
DWORD Unused7;
|
||||||
DWORD Unused8[115];
|
WCHAR FileName[64]; /* end of file name */
|
||||||
|
DWORD Unused8[83];
|
||||||
DWORD Checksum;
|
DWORD Checksum;
|
||||||
} HEADER_BLOCK, *PHEADER_BLOCK;
|
} HEADER_BLOCK, *PHEADER_BLOCK;
|
||||||
|
|
||||||
|
@ -75,6 +76,9 @@ typedef struct _HEAP_BLOCK
|
||||||
DWORD BlockId;
|
DWORD BlockId;
|
||||||
BLOCK_OFFSET BlockOffset;
|
BLOCK_OFFSET BlockOffset;
|
||||||
DWORD BlockSize;
|
DWORD BlockSize;
|
||||||
|
DWORD Unused1;
|
||||||
|
LARGE_INTEGER DateModified;
|
||||||
|
DWORD Unused2;
|
||||||
} HEAP_BLOCK, *PHEAP_BLOCK;
|
} HEAP_BLOCK, *PHEAP_BLOCK;
|
||||||
|
|
||||||
// each sub_block begin with this struct :
|
// each sub_block begin with this struct :
|
||||||
|
@ -139,16 +143,9 @@ typedef struct _VALUE_BLOCK
|
||||||
WORD Flags;
|
WORD Flags;
|
||||||
WORD Unused1;
|
WORD Unused1;
|
||||||
// FIXME : Name is char, not wchar
|
// FIXME : Name is char, not wchar
|
||||||
WCHAR Name[0]; /* warning : not zero terminated */
|
UCHAR Name[0]; /* warning : not zero terminated */
|
||||||
} VALUE_BLOCK, *PVALUE_BLOCK;
|
} VALUE_BLOCK, *PVALUE_BLOCK;
|
||||||
|
|
||||||
typedef struct _IN_MEMORY_BLOCK
|
|
||||||
{
|
|
||||||
DWORD FileOffset;
|
|
||||||
DWORD BlockSize;
|
|
||||||
PVOID *Data;
|
|
||||||
} IN_MEMORY_BLOCK, *PIN_MEMORY_BLOCK;
|
|
||||||
|
|
||||||
typedef struct _REGISTRY_FILE
|
typedef struct _REGISTRY_FILE
|
||||||
{
|
{
|
||||||
PWSTR Filename;
|
PWSTR Filename;
|
||||||
|
@ -169,11 +166,14 @@ typedef struct _KEY_OBJECT
|
||||||
CSHORT Size;
|
CSHORT Size;
|
||||||
|
|
||||||
ULONG Flags;
|
ULONG Flags;
|
||||||
WCHAR *Name;
|
WORD NameSize; // length of Name
|
||||||
|
UCHAR *Name;
|
||||||
PREGISTRY_FILE RegistryFile;
|
PREGISTRY_FILE RegistryFile;
|
||||||
PKEY_BLOCK KeyBlock;
|
PKEY_BLOCK KeyBlock;
|
||||||
struct _KEY_OBJECT *NextKey;
|
struct _KEY_OBJECT *ParentKey;
|
||||||
struct _KEY_OBJECT *SubKey;
|
DWORD NumberOfSubKeys; /* subkeys loaded in SubKeys */
|
||||||
|
DWORD SizeOfSubKeys; /* space allocated in SubKeys */
|
||||||
|
struct _KEY_OBJECT **SubKeys; /* list of subkeys loaded */
|
||||||
} KEY_OBJECT, *PKEY_OBJECT;
|
} KEY_OBJECT, *PKEY_OBJECT;
|
||||||
|
|
||||||
|
|
||||||
|
@ -181,12 +181,14 @@ typedef struct _KEY_OBJECT
|
||||||
|
|
||||||
static POBJECT_TYPE CmiKeyType = NULL;
|
static POBJECT_TYPE CmiKeyType = NULL;
|
||||||
static PREGISTRY_FILE CmiVolatileFile = NULL;
|
static PREGISTRY_FILE CmiVolatileFile = NULL;
|
||||||
static PKEY_OBJECT CmiKeyList = NULL;
|
static PKEY_OBJECT CmiRootKey = NULL;
|
||||||
|
static PKEY_OBJECT CmiMachineKey = NULL;
|
||||||
static KSPIN_LOCK CmiKeyListLock;
|
static KSPIN_LOCK CmiKeyListLock;
|
||||||
static PREGISTRY_FILE CmiSystemFile = NULL;
|
static PREGISTRY_FILE CmiSystemFile = NULL;
|
||||||
|
|
||||||
/* ----------------------------------------- Forward Declarations */
|
/* ----------------------------------------- Forward Declarations */
|
||||||
|
|
||||||
|
|
||||||
static NTSTATUS CmiObjectParse(PVOID ParsedObject,
|
static NTSTATUS CmiObjectParse(PVOID ParsedObject,
|
||||||
PVOID *NextObject,
|
PVOID *NextObject,
|
||||||
PUNICODE_STRING FullPath,
|
PUNICODE_STRING FullPath,
|
||||||
|
@ -196,9 +198,9 @@ static NTSTATUS CmiObjectParse(PVOID ParsedObject,
|
||||||
static VOID CmiObjectDelete(PVOID DeletedObject);
|
static VOID CmiObjectDelete(PVOID DeletedObject);
|
||||||
static NTSTATUS CmiBuildKeyPath(PWSTR *KeyPath,
|
static NTSTATUS CmiBuildKeyPath(PWSTR *KeyPath,
|
||||||
POBJECT_ATTRIBUTES ObjectAttributes);
|
POBJECT_ATTRIBUTES ObjectAttributes);
|
||||||
static VOID CmiAddKeyToList(PKEY_OBJECT NewKey);
|
static VOID CmiAddKeyToList(PKEY_OBJECT ParentKey,PKEY_OBJECT NewKey);
|
||||||
static VOID CmiRemoveKeyFromList(PKEY_OBJECT NewKey);
|
static VOID CmiRemoveKeyFromList(PKEY_OBJECT NewKey);
|
||||||
static PKEY_OBJECT CmiScanKeyList(PWSTR KeyNameBuf);
|
static PKEY_OBJECT CmiScanKeyList(PKEY_OBJECT Parent,PCHAR KeyNameBuf);
|
||||||
static PREGISTRY_FILE CmiCreateRegistry(PWSTR Filename);
|
static PREGISTRY_FILE CmiCreateRegistry(PWSTR Filename);
|
||||||
static NTSTATUS CmiCreateKey(IN PREGISTRY_FILE RegistryFile,
|
static NTSTATUS CmiCreateKey(IN PREGISTRY_FILE RegistryFile,
|
||||||
IN PWSTR KeyNameBuf,
|
IN PWSTR KeyNameBuf,
|
||||||
|
@ -208,12 +210,14 @@ static NTSTATUS CmiCreateKey(IN PREGISTRY_FILE RegistryFile,
|
||||||
IN PUNICODE_STRING Class,
|
IN PUNICODE_STRING Class,
|
||||||
IN ULONG CreateOptions,
|
IN ULONG CreateOptions,
|
||||||
OUT PULONG Disposition);
|
OUT PULONG Disposition);
|
||||||
|
#ifdef xxx
|
||||||
static NTSTATUS CmiFindKey(IN PREGISTRY_FILE RegistryFile,
|
static NTSTATUS CmiFindKey(IN PREGISTRY_FILE RegistryFile,
|
||||||
IN PWSTR KeyNameBuf,
|
IN PWSTR KeyNameBuf,
|
||||||
OUT PKEY_BLOCK *KeyBlock,
|
OUT PKEY_BLOCK *KeyBlock,
|
||||||
IN ACCESS_MASK DesiredAccess,
|
IN ACCESS_MASK DesiredAccess,
|
||||||
IN ULONG TitleIndex,
|
IN ULONG TitleIndex,
|
||||||
IN PUNICODE_STRING Class);
|
IN PUNICODE_STRING Class);
|
||||||
|
#endif
|
||||||
static ULONG CmiGetMaxNameLength(PREGISTRY_FILE RegistryFile,
|
static ULONG CmiGetMaxNameLength(PREGISTRY_FILE RegistryFile,
|
||||||
PKEY_BLOCK KeyBlock);
|
PKEY_BLOCK KeyBlock);
|
||||||
static ULONG CmiGetMaxClassLength(PREGISTRY_FILE RegistryFile,
|
static ULONG CmiGetMaxClassLength(PREGISTRY_FILE RegistryFile,
|
||||||
|
@ -236,7 +240,7 @@ static NTSTATUS CmiAddSubKey(IN PREGISTRY_FILE RegistryFile,
|
||||||
IN ULONG CreateOptions);
|
IN ULONG CreateOptions);
|
||||||
static NTSTATUS CmiScanKeyForValue(IN PREGISTRY_FILE RegistryFile,
|
static NTSTATUS CmiScanKeyForValue(IN PREGISTRY_FILE RegistryFile,
|
||||||
IN PKEY_BLOCK KeyBlock,
|
IN PKEY_BLOCK KeyBlock,
|
||||||
IN PWSTR ValueName,
|
IN PCHAR ValueName,
|
||||||
OUT PVALUE_BLOCK *ValueBlock);
|
OUT PVALUE_BLOCK *ValueBlock);
|
||||||
static NTSTATUS CmiGetValueFromKeyByIndex(IN PREGISTRY_FILE RegistryFile,
|
static NTSTATUS CmiGetValueFromKeyByIndex(IN PREGISTRY_FILE RegistryFile,
|
||||||
IN PKEY_BLOCK KeyBlock,
|
IN PKEY_BLOCK KeyBlock,
|
||||||
|
@ -244,13 +248,13 @@ static NTSTATUS CmiGetValueFromKeyByIndex(IN PREGISTRY_FILE RegistryFile,
|
||||||
OUT PVALUE_BLOCK *ValueBlock);
|
OUT PVALUE_BLOCK *ValueBlock);
|
||||||
static NTSTATUS CmiAddValueToKey(IN PREGISTRY_FILE RegistryFile,
|
static NTSTATUS CmiAddValueToKey(IN PREGISTRY_FILE RegistryFile,
|
||||||
IN PKEY_BLOCK KeyBlock,
|
IN PKEY_BLOCK KeyBlock,
|
||||||
IN PWSTR ValueNameBuf,
|
IN PCHAR ValueNameBuf,
|
||||||
IN ULONG Type,
|
IN ULONG Type,
|
||||||
IN PVOID Data,
|
IN PVOID Data,
|
||||||
IN ULONG DataSize);
|
IN ULONG DataSize);
|
||||||
static NTSTATUS CmiDeleteValueFromKey(IN PREGISTRY_FILE RegistryFile,
|
static NTSTATUS CmiDeleteValueFromKey(IN PREGISTRY_FILE RegistryFile,
|
||||||
IN PKEY_BLOCK KeyBlock,
|
IN PKEY_BLOCK KeyBlock,
|
||||||
IN PWSTR ValueName);
|
IN PCHAR ValueName);
|
||||||
static NTSTATUS CmiAllocateKeyBlock(IN PREGISTRY_FILE RegistryFile,
|
static NTSTATUS CmiAllocateKeyBlock(IN PREGISTRY_FILE RegistryFile,
|
||||||
OUT PKEY_BLOCK *KeyBlock,
|
OUT PKEY_BLOCK *KeyBlock,
|
||||||
IN PCHAR NewSubKeyName,
|
IN PCHAR NewSubKeyName,
|
||||||
|
@ -272,7 +276,7 @@ static NTSTATUS CmiDestroyHashTableBlock(PREGISTRY_FILE RegistryFile,
|
||||||
PHASH_TABLE_BLOCK HashBlock);
|
PHASH_TABLE_BLOCK HashBlock);
|
||||||
static NTSTATUS CmiAllocateValueBlock(IN PREGISTRY_FILE RegistryFile,
|
static NTSTATUS CmiAllocateValueBlock(IN PREGISTRY_FILE RegistryFile,
|
||||||
OUT PVALUE_BLOCK *ValueBlock,
|
OUT PVALUE_BLOCK *ValueBlock,
|
||||||
IN PWSTR ValueNameBuf,
|
IN PCHAR ValueNameBuf,
|
||||||
IN ULONG Type,
|
IN ULONG Type,
|
||||||
IN PVOID Data,
|
IN PVOID Data,
|
||||||
IN ULONG DataSize);
|
IN ULONG DataSize);
|
||||||
|
@ -307,7 +311,8 @@ CmInitializeRegistry(VOID)
|
||||||
HANDLE RootKeyHandle;
|
HANDLE RootKeyHandle;
|
||||||
UNICODE_STRING RootKeyName;
|
UNICODE_STRING RootKeyName;
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
PKEY_BLOCK KeyBlock;
|
PKEY_OBJECT NewKey;
|
||||||
|
HANDLE KeyHandle;
|
||||||
|
|
||||||
/* Initialize the Key object type */
|
/* Initialize the Key object type */
|
||||||
CmiKeyType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
|
CmiKeyType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
|
||||||
|
@ -325,34 +330,73 @@ CmInitializeRegistry(VOID)
|
||||||
CmiKeyType->Security = NULL;
|
CmiKeyType->Security = NULL;
|
||||||
CmiKeyType->QueryName = NULL;
|
CmiKeyType->QueryName = NULL;
|
||||||
CmiKeyType->OkayToClose = NULL;
|
CmiKeyType->OkayToClose = NULL;
|
||||||
|
CmiKeyType->Create = NULL;
|
||||||
RtlInitUnicodeString(&CmiKeyType->TypeName, L"Key");
|
RtlInitUnicodeString(&CmiKeyType->TypeName, L"Key");
|
||||||
|
|
||||||
/* Build the Root Key Object */
|
|
||||||
/* FIXME: This should be split into two objects, 1 system and 1 user */
|
|
||||||
RtlInitUnicodeString(&RootKeyName, REG_ROOT_KEY_NAME);
|
|
||||||
InitializeObjectAttributes(&ObjectAttributes, &RootKeyName, 0, NULL, NULL);
|
|
||||||
ObCreateObject(&RootKeyHandle,
|
|
||||||
STANDARD_RIGHTS_REQUIRED,
|
|
||||||
&ObjectAttributes,
|
|
||||||
CmiKeyType);
|
|
||||||
|
|
||||||
KeInitializeSpinLock(&CmiKeyListLock);
|
|
||||||
|
|
||||||
/* Build volitile registry store */
|
/* Build volitile registry store */
|
||||||
CmiVolatileFile = CmiCreateRegistry(NULL);
|
CmiVolatileFile = CmiCreateRegistry(NULL);
|
||||||
|
|
||||||
/* Build system registry store */
|
/* Build the Root Key Object */
|
||||||
CmiSystemFile = NULL; // CmiCreateRegistry(SYSTEM_REG_FILE);
|
RtlInitUnicodeString(&RootKeyName, REG_ROOT_KEY_NAME);
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes, &RootKeyName, 0, NULL, NULL);
|
||||||
|
NewKey=ObCreateObject(&RootKeyHandle,
|
||||||
|
STANDARD_RIGHTS_REQUIRED,
|
||||||
|
&ObjectAttributes,
|
||||||
|
CmiKeyType);
|
||||||
|
CmiRootKey = NewKey;
|
||||||
|
ObAddEntryDirectory(NameSpaceRoot, CmiRootKey, L"Registry");
|
||||||
|
Status = ObReferenceObjectByHandle(RootKeyHandle,
|
||||||
|
STANDARD_RIGHTS_REQUIRED,
|
||||||
|
ObDirectoryType,
|
||||||
|
UserMode,
|
||||||
|
(PVOID*)&CmiRootKey,
|
||||||
|
NULL);
|
||||||
|
CmiRootKey->RegistryFile = CmiVolatileFile;
|
||||||
|
CmiRootKey->KeyBlock = CmiGetBlock(CmiVolatileFile,CmiVolatileFile->HeaderBlock->RootKeyBlock);
|
||||||
|
CmiRootKey->Flags = 0;
|
||||||
|
CmiRootKey->NumberOfSubKeys=0;
|
||||||
|
CmiRootKey->SubKeys= NULL;
|
||||||
|
CmiRootKey->SizeOfSubKeys= NewKey->KeyBlock->NumberOfSubKeys;
|
||||||
|
CmiRootKey->Name=ExAllocatePool(PagedPool,strlen("Registry"));
|
||||||
|
CmiRootKey->NameSize=strlen("Registry");
|
||||||
|
memcpy(CmiRootKey->Name,"Registry",strlen("Registry"));
|
||||||
|
|
||||||
|
KeInitializeSpinLock(&CmiKeyListLock);
|
||||||
|
|
||||||
/* Create initial predefined symbolic links */
|
/* Create initial predefined symbolic links */
|
||||||
/* HKEY_LOCAL_MACHINE */
|
/* HKEY_LOCAL_MACHINE */
|
||||||
Status = CmiCreateKey(CmiVolatileFile,
|
RtlInitUnicodeString(&RootKeyName, REG_MACHINE_KEY_NAME);
|
||||||
L"Machine",
|
InitializeObjectAttributes(&ObjectAttributes, &RootKeyName, 0, NULL, NULL);
|
||||||
&KeyBlock,
|
NewKey=ObCreateObject(&KeyHandle,
|
||||||
KEY_ALL_ACCESS,
|
STANDARD_RIGHTS_REQUIRED,
|
||||||
|
&ObjectAttributes,
|
||||||
|
CmiKeyType);
|
||||||
|
Status = CmiAddSubKey(CmiVolatileFile,
|
||||||
|
CmiRootKey->KeyBlock,
|
||||||
|
&NewKey->KeyBlock,
|
||||||
|
"Machine",
|
||||||
|
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;
|
||||||
|
|
||||||
|
#ifdef xxx
|
||||||
|
/* HKEY_LOCAL_MACHINE */
|
||||||
|
Status = CmiAddSubKey(CmiVolatileFile,
|
||||||
|
CmiRootKey->KeyBlock,
|
||||||
|
&KeyBlock,
|
||||||
|
"Machine",
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
REG_OPTION_VOLATILE,
|
|
||||||
0);
|
0);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -361,13 +405,12 @@ CmInitializeRegistry(VOID)
|
||||||
CmiReleaseBlock(CmiVolatileFile, KeyBlock);
|
CmiReleaseBlock(CmiVolatileFile, KeyBlock);
|
||||||
|
|
||||||
/* HKEY_USERS */
|
/* HKEY_USERS */
|
||||||
Status = CmiCreateKey(CmiVolatileFile,
|
Status = CmiAddSubKey(CmiVolatileFile,
|
||||||
L"Users",
|
CmiRootKey->KeyBlock,
|
||||||
&KeyBlock,
|
&KeyBlock,
|
||||||
KEY_ALL_ACCESS,
|
"Users",
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
REG_OPTION_VOLATILE,
|
|
||||||
0);
|
0);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -375,6 +418,7 @@ CmInitializeRegistry(VOID)
|
||||||
}
|
}
|
||||||
CHECKPOINT;
|
CHECKPOINT;
|
||||||
CmiReleaseBlock(CmiVolatileFile, KeyBlock);
|
CmiReleaseBlock(CmiVolatileFile, KeyBlock);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* FIXME: create remaining structure needed for default handles */
|
/* FIXME: create remaining structure needed for default handles */
|
||||||
/* FIXME: load volatile registry data from ROSDTECT */
|
/* FIXME: load volatile registry data from ROSDTECT */
|
||||||
|
@ -394,6 +438,7 @@ CmInitializeRegistry2(VOID)
|
||||||
CmiSystemFile = CmiCreateRegistry(SYSTEM_REG_FILE);
|
CmiSystemFile = CmiCreateRegistry(SYSTEM_REG_FILE);
|
||||||
if( CmiSystemFile )
|
if( CmiSystemFile )
|
||||||
{
|
{
|
||||||
|
CHECKPOINT;
|
||||||
RtlInitUnicodeString(&KeyName, REG_SYSTEM_KEY_NAME);
|
RtlInitUnicodeString(&KeyName, REG_SYSTEM_KEY_NAME);
|
||||||
InitializeObjectAttributes(&ObjectAttributes, &KeyName, 0, NULL, NULL);
|
InitializeObjectAttributes(&ObjectAttributes, &KeyName, 0, NULL, NULL);
|
||||||
NewKey=ObCreateObject(&KeyHandle,
|
NewKey=ObCreateObject(&KeyHandle,
|
||||||
|
@ -402,11 +447,15 @@ CmInitializeRegistry2(VOID)
|
||||||
CmiKeyType);
|
CmiKeyType);
|
||||||
NewKey->RegistryFile = CmiSystemFile;
|
NewKey->RegistryFile = CmiSystemFile;
|
||||||
NewKey->KeyBlock = CmiGetBlock(CmiSystemFile,32);
|
NewKey->KeyBlock = CmiGetBlock(CmiSystemFile,32);
|
||||||
DPRINT("root : id = %x\n",NewKey->KeyBlock->SubBlockId);
|
|
||||||
DPRINT("root : hashOffset = %x\n",NewKey->KeyBlock->HashTableOffset);
|
|
||||||
DPRINT("root : nom = %6.6s\n",NewKey->KeyBlock->Name);
|
|
||||||
NewKey->Flags = 0;
|
NewKey->Flags = 0;
|
||||||
NewKey->NextKey = NULL;
|
NewKey->NumberOfSubKeys=0;
|
||||||
|
NewKey->SubKeys= ExAllocatePool(PagedPool
|
||||||
|
, NewKey->KeyBlock->NumberOfSubKeys * sizeof(DWORD));
|
||||||
|
NewKey->SizeOfSubKeys= NewKey->KeyBlock->NumberOfSubKeys;
|
||||||
|
NewKey->Name=ExAllocatePool(PagedPool,strlen("System"));
|
||||||
|
NewKey->NameSize=strlen("System");
|
||||||
|
memcpy(NewKey->Name,"System",strlen("System"));
|
||||||
|
CmiAddKeyToList(CmiMachineKey,NewKey);
|
||||||
/* tests :*/
|
/* tests :*/
|
||||||
{
|
{
|
||||||
HANDLE HKey;
|
HANDLE HKey;
|
||||||
|
@ -415,26 +464,17 @@ DPRINT("root : nom = %6.6s\n",NewKey->KeyBlock->Name);
|
||||||
Status = CmiScanForSubKey(CmiSystemFile,
|
Status = CmiScanForSubKey(CmiSystemFile,
|
||||||
NewKey->KeyBlock,
|
NewKey->KeyBlock,
|
||||||
&SubKeyBlock,
|
&SubKeyBlock,
|
||||||
L"ControlSet001",
|
"ControlSet001",
|
||||||
KEY_READ);
|
KEY_READ);
|
||||||
CHECKPOINT;
|
|
||||||
if(NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT("found subkey ,ptr=%x\n",SubKeyBlock);
|
|
||||||
DPRINT(" Id=%x\n",SubKeyBlock->SubBlockId);
|
|
||||||
DPRINT(" Type=%x\n",SubKeyBlock->Type);
|
|
||||||
DPRINT(" parent=%x\n",SubKeyBlock->ParentKeyOffset);
|
|
||||||
DPRINT(" name=%x\n",SubKeyBlock->Name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DPRINT("not found subkey ControlSet001\n");
|
|
||||||
}
|
|
||||||
//RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\Software\\Windows");
|
//RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\Software\\Windows");
|
||||||
RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\System\\ControlSet001");
|
RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\System\\ControlSet001");
|
||||||
InitializeObjectAttributes(&ObjectAttributes, &KeyName, 0, NULL, NULL);
|
InitializeObjectAttributes(&ObjectAttributes, &KeyName, 0, NULL, NULL);
|
||||||
Status = NtOpenKey ( &HKey, KEY_READ , &ObjectAttributes);
|
Status = NtOpenKey ( &HKey, KEY_READ , &ObjectAttributes);
|
||||||
DPRINT(" NtOpenKey = %x, HKey=%x\n",Status,HKey);
|
DPRINT(" NtOpenKey = %x, HKey=%x\n",Status,HKey);
|
||||||
|
//for(;;)
|
||||||
|
//{
|
||||||
|
//__asm__ ("hlt\n\t");
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -467,6 +507,7 @@ NtCreateKey (
|
||||||
|
|
||||||
assert(ObjectAttributes != NULL);
|
assert(ObjectAttributes != NULL);
|
||||||
|
|
||||||
|
/* FIXME : FileToUse depends also from Parent Key */
|
||||||
FileToUse = (CreateOptions & REG_OPTION_VOLATILE) ?
|
FileToUse = (CreateOptions & REG_OPTION_VOLATILE) ?
|
||||||
CmiVolatileFile : CmiSystemFile;
|
CmiVolatileFile : CmiSystemFile;
|
||||||
|
|
||||||
|
@ -478,7 +519,9 @@ NtCreateKey (
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Scan the key list to see if key already open */
|
/* Scan the key list to see if key already open */
|
||||||
CurKey = CmiScanKeyList(KeyNameBuf);
|
/* FIXME : walk through the tree of opened keys */
|
||||||
|
// CurKey = CmiScanKeyList(KeyNameBuf);
|
||||||
|
CurKey = NULL;
|
||||||
if (CurKey != NULL)
|
if (CurKey != NULL)
|
||||||
{
|
{
|
||||||
/* Unmark the key if the key has been marked for Delete */
|
/* Unmark the key if the key has been marked for Delete */
|
||||||
|
@ -527,10 +570,11 @@ NtCreateKey (
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
NewKey->Flags = 0;
|
NewKey->Flags = 0;
|
||||||
NewKey->Name = KeyNameBuf;
|
NewKey->Name = KeyBlock->Name;
|
||||||
|
NewKey->NameSize = KeyBlock->NameSize;
|
||||||
NewKey->KeyBlock = KeyBlock;
|
NewKey->KeyBlock = KeyBlock;
|
||||||
NewKey->RegistryFile = FileToUse;
|
NewKey->RegistryFile = FileToUse;
|
||||||
CmiAddKeyToList(NewKey);
|
CmiAddKeyToList(CurKey,NewKey);
|
||||||
Status = ObCreateHandle(PsGetCurrentProcess(),
|
Status = ObCreateHandle(PsGetCurrentProcess(),
|
||||||
NewKey,
|
NewKey,
|
||||||
DesiredAccess,
|
DesiredAccess,
|
||||||
|
@ -793,7 +837,8 @@ NtEnumerateValueKey (
|
||||||
ValueBasicInformation->Type = ValueBlock->DataType;
|
ValueBasicInformation->Type = ValueBlock->DataType;
|
||||||
ValueBasicInformation->NameLength =
|
ValueBasicInformation->NameLength =
|
||||||
(ValueBlock->NameSize + 1) * sizeof(WCHAR);
|
(ValueBlock->NameSize + 1) * sizeof(WCHAR);
|
||||||
wcscpy(ValueBasicInformation->Name, ValueBlock->Name);
|
mbstowcs(ValueBasicInformation->Name, ValueBlock->Name,ValueBlock->NameSize);
|
||||||
|
ValueBasicInformation->Name[ValueBlock->NameSize]=0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -838,7 +883,8 @@ NtEnumerateValueKey (
|
||||||
ValueFullInformation->DataLength = ValueBlock->DataSize;
|
ValueFullInformation->DataLength = ValueBlock->DataSize;
|
||||||
ValueFullInformation->NameLength =
|
ValueFullInformation->NameLength =
|
||||||
(ValueBlock->NameSize + 1) * sizeof(WCHAR);
|
(ValueBlock->NameSize + 1) * sizeof(WCHAR);
|
||||||
wcscpy(ValueFullInformation->Name, ValueBlock->Name);
|
mbstowcs(ValueFullInformation->Name, ValueBlock->Name,ValueBlock->NameSize);
|
||||||
|
ValueFullInformation->Name[ValueBlock->NameSize]=0;
|
||||||
DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset);
|
DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset);
|
||||||
RtlCopyMemory(&ValueFullInformation->Name[ValueBlock->NameSize + 1],
|
RtlCopyMemory(&ValueFullInformation->Name[ValueBlock->NameSize + 1],
|
||||||
DataBlock,
|
DataBlock,
|
||||||
|
@ -876,6 +922,41 @@ NtOpenKey (
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes
|
IN POBJECT_ATTRIBUTES ObjectAttributes
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PVOID Object;
|
||||||
|
|
||||||
|
DPRINT("NtOpenKey (Name %wZ)\n",
|
||||||
|
ObjectAttributes->ObjectName);
|
||||||
|
|
||||||
|
Status = ObReferenceObjectByName(
|
||||||
|
ObjectAttributes->ObjectName,
|
||||||
|
ObjectAttributes->Attributes,
|
||||||
|
NULL,
|
||||||
|
DesiredAccess,
|
||||||
|
CmiKeyType,
|
||||||
|
UserMode,
|
||||||
|
NULL,
|
||||||
|
& Object
|
||||||
|
);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = ObCreateHandle(
|
||||||
|
PsGetCurrentProcess(),
|
||||||
|
Object,
|
||||||
|
DesiredAccess,
|
||||||
|
FALSE,
|
||||||
|
KeyHandle
|
||||||
|
);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
#ifdef xxx
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PWSTR KeyNameBuf;
|
PWSTR KeyNameBuf;
|
||||||
PREGISTRY_FILE FileToUse;
|
PREGISTRY_FILE FileToUse;
|
||||||
|
@ -889,8 +970,10 @@ NtOpenKey (
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME : walk through the tree of opened keys */
|
||||||
/* Scan the key list to see if key already open */
|
/* Scan the key list to see if key already open */
|
||||||
CurKey = CmiScanKeyList(KeyNameBuf);
|
//CurKey = CmiScanKeyList(KeyNameBuf);
|
||||||
|
CurKey = NULL;
|
||||||
if (CurKey != NULL)
|
if (CurKey != NULL)
|
||||||
{
|
{
|
||||||
/* Fail if the key has been deleted */
|
/* Fail if the key has been deleted */
|
||||||
|
@ -947,10 +1030,11 @@ NtOpenKey (
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
NewKey->Flags = 0;
|
NewKey->Flags = 0;
|
||||||
NewKey->Name = KeyNameBuf;
|
NewKey->Name = KeyBlock->Name;
|
||||||
|
NewKey->NameSize = KeyBlock->NameSize;
|
||||||
NewKey->RegistryFile = FileToUse;
|
NewKey->RegistryFile = FileToUse;
|
||||||
NewKey->KeyBlock = KeyBlock;
|
NewKey->KeyBlock = KeyBlock;
|
||||||
CmiAddKeyToList(NewKey);
|
CmiAddKeyToList(CurKey,NewKey);
|
||||||
Status = ObCreateHandle(PsGetCurrentProcess(),
|
Status = ObCreateHandle(PsGetCurrentProcess(),
|
||||||
NewKey,
|
NewKey,
|
||||||
DesiredAccess,
|
DesiredAccess,
|
||||||
|
@ -958,6 +1042,7 @@ NtOpenKey (
|
||||||
KeyHandle);
|
KeyHandle);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1118,6 +1203,10 @@ NtQueryValueKey (
|
||||||
PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation;
|
PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation;
|
||||||
PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation;
|
PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation;
|
||||||
PKEY_VALUE_FULL_INFORMATION ValueFullInformation;
|
PKEY_VALUE_FULL_INFORMATION ValueFullInformation;
|
||||||
|
char ValueName2[MAX_PATH];
|
||||||
|
|
||||||
|
wcstombs(ValueName2,ValueName->Buffer,ValueName->Length);
|
||||||
|
ValueName2[ValueName->Length]=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,
|
Status = ObReferenceObjectByHandle(KeyHandle,
|
||||||
|
@ -1138,7 +1227,7 @@ NtQueryValueKey (
|
||||||
/* Get Value block of interest */
|
/* Get Value block of interest */
|
||||||
Status = CmiScanKeyForValue(RegistryFile,
|
Status = CmiScanKeyForValue(RegistryFile,
|
||||||
KeyBlock,
|
KeyBlock,
|
||||||
ValueName->Buffer,
|
ValueName2,
|
||||||
&ValueBlock);
|
&ValueBlock);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -1162,7 +1251,8 @@ NtQueryValueKey (
|
||||||
ValueBasicInformation->TitleIndex = 0;
|
ValueBasicInformation->TitleIndex = 0;
|
||||||
ValueBasicInformation->Type = ValueBlock->DataType;
|
ValueBasicInformation->Type = ValueBlock->DataType;
|
||||||
ValueBasicInformation->NameLength = ValueBlock->NameSize;
|
ValueBasicInformation->NameLength = ValueBlock->NameSize;
|
||||||
wcscpy(ValueBasicInformation->Name, ValueBlock->Name);
|
mbstowcs(ValueBasicInformation->Name, ValueBlock->Name,ValueBlock->NameSize);
|
||||||
|
ValueBasicInformation->Name[ValueBlock->NameSize]=0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1206,7 +1296,8 @@ NtQueryValueKey (
|
||||||
ValueBlock->NameSize * sizeof(WCHAR);
|
ValueBlock->NameSize * sizeof(WCHAR);
|
||||||
ValueFullInformation->DataLength = ValueBlock->DataSize;
|
ValueFullInformation->DataLength = ValueBlock->DataSize;
|
||||||
ValueFullInformation->NameLength = ValueBlock->NameSize;
|
ValueFullInformation->NameLength = ValueBlock->NameSize;
|
||||||
wcscpy(ValueFullInformation->Name, ValueBlock->Name);
|
mbstowcs(ValueFullInformation->Name, ValueBlock->Name,ValueBlock->NameSize);
|
||||||
|
ValueFullInformation->Name[ValueBlock->NameSize]=0;
|
||||||
DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset);
|
DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset);
|
||||||
RtlCopyMemory(&ValueFullInformation->Name[ValueBlock->NameSize + 1],
|
RtlCopyMemory(&ValueFullInformation->Name[ValueBlock->NameSize + 1],
|
||||||
DataBlock,
|
DataBlock,
|
||||||
|
@ -1242,6 +1333,10 @@ NtSetValueKey (
|
||||||
PREGISTRY_FILE RegistryFile;
|
PREGISTRY_FILE RegistryFile;
|
||||||
PKEY_BLOCK KeyBlock;
|
PKEY_BLOCK KeyBlock;
|
||||||
PVALUE_BLOCK ValueBlock;
|
PVALUE_BLOCK ValueBlock;
|
||||||
|
char ValueName2[MAX_PATH];
|
||||||
|
|
||||||
|
wcstombs(ValueName2,ValueName->Buffer,ValueName->Length);
|
||||||
|
ValueName2[ValueName->Length]=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,
|
Status = ObReferenceObjectByHandle(KeyHandle,
|
||||||
|
@ -1260,7 +1355,7 @@ NtSetValueKey (
|
||||||
RegistryFile = KeyObject->RegistryFile;
|
RegistryFile = KeyObject->RegistryFile;
|
||||||
Status = CmiScanKeyForValue(RegistryFile,
|
Status = CmiScanKeyForValue(RegistryFile,
|
||||||
KeyBlock,
|
KeyBlock,
|
||||||
ValueName->Buffer,
|
ValueName2,
|
||||||
&ValueBlock);
|
&ValueBlock);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -1271,7 +1366,7 @@ NtSetValueKey (
|
||||||
{
|
{
|
||||||
Status = CmiAddValueToKey(RegistryFile,
|
Status = CmiAddValueToKey(RegistryFile,
|
||||||
KeyBlock,
|
KeyBlock,
|
||||||
ValueName->Buffer,
|
ValueName2,
|
||||||
Type,
|
Type,
|
||||||
Data,
|
Data,
|
||||||
DataSize);
|
DataSize);
|
||||||
|
@ -1300,6 +1395,10 @@ NtDeleteValueKey (
|
||||||
PKEY_OBJECT KeyObject;
|
PKEY_OBJECT KeyObject;
|
||||||
PREGISTRY_FILE RegistryFile;
|
PREGISTRY_FILE RegistryFile;
|
||||||
PKEY_BLOCK KeyBlock;
|
PKEY_BLOCK KeyBlock;
|
||||||
|
char ValueName2[MAX_PATH];
|
||||||
|
|
||||||
|
wcstombs(ValueName2,ValueName->Buffer,ValueName->Length);
|
||||||
|
ValueName2[ValueName->Length]=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,
|
Status = ObReferenceObjectByHandle(KeyHandle,
|
||||||
|
@ -1318,7 +1417,7 @@ NtDeleteValueKey (
|
||||||
RegistryFile = KeyObject->RegistryFile;
|
RegistryFile = KeyObject->RegistryFile;
|
||||||
Status = CmiDeleteValueFromKey(RegistryFile,
|
Status = CmiDeleteValueFromKey(RegistryFile,
|
||||||
KeyBlock,
|
KeyBlock,
|
||||||
ValueName->Buffer);
|
ValueName2);
|
||||||
ObDereferenceObject(KeyObject);
|
ObDereferenceObject(KeyObject);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
|
@ -1522,105 +1621,82 @@ static NTSTATUS CmiObjectParse(PVOID ParsedObject,
|
||||||
PWSTR *Path,
|
PWSTR *Path,
|
||||||
POBJECT_TYPE ObjectType)
|
POBJECT_TYPE ObjectType)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
CHAR cPath[MAX_PATH];
|
||||||
/* FIXME: this should be allocated based on the largest subkey name */
|
PWSTR end;
|
||||||
CHAR CurKeyName[260];
|
PKEY_OBJECT FoundObject;
|
||||||
PWSTR Remainder, NextSlash;
|
PKEY_OBJECT ParsedKey=ParsedObject;
|
||||||
PREGISTRY_FILE RegistryFile;
|
PKEY_BLOCK SubKeyBlock;
|
||||||
PKEY_OBJECT NewKeyObject;
|
NTSTATUS Status;
|
||||||
HANDLE KeyHandle;
|
HANDLE KeyHandle;
|
||||||
PKEY_BLOCK CurKeyBlock, SubKeyBlock;
|
DPRINT("CmiObjectParse Object %x Path %S FullPath %S\n",ParsedObject
|
||||||
|
, *Path,FullPath->Buffer);
|
||||||
Status = STATUS_SUCCESS;
|
*NextObject = NULL;
|
||||||
|
if ((*Path) == NULL)
|
||||||
/* FIXME: it should probably get this from ParsedObject */
|
{
|
||||||
RegistryFile = CmiVolatileFile;
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
/* Scan key object list for key already open */
|
|
||||||
NewKeyObject = CmiScanKeyList((*Path) + 1);
|
end = wcschr((*Path)+1, '\\');
|
||||||
if (NewKeyObject != NULL)
|
if (end != NULL)
|
||||||
{
|
{
|
||||||
/* Return reference if found */
|
*end = 0;
|
||||||
ObReferenceObjectByPointer(NewKeyObject,
|
}
|
||||||
STANDARD_RIGHTS_REQUIRED,
|
wcstombs(cPath,(*Path)+1,wcslen((*Path)+1));
|
||||||
NULL,
|
cPath[wcslen( (*Path)+1)]=0;
|
||||||
UserMode);
|
FoundObject = CmiScanKeyList(ParsedKey,cPath);
|
||||||
*Path = NULL;
|
if (FoundObject == NULL)
|
||||||
|
{
|
||||||
// return NewKeyObject;
|
Status = CmiScanForSubKey(ParsedKey->RegistryFile,
|
||||||
//FIXME
|
ParsedKey->KeyBlock,
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
CurKeyBlock = CmiGetBlock(RegistryFile,
|
|
||||||
RegistryFile->HeaderBlock->RootKeyBlock);
|
|
||||||
|
|
||||||
/* Loop through each key level and find the needed subkey */
|
|
||||||
Remainder = (*Path) + 1;
|
|
||||||
while (NT_SUCCESS(Status) && *Remainder != 0)
|
|
||||||
{
|
|
||||||
NextSlash = wcschr(Remainder, L'\\');
|
|
||||||
|
|
||||||
/* Copy just the current subkey name to a buffer */
|
|
||||||
if (NextSlash != NULL)
|
|
||||||
{
|
|
||||||
wcstombs(CurKeyName, Remainder, NextSlash - Remainder);
|
|
||||||
CurKeyName[NextSlash - Remainder] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
wcstombs(CurKeyName, Remainder, wcslen(Remainder) + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Verify existance of CurKeyName */
|
|
||||||
Status = CmiScanForSubKey(RegistryFile,
|
|
||||||
CurKeyBlock,
|
|
||||||
&SubKeyBlock,
|
&SubKeyBlock,
|
||||||
CurKeyName,
|
cPath,
|
||||||
STANDARD_RIGHTS_REQUIRED);
|
0);
|
||||||
if (!NT_SUCCESS(Status))
|
if(!NT_SUCCESS(Status) || SubKeyBlock == NULL)
|
||||||
{
|
{
|
||||||
continue;
|
if (end != NULL)
|
||||||
}
|
{
|
||||||
if (SubKeyBlock == NULL)
|
*end = '\\';
|
||||||
{
|
}
|
||||||
Status = STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
continue;
|
}
|
||||||
}
|
/* Create new key object and put into linked list */
|
||||||
CmiReleaseBlock(RegistryFile, CurKeyBlock);
|
FoundObject = ObCreateObject(&KeyHandle,
|
||||||
CurKeyBlock = SubKeyBlock;
|
STANDARD_RIGHTS_REQUIRED,
|
||||||
|
NULL,
|
||||||
|
CmiKeyType);
|
||||||
|
if (FoundObject == NULL)
|
||||||
|
{
|
||||||
|
//FIXME : return the good error code
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
FoundObject->Flags = 0;
|
||||||
|
FoundObject->Name = SubKeyBlock->Name;
|
||||||
|
FoundObject->NameSize = SubKeyBlock->NameSize;
|
||||||
|
FoundObject->KeyBlock = SubKeyBlock;
|
||||||
|
FoundObject->RegistryFile = ParsedKey->RegistryFile;
|
||||||
|
CmiAddKeyToList(ParsedKey,FoundObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
ObReferenceObjectByPointer(FoundObject,
|
||||||
|
STANDARD_RIGHTS_REQUIRED,
|
||||||
|
NULL,
|
||||||
|
UserMode);
|
||||||
|
|
||||||
|
if (end != NULL)
|
||||||
|
{
|
||||||
|
*end = '\\';
|
||||||
|
*Path = end;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*Path = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*NextObject = FoundObject;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
if (NextSlash != NULL)
|
|
||||||
{
|
|
||||||
Remainder = NextSlash + 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Remainder = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create new key object and put into linked list */
|
|
||||||
NewKeyObject = ObCreateObject(&KeyHandle,
|
|
||||||
STANDARD_RIGHTS_REQUIRED,
|
|
||||||
NULL,
|
|
||||||
CmiKeyType);
|
|
||||||
if (NewKeyObject == NULL)
|
|
||||||
{
|
|
||||||
//FIXME : return the good error code
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
NewKeyObject->Flags = 0;
|
|
||||||
NewKeyObject->Name = ExAllocatePool(NonPagedPool,
|
|
||||||
wcslen(*Path) * sizeof(WCHAR));
|
|
||||||
wcscpy(NewKeyObject->Name, (*Path) + 1);
|
|
||||||
NewKeyObject->KeyBlock = CurKeyBlock;
|
|
||||||
NewKeyObject->RegistryFile = RegistryFile;
|
|
||||||
CmiAddKeyToList(NewKeyObject);
|
|
||||||
*Path = (Remainder != NULL) ? Remainder - 1 : NULL;
|
|
||||||
|
|
||||||
NextObject = (PVOID)NewKeyObject;
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID
|
static VOID
|
||||||
|
@ -1710,7 +1786,7 @@ CmiBuildKeyPath(PWSTR *KeyPath, POBJECT_ATTRIBUTES ObjectAttributes)
|
||||||
KeyObject = (PKEY_OBJECT) ObjectBody;
|
KeyObject = (PKEY_OBJECT) ObjectBody;
|
||||||
|
|
||||||
/* Add size of Name from RootDirectory object to KeyNameSize */
|
/* Add size of Name from RootDirectory object to KeyNameSize */
|
||||||
KeyNameSize = wcslen(KeyObject->Name) * sizeof(WCHAR);
|
KeyNameSize = (KeyObject->NameSize) * sizeof(WCHAR);
|
||||||
|
|
||||||
/* Add 1 to KeyNamesize for '\\' */
|
/* Add 1 to KeyNamesize for '\\' */
|
||||||
KeyNameSize += sizeof(WCHAR);
|
KeyNameSize += sizeof(WCHAR);
|
||||||
|
@ -1760,10 +1836,10 @@ CmiBuildKeyPath(PWSTR *KeyPath, POBJECT_ATTRIBUTES ObjectAttributes)
|
||||||
KeyObject = (PKEY_OBJECT) ObjectBody;
|
KeyObject = (PKEY_OBJECT) ObjectBody;
|
||||||
|
|
||||||
/* Copy Name from RootDirectory object to KeyNameBuf */
|
/* Copy Name from RootDirectory object to KeyNameBuf */
|
||||||
wcscpy(KeyNameBuf, KeyObject->Name);
|
mbstowcs(KeyNameBuf, KeyObject->Name,KeyObject->NameSize);
|
||||||
|
|
||||||
/* Append '\\' onto KeyNameBuf */
|
/* Append '\\' onto KeyNameBuf */
|
||||||
wcscat(KeyNameBuf, L"\\");
|
KeyNameBuf[KeyObject->NameSize]=0;
|
||||||
|
|
||||||
/* Append ObjectName onto KeyNameBuf */
|
/* Append ObjectName onto KeyNameBuf */
|
||||||
wcscat(KeyNameBuf, ObjectAttributes->ObjectName->Buffer);
|
wcscat(KeyNameBuf, ObjectAttributes->ObjectName->Buffer);
|
||||||
|
@ -1781,13 +1857,25 @@ CmiBuildKeyPath(PWSTR *KeyPath, POBJECT_ATTRIBUTES ObjectAttributes)
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID
|
static VOID
|
||||||
CmiAddKeyToList(PKEY_OBJECT NewKey)
|
CmiAddKeyToList(PKEY_OBJECT ParentKey,PKEY_OBJECT NewKey)
|
||||||
{
|
{
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
|
|
||||||
KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
|
KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
|
||||||
NewKey->NextKey = CmiKeyList;
|
if (ParentKey->SizeOfSubKeys <= ParentKey->NumberOfSubKeys)
|
||||||
CmiKeyList = NewKey;
|
{
|
||||||
|
PKEY_OBJECT *tmpSubKeys = ExAllocatePool(PagedPool
|
||||||
|
, (ParentKey->KeyBlock->NumberOfSubKeys+1) * sizeof(DWORD));
|
||||||
|
if(ParentKey->NumberOfSubKeys > 0)
|
||||||
|
memcpy(tmpSubKeys,ParentKey->SubKeys
|
||||||
|
,ParentKey->KeyBlock->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 */
|
||||||
|
ParentKey->SubKeys[ParentKey->NumberOfSubKeys++] = NewKey;
|
||||||
|
NewKey->ParentKey = ParentKey;
|
||||||
KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
|
KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1795,43 +1883,48 @@ static VOID
|
||||||
CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove)
|
CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove)
|
||||||
{
|
{
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
PKEY_OBJECT CurKey;
|
PKEY_OBJECT ParentKey;
|
||||||
|
DWORD Index;
|
||||||
|
|
||||||
|
ParentKey=KeyToRemove->ParentKey;
|
||||||
KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
|
KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
|
||||||
if (CmiKeyList == KeyToRemove)
|
for (Index=0; Index < ParentKey->NumberOfSubKeys; Index++)
|
||||||
|
{
|
||||||
|
if(ParentKey->SubKeys[Index] == KeyToRemove)
|
||||||
{
|
{
|
||||||
CmiKeyList = CmiKeyList->NextKey;
|
memcpy(&ParentKey->SubKeys[Index]
|
||||||
}
|
,&ParentKey->SubKeys[Index+1]
|
||||||
else
|
,(ParentKey->NumberOfSubKeys-Index-1)*sizeof(PKEY_OBJECT));
|
||||||
{
|
ParentKey->NumberOfSubKeys--;
|
||||||
CurKey = CmiKeyList;
|
break;
|
||||||
while (CurKey != NULL && CurKey->NextKey != KeyToRemove)
|
|
||||||
{
|
|
||||||
CurKey = CurKey->NextKey;
|
|
||||||
}
|
|
||||||
if (CurKey != NULL)
|
|
||||||
{
|
|
||||||
CurKey->NextKey = KeyToRemove->NextKey;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
|
KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PKEY_OBJECT
|
static PKEY_OBJECT
|
||||||
CmiScanKeyList(PWSTR KeyName)
|
CmiScanKeyList(PKEY_OBJECT Parent,PCHAR KeyName)
|
||||||
{
|
{
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
PKEY_OBJECT CurKey;
|
PKEY_OBJECT CurKey;
|
||||||
|
DWORD Index;
|
||||||
|
WORD NameSize;
|
||||||
|
|
||||||
|
NameSize=strlen(KeyName);
|
||||||
KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
|
KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
|
||||||
CurKey = CmiKeyList;
|
for (Index=0; Index < Parent->NumberOfSubKeys; Index++)
|
||||||
while (CurKey != NULL && wcscmp(KeyName, CurKey->Name) != 0)
|
{
|
||||||
|
CurKey=Parent->SubKeys[Index];
|
||||||
|
if( NameSize == CurKey->NameSize
|
||||||
|
&& !memcmp(KeyName,CurKey->Name,NameSize))
|
||||||
{
|
{
|
||||||
CurKey = CurKey->NextKey;
|
KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
|
||||||
|
return CurKey;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
|
KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
|
||||||
|
|
||||||
return CurKey;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PREGISTRY_FILE
|
static PREGISTRY_FILE
|
||||||
|
@ -2032,6 +2125,7 @@ CHECKPOINT;
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef xxx
|
||||||
static NTSTATUS
|
static NTSTATUS
|
||||||
CmiFindKey(IN PREGISTRY_FILE RegistryFile,
|
CmiFindKey(IN PREGISTRY_FILE RegistryFile,
|
||||||
IN PWSTR KeyNameBuf,
|
IN PWSTR KeyNameBuf,
|
||||||
|
@ -2107,6 +2201,7 @@ CmiFindKey(IN PREGISTRY_FILE RegistryFile,
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static ULONG
|
static ULONG
|
||||||
CmiGetMaxNameLength(PREGISTRY_FILE RegistryFile,
|
CmiGetMaxNameLength(PREGISTRY_FILE RegistryFile,
|
||||||
|
@ -2250,28 +2345,27 @@ CmiScanForSubKey(IN PREGISTRY_FILE RegistryFile,
|
||||||
PKEY_BLOCK CurSubKeyBlock;
|
PKEY_BLOCK CurSubKeyBlock;
|
||||||
WORD KeyLength = strlen(KeyName);
|
WORD KeyLength = strlen(KeyName);
|
||||||
|
|
||||||
|
DPRINT("CmiScanForSubKey %s,file %x\n",KeyName,RegistryFile);
|
||||||
HashBlock = CmiGetBlock(RegistryFile, KeyBlock->HashTableOffset);
|
HashBlock = CmiGetBlock(RegistryFile, KeyBlock->HashTableOffset);
|
||||||
*SubKeyBlock = NULL;
|
*SubKeyBlock = NULL;
|
||||||
if (HashBlock == NULL)
|
if (HashBlock == NULL)
|
||||||
{
|
{
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
DPRINT("hash=%x,hash.id=%x\n",HashBlock,HashBlock->SubBlockId);
|
for (Idx = 0; Idx < HashBlock->HashTableSize; Idx++)
|
||||||
// for (Idx = 0; Idx < HashBlock->HashTableSize; Idx++)
|
// for (Idx = 0; Idx < KeyBlock->NumberOfSubKeys; Idx++)
|
||||||
for (Idx = 0; Idx < KeyBlock->NumberOfSubKeys; Idx++)
|
|
||||||
{
|
{
|
||||||
DPRINT("&hash=%x,hash=%4.4s\n",&HashBlock->Table[Idx].HashValue,&HashBlock->Table[Idx].HashValue);
|
|
||||||
if (HashBlock->Table[Idx].KeyOffset != 0 &&
|
if (HashBlock->Table[Idx].KeyOffset != 0 &&
|
||||||
HashBlock->Table[Idx].KeyOffset != -1 &&
|
HashBlock->Table[Idx].KeyOffset != -1 &&
|
||||||
!strncmp(KeyName, (PCHAR) &HashBlock->Table[Idx].HashValue, 4))
|
!strncmp(KeyName, (PCHAR) &HashBlock->Table[Idx].HashValue, 4))
|
||||||
{
|
{
|
||||||
CHECKPOINT;
|
|
||||||
CurSubKeyBlock = CmiGetBlock(RegistryFile,
|
CurSubKeyBlock = CmiGetBlock(RegistryFile,
|
||||||
HashBlock->Table[Idx].KeyOffset);
|
HashBlock->Table[Idx].KeyOffset);
|
||||||
if ( CurSubKeyBlock->NameSize == KeyLength
|
if ( CurSubKeyBlock->NameSize == KeyLength
|
||||||
&& !memcmp(KeyName, CurSubKeyBlock->Name, KeyLength))
|
&& !memcmp(KeyName, CurSubKeyBlock->Name, KeyLength))
|
||||||
{
|
{
|
||||||
*SubKeyBlock = CurSubKeyBlock;
|
*SubKeyBlock = CurSubKeyBlock;
|
||||||
|
DPRINT("CmiScanForSubKey : found %s\n",KeyName);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2280,7 +2374,6 @@ CHECKPOINT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CHECKPOINT;
|
|
||||||
|
|
||||||
CmiReleaseBlock(RegistryFile, HashBlock);
|
CmiReleaseBlock(RegistryFile, HashBlock);
|
||||||
|
|
||||||
|
@ -2352,7 +2445,7 @@ CmiAddSubKey(PREGISTRY_FILE RegistryFile,
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
KeyBlock->NumberOfSubKeys++;
|
KeyBlock->NumberOfSubKeys++;
|
||||||
*SubKeyBlock = NewKeyBlock;
|
if(SubKeyBlock) *SubKeyBlock = NewKeyBlock;
|
||||||
}
|
}
|
||||||
CmiReleaseBlock(RegistryFile, HashBlock);
|
CmiReleaseBlock(RegistryFile, HashBlock);
|
||||||
|
|
||||||
|
@ -2362,7 +2455,7 @@ CmiAddSubKey(PREGISTRY_FILE RegistryFile,
|
||||||
static NTSTATUS
|
static NTSTATUS
|
||||||
CmiScanKeyForValue(IN PREGISTRY_FILE RegistryFile,
|
CmiScanKeyForValue(IN PREGISTRY_FILE RegistryFile,
|
||||||
IN PKEY_BLOCK KeyBlock,
|
IN PKEY_BLOCK KeyBlock,
|
||||||
IN PWSTR ValueName,
|
IN PCHAR ValueName,
|
||||||
OUT PVALUE_BLOCK *ValueBlock)
|
OUT PVALUE_BLOCK *ValueBlock)
|
||||||
{
|
{
|
||||||
ULONG Idx;
|
ULONG Idx;
|
||||||
|
@ -2381,7 +2474,8 @@ CmiScanKeyForValue(IN PREGISTRY_FILE RegistryFile,
|
||||||
CurValueBlock = CmiGetBlock(RegistryFile,
|
CurValueBlock = CmiGetBlock(RegistryFile,
|
||||||
ValueListBlock->Values[Idx]);
|
ValueListBlock->Values[Idx]);
|
||||||
if (CurValueBlock != NULL &&
|
if (CurValueBlock != NULL &&
|
||||||
!wcscmp(CurValueBlock->Name, ValueName))
|
CurValueBlock->NameSize == strlen(ValueName) &&
|
||||||
|
!memcmp(CurValueBlock->Name, ValueName,strlen(ValueName)))
|
||||||
{
|
{
|
||||||
*ValueBlock = CurValueBlock;
|
*ValueBlock = CurValueBlock;
|
||||||
break;
|
break;
|
||||||
|
@ -2430,7 +2524,7 @@ CmiGetValueFromKeyByIndex(IN PREGISTRY_FILE RegistryFile,
|
||||||
static NTSTATUS
|
static NTSTATUS
|
||||||
CmiAddValueToKey(IN PREGISTRY_FILE RegistryFile,
|
CmiAddValueToKey(IN PREGISTRY_FILE RegistryFile,
|
||||||
IN PKEY_BLOCK KeyBlock,
|
IN PKEY_BLOCK KeyBlock,
|
||||||
IN PWSTR ValueNameBuf,
|
IN PCHAR ValueNameBuf,
|
||||||
IN ULONG Type,
|
IN ULONG Type,
|
||||||
IN PVOID Data,
|
IN PVOID Data,
|
||||||
IN ULONG DataSize)
|
IN ULONG DataSize)
|
||||||
|
@ -2499,7 +2593,7 @@ CmiAddValueToKey(IN PREGISTRY_FILE RegistryFile,
|
||||||
static NTSTATUS
|
static NTSTATUS
|
||||||
CmiDeleteValueFromKey(IN PREGISTRY_FILE RegistryFile,
|
CmiDeleteValueFromKey(IN PREGISTRY_FILE RegistryFile,
|
||||||
IN PKEY_BLOCK KeyBlock,
|
IN PKEY_BLOCK KeyBlock,
|
||||||
IN PWSTR ValueName)
|
IN PCHAR ValueName)
|
||||||
{
|
{
|
||||||
ULONG Idx;
|
ULONG Idx;
|
||||||
PVALUE_LIST_BLOCK ValueListBlock;
|
PVALUE_LIST_BLOCK ValueListBlock;
|
||||||
|
@ -2516,7 +2610,8 @@ CmiDeleteValueFromKey(IN PREGISTRY_FILE RegistryFile,
|
||||||
CurValueBlock = CmiGetBlock(RegistryFile,
|
CurValueBlock = CmiGetBlock(RegistryFile,
|
||||||
ValueListBlock->Values[Idx]);
|
ValueListBlock->Values[Idx]);
|
||||||
if (CurValueBlock != NULL &&
|
if (CurValueBlock != NULL &&
|
||||||
!wcscmp(CurValueBlock->Name, ValueName))
|
CurValueBlock->NameSize == strlen(ValueName) &&
|
||||||
|
!memcmp(CurValueBlock->Name, ValueName,strlen(ValueName)))
|
||||||
{
|
{
|
||||||
if (KeyBlock->NumberOfValues - 1 < Idx)
|
if (KeyBlock->NumberOfValues - 1 < Idx)
|
||||||
{
|
{
|
||||||
|
@ -2720,7 +2815,7 @@ CmiDestroyHashTableBlock(PREGISTRY_FILE RegistryFile,
|
||||||
static NTSTATUS
|
static NTSTATUS
|
||||||
CmiAllocateValueBlock(PREGISTRY_FILE RegistryFile,
|
CmiAllocateValueBlock(PREGISTRY_FILE RegistryFile,
|
||||||
PVALUE_BLOCK *ValueBlock,
|
PVALUE_BLOCK *ValueBlock,
|
||||||
IN PWSTR ValueNameBuf,
|
IN PCHAR ValueNameBuf,
|
||||||
IN ULONG Type,
|
IN ULONG Type,
|
||||||
IN PVOID Data,
|
IN PVOID Data,
|
||||||
IN ULONG DataSize)
|
IN ULONG DataSize)
|
||||||
|
@ -2735,7 +2830,7 @@ CmiAllocateValueBlock(PREGISTRY_FILE RegistryFile,
|
||||||
/* Handle volatile files first */
|
/* Handle volatile files first */
|
||||||
if (RegistryFile->Filename == NULL)
|
if (RegistryFile->Filename == NULL)
|
||||||
{
|
{
|
||||||
NewValueSize = sizeof(VALUE_BLOCK) + wcslen(ValueNameBuf)* sizeof(WCHAR);
|
NewValueSize = sizeof(VALUE_BLOCK) + strlen(ValueNameBuf);
|
||||||
NewValueBlock = ExAllocatePool(NonPagedPool, NewValueSize);
|
NewValueBlock = ExAllocatePool(NonPagedPool, NewValueSize);
|
||||||
if (NewValueBlock == NULL)
|
if (NewValueBlock == NULL)
|
||||||
{
|
{
|
||||||
|
@ -2745,8 +2840,8 @@ CmiAllocateValueBlock(PREGISTRY_FILE RegistryFile,
|
||||||
{
|
{
|
||||||
RtlZeroMemory(NewValueBlock, NewValueSize);
|
RtlZeroMemory(NewValueBlock, NewValueSize);
|
||||||
NewValueBlock->SubBlockId = REG_VALUE_BLOCK_ID;
|
NewValueBlock->SubBlockId = REG_VALUE_BLOCK_ID;
|
||||||
NewValueBlock->NameSize = wcslen(ValueNameBuf);
|
NewValueBlock->NameSize = strlen(ValueNameBuf);
|
||||||
wcscpy(NewValueBlock->Name, ValueNameBuf);
|
memcpy(NewValueBlock->Name, ValueNameBuf,strlen(ValueNameBuf));
|
||||||
NewValueBlock->DataType = Type;
|
NewValueBlock->DataType = Type;
|
||||||
NewValueBlock->DataSize = DataSize;
|
NewValueBlock->DataSize = DataSize;
|
||||||
Status = CmiAllocateBlock(RegistryFile,
|
Status = CmiAllocateBlock(RegistryFile,
|
||||||
|
@ -2954,16 +3049,13 @@ CmiGetBlock(PREGISTRY_FILE RegistryFile,
|
||||||
RegistryFile->BlockListSize ++;
|
RegistryFile->BlockListSize ++;
|
||||||
RegistryFile->BlockList [CurBlock]
|
RegistryFile->BlockList [CurBlock]
|
||||||
= ExAllocatePool(NonPagedPool,tmpHeap.BlockSize);
|
= ExAllocatePool(NonPagedPool,tmpHeap.BlockSize);
|
||||||
CHECKPOINT;
|
|
||||||
Status = ZwReadFile(RegistryFile->FileHandle,
|
Status = ZwReadFile(RegistryFile->FileHandle,
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
RegistryFile->BlockList[CurBlock ],
|
RegistryFile->BlockList[CurBlock ],
|
||||||
tmpHeap.BlockSize,
|
tmpHeap.BlockSize,
|
||||||
&fileOffset, 0);
|
&fileOffset, 0);
|
||||||
DPRINT(" read %d block file %x octets at %x, Status=%x\n",CurBlock,tmpHeap.BlockSize,fileOffset.u.LowPart,Status);
|
|
||||||
Block = ((char *)RegistryFile->BlockList[CurBlock]
|
Block = ((char *)RegistryFile->BlockList[CurBlock]
|
||||||
+(BlockOffset - RegistryFile->BlockList[CurBlock]->BlockOffset));
|
+(BlockOffset - RegistryFile->BlockList[CurBlock]->BlockOffset));
|
||||||
DPRINT(" hbin at %x, block at %x\n",RegistryFile->BlockList[CurBlock],Block);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Block;
|
return Block;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue