test: cmsubs.c File Reference

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# cmsubs.c File Reference

`#include "cmp.h"`

Go to the source code of this file.

## Functions

VOID | CmpRemoveKeyHash (IN PCM_KEY_HASH KeyHash)
PCM_KEY_CONTROL_BLOCK | CmpInsertKeyHash (IN PCM_KEY_HASH KeyHash, IN BOOLEAN FakeKey)
VOID | CmpDereferenceNameControlBlockWithLock (PCM_NAME_CONTROL_BLOCK Ncb)
ULONG | CmpSearchForOpenSubKeys (PCM_KEY_CONTROL_BLOCK KeyControlBlock, SUBKEY_SEARCH_TYPE SearchType)
BOOLEAN | CmpReferenceKeyControlBlock (PCM_KEY_CONTROL_BLOCK KeyControlBlock)
PCM_NAME_CONTROL_BLOCK | CmpGetNameControlBlock (PUNICODE_STRING NodeName)
VOID | CmpCleanUpSubKeyInfo (PCM_KEY_CONTROL_BLOCK KeyControlBlock)
VOID | CmpCleanUpKcbValueCache (PCM_KEY_CONTROL_BLOCK KeyControlBlock)
VOID | CmpCleanUpKcbCacheWithLock (PCM_KEY_CONTROL_BLOCK KeyControlBlock)
PUNICODE_STRING | CmpConstructName (PCM_KEY_CONTROL_BLOCK kcb)
VOID | CmpRemoveFromDelayedClose (IN PCM_KEY_CONTROL_BLOCK kcb)
PCM_KEY_CONTROL_BLOCK | CmpCreateKeyControlBlock (PHHIVE Hive, HCELL_INDEX Cell, PCM_KEY_NODE Node, PCM_KEY_CONTROL_BLOCK ParentKcb, BOOLEAN FakeKey, PUNICODE_STRING KeyName)
VOID | CmpSearchKeyControlBlockTree (PKCB_WORKER_ROUTINE WorkerRoutine, PVOID Context1, PVOID Context2)
VOID | CmpDereferenceKeyControlBlock (PCM_KEY_CONTROL_BLOCK KeyControlBlock)
VOID | CmpDereferenceKeyControlBlockWithLock (PCM_KEY_CONTROL_BLOCK KeyControlBlock)
VOID | CmpRemoveKeyControlBlock (PCM_KEY_CONTROL_BLOCK KeyControlBlock)
VOID | CmpFreeKeyBody (PHHIVE Hive, HCELL_INDEX Cell)
VOID | CmpInitializeCache ()

## Variables

FAST_MUTEX | CmpKcbLock
FAST_MUTEX | CmpPostLock
PCM_KEY_HASH * | CmpCacheTable
ULONG | CmpHashTableSize = 2048
ULONG | CmpDelayedCloseSize = 512
PCM_KEY_CONTROL_BLOCK * | CmpDelayedCloseTable
PCM_KEY_CONTROL_BLOCK * | CmpDelayedCloseCurrent
ULONG_PTR | CmpDelayedFreeIndex = 0
PCM_NAME_HASH * | CmpNameCacheTable

## Function Documentation

VOID CmpCleanUpKcbCacheWithLock | ( | PCM_KEY_CONTROL_BLOCK | KeyControlBlock | ) |

Definition at line 629 of file cmsubs.c.

References ASSERT, ASSERT_KEYBODY_LIST_EMPTY, CM_KCB_SUBKEY_HINT, CmpCleanUpKcbValueCache(), CmpDereferenceNameControlBlockWithLock(), CmpRemoveKeyControlBlock(), _CM_KEY_CONTROL_BLOCK::Delete, ExFreePoolWithTag, _CM_KEY_CONTROL_BLOCK::ExtFlags, _CM_KEY_CONTROL_BLOCK::IndexHint, _CM_KEY_CONTROL_BLOCK::NameBlock, _CM_KEY_CONTROL_BLOCK::ParentKcb, PROTECTED_POOL, _CM_KEY_CONTROL_BLOCK::RefCount, and SET_KCB_SIGNATURE.

Referenced by CmpCacheLookup(), CmpDereferenceKeyControlBlockWithLock(), CmpSearchForOpenSubKeys(), and CmpSearchKeyControlBlockTree().

    00634                    :
    00635
    00636     Clean up all cached allocations that are associated to this key.
    00637     If the parent is still open just because of this one, Remove the parent as well.
    00638
    00639 Arguments:
    00640
    00641     KeyControlBlock - pointer to a key control block.
    00642
    00643 Return Value:
    00644
    00645     NONE.
    00646
    00647 --*/
    00648 {
    00649     PCM_KEY_CONTROL_BLOCK   Kcb;
    00650     PCM_KEY_CONTROL_BLOCK   ParentKcb;
    00651
    00652     Kcb = KeyControlBlock;
    00653
    00654     ASSERT(KeyControlBlock->RefCount == 0);
    00655
    00656     while (Kcb->RefCount == 0) {
    00657         //
    00658         // First, free allocations for Value/data.
    00659         //
    00660
    00661         CmpCleanUpKcbValueCache(Kcb);
    00662
    00663         //
    00664         // Free the kcb and dereference parentkcb and nameblock.
    00665         //
    00666
    00667         CmpDereferenceNameControlBlockWithLock(Kcb->NameBlock);
    00668
    00669         if (Kcb->ExtFlags & CM_KCB_SUBKEY_HINT) {
    00670             //
    00671             // Now free the HintIndex allocation
    00672             //
    00673             ExFreePoolWithTag(Kcb->IndexHint, CM_CACHE_INDEX_TAG | PROTECTED_POOL);
    00674         }
    00675
    00676         //
    00677         // Save the ParentKcb before we free the Kcb
    00678         //
    00679         ParentKcb = Kcb->ParentKcb;
    00680
    00681         //
    00682         // We cannot call CmpDereferenceKeyControlBlockWithLock so we can avoid recurrsion.
    00683         //
    00684
    00685         if (!Kcb->Delete) {
    00686             CmpRemoveKeyControlBlock(Kcb);
    00687         }
    00688         SET_KCB_SIGNATURE(Kcb, '4FmC');
    00689         ASSERT_KEYBODY_LIST_EMPTY(Kcb);
    00690         ExFreePoolWithTag(Kcb, CM_KCB_TAG | PROTECTED_POOL);
    00691
    00692         Kcb = ParentKcb;
    00693         Kcb->RefCount--;
    00694     }
    00695 }

VOID CmpCleanUpKcbValueCache | ( | PCM_KEY_CONTROL_BLOCK | KeyControlBlock | ) |

Definition at line 568 of file cmsubs.c.

References CM_KCB_NO_DELAY_CLOSE, CM_KCB_SYM_LINK_FOUND, CMP_GET_CACHED_ADDRESS, CMP_GET_CACHED_CELLDATA, CMP_IS_CELL_CACHED, CmpDereferenceKeyControlBlockWithLock(), CmpMakeSpecialPoolReadWrite, _CACHED_CHILD_LIST::Count, _CM_KEY_CONTROL_BLOCK::Delete, ExFreePool(), _CM_KEY_CONTROL_BLOCK::ExtFlags, HCELL_NIL, _CACHED_CHILD_LIST::RealKcb, _CM_KEY_CONTROL_BLOCK::RefCount, _CM_KEY_CONTROL_BLOCK::ValueCache, and _CACHED_CHILD_LIST::ValueList.

