- Fix typo in KCB flag.

- CmDeleteKey takes a Key Body, not a KCB.
- Simplify some code since ValueCache.RealKCB is a KCB now, not a hacked PKEY_OBJECT, so a bunch of typecasts can be removed.
- Implement CmpCleanUpSubKeyInfo to remove cached subkey information when a KCB is deleted (subkeys are not cached yet, however).
- Add checks in various code paths to make sure we don't touch a read-only KCB.
- Don't double-dereference a key object during a delete.
- Add checks for invalid key information classes.
- For KeyNameInformation, the caller must have some handle access to succeed the call.
- Validate alignment of key value names.
- Don't accept NULLs at the end of key value names.
- Validate key value name lengths.
- Validate data lengths.
- Remove a couple of forced lazy flushes that aren't required anymore.
- Use CmpLockRegistry() in ntapi.c instead of the manual lock release.

svn path=/trunk/; revision=31257
This commit is contained in:
Aleksey Bragin 2007-12-15 20:51:40 +00:00
parent 55dcdfc6c9
commit 0f4bc4008d
4 changed files with 246 additions and 86 deletions

View file

@ -1035,12 +1035,13 @@ Quickie:
NTSTATUS NTSTATUS
NTAPI NTAPI
CmDeleteKey(IN PCM_KEY_CONTROL_BLOCK Kcb) CmDeleteKey(IN PCM_KEY_BODY KeyBody)
{ {
NTSTATUS Status; NTSTATUS Status;
PHHIVE Hive; PHHIVE Hive;
PCM_KEY_NODE Node, Parent; PCM_KEY_NODE Node, Parent;
HCELL_INDEX Cell, ParentCell; HCELL_INDEX Cell, ParentCell;
PCM_KEY_CONTROL_BLOCK Kcb = KeyBody->KeyControlBlock;
/* Acquire hive lock */ /* Acquire hive lock */
KeEnterCriticalRegion(); KeEnterCriticalRegion();

View file

@ -449,15 +449,15 @@ CmpCleanUpKcbValueCache(IN PCM_KEY_CONTROL_BLOCK Kcb)
else if (Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND) else if (Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND)
{ {
/* This is a sym link, check if there's only one reference left */ /* This is a sym link, check if there's only one reference left */
if ((((PCM_KEY_CONTROL_BLOCK)Kcb->ValueCache.RealKcb)->RefCount == 1) && if ((Kcb->ValueCache.RealKcb->RefCount == 1) &&
!(((PCM_KEY_CONTROL_BLOCK)Kcb->ValueCache.RealKcb)->Delete)) !(Kcb->ValueCache.RealKcb->Delete))
{ {
/* Disable delay close for the KCB */ /* Disable delay close for the KCB */
((PCM_KEY_CONTROL_BLOCK)Kcb->ValueCache.RealKcb)->ExtFlags |= CM_KCB_NO_DELAY_CLOSE; Kcb->ValueCache.RealKcb->ExtFlags |= CM_KCB_NO_DELAY_CLOSE;
} }
/* Dereference the KCB */ /* Dereference the KCB */
CmpDelayDerefKeyControlBlock((PCM_KEY_CONTROL_BLOCK)Kcb->ValueCache.RealKcb); CmpDelayDerefKeyControlBlock(Kcb->ValueCache.RealKcb);
Kcb->ExtFlags &= ~CM_KCB_SYM_LINK_FOUND; Kcb->ExtFlags &= ~CM_KCB_SYM_LINK_FOUND;
} }
} }
@ -501,6 +501,61 @@ CmpCleanUpKcbCacheWithLock(IN PCM_KEY_CONTROL_BLOCK Kcb,
} }
} }
VOID
NTAPI
CmpCleanUpSubKeyInfo(IN PCM_KEY_CONTROL_BLOCK Kcb)
{
PCM_KEY_NODE KeyNode;
/* Sanity check */
ASSERT((CmpIsKcbLockedExclusive(Kcb) == TRUE) ||
(CmpTestRegistryLockExclusive() == TRUE));
/* Check if there's any cached subkey */
if (Kcb->ExtFlags & (CM_KCB_NO_SUBKEY | CM_KCB_SUBKEY_ONE | CM_KCB_SUBKEY_HINT))
{
/* Check if there's a hint */
if (Kcb->ExtFlags & (CM_KCB_SUBKEY_HINT))
{
/* Kill it */
ExFreePool(Kcb->IndexHint);
}
/* Remove subkey flags */
Kcb->ExtFlags &= ~(CM_KCB_NO_SUBKEY | CM_KCB_SUBKEY_ONE | CM_KCB_SUBKEY_HINT);
}
/* Check if there's no linked cell */
if (Kcb->KeyCell == HCELL_NIL)
{
/* Make sure it's a delete */
ASSERT(Kcb->Delete);
KeyNode = NULL;
}
else
{
/* Get the key node */
KeyNode = (PCM_KEY_NODE)HvGetCell(Kcb->KeyHive, Kcb->KeyCell);
}
/* Check if we got the node */
if (!KeyNode)
{
/* We didn't, mark the cached data invalid */
Kcb->ExtFlags |= CM_KCB_INVALID_CACHED_INFO;
}
else
{
/* We have a keynode, update subkey counts */
Kcb->ExtFlags &= ~CM_KCB_INVALID_CACHED_INFO;
Kcb->SubKeyCount = KeyNode->SubKeyCounts[Stable] +
KeyNode->SubKeyCounts[Volatile];
/* Release the cell */
HvReleaseCell(Kcb->KeyHive, Kcb->KeyCell);
}
}
VOID VOID
NTAPI NTAPI
CmpDereferenceKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb) CmpDereferenceKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb)
@ -821,4 +876,3 @@ EnlistKeyBodyWithKCB(IN PCM_KEY_BODY KeyBody,
/* FIXME: Implement once we don't link parents to children anymore */ /* FIXME: Implement once we don't link parents to children anymore */
} }

