00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
#include "cmp.h"
00025
00026 FAST_MUTEX CmpKcbLock;
00027 FAST_MUTEX CmpPostLock;
00028
00029 PCM_KEY_HASH *
CmpCacheTable;
00030 ULONG
CmpHashTableSize = 2048;
00031 ULONG
CmpDelayedCloseSize = 512;
00032 PCM_KEY_CONTROL_BLOCK *
CmpDelayedCloseTable;
00033 PCM_KEY_CONTROL_BLOCK *
CmpDelayedCloseCurrent;
00034 ULONG_PTR
CmpDelayedFreeIndex=0;
00035 PCM_NAME_HASH *
CmpNameCacheTable;
00036
00037
VOID
00038
CmpRemoveKeyHash(
00039 IN
PCM_KEY_HASH KeyHash
00040 );
00041
00042
PCM_KEY_CONTROL_BLOCK
00043
CmpInsertKeyHash(
00044 IN
PCM_KEY_HASH KeyHash,
00045 IN BOOLEAN FakeKey
00046 );
00047
00048
00049
00050
00051
00052
00053
VOID
00054
CmpDereferenceNameControlBlockWithLock(
00055
PCM_NAME_CONTROL_BLOCK Ncb
00056 );
00057
00058
#ifdef KCB_TO_KEYBODY_LINK
00059
VOID
00060 CmpDumpKeyBodyList(
00061 IN
PCM_KEY_CONTROL_BLOCK kcb,
00062 IN PULONG Count
00063 );
00064
#endif
00065
00066
#ifdef ALLOC_PRAGMA
00067
#pragma alloc_text(PAGE,CmpSearchForOpenSubKeys)
00068
#pragma alloc_text(PAGE,CmpReferenceKeyControlBlock)
00069
#pragma alloc_text(PAGE,CmpGetNameControlBlock)
00070
#pragma alloc_text(PAGE,CmpDereferenceNameControlBlockWithLock)
00071
#pragma alloc_text(PAGE,CmpCleanUpSubKeyInfo)
00072
#pragma alloc_text(PAGE,CmpCleanUpKcbValueCache)
00073
#pragma alloc_text(PAGE,CmpCleanUpKcbCacheWithLock)
00074
#pragma alloc_text(PAGE,CmpConstructName)
00075
#pragma alloc_text(PAGE,CmpRemoveFromDelayedClose)
00076
#pragma alloc_text(PAGE,CmpCreateKeyControlBlock)
00077
#pragma alloc_text(PAGE,CmpSearchKeyControlBlockTree)
00078
#pragma alloc_text(PAGE,CmpDereferenceKeyControlBlock)
00079
#pragma alloc_text(PAGE,CmpDereferenceKeyControlBlockWithLock)
00080
#pragma alloc_text(PAGE,CmpRemoveKeyControlBlock)
00081
#pragma alloc_text(PAGE,CmpFreeKeyBody)
00082
#pragma alloc_text(PAGE,CmpInsertKeyHash)
00083
#pragma alloc_text(PAGE,CmpRemoveKeyHash)
00084
#pragma alloc_text(PAGE,CmpInitializeCache)
00085
00086
#ifdef KCB_TO_KEYBODY_LINK
00087
#pragma alloc_text(PAGE,CmpDumpKeyBodyList)
00088
#pragma alloc_text(PAGE,CmpFlushNotifiesOnKeyBodyList)
00089
#endif
00090
00091
#endif
00092
00093
#ifdef KCB_TO_KEYBODY_LINK
00094
VOID
00095 CmpDumpKeyBodyList(
00096 IN
PCM_KEY_CONTROL_BLOCK kcb,
00097 IN PULONG Count
00098 )
00099 {
00100
00101
PCM_KEY_BODY KeyBody;
00102 PUNICODE_STRING
Name;
00103
00104
if( IsListEmpty(&(
kcb->KeyBodyListHead)) ==
TRUE ) {
00105
00106
00107
00108
00109
return;
00110 }
00111
00112
00113
Name =
CmpConstructName(kcb);
00114
if( !
Name ){
00115
00116
return;
00117 }
00118
00119
00120
00121
00122 KeyBody = (
PCM_KEY_BODY)
kcb->KeyBodyListHead.Flink;
00123
while( KeyBody != (
PCM_KEY_BODY)(&(
kcb->KeyBodyListHead)) ) {
00124 KeyBody = CONTAINING_RECORD(KeyBody,
00125
CM_KEY_BODY,
00126 KeyBodyList);
00127
00128
00129
00130
ASSERT_KEY_OBJECT(KeyBody);
00131
00132
00133
00134
00135
DbgPrint(
"Process %lx :: Key %wZ \n",KeyBody->
Process,Name);
00136
00137
00138 (*Count)++;
00139
00140 KeyBody = (
PCM_KEY_BODY)KeyBody->KeyBodyList.Flink;
00141 }
00142
00143
ExFreePoolWithTag(Name, CM_NAME_TAG | PROTECTED_POOL);
00144
00145 }
00146
00147
VOID
00148 CmpFlushNotifiesOnKeyBodyList(
00149 IN
PCM_KEY_CONTROL_BLOCK kcb
00150 )
00151 {
00152
PCM_KEY_BODY KeyBody;
00153
00154
if( IsListEmpty(&(
kcb->KeyBodyListHead)) ==
FALSE ) {
00155
00156
00157
00158 KeyBody = (
PCM_KEY_BODY)
kcb->KeyBodyListHead.Flink;
00159
while( KeyBody != (
PCM_KEY_BODY)(&(
kcb->KeyBodyListHead)) ) {
00160 KeyBody = CONTAINING_RECORD(KeyBody,
00161
CM_KEY_BODY,
00162 KeyBodyList);
00163
00164
00165
00166
ASSERT_KEY_OBJECT(KeyBody);
00167
00168
00169
00170
00171
CmpFlushNotify(KeyBody);
00172
00173 KeyBody = (
PCM_KEY_BODY)KeyBody->KeyBodyList.Flink;
00174 }
00175 }
00176 }
00177
#endif
00178
00179 ULONG
00180 CmpSearchForOpenSubKeys(
00181
PCM_KEY_CONTROL_BLOCK KeyControlBlock,
00182 SUBKEY_SEARCH_TYPE SearchType
00183 )
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
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
00224
00225
ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
00226
00227
00228
00229
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
00238
00239
CmpRemoveFromDelayedClose(
kcb);
00240
CmpCleanUpKcbCacheWithLock(
kcb);
00241
00242
00243
00244
00245 Current = &
CmpCacheTable[i];
00246
continue;
00247 }
00248 Current = &
kcb->NextHash;
00249 }
00250 }
00251
00252
if (KeyControlBlock->
RefCount == 1) {
00253
00254
00255
00256
Count = 0;
00257 }
else {
00258
00259
00260
00261
Count = 0;
00262
00263
00264
#ifdef KCB_TO_KEYBODY_LINK
00265
00266
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
00289
00290
if( SearchType ==
SearchIfExist ) {
00291
Count = 1;
00292
break;
00293 }
else if(SearchType ==
SearchAndDeref) {
00294
00295
00296
00297
00298
00299
00300
ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
00301
00302
00303
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
00318
00319
goto StartDeref;
00320
00321 }
else if(SearchType ==
SearchAndCount) {
00322
00323
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 }
00342
00343
00344 BOOLEAN
00345 CmpReferenceKeyControlBlock(
00346
PCM_KEY_CONTROL_BLOCK KeyControlBlock
00347 )
00348 {
00349
if (KeyControlBlock->
RefCount == 0) {
00350
CmpRemoveFromDelayedClose(KeyControlBlock);
00351 }
00352
00353
if ((
USHORT)(KeyControlBlock->
RefCount + 1) == 0) {
00354
00355
00356
00357
00358
00359
return (
FALSE);
00360 }
else {
00361 ++(KeyControlBlock->
RefCount);
00362
return (
TRUE);
00363 }
00364 }
00365
00366
00367
PCM_NAME_CONTROL_BLOCK
00368 CmpGetNameControlBlock(
00369 PUNICODE_STRING NodeName
00370 )
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
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
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
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
00442
00443
if ((
USHORT) (Ncb->
RefCount + 1) == 0) {
00444
00445
00446
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
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
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
00493
00494 CurrentName->
NextHash =
CmpNameCacheTable[
Index];
00495
CmpNameCacheTable[
Index] = CurrentName;
00496 }
00497
00498
return(Ncb);
00499 }
00500
00501
00502
VOID
00503 CmpDereferenceNameControlBlockWithLock(
00504
PCM_NAME_CONTROL_BLOCK Ncb
00505 )
00506 {
00507
PCM_NAME_HASH *Prev;
00508
PCM_NAME_HASH Current;
00509
00510
if (--Ncb->
RefCount == 0) {
00511
00512
00513
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
00529
00530
ExFreePoolWithTag(Ncb, CM_NAME_TAG |
PROTECTED_POOL);
00531 }
00532
return;
00533 }
00534
00535
00536
VOID
00537 CmpCleanUpSubKeyInfo(
00538
PCM_KEY_CONTROL_BLOCK KeyControlBlock
00539 )
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
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 }
00565
00566
00567
VOID
00568 CmpCleanUpKcbValueCache(
00569
PCM_KEY_CONTROL_BLOCK KeyControlBlock
00570 )
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
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
00599
CmpMakeSpecialPoolReadWrite(
CMP_GET_CACHED_ADDRESS(CachedList[i]) );
00600
00601
ExFreePool((PVOID)
CMP_GET_CACHED_ADDRESS(CachedList[i]));
00602
00603 }
00604 }
00605
00606
00607
CmpMakeSpecialPoolReadWrite(
CMP_GET_CACHED_ADDRESS(KeyControlBlock->
ValueCache.
ValueList) );
00608
00609
ExFreePool((PVOID)
CMP_GET_CACHED_ADDRESS(KeyControlBlock->
ValueCache.
ValueList));
00610
00611
00612 KeyControlBlock->
ValueCache.
ValueList =
HCELL_NIL;
00613
00614 }
else if (KeyControlBlock->
ExtFlags &
CM_KCB_SYM_LINK_FOUND) {
00615
00616
00617
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 }
00626
00627
00628
VOID
00629 CmpCleanUpKcbCacheWithLock(
00630
PCM_KEY_CONTROL_BLOCK KeyControlBlock
00631 )
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
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
00659
00660
00661
CmpCleanUpKcbValueCache(Kcb);
00662
00663
00664
00665
00666
00667
CmpDereferenceNameControlBlockWithLock(Kcb->
NameBlock);
00668
00669
if (Kcb->
ExtFlags &
CM_KCB_SUBKEY_HINT) {
00670
00671
00672
00673
ExFreePoolWithTag(Kcb->
IndexHint, CM_CACHE_INDEX_TAG |
PROTECTED_POOL);
00674 }
00675
00676
00677
00678
00679 ParentKcb = Kcb->
ParentKcb;
00680
00681
00682
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 }
00696
00697
00698 PUNICODE_STRING
00699 CmpConstructName(
00700
PCM_KEY_CONTROL_BLOCK kcb
00701 )
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
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
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
00741
00742 Length +=
sizeof(WCHAR);
00743
00744 TmpKcb = TmpKcb->
ParentKcb;
00745 }
00746
00747
00748
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
00763
00764 TmpKcb =
kcb;
00765 BeginPosition = Length;
00766
00767
while (TmpKcb) {
00768
00769
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 }
00804
00805
00806
VOID
00807 CmpRemoveFromDelayedClose(
00808 IN
PCM_KEY_CONTROL_BLOCK kcb
00809 )
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 }
00821
00822
00823
PCM_KEY_CONTROL_BLOCK
00824 CmpCreateKeyControlBlock(
00825
PHHIVE Hive,
00826 HCELL_INDEX Cell,
00827
PCM_KEY_NODE Node,
00828
PCM_KEY_CONTROL_BLOCK ParentKcb,
00829 BOOLEAN FakeKey,
00830 PUNICODE_STRING KeyName
00831 )
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
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
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
00894
00895
00896 NodeName.Buffer++;
00897 NodeName.Length -=
sizeof(WCHAR);
00898 }
00899
00900
00901
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
00918
00919
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
00943
00944
00945
00946
LOCK_KCB_TREE();
00947
00948
00949
00950
00951 kcbmatch =
CmpInsertKeyHash(&
kcb->KeyHash, FakeKey);
00952
if (kcbmatch !=
NULL) {
00953
00954
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
00965
00966
00967
CmpRemoveFromDelayedClose(
kcb);
00968 }
00969
if ((
USHORT)(
kcb->RefCount + 1) == 0) {
00970
00971
00972
00973
00974
00975
00976
ASSERT(
kcb->RefCount + 1 != 0);
00977
kcb =
NULL;
00978 }
else {
00979 ++
kcb->RefCount;
00980 }
00981 }
00982
else {
00983
00984
00985
00986
00987
00988
00989
00990
00991
if (ParentKcb) {
00992
if (
CmpReferenceKeyControlBlock(ParentKcb)) {
00993
kcb->ParentKcb = ParentKcb;
00994
kcb->TotalLevels = ParentKcb->
TotalLevels + 1;
00995 }
else {
00996
00997
00998
00999
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
01010
01011
kcb->ParentKcb =
NULL;
01012
kcb->TotalLevels = 1;
01013 }
01014
01015
if (
kcb) {
01016
01017
01018
01019
01020
kcb->NameBlock =
CmpGetNameControlBlock (&NodeName);
01021
01022
if (
kcb->NameBlock) {
01023
01024
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
01035
01036
kcb->Security = Node->
Security;
01037
01038
if (FakeKey) {
01039
01040
01041
01042
kcb->ExtFlags |=
CM_KCB_KEY_NON_EXIST;
01043 }
01044 }
else {
01045
01046
01047
01048
01049
01050
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 }
01067
01068
01069
01070
VOID
01071 CmpSearchKeyControlBlockTree(
01072 PKCB_WORKER_ROUTINE WorkerRoutine,
01073 PVOID Context1,
01074 PVOID Context2
01075 )
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
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
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
01125
01126
CmpRemoveFromDelayedClose(Current);
01127
CmpCleanUpKcbCacheWithLock(Current);
01128
01129
01130
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 }
01150
01151
01152
VOID
01153 CmpDereferenceKeyControlBlock(
01154
PCM_KEY_CONTROL_BLOCK KeyControlBlock
01155 )
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175 {
01176
LOCK_KCB_TREE();
01177
CmpDereferenceKeyControlBlockWithLock(KeyControlBlock) ;
01178
UNLOCK_KCB_TREE();
01179
return;
01180 }
01181
01182
01183
VOID
01184 CmpDereferenceKeyControlBlockWithLock(
01185
PCM_KEY_CONTROL_BLOCK KeyControlBlock
01186 )
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
01198
01199
if (KeyControlBlock->
ExtFlags &
CM_KCB_NO_DELAY_CLOSE) {
01200
01201
01202
01203
01204
01205
01206
CmpCleanUpKcbCacheWithLock(KeyControlBlock);
01207 }
else if (!KeyControlBlock->
Delete) {
01208
01209
01210
01211
01212
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
01226
01227
ASSERT(*
CmpDelayedCloseCurrent !=
NULL);
01228
ASSERT(!(*CmpDelayedCloseCurrent)->Delete);
01229
01230
01231
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
01246
01247
01248
01249
01250
01251
CmpCleanUpKcbCacheWithLock(KeyControlBlock);
01252 }
01253 }
01254
01255
return;
01256 }
01257
01258
01259
VOID
01260 CmpRemoveKeyControlBlock(
01261
PCM_KEY_CONTROL_BLOCK KeyControlBlock
01262 )
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284 {
01285
ASSERT_KCB(KeyControlBlock);
01286
01287
01288
01289
01290
CmpRemoveKeyHash(&KeyControlBlock->
KeyHash);
01291
01292
return;
01293 }
01294
01295
01296
VOID
01297 CmpFreeKeyBody(
01298
PHHIVE Hive,
01299 HCELL_INDEX Cell
01300 )
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321 {
01322
PCELL_DATA key;
01323
01324
01325
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
01341
01342
HvFreeCell(
Hive,
Cell);
01343
01344
return;
01345 }
01346
01347
01348
01349
PCM_KEY_CONTROL_BLOCK
01350 CmpInsertKeyHash(
01351 IN
PCM_KEY_HASH KeyHash,
01352 IN BOOLEAN FakeKey
01353 )
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
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
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
if (FakeKey) {
01394 KeyHash->KeyCell++;
01395 }
01396
01397
01398
01399
01400 Current =
CmpCacheTable[
Index];
01401
while (Current) {
01402
ASSERT_KEY_HASH(Current);
01403
01404
01405
01406
01407
01408
01409
if ((KeyHash->ConvKey == Current->
ConvKey) &&
01410 (KeyHash->KeyCell == Current->
KeyCell) &&
01411 (KeyHash->KeyHive == Current->
KeyHive)) {
01412
01413
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
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
01451
01452 KeyHash->
NextHash =
CmpCacheTable[
Index];
01453
CmpCacheTable[
Index] = KeyHash;
01454
return(
NULL);
01455 }
01456
01457
01458
VOID
01459 CmpRemoveKeyHash(
01460 IN
PCM_KEY_HASH KeyHash
01461 )
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
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
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 }
01509
01510
01511
VOID
01512 CmpInitializeCache()
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 }