Referenced by CmDeleteValueKey(), CmpCleanUpKcbCacheWithLock(), CmpDoOpen(), CmpGetSymbolicLink(), CmRestoreKey(), and CmSetValueKey().

    00573                    :
    00574
    00575     Clean up cached value/data that are associated to this key.
    00576
    00577 Arguments:
    00578
    00579     KeyControlBlock - pointer to a key control block.
    00580
    00581 Return Value:
    00582
    00583     NONE.
    00584
    00585 --*/
    00586 {
    00587     ULONG i;
    00588     PULONG_PTR CachedList;
    00589     PCELL_DATA pcell;
    00590     ULONG      realsize;
    00591     BOOLEAN    small;
    00592
    00593     if (CMP_IS_CELL_CACHED(KeyControlBlock->ValueCache.ValueList)) {
    00594         CachedList = (PULONG_PTR) CMP_GET_CACHED_CELLDATA(KeyControlBlock->ValueCache.ValueList);
    00595         for (i = 0; i < KeyControlBlock->ValueCache.Count; i++) {
    00596             if (CMP_IS_CELL_CACHED(CachedList[i])) {
    00597
    00598                 // Trying to catch the BAD guy who writes over our pool.
    00599                 CmpMakeSpecialPoolReadWrite( CMP_GET_CACHED_ADDRESS(CachedList[i]) );
    00600
    00601                 ExFreePool((PVOID) CMP_GET_CACHED_ADDRESS(CachedList[i]));
    00602
    00603             }
    00604         }
    00605
    00606         // Trying to catch the BAD guy who writes over our pool.
    00607         CmpMakeSpecialPoolReadWrite( CMP_GET_CACHED_ADDRESS(KeyControlBlock->ValueCache.ValueList) );
    00608
    00609         ExFreePool((PVOID) CMP_GET_CACHED_ADDRESS(KeyControlBlock->ValueCache.ValueList));
    00610
    00611         // Mark the ValueList as NULL
    00612         KeyControlBlock->ValueCache.ValueList = HCELL_NIL;
    00613
    00614     } else if (KeyControlBlock->ExtFlags & CM_KCB_SYM_LINK_FOUND) {
    00615         //
    00616         // This is a symbolic link key with symbolic name resolved.
    00617         // Dereference to its real kcb and clear the bit.
    00618         //
    00619         if ((KeyControlBlock->ValueCache.RealKcb->RefCount == 1) && !(KeyControlBlock->ValueCache.RealKcb->Delete)) {
    00620             KeyControlBlock->ValueCache.RealKcb->ExtFlags |= CM_KCB_NO_DELAY_CLOSE;
    00621         }
    00622         CmpDereferenceKeyControlBlockWithLock(KeyControlBlock->ValueCache.RealKcb);
    00623         KeyControlBlock->ExtFlags &= ~CM_KCB_SYM_LINK_FOUND;
    00624     }
    00625 }

VOID CmpCleanUpSubKeyInfo | ( | PCM_KEY_CONTROL_BLOCK | KeyControlBlock | ) |

Definition at line 537 of file cmsubs.c.

References ASSERT_CM_LOCK_OWNED_EXCLUSIVE, CM_KCB_NO_SUBKEY, CM_KCB_SUBKEY_HINT, CM_KCB_SUBKEY_ONE, ExFreePoolWithTag, _CM_KEY_CONTROL_BLOCK::ExtFlags, _CM_KEY_CONTROL_BLOCK::IndexHint, and PROTECTED_POOL.

Referenced by CmDeleteKey(), CmpCreateLinkNode(), CmpDoCreate(), CmpSearchForOpenSubKeys(), and NtUnloadKey().

    00541                    :
    00542
    00543     Clean up the subkey information cache due to create or delete keys.
    00544     Registry is locked exclusively and no need to lock the KCB.
    00545
    00546 Arguments:
    00547
    00548     KeyControlBlock - pointer to a key control block.
    00549
    00550 Return Value:
    00551
    00552     NONE.
    00553
    00554 --*/
    00555 {
    00556     ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
    00557
    00558     if (KeyControlBlock->ExtFlags & (CM_KCB_NO_SUBKEY | CM_KCB_SUBKEY_ONE | CM_KCB_SUBKEY_HINT)) {
    00559         if (KeyControlBlock->ExtFlags & (CM_KCB_SUBKEY_HINT)) {
    00560             ExFreePoolWithTag(KeyControlBlock->IndexHint, CM_CACHE_INDEX_TAG | PROTECTED_POOL);
    00561         }
    00562         KeyControlBlock->ExtFlags &= ~((CM_KCB_NO_SUBKEY | CM_KCB_SUBKEY_ONE | CM_KCB_SUBKEY_HINT));
    00563     }
    00564 }

PUNICODE_STRING CmpConstructName | ( | PCM_KEY_CONTROL_BLOCK | kcb | ) |

Definition at line 699 of file cmsubs.c.

References _CM_NAME_CONTROL_BLOCK::Compressed, ExAllocatePoolWithTag, kcb(), _CM_NAME_CONTROL_BLOCK::Name, _CM_KEY_CONTROL_BLOCK::NameBlock, _CM_NAME_CONTROL_BLOCK::NameLength, PagedPool, _CM_KEY_CONTROL_BLOCK::ParentKcb, PROTECTED_POOL, and USHORT.

Referenced by CmpGetSymbolicLink(), CmpLoadHiveVolatile(), CmpQueryKeyName(), and CmQueryKey().

    00704                    :
    00705
    00706     Construct the name given a kcb.
    00707
    00708 Arguments:
    00709
    00710     kcb - Kcb for the key
    00711
    00712 Return Value:
    00713
    00714     Pointer to the unicode string constructed.
    00715     Caller is responsible to free this storage space.
    00716
    00717 --*/
    00718 {
    00719     PUNICODE_STRING FullName;
    00720     PCM_KEY_CONTROL_BLOCK TmpKcb;
    00721     USHORT Length;
    00722     USHORT size;
    00723     USHORT i;
    00724     USHORT BeginPosition;
    00725     WCHAR *w1, *w2;
    00726     UCHAR *u2;
    00727
    00728     //
    00729     // Calculate the total string length.
    00730     //
    00731     Length = 0;
    00732     TmpKcb = kcb;
    00733     while (TmpKcb) {
    00734         if (TmpKcb->NameBlock->Compressed) {
    00735             Length += TmpKcb->NameBlock->NameLength * sizeof(WCHAR);
    00736         } else {
    00737             Length += TmpKcb->NameBlock->NameLength;
    00738         }
    00739         //
    00740         // Add the sapce for OBJ_NAME_PATH_SEPARATOR;
    00741         //
    00742         Length += sizeof(WCHAR);
    00743
    00744         TmpKcb = TmpKcb->ParentKcb;
    00745     }
    00746
    00747     //
    00748     // Allocate the pool for the unicode string
    00749     //
    00750     size = sizeof(UNICODE_STRING) + Length;
    00751
    00752     FullName = (PUNICODE_STRING) ExAllocatePoolWithTag(PagedPool,
    00753                                                        size,
    00754                                                        CM_NAME_TAG | PROTECTED_POOL);
    00755
    00756     if (FullName) {
    00757         FullName->Buffer = (USHORT *) ((ULONG_PTR) FullName + sizeof(UNICODE_STRING));
    00758         FullName->Length = Length;
    00759         FullName->MaximumLength = Length;
    00760
    00761         //
    00762         // Now fill the name into the buffer.
    00763         //
    00764         TmpKcb = kcb;
    00765         BeginPosition = Length;
    00766
    00767         while (TmpKcb) {
    00768             //
    00769             // Calculate the begin position of each subkey. Then fill in the char.
    00770             //
    00771             //
    00772             if (TmpKcb->NameBlock->Compressed) {
    00773                 BeginPosition -= (TmpKcb->NameBlock->NameLength + 1) * sizeof(WCHAR);
    00774                 w1 = &(FullName->Buffer[BeginPosition/sizeof(WCHAR)]);
    00775                 *w1 = OBJ_NAME_PATH_SEPARATOR;
    00776                 w1++;
    00777
    00778                 u2 = (UCHAR *) &(TmpKcb->NameBlock->Name[0]);
    00779
    00780                 for (i=0; i<TmpKcb->NameBlock->NameLength; i++) {
    00781                     *w1 = (WCHAR)(*u2);
    00782                     w1++;
    00783                     u2++;
    00784                 }
    00785             } else {
    00786                 BeginPosition -= (TmpKcb->NameBlock->NameLength + sizeof(WCHAR));
    00787                 w1 = &(FullName->Buffer[BeginPosition/sizeof(WCHAR)]);
    00788                 *w1 = OBJ_NAME_PATH_SEPARATOR;
    00789                 w1++;
    00790
    00791                 w2 = TmpKcb->NameBlock->Name;
    00792
    00793                 for (i=0; i<TmpKcb->NameBlock->NameLength; i=i+sizeof(WCHAR)) {
    00794                     *w1 = *w2;
    00795                     w1++;
    00796                     w2++;
    00797                 }
    00798             }
    00799             TmpKcb = TmpKcb->ParentKcb;
    00800         }
    00801     }
    00802     return (FullName);
    00803 }