View file

@ -90,7 +90,6 @@ NtDeleteKey(IN HANDLE KeyHandle)
REG_DELETE_KEY_INFORMATION DeleteKeyInfo; REG_DELETE_KEY_INFORMATION DeleteKeyInfo;
REG_POST_OPERATION_INFORMATION PostOperationInfo; REG_POST_OPERATION_INFORMATION PostOperationInfo;
PAGED_CODE(); PAGED_CODE();
DPRINT("NtDeleteKey(KH 0x%p)\n", KeyHandle); DPRINT("NtDeleteKey(KH 0x%p)\n", KeyHandle);
/* Verify that the handle is valid and is a registry key */ /* Verify that the handle is valid and is a registry key */
@ -98,13 +97,9 @@ NtDeleteKey(IN HANDLE KeyHandle)
DELETE, DELETE,
CmpKeyObjectType, CmpKeyObjectType,
ExGetPreviousMode(), ExGetPreviousMode(),
(PVOID *)&KeyObject, (PVOID*)&KeyObject,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status)) return Status;
{
DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n");
return Status;
}
/* Setup the callback */ /* Setup the callback */
PostOperationInfo.Object = (PVOID)KeyObject; PostOperationInfo.Object = (PVOID)KeyObject;
@ -112,16 +107,17 @@ NtDeleteKey(IN HANDLE KeyHandle)
Status = CmiCallRegisteredCallbacks(RegNtPreDeleteKey, &DeleteKeyInfo); Status = CmiCallRegisteredCallbacks(RegNtPreDeleteKey, &DeleteKeyInfo);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
/* Call the internal API */ /* Check if we are read-only */
Status = CmDeleteKey(KeyObject->KeyControlBlock); if ((KeyObject->KeyControlBlock->ExtFlags & CM_KCB_READ_ONLY_KEY) ||
(KeyObject->KeyControlBlock->ParentKcb->ExtFlags & CM_KCB_READ_ONLY_KEY))
/* Remove the keep-alive reference */
ObDereferenceObject(KeyObject);
if (KeyObject->KeyControlBlock->KeyHive !=
KeyObject->KeyControlBlock->ParentKcb->KeyHive)
{ {
/* Dereference again */ /* Fail */
ObDereferenceObject(KeyObject); Status = STATUS_ACCESS_DENIED;
}
else
{
/* Call the internal API */
Status = CmDeleteKey(KeyObject);
} }
/* Do post callback */ /* Do post callback */
@ -148,22 +144,26 @@ NtEnumerateKey(IN HANDLE KeyHandle,
REG_ENUMERATE_KEY_INFORMATION EnumerateKeyInfo; REG_ENUMERATE_KEY_INFORMATION EnumerateKeyInfo;
REG_POST_OPERATION_INFORMATION PostOperationInfo; REG_POST_OPERATION_INFORMATION PostOperationInfo;
PAGED_CODE(); PAGED_CODE();
DPRINT("NtEnumerateKey() KH 0x%x, Index 0x%x, KIC %d, Length %d\n", DPRINT("NtEnumerateKey() KH 0x%x, Index 0x%x, KIC %d, Length %d\n",
KeyHandle, Index, KeyInformationClass, Length); KeyHandle, Index, KeyInformationClass, Length);
/* Reject classes we don't know about */
if ((KeyInformationClass != KeyBasicInformation) &&
(KeyInformationClass != KeyNodeInformation) &&
(KeyInformationClass != KeyFullInformation))
{
/* Fail */
return STATUS_INVALID_PARAMETER;
}
/* 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,
KEY_ENUMERATE_SUB_KEYS, KEY_ENUMERATE_SUB_KEYS,
CmpKeyObjectType, CmpKeyObjectType,
ExGetPreviousMode(), ExGetPreviousMode(),
(PVOID *)&KeyObject, (PVOID*)&KeyObject,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status)) return Status;
{
DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n");
return Status;
}
/* Setup the callback */ /* Setup the callback */
PostOperationInfo.Object = (PVOID)KeyObject; PostOperationInfo.Object = (PVOID)KeyObject;
@ -209,22 +209,26 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
REG_ENUMERATE_VALUE_KEY_INFORMATION EnumerateValueKeyInfo; REG_ENUMERATE_VALUE_KEY_INFORMATION EnumerateValueKeyInfo;
REG_POST_OPERATION_INFORMATION PostOperationInfo; REG_POST_OPERATION_INFORMATION PostOperationInfo;
PAGED_CODE(); PAGED_CODE();
DPRINT("NtEnumerateValueKey() KH 0x%x, Index 0x%x, KVIC %d, Length %d\n", DPRINT("NtEnumerateValueKey() KH 0x%x, Index 0x%x, KVIC %d, Length %d\n",
KeyHandle, Index, KeyValueInformationClass, Length); KeyHandle, Index, KeyValueInformationClass, Length);
/* Reject classes we don't know about */
if ((KeyValueInformationClass != KeyValueBasicInformation) &&
(KeyValueInformationClass != KeyValueFullInformation) &&
(KeyValueInformationClass != KeyValuePartialInformation))
{
/* Fail */
return STATUS_INVALID_PARAMETER;
}
/* 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,
KEY_QUERY_VALUE, KEY_QUERY_VALUE,
CmpKeyObjectType, CmpKeyObjectType,
ExGetPreviousMode(), ExGetPreviousMode(),
(PVOID *)&KeyObject, (PVOID*)&KeyObject,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status)) return Status;
{
DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n");
return Status;
}
/* Setup the callback */ /* Setup the callback */
PostOperationInfo.Object = (PVOID)KeyObject; PostOperationInfo.Object = (PVOID)KeyObject;
@ -269,26 +273,58 @@ NtQueryKey(IN HANDLE KeyHandle,
PCM_KEY_BODY KeyObject; PCM_KEY_BODY KeyObject;
REG_QUERY_KEY_INFORMATION QueryKeyInfo; REG_QUERY_KEY_INFORMATION QueryKeyInfo;
REG_POST_OPERATION_INFORMATION PostOperationInfo; REG_POST_OPERATION_INFORMATION PostOperationInfo;
OBJECT_HANDLE_INFORMATION HandleInfo;
PAGED_CODE(); PAGED_CODE();
DPRINT("NtQueryKey() KH 0x%x, KIC %d, Length %d\n", DPRINT("NtQueryKey() KH 0x%x, KIC %d, Length %d\n",
KeyHandle, KeyInformationClass, Length); KeyHandle, KeyInformationClass, Length);
/* Verify that the handle is valid and is a registry key */ /* Reject invalid classes */
Status = ObReferenceObjectByHandle(KeyHandle, if ((KeyInformationClass != KeyBasicInformation) &&
(KeyInformationClass != (KeyInformationClass != KeyNodeInformation) &&
KeyNameInformation) ? (KeyInformationClass != KeyFullInformation) &&
KEY_QUERY_VALUE : 0, (KeyInformationClass != KeyNameInformation) &&
CmpKeyObjectType, (KeyInformationClass != KeyCachedInformation) &&
ExGetPreviousMode(), (KeyInformationClass != KeyFlagsInformation))
(PVOID *)&KeyObject,
NULL);
if (!NT_SUCCESS(Status))
{ {
DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n"); /* Fail */
return Status; return STATUS_INVALID_PARAMETER;
} }
/* Check if just the name is required */
if (KeyInformationClass == KeyNameInformation)
{
/* Ignore access level */
Status = ObReferenceObjectByHandle(KeyHandle,
0,
CmpKeyObjectType,
ExGetPreviousMode(),
(PVOID*)&KeyObject,
&HandleInfo);
if (NT_SUCCESS(Status))
{
/* At least a single bit of access is required */
if (!HandleInfo.GrantedAccess)
{
/* No such luck */
ObDereferenceObject(KeyObject);
Status = STATUS_ACCESS_DENIED;
}
}
}
else
{
/* Get a reference */
Status = ObReferenceObjectByHandle(KeyHandle,
KEY_QUERY_VALUE,
CmpKeyObjectType,
ExGetPreviousMode(),
(PVOID*)&KeyObject,
NULL);
}
/* Quit on failure */
if (!NT_SUCCESS(Status)) return Status;
/* Setup the callback */ /* Setup the callback */
PostOperationInfo.Object = (PVOID)KeyObject; PostOperationInfo.Object = (PVOID)KeyObject;
QueryKeyInfo.Object = (PVOID)KeyObject; QueryKeyInfo.Object = (PVOID)KeyObject;
@ -331,8 +367,8 @@ NtQueryValueKey(IN HANDLE KeyHandle,
PCM_KEY_BODY KeyObject; PCM_KEY_BODY KeyObject;
REG_QUERY_VALUE_KEY_INFORMATION QueryValueKeyInfo; REG_QUERY_VALUE_KEY_INFORMATION QueryValueKeyInfo;
REG_POST_OPERATION_INFORMATION PostOperationInfo; REG_POST_OPERATION_INFORMATION PostOperationInfo;
UNICODE_STRING ValueNameCopy = *ValueName;
PAGED_CODE(); PAGED_CODE();
DPRINT("NtQueryValueKey() KH 0x%x, VN '%wZ', KVIC %d, Length %d\n", DPRINT("NtQueryValueKey() KH 0x%x, VN '%wZ', KVIC %d, Length %d\n",
KeyHandle, ValueName, KeyValueInformationClass, Length); KeyHandle, ValueName, KeyValueInformationClass, Length);
@ -341,18 +377,32 @@ NtQueryValueKey(IN HANDLE KeyHandle,
KEY_QUERY_VALUE, KEY_QUERY_VALUE,
CmpKeyObjectType, CmpKeyObjectType,
ExGetPreviousMode(), ExGetPreviousMode(),
(PVOID *)&KeyObject, (PVOID*)&KeyObject,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status)) return Status;
/* Make sure the name is aligned properly */
if ((ValueNameCopy.Length & (sizeof(WCHAR) - 1)))
{ {
DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n"); /* It isn't, so we'll fail */
return Status; ObDereferenceObject(KeyObject);
return STATUS_INVALID_PARAMETER;
}
else
{
/* Ignore any null characters at the end */
while ((ValueNameCopy.Length) &&
!(ValueNameCopy.Buffer[ValueNameCopy.Length / sizeof(WCHAR) - 1]))
{
/* Skip it */
ValueNameCopy.Length -= sizeof(WCHAR);
}
} }
/* Setup the callback */ /* Setup the callback */
PostOperationInfo.Object = (PVOID)KeyObject; PostOperationInfo.Object = (PVOID)KeyObject;
QueryValueKeyInfo.Object = (PVOID)KeyObject; QueryValueKeyInfo.Object = (PVOID)KeyObject;
QueryValueKeyInfo.ValueName = ValueName; QueryValueKeyInfo.ValueName = &ValueNameCopy;
QueryValueKeyInfo.KeyValueInformationClass = KeyValueInformationClass; QueryValueKeyInfo.KeyValueInformationClass = KeyValueInformationClass;
QueryValueKeyInfo.Length = Length; QueryValueKeyInfo.Length = Length;
QueryValueKeyInfo.ResultLength = ResultLength; QueryValueKeyInfo.ResultLength = ResultLength;
@ -363,7 +413,7 @@ NtQueryValueKey(IN HANDLE KeyHandle,
{ {
/* Call the internal API */ /* Call the internal API */
Status = CmQueryValueKey(KeyObject->KeyControlBlock, Status = CmQueryValueKey(KeyObject->KeyControlBlock,
*ValueName, ValueNameCopy,
KeyValueInformationClass, KeyValueInformationClass,
KeyValueInformation, KeyValueInformation,
Length, Length,
@ -374,8 +424,6 @@ NtQueryValueKey(IN HANDLE KeyHandle,
CmiCallRegisteredCallbacks(RegNtPostQueryValueKey, &PostOperationInfo); CmiCallRegisteredCallbacks(RegNtPostQueryValueKey, &PostOperationInfo);
} }
DPRINT("NtQueryValueKey() returning 0x%08X\n", Status);
/* Dereference and return status */ /* Dereference and return status */
ObDereferenceObject(KeyObject); ObDereferenceObject(KeyObject);
return Status; return Status;
@ -394,8 +442,8 @@ NtSetValueKey(IN HANDLE KeyHandle,
PCM_KEY_BODY KeyObject; PCM_KEY_BODY KeyObject;
REG_SET_VALUE_KEY_INFORMATION SetValueKeyInfo; REG_SET_VALUE_KEY_INFORMATION SetValueKeyInfo;
REG_POST_OPERATION_INFORMATION PostOperationInfo; REG_POST_OPERATION_INFORMATION PostOperationInfo;
UNICODE_STRING ValueNameCopy = *ValueName;
PAGED_CODE(); PAGED_CODE();
DPRINT("NtSetValueKey() KH 0x%x, VN '%wZ', TI %x, T %d, DS %d\n", DPRINT("NtSetValueKey() KH 0x%x, VN '%wZ', TI %x, T %d, DS %d\n",
KeyHandle, ValueName, TitleIndex, Type, DataSize); KeyHandle, ValueName, TitleIndex, Type, DataSize);
@ -404,12 +452,34 @@ NtSetValueKey(IN HANDLE KeyHandle,
KEY_SET_VALUE, KEY_SET_VALUE,
CmpKeyObjectType, CmpKeyObjectType,
ExGetPreviousMode(), ExGetPreviousMode(),
(PVOID *)&KeyObject, (PVOID*)&KeyObject,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status)) return Status;
/* Make sure the name is aligned, not too long, and the data under 4GB */
if ( (ValueNameCopy.Length > 32767) ||
((ValueNameCopy.Length & (sizeof(WCHAR) - 1))) ||
(DataSize > 0x80000000))
{ {
DPRINT1("ObReferenceObjectByHandle() failed with Status = 0x%08X\n", Status); /* Fail */
return Status; ObDereferenceObject(KeyObject);
return STATUS_INVALID_PARAMETER;
}
/* Ignore any null characters at the end */
while ((ValueNameCopy.Length) &&
!(ValueNameCopy.Buffer[ValueNameCopy.Length / sizeof(WCHAR) - 1]))
{
/* Skip it */
ValueNameCopy.Length -= sizeof(WCHAR);
}
/* Don't touch read-only keys */
if (KeyObject->KeyControlBlock->ExtFlags & CM_KCB_READ_ONLY_KEY)
{
/* Fail */
ObDereferenceObject(KeyObject);
return STATUS_ACCESS_DENIED;
} }
/* Setup callback */ /* Setup callback */
@ -427,19 +497,18 @@ NtSetValueKey(IN HANDLE KeyHandle,
{ {
/* Call the internal API */ /* Call the internal API */
Status = CmSetValueKey(KeyObject->KeyControlBlock, Status = CmSetValueKey(KeyObject->KeyControlBlock,
ValueName, &ValueNameCopy,
Type, Type,
Data, Data,
DataSize); DataSize);
} }
/* Do the post-callback and de-reference the key object */ /* Do the post-callback */
PostOperationInfo.Status = Status; PostOperationInfo.Status = Status;
CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo); CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo);
ObDereferenceObject(KeyObject);
/* Synchronize the hives and return */ /* Dereference and return status */
CmpLazyFlush(); ObDereferenceObject(KeyObject);
return Status; return Status;
} }
@ -453,6 +522,7 @@ NtDeleteValueKey(IN HANDLE KeyHandle,
REG_DELETE_VALUE_KEY_INFORMATION DeleteValueKeyInfo; REG_DELETE_VALUE_KEY_INFORMATION DeleteValueKeyInfo;
REG_POST_OPERATION_INFORMATION PostOperationInfo; REG_POST_OPERATION_INFORMATION PostOperationInfo;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
UNICODE_STRING ValueNameCopy = *ValueName;
PAGED_CODE(); PAGED_CODE();
/* Verify that the handle is valid and is a registry key */ /* Verify that the handle is valid and is a registry key */
@ -462,10 +532,22 @@ NtDeleteValueKey(IN HANDLE KeyHandle,
PreviousMode, PreviousMode,
(PVOID *)&KeyObject, (PVOID *)&KeyObject,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status)) return Status;
/* Don't touch read-only keys */
if (KeyObject->KeyControlBlock->ExtFlags & CM_KCB_READ_ONLY_KEY)
{ {
DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n"); /* Fail */
return Status; ObDereferenceObject(KeyObject);
return STATUS_ACCESS_DENIED;
}
/* Make sure the name is aligned properly */
if ((ValueNameCopy.Length & (sizeof(WCHAR) - 1)))
{
/* It isn't, so we'll fail */
ObDereferenceObject(KeyObject);
return STATUS_INVALID_PARAMETER;
} }
/* Do the callback */ /* Do the callback */
@ -476,7 +558,7 @@ NtDeleteValueKey(IN HANDLE KeyHandle,
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
/* Call the internal API */ /* Call the internal API */
Status = CmDeleteValueKey(KeyObject->KeyControlBlock, *ValueName); Status = CmDeleteValueKey(KeyObject->KeyControlBlock, ValueNameCopy);
/* Do the post callback */ /* Do the post callback */
PostOperationInfo.Object = (PVOID)KeyObject; PostOperationInfo.Object = (PVOID)KeyObject;
@ -485,9 +567,8 @@ NtDeleteValueKey(IN HANDLE KeyHandle,
&PostOperationInfo); &PostOperationInfo);
} }
/* Dereference the key body and synchronize the hives */ /* Dereference the key body */
ObDereferenceObject(KeyObject); ObDereferenceObject(KeyObject);
CmpLazyFlush();
return Status; return Status;
} }
@ -509,8 +590,10 @@ NtFlushKey(IN HANDLE KeyHandle)
if (!NT_SUCCESS(Status)) return Status; if (!NT_SUCCESS(Status)) return Status;
/* Lock the registry */ /* Lock the registry */
KeEnterCriticalRegion(); CmpLockRegistry();
ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE);
/* Lock the KCB */
CmpAcquireKcbLockShared(KeyObject->KeyControlBlock);
/* Make sure KCB isn't deleted */ /* Make sure KCB isn't deleted */
if (KeyObject->KeyControlBlock->Delete) if (KeyObject->KeyControlBlock->Delete)
@ -524,9 +607,9 @@ NtFlushKey(IN HANDLE KeyHandle)
Status = CmFlushKey(KeyObject->KeyControlBlock, FALSE); Status = CmFlushKey(KeyObject->KeyControlBlock, FALSE);
} }
/* Release the lock */ /* Release the locks */
ExReleaseResourceLite(&CmpRegistryLock); CmpReleaseKcbLock(KeyObject->KeyControlBlock);
KeLeaveCriticalRegion(); CmpUnlockRegistry();
/* Dereference the object and return status */ /* Dereference the object and return status */
ObDereferenceObject(KeyObject); ObDereferenceObject(KeyObject);

