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_HASHCmpCacheTable
ULONG CmpHashTableSize = 2048
ULONG CmpDelayedCloseSize = 512
PCM_KEY_CONTROL_BLOCKCmpDelayedCloseTable
PCM_KEY_CONTROL_BLOCKCmpDelayedCloseCurrent
ULONG_PTR CmpDelayedFreeIndex = 0
PCM_NAME_HASHCmpNameCacheTable


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.


Generated on Sat May 15 19:43:11 2004 for test by doxygen 1.3.7