PCM_KEY_CONTROL_BLOCK CmpCreateKeyControlBlock | ( | PHHIVE | Hive,
|  | HCELL_INDEX | Cell,
|  | PCM_KEY_NODE | Node,
|  | PCM_KEY_CONTROL_BLOCK | ParentKcb,
|  | BOOLEAN | FakeKey,
|  | PUNICODE_STRING | KeyName
| ) |

Definition at line 824 of file cmsubs.c.

References ASSERT, ASSERT_KCB, ASSERT_KEYBODY_LIST_EMPTY, Cell, CM_KCB_KEY_NON_EXIST, CmpDereferenceKeyControlBlockWithLock(), CmpGetNameControlBlock(), CmpInsertKeyHash(), CmpReferenceKeyControlBlock(), CmpRemoveFromDelayedClose(), CmpRemoveKeyControlBlock(), _CM_KEY_CONTROL_BLOCK::ConvKey, _CHILD_LIST::Count, _CM_KEY_CONTROL_BLOCK::Delete, ExAllocatePoolWithTag, ExFreePoolWithTag, FALSE, _CM_KEY_NODE::Flags, Hive, INIT_KCB_KEYBODY_LIST, kcb(), KeyName, _CHILD_LIST::List, LOCK_KCB_TREE, NULL, PagedPool, PROTECTED_POOL, RtlUpcaseUnicodeChar(), _CM_KEY_NODE::Security, SET_KCB_SIGNATURE, Size, _CM_KEY_CONTROL_BLOCK::TotalLevels, UNLOCK_KCB_TREE, USHORT, and _CM_KEY_NODE::ValueList.

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

    00834                    :
    00835
    00836     Allocate and initialize a key control block, insert it into
    00837     the kcb tree.
    00838
    00839     Full path will be BaseName + '\' + KeyName, unless BaseName
    00840     NULL, in which case the full path is simply KeyName.
    00841
    00842     RefCount of returned KCB WILL have been incremented to reflect
    00843     callers ref.
    00844
    00845 Arguments:
    00846
    00847     Hive - Supplies Hive that holds the key we are creating a KCB for.
    00848
    00849     Cell - Supplies Cell that contains the key we are creating a KCB for.
    00850
    00851     Node - Supplies pointer to key node.
    00852
    00853     ParentKcb - Parent kcb of the kcb to be created
    00854
    00855     FakeKey - Whether the kcb to be create is a fake one or not
    00856
    00857     KeyName - the subkey name to of the KCB to be created.
    00858
    00859     NOTE:  We need the parameter instead of just using the name in the KEY_NODE
    00860            because there is no name in the root cell of a hive.
    00861
    00862 Return Value:
    00863
    00864     NULL - failure (insufficient memory)
    00865     else a pointer to the new kcb.
    00866
    00867 --*/
    00868 {
    00869     PCM_KEY_CONTROL_BLOCK   kcb;
    00870     PCM_KEY_CONTROL_BLOCK   kcbmatch=NULL;
    00871     PCMHIVE CmHive;
    00872     ULONG namelength;
    00873     PUNICODE_STRING         fullname;
    00874     ULONG       Size;
    00875     ULONG i;
    00876
    00877     UNICODE_STRING         NodeName;
    00878     ULONG ConvKey=0;
    00879     ULONG Cnt;
    00880     WCHAR *Cp;
    00881
    00882     //
    00883     // ParentKCb has the base hash value.
    00884     //
    00885     if (ParentKcb) {
    00886         ConvKey = ParentKcb->ConvKey;
    00887     }
    00888
    00889     NodeName = *KeyName;
    00890
    00891     while ((NodeName.Length > 0) && (NodeName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR)) {
    00892         //
    00893         // This must be the \REGISTRY.
    00894         // Strip off the leading OBJ_NAME_PATH_SEPARATOR
    00895         //
    00896         NodeName.Buffer++;
    00897         NodeName.Length -= sizeof(WCHAR);
    00898     }
    00899
    00900     //
    00901     // Manually compute the hash to use.
    00902     //
    00903     ASSERT(NodeName.Length > 0);
    00904
    00905     if (NodeName.Length) {
    00906         Cp = NodeName.Buffer;
    00907         for (Cnt=0; Cnt<NodeName.Length; Cnt += sizeof(WCHAR)) {
    00908             if ((*Cp != OBJ_NAME_PATH_SEPARATOR) &&
    00909                 (*Cp != UNICODE_NULL)) {
    00910                 ConvKey = 37 * ConvKey + (ULONG)RtlUpcaseUnicodeChar(*Cp);
    00911             }
    00912             ++Cp;
    00913         }
    00914     }
    00915
    00916     //
    00917     // Create a new kcb, which we will free if one already exists
    00918     // for this key.
    00919     // Now it is a fixed size structure.
    00920     //
    00921     kcb = ExAllocatePoolWithTag(PagedPool,
    00922                                 sizeof(CM_KEY_CONTROL_BLOCK),
    00923                                 CM_KCB_TAG | PROTECTED_POOL);
    00924
    00925
    00926     if (kcb == NULL) {
    00927         return(NULL);
    00928     } else {
    00929         SET_KCB_SIGNATURE(kcb, KCB_SIGNATURE);
    00930         INIT_KCB_KEYBODY_LIST(kcb);
    00931         kcb->Delete = FALSE;
    00932         kcb->RefCount = 1;
    00933         kcb->KeyHive = Hive;
    00934         kcb->KeyCell = Cell;
    00935         kcb->KeyNode = Node;
    00936         kcb->ConvKey = ConvKey;
    00937
    00938     }
    00939
    00940     ASSERT_KCB(kcb);
    00941     //
    00942     // Find location to insert kcb in kcb tree.
    00943     //
    00944
    00945
    00946     LOCK_KCB_TREE();
    00947
    00948     //
    00949     // Add the KCB to the hash table
    00950     //
    00951     kcbmatch = CmpInsertKeyHash(&kcb->KeyHash, FakeKey);
    00952     if (kcbmatch != NULL) {
    00953         //
    00954         // A match was found.
    00955         //
    00956         ASSERT(!kcbmatch->Delete);
    00957         SET_KCB_SIGNATURE(kcb, '1FmC');
    00958         ASSERT_KEYBODY_LIST_EMPTY(kcb);
    00959         ExFreePoolWithTag(kcb, CM_KCB_TAG | PROTECTED_POOL);
    00960         ASSERT_KCB(kcbmatch);
    00961         kcb = kcbmatch;
    00962         if (kcb->RefCount == 0) {
    00963             //
    00964             // This kcb is on the delayed close list. Remove it from that
    00965             // list.
    00966             //
    00967             CmpRemoveFromDelayedClose(kcb);
    00968         }
    00969         if ((USHORT)(kcb->RefCount + 1) == 0) {
    00970             //
    00971             // We have maxed out the ref count on this key. Probably
    00972             // some bogus app has opened the same key 64K times without
    00973             // ever closing it. Just fail the open, they've got enough
    00974             // handles already.
    00975             //
    00976             ASSERT(kcb->RefCount + 1 != 0);
    00977             kcb = NULL;
    00978         } else {
    00979             ++kcb->RefCount;
    00980         }
    00981     }
    00982     else {
    00983         //
    00984         // No kcb created previously, fill in all the data.
    00985         //
    00986
    00987         //
    00988         // Now try to reference the parentkcb
    00989         //
    00990
    00991         if (ParentKcb) {
    00992             if (CmpReferenceKeyControlBlock(ParentKcb)) {
    00993                 kcb->ParentKcb = ParentKcb;
    00994                 kcb->TotalLevels = ParentKcb->TotalLevels + 1;
    00995             } else {
    00996                 //
    00997                 // We have maxed out the ref count on the parent.
    00998                 // Since it has been cached in the cachetable,
    00999                 // remove it first before we free the allocation.
    01000                 //
    01001                 CmpRemoveKeyControlBlock(kcb);
    01002                 SET_KCB_SIGNATURE(kcb, '2FmC');
    01003                 ASSERT_KEYBODY_LIST_EMPTY(kcb);
    01004                 ExFreePoolWithTag(kcb, CM_KCB_TAG | PROTECTED_POOL);
    01005                 kcb = NULL;
    01006             }
    01007         } else {
    01008             //
    01009             // It is the \REGISTRY node.
    01010             //
    01011             kcb->ParentKcb = NULL;
    01012             kcb->TotalLevels = 1;
    01013         }
    01014
    01015         if (kcb) {
    01016             //
    01017             // Now try to find the Name Control block that has the name for this node.
    01018             //
    01019
    01020             kcb->NameBlock = CmpGetNameControlBlock (&NodeName);
    01021
    01022             if (kcb->NameBlock) {
    01023                 //
    01024                 // Now fill in all the data needed for the cache.
    01025                 //
    01026                 kcb->ValueCache.Count = Node->ValueList.Count;
    01027                 kcb->ValueCache.ValueList = (ULONG_PTR) Node->ValueList.List;
    01028
    01029                 kcb->Flags = Node->Flags;
    01030                 kcb->ExtFlags = 0;
    01031                 kcb->DelayedCloseIndex = 0;
    01032
    01033                 //
    01034                 // Cache the security cells in the kcb
    01035                 //
    01036                 kcb->Security = Node->Security;
    01037
    01038                 if (FakeKey) {
    01039                     //
    01040                     // The KCb to be created is a fake one
    01041                     //
    01042                     kcb->ExtFlags |= CM_KCB_KEY_NON_EXIST;
    01043                 }
    01044             } else {
    01045                 //
    01046                 // We have maxed out the ref count on the Name.
    01047                 //
    01048
    01049                 //
    01050                 // First dereference the parent KCB.
    01051                 //
    01052                 CmpDereferenceKeyControlBlockWithLock(ParentKcb);
    01053
    01054                 CmpRemoveKeyControlBlock(kcb);
    01055                 SET_KCB_SIGNATURE(kcb, '3FmC');
    01056                 ASSERT_KEYBODY_LIST_EMPTY(kcb);
    01057                 ExFreePoolWithTag(kcb, CM_KCB_TAG | PROTECTED_POOL);
    01058                 kcb = NULL;
    01059             }
    01060         }
    01061     }
    01062
    01063
    01064     UNLOCK_KCB_TREE();
    01065     return kcb;
    01066 }

