mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 02:25:17 +00:00
- Move Nt* APIs converted to new CM into config/cmapi.c
- Start removing usage of ReactOS Hive Flags and use NT Hive Flags instead. - Add CmpLockRegsitry based on CmpLockRegistryExclusive. - Add new lazy flush implementation based on the old one, but with parallel work support. Not yet in use. - Don't delete a key that's already being deleted. - Update KcbMaxNameLen after a deletion. - Set the DELETE flag in the KCB during a deletion. - Remove the KCB Key hash during a delete. - Implement CmFlushKey (not yet used). svn path=/trunk/; revision=30079
This commit is contained in:
parent
64fe695591
commit
3765b77c14
10 changed files with 1098 additions and 689 deletions
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -535,6 +535,7 @@ CmiInitHives(BOOLEAN SetupBoot)
|
|||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CmShutdownRegistry(VOID)
|
||||
{
|
||||
PCMHIVE Hive;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
252
reactos/ntoskrnl/config/cmlazy.c
Normal file
252
reactos/ntoskrnl/config/cmlazy.c
Normal file
|
@ -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 */
|
|
@ -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);
|
||||
}
|
||||
|
|
649
reactos/ntoskrnl/config/ntapi.c
Normal file
649
reactos/ntoskrnl/config/ntapi.c
Normal file
|
@ -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 */
|
|
@ -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);
|
||||
|
|
|
@ -123,6 +123,7 @@
|
|||
<file>cmhook.c</file>
|
||||
<file>cmkcbncb.c</file>
|
||||
<file>cmkeydel.c</file>
|
||||
<file>cmlazy.c</file>
|
||||
<file>cmmapvw.c</file>
|
||||
<file>cmname.c</file>
|
||||
<file>cmparse.c</file>
|
||||
|
@ -132,6 +133,7 @@
|
|||
<file>cmvalue.c</file>
|
||||
<file>cmvalche.c</file>
|
||||
<file>cmwraprs.c</file>
|
||||
<file>ntapi.c</file>
|
||||
</directory>
|
||||
<directory name="cm">
|
||||
<file>ntfunc.c</file>
|
||||
|
|
Loading…
Reference in a new issue