Implemented NtLoadKey2() and NtUnloadKey().

Implementation is still incomplete but functional.

svn path=/trunk/; revision=4801
This commit is contained in:
Eric Kohl 2003-05-30 22:28:14 +00:00
parent da25678127
commit dea1b856c7
6 changed files with 277 additions and 60 deletions

View file

@ -262,16 +262,20 @@ typedef struct _REGISTRY_HIVE
} REGISTRY_HIVE, *PREGISTRY_HIVE;
/* REGISTRY_HIVE.Flags constants */
/* When set, the hive is volatile. It will not be sync'ed to disk. */
#define HIVE_VOLATILE 0x00000001
/* When set, the hive uses pointers instead of offsets. */
#define HIVE_POINTER 0x00000002
/* When set, the hive is temporary. It will not be sync'ed to disk. */
#define HIVE_TEMPORARY 0x00000004
#define HIVE_POINTER 0x00000001
#define IsVolatileHive(Hive)(Hive->Flags & HIVE_VOLATILE)
#define IsPointerHive(Hive)(Hive->Flags & HIVE_POINTER)
#define IsTemporaryHive(Hive)(Hive->Flags & HIVE_TEMPORARY)
/* When set, the hive is not backed by a file.
Therefore, it can not be flushed to disk. */
#define HIVE_NO_FILE 0x00000002
/* When set, a modified (dirty) hive is not synchronized automatically.
Explicit synchronization (save/flush) works. */
#define HIVE_NO_SYNCH 0x00000004
#define IsPointerHive(Hive) ((Hive)->Flags & HIVE_POINTER)
#define IsNoFileHive(Hive) ((Hive)->Flags & HIVE_NO_FILE)
#define IsNoSynchHive(Hive) ((Hive)->Flags & HIVE_NO_SYNCH)
#define IsFreeCell(Cell)(Cell->CellSize >= 0)
@ -423,6 +427,11 @@ CmiCreateRegistryHive(PWSTR Filename,
PREGISTRY_HIVE *RegistryHive,
BOOLEAN CreateNew);
NTSTATUS
CmiLoadHive(PUNICODE_STRING KeyName,
PUNICODE_STRING FileName,
ULONG Flags);
NTSTATUS
CmiRemoveRegistryHive(PREGISTRY_HIVE RegistryHive);
@ -558,8 +567,12 @@ CmiAddFree(PREGISTRY_HIVE RegistryHive,
BOOLEAN MergeFreeBlocks);
NTSTATUS
CmiConnectHive(PREGISTRY_HIVE RegistryHive,
PUNICODE_STRING KeyName);
CmiConnectHive(PUNICODE_STRING KeyName,
PREGISTRY_HIVE RegistryHive);
NTSTATUS
CmiDisconnectHive (PUNICODE_STRING KeyName,
PREGISTRY_HIVE *RegistryHive);
NTSTATUS
CmiInitHives(BOOLEAN SetupBoot);

View file