VOID CmpDereferenceKeyControlBlock | ( | PCM_KEY_CONTROL_BLOCK | KeyControlBlock | ) |

Definition at line 1153 of file cmsubs.c.

References CmpDereferenceKeyControlBlockWithLock(), LOCK_KCB_TREE, and UNLOCK_KCB_TREE.

Referenced by CmpAddInfoAfterParseFailure(), CmpDeleteKeyObject(), CmpDoOpen(), and CmpParseKey().

    01158                    :
    01159
    01160     Decrements the reference count on a key control block, and frees it if it
    01161     becomes zero.
    01162
    01163     It is expected that no notify control blocks remain if the reference count
    01164     becomes zero.
    01165
    01166 Arguments:
    01167
    01168     KeyControlBlock - pointer to a key control block.
    01169
    01170 Return Value:
    01171
    01172     NONE.
    01173
    01174 --*/
    01175 {
    01176     LOCK_KCB_TREE();
    01177     CmpDereferenceKeyControlBlockWithLock(KeyControlBlock) ;
    01178     UNLOCK_KCB_TREE();
    01179     return;
    01180 }

VOID CmpDereferenceKeyControlBlockWithLock | ( | PCM_KEY_CONTROL_BLOCK | KeyControlBlock | ) |

Definition at line 1184 of file cmsubs.c.

References ASSERT, ASSERT_KCB, CM_KCB_NO_DELAY_CLOSE, CmpCleanUpKcbCacheWithLock(), CmpDelayedCloseCurrent, CmpDelayedCloseSize, CmpDelayedCloseTable, CmpDelayedFreeIndex, _CM_KEY_CONTROL_BLOCK::DelayedCloseIndex, _CM_KEY_CONTROL_BLOCK::Delete, _CM_KEY_CONTROL_BLOCK::ExtFlags, NULL, _CM_KEY_CONTROL_BLOCK::RefCount, and USHORT.

Referenced by CmEnumerateValueKey(), CmpCleanUpKcbValueCache(), CmpCreateKeyControlBlock(), CmpDereferenceKeyControlBlock(), CmpDoCreateChild(), CmpParseKey(), and CmQueryValueKey().

    01187 {
    01188     ULONG_PTR FreeIndex;
    01189     PCM_KEY_CONTROL_BLOCK KcbToFree;
    01190
    01191
    01192
    01193     ASSERT_KCB(KeyControlBlock);
    01194
    01195     if (--KeyControlBlock->RefCount == 0) {
    01196         //
    01197         // Remove kcb from the tree
    01198         //
    01199         if (KeyControlBlock->ExtFlags & CM_KCB_NO_DELAY_CLOSE) {
    01200             //
    01201             // Free storage directly so we can clean up junk quickly.
    01202             //
    01203             //
    01204             // Need to free all cached Index List, Index Leaf, Value, etc.
    01205             //
    01206             CmpCleanUpKcbCacheWithLock(KeyControlBlock);
    01207         } else if (!KeyControlBlock->Delete) {
    01208
    01209             //
    01210             // Put this kcb on our delayed close list.
    01211             //
    01212             // First check the free list for a free slot.
    01213             //
    01214             FreeIndex = CmpDelayedFreeIndex;
    01215             if (FreeIndex != -1) {
    01216                 ASSERT(FreeIndex < CmpDelayedCloseSize);
    01217                 CmpDelayedFreeIndex = (ULONG_PTR)CmpDelayedCloseTable[FreeIndex];
    01218                 KeyControlBlock->DelayedCloseIndex = (USHORT) FreeIndex;
    01219                 ASSERT((CmpDelayedFreeIndex == -1) ||
    01220                        (CmpDelayedFreeIndex < CmpDelayedCloseSize));
    01221                 CmpDelayedCloseTable[FreeIndex] = KeyControlBlock;
    01222             } else {
    01223
    01224                 //
    01225                 // Nothing is free, we have to get rid of something.
    01226                 //
    01227                 ASSERT(*CmpDelayedCloseCurrent != NULL);
    01228                 ASSERT(!(*CmpDelayedCloseCurrent)->Delete);
    01229                 //
    01230                 // Need to free all cached Index List, Index Leaf, Value, etc.
    01231                 // Change the code sequence for the recurrsive call to dereference the parent.
    01232                 //
    01233                 KcbToFree = *CmpDelayedCloseCurrent;
    01234                 *CmpDelayedCloseCurrent = KeyControlBlock;
    01235                 KeyControlBlock->DelayedCloseIndex = (USHORT)(CmpDelayedCloseCurrent - CmpDelayedCloseTable);
    01236                 ++CmpDelayedCloseCurrent;
    01237                 if ((ULONG)(CmpDelayedCloseCurrent - CmpDelayedCloseTable) == CmpDelayedCloseSize) {
    01238                     CmpDelayedCloseCurrent = CmpDelayedCloseTable;
    01239                 }
    01240
    01241                 CmpCleanUpKcbCacheWithLock(KcbToFree);
    01242             }
    01243         } else {
    01244             //
    01245             // Free storage directly as there is no point in putting this on
    01246             // our delayed close list.
    01247             //
    01248             //
    01249             // Need to free all cached Index List, Index Leaf, Value, etc.
    01250             //
    01251             CmpCleanUpKcbCacheWithLock(KeyControlBlock);
    01252         }
    01253     }
    01254
    01255     return;
    01256 }

VOID CmpDereferenceNameControlBlockWithLock | ( | PCM_NAME_CONTROL_BLOCK | Ncb | ) |

Definition at line 503 of file cmsubs.c.

References ASSERT, CmpNameCacheTable, _CM_NAME_CONTROL_BLOCK::ConvKey, ExFreePoolWithTag, GET_HASH_ENTRY, _CM_NAME_CONTROL_BLOCK::NameHash, _CM_NAME_HASH::NextHash, NULL, PROTECTED_POOL, _CM_NAME_CONTROL_BLOCK::RefCount, and TRUE.

