mirror of
https://github.com/reactos/reactos.git
synced 2024-12-31 19:42:51 +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);
|
CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
|
||||||
|
|
||||||
CmiSyncHives();
|
CmiSyncHives();
|
||||||
|
|
||||||
LocalDisposition = REG_CREATED_NEW_KEY;
|
LocalDisposition = REG_CREATED_NEW_KEY;
|
||||||
|
|
||||||
SuccessReturn:
|
SuccessReturn:
|
||||||
|
@ -422,13 +422,13 @@ NtFlushKey(IN HANDLE KeyHandle)
|
||||||
PKEY_OBJECT KeyObject;
|
PKEY_OBJECT KeyObject;
|
||||||
PCMHIVE RegistryHive;
|
PCMHIVE RegistryHive;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
DPRINT("NtFlushKey (KeyHandle %lx) called\n", KeyHandle);
|
DPRINT("NtFlushKey (KeyHandle %lx) called\n", KeyHandle);
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
PreviousMode = ExGetPreviousMode();
|
||||||
|
|
||||||
/* Verify that the handle is valid and is a registry key */
|
/* Verify that the handle is valid and is a registry key */
|
||||||
Status = ObReferenceObjectByHandle(KeyHandle,
|
Status = ObReferenceObjectByHandle(KeyHandle,
|
||||||
0,
|
0,
|
||||||
|
@ -440,15 +440,15 @@ NtFlushKey(IN HANDLE KeyHandle)
|
||||||
{
|
{
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
VERIFY_KEY_OBJECT(KeyObject);
|
VERIFY_KEY_OBJECT(KeyObject);
|
||||||
|
|
||||||
RegistryHive = (PCMHIVE)KeyObject->KeyControlBlock->KeyHive;
|
RegistryHive = (PCMHIVE)KeyObject->KeyControlBlock->KeyHive;
|
||||||
|
|
||||||
/* Acquire hive lock */
|
/* Acquire hive lock */
|
||||||
KeEnterCriticalRegion();
|
KeEnterCriticalRegion();
|
||||||
ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE);
|
ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE);
|
||||||
|
|
||||||
if (IsNoFileHive(RegistryHive))
|
if (IsNoFileHive(RegistryHive))
|
||||||
{
|
{
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
|
@ -458,16 +458,15 @@ NtFlushKey(IN HANDLE KeyHandle)
|
||||||
/* Flush non-volatile hive */
|
/* Flush non-volatile hive */
|
||||||
Status = CmiFlushRegistryHive(RegistryHive);
|
Status = CmiFlushRegistryHive(RegistryHive);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExReleaseResourceLite(&CmpRegistryLock);
|
ExReleaseResourceLite(&CmpRegistryLock);
|
||||||
KeLeaveCriticalRegion();
|
KeLeaveCriticalRegion();
|
||||||
|
|
||||||
ObDereferenceObject(KeyObject);
|
ObDereferenceObject(KeyObject);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
NtOpenKey(OUT PHANDLE KeyHandle,
|
NtOpenKey(OUT PHANDLE KeyHandle,
|
||||||
|
@ -674,7 +673,7 @@ NtInitializeRegistry (IN USHORT Flag)
|
||||||
|
|
||||||
if (CmiRegistryInitialized == TRUE)
|
if (CmiRegistryInitialized == TRUE)
|
||||||
return STATUS_ACCESS_DENIED;
|
return STATUS_ACCESS_DENIED;
|
||||||
|
|
||||||
/* Save boot log file */
|
/* Save boot log file */
|
||||||
IopSaveBootLogToFile();
|
IopSaveBootLogToFile();
|
||||||
|
|
||||||
|
@ -685,635 +684,4 @@ NtInitializeRegistry (IN USHORT Flag)
|
||||||
return Status;
|
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 */
|
/* EOF */
|
||||||
|
|
|
@ -36,7 +36,7 @@ CmiLoadHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
|
||||||
if (Flags & ~REG_NO_LAZY_FLUSH) return STATUS_INVALID_PARAMETER;
|
if (Flags & ~REG_NO_LAZY_FLUSH) return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
Status = CmpInitHiveFromFile(FileName,
|
Status = CmpInitHiveFromFile(FileName,
|
||||||
(Flags & REG_NO_LAZY_FLUSH) ? HIVE_NO_SYNCH : 0,
|
(Flags & REG_NO_LAZY_FLUSH) ? HIVE_NOLAZYFLUSH : 0,
|
||||||
&Hive,
|
&Hive,
|
||||||
&Allocate,
|
&Allocate,
|
||||||
0);
|
0);
|
||||||
|
@ -72,7 +72,7 @@ CmiFlushRegistryHive(PCMHIVE RegistryHive)
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
ULONG Disposition;
|
ULONG Disposition;
|
||||||
|
|
||||||
ASSERT(!IsNoFileHive(RegistryHive));
|
ASSERT(!RegistryHive->Hive.HiveFlags & HIVE_VOLATILE);
|
||||||
|
|
||||||
if (RtlFindSetBits(&RegistryHive->Hive.DirtyVector, 1, 0) == ~0)
|
if (RtlFindSetBits(&RegistryHive->Hive.DirtyVector, 1, 0) == ~0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -535,6 +535,7 @@ CmiInitHives(BOOLEAN SetupBoot)
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
NTAPI
|
||||||
CmShutdownRegistry(VOID)
|
CmShutdownRegistry(VOID)
|
||||||
{
|
{
|
||||||
PCMHIVE Hive;
|
PCMHIVE Hive;
|
||||||
|
|
|
@ -502,7 +502,6 @@ typedef struct _KEY_INFORMATION
|
||||||
#define SYSTEM_LOG_FILE L"\\SystemRoot\\System32\\Config\\SYSTEM.log"
|
#define SYSTEM_LOG_FILE L"\\SystemRoot\\System32\\Config\\SYSTEM.log"
|
||||||
#define REG_SYSTEM_KEY_NAME L"\\Registry\\Machine\\SYSTEM"
|
#define REG_SYSTEM_KEY_NAME L"\\Registry\\Machine\\SYSTEM"
|
||||||
#define REG_HARDWARE_KEY_NAME L"\\Registry\\Machine\\HARDWARE"
|
#define REG_HARDWARE_KEY_NAME L"\\Registry\\Machine\\HARDWARE"
|
||||||
#define IsNoFileHive(Hive) ((Hive)->Flags & HIVE_NO_FILE)
|
|
||||||
typedef struct _KEY_OBJECT
|
typedef struct _KEY_OBJECT
|
||||||
{
|
{
|
||||||
ULONG Type;
|
ULONG Type;
|
||||||
|
@ -515,16 +514,9 @@ typedef struct _KEY_OBJECT
|
||||||
} KEY_OBJECT, *PKEY_OBJECT;
|
} KEY_OBJECT, *PKEY_OBJECT;
|
||||||
extern PCMHIVE CmiVolatileHive;
|
extern PCMHIVE CmiVolatileHive;
|
||||||
extern LIST_ENTRY CmiKeyObjectListHead, CmiConnectedHiveList;
|
extern LIST_ENTRY CmiKeyObjectListHead, CmiConnectedHiveList;
|
||||||
extern KTIMER CmiWorkerTimer;
|
|
||||||
VOID NTAPI CmiWorkerThread(IN PVOID Param);
|
|
||||||
PVOID NTAPI CmpRosGetHardwareHive(OUT PULONG Length);
|
PVOID NTAPI CmpRosGetHardwareHive(OUT PULONG Length);
|
||||||
NTSTATUS CmiCallRegisteredCallbacks(IN REG_NOTIFY_CLASS Argument1, IN PVOID Argument2);
|
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);
|
VOID CmiSyncHives(VOID);
|
||||||
#define HIVE_NO_FILE 0x00000002
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -783,6 +775,12 @@ CmpLockRegistryExclusive(
|
||||||
VOID
|
VOID
|
||||||
);
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CmpLockRegistry(
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
CmpUnlockRegistry(
|
CmpUnlockRegistry(
|
||||||
|
@ -853,6 +851,12 @@ CmpFreeKeyControlBlock(
|
||||||
IN PCM_KEY_CONTROL_BLOCK Kcb
|
IN PCM_KEY_CONTROL_BLOCK Kcb
|
||||||
);
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CmpRemoveKeyControlBlock(
|
||||||
|
IN PCM_KEY_CONTROL_BLOCK Kcb
|
||||||
|
);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
CmpCleanUpKcbCacheWithLock(
|
CmpCleanUpKcbCacheWithLock(
|
||||||
|
@ -957,10 +961,28 @@ CmpGetNextName(
|
||||||
//
|
//
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
NTAPI
|
NTAPI
|
||||||
CmpFlushEntireRegistry(
|
CmpDoFlushAll(
|
||||||
IN BOOLEAN ForceFlush
|
IN BOOLEAN ForceFlush
|
||||||
);
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CmpShutdownWorkers(
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CmpCmdInit(
|
||||||
|
IN BOOLEAN SetupBoot
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CmpLazyFlush(
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Open/Create Routines
|
// Open/Create Routines
|
||||||
//
|
//
|
||||||
|
@ -1269,6 +1291,13 @@ CmDeleteKey(
|
||||||
IN PCM_KEY_CONTROL_BLOCK Kcb
|
IN PCM_KEY_CONTROL_BLOCK Kcb
|
||||||
);
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
CmFlushKey(
|
||||||
|
IN PCM_KEY_CONTROL_BLOCK Kcb,
|
||||||
|
IN BOOLEAN EclusiveLock
|
||||||
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
CmDeleteValueKey(
|
CmDeleteValueKey(
|
||||||
|
@ -1326,6 +1355,9 @@ extern BOOLEAN ExpInTextModeSetup;
|
||||||
extern BOOLEAN InitIsWinPEMode;
|
extern BOOLEAN InitIsWinPEMode;
|
||||||
extern ULONG CmpHashTableSize;
|
extern ULONG CmpHashTableSize;
|
||||||
extern ULONG CmpDelayedCloseSize, CmpDelayedCloseIndex;
|
extern ULONG CmpDelayedCloseSize, CmpDelayedCloseIndex;
|
||||||
|
extern BOOLEAN CmpNoWrite;
|
||||||
|
extern BOOLEAN CmpForceForceFlush;
|
||||||
|
extern BOOLEAN CmpWasSetupBoot;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Inlined functions
|
// Inlined functions
|
||||||
|
|
|
@ -15,6 +15,59 @@
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* 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
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
CmpSetValueKeyNew(IN PHHIVE Hive,
|
CmpSetValueKeyNew(IN PHHIVE Hive,
|
||||||
|
@ -1029,6 +1082,17 @@ CmDeleteKey(IN PCM_KEY_CONTROL_BLOCK Kcb)
|
||||||
Status = STATUS_CANNOT_DELETE;
|
Status = STATUS_CANNOT_DELETE;
|
||||||
goto Quickie;
|
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 */
|
/* Check if we don't have any children */
|
||||||
if (!(Node->SubKeyCounts[Stable] + Node->SubKeyCounts[Volatile]))
|
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);
|
Parent = (PCM_KEY_NODE)HvGetCell(Hive, ParentCell);
|
||||||
if (Parent)
|
if (Parent)
|
||||||
{
|
{
|
||||||
|
/* Update the maximum name length */
|
||||||
|
Kcb->ParentKcb->KcbMaxNameLen = Parent->MaxNameLen;
|
||||||
|
|
||||||
/* Make sure we're dirty */
|
/* Make sure we're dirty */
|
||||||
ASSERT(HvIsCellDirty(Hive, ParentCell));
|
ASSERT(HvIsCellDirty(Hive, ParentCell));
|
||||||
|
|
||||||
/* Update the write time */
|
/* Update the write time */
|
||||||
KeQuerySystemTime(&Parent->LastWriteTime);
|
KeQuerySystemTime(&Parent->LastWriteTime);
|
||||||
|
KeQuerySystemTime(&Kcb->ParentKcb->KcbLastWriteTime);
|
||||||
|
|
||||||
/* Release the cell */
|
/* Release the cell */
|
||||||
HvReleaseCell(Hive, ParentCell);
|
HvReleaseCell(Hive, ParentCell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set the KCB in delete mode and remove it */
|
||||||
|
Kcb->Delete = TRUE;
|
||||||
|
CmpRemoveKeyControlBlock(Kcb);
|
||||||
|
|
||||||
/* Clear the cell */
|
/* Clear the cell */
|
||||||
Kcb->KeyCell = HCELL_NIL;
|
Kcb->KeyCell = HCELL_NIL;
|
||||||
|
@ -1062,14 +1134,9 @@ CmDeleteKey(IN PCM_KEY_CONTROL_BLOCK Kcb)
|
||||||
Status = STATUS_CANNOT_DELETE;
|
Status = STATUS_CANNOT_DELETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure we're file-backed */
|
/* Flush the registry */
|
||||||
if (!(IsNoFileHive((PCMHIVE)Kcb->KeyHive)) ||
|
CmiSyncHives();
|
||||||
!(IsNoFileHive((PCMHIVE)Kcb->ParentKcb->KeyHive)))
|
|
||||||
{
|
|
||||||
/* Sync up the hives */
|
|
||||||
CmiSyncHives();
|
|
||||||
}
|
|
||||||
|
|
||||||
Quickie:
|
Quickie:
|
||||||
/* Release the cell */
|
/* Release the cell */
|
||||||
HvReleaseCell(Hive, Cell);
|
HvReleaseCell(Hive, Cell);
|
||||||
|
@ -1079,3 +1146,36 @@ Quickie:
|
||||||
KeLeaveCriticalRegion();
|
KeLeaveCriticalRegion();
|
||||||
return Status;
|
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 CmpSpecialBootCondition;
|
||||||
BOOLEAN CmpNoWrite;
|
BOOLEAN CmpNoWrite;
|
||||||
BOOLEAN CmpForceForceFlush;
|
BOOLEAN CmpForceForceFlush;
|
||||||
|
BOOLEAN CmpWasSetupBoot;
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
@ -810,7 +811,7 @@ CmInitSystem1(VOID)
|
||||||
/* Build the master hive */
|
/* Build the master hive */
|
||||||
Status = CmpInitializeHive((PCMHIVE*)&CmiVolatileHive,
|
Status = CmpInitializeHive((PCMHIVE*)&CmiVolatileHive,
|
||||||
HINIT_CREATE,
|
HINIT_CREATE,
|
||||||
HIVE_VOLATILE | HIVE_NO_FILE,
|
HIVE_VOLATILE,
|
||||||
HFILE_TYPE_PRIMARY,
|
HFILE_TYPE_PRIMARY,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -900,7 +901,7 @@ CmInitSystem1(VOID)
|
||||||
((PHBASE_BLOCK)BaseAddress)->Length = Length;
|
((PHBASE_BLOCK)BaseAddress)->Length = Length;
|
||||||
Status = CmpInitializeHive((PCMHIVE*)&HardwareHive,
|
Status = CmpInitializeHive((PCMHIVE*)&HardwareHive,
|
||||||
HINIT_MEMORY, //HINIT_CREATE,
|
HINIT_MEMORY, //HINIT_CREATE,
|
||||||
HIVE_NO_FILE, //HIVE_VOLATILE,
|
HIVE_VOLATILE,
|
||||||
HFILE_TYPE_PRIMARY,
|
HFILE_TYPE_PRIMARY,
|
||||||
BaseAddress, // NULL,
|
BaseAddress, // NULL,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -972,6 +973,26 @@ CmpLockRegistryExclusive(VOID)
|
||||||
RtlGetCallersAddress(&CmpRegistryLockCaller, &CmpRegistryLockCallerCaller);
|
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
|
BOOLEAN
|
||||||
NTAPI
|
NTAPI
|
||||||
CmpTestRegistryLock(VOID)
|
CmpTestRegistryLock(VOID)
|
||||||
|
@ -1002,7 +1023,7 @@ CmpUnlockRegistry(VOID)
|
||||||
CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK();
|
CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK();
|
||||||
|
|
||||||
/* Flush the registry */
|
/* Flush the registry */
|
||||||
CmpFlushEntireRegistry(TRUE);
|
CmpDoFlushAll(TRUE);
|
||||||
CmpFlushOnLockRelease = FALSE;
|
CmpFlushOnLockRelease = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1011,27 +1032,11 @@ CmpUnlockRegistry(VOID)
|
||||||
KeLeaveCriticalRegion();
|
KeLeaveCriticalRegion();
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
CmpFlushEntireRegistry(IN BOOLEAN ForceFlush)
|
CmShutdownSystem(VOID)
|
||||||
{
|
{
|
||||||
BOOLEAN Flushed = TRUE;
|
/* Kill the workers and fush all hives */
|
||||||
|
CmpShutdownWorkers();
|
||||||
/* Make sure that the registry isn't read-only now */
|
CmpDoFlushAll(TRUE);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
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 ObInit(VOID);
|
||||||
BOOLEAN NTAPI CmInitSystem1(VOID);
|
BOOLEAN NTAPI CmInitSystem1(VOID);
|
||||||
VOID CmShutdownRegistry(VOID);
|
VOID NTAPI CmShutdownRegistry(VOID);
|
||||||
//BOOLEAN CmImportSystemHive(PCHAR ChunkBase, ULONG ChunkSize);
|
//BOOLEAN CmImportSystemHive(PCHAR ChunkBase, ULONG ChunkSize);
|
||||||
//BOOLEAN CmImportHardwareHive(PCHAR ChunkBase, ULONG ChunkSize);
|
//BOOLEAN CmImportHardwareHive(PCHAR ChunkBase, ULONG ChunkSize);
|
||||||
BOOLEAN NTAPI KdInitSystem(ULONG Reserved, PLOADER_PARAMETER_BLOCK LoaderBlock);
|
BOOLEAN NTAPI KdInitSystem(ULONG Reserved, PLOADER_PARAMETER_BLOCK LoaderBlock);
|
||||||
|
|
|
@ -123,6 +123,7 @@
|
||||||
<file>cmhook.c</file>
|
<file>cmhook.c</file>
|
||||||
<file>cmkcbncb.c</file>
|
<file>cmkcbncb.c</file>
|
||||||
<file>cmkeydel.c</file>
|
<file>cmkeydel.c</file>
|
||||||
|
<file>cmlazy.c</file>
|
||||||
<file>cmmapvw.c</file>
|
<file>cmmapvw.c</file>
|
||||||
<file>cmname.c</file>
|
<file>cmname.c</file>
|
||||||
<file>cmparse.c</file>
|
<file>cmparse.c</file>
|
||||||
|
@ -132,6 +133,7 @@
|
||||||
<file>cmvalue.c</file>
|
<file>cmvalue.c</file>
|
||||||
<file>cmvalche.c</file>
|
<file>cmvalche.c</file>
|
||||||
<file>cmwraprs.c</file>
|
<file>cmwraprs.c</file>
|
||||||
|
<file>ntapi.c</file>
|
||||||
</directory>
|
</directory>
|
||||||
<directory name="cm">
|
<directory name="cm">
|
||||||
<file>ntfunc.c</file>
|
<file>ntfunc.c</file>
|
||||||
|
|
Loading…
Reference in a new issue