diff --git a/reactos/ntoskrnl/cm/cm.h b/reactos/ntoskrnl/cm/cm.h index 71f54d2d57e..326835a2c5f 100644 --- a/reactos/ntoskrnl/cm/cm.h +++ b/reactos/ntoskrnl/cm/cm.h @@ -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); diff --git a/reactos/ntoskrnl/cm/import.c b/reactos/ntoskrnl/cm/import.c index 1e41d62c032..972cccc17bd 100644 --- a/reactos/ntoskrnl/cm/import.c +++ b/reactos/ntoskrnl/cm/import.c @@ -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); diff --git a/reactos/ntoskrnl/cm/ntfunc.c b/reactos/ntoskrnl/cm/ntfunc.c index 457817b353e..ebf4edc95e6 100644 --- a/reactos/ntoskrnl/cm/ntfunc.c +++ b/reactos/ntoskrnl/cm/ntfunc.c @@ -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 == FALSE) - { - /* FIXME: save boot log file */ + if (CmiRegistryInitialized == TRUE) + return STATUS_ACCESS_DENIED; - Status = CmiInitHives(SetUpBoot); + /* FIXME: save boot log file */ - CmiRegistryInitialized = TRUE; - } + Status = CmiInitHives (SetUpBoot); - return(Status); + CmiRegistryInitialized = TRUE; + + return Status; } /* EOF */ diff --git a/reactos/ntoskrnl/cm/regfile.c b/reactos/ntoskrnl/cm/regfile.c index 0984d568a5b..a5f3073aafd 100644 --- a/reactos/ntoskrnl/cm/regfile.c +++ b/reactos/ntoskrnl/cm/regfile.c @@ -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); diff --git a/reactos/ntoskrnl/cm/registry.c b/reactos/ntoskrnl/cm/registry.c index a258132c17f..0a994c24c2b 100644 --- a/reactos/ntoskrnl/cm/registry.c +++ b/reactos/ntoskrnl/cm/registry.c @@ -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 #include #include -#include +#include #include #include @@ -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); + { + ExFreePool (NewKey->SubKeys); + } + 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, diff --git a/reactos/ntoskrnl/cm/regobj.c b/reactos/ntoskrnl/cm/regobj.c index 9e041443b03..8d61e98cbfc 100644 --- a/reactos/ntoskrnl/cm/regobj.c +++ b/reactos/ntoskrnl/cm/regobj.c @@ -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(); }