Referenced by CmpCleanUpKcbCacheWithLock().

    00506 {
    00507     PCM_NAME_HASH *Prev;
    00508     PCM_NAME_HASH Current;
    00509
    00510     if (--Ncb->RefCount == 0) {
    00511
    00512         //
    00513         // Remove it from the the Hash Table
    00514         //
    00515         Prev = &(GET_HASH_ENTRY(CmpNameCacheTable, Ncb->ConvKey));
    00516
    00517         while (TRUE) {
    00518             Current = *Prev;
    00519             ASSERT(Current != NULL);
    00520             if (Current == &(Ncb->NameHash)) {
    00521                 *Prev = Current->NextHash;
    00522                 break;
    00523             }
    00524             Prev = &Current->NextHash;
    00525         }
    00526
    00527         //
    00528         // Free storage
    00529         //
    00530         ExFreePoolWithTag(Ncb, CM_NAME_TAG | PROTECTED_POOL);
    00531     }
    00532     return;
    00533 }

VOID CmpFreeKeyBody | ( | PHHIVE | Hive,
|  | HCELL_INDEX | Cell
| ) |

Definition at line 1297 of file cmsubs.c.

References Cell, _CM_KEY_NODE::Class, _CM_KEY_NODE::ClassLength, _CM_KEY_NODE::Flags, HCELL_NIL, Hive, HvFreeCell(), HvGetCell, KEY_HIVE_EXIT, _CELL_DATA::_u::KeyNode, _CM_KEY_NODE::Security, and _CELL_DATA::u.

Referenced by CmpFreeKeyByCell().

    01303                    :
    01304
    01305     Free storage for the key entry Hive.Cell refers to, including
    01306     its class and security data.  Will NOT free child list or value list.
    01307
    01308 Arguments:
    01309
    01310     Hive - supplies a pointer to the hive control structure for the hive
    01311
    01312     Cell - supplies index of key to free
    01313
    01314 Return Value:
    01315
    01316     NTSTATUS - Result code from call, among the following:
    01317
    01318         <TBS>
    01319
    01320 --*/
    01321 {
    01322     PCELL_DATA key;
    01323
    01324     //
    01325     // map in the cell
    01326     //
    01327     key = HvGetCell(Hive, Cell);
    01328
    01329     if (!(key->u.KeyNode.Flags & KEY_HIVE_EXIT)) {
    01330         if (key->u.KeyNode.Security != HCELL_NIL) {
    01331             HvFreeCell(Hive, key->u.KeyNode.Security);
    01332         }
    01333
    01334         if (key->u.KeyNode.ClassLength > 0) {
    01335             HvFreeCell(Hive, key->u.KeyNode.Class);
    01336         }
    01337     }
    01338
    01339     //
    01340     // unmap the cell itself and free it
    01341     //
    01342     HvFreeCell(Hive, Cell);
    01343
    01344     return;
    01345 }

PCM_NAME_CONTROL_BLOCK CmpGetNameControlBlock | ( | PUNICODE_STRING | NodeName | ) |

Definition at line 368 of file cmsubs.c.

References CmpCompareCompressedName(), CmpNameCacheTable, _CM_NAME_CONTROL_BLOCK::Compressed, _CM_NAME_CONTROL_BLOCK::ConvKey, _CM_NAME_HASH::ConvKey, ExAllocatePoolWithTag, FALSE, GET_HASH_INDEX, Index, Name, _CM_NAME_CONTROL_BLOCK::Name, _CM_NAME_CONTROL_BLOCK::NameHash, _CM_NAME_CONTROL_BLOCK::NameLength, _CM_NAME_HASH::NextHash, NULL, PagedPool, PROTECTED_POOL, _CM_NAME_CONTROL_BLOCK::RefCount, RtlUpcaseUnicodeChar(), Size, TRUE, and USHORT.

Referenced by CmpCreateKeyControlBlock().

    00371 {
    00372     PCM_NAME_CONTROL_BLOCK   Ncb;
    00373     ULONG  Cnt;
    00374     WCHAR *Cp;
    00375     WCHAR *Cp2;
    00376     ULONG Index;
    00377     ULONG i;
    00378     ULONG      Size;
    00379     PCM_NAME_HASH CurrentName;
    00380     ULONG rc;
    00381     BOOLEAN NameFound = FALSE;
    00382     USHORT NameSize;
    00383     BOOLEAN NameCompressed;
    00384     ULONG NameConvKey=0;
    00385     LONG Result;
    00386
    00387     //
    00388     // Calculate the ConvKey for this NadeName;
    00389     //
    00390
    00391     Cp = NodeName->Buffer;
    00392     for (Cnt=0; Cnt<NodeName->Length; Cnt += sizeof(WCHAR)) {
    00393         if (*Cp != OBJ_NAME_PATH_SEPARATOR) {
    00394             NameConvKey = 37 * NameConvKey + (ULONG) RtlUpcaseUnicodeChar(*Cp);
    00395         }
    00396         ++Cp;
    00397     }
    00398
    00399     //
    00400     // Find the Name Size;
    00401     //
    00402     NameCompressed = TRUE;
    00403     NameSize = NodeName->Length / sizeof(WCHAR);
    00404     for (i=0;i<NodeName->Length/sizeof(WCHAR);i++) {
    00405         if ((USHORT)NodeName->Buffer[i] > (UCHAR)-1) {
    00406             NameSize = NodeName->Length;
    00407             NameCompressed = FALSE;
    00408         }
    00409     }
    00410
    00411     Index = GET_HASH_INDEX(NameConvKey);
    00412     CurrentName = CmpNameCacheTable[Index];
    00413
    00414     while (CurrentName) {
    00415         Ncb =  CONTAINING_RECORD(CurrentName, CM_NAME_CONTROL_BLOCK, NameHash);
    00416
    00417         if ((NameConvKey == CurrentName->ConvKey) &&
    00418             (NameSize == Ncb->NameLength)) {
    00419             //
    00420             // Hash value matches, compare the names.
    00421             //
    00422             NameFound = TRUE;
    00423             if (Ncb->Compressed) {
    00424                 if (CmpCompareCompressedName(NodeName, Ncb->Name, NameSize)) {
    00425                     NameFound = FALSE;
    00426                 }
    00427             } else {
    00428                 Cp = (WCHAR *) NodeName->Buffer;
    00429                 Cp2 = (WCHAR *) Ncb->Name;
    00430                 for (i=0 ;i<Ncb->NameLength; i+= sizeof(WCHAR)) {
    00431                     if (RtlUpcaseUnicodeChar(*Cp) != RtlUpcaseUnicodeChar(*Cp2)) {
    00432                         NameFound = FALSE;
    00433                         break;
    00434                     }
    00435                     ++Cp;
    00436                     ++Cp2;
    00437                 }
    00438             }
    00439             if (NameFound) {
    00440                 //
    00441                 // Found it, increase the refcount.
    00442                 //
    00443                 if ((USHORT) (Ncb->RefCount + 1) == 0) {
    00444                     //
    00445                     // We have maxed out the ref count.
    00446                     // fail the call.
    00447                     //
    00448                     Ncb = NULL;
    00449                 } else {
    00450                     ++Ncb->RefCount;
    00451                 }
    00452                 break;
    00453             }
    00454         }
    00455         CurrentName = CurrentName->NextHash;
    00456     }
    00457
    00458     if (NameFound == FALSE) {
    00459         //
    00460         // Now need to create one Name block for this string.
    00461         //
    00462         Size = FIELD_OFFSET(CM_NAME_CONTROL_BLOCK, Name) + NameSize;
    00463
    00464         Ncb = ExAllocatePoolWithTag(PagedPool,
    00465                                     Size,
    00466                                     CM_NAME_TAG | PROTECTED_POOL);
    00467
    00468         if (Ncb == NULL) {
    00469             return(NULL);
    00470         }
    00471         RtlZeroMemory(Ncb, Size);
    00472
    00473         //
    00474         // Update all the info for this newly created Name block.
    00475         //
    00476         if (NameCompressed) {
    00477             Ncb->Compressed = TRUE;
    00478             for (i=0;i<NameSize;i++) {
    00479                 ((PUCHAR)Ncb->Name)[i] = (UCHAR)(NodeName->Buffer[i]);
    00480             }
    00481         } else {
    00482             Ncb->Compressed = FALSE;
    00483             RtlCopyMemory((PVOID)(Ncb->Name), (PVOID)(NodeName->Buffer), NameSize);
    00484         }
    00485
    00486         Ncb->ConvKey = NameConvKey;
    00487         Ncb->RefCount = 1;
    00488         Ncb->NameLength = NameSize;
    00489
    00490         CurrentName = &(Ncb->NameHash);
    00491         //
    00492         // Insert into Name Hash table.
    00493         //
    00494         CurrentName->NextHash = CmpNameCacheTable[Index];
    00495         CmpNameCacheTable[Index] = CurrentName;
    00496     }
    00497
    00498     return(Ncb);
    00499 }