View file

@ -53,7 +53,7 @@
#define CM_KCB_KEY_NON_EXIST 0x10 #define CM_KCB_KEY_NON_EXIST 0x10
#define CM_KCB_NO_DELAY_CLOSE 0x20 #define CM_KCB_NO_DELAY_CLOSE 0x20
#define CM_KCB_INVALID_CACHED_INFO 0x40 #define CM_KCB_INVALID_CACHED_INFO 0x40
#define CM_KEY_READ_ONLY_KEY 0x80 #define CM_KCB_READ_ONLY_KEY 0x80
// //
// CM_KEY_VALUE Types // CM_KEY_VALUE Types
@ -577,6 +577,16 @@ CmpGetValueKeyFromCache(
OUT PHCELL_INDEX CellToRelease OUT PHCELL_INDEX CellToRelease
); );
VALUE_SEARCH_RETURN_TYPE
NTAPI
CmpCompareNewValueDataAgainstKCBCache(
IN PCM_KEY_CONTROL_BLOCK Kcb,
IN PUNICODE_STRING ValueName,
IN ULONG Type,
IN PVOID Data,
IN ULONG DataSize
);
// //
// Registry Validation Functions // Registry Validation Functions
// //
@ -858,6 +868,12 @@ CmpRemoveKeyControlBlock(
IN PCM_KEY_CONTROL_BLOCK Kcb IN PCM_KEY_CONTROL_BLOCK Kcb
); );
VOID
NTAPI
CmpCleanUpKcbValueCache(
IN PCM_KEY_CONTROL_BLOCK Kcb
);
VOID VOID
NTAPI NTAPI
CmpCleanUpKcbCacheWithLock( CmpCleanUpKcbCacheWithLock(
@ -865,6 +881,12 @@ CmpCleanUpKcbCacheWithLock(
IN BOOLEAN LockHeldExclusively IN BOOLEAN LockHeldExclusively
); );
VOID
NTAPI
CmpCleanUpSubKeyInfo(
IN PCM_KEY_CONTROL_BLOCK Kcb
);
VOID VOID
NTAPI NTAPI
CmpDereferenceKeyControlBlockWithLock( CmpDereferenceKeyControlBlockWithLock(
@ -1324,7 +1346,7 @@ CmEnumerateKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
NTSTATUS NTSTATUS
NTAPI NTAPI
CmDeleteKey( CmDeleteKey(
IN PCM_KEY_CONTROL_BLOCK Kcb IN PCM_KEY_BODY KeyBody
); );
NTSTATUS NTSTATUS