ReactOS 0.4.15-dev-7659-ga55345b
cmkcbncb.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for cmkcbncb.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

VOID NTAPI CmpInitializeCache (VOID)
 
VOID NTAPI CmpRemoveKeyHash (IN PCM_KEY_HASH KeyHash)
 
PCM_KEY_CONTROL_BLOCK NTAPI CmpInsertKeyHash (IN PCM_KEY_HASH KeyHash, IN BOOLEAN IsFake)
 
PCM_NAME_CONTROL_BLOCK NTAPI CmpGetNameControlBlock (IN PUNICODE_STRING NodeName)
 
VOID NTAPI CmpRemoveKeyControlBlock (IN PCM_KEY_CONTROL_BLOCK Kcb)
 
VOID NTAPI CmpDereferenceNameControlBlockWithLock (IN PCM_NAME_CONTROL_BLOCK Ncb)
 
BOOLEAN NTAPI CmpReferenceKeyControlBlock (IN PCM_KEY_CONTROL_BLOCK Kcb)
 
VOID NTAPI CmpCleanUpKcbValueCache (IN PCM_KEY_CONTROL_BLOCK Kcb)
 
VOID NTAPI CmpCleanUpKcbCacheWithLock (IN PCM_KEY_CONTROL_BLOCK Kcb, IN BOOLEAN LockHeldExclusively)
 
VOID NTAPI CmpCleanUpSubKeyInfo (IN PCM_KEY_CONTROL_BLOCK Kcb)
 
VOID NTAPI CmpDereferenceKeyControlBlock (IN PCM_KEY_CONTROL_BLOCK Kcb)
 
VOID NTAPI CmpDereferenceKeyControlBlockWithLock (IN PCM_KEY_CONTROL_BLOCK Kcb, IN BOOLEAN LockHeldExclusively)
 
VOID NTAPI InitializeKCBKeyBodyList (IN PCM_KEY_CONTROL_BLOCK Kcb)
 
PCM_KEY_CONTROL_BLOCK NTAPI CmpCreateKeyControlBlock (IN PHHIVE Hive, IN HCELL_INDEX Index, IN PCM_KEY_NODE Node, IN PCM_KEY_CONTROL_BLOCK Parent, IN ULONG Flags, IN PUNICODE_STRING KeyName)
 
PUNICODE_STRING NTAPI CmpConstructName (IN PCM_KEY_CONTROL_BLOCK Kcb)
 
VOID NTAPI EnlistKeyBodyWithKCB (IN PCM_KEY_BODY KeyBody, IN ULONG Flags)
 
VOID NTAPI DelistKeyBodyFromKCB (IN PCM_KEY_BODY KeyBody, IN BOOLEAN LockHeld)
 
VOID CmpUnLockKcbArray (_In_ PULONG KcbArray)
 Unlocks a number of KCBs provided by a KCB array.
 
static VOID CmpLockKcbArray (_In_ PULONG KcbArray, _In_ ULONG KcbLockFlags)
 Locks a given number of KCBs.
 
static VOID CmpSortKcbArray (_Inout_ PULONG KcbArray)
 Sorts an array of KCB hashes in ascending order and removes any key indices that are duplicates. The purpose of sorting the KCB elements is to ensure consistent and proper locking order, so that we can prevent a deadlock.
 
PULONG NTAPI CmpBuildAndLockKcbArray (_In_ PCM_HASH_CACHE_STACK HashCacheStack, _In_ ULONG KcbLockFlags, _In_ PCM_KEY_CONTROL_BLOCK Kcb, _Inout_ PULONG OuterStackArray, _In_ ULONG TotalRemainingSubkeys, _In_ ULONG MatchRemainSubkeyLevel)
 Builds an array of KCBs and locks them. Whether these KCBs are locked exclusively or in shared mode by the calling thread, is specified by the KcbLockFlags parameter. The array is sorted.
 
VOID NTAPI CmpFlushNotifiesOnKeyBodyList (IN PCM_KEY_CONTROL_BLOCK Kcb, IN BOOLEAN LockHeld)
 

Variables

ULONG CmpHashTableSize = 2048
 
PCM_KEY_HASH_TABLE_ENTRY CmpCacheTable
 
PCM_NAME_HASH_TABLE_ENTRY CmpNameCacheTable
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file cmkcbncb.c.

Function Documentation

◆ CmpBuildAndLockKcbArray()

PULONG NTAPI CmpBuildAndLockKcbArray ( _In_ PCM_HASH_CACHE_STACK  HashCacheStack,
_In_ ULONG  KcbLockFlags,
_In_ PCM_KEY_CONTROL_BLOCK  Kcb,
_Inout_ PULONG  OuterStackArray,
_In_ ULONG  TotalRemainingSubkeys,
_In_ ULONG  MatchRemainSubkeyLevel 
)

Builds an array of KCBs and locks them. Whether these KCBs are locked exclusively or in shared mode by the calling thread, is specified by the KcbLockFlags parameter. The array is sorted.

Parameters
[in]HashCacheStackA pointer to a hash cache stack. This stack parameter stores the convkey hashes of interested KCBs of a key path name that need to be locked.
[in]KcbLockFlagsDefine a lock flag to lock the KCBs. Consult the CmpLockKcbArray documentation for more information.
[in]KcbA pointer to a key control block to be given. This KCB is included in the array for locking, that is, given by the CmpParseKey from the parser object.
[in,out]OuterStackArrayA pointer to an array that lives on the caller's stack. It acts like an auxiliary array used by the function to store the KCB elements for locking. The expected size of the array is up to 32 elements, which is the imposed limit by CMP_HASH_STACK_LIMIT. This limit also corresponds to the maximum depth of subkey levels.
[in]TotalRemainingSubkeysThe number of total remaining subkey levels.
[in]MatchRemainSubkeyLevelThe number of remaining subkey levels that match.
Returns
Returns a pointer to an array of KCBs that have been locked.
Remarks
The caller HAS THE RESPONSIBILITY to unlock the KCBs after the necessary operations are done!

Definition at line 1302 of file cmkcbncb.c.

1309{
1310 ULONG KcbIndex = 1, HashStackIndex, TotalRemaining;
1311 PULONG LockedKcbs = NULL;
1312 PCM_KEY_CONTROL_BLOCK ParentKcb = Kcb->ParentKcb;;
1313
1314 /* These parameters are expected */
1315 ASSERT(HashCacheStack != NULL);
1316 ASSERT(Kcb != NULL);
1317 ASSERT(OuterStackArray != NULL);
1318
1319 /*
1320 * Ensure when we build an array of KCBs to lock, that
1321 * we don't go beyond the boundary the limit allows us
1322 * to. 1 is the current KCB we would want to lock
1323 * alongside with the remaining key levels in the formula.
1324 */
1325 TotalRemaining = (1 + TotalRemainingSubkeys) - MatchRemainSubkeyLevel;
1326 ASSERT(TotalRemaining <= CMP_KCBS_IN_ARRAY_LIMIT);
1327
1328 /* Count the parent if we have one */
1329 if (ParentKcb)
1330 {
1331 /* Ensure we are still below the limit and add the parent to KCBs to lock */
1332 if (TotalRemainingSubkeys == MatchRemainSubkeyLevel)
1333 {
1334 TotalRemaining++;
1335 ASSERT(TotalRemaining <= CMP_KCBS_IN_ARRAY_LIMIT);
1336 OuterStackArray[KcbIndex++] = GET_HASH_INDEX(ParentKcb->ConvKey);
1337 }
1338 }
1339
1340 /* Add the current KCB */
1341 OuterStackArray[KcbIndex++] = GET_HASH_INDEX(Kcb->ConvKey);
1342
1343 /* Loop over the hash stack and grab the hashes for locking (they will be converted to indices) */
1344 for (HashStackIndex = 0;
1345 HashStackIndex < TotalRemainingSubkeys;
1346 HashStackIndex++)
1347 {
1348 OuterStackArray[KcbIndex++] = GET_HASH_INDEX(HashCacheStack[HashStackIndex].ConvKey);
1349 }
1350
1351 /*
1352 * Store how many KCBs we need to lock and sort the array.
1353 * Remove any duplicated indices from the array if any.
1354 */
1355 OuterStackArray[0] = KcbIndex - 1;
1356 CmpSortKcbArray(OuterStackArray);
1357
1358 /* Lock them */
1359 CmpLockKcbArray(OuterStackArray, KcbLockFlags);
1360
1361 /* Give the locked KCBs to caller now */
1362 LockedKcbs = OuterStackArray;
1363 return LockedKcbs;
1364}
#define CMP_KCBS_IN_ARRAY_LIMIT
Definition: cm.h:132
#define GET_HASH_INDEX(ConvKey)
Definition: cm_x.h:24
static VOID CmpSortKcbArray(_Inout_ PULONG KcbArray)
Sorts an array of KCB hashes in ascending order and removes any key indices that are duplicates....
Definition: cmkcbncb.c:1211
static VOID CmpLockKcbArray(_In_ PULONG KcbArray, _In_ ULONG KcbLockFlags)
Locks a given number of KCBs.
Definition: cmkcbncb.c:1177
#define NULL
Definition: types.h:112
#define ASSERT(a)
Definition: mode.c:44
struct _CM_KEY_CONTROL_BLOCK * ParentKcb
Definition: cm.h:289
uint32_t * PULONG
Definition: typedefs.h:59
uint32_t ULONG
Definition: typedefs.h:59