VOID CmpInitializeCache | ( |  | ) |

Definition at line 1512 of file cmsubs.c.

References CmpCacheTable, CmpDelayedCloseCurrent, CmpDelayedCloseSize, CmpDelayedCloseTable, CmpDelayedFreeIndex, CmpHashTableSize, CmpNameCacheTable, ExAllocatePoolWithTag, KeBugCheckEx(), NULL, PagedPool, and PCM_KEY_CONTROL_BLOCK.

Referenced by CmInitSystem1().

    01513 {
    01514     ULONG TotalCmCacheSize;
    01515     ULONG i;
    01516
    01517     TotalCmCacheSize = CmpHashTableSize * sizeof(PCM_KEY_HASH);
    01518
    01519     CmpCacheTable = ExAllocatePoolWithTag(PagedPool,
    01520                                           TotalCmCacheSize,
    01521                                           'aCMC');
    01522     if (CmpCacheTable == NULL) {
    01523         KeBugCheckEx(CONFIG_INITIALIZATION_FAILED,6,1,0,0);
    01524         return;
    01525     }
    01526     RtlZeroMemory(CmpCacheTable, TotalCmCacheSize);
    01527
    01528     TotalCmCacheSize = CmpHashTableSize * sizeof(PCM_NAME_HASH);
    01529     CmpNameCacheTable = ExAllocatePoolWithTag(PagedPool,
    01530                                               TotalCmCacheSize,
    01531                                               'aCMC');
    01532     if (CmpNameCacheTable == NULL) {
    01533         KeBugCheckEx(CONFIG_INITIALIZATION_FAILED,6,1,0,0);
    01534         return;
    01535     }
    01536     RtlZeroMemory(CmpNameCacheTable, TotalCmCacheSize);
    01537
    01538     CmpDelayedCloseTable = ExAllocatePoolWithTag(PagedPool,
    01539                                                  CmpDelayedCloseSize * sizeof(PCM_KEY_CONTROL_BLOCK),
    01540                                                  'cDMC');
    01541     if (CmpDelayedCloseTable == NULL) {
    01542         KeBugCheckEx(CONFIG_INITIALIZATION_FAILED,6,2,0,0);
    01543         return;
    01544     }
    01545     CmpDelayedFreeIndex = 0;
    01546     for (i=0; i<CmpDelayedCloseSize-1; i++) {
    01547         CmpDelayedCloseTable[i] = (PCM_KEY_CONTROL_BLOCK)ULongToPtr(i+1);
    01548     }
    01549     CmpDelayedCloseTable[CmpDelayedCloseSize-1] = (PCM_KEY_CONTROL_BLOCK)-1;
    01550     CmpDelayedCloseCurrent = CmpDelayedCloseTable;
    01551 }

PCM_KEY_CONTROL_BLOCK CmpInsertKeyHash | ( | IN PCM_KEY_HASH | KeyHash,
|  | IN BOOLEAN | FakeKey
| ) |

Definition at line 1350 of file cmsubs.c.

References ASSERT, ASSERT_KEY_HASH, CM_KCB_KEY_NON_EXIST, CmpCacheTable, CmpHashTableSize, _CM_KEY_HASH::ConvKey, GET_HASH_INDEX, HASH_VALUE, Index, kcb(), _CM_KEY_HASH::KeyCell, _CM_KEY_HASH::KeyHive, _CM_KEY_HASH::NextHash, and NULL.

Referenced by CmpCreateKeyControlBlock().

    01356                    :
    01357
    01358     Adds a key hash structure to the hash table. The hash table
    01359     will be checked to see if a duplicate entry already exists. If
    01360     a duplicate is found, its kcb will be returned. If a duplicate is not
    01361     found, NULL will be returned.
    01362
    01363 Arguments:
    01364
    01365     KeyHash - Supplies the key hash structure to be added.
    01366
    01367 Return Value:
    01368
    01369     NULL - if the supplied key has was added
    01370     PCM_KEY_HASH - The duplicate hash entry, if one was found
    01371
    01372 --*/
    01373
    01374 {
    01375     HASH_VALUE Hash;
    01376     ULONG Index;
    01377     PCM_KEY_HASH Current;
    01378
    01379     ASSERT_KEY_HASH(KeyHash);
    01380     Index = GET_HASH_INDEX(KeyHash->ConvKey);
    01381
    01382     //
    01383     // If this is a fake key, we will use the cell and hive from its
    01384     // parent for uniqeness.  To deal with the case when the fake
    01385     // has the same ConvKey as its parent (in which case we cannot distingish
    01386     // between the two), we set the lowest bit of the fake key's cell.
    01387     //
    01388     // It's possible (unlikely) that we cannot distingish two fake keys
    01389     // (when their Convkey's are the same) under the same key.  It is not breaking
    01390     // anything, we just cannot find the other one in cache lookup.
    01391     //
    01392     //
    01393     if (FakeKey) {
    01394         KeyHash->KeyCell++;
    01395     }
    01396
    01397     //
    01398     // First look for duplicates.
    01399     //
    01400     Current = CmpCacheTable[Index];
    01401     while (Current) {
    01402         ASSERT_KEY_HASH(Current);
    01403         //
    01404         // We must check ConvKey since we can create a fake kcb
    01405         // for keys that does not exist.
    01406         // We will use the Hive and Cell from the parent.
    01407         //
    01408
    01409         if ((KeyHash->ConvKey == Current->ConvKey) &&
    01410             (KeyHash->KeyCell == Current->KeyCell) &&
    01411             (KeyHash->KeyHive == Current->KeyHive)) {
    01412             //
    01413             // Found a match
    01414             //
    01415             return(CONTAINING_RECORD(Current,
    01416                                      CM_KEY_CONTROL_BLOCK,
    01417                                      KeyHash));
    01418         }
    01419         Current = Current->NextHash;
    01420     }
    01421
    01422 #if DBG
    01423     //
    01424     // Make sure this key is not somehow cached in the wrong spot.
    01425     //
    01426     {
    01427         ULONG DbgIndex;
    01428         PCM_KEY_CONTROL_BLOCK kcb;
    01429
    01430         for (DbgIndex = 0; DbgIndex < CmpHashTableSize; DbgIndex++) {
    01431             Current = CmpCacheTable[DbgIndex];
    01432             while (Current) {
    01433                 kcb = CONTAINING_RECORD(Current,
    01434                                         CM_KEY_CONTROL_BLOCK,
    01435                                         KeyHash);
    01436
    01437                 ASSERT_KEY_HASH(Current);
    01438                 ASSERT((KeyHash->KeyHive != Current->KeyHive) ||
    01439                        FakeKey ||
    01440                        (kcb->ExtFlags & CM_KCB_KEY_NON_EXIST) ||
    01441                        (KeyHash->KeyCell != Current->KeyCell));
    01442                 Current = Current->NextHash;
    01443             }
    01444         }
    01445     }
    01446
    01447 #endif
    01448
    01449     //
    01450     // No duplicate was found, add this entry at the head of the list
    01451     //
    01452     KeyHash->NextHash = CmpCacheTable[Index];
    01453     CmpCacheTable[Index] = KeyHash;
    01454     return(NULL);
    01455 }

BOOLEAN CmpReferenceKeyControlBlock | ( | PCM_KEY_CONTROL_BLOCK | KeyControlBlock | ) |

Definition at line 345 of file cmsubs.c.

References CmpRemoveFromDelayedClose(), FALSE, _CM_KEY_CONTROL_BLOCK::RefCount, TRUE, and USHORT.

Referenced by CmpCacheLookup(), CmpCreateKeyControlBlock(), CmpDoOpen(), CmpGetSymbolicLink(), and CmpParseKey().

    00348 {
    00349     if (KeyControlBlock->RefCount == 0) {
    00350         CmpRemoveFromDelayedClose(KeyControlBlock);
    00351     }
    00352
    00353     if ((USHORT)(KeyControlBlock->RefCount + 1) == 0) {
    00354         //
    00355         // We have maxed out the ref count on this key. Probably
    00356         // some bogus app has opened the same key 64K times without
    00357         // ever closing it. Just fail the call
    00358         //
    00359         return (FALSE);
    00360     } else {
    00361         ++(KeyControlBlock->RefCount);
    00362         return (TRUE);
    00363     }
    00364 }

