mirror of
https://github.com/reactos/reactos.git
synced 2024-10-15 05:37:44 +00:00
more hacking on the registry
svn path=/trunk/; revision=541
This commit is contained in:
parent
06938a9103
commit
a5e573f1b3
|
@ -20,25 +20,85 @@
|
|||
|
||||
#if PROTO_REG
|
||||
|
||||
typedef DWORD BLOCK_OFFSET;
|
||||
|
||||
typedef struct _KEY_BLOCK
|
||||
{
|
||||
DWORD SubBlockId;
|
||||
DWORD Type;
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
BLOCK_OFFSET ParentKeyOffset;
|
||||
DWORD NumberOfSubKeys;
|
||||
BLOCK_OFFSET HashTableOffset;
|
||||
DWORD NumberValues;
|
||||
BLOCK_OFFSET ValuesOffset;
|
||||
BLOCK_OFFSET SecurityKeyOffset;
|
||||
BLOCK_OFFSET ClassNameOffset;
|
||||
DWORD Unused1;
|
||||
DWORD NameSize;
|
||||
DWORD ClassSize;
|
||||
CHAR Name[1];
|
||||
} KEY_BLOCK, *PKEY_BLOCK;
|
||||
|
||||
typedef struct _HASH_RECORD
|
||||
{
|
||||
BLOCK_OFFSET KeyOffset;
|
||||
ULONG HashValue;
|
||||
} HASH_RECORD, *PHASH_RECORD;
|
||||
|
||||
typedef struct _HASH_BLOCK
|
||||
{
|
||||
DWORD SubBlockId;
|
||||
DWORD HashTableSize;
|
||||
HASH_RECORD Table[1];
|
||||
} HASH_BLOCK, *PHASH_BLOCK;
|
||||
|
||||
/* Type defining the Object Manager Key Object */
|
||||
typedef struct _KEY_OBJECT
|
||||
/*
|
||||
* Type defining the Object Manager Key Object
|
||||
*/
|
||||
{
|
||||
CSHORT Type;
|
||||
CSHORT Size;
|
||||
|
||||
ULONG Flags;
|
||||
WCHAR *Name;
|
||||
PKEY_BLOCK KeyBlock;
|
||||
struct _KEY_OBJECT *NextKey;
|
||||
} KEY_OBJECT, *PKEY_OBJECT;
|
||||
|
||||
#define KO_MARKED_FOR_DELETE 0x00000001
|
||||
|
||||
typedef struct _REGISTRY_FILE
|
||||
{
|
||||
PWSTR Filename;
|
||||
PVOID Data;
|
||||
PVOID (*Extend)(PVOID *Data, ULONG NewSize);
|
||||
PVOID (*Flush)(VOID);
|
||||
} REGISTRY_FILE, *PREGISTRY_FILE;
|
||||
|
||||
static POBJECT_TYPE CmiKeyType = NULL;
|
||||
static PKEY_OBJECT CmiKeyList = NULL;
|
||||
static KSPIN_LOCK CmiKeyListLock;
|
||||
static PREGISTRY_FILE CmiVolatileFile = NULL;
|
||||
static PREGISTRY_FILE CmiSystemFile = NULL;
|
||||
|
||||
static PVOID CmiObjectParse(PVOID ParsedObject, PWSTR *Path);
|
||||
static PVOID CmiObjectDelete(PVOID DeletedObject);
|
||||
static VOID CmiAddKeyToList(PKEY_OBJECT NewKey);
|
||||
static PKEY_OBJECT CmiScanKeyList(PWSTR *KeyNameBuf);
|
||||
static NTSTATUS CmiCreateKey(PREGISTRY_FILE RegistryFile,
|
||||
PWSTR KeyNameBuf,
|
||||
PKEY_BLOCK *KeyBlock,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
ULONG TitleIndex,
|
||||
PUNICODE_STRING Class,
|
||||
ULONG CreateOptions,
|
||||
PULONG Disposition);
|
||||
static NTSTATUS CmiFindKey(PREGISTRY_FILE RegistryFile,
|
||||
PWSTR KeyNameBuf,
|
||||
PKEY_BLOCK *KeyBlock,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
ULONG TitleIndex,
|
||||
PUNICODE_STRING Class);
|
||||
#endif
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
@ -61,8 +121,8 @@ CmInitializeRegistry(VOID)
|
|||
CmiKeyType->Dump = NULL;
|
||||
CmiKeyType->Open = NULL;
|
||||
CmiKeyType->Close = NULL;
|
||||
CmiKeyType->Delete = NULL;
|
||||
CmiKeyType->Parse = CmpObjectParse;
|
||||
CmiKeyType->Delete = CmiKeyDelete;
|
||||
CmiKeyType->Parse = CmiKeyParse;
|
||||
CmiKeyType->Security = NULL;
|
||||
CmiKeyType->QueryName = NULL;
|
||||
CmiKeyType->OkayToClose = NULL;
|
||||
|
@ -77,6 +137,9 @@ CmInitializeRegistry(VOID)
|
|||
&ObjectAttributes,
|
||||
CmiKeyType);
|
||||
|
||||
KeInitializeSpinLock(&CmiKeylistLock);
|
||||
|
||||
/* FIXME: build volitile registry store */
|
||||
/* FIXME: map / build registry data */
|
||||
/* FIXME: Create initial predefined symbolic links */
|
||||
/* HKEY_LOCAL_MACHINE */
|
||||
|
@ -87,13 +150,13 @@ CmInitializeRegistry(VOID)
|
|||
}
|
||||
|
||||
NTSTATUS
|
||||
NtCreateKey(PHANDLE KeyHandle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
ULONG TitleIndex,
|
||||
PUNICODE_STRING Class,
|
||||
ULONG CreateOptions,
|
||||
PULONG Disposition)
|
||||
NtCreateKey(OUT PHANDLE KeyHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
IN ULONG TitleIndex,
|
||||
IN PUNICODE_STRING Class,
|
||||
IN ULONG CreateOptions,
|
||||
OUT PULONG Disposition)
|
||||
{
|
||||
return ZwCreateKey(KeyHandle,
|
||||
DesiredAccess,
|
||||
|
@ -105,45 +168,69 @@ NtCreateKey(PHANDLE KeyHandle,
|
|||
}
|
||||
|
||||
NTSTATUS
|
||||
ZwCreateKey(PHANDLE KeyHandle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
ULONG TitleIndex,
|
||||
PUNICODE_STRING Class,
|
||||
ULONG CreateOptions,
|
||||
PULONG Disposition)
|
||||
ZwCreateKey(OUT PHANDLE KeyHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
IN ULONG TitleIndex,
|
||||
IN PUNICODE_STRING Class,
|
||||
IN ULONG CreateOptions,
|
||||
OUT PULONG Disposition)
|
||||
{
|
||||
#if PROTO_REG
|
||||
PWSTR KeyNameBuf;
|
||||
NTSTATUS Status;
|
||||
PKEY_TYPE CurKey;
|
||||
|
||||
/* FIXME: Should CurLevel be alloced to handle arbitrary size components? */
|
||||
WCHAR *S, *T, CurLevel[255];
|
||||
PKEY_OBJECT ParentKey, CurSubKey, NewKey;
|
||||
PREGISTRY_FILE FileToUse;
|
||||
PKEY_BLOCK KeyBlock;
|
||||
|
||||
assert(ObjectAttributes != NULL);
|
||||
|
||||
FileToUse = (CreateOptions & REG_OPTION_NON_VOLATILE) ?
|
||||
CmiSystemFile : CmiVolatileFile;
|
||||
|
||||
/* Construct the complete registry relative pathname */
|
||||
Status = CmiBuildKeyPath(&KeyNameBuf, ObjectAttributes);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* FIXME: Scan the key list to see if key already open */
|
||||
CurKey = CmiKeyList;
|
||||
while (CurKey != NULL && wcscmp(KeyPath, CurKey->Name) != 0)
|
||||
{
|
||||
CurKey = CurKey->Next;
|
||||
}
|
||||
/* Scan the key list to see if key already open */
|
||||
CurKey = CmiScanKeyList(KeyNameBuf);
|
||||
if (CurKey != NULL)
|
||||
{
|
||||
/* FIXME: If so, return a reference to it */
|
||||
/* FIXME: destroy KeyNameBuf before return */
|
||||
/* FIXME:(?) we could check to see if the key still exists here... */
|
||||
/* Unmark the key if the key has been marked for Delete */
|
||||
if (CurKey->Flags & KO_MARKED_FOR_DELETE)
|
||||
{
|
||||
CurKey->Flags &= ~KO_MARKED_FOR_DELETE;
|
||||
}
|
||||
|
||||
/* FIXME: Call CmiCreateKey to create/open the key in the registry file */
|
||||
Status = CmiCreateKey(KeyNameBuf, TitleIndex, Class, Disposition);
|
||||
/* If so, return a reference to it */
|
||||
Status = ObCreateHandle(PsGetCurrentProcess(),
|
||||
CurKey,
|
||||
DesiredAccess,
|
||||
FALSE,
|
||||
KeyHandle);
|
||||
ExFreePool(KeyNameBuf);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Create or open the key in the registry file */
|
||||
Status = CmiCreateKey(FileToUse,
|
||||
KeyNameBuf,
|
||||
&KeyBlock,
|
||||
DesiredAccess,
|
||||
TitleIndex,
|
||||
Class,
|
||||
CreateOptions,
|
||||
Disposition);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExFreePool(KeyNameBuf);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Create new key object and put into linked list */
|
||||
NewKey = ObGenericCreateObject(KeyHandle,
|
||||
|
@ -156,55 +243,245 @@ ZwCreateKey(PHANDLE KeyHandle,
|
|||
}
|
||||
NewKey->Flags = 0;
|
||||
NewKey->Name = KeyNameBuf;
|
||||
NewKey->NextKey = CmiKeyList;
|
||||
CmiKeyList = NewKey;
|
||||
NewKey->KeyBlock = KeyBlock;
|
||||
CmiAddKeyToList(NewKey);
|
||||
Status = ObCreateHandle(PsGetCurrentProcess(),
|
||||
CurKey,
|
||||
DesiredAccess,
|
||||
FALSE,
|
||||
KeyHandle);
|
||||
|
||||
return Status;
|
||||
#else
|
||||
UNIMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NtDeleteKey(IN HANDLE KeyHandle)
|
||||
{
|
||||
return ZwDeleteKey(KeyHandle);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ZwDeleteKey(IN HANDLE KeyHandle)
|
||||
{
|
||||
#ifdef PROTO_REG
|
||||
PHANDLE_REP KeyHandleRep;
|
||||
POBJECT_HEADER KeyObjectHeader;
|
||||
PKEY_OBJECT KeyObject;
|
||||
|
||||
/* Verify that the handle is valid and is a registry key */
|
||||
KeyHandleRep = ObTranslateHandle(PsGetCurrentProcess(), KeyHandle);
|
||||
if (KeyHandleRep == NULL)
|
||||
{
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
KeyObjectHeader = BODY_TO_HEADER(KeyHandleRep->ObjectBody);
|
||||
if (KeyObjectHeader->ObjectType != CmiKeyType)
|
||||
{
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
/* Verify required access for delete */
|
||||
if ((KeyHandleRep & KEY_DELETE_ACCESS) != KEY_DELETE_ACCESS)
|
||||
{
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
/* Set the marked for delete bit in the key object */
|
||||
KeyObject = (PKEY_OBJECT) KeyHandleRep->ObjectBody;
|
||||
KeyObject->Flags |= KO_MARKED_FOR_DELETE;
|
||||
|
||||
/* Dereference the object */
|
||||
ObDeleteHandle(KeyHandle);
|
||||
/* FIXME: I think that ObDeleteHandle should dereference the object */
|
||||
ObDereferenceObject(KeyObject);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
#else
|
||||
UNIMPLEMENTED;
|
||||
#endif
|
||||
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS NtDeleteKey(HANDLE KeyHandle)
|
||||
NTSTATUS
|
||||
NtEnumerateKey(IN HANDLE KeyHandle,
|
||||
IN ULONG Index,
|
||||
IN KEY_INFORMATION_CLASS KeyInformationClass,
|
||||
OUT PVOID KeyInformation,
|
||||
IN ULONG Length,
|
||||
OUT PULONG ResultLength)
|
||||
{
|
||||
return(ZwDeleteKey(KeyHandle));
|
||||
}
|
||||
|
||||
NTSTATUS ZwDeleteKey(HANDLE KeyHandle)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS NtEnumerateKey(HANDLE KeyHandle,
|
||||
ULONG Index,
|
||||
KEY_INFORMATION_CLASS KeyInformationClass,
|
||||
PVOID KeyInformation,
|
||||
ULONG Length,
|
||||
PULONG ResultLength)
|
||||
{
|
||||
return(ZwEnumerateKey(KeyHandle,
|
||||
return ZwEnumerateKey(KeyHandle,
|
||||
Index,
|
||||
KeyInformationClass,
|
||||
KeyInformation,
|
||||
Length,
|
||||
ResultLength));
|
||||
ResultLength);
|
||||
}
|
||||
|
||||
NTSTATUS ZwEnumerateKey(HANDLE KeyHandle,
|
||||
ULONG Index,
|
||||
KEY_INFORMATION_CLASS KeyInformationClass,
|
||||
PVOID KeyInformation,
|
||||
ULONG Length,
|
||||
PULONG ResultLength)
|
||||
NTSTATUS
|
||||
ZwEnumerateKey(IN HANDLE KeyHandle,
|
||||
IN ULONG Index,
|
||||
IN KEY_INFORMATION_CLASS KeyInformationClass,
|
||||
OUT PVOID KeyInformation,
|
||||
IN ULONG Length,
|
||||
OUT PULONG ResultLength)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
#ifdef PROTO_REG
|
||||
NTSTATUS Status;
|
||||
PHANDLE_REP KeyHandleRep;
|
||||
POBJECT_HEADER KeyObjectHeader;
|
||||
PKEY_OBJECT KeyObject;
|
||||
PKEY_BLOCK KeyBlock, SubKeyBlock;
|
||||
PHASH_TABLE_BLOCK HashTableBlock;
|
||||
PWSTR ClassBlock;
|
||||
PKEY_BASIC_INFORMATION KeyBasicInformation;
|
||||
PKEY_NODE_INFORMATION KeyNodeInformation;
|
||||
PKEY_FULL_INFORMATION KeyFullInformation;
|
||||
|
||||
/* Verify that the handle is valid and is a registry key */
|
||||
KeyHandleRep = ObTranslateHandle(PsGetCurrentProcess(), KeyHandle);
|
||||
if (KeyHandleRep == NULL)
|
||||
{
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
KeyObjectHeader = BODY_TO_HEADER(KeyHandleRep->ObjectBody);
|
||||
if (KeyObjectHeader->ObjectType != CmiKeyObject)
|
||||
{
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
NTSTATUS NtEnumerateValueKey(HANDLE KeyHandle, ULONG Index,
|
||||
KEY_VALUE_INFORMATION_CLASS KeyInformationClass,
|
||||
PVOID KeyInformation,
|
||||
ULONG Length,
|
||||
PULONG ResultLength)
|
||||
/* Verify required access for enumerate */
|
||||
if ((KeyHandleRep->AccessGranted & KEY_ENUMERATE_SUB_KEY) !=
|
||||
KEY_ENUMERATE_SUB_KEY)
|
||||
{
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
/* Get pointer to KeyBlock */
|
||||
KeyObject = (PKEY_OBJECT) KeyHandleRep->ObjectBody;
|
||||
KeyBlock = KeyObject->KeyBlock;
|
||||
|
||||
/* Get pointer to SubKey */
|
||||
HashTableBlock = CmiGetHashTableBlock(KeyBlock);
|
||||
SubKeyBlock = CmiGetKeyFromHashByIndex(HashTableBlock, Index);
|
||||
if (SubKeyBlock == NULL)
|
||||
{
|
||||
return STATUS_NO_MORE_ENTRIES;
|
||||
}
|
||||
|
||||
CmiLockBlock(SubKeyBlock);
|
||||
Status = STATUS_SUCCESS;
|
||||
switch (KeyInformationClass)
|
||||
{
|
||||
case KeyBasicInformation:
|
||||
/* Check size of buffer */
|
||||
if (Length < sizeof(KEY_BASIC_INFORMATION) +
|
||||
SubKeyBlock->NameSize * sizeof(WCHAR))
|
||||
{
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fill buffer with requested info */
|
||||
KeyBasicInformation = (PKEY_BASIC_INFORMATION) KeyInformation;
|
||||
KeyBasicInformation->LastWriteTime = SubKeyBlock->LastWriteTime;
|
||||
KeyBasicInformation->TitleIndex = Index;
|
||||
KeyBasicInformation->NameLength = SubKeyBlock->NameSize;
|
||||
wcsncpy(KeyBasicInformation->Name,
|
||||
SubKeyBlock->Name,
|
||||
SubKeyBlock->NameSize);
|
||||
KeyBasicInformation->Name[SubKeyBlock->NameSize] = 0;
|
||||
*ReturnLength = sizeof(KEY_BASIC_INFORMATION) +
|
||||
SubKeyBlock->NameSize * sizeof(WCHAR);
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyNodeInformation:
|
||||
/* Check size of buffer */
|
||||
if (Length < sizeof(KEY_NODE_INFORMATION) +
|
||||
SubKeyBlock->NameSize * sizeof(WCHAR) +
|
||||
(SubKeyBlock->ClassSize + 1) * sizeof(WCHAR))
|
||||
{
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fill buffer with requested info */
|
||||
KeyNodeInformation = (PKEY_NODE_INFORMATION) KeyInformation;
|
||||
KeyNodeInformation->LastWriteTime = SubKeyBlock->LastWriteTime;
|
||||
KeyNodeInformation->TitleIndex = Index;
|
||||
KeyNodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) +
|
||||
SubKeyBlock->NameSize * sizeof(WCHAR);
|
||||
KeyNodeInformation->ClassLength = SubKeyBlock->ClassSize;
|
||||
KeyNodeInformation->NameLength = SubKeyBlock->NameSize;
|
||||
wcsncpy(KeyNodeInformation->Name,
|
||||
SubKeyBlock->Name,
|
||||
SubKeyBlock->NameSize);
|
||||
KeyNodeInformation->Name[SubKeyBlock->NameSize] = 0;
|
||||
if (SubKeyBlock->ClassSize != 0)
|
||||
{
|
||||
ClassBlock = CmiGetClassBlock(SubKeyBlock);
|
||||
|
||||
wcsncpy(KeyNodeInformation->Name + SubKeyBlock->NameSize + 1,
|
||||
ClassBlock,
|
||||
SubKeyBlock->ClassSize);
|
||||
KeyNodeInformation->
|
||||
Name[SubKeyBlock->NameSize + 1 + SubKeyBlock->ClassSize] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyFullInformation:
|
||||
/* FIXME: check size of buffer */
|
||||
if (Length < sizeof(KEY_FULL_INFORMATION) +
|
||||
SubKeyBlock->ClassSize * sizeof(WCHAR))
|
||||
{
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME: fill buffer with requested info */
|
||||
KeyFullInformation = (PKEY_FULL_INFORMATION) KeyInformation;
|
||||
KeyFullInformation->LastWriteTime = SubKeyBlock->LastWriteTime;
|
||||
KeyFullInformation->TitleIndex = Index;
|
||||
KeyFullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) -
|
||||
sizeof(WCHAR);
|
||||
KeyFullInformation->ClassLength = SubKeyBlock->ClassSize;
|
||||
KeyFullInformation->SubKeys = SubKeyBlock->NumberOfSubKeys;
|
||||
KeyFullInformation->MaxNameLen = CmiGetMaxNameLength(SubKeyBlock);
|
||||
KeyFullInformation->MaxClassLen = CmiGetMaxClassLength(SubKeyBlock);
|
||||
KeyFullInformation->Values = ;
|
||||
KeyFullInformation->MaxValueNameLen =
|
||||
CmiGetMaxValueNameLength(SubKeyBlock);
|
||||
KeyFullInformation->MaxValueDataLen =
|
||||
CmiGetMaxValueDataLength(SubKeyBlock);
|
||||
ClassBlock = CmiGetClassBlock(SubKeyBlock);
|
||||
CmiLockBlock(ClassBlock);
|
||||
wcsncpy(KeyFullInformation->Class,
|
||||
ClassBlock,
|
||||
SubKeyBlock->ClassSize);
|
||||
CmiUnlockBlock(ClassBlock);
|
||||
KeyFullInformation->Class[SubKeyBlock->ClassSize] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
CmiUnlockBlock(SubKeyBlock);
|
||||
|
||||
return Status;
|
||||
#else
|
||||
UNIMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NtEnumerateValueKey(IN HANDLE KeyHandle,
|
||||
IN ULONG Index,
|
||||
IN KEY_VALUE_INFORMATION_CLASS KeyInformationClass,
|
||||
OUT PVOID KeyInformation,
|
||||
IN ULONG Length,
|
||||
OUT PULONG ResultLength)
|
||||
{
|
||||
return ZwEnumerateValueKey(KeyHandle,
|
||||
Index,
|
||||
|
@ -214,44 +491,132 @@ NTSTATUS NtEnumerateValueKey(HANDLE KeyHandle, ULONG Index,
|
|||
ResultLength);
|
||||
}
|
||||
|
||||
NTSTATUS ZwEnumerateValueKey(HANDLE KeyHandle, ULONG Index,
|
||||
KEY_VALUE_INFORMATION_CLASS KeyInformationClass,
|
||||
PVOID KeyInformation,
|
||||
ULONG Length,
|
||||
PULONG ResultLength)
|
||||
NTSTATUS
|
||||
ZwEnumerateValueKey(IN HANDLE KeyHandle,
|
||||
IN ULONG Index,
|
||||
IN KEY_VALUE_INFORMATION_CLASS KeyInformationClass,
|
||||
OUT PVOID KeyInformation,
|
||||
IN ULONG Length,
|
||||
OUT PULONG ResultLength)
|
||||
{
|
||||
#ifdef PROTO_REG
|
||||
UNIMPLEMENTED;
|
||||
#else
|
||||
UNIMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
NTSTATUS NtFlushKey(HANDLE KeyHandle)
|
||||
NTSTATUS
|
||||
NtFlushKey(IN HANDLE KeyHandle)
|
||||
{
|
||||
return ZwFlushKey(KeyHandle);
|
||||
}
|
||||
|
||||
NTSTATUS ZwFlushKey(HANDLE KeyHandle)
|
||||
NTSTATUS
|
||||
ZwFlushKey(IN HANDLE KeyHandle)
|
||||
{
|
||||
#ifdef PROTO_REG
|
||||
return STATUS_SUCCESS;
|
||||
#else
|
||||
UNIMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
NTSTATUS NtOpenKey(PHANDLE KeyHandle, ACCESS_MASK DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes)
|
||||
NTSTATUS
|
||||
NtOpenKey(OUT PHANDLE KeyHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
||||
{
|
||||
return ZwOpenKey(KeyHandle,
|
||||
DesiredAccess,
|
||||
ObjectAttributes);
|
||||
}
|
||||
|
||||
NTSTATUS ZwOpenKey(PHANDLE KeyHandle, ACCESS_MASK DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes)
|
||||
NTSTATUS
|
||||
ZwOpenKey(OUT PHANDLE KeyHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
#ifdef PROTO_REG
|
||||
PWSTR KeyNameBuf;
|
||||
PKEY_BLOCK KeyBlock;
|
||||
PKEY_OBJECT CurKey;
|
||||
|
||||
/* Construct the complete registry relative pathname */
|
||||
Status = CmiBuildKeyPath(&KeyNameBuf, ObjectAttributes);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NtQueryKey(HANDLE KeyHandle,
|
||||
KEY_INFORMATION_CLASS KeyInformationClass,
|
||||
PVOID KeyInformation,
|
||||
ULONG Length,
|
||||
PULONG ResultLength)
|
||||
/* Scan the key list to see if key already open */
|
||||
CurKey = CmiScanKeyList(KeyNameBuf);
|
||||
if (CurKey != NULL)
|
||||
{
|
||||
/* Fail if the key has been deleted */
|
||||
if (CurKey->Flags & KO_MARKED_FOR_DELETE)
|
||||
{
|
||||
ExFreePool(KeyNameBuf);
|
||||
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* If so, return a reference to it */
|
||||
Status = ObCreateHandle(PsGetCurrentProcess(),
|
||||
CurKey,
|
||||
DesiredAccess,
|
||||
FALSE,
|
||||
KeyHandle);
|
||||
ExFreePool(KeyNameBuf);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Open the key in the registry file */
|
||||
Status = CmiFindKey(FileToUse,
|
||||
KeyNameBuf,
|
||||
&KeyBlock,
|
||||
DesiredAccess,
|
||||
0,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExFreePool(KeyNameBuf);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Create new key object and put into linked list */
|
||||
NewKey = ObGenericCreateObject(KeyHandle,
|
||||
DesiredAccess,
|
||||
NULL,
|
||||
CmiKeyType);
|
||||
if (NewKey == NULL)
|
||||
{
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
NewKey->Flags = 0;
|
||||
NewKey->Name = KeyNameBuf;
|
||||
NewKey->KeyBlock = KeyBlock;
|
||||
CmiAddKeyToList(NewKey);
|
||||
Status = ObCreateHandle(PsGetCurrentProcess(),
|
||||
CurKey,
|
||||
DesiredAccess,
|
||||
FALSE,
|
||||
KeyHandle);
|
||||
|
||||
return Status;
|
||||
#else
|
||||
UNIMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NtQueryKey(IN HANDLE KeyHandle,
|
||||
IN KEY_INFORMATION_CLASS KeyInformationClass,
|
||||
OUT PVOID KeyInformation,
|
||||
IN ULONG Length,
|
||||
OUT PULONG ResultLength)
|
||||
{
|
||||
return ZwQueryKey(KeyHandle,
|
||||
KeyInformationClass,
|
||||
|
@ -260,21 +625,158 @@ NTSTATUS NtQueryKey(HANDLE KeyHandle,
|
|||
ResultLength);
|
||||
}
|
||||
|
||||
NTSTATUS ZwQueryKey(HANDLE KeyHandle,
|
||||
KEY_INFORMATION_CLASS KeyInformationClass,
|
||||
PVOID KeyInformation,
|
||||
ULONG Length,
|
||||
PULONG ResultLength)
|
||||
NTSTATUS
|
||||
ZwQueryKey(IN HANDLE KeyHandle,
|
||||
IN KEY_INFORMATION_CLASS KeyInformationClass,
|
||||
OUT PVOID KeyInformation,
|
||||
IN ULONG Length,
|
||||
OUT PULONG ResultLength)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
#ifdef PROTO_REG
|
||||
NTSTATUS Status;
|
||||
PHANDLE_REP KeyHandleRep;
|
||||
POBJECT_HEADER KeyObjectHeader;
|
||||
PKEY_OBJECT KeyObject;
|
||||
PKEY_BLOCK KeyBlock;
|
||||
PWSTR ClassBlock;
|
||||
PKEY_BASIC_INFORMATION KeyBasicInformation;
|
||||
PKEY_NODE_INFORMATION KeyNodeInformation;
|
||||
PKEY_FULL_INFORMATION KeyFullInformation;
|
||||
|
||||
/* Verify that the handle is valid and is a registry key */
|
||||
KeyHandleRep = ObTranslateHandle(PsGetCurrentProcess(), KeyHandle);
|
||||
if (KeyHandleRep == NULL)
|
||||
{
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
KeyObjectHeader = BODY_TO_HEADER(KeyHandleRep->ObjectBody);
|
||||
if (KeyObjectHeader->ObjectType != CmiKeyObject)
|
||||
{
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
NTSTATUS NtQueryValueKey(HANDLE KeyHandle,
|
||||
PUNICODE_STRING ValueName,
|
||||
KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
|
||||
PVOID KeyValueInformation,
|
||||
ULONG Length,
|
||||
PULONG ResultLength)
|
||||
/* Verify required access for enumerate */
|
||||
if ((KeyHandleRep->AccessGranted & KEY_QUERY_KEY) != KEY_QUERY_KEY)
|
||||
{
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
/* Get pointer to KeyBlock */
|
||||
KeyObject = (PKEY_OBJECT) KeyHandleRep->ObjectBody;
|
||||
KeyBlock = KeyObject->KeyBlock;
|
||||
|
||||
CmiLockBlock(KeyBlock);
|
||||
Status = STATUS_SUCCESS;
|
||||
switch (KeyInformationClass)
|
||||
{
|
||||
case KeyBasicInformation:
|
||||
/* Check size of buffer */
|
||||
if (Length < sizeof(KEY_BASIC_INFORMATION) +
|
||||
KeyBlock->NameSize * sizeof(WCHAR))
|
||||
{
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fill buffer with requested info */
|
||||
KeyBasicInformation = (PKEY_BASIC_INFORMATION) KeyInformation;
|
||||
KeyBasicInformation->LastWriteTime = KeyBlock->LastWriteTime;
|
||||
KeyBasicInformation->TitleIndex = 0;
|
||||
KeyBasicInformation->NameLength = KeyBlock->NameSize;
|
||||
wcsncpy(KeyBasicInformation->Name,
|
||||
KeyBlock->Name,
|
||||
KeyBlock->NameSize);
|
||||
KeyBasicInformation->Name[KeyBlock->NameSize] = 0;
|
||||
*ReturnLength = sizeof(KEY_BASIC_INFORMATION) +
|
||||
KeyBlock->NameSize * sizeof(WCHAR);
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyNodeInformation:
|
||||
/* Check size of buffer */
|
||||
if (Length < sizeof(KEY_NODE_INFORMATION) +
|
||||
KeyBlock->NameSize * sizeof(WCHAR) +
|
||||
(KeyBlock->ClassSize + 1) * sizeof(WCHAR))
|
||||
{
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fill buffer with requested info */
|
||||
KeyNodeInformation = (PKEY_NODE_INFORMATION) KeyInformation;
|
||||
KeyNodeInformation->LastWriteTime = KeyBlock->LastWriteTime;
|
||||
KeyNodeInformation->TitleIndex = 0;
|
||||
KeyNodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) +
|
||||
KeyBlock->NameSize * sizeof(WCHAR);
|
||||
KeyNodeInformation->ClassLength = KeyBlock->ClassSize;
|
||||
KeyNodeInformation->NameLength = KeyBlock->NameSize;
|
||||
wcsncpy(KeyNodeInformation->Name,
|
||||
KeyBlock->Name,
|
||||
KeyBlock->NameSize);
|
||||
KeyNodeInformation->Name[KeyBlock->NameSize] = 0;
|
||||
if (KeyBlock->ClassSize != 0)
|
||||
{
|
||||
ClassBlock = CmiGetClassBlock(KeyBlock);
|
||||
CmiLockBlock(ClassBlock);
|
||||
wcsncpy(KeyNodeInformation->Name + KeyBlock->NameSize + 1,
|
||||
ClassBlock,
|
||||
KeyBlock->ClassSize);
|
||||
CmiUnlockBlock(ClassBlock);
|
||||
KeyNodeInformation->
|
||||
Name[KeyBlock->NameSize + 1 + KeyBlock->ClassSize] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyFullInformation:
|
||||
/* Check size of buffer */
|
||||
if (Length < sizeof(KEY_FULL_INFORMATION) +
|
||||
KeyBlock->ClassSize * sizeof(WCHAR))
|
||||
{
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME: fill buffer with requested info */
|
||||
KeyFullInformation = (PKEY_FULL_INFORMATION) KeyInformation;
|
||||
KeyFullInformation->LastWriteTime = KeyBlock->LastWriteTime;
|
||||
KeyFullInformation->TitleIndex = 0;
|
||||
KeyFullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) -
|
||||
sizeof(WCHAR);
|
||||
KeyFullInformation->ClassLength = KeyBlock->ClassSize;
|
||||
KeyFullInformation->SubKeys = KeyBlock->NumberOfSubKeys;
|
||||
KeyFullInformation->MaxNameLen = CmiGetMaxNameLength(KeyBlock);
|
||||
KeyFullInformation->MaxClassLen = CmiGetMaxClassLength(KeyBlock);
|
||||
KeyFullInformation->Values = ?;
|
||||
KeyFullInformation->MaxValueNameLen =
|
||||
CmiGetMaxValueNameLength(KeyBlock);
|
||||
KeyFullInformation->MaxValueDataLen =
|
||||
CmiGetMaxValueDataLength(KeyBlock);
|
||||
ClassBlock = CmiGetClassBlock(KeyBlock);
|
||||
CmiLockBlock(ClassBlock);
|
||||
wcsncpy(KeyFullInformation->Class,
|
||||
ClassBlock,
|
||||
KeyBlock->ClassSize);
|
||||
CmiUnlockBlock(ClassBlock);
|
||||
KeyFullInformation->Class[KeyBlock->ClassSize] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
CmiUnlockBlock(KeyBlock);
|
||||
|
||||
return Status;
|
||||
#else
|
||||
UNIMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NtQueryValueKey(IN HANDLE KeyHandle,
|
||||
IN PUNICODE_STRING ValueName,
|
||||
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
|
||||
OUT PVOID KeyValueInformation,
|
||||
IN ULONG Length,
|
||||
OUT PULONG ResultLength)
|
||||
{
|
||||
return ZwQueryValueKey(KeyHandle,
|
||||
ValueName,
|
||||
|
@ -284,14 +786,64 @@ NTSTATUS NtQueryValueKey(HANDLE KeyHandle,
|
|||
ResultLength);
|
||||
}
|
||||
|
||||
NTSTATUS ZwQueryValueKey(HANDLE KeyHandle,
|
||||
PUNICODE_STRING ValueName,
|
||||
KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
|
||||
PVOID KeyValueInformation,
|
||||
ULONG Length,
|
||||
PULONG ResultLength)
|
||||
NTSTATUS
|
||||
ZwQueryValueKey(IN HANDLE KeyHandle,
|
||||
IN PUNICODE_STRING ValueName,
|
||||
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
|
||||
OUT PVOID KeyValueInformation,
|
||||
IN ULONG Length,
|
||||
OUT PULONG ResultLength)
|
||||
{
|
||||
#ifdef PROTO_REG
|
||||
NTSTATUS Status;
|
||||
PHANDLE_REP KeyHandleRep;
|
||||
POBJECT_HEADER KeyObjectHeader;
|
||||
PKEY_OBJECT KeyObject;
|
||||
PKEY_BLOCK KeyBlock;
|
||||
PKEY_VALUE_BASIC_INFORMATION KeyValueBasicInformation;
|
||||
PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInformation;
|
||||
PKEY_VALUE_FULL_INFORMATION KeyValueFullInformation;
|
||||
|
||||
/* Verify that the handle is valid and is a registry key */
|
||||
KeyHandleRep = ObTranslateHandle(PsGetCurrentProcess(), KeyHandle);
|
||||
if (KeyHandleRep == NULL)
|
||||
{
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
KeyObjectHeader = BODY_TO_HEADER(KeyHandleRep->ObjectBody);
|
||||
if (KeyObjectHeader->ObjectType != CmiKeyObject)
|
||||
{
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
/* Verify required access for enumerate */
|
||||
if ((KeyHandleRep->AccessGranted & KEY_QUERY_KEY) != KEY_QUERY_KEY)
|
||||
{
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
/* Get pointer to KeyBlock */
|
||||
KeyObject = (PKEY_OBJECT) KeyHandleRep->ObjectBody;
|
||||
KeyBlock = KeyObject->KeyBlock;
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
CmiLockBlock(KeyBlock);
|
||||
|
||||
/* FIXME: get value list block */
|
||||
/* FIXME: loop through value list */
|
||||
/* FIXME: get value block for current list entry */
|
||||
/* FIXME: compare name with desired value name */
|
||||
/* FIXME: if name is correct */
|
||||
/* FIXME: check size of input buffer */
|
||||
/* FIXME: copy data into buffer */
|
||||
/* FIXME: set ResultLength */
|
||||
|
||||
CmiUnlockBlock(KeyBlock);
|
||||
|
||||
return Status;
|
||||
#else
|
||||
UNIMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
NTSTATUS NtSetValueKey(HANDLE KeyHandle, PUNICODE_STRING ValueName,
|
||||
|
@ -315,10 +867,8 @@ NTSTATUS ZwSetValueKey(HANDLE KeyHandle, PUNICODE_STRING ValueName,
|
|||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtDeleteValueKey(
|
||||
IN HANDLE KeyHandle,
|
||||
IN PUNICODE_STRING ValueName
|
||||
)
|
||||
NtDeleteValueKey(IN HANDLE KeyHandle,
|
||||
IN PUNICODE_STRING ValueName)
|
||||
{
|
||||
return ZwDeleteValueKey(KeyHandle,
|
||||
ValueName);
|
||||
|
@ -643,6 +1193,13 @@ CmiObjectParse(PVOID ParsedObject, PWSTR* Path)
|
|||
|
||||
}
|
||||
|
||||
static PVOID CmiObjectDelete(PVOID DeletedObject)
|
||||
{
|
||||
/* FIXME: if marked for delete, then call CmiDeleteKey */
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS
|
||||
CmiBuildKeyPath(PWSTR *KeyPath, POBJECT_ATTRIBUTES ObjectAttributes)
|
||||
{
|
||||
|
@ -693,13 +1250,44 @@ CmiBuildKeyPath(PWSTR *KeyPath, POBJECT_ATTRIBUTES ObjectAttributes)
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static VOID
|
||||
CmiAddKeyToList(PKEY_OBJECT NewKey)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
|
||||
KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
|
||||
NewKey->NextKey = CmiKeyList;
|
||||
CmiKeyList = NewKey;
|
||||
KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
|
||||
}
|
||||
|
||||
static PKEY_OBJECT
|
||||
CmiScanKeyList(PWSTR *KeyNameBuf)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PKEY_OBJECT CurKey;
|
||||
|
||||
KeAcquireSpinLock(CmiKeyListLock, &OldIrql);
|
||||
CurKey = CmiKeyList;
|
||||
while (CurKey != NULL && wcscmp(KeyPath, CurKey->Name) != 0)
|
||||
{
|
||||
CurKey = CurKey->Next;
|
||||
}
|
||||
KeReleaseSpinLock(CmiKeyListLock, OldIrql);
|
||||
|
||||
return CurKey;
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
CmiCreateKey(PWSTR KeyNameBuf,
|
||||
CmiCreateKey(PREGISTRY_FILE RegistryFile,
|
||||
PWSTR KeyNameBuf,
|
||||
PKEY_BLOCK KeyBlock,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
ULONG TitleIndex,
|
||||
PUNICODE_STRING Class,
|
||||
ULONG CreateOptions,
|
||||
PULONG Disposition)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in a new issue