Referenced by CmpBuildHashStackAndLookupCache(), and CmpLookInCache().

◆ CmpCleanUpKcbCacheWithLock()

VOID NTAPI CmpCleanUpKcbCacheWithLock ( IN PCM_KEY_CONTROL_BLOCK  Kcb,
IN BOOLEAN  LockHeldExclusively 
)

Definition at line 476 of file cmkcbncb.c.

478{
480 PAGED_CODE();
481
482 /* Sanity checks */
484 ASSERT(Kcb->RefCount == 0);
485
486 /* Cleanup the value cache */
488
489 /* Dereference the NCB */
491
492 /* Check if we have an index hint block and free it */
493 if (Kcb->ExtFlags & CM_KCB_SUBKEY_HINT) CmpFree(Kcb->IndexHint, 0);
494
495 /* Check if we were already deleted */
496 Parent = Kcb->ParentKcb;
497 if (!Kcb->Delete) CmpRemoveKeyControlBlock(Kcb);
498
499 /* Set invalid KCB signature */
500 Kcb->Signature = CM_KCB_INVALID_SIGNATURE;
501
502 /* Free the KCB as well */
504
505 /* Check if we have a parent */
506 if (Parent)
507 {
508 /* Dereference the parent */
509 LockHeldExclusively ?
510 CmpDereferenceKeyControlBlockWithLock(Parent,LockHeldExclusively) :
512 }
513}
#define PAGED_CODE()
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn UINT32 *TableIdx UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 ACPI_BUFFER *RetPathPtr ACPI_OBJECT_HANDLER void *Data ACPI_OBJECT_HANDLER void **Data ACPI_STRING ACPI_OBJECT_LIST ACPI_BUFFER *ReturnObjectBuffer ACPI_DEVICE_INFO **ReturnBuffer ACPI_HANDLE Parent
Definition: acpixf.h:732
VOID NTAPI CmpFree(_In_ PVOID Ptr, _In_ ULONG Quota)
Definition: bootreg.c:105
#define CM_KCB_SUBKEY_HINT
Definition: cm.h:54
#define CM_KCB_INVALID_SIGNATURE
Definition: cm.h:47
#define CMP_ASSERT_KCB_LOCK(k)
Definition: cm_x.h:261
VOID NTAPI CmpFreeKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmalloc.c:53
VOID NTAPI CmpDelayDerefKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmdelay.c:286
VOID NTAPI CmpCleanUpKcbValueCache(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmkcbncb.c:431
VOID NTAPI CmpDereferenceKeyControlBlockWithLock(IN PCM_KEY_CONTROL_BLOCK Kcb, IN BOOLEAN LockHeldExclusively)
Definition: cmkcbncb.c:606
VOID NTAPI CmpDereferenceNameControlBlockWithLock(IN PCM_NAME_CONTROL_BLOCK Ncb)
Definition: cmkcbncb.c:317
VOID NTAPI CmpRemoveKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmkcbncb.c:306

Referenced by _Function_class_(), CmpAddToDelayedClose(), CmpDereferenceKeyControlBlockWithLock(), CmpEnumerateOpenSubKeys(), and CmpLookInCache().

◆ CmpCleanUpKcbValueCache()

VOID NTAPI CmpCleanUpKcbValueCache ( IN PCM_KEY_CONTROL_BLOCK  Kcb)

Definition at line 431 of file cmkcbncb.c.

432{
433 PULONG_PTR CachedList;
434 ULONG i;
435
436 /* Make sure we have the exclusive lock */
438
439 /* Check if the value list is cached */
440 if (CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList))
441 {
442 /* Get the cache list */
443 CachedList = (PULONG_PTR)CMP_GET_CACHED_DATA(Kcb->ValueCache.ValueList);
444 for (i = 0; i < Kcb->ValueCache.Count; i++)
445 {
446 /* Check if this cell is cached */
447 if (CMP_IS_CELL_CACHED(CachedList[i]))
448 {
449 /* Free it */
450 CmpFree((PVOID)CMP_GET_CACHED_CELL(CachedList[i]), 0);
451 }
452 }
453
454 /* Now free the list */
455 CmpFree((PVOID)CMP_GET_CACHED_CELL(Kcb->ValueCache.ValueList), 0);
456 Kcb->ValueCache.ValueList = HCELL_NIL;
457 }
458 else if (Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND)
459 {
460 /* This is a sym link, check if there's only one reference left */
461 if ((Kcb->ValueCache.RealKcb->RefCount == 1) &&
462 !(Kcb->ValueCache.RealKcb->Delete))
463 {
464 /* Disable delay close for the KCB */
465 Kcb->ValueCache.RealKcb->ExtFlags |= CM_KCB_NO_DELAY_CLOSE;
466 }
467
468 /* Dereference the KCB */
469 CmpDelayDerefKeyControlBlock(Kcb->ValueCache.RealKcb);
470 Kcb->ExtFlags &= ~CM_KCB_SYM_LINK_FOUND;
471 }
472}
#define CM_KCB_NO_DELAY_CLOSE
Definition: cm.h:57
#define CM_KCB_SYM_LINK_FOUND
Definition: cm.h:55
#define CMP_GET_CACHED_DATA(c)
Definition: cm_x.h:42
#define CMP_GET_CACHED_CELL(c)
Definition: cm_x.h:40
#define CMP_IS_CELL_CACHED(c)
Definition: cm_x.h:34
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define HCELL_NIL
Definition: hivedata.h:110
uint32_t * PULONG_PTR
Definition: typedefs.h:65

Referenced by CmDeleteValueKey(), CmpCleanUpKcbCacheWithLock(), CmpCompareNewValueDataAgainstKCBCache(), CmpDoOpen(), and CmSetValueKey().

◆ CmpCleanUpSubKeyInfo()

VOID NTAPI CmpCleanUpSubKeyInfo ( IN PCM_KEY_CONTROL_BLOCK  Kcb)

Definition at line 517 of file cmkcbncb.c.