VOID CmpRemoveFromDelayedClose | ( | IN PCM_KEY_CONTROL_BLOCK | kcb | ) |

Definition at line 807 of file cmsubs.c.

References ASSERT, CmpDelayedCloseSize, CmpDelayedCloseTable, CmpDelayedFreeIndex, and kcb().

Referenced by CmpCacheLookup(), CmpCreateKeyControlBlock(), CmpReferenceKeyControlBlock(), CmpSearchForOpenSubKeys(), and CmpSearchKeyControlBlockTree().

    00810 {
    00811     ULONG i;
    00812     i = kcb->DelayedCloseIndex;
    00813
    00814     ASSERT (CmpDelayedCloseTable[i] == kcb);
    00815     ASSERT(i != CmpDelayedCloseSize);
    00816
    00817     CmpDelayedCloseTable[i] = (PCM_KEY_CONTROL_BLOCK)CmpDelayedFreeIndex;
    00818     CmpDelayedFreeIndex = i;
    00819     kcb->DelayedCloseIndex = 0;
    00820 }

VOID CmpRemoveKeyControlBlock | ( | PCM_KEY_CONTROL_BLOCK | KeyControlBlock | ) |

Definition at line 1260 of file cmsubs.c.

References ASSERT_KCB, CmpRemoveKeyHash(), and _CM_KEY_CONTROL_BLOCK::KeyHash.

Referenced by CmDeleteKey(), CmpCacheLookup(), CmpCleanUpKcbCacheWithLock(), CmpCreateKeyControlBlock(), CmpDoCreateChild(), CmpParseKey(), CmpSearchForOpenSubKeys(), and NtUnloadKey().

    01265                    :
    01266
    01267     Remove a key control block from the KCB tree.
    01268
    01269     It is expected that no notify control blocks remain.
    01270
    01271     The kcb will NOT be freed, call DereferenceKeyControlBlock for that.
    01272
    01273     This call assumes the KCB tree is already locked or registry is locked exclusively.
    01274
    01275 Arguments:
    01276
    01277     KeyControlBlock - pointer to a key control block.
    01278
    01279 Return Value:
    01280
    01281     NONE.
    01282
    01283 --*/
    01284 {
    01285     ASSERT_KCB(KeyControlBlock);
    01286
    01287     //
    01288     // Remove the KCB from the hash table
    01289     //
    01290     CmpRemoveKeyHash(&KeyControlBlock->KeyHash);
    01291
    01292     return;
    01293 }

VOID CmpRemoveKeyHash | ( | IN PCM_KEY_HASH | KeyHash | ) |

Definition at line 1459 of file cmsubs.c.

References ASSERT, ASSERT_KEY_HASH, CmpCacheTable, CmpHashTableSize, HASH_KEY, HASH_VALUE, Index, _CM_KEY_HASH::NextHash, NULL, and TRUE.

Referenced by CmpRemoveKeyControlBlock().

    01464                    :
    01465
    01466     Removes a key hash structure from the hash table.
    01467
    01468 Arguments:
    01469
    01470     KeyHash - Supplies the key hash structure to be deleted.
    01471
    01472 Return Value:
    01473
    01474     None
    01475
    01476 --*/
    01477
    01478 {
    01479     HASH_VALUE Hash;
    01480     ULONG Index;
    01481     PCM_KEY_HASH *Prev;
    01482     PCM_KEY_HASH Current;
    01483
    01484     ASSERT_KEY_HASH(KeyHash);
    01485
    01486     Hash = HASH_KEY(KeyHash->ConvKey);
    01487     Index = Hash % CmpHashTableSize;
    01488
    01489     //
    01490     // Find this entry.
    01491     //
    01492     Prev = &CmpCacheTable[Index];
    01493     while (TRUE) {
    01494         Current = *Prev;
    01495         ASSERT(Current != NULL);
    01496         ASSERT_KEY_HASH(Current);
    01497         if (Current == KeyHash) {
    01498             *Prev = Current->NextHash;
    01499 #if DBG
    01500             if (*Prev) {
    01501                 ASSERT_KEY_HASH(*Prev);
    01502             }
    01503 #endif
    01504             break;
    01505         }
    01506         Prev = &Current->NextHash;
    01507     }
    01508 }

ULONG CmpSearchForOpenSubKeys | ( | PCM_KEY_CONTROL_BLOCK | KeyControlBlock,
|  | SUBKEY_SEARCH_TYPE | SearchType
| ) |

Definition at line 180 of file cmsubs.c.

References ASSERT_CM_LOCK_OWNED_EXCLUSIVE, CmpCacheTable, CmpCleanUpKcbCacheWithLock(), CmpCleanUpSubKeyInfo(), CmpHashTableSize, CmpRemoveFromDelayedClose(), CmpRemoveKeyControlBlock(), Count, HCELL_NIL, kcb(), NULL, _CM_KEY_CONTROL_BLOCK::ParentKcb, _CM_KEY_CONTROL_BLOCK::RefCount, SearchAndCount, SearchAndDeref, SearchIfExist, _CM_KEY_CONTROL_BLOCK::TotalLevels, TRUE, and USHORT.

Referenced by CmRestoreKey(), CmUnloadKey(), and NtQueryOpenSubKeys().

    00185                    :
    00186
    00187     This routine searches the KCB tree for any open handles to keys that
    00188     are subkeys of the given key.
    00189
    00190     It is used by CmRestoreKey to verify that the tree being restored to
    00191     has no open handles.
    00192
    00193 Arguments:
    00194
    00195     KeyControlBlock - Supplies the key control block for the key for which
    00196         open subkeys are to be found.
    00197
    00198     SearchType - the type of the search
    00199         SearchIfExist - exits at the first open subkey found ==> returns 1 if any subkey is open
    00200
    00201         SearchAndDeref - Forces the keys underneath the Key referenced KeyControlBlock to
    00202                 be marked as not referenced (see the REG_FORCE_RESTORE flag in CmRestoreKey)
    00203                 returns 1 if at least one deref was made
    00204
    00205         SearchAndCount - Counts all open subkeys - returns the number of them
    00206
    00207 Return Value:
    00208
    00209     TRUE  - open handles to subkeys of the given key exist
    00210
    00211     FALSE - open handles to subkeys of the given key do not exist.
    00212 --*/
    00213 {
    00214     ULONG i;
    00215     PCM_KEY_HASH *Current;
    00216     PCM_KEY_CONTROL_BLOCK kcb;
    00217     PCM_KEY_CONTROL_BLOCK Realkcb;
    00218     PCM_KEY_CONTROL_BLOCK Parent;
    00219     USHORT LevelDiff, l;
    00220     ULONG   Count = 0;
    00221
    00222     //
    00223     // Registry lock should be held exclusively, so no need to KCB lock
    00224     //
    00225     ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
    00226
    00227
    00228     //
    00229     // First, clean up all subkeys in the cache
    00230     //
    00231     for (i=0; i<CmpHashTableSize; i++) {
    00232         Current = &CmpCacheTable[i];
    00233         while (*Current) {
    00234             kcb = CONTAINING_RECORD(*Current, CM_KEY_CONTROL_BLOCK, KeyHash);
    00235             if (kcb->RefCount == 0) {
    00236                 //
    00237                 // This kcb is in DelayClose case, remove it.
    00238                 //
    00239                 CmpRemoveFromDelayedClose(kcb);
    00240                 CmpCleanUpKcbCacheWithLock(kcb);
    00241
    00242                 //
    00243                 // The HashTable is changed, start over in this index again.
    00244                 //
    00245                 Current = &CmpCacheTable[i];
    00246                 continue;
    00247             }
    00248             Current = &kcb->NextHash;
    00249         }
    00250     }
    00251
    00252     if (KeyControlBlock->RefCount == 1) {
    00253         //
    00254         // There is only one open handle, so there must be no open subkeys.
    00255         //
    00256         Count = 0;
    00257     } else {
    00258         //
    00259         // Now search for an open subkey handle.
    00260         //
    00261         Count = 0;
    00262
    00263
    00264 #ifdef KCB_TO_KEYBODY_LINK
    00265         //
    00266         // dump the root first if we were asked to do so.
    00267         //
    00268         if(SearchType == SearchAndCount) {
    00269             CmpDumpKeyBodyList(KeyControlBlock,&Count);
    00270         }
    00271 #endif
    00272         for (i=0; i<CmpHashTableSize; i++) {
    00273
    00274 StartDeref:
    00275             Current = &CmpCacheTable[i];
    00276             while (*Current) {
    00277                 kcb = CONTAINING_RECORD(*Current, CM_KEY_CONTROL_BLOCK, KeyHash);
    00278                 if (kcb->TotalLevels > KeyControlBlock->TotalLevels) {
    00279                     LevelDiff = kcb->TotalLevels - KeyControlBlock->TotalLevels;
    00280
    00281                     Parent = kcb;
    00282                     for (l=0; l<LevelDiff; l++) {
    00283                         Parent = Parent->ParentKcb;
    00284                     }
    00285
    00286                     if (Parent == KeyControlBlock) {
    00287                         //
    00288                         // Found a match;
    00289                         //
    00290                         if( SearchType == SearchIfExist ) {
    00291                             Count = 1;
    00292                             break;
    00293                         } else if(SearchType == SearchAndDeref) {
    00294                             //
    00295                             // Mark the key as deleted, remove it from cache, but don't add it
    00296                             // to the Delay Close table (we want the key to be visible only to
    00297                             // the one(s) that have open handles on it.
    00298                             //
    00299
    00300                             ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
    00301
    00302                             //
    00303                             // flush any pending notifies as the kcb won't be around any longer
    00304                             //
    00305 #ifdef KCB_TO_KEYBODY_LINK
    00306                             CmpFlushNotifiesOnKeyBodyList(kcb);
    00307 #endif
    00308
    00309                             CmpCleanUpSubKeyInfo(kcb->ParentKcb);
    00310                             kcb->Delete = TRUE;
    00311                             CmpRemoveKeyControlBlock(kcb);
    00312                             kcb->KeyCell = HCELL_NIL;
    00313                             kcb->KeyNode = NULL;
    00314                             Count++;
    00315
    00316                             //
    00317                             // Restart the search
    00318                             //
    00319                             goto StartDeref;
    00320
    00321                         } else if(SearchType == SearchAndCount) {
    00322                             //
    00323                             // here do the dumping and count incrementing stuff
    00324                             //
    00325                         #ifdef KCB_TO_KEYBODY_LINK
    00326                             CmpDumpKeyBodyList(kcb,&Count);
    00327                         #else
    00328                             Count++;
    00329                         #endif
    00330                         }
    00331                     }
    00332
    00333                 }
    00334                 Current = &kcb->NextHash;
    00335             }
    00336         }
    00337     }
    00338
    00339
    00340     return Count;
    00341 }