@ -1,4 +1,4 @@
/* $Id: import.c,v 1.19 2003/05/24 13:18:32 ekohl Exp $
/* $Id: import.c,v 1.20 2003/05/30 22:28:14 ekohl Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -127,7 +127,7 @@ CmImportBinaryHive (PCHAR ChunkBase,
return Status;
}
if (!(Hive->Flags & HIVE_VOLATILE))
if (!(Hive->Flags & HIVE_NO_FILE))
{
/* Create the block bitmap */
Status = CmiCreateHiveBitmap (Hive);
@ -190,8 +190,8 @@ CmImportSystemHive(PCHAR ChunkBase,
/* Attach it to the machine key */
RtlInitUnicodeString (&KeyName,
L"\\Registry\\Machine\\System");
Status = CmiConnectHive (RegistryHive,
&KeyName);
Status = CmiConnectHive (&KeyName,
RegistryHive);
if (!NT_SUCCESS(Status))
{
DPRINT1 ("CmiConnectHive() failed (Status %lx)\n", Status);
@ -328,7 +328,7 @@ CmImportHardwareHive(PCHAR ChunkBase,
DPRINT ("ChunkBase %lx ChunkSize %lu\n", ChunkBase, ChunkSize);
/* Import the binary system hive (volatile, offset-based, permanent) */
if (!CmImportBinaryHive (ChunkBase, ChunkSize, HIVE_VOLATILE, &RegistryHive))
if (!CmImportBinaryHive (ChunkBase, ChunkSize, HIVE_NO_FILE, &RegistryHive))
{
DPRINT1 ("CmiImportBinaryHive() failed\n", Status);
return FALSE;
@ -337,8 +337,8 @@ CmImportHardwareHive(PCHAR ChunkBase,
/* Attach it to the machine key */
RtlInitUnicodeString (&KeyName,
L"\\Registry\\Machine\\HARDWARE");
Status = CmiConnectHive (RegistryHive,
&KeyName);
Status = CmiConnectHive (&KeyName,
RegistryHive);
if (!NT_SUCCESS(Status))
{
DPRINT1 ("CmiConnectHive() failed (Status %lx)\n", Status);

View file

@ -748,7 +748,7 @@ NtFlushKey(IN HANDLE KeyHandle)
ExAcquireResourceExclusiveLite(&RegistryHive->HiveResource,
TRUE);
if (IsVolatileHive(RegistryHive))
if (IsNoFileHive(RegistryHive))
{
Status = STATUS_SUCCESS;
}
@ -1300,7 +1300,7 @@ NtSetValueKey(IN HANDLE KeyHandle,
ValueCell->DataType = Type;
/* Update time of heap */
if (!IsVolatileHive(RegistryHive))
if (!IsNoFileHive(RegistryHive))
{
NtQuerySystemTime((PTIME) &pBin->DateModified);
}
@ -1355,7 +1355,7 @@ NtSetValueKey(IN HANDLE KeyHandle,
}
/* Update time of heap */
if (!IsVolatileHive(RegistryHive) && CmiGetBlock(RegistryHive, VBOffset, &pBin))
if (!IsNoFileHive(RegistryHive) && CmiGetBlock(RegistryHive, VBOffset, &pBin))
{
NtQuerySystemTime((PTIME) &pBin->DateModified);
}
@ -1420,7 +1420,9 @@ NTSTATUS STDCALL
NtLoadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes,
IN POBJECT_ATTRIBUTES FileObjectAttributes)
{
return NtLoadKey2 (KeyObjectAttributes, FileObjectAttributes, 0);
return NtLoadKey2 (KeyObjectAttributes,
FileObjectAttributes,
0);
}
@ -1428,14 +1430,31 @@ NtLoadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes,
* NOTE:
* KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
* KeyObjectAttributes->Name specifies the name of the key to load.
* Flags can be 0 or REG_NO_LAZY_FLUSH.
*/
NTSTATUS STDCALL
NtLoadKey2 (IN POBJECT_ATTRIBUTES KeyObjectAttributes,
IN POBJECT_ATTRIBUTES FileObjectAttributes,
IN ULONG Flags)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
NTSTATUS Status;
DPRINT ("NtLoadKey2() called\n");
if (Flags & ~REG_NO_LAZY_FLUSH)
return STATUS_INVALID_PARAMETER;
/* FIXME: Get the absolute file name */
Status = CmiLoadHive (KeyObjectAttributes->ObjectName,
FileObjectAttributes->ObjectName,
Flags);
if (!NT_SUCCESS (Status))
{
DPRINT1 ("CmiLoadHive() failed (Status %lx)\n", Status);
}
return Status;
}
@ -1567,15 +1586,14 @@ NtQueryMultipleValueKey (IN HANDLE KeyHandle,
DPRINT("Return Status 0x%X\n", Status);
return(Status);
return Status;
}
NTSTATUS STDCALL
NtReplaceKey (IN POBJECT_ATTRIBUTES ObjectAttributes,
IN HANDLE Key,
IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
)
IN POBJECT_ATTRIBUTES ReplacedObjectAttributes)
{
UNIMPLEMENTED;
}
@ -1616,25 +1634,82 @@ NtSetInformationKey (IN HANDLE KeyHandle,
NTSTATUS STDCALL
NtUnloadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes)
{
UNIMPLEMENTED;
PREGISTRY_HIVE RegistryHive;
NTSTATUS Status;
DPRINT ("NtUnloadKey() called\n");
Status = CmiDisconnectHive (KeyObjectAttributes->ObjectName,
&RegistryHive);
if (!NT_SUCCESS (Status))
{
DPRINT1 ("CmiDisconnectHive() failed (Status %lx)\n", Status);
return Status;
}
DPRINT ("RegistryHive %p\n", RegistryHive);
/* Acquire hive list lock exclusively */
ExAcquireResourceExclusiveLite (&CmiHiveListLock,
TRUE);
#if 0
/* Flush hive */
if (!IsNoFileHive (RegistryHive))
CmiFlushRegistryHive (RegistryHive);
#endif
/* Remove hive from hive list */
RemoveEntryList (&RegistryHive->HiveList);
/* Release hive list lock */
ExReleaseResourceLite (&CmiHiveListLock);
/* Release file names */
RtlFreeUnicodeString (&RegistryHive->HiveFileName);
RtlFreeUnicodeString (&RegistryHive->LogFileName);
/* Release hive bitmap */
ExFreePool (RegistryHive->BitmapBuffer);
/* Release free cell list */
ExFreePool (RegistryHive->FreeList);
ExFreePool (RegistryHive->FreeListOffset);
/* Release hive resource */
ExDeleteResource (&RegistryHive->HiveResource);
/* Release bins and bin list */
CmiFreeHiveBins (RegistryHive);
ExFreePool (RegistryHive->BlockList);
/* Release hive header */
ExFreePool (RegistryHive->HiveHeader);
/* Release hive */
ExFreePool (RegistryHive);
DPRINT ("NtUnloadKey() done\n");
return STATUS_SUCCESS;
}
NTSTATUS STDCALL
NtInitializeRegistry (IN BOOLEAN SetUpBoot)
{
NTSTATUS Status = STATUS_ACCESS_DENIED;
NTSTATUS Status;
if (CmiRegistryInitialized == TRUE)
return STATUS_ACCESS_DENIED;
if (CmiRegistryInitialized == FALSE)
{
/* FIXME: save boot log file */
Status = CmiInitHives (SetUpBoot);
CmiRegistryInitialized = TRUE;
}
return(Status);
return Status;
}
/* EOF */

View file

@ -1073,7 +1073,7 @@ CmiInitVolatileRegistryHive(PREGISTRY_HIVE RegistryHive)
{
PKEY_CELL RootKeyCell;
RegistryHive->Flags |= (HIVE_VOLATILE | HIVE_POINTER);
RegistryHive->Flags |= (HIVE_NO_FILE | HIVE_POINTER);
CmiCreateDefaultHiveHeader(RegistryHive->HiveHeader);
@ -1156,6 +1156,75 @@ CmiCreateRegistryHive(PWSTR Filename,
}
NTSTATUS
CmiLoadHive(IN PUNICODE_STRING KeyName,
IN PUNICODE_STRING FileName,
IN ULONG Flags)
{
PREGISTRY_HIVE Hive;
NTSTATUS Status;
DPRINT ("CmiLoadHive(Filename %wZ)\n", FileName);
Hive = ExAllocatePool (NonPagedPool,
sizeof(REGISTRY_HIVE));
if (Hive == NULL)
{
DPRINT1 ("Failed to allocate hive header.\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory (Hive,
sizeof(REGISTRY_HIVE));
DPRINT ("Hive %x\n", Hive);
Hive->HiveHeader = (PHIVE_HEADER)ExAllocatePool(NonPagedPool,
sizeof(HIVE_HEADER));
if (Hive->HiveHeader == NULL)
{
DPRINT1 ("Failed to allocate hive header.\n");
ExFreePool (Hive);
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = CmiInitNonVolatileRegistryHive (Hive,
FileName->Buffer,
TRUE);
if (!NT_SUCCESS (Status))
{
DPRINT1 ("CmiInitNonVolatileRegistryHive() failed (Status %lx)\n", Status);
ExFreePool (Hive->HiveHeader);
ExFreePool (Hive);
return Status;
}
ExInitializeResourceLite (&Hive->HiveResource);
/* Add the new hive to the hive list */
ExAcquireResourceExclusiveLite (&CmiHiveListLock,
TRUE);
InsertTailList (&CmiHiveListHead,
&Hive->HiveList);
ExReleaseResourceLite (&CmiHiveListLock);
VERIFY_REGISTRY_HIVE(Hive);
Status = CmiConnectHive (KeyName,
Hive);
if (!NT_SUCCESS(Status))
{
DPRINT1 ("CmiConnectHive() failed (Status %lx)\n", Status);
// CmiRemoveRegistryHive (Hive);
}
DPRINT ("CmiLoadHive() done\n");
return Status;
}
NTSTATUS
CmiRemoveRegistryHive(PREGISTRY_HIVE RegistryHive)
{
@ -1172,6 +1241,7 @@ CmiRemoveRegistryHive(PREGISTRY_HIVE RegistryHive)
/* FIXME: Remove attached keys and values */
/* Release hive header */
ExFreePool(RegistryHive->HiveHeader);
@ -2885,7 +2955,7 @@ CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive,
}
/* Update time of heap */
if (!IsVolatileHive(RegistryHive))
if (!IsNoFileHive(RegistryHive))
NtQuerySystemTime((PTIME) &pBin->DateModified);
}
@ -2893,7 +2963,7 @@ CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive,
Status = CmiDestroyBlock(RegistryHive, ValueCell, VBOffset);
/* Update time of heap */
if (!IsVolatileHive(RegistryHive) && CmiGetBlock(RegistryHive, VBOffset, &pBin))
if (!IsNoFileHive(RegistryHive) && CmiGetBlock(RegistryHive, VBOffset, &pBin))
{
NtQuerySystemTime((PTIME) &pBin->DateModified);
}
@ -2951,7 +3021,7 @@ CmiAddBin(PREGISTRY_HIVE RegistryHive,
tmpBlock->CellSize = (REG_BLOCK_SIZE - REG_HBIN_DATA_OFFSET);
/* Grow bitmap if necessary */
if (IsVolatileHive(RegistryHive) &&
if (IsNoFileHive(RegistryHive) &&
(RegistryHive->BlockListSize % (sizeof(ULONG) * 8) == 0))
{
PULONG BitmapBuffer;
@ -3132,7 +3202,7 @@ CmiDestroyBlock(PREGISTRY_HIVE RegistryHive,
CmiAddFree(RegistryHive, Block, Offset, TRUE);
/* Update time of heap */
if (!IsVolatileHive(RegistryHive) && CmiGetBlock(RegistryHive, Offset,&pBin))
if (!IsNoFileHive(RegistryHive) && CmiGetBlock(RegistryHive, Offset,&pBin))
NtQuerySystemTime((PTIME) &pBin->DateModified);
CmiMarkBlockDirty(RegistryHive, Offset);
@ -3391,7 +3461,7 @@ CmiMarkBlockDirty(PREGISTRY_HIVE RegistryHive,
ULONG BlockNumber;
ULONG BlockCount;
if (IsVolatileHive(RegistryHive))
if (IsNoFileHive(RegistryHive))
return;
DPRINT("CmiMarkBlockDirty(Offset 0x%lx)\n", (ULONG)BlockOffset);
@ -3429,7 +3499,7 @@ CmiMarkBinDirty(PREGISTRY_HIVE RegistryHive,
ULONG BlockCount;
PHBIN Bin;
if (IsVolatileHive(RegistryHive))
if (IsNoFileHive(RegistryHive))
return;
DPRINT("CmiMarkBinDirty(Offset 0x%lx)\n", (ULONG)BinOffset);

View file

@ -1,4 +1,4 @@
/* $Id: registry.c,v 1.98 2003/05/29 14:09:41 ekohl Exp $
/* $Id: registry.c,v 1.99 2003/05/30 22:28:14 ekohl Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -15,7 +15,7 @@
#include <roscfg.h>
#include <limits.h>
#include <string.h>
#include <internal/pool.h>
#include <internal/ob.h>
#include <internal/registry.h>
#include <reactos/bugcodes.h>
@ -498,14 +498,13 @@ CmiCreateCurrentControlSetLink(VOID)
NTSTATUS
CmiConnectHive(PREGISTRY_HIVE RegistryHive,
PUNICODE_STRING KeyName)
CmiConnectHive(IN PUNICODE_STRING KeyName,
IN PREGISTRY_HIVE RegistryHive)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING ParentKeyName;
PKEY_OBJECT ParentKey;
PKEY_OBJECT NewKey;
HANDLE KeyHandle;
NTSTATUS Status;
PWSTR SubName;
@ -549,7 +548,7 @@ CmiConnectHive(PREGISTRY_HIVE RegistryHive,
NULL,
NULL);
Status = ObCreateObject(&KeyHandle,
Status = ObCreateObject(NULL,
STANDARD_RIGHTS_REQUIRED,
&ObjectAttributes,
CmiKeyType,
@ -572,7 +571,7 @@ CmiConnectHive(PREGISTRY_HIVE RegistryHive,
if ((NewKey->SubKeys == NULL) && (NewKey->KeyCell->NumberOfSubKeys != 0))
{
DPRINT("NumberOfSubKeys %d\n", NewKey->KeyCell->NumberOfSubKeys);
NtClose(NewKey);
ObDereferenceObject (NewKey);
ObDereferenceObject (ParentKey);
return(STATUS_INSUFFICIENT_RESOURCES);
}
@ -583,8 +582,10 @@ CmiConnectHive(PREGISTRY_HIVE RegistryHive,
{
DPRINT1("RtlCreateUnicodeString() failed (Status %lx)\n", Status);
if (NewKey->SubKeys != NULL)
{
ExFreePool (NewKey->SubKeys);
NtClose(KeyHandle);
}
ObDereferenceObject (NewKey);
ObDereferenceObject (ParentKey);
return STATUS_INSUFFICIENT_RESOURCES;
}
@ -594,7 +595,65 @@ CmiConnectHive(PREGISTRY_HIVE RegistryHive,
VERIFY_KEY_OBJECT(NewKey);
return(STATUS_SUCCESS);
/* Note: Do not dereference NewKey here! */
return STATUS_SUCCESS;
}
NTSTATUS
CmiDisconnectHive (IN PUNICODE_STRING KeyName,
OUT PREGISTRY_HIVE *RegistryHive)
{
PKEY_OBJECT KeyObject;
PREGISTRY_HIVE Hive;
NTSTATUS Status;
DPRINT("CmiDisconnectHive() called\n");
*RegistryHive = NULL;
Status = ObReferenceObjectByName (KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
STANDARD_RIGHTS_REQUIRED,
CmiKeyType,
KernelMode,
NULL,
(PVOID*)&KeyObject);
if (!NT_SUCCESS(Status))
{
DPRINT1 ("ObReferenceObjectByName() failed (Status %lx)\n", Status);
return Status;
}
DPRINT("KeyObject %p Hive %p\n", KeyObject, KeyObject->RegistryHive);
if (!(KeyObject->KeyCell->Flags & REG_KEY_ROOT_CELL))
{
DPRINT1("Key is not the Hive-Root-Key\n");
ObDereferenceObject(KeyObject);
return STATUS_INVALID_PARAMETER;
}
if (ObGetObjectHandleCount(KeyObject) != 0 ||
ObGetObjectPointerCount(KeyObject) != 2)
{
DPRINT1("Hive is still in use\n");
ObDereferenceObject(KeyObject);
return STATUS_UNSUCCESSFUL;
}
Hive = KeyObject->RegistryHive;
/* Dereference KeyObject twice to delete it */
ObDereferenceObject(KeyObject);
ObDereferenceObject(KeyObject);
*RegistryHive = Hive;
DPRINT("CmiDisconnectHive() done\n");
return STATUS_SUCCESS;
}
@ -619,8 +678,8 @@ CmiInitializeSystemHive (PWSTR FileName,
return Status;
}
Status = CmiConnectHive (RegistryHive,
KeyName);
Status = CmiConnectHive (KeyName,
RegistryHive);
if (!NT_SUCCESS(Status))
{
DPRINT1 ("CmiConnectHive() failed (Status %lx)\n", Status);
@ -713,8 +772,8 @@ CmiInitializeHive(PWSTR FileName,
}
/* Connect the hive */
Status = CmiConnectHive(RegistryHive,
KeyName);
Status = CmiConnectHive(KeyName,
RegistryHive);
if (!NT_SUCCESS(Status))
{
DPRINT1("CmiConnectHive() failed (Status %lx)\n", Status);
@ -922,7 +981,7 @@ CmShutdownRegistry(VOID)
{
Hive = CONTAINING_RECORD(Entry, REGISTRY_HIVE, HiveList);
if (!IsVolatileHive(Hive))
if (!(IsNoFileHive(Hive) || IsNoSynchHive(Hive)))
{
/* Acquire hive resource exclusively */
ExAcquireResourceExclusiveLite(&Hive->HiveResource,
@ -963,7 +1022,7 @@ CmiHiveSyncRoutine(PVOID DeferredContext)
{
Hive = CONTAINING_RECORD(Entry, REGISTRY_HIVE, HiveList);
if (!IsVolatileHive(Hive))
if (!(IsNoFileHive(Hive) || IsNoSynchHive(Hive)))
{
/* Acquire hive resource exclusively */
ExAcquireResourceExclusiveLite(&Hive->HiveResource,

View file

@ -267,7 +267,7 @@ CmiObjectDelete(PVOID DeletedObject)
{
PKEY_OBJECT KeyObject;
DPRINT("Delete object key\n");
DPRINT("Delete key object (%p)\n", DeletedObject);
KeyObject = (PKEY_OBJECT) DeletedObject;
@ -286,7 +286,7 @@ CmiObjectDelete(PVOID DeletedObject)
KeyObject->ParentKey,
KeyObject);
if (!IsVolatileHive(KeyObject->RegistryHive))
if (!IsNoFileHive(KeyObject->RegistryHive))
{
CmiSyncHives();
}