00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include "cmp.h"
00022
00023 ULONG
CmpCacheOnFlag =
CM_CACHE_FAKE_KEY;
00024
00025 extern PCMHIVE CmpMasterHive;
00026 extern BOOLEAN
CmpNoMasterCreates;
00027 extern PCM_KEY_CONTROL_BLOCK CmpKeyControlBlockRoot;
00028 extern UNICODE_STRING
CmSymbolicLinkValueName;
00029
00030 #define CM_HASH_STACK_SIZE 30
00031
00032 typedef struct _CM_HASH_ENTRY {
00033 ULONG
ConvKey;
00034 UNICODE_STRING
KeyName;
00035 }
CM_HASH_ENTRY, *
PCM_HASH_ENTRY;
00036
00037 ULONG
00038
CmpComputeHashValue(
00039 IN PCM_HASH_ENTRY HashStack,
00040 IN OUT ULONG *TotalSubkeys,
00041 IN ULONG BaseConvKey,
00042 IN PUNICODE_STRING RemainingName
00043 );
00044
00045
NTSTATUS
00046
CmpCacheLookup(
00047 IN PCM_HASH_ENTRY HashStack,
00048 IN ULONG TotalRemainingSubkeys,
00049 OUT ULONG *MatchRemainSubkeyLevel,
00050 IN OUT
PCM_KEY_CONTROL_BLOCK *Kcb,
00051 OUT PUNICODE_STRING RemainingName,
00052 OUT
PHHIVE *Hive,
00053 OUT HCELL_INDEX *Cell
00054 );
00055
00056
VOID
00057
CmpCacheAdd(
00058 IN PCM_HASH_ENTRY LastHashEntry,
00059 IN ULONG Count
00060 );
00061
00062
PCM_KEY_CONTROL_BLOCK
00063
CmpAddInfoAfterParseFailure(
00064
PHHIVE Hive,
00065 HCELL_INDEX Cell,
00066
PCM_KEY_NODE Node,
00067
PCM_KEY_CONTROL_BLOCK kcb,
00068 PUNICODE_STRING NodeName
00069 );
00070
00071
00072
00073
00074
00075 BOOLEAN
00076
CmpGetSymbolicLink(
00077 IN
PHHIVE Hive,
00078 IN
PCM_KEY_NODE Node,
00079 IN OUT PUNICODE_STRING ObjectName,
00080 IN OUT
PCM_KEY_CONTROL_BLOCK SymbolicKcb,
00081 IN PUNICODE_STRING RemainingName
00082 );
00083
00084
NTSTATUS
00085
CmpDoOpen(
00086 IN
PHHIVE Hive,
00087 IN HCELL_INDEX Cell,
00088 IN
PCM_KEY_NODE Node,
00089 IN
PACCESS_STATE AccessState,
00090 IN KPROCESSOR_MODE AccessMode,
00091 IN ULONG Attributes,
00092 IN
PCM_PARSE_CONTEXT Context,
00093 IN BOOLEAN CompleteKeyCached,
00094 IN OUT
PCM_KEY_CONTROL_BLOCK *CachedKcb,
00095 IN PUNICODE_STRING KeyName,
00096 OUT PVOID *Object
00097 );
00098
00099
NTSTATUS
00100
CmpCreateLinkNode(
00101 IN
PHHIVE Hive,
00102 IN HCELL_INDEX Cell,
00103 IN
PACCESS_STATE AccessState,
00104 IN UNICODE_STRING Name,
00105 IN KPROCESSOR_MODE AccessMode,
00106 IN ULONG Attributes,
00107 IN
PCM_PARSE_CONTEXT Context,
00108 IN
PCM_KEY_CONTROL_BLOCK ParentKcb,
00109 OUT PVOID *Object
00110 );
00111
00112
#ifdef ALLOC_PRAGMA
00113
#pragma alloc_text(PAGE,CmpParseKey)
00114
#pragma alloc_text(PAGE,CmpGetNextName)
00115
#pragma alloc_text(PAGE,CmpDoOpen)
00116
#pragma alloc_text(PAGE,CmpCreateLinkNode)
00117
#pragma alloc_text(PAGE,CmpGetSymbolicLink)
00118
#pragma alloc_text(PAGE,CmpComputeHashValue)
00119
#pragma alloc_text(PAGE,CmpCacheLookup)
00120
#pragma alloc_text(PAGE,CmpAddInfoAfterParseFailure)
00121
#endif
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 #define CmpStepThroughExit(h,c,n) \
00132
if ((n)->Flags & KEY_HIVE_EXIT) { \
00133
(h)=(n)->ChildHiveReference.KeyHive; \
00134
(c)=(n)->ChildHiveReference.KeyCell; \
00135
(n)=(PCM_KEY_NODE)HvGetCell((h),(c)); \
00136
}
00137
00138 #define CMP_PARSE_GOTO_NONE 0
00139 #define CMP_PARSE_GOTO_CREATE 1
00140 #define CMP_PARSE_GOTO_RETURN 2
00141 #define CMP_PARSE_GOTO_RETURN2 3
00142
00143
00144
NTSTATUS
00145 CmpParseKey(
00146 IN PVOID ParseObject,
00147 IN PVOID ObjectType,
00148 IN OUT
PACCESS_STATE AccessState,
00149 IN KPROCESSOR_MODE AccessMode,
00150 IN ULONG Attributes,
00151 IN OUT PUNICODE_STRING CompleteName,
00152 IN OUT PUNICODE_STRING RemainingName,
00153 IN OUT PVOID Context OPTIONAL,
00154 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
00155 OUT PVOID *Object
00156 )
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
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
NTSTATUS status;
00212 BOOLEAN rc;
00213
PHHIVE Hive;
00214
PCM_KEY_NODE Node;
00215
HCELL_INDEX Cell;
00216
HCELL_INDEX ParentCell;
00217
HCELL_INDEX NextCell;
00218
PHCELL_INDEX Index;
00219
PCM_PARSE_CONTEXT lcontext;
00220 UNICODE_STRING Current;
00221 UNICODE_STRING NextName;
00222
00223 BOOLEAN Last;
00224
00225
00226
CM_HASH_ENTRY HashStack[
CM_HASH_STACK_SIZE];
00227 ULONG TotalRemainingSubkeys;
00228 ULONG MatchRemainSubkeyLevel;
00229 ULONG TotalSubkeys=0;
00230 ULONG SubkeyParsed;
00231
PCM_KEY_CONTROL_BLOCK kcb;
00232
PCM_KEY_HASH PCmpCacheEntry=
NULL;
00233
PCM_KEY_CONTROL_BLOCK ParentKcb;
00234 UNICODE_STRING TmpNodeName;
00235 ULONG namelength;
00236 ULONG GoToValue =
CMP_PARSE_GOTO_NONE;
00237 BOOLEAN CompleteKeyCached =
FALSE;
00238
USHORT i,j;
00239 WCHAR *p1;
00240
00241
CMLOG(
CML_MINOR,
CMS_PARSE) {
00242 KdPrint((
"CmpParseKey:\n\t"));
00243 KdPrint((
"CompleteName = '%wZ'\n\t", CompleteName));
00244 KdPrint((
"RemainingName = '%wZ'\n", RemainingName));
00245 }
00246
00247
00248
00249
00250
while ((RemainingName->Length > 0) &&
00251 (RemainingName->Buffer[(RemainingName->Length/
sizeof(WCHAR)) - 1] == OBJ_NAME_PATH_SEPARATOR)) {
00252 RemainingName->Length -=
sizeof(WCHAR);
00253 }
00254
00255 Current = *RemainingName;
00256
if (ObjectType !=
CmpKeyObjectType) {
00257
return STATUS_OBJECT_TYPE_MISMATCH;
00258 }
00259
00260 lcontext = (
PCM_PARSE_CONTEXT)Context;
00261
00262
00263
00264
00265
if (((
PCM_KEY_BODY)ParseObject)->KeyControlBlock->Delete ==
TRUE) {
00266
return(STATUS_KEY_DELETED);
00267 }
00268
00269
00270
00271
00272
00273
00274
kcb = ((
PCM_KEY_BODY)ParseObject)->KeyControlBlock;
00275
Hive =
kcb->KeyHive;
00276
Cell =
kcb->KeyCell;
00277 Node =
kcb->KeyNode;
00278
00279
00280
00281
00282 TotalRemainingSubkeys =
CmpComputeHashValue(HashStack,
00283 &TotalSubkeys,
00284
kcb->ConvKey,
00285 &Current);
00286
00287
00288
00289
00290
00291
00292
LOCK_KCB_TREE();
00293
00294 status =
CmpCacheLookup(HashStack,
00295 TotalRemainingSubkeys,
00296 &MatchRemainSubkeyLevel,
00297 &
kcb,
00298 &Current,
00299 &
Hive,
00300 &
Cell);
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
if (!
NT_SUCCESS (status)) {
00311
UNLOCK_KCB_TREE();
00312
goto JustReturn;
00313 }
00314
00315 SubkeyParsed = MatchRemainSubkeyLevel;
00316 ParentKcb =
kcb;
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
if (
kcb->ExtFlags &
CM_KCB_CACHE_MASK) {
00335
if (MatchRemainSubkeyLevel == TotalRemainingSubkeys) {
00336
00337
00338
00339
if (
kcb->ExtFlags &
CM_KCB_KEY_NON_EXIST) {
00340
00341
00342
00343
if (ARGUMENT_PRESENT(lcontext)) {
00344 ULONG LevelToSkip = TotalRemainingSubkeys-1;
00345 ULONG i=0;
00346
00347
00348
00349
00350
00351
00352
00353
00354 ParentKcb =
kcb->ParentKcb;
00355
00356
if (
CmpReferenceKeyControlBlock(ParentKcb)) {
00357
00358
kcb->Delete =
TRUE;
00359
CmpRemoveKeyControlBlock(
kcb);
00360
CmpDereferenceKeyControlBlockWithLock(
kcb);
00361
00362
00363
00364
00365
Hive = ParentKcb->
KeyHive;
00366
Cell = ParentKcb->
KeyCell;
00367 Node = ParentKcb->
KeyNode;
00368
00369
00370
00371
00372
00373 NextName = *RemainingName;
00374
if ((NextName.Buffer ==
NULL) || (NextName.Length == 0)) {
00375 KdPrint((
"Something wrong in finding the child name\n"));
00376 DbgBreakPoint();
00377 }
00378
00379
00380
00381
if (*(NextName.Buffer) == OBJ_NAME_PATH_SEPARATOR) {
00382 NextName.Buffer++;
00383 NextName.Length -=
sizeof(WCHAR);
00384 NextName.MaximumLength -=
sizeof(WCHAR);
00385 }
00386
00387
while (i < LevelToSkip) {
00388
if (*(NextName.Buffer) == OBJ_NAME_PATH_SEPARATOR) {
00389 i++;
00390 }
00391 NextName.Buffer++;
00392 NextName.Length -=
sizeof(WCHAR);
00393 NextName.MaximumLength -=
sizeof(WCHAR);
00394 }
00395 GoToValue =
CMP_PARSE_GOTO_CREATE;
00396 }
else {
00397
00398
00399
00400
00401 status = STATUS_INSUFFICIENT_RESOURCES;
00402 GoToValue =
CMP_PARSE_GOTO_RETURN2;
00403 }
00404 }
else {
00405 status = STATUS_OBJECT_NAME_NOT_FOUND;
00406 GoToValue =
CMP_PARSE_GOTO_RETURN;
00407 }
00408 }
00409 }
else if (
kcb->ExtFlags &
CM_KCB_KEY_NON_EXIST) {
00410
00411
00412
00413 status = STATUS_OBJECT_NAME_NOT_FOUND;
00414 GoToValue =
CMP_PARSE_GOTO_RETURN;
00415 }
else if (
kcb->ExtFlags &
CM_KCB_NO_SUBKEY) {
00416
00417
00418
00419
if (((TotalRemainingSubkeys - MatchRemainSubkeyLevel) == 1) && (ARGUMENT_PRESENT(lcontext))) {
00420
00421
00422
00423
00424 }
else {
00425 status = STATUS_OBJECT_NAME_NOT_FOUND;
00426 GoToValue =
CMP_PARSE_GOTO_RETURN;
00427 }
00428 }
else {
00429
00430
00431
00432
00433 ULONG HintLength;
00434 ULONG HintCounts;
00435 ULONG CmpCount;
00436 WCHAR c1;
00437 WCHAR c2;
00438 UCHAR *TmpName;
00439 LONG Result;
00440 BOOLEAN NoMatch =
TRUE;
00441
00442
00443
00444
00445
00446
00447
00448 TmpNodeName = Current;
00449
00450 rc =
CmpGetNextName(&TmpNodeName, &NextName, &Last);
00451
00452
if (
kcb->ExtFlags &
CM_KCB_SUBKEY_ONE) {
00453 HintCounts = 1;
00454 TmpName = &(
kcb->NameHint[0]);
00455 }
else {
00456
00457
00458
00459 HintCounts =
kcb->IndexHint->Count;
00460 TmpName = &(
kcb->IndexHint->NameHint[0]);
00461 }
00462
00463
00464
00465
00466
if (NextName.Length < (
sizeof(WCHAR) *
CM_SUBKEY_HINT_LENGTH) ) {
00467 HintLength = NextName.Length /
sizeof(WCHAR);
00468 }
else {
00469 HintLength =
CM_SUBKEY_HINT_LENGTH;
00470 }
00471
00472
for (CmpCount=0; CmpCount<HintCounts; CmpCount++) {
00473 NoMatch =
FALSE;
00474
00475
if( TmpName[0] == 0) {
00476
00477
00478
00479
break;
00480 }
00481
00482
for (i=0; i<HintLength; i++) {
00483 c1 = NextName.Buffer[i];
00484 c2 = (WCHAR) *TmpName;
00485
00486 Result = (LONG)
RtlUpcaseUnicodeChar(c1) - (LONG)
RtlUpcaseUnicodeChar(c2);
00487
if (Result != 0) {
00488 NoMatch =
TRUE;
00489 TmpName += (
CM_SUBKEY_HINT_LENGTH-i);
00490
break;
00491 }
00492 TmpName++;
00493 }
00494
00495
if (NoMatch ==
FALSE) {
00496
00497
00498
00499
break;
00500 }
00501 }
00502
00503
if (NoMatch) {
00504
if (((TotalRemainingSubkeys - MatchRemainSubkeyLevel) == 1) && (ARGUMENT_PRESENT(lcontext))) {
00505
00506
00507
00508
00509 }
else {
00510 status = STATUS_OBJECT_NAME_NOT_FOUND;
00511 GoToValue =
CMP_PARSE_GOTO_RETURN;
00512 }
00513 }
00514 }
00515 }
00516
00517
UNLOCK_KCB_TREE();
00518
00519
00520
if (GoToValue ==
CMP_PARSE_GOTO_CREATE) {
00521
goto CreateChild;
00522 }
else if (GoToValue ==
CMP_PARSE_GOTO_RETURN) {
00523
goto FreeAndReturn;
00524 }
else if (GoToValue ==
CMP_PARSE_GOTO_RETURN2) {
00525
goto JustReturn;
00526 }
00527
00528
if (MatchRemainSubkeyLevel) {
00529
00530
00531
00532
00533
00534
00535
00536 Node =
kcb->KeyNode;
00537
00538
if (MatchRemainSubkeyLevel == TotalSubkeys) {
00539
00540
00541
00542
00543
00544
00545
00546 CompleteKeyCached =
TRUE;
00547
goto Found;
00548 }
00549 }
else if (TotalRemainingSubkeys == 0) {
00550
00551
00552
00553 CompleteKeyCached =
TRUE;
00554
goto Found;
00555 }
00556
00557
00558
00559
00560
00561 status = STATUS_SUCCESS;
00562
while (
TRUE) {
00563
00564
00565
00566
00567 rc =
CmpGetNextName(&Current, &NextName, &Last);
00568
if ((NextName.Length > 0) && (rc ==
TRUE)) {
00569
00570
00571
00572
00573
00574
00575
00576
if (!(
kcb->KeyNode->Flags &
KEY_SYM_LINK)) {
00577
00578
00579
00580
00581 NextCell =
CmpFindSubKeyByName(
Hive,
00582 Node,
00583 &NextName);
00584
00585
CMLOG(
CML_FLOW,
CMS_PARSE) {
00586 KdPrint((
"CmpParseKey:\n\t"));
00587 KdPrint((
"NextName = '%wZ'\n\t", &NextName));
00588 KdPrint((
"NextCell = %08lx Last = %01lx\n", NextCell, Last));
00589 }
00590
if (NextCell !=
HCELL_NIL) {
00591
Cell = NextCell;
00592 Node = (
PCM_KEY_NODE)
HvGetCell(
Hive,
Cell);
00593
if (Last ==
TRUE) {
00594
00595 Found:
00596
00597
00598
00599
00600
00601
00602
if (CompleteKeyCached ==
TRUE) {
00603
00604
00605
00606
00607
00608
00609 }
else {
00610
CmpStepThroughExit(
Hive,
Cell, Node);
00611 }
00612
00613
00614
00615
00616
00617
00618 status =
CmpDoOpen(
Hive,
00619
Cell,
00620 Node,
00621 AccessState,
00622 AccessMode,
00623 Attributes,
00624 lcontext,
00625 CompleteKeyCached,
00626 &
kcb,
00627 &NextName,
00628 Object);
00629
00630
if (status == STATUS_REPARSE) {
00631
00632
00633
00634
00635
00636
if (!
CmpGetSymbolicLink(
Hive,
00637 Node,
00638 CompleteName,
00639
kcb,
00640
NULL)) {
00641
CMLOG(
CML_MAJOR,
CMS_PARSE) {
00642 KdPrint((
"CmpParseKey: couldn't find symbolic link name\n"));
00643 }
00644 status = STATUS_OBJECT_NAME_NOT_FOUND;
00645 }
00646 }
00647
00648
break;
00649 }
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
CmpStepThroughExit(
Hive,
Cell, Node);
00661
00662
00663
00664
00665
00666
kcb =
CmpCreateKeyControlBlock(
Hive,
00667
Cell,
00668 Node,
00669 ParentKcb,
00670
FALSE,
00671 &NextName);
00672
00673
if (
kcb ==
NULL) {
00674 status = STATUS_INSUFFICIENT_RESOURCES;
00675
goto FreeAndReturn;
00676
00677
00678
00679
00680 }
00681
00682
00683
00684
00685
00686
CmpDereferenceKeyControlBlock(ParentKcb);
00687
00688 ParentKcb =
kcb;
00689
00690
00691 }
else {
00692
00693
00694
00695
00696
00697
if ((Last ==
TRUE) && (ARGUMENT_PRESENT(lcontext))) {
00698
00699 CreateChild:
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
if (lcontext->
CreateLink) {
00722 status =
CmpCreateLinkNode(
Hive,
00723
Cell,
00724 AccessState,
00725 NextName,
00726 AccessMode,
00727 Attributes,
00728 lcontext,
00729 ParentKcb,
00730 Object);
00731
00732 }
else {
00733
00734
if ( (
Hive == &(
CmpMasterHive->
Hive)) &&
00735 (
CmpNoMasterCreates ==
TRUE) ) {
00736
00737
00738
00739
00740
00741 status = STATUS_INVALID_PARAMETER;
00742
break;
00743 }
00744
00745 status =
CmpDoCreate(
Hive,
00746
Cell,
00747 AccessState,
00748 &NextName,
00749 AccessMode,
00750 lcontext,
00751 ParentKcb,
00752 Object);
00753 }
00754
00755 lcontext->
Disposition = REG_CREATED_NEW_KEY;
00756
break;
00757
00758 }
else {
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770 ParentKcb =
CmpAddInfoAfterParseFailure(
Hive,
00771
Cell,
00772 Node,
00773
kcb,
00774 &NextName
00775 );
00776
00777 status = STATUS_OBJECT_NAME_NOT_FOUND;
00778
break;
00779 }
00780
00781 }
00782
00783 }
else {
00784
00785
00786
00787
00788 Current.Buffer = NextName.Buffer;
00789 Current.Length += NextName.Length;
00790 Current.MaximumLength += NextName.MaximumLength;
00791
if (
CmpGetSymbolicLink(
Hive,
00792 Node,
00793 CompleteName,
00794
kcb,
00795 &Current)) {
00796
00797 status = STATUS_REPARSE;
00798
break;
00799
00800 }
else {
00801
CMLOG(
CML_MAJOR,
CMS_PARSE) {
00802 KdPrint((
"CmpParseKey: couldn't find symbolic link name\n"));
00803 }
00804 status = STATUS_OBJECT_NAME_NOT_FOUND;
00805
break;
00806 }
00807 }
00808
00809 }
else if (rc ==
TRUE && Last ==
TRUE) {
00810
00811
00812
00813
00814
00815
CmpStepThroughExit(
Hive,
Cell, Node);
00816
00817
00818
00819
00820
00821
00822 status =
CmpDoOpen(
Hive,
00823
Cell,
00824 Node,
00825 AccessState,
00826 AccessMode,
00827 Attributes,
00828 lcontext,
00829
TRUE,
00830 &
kcb,
00831 &NextName,
00832 Object);
00833
break;
00834
00835 }
else {
00836
00837
00838
00839
00840 status = STATUS_INVALID_PARAMETER;
00841
break;
00842 }
00843
00844 }
00845
00846 FreeAndReturn:
00847
00848
00849
00850
00851
00852
CmpDereferenceKeyControlBlock(ParentKcb);
00853 JustReturn:
00854
00855
return status;
00856 }
00857
00858
00859 BOOLEAN
00860 CmpGetNextName(
00861 IN OUT PUNICODE_STRING RemainingName,
00862 OUT PUNICODE_STRING NextName,
00863 OUT PBOOLEAN Last
00864 )
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892 {
00893 BOOLEAN rc =
TRUE;
00894
00895
00896
00897
00898
if ((RemainingName->Buffer ==
NULL) || (RemainingName->Length == 0)) {
00899 *Last =
TRUE;
00900 NextName->Buffer =
NULL;
00901 NextName->Length = 0;
00902
return TRUE;
00903 }
00904
00905
if (*(RemainingName->Buffer) == UNICODE_NULL) {
00906 *Last =
TRUE;
00907 NextName->Buffer =
NULL;
00908 NextName->Length = 0;
00909
return TRUE;
00910 }
00911
00912
00913
00914
00915
if (*(RemainingName->Buffer) == OBJ_NAME_PATH_SEPARATOR) {
00916 RemainingName->Buffer++;
00917 RemainingName->Length -=
sizeof(WCHAR);
00918 RemainingName->MaximumLength -=
sizeof(WCHAR);
00919 }
00920
00921
00922
00923
00924 NextName->Buffer = RemainingName->Buffer;
00925
while (
TRUE) {
00926
if (RemainingName->Length == 0) {
00927
break;
00928 }
00929
if (*RemainingName->Buffer == OBJ_NAME_PATH_SEPARATOR) {
00930
break;
00931 }
00932
00933
00934
00935
00936
00937
00938 RemainingName->Buffer++;
00939 RemainingName->Length -=
sizeof(WCHAR);
00940 RemainingName->MaximumLength -=
sizeof(WCHAR);
00941 }
00942
00943
00944
00945
00946 NextName->Length = (
USHORT)
00947 ((PUCHAR)RemainingName->Buffer - (PUCHAR)(NextName->Buffer));
00948
if (NextName->Length >
MAX_KEY_NAME_LENGTH)
00949 {
00950 rc =
FALSE;
00951 }
00952 NextName->MaximumLength = NextName->Length;
00953
00954
00955
00956
00957 *Last = (RemainingName->Length == 0);
00958
return rc;
00959 }
00960
00961
00962
NTSTATUS
00963 CmpDoOpen(
00964 IN
PHHIVE Hive,
00965 IN HCELL_INDEX Cell,
00966 IN
PCM_KEY_NODE Node,
00967 IN
PACCESS_STATE AccessState,
00968 IN KPROCESSOR_MODE AccessMode,
00969 IN ULONG Attributes,
00970 IN
PCM_PARSE_CONTEXT Context,
00971 IN BOOLEAN CompleteKeyCached,
00972 IN OUT
PCM_KEY_CONTROL_BLOCK *CachedKcb,
00973 IN PUNICODE_STRING KeyName,
00974 OUT PVOID *Object
00975 )
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013 {
01014
NTSTATUS status;
01015
PCM_KEY_BODY pbody;
01016
PCM_KEY_CONTROL_BLOCK kcb;
01017
KPROCESSOR_MODE mode;
01018 BOOLEAN BackupRestore;
01019
01020
CMLOG(
CML_FLOW,
CMS_PARSE) {
01021 KdPrint((
"CmpDoOpen:\n"));
01022 }
01023
if (ARGUMENT_PRESENT(Context)) {
01024
01025
01026
01027
01028
if (Context->CreateLink) {
01029
01030
01031
01032
01033
return STATUS_ACCESS_DENIED;
01034
01035 }
else if (Context->CreateOptions & REG_OPTION_CREATE_LINK) {
01036
01037
01038
01039
01040
return STATUS_OBJECT_NAME_COLLISION;
01041
01042 }
else {
01043
01044
01045
01046 Context->Disposition = REG_OPENED_EXISTING_KEY;
01047 }
01048 }
01049
01050
01051
01052
01053
if (CompleteKeyCached) {
01054
01055
01056
01057
if ((*CachedKcb)->Flags &
KEY_SYM_LINK && !(Attributes & OBJ_OPENLINK)) {
01058
01059
01060
01061
01062
01063
LOCK_KCB_TREE();
01064
if ((*CachedKcb)->ExtFlags &
CM_KCB_SYM_LINK_FOUND) {
01065
kcb = (*CachedKcb)->ValueCache.RealKcb;
01066
01067
if (
kcb->Delete ==
TRUE) {
01068
01069
01070
01071
01072
01073
CmpCleanUpKcbValueCache(*CachedKcb);
01074
UNLOCK_KCB_TREE();
01075
return(STATUS_REPARSE);
01076 }
01077
01078
if (!
CmpReferenceKeyControlBlock(
kcb)) {
01079
UNLOCK_KCB_TREE();
01080
return STATUS_INSUFFICIENT_RESOURCES;
01081 }
01082 }
else {
01083
UNLOCK_KCB_TREE();
01084
return(STATUS_REPARSE);
01085 }
01086
UNLOCK_KCB_TREE();
01087 }
else {
01088
01089
01090
01091
LOCK_KCB_TREE();
01092
kcb = *CachedKcb;
01093
if (!
CmpReferenceKeyControlBlock(
kcb)) {
01094
UNLOCK_KCB_TREE();
01095
return STATUS_INSUFFICIENT_RESOURCES;
01096 }
01097
UNLOCK_KCB_TREE();
01098 }
01099 }
else {
01100
01101
01102
01103
01104
01105
if (Node->Flags &
KEY_SYM_LINK && !(Attributes & OBJ_OPENLINK)) {
01106
01107
01108
01109
kcb =
CmpCreateKeyControlBlock(
Hive,
Cell, Node, *CachedKcb,
FALSE,
KeyName);
01110
if (
kcb ==
NULL) {
01111
return STATUS_INSUFFICIENT_RESOURCES;
01112 }
01113
CmpDereferenceKeyControlBlock(
kcb);
01114 *CachedKcb =
kcb;
01115
return(STATUS_REPARSE);
01116 }
01117
01118
01119
01120
01121
01122
kcb =
CmpCreateKeyControlBlock(
Hive,
Cell, Node, *CachedKcb,
FALSE,
KeyName);
01123
if (
kcb ==
NULL) {
01124
return STATUS_INSUFFICIENT_RESOURCES;
01125 }
01126
ASSERT(
kcb->Delete ==
FALSE);
01127
01128 *CachedKcb =
kcb;
01129 }
01130
01131
01132
01133
01134 status =
ObCreateObject(AccessMode,
01135
CmpKeyObjectType,
01136
NULL,
01137 AccessMode,
01138
NULL,
01139
sizeof(
CM_KEY_BODY),
01140 0,
01141 0,
01142 Object);
01143
01144
if (
NT_SUCCESS(status)) {
01145
01146 pbody = (
PCM_KEY_BODY)(*Object);
01147
01148
CMLOG(
CML_MINOR,
CMS_POOL|
CMS_PARSE) {
01149 KdPrint((
"CmpDoOpen: object allocated at:%08lx\n", pbody));
01150 }
01151
01152
01153
01154
01155
01156 pbody = (
PCM_KEY_BODY)(*Object);
01157
01158
if (
kcb->Flags &
KEY_PREDEF_HANDLE) {
01159 pbody->
Type =
kcb->ValueCache.Count;
01160 pbody->
KeyControlBlock =
kcb;
01161
return(STATUS_PREDEFINED_HANDLE);
01162 }
else {
01163
01164
01165
01166 pbody->
Type =
KEY_BODY_TYPE;
01167 pbody->
KeyControlBlock =
kcb;
01168 pbody->
NotifyBlock =
NULL;
01169 pbody->
Process =
PsGetCurrentProcess();
01170
ENLIST_KEYBODY_IN_KEYBODY_LIST(pbody);
01171 }
01172
01173 }
else {
01174
01175
01176
01177
01178
CmpDereferenceKeyControlBlock(
kcb);
01179
return status;
01180 }
01181
01182
01183
01184
01185 BackupRestore =
FALSE;
01186
if (ARGUMENT_PRESENT(Context)) {
01187
if (Context->CreateOptions & REG_OPTION_BACKUP_RESTORE) {
01188 BackupRestore =
TRUE;
01189 }
01190 }
01191
01192 status = STATUS_SUCCESS;
01193
01194
if (BackupRestore ==
TRUE) {
01195
01196
01197
01198
01199
01200 AccessState->RemainingDesiredAccess = 0;
01201 AccessState->PreviouslyGrantedAccess = 0;
01202
01203 mode = KeGetPreviousMode();
01204
01205
if (
SeSinglePrivilegeCheck(
SeBackupPrivilege, mode)) {
01206 AccessState->PreviouslyGrantedAccess |=
01207 KEY_READ | ACCESS_SYSTEM_SECURITY;
01208 }
01209
01210
if (
SeSinglePrivilegeCheck(
SeRestorePrivilege, mode)) {
01211 AccessState->PreviouslyGrantedAccess |=
01212 KEY_WRITE | ACCESS_SYSTEM_SECURITY | WRITE_DAC | WRITE_OWNER;
01213 }
01214
01215
if (AccessState->PreviouslyGrantedAccess == 0) {
01216
01217
01218
01219
01220
01221
CMLOG(
CML_FLOW,
CMS_PARSE) {
01222 KdPrint((
"CmpDoOpen for backup restore: access denied\n"));
01223 }
01224
ObDereferenceObject(*Object);
01225
return STATUS_ACCESS_DENIED;
01226 }
01227
01228 }
else {
01229
01230
if (!
ObCheckObjectAccess(*Object,
01231 AccessState,
01232
TRUE,
01233 AccessMode,
01234 &status))
01235 {
01236
01237
01238
01239
01240
CMLOG(
CML_FLOW,
CMS_PARSE) {
01241 KdPrint((
"CmpDoOpen: access denied\n"));
01242 }
01243
ObDereferenceObject(*Object);
01244 }
01245 }
01246
01247
return status;
01248 }
01249
01250
01251
NTSTATUS
01252 CmpCreateLinkNode(
01253 IN
PHHIVE Hive,
01254 IN HCELL_INDEX Cell,
01255 IN
PACCESS_STATE AccessState,
01256 IN UNICODE_STRING Name,
01257 IN KPROCESSOR_MODE AccessMode,
01258 IN ULONG Attributes,
01259 IN
PCM_PARSE_CONTEXT Context,
01260 IN
PCM_KEY_CONTROL_BLOCK ParentKcb,
01261 OUT PVOID *Object
01262 )
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301 {
01302
NTSTATUS Status;
01303
PCELL_DATA Parent;
01304
PCELL_DATA Link;
01305
PCELL_DATA CellData;
01306
HCELL_INDEX LinkCell;
01307
HCELL_INDEX KeyCell;
01308
HCELL_INDEX ChildCell;
01309
PCM_KEY_CONTROL_BLOCK kcb = ParentKcb;
01310
PCM_KEY_BODY KeyBody;
01311 LARGE_INTEGER systemtime;
01312
01313
CMLOG(
CML_FLOW,
CMS_PARSE) {
01314 KdPrint((
"CmpCreateLinkNode:\n"));
01315 }
01316
01317
if (
Hive != &
CmpMasterHive->
Hive) {
01318
CMLOG(
CML_MAJOR,
CMS_PARSE) {
01319 KdPrint((
"CmpCreateLinkNode: attempt to create link node in\n"));
01320 KdPrint((
" non-master hive %08lx\n",
Hive));
01321 }
01322
return(STATUS_ACCESS_DENIED);
01323 }
01324
01325
01326
01327
01328
01329
01330
01331 LinkCell =
HvAllocateCell(
Hive,
CmpHKeyNodeSize(
Hive, &
Name),
Stable);
01332
if (LinkCell ==
HCELL_NIL) {
01333
return STATUS_INSUFFICIENT_RESOURCES;
01334 }
01335
01336 KeyCell = Context->ChildHive.KeyCell;
01337
01338
if (KeyCell !=
HCELL_NIL) {
01339
01340
01341
01342
01343 ChildCell=KeyCell;
01344
01345
01346
01347
01348
01349
01350 CellData =
HvGetCell(Context->ChildHive.KeyHive, ChildCell);
01351 CellData->
u.
KeyNode.
Parent = LinkCell;
01352 CellData->
u.
KeyNode.
Flags |=
KEY_HIVE_ENTRY |
KEY_NO_DELETE;
01353
Status =
CmpDoOpen( Context->ChildHive.KeyHive,
01354 KeyCell,
01355 (
PCM_KEY_NODE)
HvGetCell(Context->ChildHive.KeyHive,KeyCell),
01356 AccessState,
01357 AccessMode,
01358 Attributes,
01359
NULL,
01360
FALSE,
01361 &
kcb,
01362 &
Name,
01363 Object );
01364 }
else {
01365
01366
01367
01368
01369
01370
01371
Status =
CmpDoCreateChild( Context->ChildHive.KeyHive,
01372
Cell,
01373
NULL,
01374 AccessState,
01375 &
Name,
01376 AccessMode,
01377 Context,
01378 ParentKcb,
01379
KEY_HIVE_ENTRY |
KEY_NO_DELETE,
01380 &ChildCell,
01381 Object );
01382
01383
if (
NT_SUCCESS(
Status)) {
01384
01385
01386
01387
01388
01389 Context->ChildHive.KeyHive->BaseBlock->RootCell = ChildCell;
01390 }
01391
01392 }
01393
if (
NT_SUCCESS(
Status)) {
01394
01395
01396
01397
01398
01399
01400 CellData =
HvGetCell(Context->ChildHive.KeyHive, ChildCell);
01401 CellData->
u.
KeyNode.
Parent = LinkCell;
01402 CellData->
u.
KeyNode.
Flags |=
KEY_HIVE_ENTRY |
KEY_NO_DELETE;
01403
01404
01405
01406
01407 Link =
HvGetCell(
Hive, LinkCell);
01408 Link->
u.
KeyNode.
Signature =
CM_LINK_NODE_SIGNATURE;
01409 Link->
u.
KeyNode.
Flags =
KEY_HIVE_EXIT |
KEY_NO_DELETE;
01410 Link->
u.
KeyNode.
Parent =
Cell;
01411 Link->
u.
KeyNode.
NameLength =
CmpCopyName(
Hive, Link->
u.
KeyNode.
Name, &
Name);
01412
if (Link->
u.
KeyNode.
NameLength <
Name.Length) {
01413 Link->
u.
KeyNode.
Flags |=
KEY_COMP_NAME;
01414 }
01415
01416
KeQuerySystemTime(&systemtime);
01417 Link->
u.
KeyNode.
LastWriteTime = systemtime;
01418
01419
01420
01421
01422 Link->
u.
KeyNode.
SubKeyCounts[
Stable] = 0;
01423 Link->
u.
KeyNode.
SubKeyCounts[
Volatile] = 0;
01424 Link->
u.
KeyNode.
SubKeyLists[
Stable] =
HCELL_NIL;
01425 Link->
u.
KeyNode.
SubKeyLists[
Volatile] =
HCELL_NIL;
01426 Link->
u.
KeyNode.
ValueList.
Count = 0;
01427 Link->
u.
KeyNode.
ValueList.
List =
HCELL_NIL;
01428 Link->
u.
KeyNode.
ClassLength = 0;
01429
01430
01431
01432
01433
01434 Link->
u.
KeyNode.
ChildHiveReference.
KeyHive = Context->ChildHive.KeyHive;
01435 Link->
u.
KeyNode.
ChildHiveReference.
KeyCell = ChildCell;
01436
01437
01438
01439
01440
if (!
CmpAddSubKey(
Hive,
Cell, LinkCell)) {
01441
HvFreeCell(
Hive, LinkCell);
01442
return STATUS_INSUFFICIENT_RESOURCES;
01443 }
01444
01445
01446
01447
01448 Parent =
HvGetCell(
Hive,
Cell);
01449
01450
01451
01452
01453
01454
if (Parent->
u.
KeyNode.
MaxNameLen <
Name.Length) {
01455 Parent->
u.
KeyNode.
MaxNameLen =
Name.Length;
01456 }
01457
01458
if (Parent->
u.
KeyNode.
MaxClassLen < Context->Class.Length) {
01459 Parent->
u.
KeyNode.
MaxClassLen = Context->Class.Length;
01460 }
01461
01462
01463
01464
01465
ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
01466 KeyBody = (
PCM_KEY_BODY)(*Object);
01467
CmpCleanUpSubKeyInfo (KeyBody->
KeyControlBlock->
ParentKcb);
01468
01469 }
else {
01470
HvFreeCell(
Hive, LinkCell);
01471 }
01472
return(
Status);
01473 }
01474
01475 BOOLEAN
01476 CmpGetSymbolicLink(
01477 IN
PHHIVE Hive,
01478 IN
PCM_KEY_NODE Node,
01479 IN OUT PUNICODE_STRING ObjectName,
01480 IN OUT
PCM_KEY_CONTROL_BLOCK SymbolicKcb,
01481 IN PUNICODE_STRING RemainingName OPTIONAL
01482 )
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513 {
01514
NTSTATUS Status;
01515
HCELL_INDEX LinkCell;
01516
PHCELL_INDEX Index;
01517
PCM_KEY_VALUE LinkValue;
01518 PWSTR LinkName;
01519 PWSTR NewBuffer;
01520 ULONG Length;
01521 ULONG ValueLength;
01522
extern ULONG
CmpHashTableSize;
01523
extern PCM_KEY_HASH *
CmpCacheTable;
01524 PUNICODE_STRING ConstructedName;
01525 ULONG ConvKey=0;
01526
PCM_KEY_HASH KeyHash;
01527
PCM_KEY_CONTROL_BLOCK RealKcb;
01528 BOOLEAN KcbFound =
FALSE;
01529 ULONG Cnt;
01530 WCHAR *Cp;
01531 WCHAR *Cp2;
01532
USHORT TotalLevels;
01533 BOOLEAN FreeConstructedName =
FALSE;
01534
01535
LOCK_KCB_TREE();
01536
if (SymbolicKcb->ExtFlags &
CM_KCB_SYM_LINK_FOUND) {
01537
01538
01539
01540 ConstructedName =
CmpConstructName(SymbolicKcb->ValueCache.RealKcb);
01541
if (ConstructedName) {
01542 FreeConstructedName =
TRUE;
01543 LinkName = ConstructedName->Buffer;
01544 ValueLength = ConstructedName->Length;
01545 Length = (
USHORT)ValueLength +
sizeof(WCHAR);
01546 }
01547 }
01548
UNLOCK_KCB_TREE();
01549
01550
if (FreeConstructedName ==
FALSE) {
01551
01552
01553
01554 LinkCell =
CmpFindValueByName(
Hive,
01555 Node,
01556 &
CmSymbolicLinkValueName);
01557
if (LinkCell ==
HCELL_NIL) {
01558
CMLOG(
CML_MINOR,
CMS_PARSE) {
01559 KdPrint((
"CmpGetSymbolicLink: couldn't open symbolic link\n"));
01560 }
01561
return(
FALSE);
01562 }
01563
01564 LinkValue = (
PCM_KEY_VALUE)
HvGetCell(
Hive, LinkCell);
01565
01566
if (LinkValue->
Type != REG_LINK) {
01567
CMLOG(
CML_MINOR,
CMS_PARSE) {
01568 KdPrint((
"CmpGetSymbolicLink: link value is wrong type: %08lx", LinkValue->
Type));
01569 }
01570
return(
FALSE);
01571 }
01572
01573 LinkName = (PWSTR)
HvGetCell(
Hive, LinkValue->
Data);
01574
01575
CmpIsHKeyValueSmall(ValueLength, LinkValue->
DataLength);
01576 Length = (
USHORT)ValueLength +
sizeof(WCHAR);
01577
01578
01579
01580
01581 Cp = LinkName;
01582 TotalLevels = 0;
01583
for (Cnt=0; Cnt<ValueLength; Cnt +=
sizeof(WCHAR)) {
01584
if (*Cp != OBJ_NAME_PATH_SEPARATOR) {
01585 ConvKey = 37 * ConvKey + (ULONG)
RtlUpcaseUnicodeChar(*Cp);
01586 }
else {
01587 TotalLevels++;
01588 }
01589 ++Cp;
01590 }
01591
01592
01593 KeyHash =
GET_HASH_ENTRY(
CmpCacheTable, ConvKey);
01594
01595
LOCK_KCB_TREE();
01596
while (KeyHash) {
01597 RealKcb = CONTAINING_RECORD(KeyHash,
CM_KEY_CONTROL_BLOCK, KeyHash);
01598
if ((ConvKey == KeyHash->
ConvKey) && (TotalLevels == RealKcb->
TotalLevels)) {
01599 ConstructedName =
CmpConstructName(RealKcb);
01600
if (ConstructedName) {
01601 FreeConstructedName =
TRUE;
01602
if (ConstructedName->Length == ValueLength) {
01603 KcbFound =
TRUE;
01604 Cp = LinkName;
01605 Cp2 = ConstructedName->Buffer;
01606
for (Cnt=0; Cnt<ConstructedName->Length; Cnt +=
sizeof(WCHAR)) {
01607
if (
RtlUpcaseUnicodeChar(*Cp) !=
RtlUpcaseUnicodeChar(*Cp2)) {
01608 KcbFound =
FALSE;
01609
break;
01610 }
01611 ++Cp;
01612 ++Cp2;
01613 }
01614
if (KcbFound) {
01615
01616
01617
01618
01619
01620
01621
if (
CmpReferenceKeyControlBlock(RealKcb)) {
01622
01623
01624
01625
01626
CmpCleanUpKcbValueCache(SymbolicKcb);
01627
01628 SymbolicKcb->ExtFlags |=
CM_KCB_SYM_LINK_FOUND;
01629 SymbolicKcb->ValueCache.RealKcb = RealKcb;
01630 }
else {
01631
01632
01633
01634
01635 }
01636
break;
01637 }
01638 }
01639 }
else {
01640
break;
01641 }
01642 }
01643
if (FreeConstructedName) {
01644
ExFreePoolWithTag(ConstructedName, CM_NAME_TAG |
PROTECTED_POOL);
01645 FreeConstructedName =
FALSE;
01646 }
01647 KeyHash = KeyHash->
NextHash;
01648 }
01649
UNLOCK_KCB_TREE();
01650 }
01651
01652
if (ARGUMENT_PRESENT(RemainingName)) {
01653 Length += RemainingName->Length +
sizeof(WCHAR);
01654 }
01655
01656
01657
01658
01659
01660
if( Length>0xFFFF ) {
01661
if (FreeConstructedName) {
01662
ExFreePoolWithTag(ConstructedName, CM_NAME_TAG |
PROTECTED_POOL);
01663 FreeConstructedName =
FALSE;
01664 }
01665
01666
return(
FALSE);
01667 }
01668
01669
if (Length > ObjectName->MaximumLength) {
01670 UNICODE_STRING NewObjectName;
01671
01672
01673
01674
01675
01676 NewBuffer =
ExAllocatePool(
PagedPool, Length);
01677
if (NewBuffer ==
NULL) {
01678
CMLOG(
CML_MINOR,
CMS_PARSE) {
01679 KdPrint((
"CmpGetSymbolicLink: couldn't allocate new name buffer\n"));
01680 }
01681
if (FreeConstructedName) {
01682
ExFreePoolWithTag(ConstructedName, CM_NAME_TAG |
PROTECTED_POOL);
01683 FreeConstructedName =
FALSE;
01684 }
01685
return(
FALSE);
01686 }
01687
01688 NewObjectName.Buffer = NewBuffer;
01689 NewObjectName.MaximumLength = (
USHORT)Length;
01690 NewObjectName.Length = (
USHORT)ValueLength;
01691 RtlCopyMemory(NewBuffer, LinkName, ValueLength);
01692
CMLOG(
CML_FLOW,
CMS_PARSE) {
01693 KdPrint((
"CmpGetSymbolicLink: LinkName is %wZ\n", ObjectName));
01694
if (ARGUMENT_PRESENT(RemainingName)) {
01695 KdPrint((
" RemainingName is %wZ\n", RemainingName));
01696 }
else {
01697 KdPrint((
" RemainingName is NULL\n"));
01698 }
01699 }
01700
01701
if (ARGUMENT_PRESENT(RemainingName)) {
01702 NewBuffer[ ValueLength /
sizeof(WCHAR) ] = OBJ_NAME_PATH_SEPARATOR;
01703 NewObjectName.Length +=
sizeof(WCHAR);
01704
Status =
RtlAppendUnicodeStringToString(&NewObjectName, RemainingName);
01705
ASSERT(
NT_SUCCESS(
Status));
01706 }
01707
01708
ExFreePool(ObjectName->Buffer);
01709 *ObjectName = NewObjectName;
01710 }
else {
01711
01712
01713
01714
01715
01716
01717 ObjectName->Length = (
USHORT)ValueLength;
01718
if (ARGUMENT_PRESENT(RemainingName)) {
01719 RtlMoveMemory(&ObjectName->Buffer[(ValueLength /
sizeof(WCHAR)) + 1],
01720 RemainingName->Buffer,
01721 RemainingName->Length);
01722 ObjectName->Buffer[ValueLength /
sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR;
01723 ObjectName->Length += RemainingName->Length +
sizeof(WCHAR);
01724 }
01725 RtlCopyMemory(ObjectName->Buffer, LinkName, ValueLength);
01726 }
01727 ObjectName->Buffer[ObjectName->Length /
sizeof(WCHAR)] = UNICODE_NULL;
01728
01729
if (FreeConstructedName) {
01730
ExFreePoolWithTag(ConstructedName, CM_NAME_TAG |
PROTECTED_POOL);
01731 }
01732
return(
TRUE);
01733 }
01734
01735
01736 ULONG
01737 CmpComputeHashValue(
01738 IN PCM_HASH_ENTRY HashStack,
01739 IN OUT ULONG *TotalSubkeys,
01740 IN ULONG BaseConvKey,
01741 IN PUNICODE_STRING RemainingName
01742 )
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767 {
01768 ULONG TotalRemainingSubkeys=0;
01769 ULONG TotalKeys=0;
01770 ULONG ConvKey=BaseConvKey;
01771
USHORT Cnt;
01772 WCHAR *Cp;
01773 WCHAR *Begin;
01774
USHORT Length;
01775
01776
if (RemainingName->Length) {
01777 Cp = RemainingName->Buffer;
01778 Cnt = RemainingName->Length;
01779
01780
01781
01782
while (*Cp == OBJ_NAME_PATH_SEPARATOR) {
01783 Cp++;
01784 Cnt -=
sizeof(WCHAR);
01785 }
01786 Begin = Cp;
01787 Length = 0;
01788
01789 HashStack[TotalRemainingSubkeys].KeyName.Buffer = Cp;
01790
01791
while (Cnt){
01792
if ( *Cp == OBJ_NAME_PATH_SEPARATOR ) {
01793
if (TotalRemainingSubkeys <
CM_HASH_STACK_SIZE) {
01794 HashStack[TotalRemainingSubkeys].ConvKey = ConvKey;
01795
01796
01797
01798
01799
01800 HashStack[TotalRemainingSubkeys].KeyName.Length = Length;
01801 Length = 0;
01802 TotalRemainingSubkeys++;
01803 }
01804
01805 TotalKeys++;
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
while(*Cp == OBJ_NAME_PATH_SEPARATOR){
01816 Cp++;
01817 Cnt -=
sizeof(WCHAR);
01818 }
01819 HashStack[TotalRemainingSubkeys].KeyName.Buffer = Cp;
01820
01821 }
else {
01822 ConvKey = 37 * ConvKey + (ULONG)
RtlUpcaseUnicodeChar(*Cp);
01823
01824
01825
01826
01827 Cp++;
01828 Cnt -=
sizeof(WCHAR);
01829 Length +=
sizeof(WCHAR);
01830
01831 }
01832
01833
01834 }
01835
01836
01837
01838
01839
01840
if (TotalRemainingSubkeys <
CM_HASH_STACK_SIZE) {
01841 HashStack[TotalRemainingSubkeys].ConvKey = ConvKey;
01842 HashStack[TotalRemainingSubkeys].KeyName.Length = Length;
01843 TotalRemainingSubkeys++;
01844 }
01845 TotalKeys++;
01846
01847 (*TotalSubkeys) = TotalKeys;
01848 }
01849
01850
return(TotalRemainingSubkeys);
01851 }
01852
NTSTATUS
01853 CmpCacheLookup(
01854 IN PCM_HASH_ENTRY HashStack,
01855 IN ULONG TotalRemainingSubkeys,
01856 OUT ULONG *MatchRemainSubkeyLevel,
01857 IN OUT
PCM_KEY_CONTROL_BLOCK *Kcb,
01858 OUT PUNICODE_STRING RemainingName,
01859 OUT
PHHIVE *Hive,
01860 OUT HCELL_INDEX *Cell
01861 )
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892 {
01893 LONG i;
01894 LONG j;
01895
NTSTATUS status = STATUS_SUCCESS;
01896 ULONG CurrentLevel;
01897
PCM_KEY_HASH Current;
01898
PCM_KEY_CONTROL_BLOCK BaseKcb;
01899
PCM_KEY_CONTROL_BLOCK CurrentKcb;
01900
PCM_KEY_CONTROL_BLOCK ParentKcb;
01901 BOOLEAN Found =
FALSE;
01902
01903 BaseKcb = *Kcb;
01904 CurrentLevel = TotalRemainingSubkeys + BaseKcb->
TotalLevels + 1;
01905
01906
for(i = TotalRemainingSubkeys-1; i>=0; i--) {
01907
01908
01909
01910
01911
01912
01913 CurrentLevel--;
01914
01915 Current =
GET_HASH_ENTRY(
CmpCacheTable, HashStack[i].ConvKey);
01916
01917
while (Current) {
01918
ASSERT_KEY_HASH(Current);
01919
01920
01921
01922
01923 CurrentKcb = (CONTAINING_RECORD(Current,
CM_KEY_CONTROL_BLOCK, KeyHash));
01924
01925
if (CurrentKcb->
TotalLevels == CurrentLevel) {
01926
01927
01928
01929
01930 Found =
TRUE;
01931 ParentKcb = CurrentKcb;
01932
for (j=i; j>=0; j--) {
01933
if (HashStack[j].ConvKey == ParentKcb->
ConvKey) {
01934
01935
01936
01937 LONG Result;
01938 UNICODE_STRING TmpNodeName;
01939
01940
if (ParentKcb->
NameBlock->
Compressed) {
01941 Result =
CmpCompareCompressedName(&(HashStack[j].
KeyName),
01942 ParentKcb->
NameBlock->
Name,
01943 ParentKcb->
NameBlock->
NameLength);
01944 }
else {
01945 TmpNodeName.Buffer = ParentKcb->
NameBlock->
Name;
01946 TmpNodeName.Length = ParentKcb->
NameBlock->
NameLength;
01947 TmpNodeName.MaximumLength = ParentKcb->
NameBlock->
NameLength;
01948
01949 Result =
RtlCompareUnicodeString (&(HashStack[j].
KeyName),
01950 &TmpNodeName,
01951
TRUE);
01952 }
01953
01954
if (Result) {
01955 Found =
FALSE;
01956
break;
01957 }
01958 ParentKcb = ParentKcb->
ParentKcb;
01959 }
else {
01960 Found =
FALSE;
01961
break;
01962 }
01963 }
01964
if (Found) {
01965
01966
01967
01968
if (BaseKcb == ParentKcb) {
01969
if (CurrentKcb->ParentKcb->Delete) {
01970
01971
01972
01973
01974
01975
ASSERT (CurrentKcb->ExtFlags &
CM_KCB_KEY_NON_EXIST);
01976
01977
01978
01979
01980
01981
01982
01983
if (CurrentKcb->RefCount == 0) {
01984
01985
01986
01987
CmpRemoveFromDelayedClose(CurrentKcb);
01988
CmpCleanUpKcbCacheWithLock(CurrentKcb);
01989 }
else {
01990
01991
01992
01993
01994 CurrentKcb->Delete =
TRUE;
01995
CmpRemoveKeyControlBlock(CurrentKcb);
01996 }
01997 Found =
FALSE;
01998
break;
01999 }
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009
while ((RemainingName->Length > 0) &&
02010 (RemainingName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)) {
02011 RemainingName->Buffer++;
02012 RemainingName->Length -=
sizeof(WCHAR);
02013 }
02014
02015
02016
02017
02018
for(j=0; j<=i; j++) {
02019 RemainingName->Buffer += HashStack[j].KeyName.Length/
sizeof(WCHAR) + 1;
02020 RemainingName->Length -= HashStack[j].KeyName.Length +
sizeof(WCHAR);
02021 }
02022
02023
02024
02025
02026 *Kcb = CurrentKcb;
02027 *
Hive = CurrentKcb->KeyHive;
02028 *
Cell = CurrentKcb->KeyCell;
02029
break;
02030 }
else {
02031 Found =
FALSE;
02032 }
02033 }
02034 }
02035 Current = Current->
NextHash;
02036 }
02037
02038
if (Found) {
02039
break;
02040 }
02041 }
02042
02043
02044
02045
02046
02047
if (!
CmpReferenceKeyControlBlock(*Kcb)) {
02048 status = STATUS_INSUFFICIENT_RESOURCES;
02049 }
02050 *MatchRemainSubkeyLevel = i+1;
02051
return status;
02052 }
02053
02054
02055
PCM_KEY_CONTROL_BLOCK
02056 CmpAddInfoAfterParseFailure(
02057
PHHIVE Hive,
02058 HCELL_INDEX Cell,
02059
PCM_KEY_NODE Node,
02060
PCM_KEY_CONTROL_BLOCK kcb,
02061 PUNICODE_STRING NodeName
02062 )
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096 {
02097
02098 ULONG TotalSubKeyCounts;
02099 BOOLEAN CreateFakeKcb =
FALSE;
02100 BOOLEAN HintCached;
02101
PCM_KEY_CONTROL_BLOCK ParentKcb;
02102
USHORT i,j,k;
02103
02104
if (!
UseFastIndex(
Hive)) {
02105
02106
02107
02108
return (
kcb);
02109 }
02110
02111 TotalSubKeyCounts = Node->
SubKeyCounts[
Stable] + Node->
SubKeyCounts[
Volatile];
02112
02113
if (TotalSubKeyCounts == 0) {
02114
LOCK_KCB_TREE();
02115
kcb->ExtFlags |=
CM_KCB_NO_SUBKEY;
02116
UNLOCK_KCB_TREE();
02117 }
else if (TotalSubKeyCounts == 1) {
02118
LOCK_KCB_TREE();
02119
if (!(
kcb->ExtFlags &
CM_KCB_SUBKEY_ONE)) {
02120
02121
02122
02123
PCM_KEY_INDEX Index;
02124
PCM_INDEX Hint;
02125
02126
if (Node->
SubKeyCounts[
Stable] == 1) {
02127
Index = (
PCM_KEY_INDEX)
HvGetCell(
Hive, Node->
SubKeyLists[
Stable]);
02128 }
else {
02129
Index = (
PCM_KEY_INDEX)
HvGetCell(
Hive, Node->
SubKeyLists[
Volatile]);
02130 }
02131
02132
if (
Index->Signature ==
CM_KEY_FAST_LEAF) {
02133
PCM_KEY_FAST_INDEX FastIndex;
02134 FastIndex = (
PCM_KEY_FAST_INDEX)
Index;
02135 Hint = &FastIndex->
List[0];
02136
02137
for (k=0; k<
CM_SUBKEY_HINT_LENGTH; k++) {
02138
kcb->NameHint[k] = Hint->
NameHint[k];
02139 }
02140
02141
kcb->ExtFlags |=
CM_KCB_SUBKEY_ONE;
02142 }
02143 }
else {
02144
02145
02146
02147
02148 CreateFakeKcb =
TRUE;
02149 }
02150
UNLOCK_KCB_TREE();
02151 }
else if (TotalSubKeyCounts <
CM_MAX_CACHE_HINT_SIZE) {
02152
LOCK_KCB_TREE();
02153
if (!(
kcb->ExtFlags &
CM_KCB_SUBKEY_HINT)) {
02154
02155
02156
02157
02158 ULONG
Size;
02159
PCM_KEY_INDEX Index;
02160
PCM_INDEX Hint;
02161
PCM_KEY_FAST_INDEX FastIndex;
02162 UCHAR *NameHint;
02163
02164
Size =
sizeof(ULONG) * (Node->
SubKeyCounts[
Stable] + Node->
SubKeyCounts[
Volatile] + 1);
02165
02166
kcb->IndexHint =
ExAllocatePoolWithTag(
PagedPool,
02167
Size,
02168 CM_CACHE_INDEX_TAG |
PROTECTED_POOL);
02169
02170 HintCached =
TRUE;
02171
if (
kcb->IndexHint) {
02172
kcb->IndexHint->Count = Node->
SubKeyCounts[
Stable] + Node->
SubKeyCounts[
Volatile];
02173
02174 NameHint = &(
kcb->IndexHint->NameHint[0]);
02175
02176
for (i = 0; i <
Hive->
StorageTypeCount; i++) {
02177
if(Node->
SubKeyCounts[i]) {
02178
Index = (
PCM_KEY_INDEX)
HvGetCell(
Hive, Node->
SubKeyLists[i]);
02179
for (j=0; j<Node->
SubKeyCounts[i]; j++) {
02180
if (
Index->Signature ==
CM_KEY_FAST_LEAF) {
02181 FastIndex = (
PCM_KEY_FAST_INDEX)
Index;
02182 Hint = &FastIndex->
List[j];
02183
02184
for (k=0; k<
CM_SUBKEY_HINT_LENGTH; k++) {
02185 NameHint[k] = Hint->
NameHint[k];
02186 }
02187 }
else {
02188 HintCached =
FALSE;
02189
break;
02190 }
02191 NameHint +=
CM_SUBKEY_HINT_LENGTH;
02192 }
02193 }
02194 }
02195
02196
if (HintCached) {
02197
kcb->ExtFlags |=
CM_KCB_SUBKEY_HINT;
02198 }
else {
02199
02200
02201
02202
ExFreePoolWithTag(
kcb->IndexHint, CM_CACHE_INDEX_TAG |
PROTECTED_POOL);
02203 }
02204 }
02205 }
else {
02206
02207
02208
02209
02210 CreateFakeKcb =
TRUE;
02211 }
02212
UNLOCK_KCB_TREE();
02213 }
else {
02214 CreateFakeKcb =
TRUE;
02215 }
02216
02217 ParentKcb =
kcb;
02218
02219
if (CreateFakeKcb && (
CmpCacheOnFlag &
CM_CACHE_FAKE_KEY)) {
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
kcb =
CmpCreateKeyControlBlock(
Hive,
02231
Cell,
02232 Node,
02233 ParentKcb,
02234
TRUE,
02235 NodeName);
02236
02237
if (
kcb) {
02238
CmpDereferenceKeyControlBlock(ParentKcb);
02239 ParentKcb =
kcb;
02240 }
02241 }
02242
02243
return (ParentKcb);
02244 }