- 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:
Aleksey Bragin 2007-11-02 23:12:22 +00:00
parent 64fe695591
commit 3765b77c14
10 changed files with 1098 additions and 689 deletions

View file

@ -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 */

View file

@ -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)
{

View file

@ -535,6 +535,7 @@ CmiInitHives(BOOLEAN SetupBoot)
}
VOID
NTAPI
CmShutdownRegistry(VOID)
{
PCMHIVE Hive;

View file

@ -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

View file

@ -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;
}

View 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 */

View file

@ -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);
}

View 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 */

View file

@ -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);

View file

@ -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>