518{
519 PCM_KEY_NODE KeyNode;
520
521 /* Make sure we have the exclusive lock */
523
524 /* Check if there's any cached subkey */
525 if (Kcb->ExtFlags & (CM_KCB_NO_SUBKEY | CM_KCB_SUBKEY_ONE | CM_KCB_SUBKEY_HINT))
526 {
527 /* Check if there's a hint */
528 if (Kcb->ExtFlags & (CM_KCB_SUBKEY_HINT))
529 {
530 /* Kill it */
531 CmpFree(Kcb->IndexHint, 0);
532 }
533
534 /* Remove subkey flags */
536 }
537
538 /* Check if there's no linked cell */
539 if (Kcb->KeyCell == HCELL_NIL)
540 {
541 /* Make sure it's a delete */
542 ASSERT(Kcb->Delete);
543 KeyNode = NULL;
544 }
545 else
546 {
547 /* Get the key node */
548 KeyNode = (PCM_KEY_NODE)HvGetCell(Kcb->KeyHive, Kcb->KeyCell);
549 }
550
551 /* Check if we got the node */
552 if (!KeyNode)
553 {
554 /* We didn't, mark the cached data invalid */
555 Kcb->ExtFlags |= CM_KCB_INVALID_CACHED_INFO;
556 }
557 else
558 {
559 /* We have a keynode, update subkey counts */
560 Kcb->ExtFlags &= ~CM_KCB_INVALID_CACHED_INFO;
561 Kcb->SubKeyCount = KeyNode->SubKeyCounts[Stable] +
562 KeyNode->SubKeyCounts[Volatile];
563
564 /* Release the cell */
565 HvReleaseCell(Kcb->KeyHive, Kcb->KeyCell);
566 }
567}
#define CM_KCB_SUBKEY_ONE
Definition: cm.h:53
#define CM_KCB_INVALID_CACHED_INFO
Definition: cm.h:58
#define CM_KCB_NO_SUBKEY
Definition: cm.h:52
struct _CM_KEY_NODE * PCM_KEY_NODE
#define HvReleaseCell(Hive, Cell)
Definition: cmlib.h:455
#define HvGetCell(Hive, Cell)
Definition: cmlib.h:452
@ Volatile
Definition: hivedata.h:128
@ Stable
Definition: hivedata.h:127
ULONG SubKeyCounts[HTYPE_COUNT]
Definition: cmdata.h:97

Referenced by CmDeleteKey(), CmpCreateLinkNode(), CmpDoCreate(), CmpEnumerateOpenSubKeys(), and CmUnloadKey().

◆ CmpConstructName()

PUNICODE_STRING NTAPI CmpConstructName ( IN PCM_KEY_CONTROL_BLOCK  Kcb)

Definition at line 897 of file cmkcbncb.c.

