diff --git a/reactos/ntoskrnl/cm/ntfunc.c b/reactos/ntoskrnl/cm/ntfunc.c index fb33d7019d6..23e7160f8b1 100644 --- a/reactos/ntoskrnl/cm/ntfunc.c +++ b/reactos/ntoskrnl/cm/ntfunc.c @@ -382,7 +382,7 @@ NtCreateKey(OUT PHANDLE KeyHandle, CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo); CmiSyncHives(); - + LocalDisposition = REG_CREATED_NEW_KEY; SuccessReturn: @@ -422,13 +422,13 @@ NtFlushKey(IN HANDLE KeyHandle) PKEY_OBJECT KeyObject; PCMHIVE RegistryHive; KPROCESSOR_MODE PreviousMode; - + PAGED_CODE(); - + DPRINT("NtFlushKey (KeyHandle %lx) called\n", KeyHandle); - + PreviousMode = ExGetPreviousMode(); - + /* Verify that the handle is valid and is a registry key */ Status = ObReferenceObjectByHandle(KeyHandle, 0, @@ -440,15 +440,15 @@ NtFlushKey(IN HANDLE KeyHandle) { return(Status); } - + VERIFY_KEY_OBJECT(KeyObject); - + RegistryHive = (PCMHIVE)KeyObject->KeyControlBlock->KeyHive; - + /* Acquire hive lock */ KeEnterCriticalRegion(); ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE); - + if (IsNoFileHive(RegistryHive)) { Status = STATUS_SUCCESS; @@ -458,16 +458,15 @@ NtFlushKey(IN HANDLE KeyHandle) /* Flush non-volatile hive */ Status = CmiFlushRegistryHive(RegistryHive); } - + ExReleaseResourceLite(&CmpRegistryLock); KeLeaveCriticalRegion(); - + ObDereferenceObject(KeyObject); - + return STATUS_SUCCESS; } - NTSTATUS NTAPI NtOpenKey(OUT PHANDLE KeyHandle, @@ -674,7 +673,7 @@ NtInitializeRegistry (IN USHORT Flag) if (CmiRegistryInitialized == TRUE) return STATUS_ACCESS_DENIED; - + /* Save boot log file */ IopSaveBootLogToFile(); @@ -685,635 +684,4 @@ NtInitializeRegistry (IN USHORT Flag) return Status; } -NTSTATUS -NTAPI -NtDeleteKey(IN HANDLE KeyHandle) -{ - PKEY_OBJECT KeyObject; - NTSTATUS Status; - REG_DELETE_KEY_INFORMATION DeleteKeyInfo; - REG_POST_OPERATION_INFORMATION PostOperationInfo; - PAGED_CODE(); - - DPRINT("NtDeleteKey(KH 0x%p)\n", KeyHandle); - - /* Verify that the handle is valid and is a registry key */ - Status = ObReferenceObjectByHandle(KeyHandle, - DELETE, - CmpKeyObjectType, - ExGetPreviousMode(), - (PVOID *)&KeyObject, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n"); - return Status; - } - - /* Setup the callback */ - PostOperationInfo.Object = (PVOID)KeyObject; - DeleteKeyInfo.Object = (PVOID)KeyObject; - Status = CmiCallRegisteredCallbacks(RegNtPreDeleteKey, &DeleteKeyInfo); - if (NT_SUCCESS(Status)) - { - /* Call the internal API */ - Status = CmDeleteKey(KeyObject->KeyControlBlock); - - /* Remove the keep-alive reference */ - ObDereferenceObject(KeyObject); - if (KeyObject->KeyControlBlock->KeyHive != - KeyObject->KeyControlBlock->ParentKcb->KeyHive) - { - /* Dereference again */ - ObDereferenceObject(KeyObject); - } - - /* Do post callback */ - PostOperationInfo.Status = Status; - CmiCallRegisteredCallbacks(RegNtPostDeleteKey, &PostOperationInfo); - } - - /* Dereference the object */ - ObDereferenceObject(KeyObject); - return Status; -} - -NTSTATUS -NTAPI -NtEnumerateKey(IN HANDLE KeyHandle, - IN ULONG Index, - IN KEY_INFORMATION_CLASS KeyInformationClass, - OUT PVOID KeyInformation, - IN ULONG Length, - OUT PULONG ResultLength) -{ - NTSTATUS Status; - PKEY_OBJECT KeyObject; - REG_ENUMERATE_KEY_INFORMATION EnumerateKeyInfo; - REG_POST_OPERATION_INFORMATION PostOperationInfo; - PAGED_CODE(); - - DPRINT("NtEnumerateKey() KH 0x%x, Index 0x%x, KIC %d, Length %d\n", - KeyHandle, Index, KeyInformationClass, Length); - - /* Verify that the handle is valid and is a registry key */ - Status = ObReferenceObjectByHandle(KeyHandle, - KEY_ENUMERATE_SUB_KEYS, - CmpKeyObjectType, - ExGetPreviousMode(), - (PVOID *)&KeyObject, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n"); - return Status; - } - - /* Setup the callback */ - PostOperationInfo.Object = (PVOID)KeyObject; - EnumerateKeyInfo.Object = (PVOID)KeyObject; - EnumerateKeyInfo.Index = Index; - EnumerateKeyInfo.KeyInformationClass = KeyInformationClass; - EnumerateKeyInfo.Length = Length; - EnumerateKeyInfo.ResultLength = ResultLength; - - /* Do the callback */ - Status = CmiCallRegisteredCallbacks(RegNtPreEnumerateKey, &EnumerateKeyInfo); - if (NT_SUCCESS(Status)) - { - /* Call the internal API */ - Status = CmEnumerateKey(KeyObject->KeyControlBlock, - Index, - KeyInformationClass, - KeyInformation, - Length, - ResultLength); - - /* Do the post callback */ - PostOperationInfo.Status = Status; - CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo); - } - - /* Dereference and return status */ - ObDereferenceObject(KeyObject); - return Status; -} - -NTSTATUS -NTAPI -NtEnumerateValueKey(IN HANDLE KeyHandle, - IN ULONG Index, - IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, - OUT PVOID KeyValueInformation, - IN ULONG Length, - OUT PULONG ResultLength) -{ - NTSTATUS Status; - PKEY_OBJECT KeyObject; - REG_ENUMERATE_VALUE_KEY_INFORMATION EnumerateValueKeyInfo; - REG_POST_OPERATION_INFORMATION PostOperationInfo; - PAGED_CODE(); - - DPRINT("NtEnumerateValueKey() KH 0x%x, Index 0x%x, KVIC %d, Length %d\n", - KeyHandle, Index, KeyValueInformationClass, Length); - - /* Verify that the handle is valid and is a registry key */ - Status = ObReferenceObjectByHandle(KeyHandle, - KEY_QUERY_VALUE, - CmpKeyObjectType, - ExGetPreviousMode(), - (PVOID *)&KeyObject, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n"); - return Status; - } - - /* Setup the callback */ - PostOperationInfo.Object = (PVOID)KeyObject; - EnumerateValueKeyInfo.Object = (PVOID)KeyObject; - EnumerateValueKeyInfo.Index = Index; - EnumerateValueKeyInfo.KeyValueInformationClass = KeyValueInformationClass; - EnumerateValueKeyInfo.KeyValueInformation = KeyValueInformation; - EnumerateValueKeyInfo.Length = Length; - EnumerateValueKeyInfo.ResultLength = ResultLength; - - /* Do the callback */ - Status = CmiCallRegisteredCallbacks(RegNtPreEnumerateValueKey, - &EnumerateValueKeyInfo); - if (NT_SUCCESS(Status)) - { - /* Call the internal API */ - Status = CmEnumerateValueKey(KeyObject->KeyControlBlock, - Index, - KeyValueInformationClass, - KeyValueInformation, - Length, - ResultLength); - - /* Do the post callback */ - PostOperationInfo.Status = Status; - CmiCallRegisteredCallbacks(RegNtPostEnumerateValueKey, &PostOperationInfo); - } - - ObDereferenceObject(KeyObject); - return Status; -} - -NTSTATUS -NTAPI -NtQueryKey(IN HANDLE KeyHandle, - IN KEY_INFORMATION_CLASS KeyInformationClass, - OUT PVOID KeyInformation, - IN ULONG Length, - OUT PULONG ResultLength) -{ - NTSTATUS Status; - PKEY_OBJECT KeyObject; - REG_QUERY_KEY_INFORMATION QueryKeyInfo; - REG_POST_OPERATION_INFORMATION PostOperationInfo; - PAGED_CODE(); - - DPRINT("NtQueryKey() KH 0x%x, KIC %d, Length %d\n", - KeyHandle, KeyInformationClass, Length); - - /* Verify that the handle is valid and is a registry key */ - Status = ObReferenceObjectByHandle(KeyHandle, - (KeyInformationClass != - KeyNameInformation) ? - KEY_QUERY_VALUE : 0, - CmpKeyObjectType, - ExGetPreviousMode(), - (PVOID *)&KeyObject, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n"); - return Status; - } - - /* Setup the callback */ - PostOperationInfo.Object = (PVOID)KeyObject; - QueryKeyInfo.Object = (PVOID)KeyObject; - QueryKeyInfo.KeyInformationClass = KeyInformationClass; - QueryKeyInfo.KeyInformation = KeyInformation; - QueryKeyInfo.Length = Length; - QueryKeyInfo.ResultLength = ResultLength; - - /* Do the callback */ - Status = CmiCallRegisteredCallbacks(RegNtPreQueryKey, &QueryKeyInfo); - if (NT_SUCCESS(Status)) - { - /* Call the internal API */ - Status = CmQueryKey(KeyObject->KeyControlBlock, - KeyInformationClass, - KeyInformation, - Length, - ResultLength); - - /* Do the post callback */ - PostOperationInfo.Status = Status; - CmiCallRegisteredCallbacks(RegNtPostQueryKey, &PostOperationInfo); - } - - /* Dereference and return status */ - ObDereferenceObject(KeyObject); - return Status; -} - -NTSTATUS -NTAPI -NtQueryValueKey(IN HANDLE KeyHandle, - IN PUNICODE_STRING ValueName, - IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, - OUT PVOID KeyValueInformation, - IN ULONG Length, - OUT PULONG ResultLength) -{ - NTSTATUS Status; - PKEY_OBJECT KeyObject; - REG_QUERY_VALUE_KEY_INFORMATION QueryValueKeyInfo; - REG_POST_OPERATION_INFORMATION PostOperationInfo; - PAGED_CODE(); - - DPRINT("NtQueryValueKey() KH 0x%x, VN '%wZ', KVIC %d, Length %d\n", - KeyHandle, ValueName, KeyValueInformationClass, Length); - - /* Verify that the handle is valid and is a registry key */ - Status = ObReferenceObjectByHandle(KeyHandle, - KEY_QUERY_VALUE, - CmpKeyObjectType, - ExGetPreviousMode(), - (PVOID *)&KeyObject, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n"); - return Status; - } - - /* Setup the callback */ - PostOperationInfo.Object = (PVOID)KeyObject; - QueryValueKeyInfo.Object = (PVOID)KeyObject; - QueryValueKeyInfo.ValueName = ValueName; - QueryValueKeyInfo.KeyValueInformationClass = KeyValueInformationClass; - QueryValueKeyInfo.Length = Length; - QueryValueKeyInfo.ResultLength = ResultLength; - - /* Do the callback */ - Status = CmiCallRegisteredCallbacks(RegNtPreQueryValueKey, &QueryValueKeyInfo); - if (NT_SUCCESS(Status)) - { - /* Call the internal API */ - Status = CmQueryValueKey(KeyObject->KeyControlBlock, - *ValueName, - KeyValueInformationClass, - KeyValueInformation, - Length, - ResultLength); - - /* Do the post callback */ - PostOperationInfo.Status = Status; - CmiCallRegisteredCallbacks(RegNtPostQueryValueKey, &PostOperationInfo); - } - - DPRINT("NtQueryValueKey() returning 0x%08X\n", Status); - - /* Dereference and return status */ - ObDereferenceObject(KeyObject); - return Status; -} - -NTSTATUS -NTAPI -NtSetValueKey(IN HANDLE KeyHandle, - IN PUNICODE_STRING ValueName, - IN ULONG TitleIndex, - IN ULONG Type, - IN PVOID Data, - IN ULONG DataSize) -{ - NTSTATUS Status; - PKEY_OBJECT KeyObject; - REG_SET_VALUE_KEY_INFORMATION SetValueKeyInfo; - REG_POST_OPERATION_INFORMATION PostOperationInfo; - PAGED_CODE(); - - DPRINT("NtSetValueKey() KH 0x%x, VN '%wZ', TI %x, T %d, DS %d\n", - KeyHandle, ValueName, TitleIndex, Type, DataSize); - - /* Verify that the handle is valid and is a registry key */ - Status = ObReferenceObjectByHandle(KeyHandle, - KEY_SET_VALUE, - CmpKeyObjectType, - ExGetPreviousMode(), - (PVOID *)&KeyObject, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("ObReferenceObjectByHandle() failed with Status = 0x%08X\n", Status); - return Status; - } - - /* Setup callback */ - PostOperationInfo.Object = (PVOID)KeyObject; - SetValueKeyInfo.Object = (PVOID)KeyObject; - SetValueKeyInfo.ValueName = ValueName; - SetValueKeyInfo.TitleIndex = TitleIndex; - SetValueKeyInfo.Type = Type; - SetValueKeyInfo.Data = Data; - SetValueKeyInfo.DataSize = DataSize; - - /* Do the callback */ - Status = CmiCallRegisteredCallbacks(RegNtPreSetValueKey, &SetValueKeyInfo); - if (NT_SUCCESS(Status)) - { - /* Call the internal API */ - Status = CmSetValueKey(KeyObject->KeyControlBlock, - ValueName, - Type, - Data, - DataSize); - } - - /* Do the post-callback and de-reference the key object */ - PostOperationInfo.Status = Status; - CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo); - ObDereferenceObject(KeyObject); - - /* Synchronize the hives and return */ - CmiSyncHives(); - return Status; -} - -NTSTATUS -NTAPI -NtDeleteValueKey(IN HANDLE KeyHandle, - IN PUNICODE_STRING ValueName) -{ - PKEY_OBJECT KeyObject; - NTSTATUS Status; - REG_DELETE_VALUE_KEY_INFORMATION DeleteValueKeyInfo; - REG_POST_OPERATION_INFORMATION PostOperationInfo; - KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); - PAGED_CODE(); - - /* Verify that the handle is valid and is a registry key */ - Status = ObReferenceObjectByHandle(KeyHandle, - KEY_SET_VALUE, - CmpKeyObjectType, - PreviousMode, - (PVOID *)&KeyObject, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n"); - return Status; - } - - /* Do the callback */ - DeleteValueKeyInfo.Object = (PVOID)KeyObject; - DeleteValueKeyInfo.ValueName = ValueName; - Status = CmiCallRegisteredCallbacks(RegNtPreDeleteValueKey, - &DeleteValueKeyInfo); - if (NT_SUCCESS(Status)) - { - /* Call the internal API */ - Status = CmDeleteValueKey(KeyObject->KeyControlBlock, *ValueName); - - /* Do the post callback */ - PostOperationInfo.Object = (PVOID)KeyObject; - PostOperationInfo.Status = Status; - CmiCallRegisteredCallbacks(RegNtPostDeleteValueKey, - &PostOperationInfo); - } - - /* Dereference the key body and synchronize the hives */ - ObDereferenceObject(KeyObject); - CmiSyncHives(); - return Status; -} - -NTSTATUS -NTAPI -NtCompactKeys(IN ULONG Count, - IN PHANDLE KeyArray) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NtCompressKey(IN HANDLE Key) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NtLoadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes, - IN POBJECT_ATTRIBUTES FileObjectAttributes) -{ - return NtLoadKey2(KeyObjectAttributes, FileObjectAttributes, 0); -} - -NTSTATUS -NTAPI -NtLoadKeyEx(IN POBJECT_ATTRIBUTES TargetKey, - IN POBJECT_ATTRIBUTES SourceFile, - IN ULONG Flags, - IN HANDLE TrustClassKey, - IN HANDLE Event, - IN ACCESS_MASK DesiredAccess, - OUT PHANDLE RootHandle) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NtLockProductActivationKeys(IN PULONG pPrivateVer, - IN PULONG pSafeMode) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NtLockRegistryKey(IN HANDLE KeyHandle) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NtNotifyChangeMultipleKeys(IN HANDLE MasterKeyHandle, - IN ULONG Count, - IN POBJECT_ATTRIBUTES SlaveObjects, - IN HANDLE Event, - IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, - IN PVOID ApcContext OPTIONAL, - OUT PIO_STATUS_BLOCK IoStatusBlock, - IN ULONG CompletionFilter, - IN BOOLEAN WatchTree, - OUT PVOID Buffer, - IN ULONG Length, - IN BOOLEAN Asynchronous) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NtNotifyChangeKey(IN HANDLE KeyHandle, - IN HANDLE Event, - IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, - IN PVOID ApcContext OPTIONAL, - OUT PIO_STATUS_BLOCK IoStatusBlock, - IN ULONG CompletionFilter, - IN BOOLEAN WatchTree, - OUT PVOID Buffer, - IN ULONG Length, - IN BOOLEAN Asynchronous) -{ - return NtNotifyChangeMultipleKeys(KeyHandle, - 0, - NULL, - Event, - ApcRoutine, - ApcContext, - IoStatusBlock, - CompletionFilter, - WatchTree, - Buffer, - Length, - Asynchronous); -} - -NTSTATUS -NTAPI -NtQueryMultipleValueKey(IN HANDLE KeyHandle, - IN OUT PKEY_VALUE_ENTRY ValueList, - IN ULONG NumberOfValues, - OUT PVOID Buffer, - IN OUT PULONG Length, - OUT PULONG ReturnLength) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NtQueryOpenSubKeys(IN POBJECT_ATTRIBUTES TargetKey, - IN ULONG HandleCount) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NtQueryOpenSubKeysEx(IN POBJECT_ATTRIBUTES TargetKey, - IN ULONG BufferLength, - IN PVOID Buffer, - IN PULONG RequiredSize) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NtReplaceKey(IN POBJECT_ATTRIBUTES ObjectAttributes, - IN HANDLE Key, - IN POBJECT_ATTRIBUTES ReplacedObjectAttributes) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NtRestoreKey(IN HANDLE KeyHandle, - IN HANDLE FileHandle, - IN ULONG RestoreFlags) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NtSaveKey(IN HANDLE KeyHandle, - IN HANDLE FileHandle) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NtSaveKeyEx(IN HANDLE KeyHandle, - IN HANDLE FileHandle, - IN ULONG Flags) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NtSaveMergedKeys(IN HANDLE HighPrecedenceKeyHandle, - IN HANDLE LowPrecedenceKeyHandle, - IN HANDLE FileHandle) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NtSetInformationKey(IN HANDLE KeyHandle, - IN KEY_SET_INFORMATION_CLASS KeyInformationClass, - IN PVOID KeyInformation, - IN ULONG KeyInformationLength) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NtUnloadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NtUnloadKey2(IN POBJECT_ATTRIBUTES TargetKey, - IN ULONG Flags) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NtUnloadKeyEx(IN POBJECT_ATTRIBUTES TargetKey, - IN HANDLE Event) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - /* EOF */ diff --git a/reactos/ntoskrnl/cm/regfile.c b/reactos/ntoskrnl/cm/regfile.c index 653bc2bbd42..0bfe640de20 100644 --- a/reactos/ntoskrnl/cm/regfile.c +++ b/reactos/ntoskrnl/cm/regfile.c @@ -36,7 +36,7 @@ CmiLoadHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes, if (Flags & ~REG_NO_LAZY_FLUSH) return STATUS_INVALID_PARAMETER; Status = CmpInitHiveFromFile(FileName, - (Flags & REG_NO_LAZY_FLUSH) ? HIVE_NO_SYNCH : 0, + (Flags & REG_NO_LAZY_FLUSH) ? HIVE_NOLAZYFLUSH : 0, &Hive, &Allocate, 0); @@ -72,7 +72,7 @@ CmiFlushRegistryHive(PCMHIVE RegistryHive) NTSTATUS Status; ULONG Disposition; - ASSERT(!IsNoFileHive(RegistryHive)); + ASSERT(!RegistryHive->Hive.HiveFlags & HIVE_VOLATILE); if (RtlFindSetBits(&RegistryHive->Hive.DirtyVector, 1, 0) == ~0) { diff --git a/reactos/ntoskrnl/cm/registry.c b/reactos/ntoskrnl/cm/registry.c index 6b148984c76..25a29aecc4a 100644 --- a/reactos/ntoskrnl/cm/registry.c +++ b/reactos/ntoskrnl/cm/registry.c @@ -535,6 +535,7 @@ CmiInitHives(BOOLEAN SetupBoot) } VOID +NTAPI CmShutdownRegistry(VOID) { PCMHIVE Hive; diff --git a/reactos/ntoskrnl/config/cm.h b/reactos/ntoskrnl/config/cm.h index bb341367d0b..67f27d71fea 100644 --- a/reactos/ntoskrnl/config/cm.h +++ b/reactos/ntoskrnl/config/cm.h @@ -502,7 +502,6 @@ typedef struct _KEY_INFORMATION #define SYSTEM_LOG_FILE L"\\SystemRoot\\System32\\Config\\SYSTEM.log" #define REG_SYSTEM_KEY_NAME L"\\Registry\\Machine\\SYSTEM" #define REG_HARDWARE_KEY_NAME L"\\Registry\\Machine\\HARDWARE" -#define IsNoFileHive(Hive) ((Hive)->Flags & HIVE_NO_FILE) typedef struct _KEY_OBJECT { ULONG Type; @@ -515,16 +514,9 @@ typedef struct _KEY_OBJECT } KEY_OBJECT, *PKEY_OBJECT; extern PCMHIVE CmiVolatileHive; extern LIST_ENTRY CmiKeyObjectListHead, CmiConnectedHiveList; -extern KTIMER CmiWorkerTimer; -VOID NTAPI CmiWorkerThread(IN PVOID Param); PVOID NTAPI CmpRosGetHardwareHive(OUT PULONG Length); NTSTATUS CmiCallRegisteredCallbacks(IN REG_NOTIFY_CLASS Argument1, IN PVOID Argument2); -ULONG CmiGetMaxNameLength(IN PHHIVE RegistryHive, IN PCM_KEY_NODE KeyCell); -ULONG CmiGetMaxClassLength(IN PHHIVE RegistryHive, IN PCM_KEY_NODE KeyCell); -ULONG CmiGetMaxValueNameLength(IN PHHIVE RegistryHive, IN PCM_KEY_NODE KeyCell); -ULONG CmiGetMaxValueDataLength(IN PHHIVE RegistryHive, IN PCM_KEY_NODE KeyCell); VOID CmiSyncHives(VOID); -#define HIVE_NO_FILE 0x00000002 /////////////////////////////////////////////////////////////////////////////// // @@ -783,6 +775,12 @@ CmpLockRegistryExclusive( VOID ); +VOID +NTAPI +CmpLockRegistry( + VOID +); + VOID NTAPI CmpUnlockRegistry( @@ -853,6 +851,12 @@ CmpFreeKeyControlBlock( IN PCM_KEY_CONTROL_BLOCK Kcb ); +VOID +NTAPI +CmpRemoveKeyControlBlock( + IN PCM_KEY_CONTROL_BLOCK Kcb +); + VOID NTAPI CmpCleanUpKcbCacheWithLock( @@ -957,10 +961,28 @@ CmpGetNextName( // BOOLEAN NTAPI -CmpFlushEntireRegistry( +CmpDoFlushAll( IN BOOLEAN ForceFlush ); +VOID +NTAPI +CmpShutdownWorkers( + VOID +); + +VOID +NTAPI +CmpCmdInit( + IN BOOLEAN SetupBoot +); + +VOID +NTAPI +CmpLazyFlush( + VOID +); + // // Open/Create Routines // @@ -1269,6 +1291,13 @@ CmDeleteKey( IN PCM_KEY_CONTROL_BLOCK Kcb ); +NTSTATUS +NTAPI +CmFlushKey( + IN PCM_KEY_CONTROL_BLOCK Kcb, + IN BOOLEAN EclusiveLock +); + NTSTATUS NTAPI CmDeleteValueKey( @@ -1326,6 +1355,9 @@ extern BOOLEAN ExpInTextModeSetup; extern BOOLEAN InitIsWinPEMode; extern ULONG CmpHashTableSize; extern ULONG CmpDelayedCloseSize, CmpDelayedCloseIndex; +extern BOOLEAN CmpNoWrite; +extern BOOLEAN CmpForceForceFlush; +extern BOOLEAN CmpWasSetupBoot; // // Inlined functions diff --git a/reactos/ntoskrnl/config/cmapi.c b/reactos/ntoskrnl/config/cmapi.c index f45a21a6cc3..b4e906ca790 100644 --- a/reactos/ntoskrnl/config/cmapi.c +++ b/reactos/ntoskrnl/config/cmapi.c @@ -15,6 +15,59 @@ /* FUNCTIONS *****************************************************************/ +BOOLEAN +NTAPI +CmpDoFlushAll(IN BOOLEAN ForceFlush) +{ + NTSTATUS Status; + PLIST_ENTRY NextEntry; + PCMHIVE Hive; + BOOLEAN Result = TRUE; + + /* Make sure that the registry isn't read-only now */ + if (CmpNoWrite) return TRUE; + + /* Otherwise, acquire the hive list lock and disable force flush */ + CmpForceForceFlush = FALSE; + ExAcquirePushLockShared(&CmpHiveListHeadLock); + + /* Loop the hive list */ + NextEntry = CmpHiveListHead.Flink; + while (NextEntry != &CmpHiveListHead) + { + /* Get the hive */ + Hive = CONTAINING_RECORD(NextEntry, CMHIVE, HiveList); + if (!(Hive->Hive.HiveFlags & HIVE_NOLAZYFLUSH)) + { + /* Find out why this is needed? [Aleksey] */ + ULONG Disposition; + Status = CmpOpenHiveFiles(&Hive->FileFullPath, + L".LOG", + &Hive->FileHandles[HFILE_TYPE_PRIMARY], + &Hive->FileHandles[HFILE_TYPE_LOG], + &Disposition, + &Disposition, + FALSE, + FALSE, + TRUE, + NULL); + + /* Do the sync */ + DPRINT1("Flushing: %wZ\n", &Hive->FileFullPath); + DPRINT1("Handle: %lx\n", Hive->FileHandles[HFILE_TYPE_PRIMARY]); + Status = HvSyncHive(&Hive->Hive); + if (!NT_SUCCESS(Status)) Result = FALSE; + } + + /* Try the next entry */ + NextEntry = NextEntry->Flink; + } + + /* Release lock and return */ + ExReleasePushLock(&CmpHiveListHeadLock); + return Result; +} + NTSTATUS NTAPI CmpSetValueKeyNew(IN PHHIVE Hive, @@ -1029,6 +1082,17 @@ CmDeleteKey(IN PCM_KEY_CONTROL_BLOCK Kcb) Status = STATUS_CANNOT_DELETE; goto Quickie; } + + /* Check if we're already being deleted */ + if (Kcb->Delete) + { + /* Don't do it twice */ + Status = STATUS_SUCCESS; + goto Quickie; + } + + /* Sanity check */ + ASSERT(Node->Flags == Kcb->Flags); /* Check if we don't have any children */ if (!(Node->SubKeyCounts[Stable] + Node->SubKeyCounts[Volatile])) @@ -1042,15 +1106,23 @@ CmDeleteKey(IN PCM_KEY_CONTROL_BLOCK Kcb) Parent = (PCM_KEY_NODE)HvGetCell(Hive, ParentCell); if (Parent) { + /* Update the maximum name length */ + Kcb->ParentKcb->KcbMaxNameLen = Parent->MaxNameLen; + /* Make sure we're dirty */ ASSERT(HvIsCellDirty(Hive, ParentCell)); /* Update the write time */ KeQuerySystemTime(&Parent->LastWriteTime); + KeQuerySystemTime(&Kcb->ParentKcb->KcbLastWriteTime); /* Release the cell */ HvReleaseCell(Hive, ParentCell); } + + /* Set the KCB in delete mode and remove it */ + Kcb->Delete = TRUE; + CmpRemoveKeyControlBlock(Kcb); /* Clear the cell */ Kcb->KeyCell = HCELL_NIL; @@ -1062,14 +1134,9 @@ CmDeleteKey(IN PCM_KEY_CONTROL_BLOCK Kcb) Status = STATUS_CANNOT_DELETE; } - /* Make sure we're file-backed */ - if (!(IsNoFileHive((PCMHIVE)Kcb->KeyHive)) || - !(IsNoFileHive((PCMHIVE)Kcb->ParentKcb->KeyHive))) - { - /* Sync up the hives */ - CmiSyncHives(); - } - + /* Flush the registry */ + CmiSyncHives(); + Quickie: /* Release the cell */ HvReleaseCell(Hive, Cell); @@ -1079,3 +1146,36 @@ Quickie: KeLeaveCriticalRegion(); return Status; } + +NTSTATUS +NTAPI +CmFlushKey(IN PCM_KEY_CONTROL_BLOCK Kcb, + IN BOOLEAN EclusiveLock) +{ + PCMHIVE CmHive; + NTSTATUS Status; + PHHIVE Hive; + + /* Get the hives */ + Hive = Kcb->KeyHive; + CmHive = (PCMHIVE)Hive; + + /* Check if this is the master hive */ + if (CmHive == CmiVolatileHive) + { + /* Flush all the hives instead */ + CmpDoFlushAll(FALSE); + } + else + { + /* Flush only this hive */ + if (!HvSyncHive(Hive)) + { + /* Fail */ + Status = STATUS_REGISTRY_IO_FAILED; + } + } + + /* Return the status */ + return Status; +} diff --git a/reactos/ntoskrnl/config/cmlazy.c b/reactos/ntoskrnl/config/cmlazy.c new file mode 100644 index 00000000000..bffe6f57b09 --- /dev/null +++ b/reactos/ntoskrnl/config/cmlazy.c @@ -0,0 +1,252 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: ntoskrnl/config/cmapi.c + * PURPOSE: Configuration Manager - Internal Registry APIs + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES *******************************************************************/ + +#include "ntoskrnl.h" +#include "cm.h" +#define NDEBUG +#include "debug.h" + +/* GLOBALS ********************************************************************/ + +KTIMER CmpLazyFlushTimer; +KDPC CmpLazyFlushDpc; +WORK_QUEUE_ITEM CmpLazyWorkItem; +KTIMER CmpEnableLazyFlushTimer; +KDPC CmpEnableLazyFlushDpc; +BOOLEAN CmpLazyFlushPending; +BOOLEAN CmpForceForceFlush; +BOOLEAN CmpHoldLazyFlush = TRUE; +ULONG CmpLazyFlushIntervalInSeconds = 5; +ULONG CmpLazyFlushHiveCount = 7; +ULONG CmpLazyFlushCount = 1; +LONG CmpFlushStarveWriters; + +/* FUNCTIONS ******************************************************************/ + +BOOLEAN +NTAPI +CmpDoFlushNextHive(IN BOOLEAN ForceFlush, + OUT PBOOLEAN Error, + OUT PULONG DirtyCount) +{ + NTSTATUS Status; + PLIST_ENTRY NextEntry; + PCMHIVE CmHive; + BOOLEAN Result; + ULONG HiveCount = CmpLazyFlushHiveCount; + + /* Set Defaults */ + *Error = FALSE; + *DirtyCount = 0; + + /* Don't do anything if we're not supposed to */ + if (CmpNoWrite) return TRUE; + + /* Make sure we have to flush at least one hive */ + if (!HiveCount) HiveCount = 1; + + /* Don't force flush */ + CmpForceForceFlush = FALSE; + + /* Acquire the list lock and loop */ + ExAcquirePushLockShared(&CmpHiveListHeadLock); + NextEntry = CmpHiveListHead.Flink; + while (NextEntry != &CmpHiveListHead) + { + /* Get the hive and check if we should flush it */ + CmHive = CONTAINING_RECORD(NextEntry, CMHIVE, HiveList); + if (!(CmHive->Hive.HiveFlags & HIVE_NOLAZYFLUSH) && + (CmHive->FlushCount != CmpLazyFlushCount)) + { + /* Great sucess! */ + Result = TRUE; + + /* Ignore clean or volatile hves */ + if (!(CmHive->Hive.DirtyCount) || + (CmHive->Hive.HiveFlags & HIVE_VOLATILE)) + { + /* Don't do anything but do update the count */ + CmHive->FlushCount = CmpLazyFlushCount; + } + else + { + /* Do the sync */ + DPRINT1("Flushing: %wZ\n", CmHive->FileFullPath); + DPRINT1("Handle: %lx\n", CmHive->FileHandles[HFILE_TYPE_PRIMARY]); + Status = HvSyncHive(&CmHive->Hive); + if(!NT_SUCCESS(Status)) + { + /* Let them know we failed */ + *Error = TRUE; + Result = FALSE; + } + } + } + else if ((CmHive->Hive.DirtyCount) && + (!(CmHive->Hive.HiveFlags & HIVE_VOLATILE)) && + (!(CmHive->Hive.HiveFlags & HIVE_NOLAZYFLUSH))) + { + /* Use another lazy flusher for this hive */ + ASSERT(CmHive->FlushCount == CmpLazyFlushCount); + *DirtyCount += CmHive->Hive.DirtyCount; + } + + /* Try the next one */ + NextEntry = NextEntry->Flink; + } + + /* Check if we've flushed everything */ + if (NextEntry == &CmpHiveListHead) + { + /* We have, tell the caller we're done */ + Result = FALSE; + } + else + { + /* We need to be called again */ + Result = TRUE; + } + + /* Unlock the list and return the result */ + ExReleasePushLock(&CmpHiveListHeadLock); + return Result; +} + +VOID +NTAPI +CmpEnableLazyFlushDpcRoutine(IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2) +{ + /* Don't stop lazy flushing from happening anymore */ + CmpHoldLazyFlush = FALSE; +} + +VOID +NTAPI +CmpLazyFlushDpcRoutine(IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2) +{ + /* Check if we should queue the lazy flush worker */ + if ((!CmpLazyFlushPending) && (!CmpHoldLazyFlush)) + { + CmpLazyFlushPending = TRUE; + ExQueueWorkItem(&CmpLazyWorkItem, DelayedWorkQueue); + } +} + +VOID +NTAPI +CmpLazyFlush(VOID) +{ + LARGE_INTEGER DueTime; + PAGED_CODE(); + + /* Check if we should set the lazy flush timer */ + if ((!CmpNoWrite) && (!CmpHoldLazyFlush)) + { + /* Do it */ + DueTime.QuadPart = Int32x32To64(CmpLazyFlushIntervalInSeconds, + -10 * 1000 * 1000); + KeSetTimer(&CmpLazyFlushTimer, DueTime, &CmpLazyFlushDpc); + } +} + +VOID +NTAPI +CmpLazyFlushWorker(IN PVOID Parameter) +{ + BOOLEAN ForceFlush, Result, MoreWork = FALSE; + ULONG DirtyCount = 0; + PAGED_CODE(); + + /* Don't do anything if lazy flushing isn't enabled yet */ + if (CmpHoldLazyFlush) return; + + /* Check if we are forcing a flush */ + ForceFlush = CmpForceForceFlush; + if (ForceFlush) + { + /* Lock the registry exclusively */ + CmpLockRegistryExclusive(); + } + else + { + /* Do a normal lock */ + CmpLockRegistry(); + InterlockedIncrement(&CmpFlushStarveWriters); + } + + /* Flush the next hive */ + MoreWork = CmpDoFlushNextHive(ForceFlush, &Result, &DirtyCount); + if (!MoreWork) + { + /* We're done */ + InterlockedIncrement((PLONG)&CmpLazyFlushCount); + } + + /* Check if we have starved writers */ + if (!ForceFlush) InterlockedDecrement(&CmpFlushStarveWriters); + + /* Not pending anymore, release the registry lock */ + CmpLazyFlushPending = FALSE; + CmpUnlockRegistry(); + + /* Check if we need to flush another hive */ + if ((MoreWork) || (DirtyCount)) CmpLazyFlush(); +} + +VOID +NTAPI +CmpCmdInit(IN BOOLEAN SetupBoot) +{ + LARGE_INTEGER DueTime; + PAGED_CODE(); + + /* Setup the lazy DPC */ + KeInitializeDpc(&CmpLazyFlushDpc, CmpLazyFlushDpcRoutine, NULL); + + /* Setup the lazy timer */ + KeInitializeTimer(&CmpLazyFlushTimer); + + /* Setup the lazy worker */ + ExInitializeWorkItem(&CmpLazyWorkItem, CmpLazyFlushWorker, NULL); + + /* Setup the forced-lazy DPC and timer */ + KeInitializeDpc(&CmpEnableLazyFlushDpc, + CmpEnableLazyFlushDpcRoutine, + NULL); + KeInitializeTimer(&CmpEnableLazyFlushTimer); + + /* Enable lazy flushing after 10 minutes */ + DueTime.QuadPart = Int32x32To64(600, -10 * 1000 * 1000); + KeSetTimer(&CmpEnableLazyFlushTimer, DueTime, &CmpEnableLazyFlushDpc); + + /* Setup flush variables */ + CmpNoWrite = CmpMiniNTBoot; + CmpWasSetupBoot = SetupBoot; + + /* Testing: Force Lazy Flushing */ + CmpHoldLazyFlush = FALSE; +} + +VOID +NTAPI +CmpShutdownWorkers(VOID) +{ + /* Stop lazy flushing */ + PAGED_CODE(); + KeCancelTimer(&CmpLazyFlushTimer); +} + +/* EOF */ diff --git a/reactos/ntoskrnl/config/cmsysini.c b/reactos/ntoskrnl/config/cmsysini.c index 986210a5973..9a7434b566e 100644 --- a/reactos/ntoskrnl/config/cmsysini.c +++ b/reactos/ntoskrnl/config/cmsysini.c @@ -23,6 +23,7 @@ BOOLEAN CmpFlushOnLockRelease; BOOLEAN CmpSpecialBootCondition; BOOLEAN CmpNoWrite; BOOLEAN CmpForceForceFlush; +BOOLEAN CmpWasSetupBoot; /* FUNCTIONS *****************************************************************/ @@ -810,7 +811,7 @@ CmInitSystem1(VOID) /* Build the master hive */ Status = CmpInitializeHive((PCMHIVE*)&CmiVolatileHive, HINIT_CREATE, - HIVE_VOLATILE | HIVE_NO_FILE, + HIVE_VOLATILE, HFILE_TYPE_PRIMARY, NULL, NULL, @@ -900,7 +901,7 @@ CmInitSystem1(VOID) ((PHBASE_BLOCK)BaseAddress)->Length = Length; Status = CmpInitializeHive((PCMHIVE*)&HardwareHive, HINIT_MEMORY, //HINIT_CREATE, - HIVE_NO_FILE, //HIVE_VOLATILE, + HIVE_VOLATILE, HFILE_TYPE_PRIMARY, BaseAddress, // NULL, NULL, @@ -972,6 +973,26 @@ CmpLockRegistryExclusive(VOID) RtlGetCallersAddress(&CmpRegistryLockCaller, &CmpRegistryLockCallerCaller); } +VOID +NTAPI +CmpLockRegistry(VOID) +{ + /* Enter a critical region */ + KeEnterCriticalRegion(); + + /* Check if we have to starve writers */ + if (CmpFlushStarveWriters) + { + /* Starve exlusive waiters */ + ExAcquireSharedStarveExclusive(&CmpRegistryLock, TRUE); + } + else + { + /* Just grab the lock */ + ExAcquireResourceSharedLite(&CmpRegistryLock, TRUE); + } +} + BOOLEAN NTAPI CmpTestRegistryLock(VOID) @@ -1002,7 +1023,7 @@ CmpUnlockRegistry(VOID) CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK(); /* Flush the registry */ - CmpFlushEntireRegistry(TRUE); + CmpDoFlushAll(TRUE); CmpFlushOnLockRelease = FALSE; } @@ -1011,27 +1032,11 @@ CmpUnlockRegistry(VOID) KeLeaveCriticalRegion(); } -BOOLEAN +VOID NTAPI -CmpFlushEntireRegistry(IN BOOLEAN ForceFlush) +CmShutdownSystem(VOID) { - BOOLEAN Flushed = TRUE; - - /* Make sure that the registry isn't read-only now */ - if (CmpNoWrite) return TRUE; - - /* Otherwise, acquire the hive list lock and disable force flush */ - CmpForceForceFlush = FALSE; - ExAcquirePushLockShared(&CmpHiveListHeadLock); - - /* Check if the hive list isn't empty */ - if (!IsListEmpty(&CmpHiveListHead)) - { - /* FIXME: TODO */ - ASSERT(FALSE); - } - - /* Release the lock and return the flush state */ - ExReleasePushLock(&CmpHiveListHeadLock); - return Flushed; + /* Kill the workers and fush all hives */ + CmpShutdownWorkers(); + CmpDoFlushAll(TRUE); } diff --git a/reactos/ntoskrnl/config/ntapi.c b/reactos/ntoskrnl/config/ntapi.c new file mode 100644 index 00000000000..3dcb58a2256 --- /dev/null +++ b/reactos/ntoskrnl/config/ntapi.c @@ -0,0 +1,649 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: ntoskrnl/config/cmapi.c + * PURPOSE: Configuration Manager - Internal Registry APIs + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include "ntoskrnl.h" +#include "cm.h" +#define NDEBUG +#include "debug.h" + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +NTAPI +NtDeleteKey(IN HANDLE KeyHandle) +{ + PKEY_OBJECT KeyObject; + NTSTATUS Status; + REG_DELETE_KEY_INFORMATION DeleteKeyInfo; + REG_POST_OPERATION_INFORMATION PostOperationInfo; + PAGED_CODE(); + + DPRINT("NtDeleteKey(KH 0x%p)\n", KeyHandle); + + /* Verify that the handle is valid and is a registry key */ + Status = ObReferenceObjectByHandle(KeyHandle, + DELETE, + CmpKeyObjectType, + ExGetPreviousMode(), + (PVOID *)&KeyObject, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n"); + return Status; + } + + /* Setup the callback */ + PostOperationInfo.Object = (PVOID)KeyObject; + DeleteKeyInfo.Object = (PVOID)KeyObject; + Status = CmiCallRegisteredCallbacks(RegNtPreDeleteKey, &DeleteKeyInfo); + if (NT_SUCCESS(Status)) + { + /* Call the internal API */ + Status = CmDeleteKey(KeyObject->KeyControlBlock); + + /* Remove the keep-alive reference */ + ObDereferenceObject(KeyObject); + if (KeyObject->KeyControlBlock->KeyHive != + KeyObject->KeyControlBlock->ParentKcb->KeyHive) + { + /* Dereference again */ + ObDereferenceObject(KeyObject); + } + + /* Do post callback */ + PostOperationInfo.Status = Status; + CmiCallRegisteredCallbacks(RegNtPostDeleteKey, &PostOperationInfo); + } + + /* Dereference the object */ + ObDereferenceObject(KeyObject); + return Status; +} + +NTSTATUS +NTAPI +NtEnumerateKey(IN HANDLE KeyHandle, + IN ULONG Index, + IN KEY_INFORMATION_CLASS KeyInformationClass, + OUT PVOID KeyInformation, + IN ULONG Length, + OUT PULONG ResultLength) +{ + NTSTATUS Status; + PKEY_OBJECT KeyObject; + REG_ENUMERATE_KEY_INFORMATION EnumerateKeyInfo; + REG_POST_OPERATION_INFORMATION PostOperationInfo; + PAGED_CODE(); + + DPRINT("NtEnumerateKey() KH 0x%x, Index 0x%x, KIC %d, Length %d\n", + KeyHandle, Index, KeyInformationClass, Length); + + /* Verify that the handle is valid and is a registry key */ + Status = ObReferenceObjectByHandle(KeyHandle, + KEY_ENUMERATE_SUB_KEYS, + CmpKeyObjectType, + ExGetPreviousMode(), + (PVOID *)&KeyObject, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n"); + return Status; + } + + /* Setup the callback */ + PostOperationInfo.Object = (PVOID)KeyObject; + EnumerateKeyInfo.Object = (PVOID)KeyObject; + EnumerateKeyInfo.Index = Index; + EnumerateKeyInfo.KeyInformationClass = KeyInformationClass; + EnumerateKeyInfo.Length = Length; + EnumerateKeyInfo.ResultLength = ResultLength; + + /* Do the callback */ + Status = CmiCallRegisteredCallbacks(RegNtPreEnumerateKey, &EnumerateKeyInfo); + if (NT_SUCCESS(Status)) + { + /* Call the internal API */ + Status = CmEnumerateKey(KeyObject->KeyControlBlock, + Index, + KeyInformationClass, + KeyInformation, + Length, + ResultLength); + + /* Do the post callback */ + PostOperationInfo.Status = Status; + CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo); + } + + /* Dereference and return status */ + ObDereferenceObject(KeyObject); + return Status; +} + +NTSTATUS +NTAPI +NtEnumerateValueKey(IN HANDLE KeyHandle, + IN ULONG Index, + IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + OUT PVOID KeyValueInformation, + IN ULONG Length, + OUT PULONG ResultLength) +{ + NTSTATUS Status; + PKEY_OBJECT KeyObject; + REG_ENUMERATE_VALUE_KEY_INFORMATION EnumerateValueKeyInfo; + REG_POST_OPERATION_INFORMATION PostOperationInfo; + PAGED_CODE(); + + DPRINT("NtEnumerateValueKey() KH 0x%x, Index 0x%x, KVIC %d, Length %d\n", + KeyHandle, Index, KeyValueInformationClass, Length); + + /* Verify that the handle is valid and is a registry key */ + Status = ObReferenceObjectByHandle(KeyHandle, + KEY_QUERY_VALUE, + CmpKeyObjectType, + ExGetPreviousMode(), + (PVOID *)&KeyObject, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n"); + return Status; + } + + /* Setup the callback */ + PostOperationInfo.Object = (PVOID)KeyObject; + EnumerateValueKeyInfo.Object = (PVOID)KeyObject; + EnumerateValueKeyInfo.Index = Index; + EnumerateValueKeyInfo.KeyValueInformationClass = KeyValueInformationClass; + EnumerateValueKeyInfo.KeyValueInformation = KeyValueInformation; + EnumerateValueKeyInfo.Length = Length; + EnumerateValueKeyInfo.ResultLength = ResultLength; + + /* Do the callback */ + Status = CmiCallRegisteredCallbacks(RegNtPreEnumerateValueKey, + &EnumerateValueKeyInfo); + if (NT_SUCCESS(Status)) + { + /* Call the internal API */ + Status = CmEnumerateValueKey(KeyObject->KeyControlBlock, + Index, + KeyValueInformationClass, + KeyValueInformation, + Length, + ResultLength); + + /* Do the post callback */ + PostOperationInfo.Status = Status; + CmiCallRegisteredCallbacks(RegNtPostEnumerateValueKey, &PostOperationInfo); + } + + ObDereferenceObject(KeyObject); + return Status; +} + +NTSTATUS +NTAPI +NtQueryKey(IN HANDLE KeyHandle, + IN KEY_INFORMATION_CLASS KeyInformationClass, + OUT PVOID KeyInformation, + IN ULONG Length, + OUT PULONG ResultLength) +{ + NTSTATUS Status; + PKEY_OBJECT KeyObject; + REG_QUERY_KEY_INFORMATION QueryKeyInfo; + REG_POST_OPERATION_INFORMATION PostOperationInfo; + PAGED_CODE(); + + DPRINT("NtQueryKey() KH 0x%x, KIC %d, Length %d\n", + KeyHandle, KeyInformationClass, Length); + + /* Verify that the handle is valid and is a registry key */ + Status = ObReferenceObjectByHandle(KeyHandle, + (KeyInformationClass != + KeyNameInformation) ? + KEY_QUERY_VALUE : 0, + CmpKeyObjectType, + ExGetPreviousMode(), + (PVOID *)&KeyObject, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n"); + return Status; + } + + /* Setup the callback */ + PostOperationInfo.Object = (PVOID)KeyObject; + QueryKeyInfo.Object = (PVOID)KeyObject; + QueryKeyInfo.KeyInformationClass = KeyInformationClass; + QueryKeyInfo.KeyInformation = KeyInformation; + QueryKeyInfo.Length = Length; + QueryKeyInfo.ResultLength = ResultLength; + + /* Do the callback */ + Status = CmiCallRegisteredCallbacks(RegNtPreQueryKey, &QueryKeyInfo); + if (NT_SUCCESS(Status)) + { + /* Call the internal API */ + Status = CmQueryKey(KeyObject->KeyControlBlock, + KeyInformationClass, + KeyInformation, + Length, + ResultLength); + + /* Do the post callback */ + PostOperationInfo.Status = Status; + CmiCallRegisteredCallbacks(RegNtPostQueryKey, &PostOperationInfo); + } + + /* Dereference and return status */ + ObDereferenceObject(KeyObject); + return Status; +} + +NTSTATUS +NTAPI +NtQueryValueKey(IN HANDLE KeyHandle, + IN PUNICODE_STRING ValueName, + IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + OUT PVOID KeyValueInformation, + IN ULONG Length, + OUT PULONG ResultLength) +{ + NTSTATUS Status; + PKEY_OBJECT KeyObject; + REG_QUERY_VALUE_KEY_INFORMATION QueryValueKeyInfo; + REG_POST_OPERATION_INFORMATION PostOperationInfo; + PAGED_CODE(); + + DPRINT("NtQueryValueKey() KH 0x%x, VN '%wZ', KVIC %d, Length %d\n", + KeyHandle, ValueName, KeyValueInformationClass, Length); + + /* Verify that the handle is valid and is a registry key */ + Status = ObReferenceObjectByHandle(KeyHandle, + KEY_QUERY_VALUE, + CmpKeyObjectType, + ExGetPreviousMode(), + (PVOID *)&KeyObject, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n"); + return Status; + } + + /* Setup the callback */ + PostOperationInfo.Object = (PVOID)KeyObject; + QueryValueKeyInfo.Object = (PVOID)KeyObject; + QueryValueKeyInfo.ValueName = ValueName; + QueryValueKeyInfo.KeyValueInformationClass = KeyValueInformationClass; + QueryValueKeyInfo.Length = Length; + QueryValueKeyInfo.ResultLength = ResultLength; + + /* Do the callback */ + Status = CmiCallRegisteredCallbacks(RegNtPreQueryValueKey, &QueryValueKeyInfo); + if (NT_SUCCESS(Status)) + { + /* Call the internal API */ + Status = CmQueryValueKey(KeyObject->KeyControlBlock, + *ValueName, + KeyValueInformationClass, + KeyValueInformation, + Length, + ResultLength); + + /* Do the post callback */ + PostOperationInfo.Status = Status; + CmiCallRegisteredCallbacks(RegNtPostQueryValueKey, &PostOperationInfo); + } + + DPRINT("NtQueryValueKey() returning 0x%08X\n", Status); + + /* Dereference and return status */ + ObDereferenceObject(KeyObject); + return Status; +} + +NTSTATUS +NTAPI +NtSetValueKey(IN HANDLE KeyHandle, + IN PUNICODE_STRING ValueName, + IN ULONG TitleIndex, + IN ULONG Type, + IN PVOID Data, + IN ULONG DataSize) +{ + NTSTATUS Status; + PKEY_OBJECT KeyObject; + REG_SET_VALUE_KEY_INFORMATION SetValueKeyInfo; + REG_POST_OPERATION_INFORMATION PostOperationInfo; + PAGED_CODE(); + + DPRINT("NtSetValueKey() KH 0x%x, VN '%wZ', TI %x, T %d, DS %d\n", + KeyHandle, ValueName, TitleIndex, Type, DataSize); + + /* Verify that the handle is valid and is a registry key */ + Status = ObReferenceObjectByHandle(KeyHandle, + KEY_SET_VALUE, + CmpKeyObjectType, + ExGetPreviousMode(), + (PVOID *)&KeyObject, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("ObReferenceObjectByHandle() failed with Status = 0x%08X\n", Status); + return Status; + } + + /* Setup callback */ + PostOperationInfo.Object = (PVOID)KeyObject; + SetValueKeyInfo.Object = (PVOID)KeyObject; + SetValueKeyInfo.ValueName = ValueName; + SetValueKeyInfo.TitleIndex = TitleIndex; + SetValueKeyInfo.Type = Type; + SetValueKeyInfo.Data = Data; + SetValueKeyInfo.DataSize = DataSize; + + /* Do the callback */ + Status = CmiCallRegisteredCallbacks(RegNtPreSetValueKey, &SetValueKeyInfo); + if (NT_SUCCESS(Status)) + { + /* Call the internal API */ + Status = CmSetValueKey(KeyObject->KeyControlBlock, + ValueName, + Type, + Data, + DataSize); + } + + /* Do the post-callback and de-reference the key object */ + PostOperationInfo.Status = Status; + CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo); + ObDereferenceObject(KeyObject); + + /* Synchronize the hives and return */ + CmiSyncHives(); + return Status; +} + +NTSTATUS +NTAPI +NtDeleteValueKey(IN HANDLE KeyHandle, + IN PUNICODE_STRING ValueName) +{ + PKEY_OBJECT KeyObject; + NTSTATUS Status; + REG_DELETE_VALUE_KEY_INFORMATION DeleteValueKeyInfo; + REG_POST_OPERATION_INFORMATION PostOperationInfo; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + PAGED_CODE(); + + /* Verify that the handle is valid and is a registry key */ + Status = ObReferenceObjectByHandle(KeyHandle, + KEY_SET_VALUE, + CmpKeyObjectType, + PreviousMode, + (PVOID *)&KeyObject, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n"); + return Status; + } + + /* Do the callback */ + DeleteValueKeyInfo.Object = (PVOID)KeyObject; + DeleteValueKeyInfo.ValueName = ValueName; + Status = CmiCallRegisteredCallbacks(RegNtPreDeleteValueKey, + &DeleteValueKeyInfo); + if (NT_SUCCESS(Status)) + { + /* Call the internal API */ + Status = CmDeleteValueKey(KeyObject->KeyControlBlock, *ValueName); + + /* Do the post callback */ + PostOperationInfo.Object = (PVOID)KeyObject; + PostOperationInfo.Status = Status; + CmiCallRegisteredCallbacks(RegNtPostDeleteValueKey, + &PostOperationInfo); + } + + /* Dereference the key body and synchronize the hives */ + ObDereferenceObject(KeyObject); + CmiSyncHives(); + return Status; +} + +NTSTATUS +NTAPI +NtCompactKeys(IN ULONG Count, + IN PHANDLE KeyArray) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +NtCompressKey(IN HANDLE Key) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +NtLoadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes, + IN POBJECT_ATTRIBUTES FileObjectAttributes) +{ + return NtLoadKey2(KeyObjectAttributes, FileObjectAttributes, 0); +} + +NTSTATUS +NTAPI +NtLoadKeyEx(IN POBJECT_ATTRIBUTES TargetKey, + IN POBJECT_ATTRIBUTES SourceFile, + IN ULONG Flags, + IN HANDLE TrustClassKey, + IN HANDLE Event, + IN ACCESS_MASK DesiredAccess, + OUT PHANDLE RootHandle) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +NtLockProductActivationKeys(IN PULONG pPrivateVer, + IN PULONG pSafeMode) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +NtLockRegistryKey(IN HANDLE KeyHandle) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +NtNotifyChangeMultipleKeys(IN HANDLE MasterKeyHandle, + IN ULONG Count, + IN POBJECT_ATTRIBUTES SlaveObjects, + IN HANDLE Event, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG CompletionFilter, + IN BOOLEAN WatchTree, + OUT PVOID Buffer, + IN ULONG Length, + IN BOOLEAN Asynchronous) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +NtNotifyChangeKey(IN HANDLE KeyHandle, + IN HANDLE Event, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG CompletionFilter, + IN BOOLEAN WatchTree, + OUT PVOID Buffer, + IN ULONG Length, + IN BOOLEAN Asynchronous) +{ + return NtNotifyChangeMultipleKeys(KeyHandle, + 0, + NULL, + Event, + ApcRoutine, + ApcContext, + IoStatusBlock, + CompletionFilter, + WatchTree, + Buffer, + Length, + Asynchronous); +} + +NTSTATUS +NTAPI +NtQueryMultipleValueKey(IN HANDLE KeyHandle, + IN OUT PKEY_VALUE_ENTRY ValueList, + IN ULONG NumberOfValues, + OUT PVOID Buffer, + IN OUT PULONG Length, + OUT PULONG ReturnLength) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +NtQueryOpenSubKeys(IN POBJECT_ATTRIBUTES TargetKey, + IN ULONG HandleCount) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +NtQueryOpenSubKeysEx(IN POBJECT_ATTRIBUTES TargetKey, + IN ULONG BufferLength, + IN PVOID Buffer, + IN PULONG RequiredSize) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +NtReplaceKey(IN POBJECT_ATTRIBUTES ObjectAttributes, + IN HANDLE Key, + IN POBJECT_ATTRIBUTES ReplacedObjectAttributes) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +NtRestoreKey(IN HANDLE KeyHandle, + IN HANDLE FileHandle, + IN ULONG RestoreFlags) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +NtSaveKey(IN HANDLE KeyHandle, + IN HANDLE FileHandle) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +NtSaveKeyEx(IN HANDLE KeyHandle, + IN HANDLE FileHandle, + IN ULONG Flags) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +NtSaveMergedKeys(IN HANDLE HighPrecedenceKeyHandle, + IN HANDLE LowPrecedenceKeyHandle, + IN HANDLE FileHandle) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +NtSetInformationKey(IN HANDLE KeyHandle, + IN KEY_SET_INFORMATION_CLASS KeyInformationClass, + IN PVOID KeyInformation, + IN ULONG KeyInformationLength) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +NtUnloadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +NtUnloadKey2(IN POBJECT_ATTRIBUTES TargetKey, + IN ULONG Flags) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +NtUnloadKeyEx(IN POBJECT_ATTRIBUTES TargetKey, + IN HANDLE Event) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +/* EOF */ diff --git a/reactos/ntoskrnl/include/internal/ntoskrnl.h b/reactos/ntoskrnl/include/internal/ntoskrnl.h index a6608cf8dab..3c0a63799f2 100644 --- a/reactos/ntoskrnl/include/internal/ntoskrnl.h +++ b/reactos/ntoskrnl/include/internal/ntoskrnl.h @@ -72,7 +72,7 @@ typedef struct __DESCRIPTOR */ BOOLEAN NTAPI ObInit(VOID); BOOLEAN NTAPI CmInitSystem1(VOID); -VOID CmShutdownRegistry(VOID); +VOID NTAPI CmShutdownRegistry(VOID); //BOOLEAN CmImportSystemHive(PCHAR ChunkBase, ULONG ChunkSize); //BOOLEAN CmImportHardwareHive(PCHAR ChunkBase, ULONG ChunkSize); BOOLEAN NTAPI KdInitSystem(ULONG Reserved, PLOADER_PARAMETER_BLOCK LoaderBlock); diff --git a/reactos/ntoskrnl/ntoskrnl.rbuild b/reactos/ntoskrnl/ntoskrnl.rbuild index 3f99c420cf8..691c54f6f00 100644 --- a/reactos/ntoskrnl/ntoskrnl.rbuild +++ b/reactos/ntoskrnl/ntoskrnl.rbuild @@ -123,6 +123,7 @@ cmhook.c cmkcbncb.c cmkeydel.c + cmlazy.c cmmapvw.c cmname.c cmparse.c @@ -132,6 +133,7 @@ cmvalue.c cmvalche.c cmwraprs.c + ntapi.c ntfunc.c