VOID CmpSearchKeyControlBlockTree | ( | PKCB_WORKER_ROUTINE | WorkerRoutine,
|  | PVOID | Context1,
|  | PVOID | Context2
| ) |

Definition at line 1071 of file cmsubs.c.

References ASSERT, ASSERT_KCB, CmpCacheTable, CmpCleanUpKcbCacheWithLock(), CmpHashTableSize, CmpRemoveFromDelayedClose(), Context1, Context2, _CM_KEY_CONTROL_BLOCK::Delete, KCB_WORKER_CONTINUE, KCB_WORKER_DELETE, KCB_WORKER_DONE, _CM_KEY_CONTROL_BLOCK::NextHash, and _CM_KEY_CONTROL_BLOCK::RefCount.

Referenced by CmpRefreshHive(), and CmUnloadKey().

    01078                    :
    01079
    01080     Traverse the kcb tree.  We will visit all nodes unless WorkerRoutine
    01081     tells us to stop part way through.
    01082
    01083     For each node, call WorkerRoutine(..., Context1, Contex2).  If it returns
    01084     KCB_WORKER_DONE, we are done, simply return.  If it returns
    01085     KCB_WORKER_CONTINUE, just continue the search. If it returns KCB_WORKER_DELETE,
    01086     the specified KCB is marked as deleted.
    01087
    01088     This routine has the side-effect of removing all delayed-close KCBs.
    01089
    01090 Arguments:
    01091
    01092     WorkerRoutine - applied to nodes witch Match.
    01093
    01094     Context1 - data we pass through
    01095
    01096     Context2 - data we pass through
    01097
    01098
    01099 Return Value:
    01100
    01101     NONE.
    01102
    01103 --*/
    01104 {
    01105     PCM_KEY_CONTROL_BLOCK   Current;
    01106     PCM_KEY_CONTROL_BLOCK   Next;
    01107     PCM_KEY_HASH *Prev;
    01108     ULONG                   WorkerResult;
    01109     ULONG                   i;
    01110
    01111     //
    01112     // Walk the hash table
    01113     //
    01114     for (i=0; i<CmpHashTableSize; i++) {
    01115         Prev = &CmpCacheTable[i];
    01116         while (*Prev) {
    01117             Current = CONTAINING_RECORD(*Prev,
    01118                                         CM_KEY_CONTROL_BLOCK,
    01119                                         KeyHash);
    01120             ASSERT_KCB(Current);
    01121             ASSERT(!Current->Delete);
    01122             if (Current->RefCount == 0) {
    01123                 //
    01124                 // This kcb is in DelayClose case, remove it.
    01125                 //
    01126                 CmpRemoveFromDelayedClose(Current);
    01127                 CmpCleanUpKcbCacheWithLock(Current);
    01128
    01129                 //
    01130                 // The HashTable is changed, start over in this index again.
    01131                 //
    01132                 Prev = &CmpCacheTable[i];
    01133                 continue;
    01134             }
    01135
    01136             WorkerResult = (WorkerRoutine)(Current, Context1, Context2);
    01137             if (WorkerResult == KCB_WORKER_DONE) {
    01138                 return;
    01139             } else if (WorkerResult == KCB_WORKER_DELETE) {
    01140                 ASSERT(Current->Delete);
    01141                 *Prev = Current->NextHash;
    01142                 continue;
    01143             } else {
    01144                 ASSERT(WorkerResult == KCB_WORKER_CONTINUE);
    01145                 Prev = &Current->NextHash;
    01146             }
    01147         }
    01148     }
    01149 }

## Variable Documentation

PCM_KEY_HASH* CmpCacheTable

| Definition at line 29 of file cmsubs.c. Referenced by CmpCacheLookup(), CmpGetSymbolicLink(), CmpInitializeCache(), CmpInsertKeyHash(), CmpRemoveKeyHash(), CmpSearchForOpenSubKeys(), and CmpSearchKeyControlBlockTree().

PCM_KEY_CONTROL_BLOCK* CmpDelayedCloseCurrent

| Definition at line 33 of file cmsubs.c. Referenced by CmpDereferenceKeyControlBlockWithLock(), and CmpInitializeCache().

ULONG CmpDelayedCloseSize = 512

| Definition at line 31 of file cmsubs.c. Referenced by CmpDereferenceKeyControlBlockWithLock(), CmpInitializeCache(), and CmpRemoveFromDelayedClose().

PCM_KEY_CONTROL_BLOCK* CmpDelayedCloseTable

| Definition at line 32 of file cmsubs.c. Referenced by CmpDereferenceKeyControlBlockWithLock(), CmpInitializeCache(), and CmpRemoveFromDelayedClose().

ULONG_PTR CmpDelayedFreeIndex = 0

| Definition at line 34 of file cmsubs.c. Referenced by CmpDereferenceKeyControlBlockWithLock(), CmpInitializeCache(), and CmpRemoveFromDelayedClose().

ULONG CmpHashTableSize = 2048

| Definition at line 30 of file cmsubs.c. Referenced by CmpGetSymbolicLink(), CmpInitializeCache(), CmpInsertKeyHash(), CmpRemoveKeyHash(), CmpSearchForOpenSubKeys(), and CmpSearchKeyControlBlockTree().

FAST_MUTEX CmpKcbLock

| Definition at line 26 of file cmsubs.c.

PCM_NAME_HASH* CmpNameCacheTable

| Definition at line 35 of file cmsubs.c. Referenced by CmpDereferenceNameControlBlockWithLock(), CmpGetNameControlBlock(), and CmpInitializeCache().

FAST_MUTEX CmpPostLock

| Definition at line 27 of file cmsubs.c.