898{
900 ULONG i;
901 USHORT NameLength;
903 PCM_KEY_NODE KeyNode;
904 BOOLEAN DeletedKey = FALSE;
905 PWCHAR TargetBuffer, CurrentNameW;
906 PUCHAR CurrentName;
907
908 /* Calculate how much size our key name is going to occupy */
909 NameLength = 0;
910 MyKcb = Kcb;
911
912 while (MyKcb)
913 {
914 /* Add length of the name */
915 if (!MyKcb->NameBlock->Compressed)
916 {
917 NameLength += MyKcb->NameBlock->NameLength;
918 }
919 else
920 {
921 NameLength += CmpCompressedNameSize(MyKcb->NameBlock->Name,
922 MyKcb->NameBlock->NameLength);
923 }
924
925 /* Sum up the separator too */
926 NameLength += sizeof(WCHAR);
927
928 /* Go to the parent KCB */
929 MyKcb = MyKcb->ParentKcb;
930 }
931
932 /* Allocate the unicode string now */
933 KeyName = CmpAllocate(NameLength + sizeof(UNICODE_STRING),
934 TRUE,
935 TAG_CM);
936
937 if (!KeyName) return NULL;
938
939 /* Set it up */
940 KeyName->Buffer = (PWSTR)(KeyName + 1);
941 KeyName->Length = NameLength;
942 KeyName->MaximumLength = NameLength;
943
944 /* Loop the keys again, now adding names */
945 NameLength = 0;
946 MyKcb = Kcb;
947
948 while (MyKcb)
949 {
950 /* Sanity checks for deleted and fake keys */
951 if ((!MyKcb->KeyCell && !MyKcb->Delete) ||
952 !MyKcb->KeyHive ||
954 {
955 /* Failure */
956 CmpFree(KeyName, 0);
957 return NULL;
958 }
959
960 /* Try to get the name from the keynode,
961 if the key is not deleted */
962 if (!DeletedKey && !MyKcb->Delete)
963 {
964 KeyNode = (PCM_KEY_NODE)HvGetCell(MyKcb->KeyHive, MyKcb->KeyCell);
965 if (!KeyNode)
966 {
967 /* Failure */
968 CmpFree(KeyName, 0);
969 return NULL;
970 }
971 }
972 else
973 {
974 /* The key was deleted */
975 KeyNode = NULL;
976 DeletedKey = TRUE;
977 }
978
979 /* Get the pointer to the beginning of the current key name */
980 NameLength += (MyKcb->NameBlock->NameLength + 1) * sizeof(WCHAR);
981 TargetBuffer = &KeyName->Buffer[(KeyName->Length - NameLength) / sizeof(WCHAR)];
982
983 /* Add a separator */
984 TargetBuffer[0] = OBJ_NAME_PATH_SEPARATOR;
985
986 /* Add the name, but remember to go from the end to the beginning */
987 if (!MyKcb->NameBlock->Compressed)
988 {
989 /* Get the pointer to the name (from the keynode, if possible) */
990 if ((MyKcb->Flags & (KEY_HIVE_ENTRY | KEY_HIVE_EXIT)) ||
991 !KeyNode)
992 {
993 CurrentNameW = MyKcb->NameBlock->Name;
994 }
995 else
996 {
997 CurrentNameW = KeyNode->Name;
998 }
999
1000 /* Copy the name */
1001 for (i=0; i < MyKcb->NameBlock->NameLength; i++)
1002 {
1003 TargetBuffer[i+1] = *CurrentNameW;
1004 CurrentNameW++;
1005 }
1006 }
1007 else
1008 {
1009 /* Get the pointer to the name (from the keynode, if possible) */
1010 if ((MyKcb->Flags & (KEY_HIVE_ENTRY | KEY_HIVE_EXIT)) ||
1011 !KeyNode)
1012 {
1013 CurrentName = (PUCHAR)MyKcb->NameBlock->Name;
1014 }
1015 else
1016 {
1017 CurrentName = (PUCHAR)KeyNode->Name;
1018 }
1019
1020 /* Copy the name */
1021 for (i=0; i < MyKcb->NameBlock->NameLength; i++)
1022 {
1023 TargetBuffer[i+1] = (WCHAR)*CurrentName;
1024 CurrentName++;
1025 }
1026 }
1027
1028 /* Release the cell, if needed */
1029 if (KeyNode) HvReleaseCell(MyKcb->KeyHive, MyKcb->KeyCell);
1030
1031 /* Go to the parent KCB */
1032 MyKcb = MyKcb->ParentKcb;
1033 }
1034
1035 /* Return resulting buffer (both UNICODE_STRING and
1036 its buffer following it) */
1037 return KeyName;
1038}
unsigned char BOOLEAN
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
PVOID NTAPI CmpAllocate(_In_ SIZE_T Size, _In_ BOOLEAN Paged, _In_ ULONG Tag)
Definition: bootreg.c:90
#define CM_KCB_KEY_NON_EXIST
Definition: cm.h:56
#define KEY_HIVE_EXIT
Definition: cmdata.h:31
#define KEY_HIVE_ENTRY
Definition: cmdata.h:32
USHORT NTAPI CmpCompressedNameSize(IN PWCHAR Name, IN ULONG Length)
Definition: cmname.c:95
#define TAG_CM
Definition: cmlib.h:212
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
unsigned short USHORT
Definition: pedump.c:61
PCM_NAME_CONTROL_BLOCK NameBlock
Definition: cm.h:290
PHHIVE KeyHive
Definition: cm.h:285
ULONG ExtFlags
Definition: cm.h:272
HCELL_INDEX KeyCell
Definition: cm.h:286
WCHAR Name[ANYSIZE_ARRAY]
Definition: cmdata.h:116
BOOLEAN Compressed
Definition: cm.h:248
USHORT NameLength
Definition: cm.h:257
WCHAR Name[ANYSIZE_ARRAY]
Definition: cm.h:258
uint16_t * PWSTR
Definition: typedefs.h:56
uint16_t * PWCHAR
Definition: typedefs.h:56
unsigned char * PUCHAR
Definition: typedefs.h:53
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2699
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by CmpQueryKeyName().

◆ CmpCreateKeyControlBlock()

PCM_KEY_CONTROL_BLOCK NTAPI CmpCreateKeyControlBlock ( IN PHHIVE  Hive,
IN HCELL_INDEX  Index,
IN PCM_KEY_NODE  Node,
IN PCM_KEY_CONTROL_BLOCK  Parent,
IN ULONG  Flags,
IN PUNICODE_STRING  KeyName 
)

Definition at line 655 of file cmkcbncb.c.

661{
662 PCM_KEY_CONTROL_BLOCK Kcb, FoundKcb = NULL;
663 UNICODE_STRING NodeName;
664 ULONG ConvKey = 0, i;
665 BOOLEAN IsFake, HashLock;
666 PWCHAR p;
667
668 /* Make sure we own this hive in case it's being unloaded */
669 if ((Hive->HiveFlags & HIVE_IS_UNLOADING) &&
670 (((PCMHIVE)Hive)->CreatorOwner != KeGetCurrentThread()))
671 {
672 /* Fail */
673 return NULL;
674 }
675
676 /* Check if this is a fake KCB */
677 IsFake = Flags & CMP_CREATE_FAKE_KCB ? TRUE : FALSE;
678
679 /* If we have a parent, use its ConvKey */
680 if (Parent) ConvKey = Parent->ConvKey;
681
682 /* Make a copy of the name */
683 NodeName = *KeyName;
684
685 /* Remove leading slash */
686 while (NodeName.Length && (*NodeName.Buffer == OBJ_NAME_PATH_SEPARATOR))
687 {
688 /* Move the buffer by one */
689 NodeName.Buffer++;
690 NodeName.Length -= sizeof(WCHAR);
691 }
692
693 /* Make sure we didn't get just a slash or something */
694 ASSERT(NodeName.Length > 0);
695
696 /* Now setup the hash */
697 p = NodeName.Buffer;
698 for (i = 0; i < NodeName.Length; i += sizeof(WCHAR))
699 {
700 /* Make sure it's a valid character */
702 {
703 /* Add this key to the hash */
704 ConvKey = COMPUTE_HASH_CHAR(ConvKey, *p);
705 }
706
707 /* Move on */
708 p++;
709 }
710
711 /* Allocate the KCB */
713 if (!Kcb) return NULL;
714
715 /* Initailize the key list */
717
718 /* Set it up */
720 Kcb->Delete = FALSE;
721 Kcb->RefCount = 1;
722 Kcb->KeyHive = Hive;
723 Kcb->KeyCell = Index;
724 Kcb->ConvKey = ConvKey;
726 Kcb->InDelayClose = 0;
727 ASSERT_KCB_VALID(Kcb);
728
729 /* Check if we have two hash entires */
730 HashLock = Flags & CMP_LOCK_HASHES_FOR_KCB ? TRUE : FALSE;
731 if (!HashLock)
732 {
733 /* It's not locked, do we have a parent? */
734 if (Parent)
735 {
736 /* Lock the parent KCB and ourselves */
738 }
739 else
740 {
741 /* Lock only ourselves */
743 }
744 }
745
746 /* Check if we already have a KCB */
747 FoundKcb = CmpInsertKeyHash(&Kcb->KeyHash, IsFake);
748 if (FoundKcb)
749 {
750 /* Sanity check */
751 ASSERT(!FoundKcb->Delete);
753
754 /* Free the one we allocated and reference this one */
756 ASSERT_KCB_VALID(FoundKcb);
757 Kcb = FoundKcb;
759 {
760 /* We got too many handles */
761 ASSERT(Kcb->RefCount + 1 != 0);
762 Kcb = NULL;
763 }
764 else
765 {
766 /* Check if we're not creating a fake one, but it used to be fake */
767 if ((Kcb->ExtFlags & CM_KCB_KEY_NON_EXIST) && !IsFake)
768 {
769 /* Set the hive and cell */
770 Kcb->KeyHive = Hive;
771 Kcb->KeyCell = Index;
772
773 /* This means that our current information is invalid */
775 }
776
777 /* Check if we didn't have any valid data */
778 if (!(Kcb->ExtFlags & (CM_KCB_NO_SUBKEY |
781 {
782 /* Calculate the index hint */
783 Kcb->SubKeyCount = Node->SubKeyCounts[Stable] +
784 Node->SubKeyCounts[Volatile];
785
786 /* Cached information is now valid */
787 Kcb->ExtFlags &= ~CM_KCB_INVALID_CACHED_INFO;
788 }
789
790 /* Setup the other data */
791 Kcb->KcbLastWriteTime = Node->LastWriteTime;
792 Kcb->KcbMaxNameLen = (USHORT)Node->MaxNameLen;
793 Kcb->KcbMaxValueNameLen = (USHORT)Node->MaxValueNameLen;
794 Kcb->KcbMaxValueDataLen = Node->MaxValueDataLen;
795 }
796 }
797 else
798 {
799 /* No KCB, do we have a parent? */
800 if (Parent)
801 {
802 /* Reference the parent */
803 if (((Parent->TotalLevels + 1) < 512) &&
805 {
806 /* Link it */
807 Kcb->ParentKcb = Parent;
808 Kcb->TotalLevels = Parent->TotalLevels + 1;
809 }
810 else
811 {
812 /* Remove the KCB and free it */
816 Kcb = NULL;
817 }
818 }
819 else
820 {
821 /* No parent, this is the root node */
822 Kcb->ParentKcb = NULL;
823 Kcb->TotalLevels = 1;
824 }
825
826 /* Check if we have a KCB */
827 if (Kcb)
828 {
829 /* Get the NCB */
830 Kcb->NameBlock = CmpGetNameControlBlock(&NodeName);
831 if (Kcb->NameBlock)
832 {
833 /* Fill it out */
834 Kcb->ValueCache.Count = Node->ValueList.Count;
835 Kcb->ValueCache.ValueList = Node->ValueList.List;
836 Kcb->Flags = Node->Flags;
837 Kcb->ExtFlags = 0;
839
840 /* Remember if this is a fake key */
841 if (IsFake) Kcb->ExtFlags |= CM_KCB_KEY_NON_EXIST;
842
843 /* Setup the other data */
844 Kcb->SubKeyCount = Node->SubKeyCounts[Stable] +
845 Node->SubKeyCounts[Volatile];
846 Kcb->KcbLastWriteTime = Node->LastWriteTime;
847 Kcb->KcbMaxNameLen = (USHORT)Node->MaxNameLen;
848 Kcb->KcbMaxValueNameLen = (USHORT)Node->MaxValueNameLen;
849 Kcb->KcbMaxValueDataLen = (USHORT)Node->MaxValueDataLen;
850 }
851 else
852 {
853 /* Dereference the KCB */
855
856 /* Remove the KCB and free it */
860 Kcb = NULL;
861 }
862 }
863 }
864
865 /* Check if this is a KCB inside a frozen hive */
866 if (Kcb && ((PCMHIVE)Hive)->Frozen && !(Kcb->Flags & KEY_SYM_LINK))
867 {
868 /* Don't add these to the delay close */
870 }
871
872 /* Sanity check */
873 ASSERT(!Kcb || !Kcb->Delete);
874
875 /* Check if we had locked the hashes */
876 if (!HashLock)
877 {
878 /* We locked them manually, do we have a parent? */
879 if (Parent)
880 {
881 /* Unlock the parent KCB and ourselves */
882 CmpReleaseTwoKcbLockByKey(ConvKey, Parent->ConvKey);
883 }
884 else
885 {
886 /* Unlock only ourselves */
887 CmpReleaseKcbLockByKey(ConvKey);
888 }
889 }
890
891 /* Return the KCB */
892 return Kcb;
893}
#define CMP_CREATE_FAKE_KCB
Definition: cm.h:83
#define CMP_LOCK_HASHES_FOR_KCB
Definition: cm.h:84
#define CM_KCB_SIGNATURE
Definition: cm.h:46
FORCEINLINE VOID CmpAcquireKcbLockExclusive(PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cm_x.h:116
#define ASSERT_KCB_VALID(k)
Definition: cm_x.h:82
FORCEINLINE VOID CmpReleaseKcbLockByKey(ULONG ConvKey)
Definition: cm_x.h:195
#define COMPUTE_HASH_CHAR(ConvKey, Char)
Definition: cm_x.h:18
PCM_KEY_CONTROL_BLOCK NTAPI CmpAllocateKeyControlBlock(VOID)
Definition: cmalloc.c:111
#define KEY_SYM_LINK
Definition: cmdata.h:34
ULONG CmpDelayedCloseSize
Definition: cmdelay.c:19
PCM_KEY_CONTROL_BLOCK NTAPI CmpInsertKeyHash(IN PCM_KEY_HASH KeyHash, IN BOOLEAN IsFake)
Definition: cmkcbncb.c:109
PCM_NAME_CONTROL_BLOCK NTAPI CmpGetNameControlBlock(IN PUNICODE_STRING NodeName)
Definition: cmkcbncb.c:148
BOOLEAN NTAPI CmpReferenceKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmkcbncb.c:357
VOID NTAPI InitializeKCBKeyBodyList(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmkcbncb.c:641
VOID NTAPI CmpAcquireTwoKcbLocksExclusiveByKey(IN ULONG ConvKey1, IN ULONG ConvKey2)
Definition: cmsysini.c:2076
VOID NTAPI CmpReleaseTwoKcbLockByKey(IN ULONG ConvKey1, IN ULONG ConvKey2)
Definition: cmsysini.c:2105
GLfloat GLfloat p
Definition: glext.h:8902
#define KeGetCurrentThread
Definition: hal.h:55
#define HIVE_IS_UNLOADING
Definition: hivedata.h:28
ULONG Count
Definition: cm.h:211
ULONG ValueList
Definition: cm.h:214
Definition: cmlib.h:316
ULONG TotalLevels
Definition: cm.h:276
USHORT KcbMaxValueNameLen
Definition: cm.h:308
ULONG DelayedCloseIndex
Definition: cm.h:275
ULONG KcbMaxValueDataLen
Definition: cm.h:309
CM_KEY_HASH KeyHash
Definition: cm.h:280
ULONG RefCount
Definition: cm.h:269
LARGE_INTEGER KcbLastWriteTime
Definition: cm.h:306
ULONG Signature
Definition: cm.h:268
USHORT KcbMaxNameLen
Definition: cm.h:307
ULONG InDelayClose
Definition: cm.h:317
ULONG SubKeyCount
Definition: cm.h:297
CACHED_CHILD_LIST ValueCache
Definition: cm.h:292
Definition: dlist.c:348
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170

Referenced by CmpCreateRegistryRoot(), CmpDoCreateChild(), CmpDoOpen(), and CmpParseKey().

◆ CmpDereferenceKeyControlBlock()

VOID NTAPI CmpDereferenceKeyControlBlock ( IN PCM_KEY_CONTROL_BLOCK  Kcb)

Definition at line 571 of file cmkcbncb.c.

572{
573 LONG OldRefCount, NewRefCount;
574 ULONG ConvKey;
576 "%s - Dereferencing KCB: %p\n", __FUNCTION__, Kcb);
577
578 /* Get the ref count and update it */
579 OldRefCount = *(PLONG)&Kcb->RefCount;
580 NewRefCount = OldRefCount - 1;
581
582 /* Check if we still have references */
583 if ((NewRefCount & 0xFFFF) > 0)
584 {
585 /* Do the dereference */
586 if (InterlockedCompareExchange((PLONG)&Kcb->RefCount,
587 NewRefCount,
588 OldRefCount) == OldRefCount)
589 {
590 /* We'de done */
591 return;
592 }
593 }
594
595 /* Save the key */
596 ConvKey = Kcb->ConvKey;
597
598 /* Do the dereference inside the lock */
601 CmpReleaseKcbLockByKey(ConvKey);
602}
#define CMTRACE(x, fmt,...)
Definition: cm.h:40
#define CM_REFERENCE_DEBUG
Definition: cm.h:26
#define __FUNCTION__
Definition: types.h:116
#define InterlockedCompareExchange
Definition: interlocked.h:104
if(dx< 0)
Definition: linetemp.h:194
long LONG
Definition: pedump.c:60
int32_t * PLONG
Definition: typedefs.h:58

Referenced by CmpLookInCache(), and CmpParseKey().

◆ CmpDereferenceKeyControlBlockWithLock()

VOID NTAPI CmpDereferenceKeyControlBlockWithLock ( IN PCM_KEY_CONTROL_BLOCK  Kcb,
IN BOOLEAN  LockHeldExclusively 
)

Definition at line 606 of file cmkcbncb.c.

608{
610 "%s - Dereferencing KCB: %p\n", __FUNCTION__, Kcb);
611
612 /* Sanity check */
613 ASSERT_KCB_VALID(Kcb);
614
615 /* Check if this is the last reference */
616 if ((InterlockedDecrement((PLONG)&Kcb->RefCount) & 0xFFFF) == 0)
617 {
618 /* Make sure we have the exclusive lock */
620
621 /* Check if we should do a direct delete */
622 if ((CmpHoldLazyFlush &&
623 !(Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND) &&
624 !(Kcb->Flags & KEY_SYM_LINK)) ||
625 (Kcb->ExtFlags & CM_KCB_NO_DELAY_CLOSE) ||
626 Kcb->Delete)
627 {
628 /* Clean up the KCB*/
629 CmpCleanUpKcbCacheWithLock(Kcb, LockHeldExclusively);
630 }
631 else
632 {
633 /* Otherwise, use delayed close */
634 CmpAddToDelayedClose(Kcb, LockHeldExclusively);
635 }
636 }
637}
#define InterlockedDecrement
Definition: armddk.h:52
VOID NTAPI CmpAddToDelayedClose(IN PCM_KEY_CONTROL_BLOCK Kcb, IN BOOLEAN LockHeldExclusively)
Definition: cmdelay.c:350
VOID NTAPI CmpCleanUpKcbCacheWithLock(IN PCM_KEY_CONTROL_BLOCK Kcb, IN BOOLEAN LockHeldExclusively)
Definition: cmkcbncb.c:476
BOOLEAN CmpHoldLazyFlush
Definition: cmlazy.c:23

Referenced by CmpCleanUpKcbCacheWithLock(), CmpCreateKeyControlBlock(), CmpDereferenceKeyControlBlock(), CmpDoOpen(), and CmpParseKey().

◆ CmpDereferenceNameControlBlockWithLock()

VOID NTAPI CmpDereferenceNameControlBlockWithLock ( IN PCM_NAME_CONTROL_BLOCK  Ncb)

Definition at line 317 of file cmkcbncb.c.

318{
319 PCM_NAME_HASH Current, *Next;
320 ULONG ConvKey = Ncb->ConvKey;
321
322 /* Lock the NCB */
324
325 /* Decrease the reference count */
326 ASSERT(Ncb->RefCount >= 1);
327 if (!(--Ncb->RefCount))
328 {
329 /* Find the NCB in the table */
330 Next = &GET_HASH_ENTRY(CmpNameCacheTable, Ncb->ConvKey)->Entry;
331 while (TRUE)
332 {
333 /* Check the current entry */
334 Current = *Next;
335 ASSERT(Current != NULL);
336 if (Current == &Ncb->NameHash)
337 {
338 /* Unlink it */
339 *Next = Current->NextHash;
340 break;
341 }
342
343 /* Get to the next one */
344 Next = &Current->NextHash;
345 }
346
347 /* Found it, now free it */
348 CmpFree(Ncb, 0);
349 }
350
351 /* Release the lock */
352 CmpReleaseNcbLockByKey(ConvKey);
353}
#define CmpReleaseNcbLockByKey(k)
Definition: cm_x.h:242
#define GET_HASH_ENTRY(Table, ConvKey)
Definition: cm_x.h:26
#define CmpAcquireNcbLockExclusiveByKey(k)
Definition: cm_x.h:224
PCM_NAME_HASH_TABLE_ENTRY CmpNameCacheTable
Definition: cmkcbncb.c:19
struct _CM_NAME_HASH * NextHash
Definition: cm.h:171
ULONG ConvKey
Definition: cm.h:170

Referenced by CmpCleanUpKcbCacheWithLock().

◆ CmpFlushNotifiesOnKeyBodyList()

VOID NTAPI CmpFlushNotifiesOnKeyBodyList ( IN PCM_KEY_CONTROL_BLOCK  Kcb,
IN BOOLEAN  LockHeld 
)

Definition at line 1368 of file cmkcbncb.c.

1370{
1371 PLIST_ENTRY NextEntry, ListHead;
1372 PCM_KEY_BODY KeyBody;
1373
1374 /* Sanity check */
1376 while (TRUE)
1377 {
1378 /* Is the list empty? */
1379 ListHead = &Kcb->KeyBodyListHead;
1380 if (!IsListEmpty(ListHead))
1381 {
1382 /* Loop the list */
1383 NextEntry = ListHead->Flink;
1384 while (NextEntry != ListHead)
1385 {
1386 /* Get the key body */
1387 KeyBody = CONTAINING_RECORD(NextEntry, CM_KEY_BODY, KeyBodyList);
1388 ASSERT(KeyBody->Type == CM_KEY_BODY_TYPE);
1389
1390 /* Check for notifications */
1391 if (KeyBody->NotifyBlock)
1392 {
1393 /* Is the lock held? */
1394 if (LockHeld)
1395 {
1396 /* Flush it */
1397 CmpFlushNotify(KeyBody, LockHeld);
1398 ASSERT(KeyBody->NotifyBlock == NULL);
1399 continue;
1400 }
1401
1402 /* Lock isn't held, so we need to take a reference */
1403 if (ObReferenceObjectSafe(KeyBody))
1404 {
1405 /* Now we can flush */
1406 CmpFlushNotify(KeyBody, LockHeld);
1407 ASSERT(KeyBody->NotifyBlock == NULL);
1408
1409 /* Release the reference we took */
1411 continue;
1412 }
1413 }
1414
1415 /* Try the next entry */
1416 NextEntry = NextEntry->Flink;
1417 }
1418 }
1419
1420 /* List has been parsed, exit */
1421 break;
1422 }
1423}
#define CM_KEY_BODY_TYPE
Definition: cm.h:64
#define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK()
Definition: cm_x.h:67
#define CmpIsKcbLockedExclusive(k)
Definition: cm_x.h:88
VOID NTAPI CmpFlushNotify(IN PCM_KEY_BODY KeyBody, IN BOOLEAN LockHeld)
Definition: cmnotify.c:30
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
BOOLEAN FASTCALL ObReferenceObjectSafe(IN PVOID Object)
Definition: obref.c:22
VOID NTAPI ObDereferenceObjectDeferDelete(IN PVOID Object)
Definition: obref.c:358
ULONG Type
Definition: cm.h:233
struct _CM_NOTIFY_BLOCK * NotifyBlock
Definition: cm.h:235
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260

Referenced by CmDeleteKey(), CmpEnumerateOpenSubKeys(), and CmUnloadKey().

◆ CmpGetNameControlBlock()

PCM_NAME_CONTROL_BLOCK NTAPI CmpGetNameControlBlock ( IN PUNICODE_STRING  NodeName)

Definition at line 148 of file cmkcbncb.c.

149{
151 ULONG ConvKey = 0;
152 PWCHAR p, pp;
153 ULONG i;
154 BOOLEAN IsCompressed = TRUE, Found = FALSE;
156 ULONG NcbSize;
158
159 /* Loop the name */
160 p = NodeName->Buffer;
161 for (i = 0; i < NodeName->Length; i += sizeof(WCHAR))
162 {
163 /* Make sure it's not a slash */
165 {
166 /* Add it to the hash */
167 ConvKey = COMPUTE_HASH_CHAR(ConvKey, *p);
168 }
169
170 /* Next character */
171 p++;
172 }
173
174 /* Set assumed lengh and loop to check */
175 Length = NodeName->Length / sizeof(WCHAR);
176 for (i = 0; i < (NodeName->Length / sizeof(WCHAR)); i++)
177 {
178 /* Check if this is a 16-bit character */
179 if (NodeName->Buffer[i] > (UCHAR)-1)
180 {
181 /* This is the actual size, and we know we're not compressed */
182 Length = NodeName->Length;
183 IsCompressed = FALSE;
184 break;
185 }
186 }
187
188 /* Lock the NCB entry */
190
191 /* Get the hash entry */
192 HashEntry = GET_HASH_ENTRY(CmpNameCacheTable, ConvKey)->Entry;
193 while (HashEntry)
194 {
195 /* Get the current NCB */
197
198 /* Check if the hash matches */
199 if ((ConvKey == HashEntry->ConvKey) && (Length == Ncb->NameLength))
200 {
201 /* Assume success */
202 Found = TRUE;
203
204 /* If the NCB is compressed, do a compressed name compare */
205 if (Ncb->Compressed)
206 {
207 /* Compare names */
208 if (CmpCompareCompressedName(NodeName, Ncb->Name, Length))
209 {
210 /* We failed */
211 Found = FALSE;
212 }
213 }
214 else
215 {
216 /* Do a manual compare */
217 p = NodeName->Buffer;
218 pp = Ncb->Name;
219 for (i = 0; i < Ncb->NameLength; i += sizeof(WCHAR))
220 {
221 /* Compare the character */
223 {
224 /* Failed */
225 Found = FALSE;
226 break;
227 }
228
229 /* Next chars */
230 p++;
231 pp++;
232 }
233 }
234
235 /* Check if we found a name */
236 if (Found)
237 {
238 /* Reference it */
239 ASSERT(Ncb->RefCount != 0xFFFF);
240 Ncb->RefCount++;
241 break;
242 }
243 }
244
245 /* Go to the next hash */
246 HashEntry = HashEntry->NextHash;
247 }
248
249 /* Check if we didn't find it */
250 if (!Found)
251 {
252 /* Allocate one */
254 Ncb = CmpAllocate(NcbSize, TRUE, TAG_CM);
255 if (!Ncb)
256 {
257 /* Release the lock and fail */
258 CmpReleaseNcbLockByKey(ConvKey);
259 return NULL;
260 }
261
262 /* Clear it out */
263 RtlZeroMemory(Ncb, NcbSize);
264
265 /* Check if the name was compressed */
266 if (IsCompressed)
267 {
268 /* Copy the compressed name */
269 for (i = 0; i < NodeName->Length / sizeof(WCHAR); i++)
270 {
271 /* Copy Unicode to ANSI */
272 ((PCHAR)Ncb->Name)[i] = (CHAR)RtlUpcaseUnicodeChar(NodeName->Buffer[i]);
273 }
274 }
275 else
276 {
277 /* Copy the name directly */
278 for (i = 0; i < NodeName->Length / sizeof(WCHAR); i++)
279 {
280 /* Copy each unicode character */
281 Ncb->Name[i] = RtlUpcaseUnicodeChar(NodeName->Buffer[i]);
282 }
283 }
284
285 /* Setup the rest of the NCB */
286 Ncb->Compressed = IsCompressed;
287 Ncb->ConvKey = ConvKey;
288 Ncb->RefCount++;
289 Ncb->NameLength = Length;
290
291 /* Insert the name in the hash table */
292 HashEntry = &Ncb->NameHash;
293 HashEntry->NextHash = GET_HASH_ENTRY(CmpNameCacheTable, ConvKey)->Entry;
294 GET_HASH_ENTRY(CmpNameCacheTable, ConvKey)->Entry = HashEntry;
295 }
296
297 /* Release NCB lock */
298 CmpReleaseNcbLockByKey(ConvKey);
299
300 /* Return the NCB found */
301 return Ncb;
302}
#define CHAR(Char)
return Found
Definition: dirsup.c:1270
LONG NTAPI CmpCompareCompressedName(IN PCUNICODE_STRING SearchName, IN PWCHAR CompressedName, IN ULONG NameLength)
Definition: cmname.c:109
#define PCHAR
Definition: match.c:90
WCHAR NTAPI RtlUpcaseUnicodeChar(_In_ WCHAR Source)
Definition: nlsboot.c:176
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
Definition: hash.c:61
CM_NAME_HASH NameHash
Definition: cm.h:252
USHORT RefCount
Definition: cm.h:249
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by CmpCreateKeyControlBlock().

◆ CmpInitializeCache()

VOID NTAPI CmpInitializeCache ( VOID  )

Definition at line 26 of file cmkcbncb.c.

27{
28 ULONG Length, i;
29
30 /* Calculate length for the table */
32
33 /* Allocate it */
35 if (!CmpCacheTable)
36 {
37 /* Take the system down */
38 KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 3, 1, 0, 0);
39 }
40
41 /* Zero out the table */
43
44 /* Initialize the locks */
45 for (i = 0;i < CmpHashTableSize; i++)
46 {
47 /* Setup the pushlock */
49 }
50
51 /* Calculate length for the name cache */
53
54 /* Now allocate the name cache table */
57 {
58 /* Take the system down */
59 KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 3, 3, 0, 0);
60 }
61
62 /* Zero out the table */
64
65 /* Initialize the locks */
66 for (i = 0;i < CmpHashTableSize; i++)
67 {
68 /* Setup the pushlock */
70 }
71
72 /* Setup the delayed close table */
74}
struct _CM_NAME_HASH_TABLE_ENTRY CM_NAME_HASH_TABLE_ENTRY
struct _CM_KEY_HASH_TABLE_ENTRY CM_KEY_HASH_TABLE_ENTRY
VOID NTAPI CmpInitializeDelayedCloseTable(VOID)
Definition: cmdelay.c:191
PCM_KEY_HASH_TABLE_ENTRY CmpCacheTable
Definition: cmkcbncb.c:18
ULONG CmpHashTableSize
Definition: cmkcbncb.c:17
#define ExInitializePushLock
Definition: ex.h:1013
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:108
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:127

Referenced by CmInitSystem1().

◆ CmpInsertKeyHash()

PCM_KEY_CONTROL_BLOCK NTAPI CmpInsertKeyHash ( IN PCM_KEY_HASH  KeyHash,
IN BOOLEAN  IsFake 
)

Definition at line 109 of file cmkcbncb.c.

111{
112 ULONG i;
115
116 /* Get the hash index */
117 i = GET_HASH_INDEX(KeyHash->ConvKey);
118
119 /* If this is a fake key, increase the key cell to use the parent data */
120 if (IsFake) KeyHash->KeyCell++;
121
122 /* Loop the hash table */
124 while (Entry)
125 {
126 /* Check if this matches */
128 if ((KeyHash->ConvKey == Entry->ConvKey) &&
129 (KeyHash->KeyCell == Entry->KeyCell) &&
130 (KeyHash->KeyHive == Entry->KeyHive))
131 {
132 /* Return it */
134 }
135
136 /* Keep looping */
137 Entry = Entry->NextHash;
138 }
139
140 /* No entry found, add this one and return NULL since none existed */
141 KeyHash->NextHash = CmpCacheTable[i].Entry;
143 return NULL;
144}
#define ASSERT_VALID_HASH(h)
Definition: cm_x.h:28
base of all file and directory entries
Definition: entries.h:83
PCM_KEY_HASH Entry
Definition: cm.h:162

Referenced by CmpCreateKeyControlBlock().

◆ CmpLockKcbArray()

static VOID CmpLockKcbArray ( _In_ PULONG  KcbArray,
_In_ ULONG  KcbLockFlags 
)
static

Locks a given number of KCBs.

Parameters
[in]KcbArrayA pointer to an array of KCBs to be locked. The count of KCBs to be locked is defined by the first element in the array.
[in]KcbLockFlagsDefine a lock flag to lock the KCBs.

CMP_LOCK_KCB_ARRAY_EXCLUSIVE – indicates the KCBs are locked exclusively and owned by the calling thread.

CMP_LOCK_KCB_ARRAY_SHARED – indicates the KCBs are locked in shared mode by the owning threads.

Definition at line 1177 of file cmkcbncb.c.

1180{
1181 ULONG i;
1182
1183 /* Lock the KCBs */
1184 for (i = 1; i <= KcbArray[0]; i++)
1185 {
1186 if (KcbLockFlags & CMP_LOCK_KCB_ARRAY_EXCLUSIVE)
1187 {
1189 }
1190 else // CMP_LOCK_KCB_ARRAY_SHARED
1191 {
1193 }
1194 }
1195}
#define CMP_LOCK_KCB_ARRAY_EXCLUSIVE
Definition: cm.h:101
FORCEINLINE VOID CmpAcquireKcbLockExclusiveByIndex(ULONG Index)
Definition: cm_x.h:105
#define CmpAcquireKcbLockSharedByIndex(i)
Definition: cm_x.h:95

Referenced by CmpBuildAndLockKcbArray().

◆ CmpReferenceKeyControlBlock()

BOOLEAN NTAPI CmpReferenceKeyControlBlock ( IN PCM_KEY_CONTROL_BLOCK  Kcb)

Definition at line 357 of file cmkcbncb.c.

358{
360 "%s - Referencing KCB: %p\n", __FUNCTION__, Kcb);
361
362 /* Check if this is the KCB's first reference */
363 if (Kcb->RefCount == 0)
364 {
365 /* Check if the KCB is locked in shared mode */
366 if (!CmpIsKcbLockedExclusive(Kcb))
367 {
368 /* Convert it to exclusive */
370 {
371 /* Set the delayed close index so that we can be ignored */
372 Kcb->DelayedCloseIndex = 1;
373
374 /* Increase the reference count while we release the lock */
375 InterlockedIncrement((PLONG)&Kcb->RefCount);
376
377 /* Go from shared to exclusive */
379
380 /* Decrement the reference count; the lock is now held again */
381 InterlockedDecrement((PLONG)&Kcb->RefCount);
382
383 /* Check if we still control the index */
384 if (Kcb->DelayedCloseIndex == 1)
385 {
386 /* Reset it */
387 Kcb->DelayedCloseIndex = 0;
388 }
389 else
390 {
391 /* Sanity check */
392 ASSERT((Kcb->DelayedCloseIndex == CmpDelayedCloseSize) ||
393 (Kcb->DelayedCloseIndex == 0));
394 }
395 }
396 }
397 }
398
399 /* Increase the reference count */
400 if ((InterlockedIncrement((PLONG)&Kcb->RefCount) & 0xFFFF) == 0)
401 {
402 /* We've overflown to 64K references, bail out */
403 InterlockedDecrement((PLONG)&Kcb->RefCount);
404 return FALSE;
405 }
406
407 /* Check if this was the last close index */
408 if (!Kcb->DelayedCloseIndex)
409 {
410 /* Check if the KCB is locked in shared mode */
411 if (!CmpIsKcbLockedExclusive(Kcb))
412 {
413 /* Convert it to exclusive */
415 {
416 /* Go from shared to exclusive */
418 }
419 }
420
421 /* If we're still the last entry, remove us */
422 if (!Kcb->DelayedCloseIndex) CmpRemoveFromDelayedClose(Kcb);
423 }
424
425 /* Return success */
426 return TRUE;
427}
#define InterlockedIncrement
Definition: armddk.h:53
FORCEINLINE VOID CmpConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
Definition: cm_x.h:205
FORCEINLINE BOOLEAN CmpTryToConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
Definition: cm_x.h:156
VOID NTAPI CmpRemoveFromDelayedClose(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmdelay.c:425

Referenced by CmpBuildHashStackAndLookupCache(), CmpCreateKeyControlBlock(), CmpDoOpen(), and CmpLookInCache().

◆ CmpRemoveKeyControlBlock()

VOID NTAPI CmpRemoveKeyControlBlock ( IN PCM_KEY_CONTROL_BLOCK  Kcb)

Definition at line 306 of file cmkcbncb.c.

307{
308 /* Make sure we have the exclusive lock */
310
311 /* Remove the key hash */
312 CmpRemoveKeyHash(&Kcb->KeyHash);
313}
VOID NTAPI CmpRemoveKeyHash(IN PCM_KEY_HASH KeyHash)
Definition: cmkcbncb.c:78

Referenced by CmDeleteKey(), CmpCleanUpKcbCacheWithLock(), CmpCreateKeyControlBlock(), CmpDoCreate(), CmpEnumerateOpenSubKeys(), CmpLookInCache(), and CmUnloadKey().

◆ CmpRemoveKeyHash()

VOID NTAPI CmpRemoveKeyHash ( IN PCM_KEY_HASH  KeyHash)

Definition at line 78 of file cmkcbncb.c.

79{
80 PCM_KEY_HASH *Prev;
81 PCM_KEY_HASH Current;
83
84 /* Lookup all the keys in this index entry */
85 Prev = &GET_HASH_ENTRY(CmpCacheTable, KeyHash->ConvKey)->Entry;
86 while (TRUE)
87 {
88 /* Save the current one and make sure it's valid */
89 Current = *Prev;
90 ASSERT(Current != NULL);
91 ASSERT_VALID_HASH(Current);
92
93 /* Check if it matches */
94 if (Current == KeyHash)
95 {
96 /* Then write the previous one */
97 *Prev = Current->NextHash;
98 if (*Prev) ASSERT_VALID_HASH(*Prev);
99 break;
100 }
101
102 /* Otherwise, keep going */
103 Prev = &Current->NextHash;
104 }
105}
struct _CM_KEY_HASH * NextHash
Definition: cm.h:150

Referenced by CmpRemoveKeyControlBlock().

◆ CmpSortKcbArray()

static VOID CmpSortKcbArray ( _Inout_ PULONG  KcbArray)
static

Sorts an array of KCB hashes in ascending order and removes any key indices that are duplicates. The purpose of sorting the KCB elements is to ensure consistent and proper locking order, so that we can prevent a deadlock.

Parameters
[in,out]KcbArrayA pointer to an array of KCBs of which the key indices are to be sorted.

Definition at line 1211 of file cmkcbncb.c.

1213{
1214 ULONG i, j, k, KcbCount;
1215
1216 /* Ensure we don't go above the limit of KCBs we can hold */
1217 KcbCount = KcbArray[0];
1218 ASSERT(KcbCount < CMP_KCBS_IN_ARRAY_LIMIT);
1219
1220 /* Exchange-Sort the array in ascending order. Complexity: O[n^2] */
1221 for (i = 1; i <= KcbCount; i++)
1222 {
1223 for (j = i + 1; j <= KcbCount; j++)
1224 {
1225 if (KcbArray[i] > KcbArray[j])
1226 {
1227 ULONG Temp = KcbArray[i];
1228 KcbArray[i] = KcbArray[j];
1229 KcbArray[j] = Temp;
1230 }
1231 }
1232 }
1233
1234 /* Now remove any duplicated indices on the sorted array if any */
1235 for (i = 1; i <= KcbCount; i++)
1236 {
1237 for (j = i + 1; j <= KcbCount; j++)
1238 {
1239 if (KcbArray[i] == KcbArray[j])
1240 {
1241 for (k = j; k <= KcbCount; k++)
1242 {
1243 KcbArray[k - 1] = KcbArray[k];
1244 }
1245
1246 j--;
1247 KcbCount--;
1248 }
1249 }
1250 }
1251
1252 /* Update the KCB count */
1253 KcbArray[0] = KcbCount;
1254}
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
int k
Definition: mpi.c:3369

Referenced by CmpBuildAndLockKcbArray().

◆ CmpUnLockKcbArray()

VOID CmpUnLockKcbArray ( _In_ PULONG  KcbArray)

Unlocks a number of KCBs provided by a KCB array.

Parameters
[in]KcbArrayA pointer to an array of KCBs to be unlocked.

Definition at line 1145 of file cmkcbncb.c.

1147{
1148 ULONG i;
1149
1150 /* Release the locked KCBs in reverse order */
1151 for (i = KcbArray[0]; i > 0; i--)
1152 {
1153 CmpReleaseKcbLockByIndex(KcbArray[i]);
1154 }
1155}
FORCEINLINE VOID CmpReleaseKcbLockByIndex(ULONG Index)
Definition: cm_x.h:174

Referenced by CmpDoOpen(), CmpLookInCache(), and CmpParseKey().

◆ DelistKeyBodyFromKCB()

VOID NTAPI DelistKeyBodyFromKCB ( IN PCM_KEY_BODY  KeyBody,
IN BOOLEAN  LockHeld 
)

Definition at line 1100 of file cmkcbncb.c.

1102{
1103 ULONG i;
1104
1105 /* Sanity check */
1106 ASSERT(KeyBody->KeyControlBlock != NULL);
1107
1108 /* Check if we can use the parent KCB array */
1109 for (i = 0; i < 4; i++)
1110 {
1111 /* Add it into the list */
1112 if (InterlockedCompareExchangePointer((PVOID*)&KeyBody->KeyControlBlock->
1113 KeyBodyArray[i],
1114 NULL,
1115 KeyBody) == KeyBody)
1116 {
1117 /* Removed */
1118 return;
1119 }
1120 }
1121
1122 /* Sanity checks */
1123 ASSERT(IsListEmpty(&KeyBody->KeyControlBlock->KeyBodyListHead) == FALSE);
1124 ASSERT(IsListEmpty(&KeyBody->KeyBodyList) == FALSE);
1125
1126 /* Lock the KCB */
1127 if (!LockHeld) CmpAcquireKcbLockExclusive(KeyBody->KeyControlBlock);
1128 CMP_ASSERT_KCB_LOCK(KeyBody->KeyControlBlock);
1129
1130 /* Remove the entry */
1131 RemoveEntryList(&KeyBody->KeyBodyList);
1132
1133 /* Unlock it it if we did a manual lock */
1134 if (!LockHeld) CmpReleaseKcbLock(KeyBody->KeyControlBlock);
1135}
FORCEINLINE VOID CmpReleaseKcbLock(PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cm_x.h:185
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129

Referenced by CmpDeleteKeyObject().

◆ EnlistKeyBodyWithKCB()

VOID NTAPI EnlistKeyBodyWithKCB ( IN PCM_KEY_BODY  KeyBody,
IN ULONG  Flags 
)

Definition at line 1042 of file cmkcbncb.c.

1044{
1045 ULONG i;
1046
1047 /* Sanity check */
1048 ASSERT(KeyBody->KeyControlBlock != NULL);
1049
1050 /* Initialize the list entry */
1051 InitializeListHead(&KeyBody->KeyBodyList);
1052
1053 /* Check if we can use the parent KCB array */
1054 for (i = 0; i < 4; i++)
1055 {
1056 /* Add it into the list */
1057 if (!InterlockedCompareExchangePointer((PVOID*)&KeyBody->KeyControlBlock->
1058 KeyBodyArray[i],
1059 KeyBody,
1060 NULL))
1061 {
1062 /* Added */
1063 return;
1064 }
1065 }
1066
1067 /* Array full, check if we need to unlock the KCB */
1069 {
1070 /* It's shared, so release the KCB shared lock */
1071 CmpReleaseKcbLock(KeyBody->KeyControlBlock);
1073 }
1074
1075 /* Check if we need to lock the KCB */
1077 {
1078 /* Acquire the lock */
1079 CmpAcquireKcbLockExclusive(KeyBody->KeyControlBlock);
1080 }
1081
1082 /* Make sure we have the exclusive lock */
1083 CMP_ASSERT_KCB_LOCK(KeyBody->KeyControlBlock);
1084
1085 /* Do the insert */
1086 InsertTailList(&KeyBody->KeyControlBlock->KeyBodyListHead,
1087 &KeyBody->KeyBodyList);
1088
1089 /* Check if we did a manual lock */
1092 {
1093 /* Release the lock */
1094 CmpReleaseKcbLock(KeyBody->KeyControlBlock);
1095 }
1096}
#define CMP_ENLIST_KCB_LOCKED_SHARED
Definition: cm.h:95
#define CMP_ENLIST_KCB_LOCKED_EXCLUSIVE
Definition: cm.h:96
#define InsertTailList(ListHead, Entry)
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944

Referenced by CmpCreateRegistryRoot(), CmpDoCreateChild(), and CmpDoOpen().

◆ InitializeKCBKeyBodyList()

VOID NTAPI InitializeKCBKeyBodyList ( IN PCM_KEY_CONTROL_BLOCK  Kcb)

Definition at line 641 of file cmkcbncb.c.

642{
643 /* Initialize the list */
644 InitializeListHead(&Kcb->KeyBodyListHead);
645
646 /* Clear the bodies */
647 Kcb->KeyBodyArray[0] =
648 Kcb->KeyBodyArray[1] =
649 Kcb->KeyBodyArray[2] =
650 Kcb->KeyBodyArray[3] = NULL;
651}

Referenced by CmpCreateKeyControlBlock().

Variable Documentation

◆ CmpCacheTable

◆ CmpHashTableSize

ULONG CmpHashTableSize = 2048

Definition at line 17 of file cmkcbncb.c.

Referenced by CmpEnumerateOpenSubKeys(), and CmpInitializeCache().

◆ CmpNameCacheTable