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
00024
00025 extern BOOLEAN
CmpNoWrite;
00026
00027 extern LIST_ENTRY
CmpHiveListHead;
00028
00029 extern BOOLEAN
CmpProfileLoaded;
00030 extern BOOLEAN
CmpWasSetupBoot;
00031
00032 extern PUCHAR
CmpStashBuffer;
00033 extern ULONG
CmpStashBufferSize;
00034
00035 extern UNICODE_STRING
CmSymbolicLinkValueName;
00036
00037 extern ULONG
CmpGlobalQuotaAllowed;
00038 extern ULONG
CmpGlobalQuotaWarning;
00039
00040
00041
00042
00043
NTSTATUS
00044
CmpSetValueKeyExisting(
00045 IN
PHHIVE Hive,
00046 IN
HCELL_INDEX OldChild,
00047 IN
PCELL_DATA Value,
00048 IN ULONG Type,
00049 IN PVOID Data,
00050 IN ULONG DataSize,
00051 IN ULONG StorageType,
00052 IN ULONG TempData
00053 );
00054
00055
00056
NTSTATUS
00057
CmpSetValueKeyNew(
00058 IN
PHHIVE Hive,
00059 IN
PCM_KEY_NODE Parent,
00060 IN PUNICODE_STRING ValueName,
00061 IN ULONG Type,
00062 IN PVOID Data,
00063 IN ULONG DataSize,
00064 IN ULONG StorageType,
00065 IN ULONG TempData
00066 );
00067
00068
#ifdef ALLOC_PRAGMA
00069
#pragma alloc_text(PAGE,CmDeleteValueKey)
00070
#pragma alloc_text(PAGE,CmEnumerateKey)
00071
#pragma alloc_text(PAGE,CmEnumerateValueKey)
00072
#pragma alloc_text(PAGE,CmFlushKey)
00073
#pragma alloc_text(PAGE,CmQueryKey)
00074
#pragma alloc_text(PAGE,CmQueryValueKey)
00075
#pragma alloc_text(PAGE,CmQueryMultipleValueKey)
00076
#pragma alloc_text(PAGE,CmSetValueKey)
00077
#pragma alloc_text(PAGE,CmpSetValueKeyExisting)
00078
#pragma alloc_text(PAGE,CmpSetValueKeyNew)
00079
#pragma alloc_text(PAGE,CmSetLastWriteTimeKey)
00080
#pragma alloc_text(PAGE,CmLoadKey)
00081
#pragma alloc_text(PAGE,CmUnloadKey)
00082
#pragma alloc_text(PAGE,CmpDoFlushAll)
00083
#pragma alloc_text(PAGE,CmReplaceKey)
00084
00085
#ifdef _WRITE_PROTECTED_REGISTRY_POOL
00086
#pragma alloc_text(PAGE,CmpMarkAllBinsReadOnly)
00087
#endif
00088
00089
#endif
00090
00091
NTSTATUS
00092 CmDeleteValueKey(
00093 IN
PCM_KEY_CONTROL_BLOCK KeyControlBlock,
00094 IN UNICODE_STRING ValueName
00095 )
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 {
00119
NTSTATUS status;
00120
PCM_KEY_NODE pcell;
00121
PCHILD_LIST plist;
00122
PCELL_DATA targetaddress;
00123 ULONG targetindex;
00124 ULONG newcount;
00125
HCELL_INDEX newcell;
00126
HCELL_INDEX ChildCell;
00127
PHHIVE Hive;
00128
HCELL_INDEX Cell;
00129 ULONG realsize;
00130 LARGE_INTEGER systemtime;
00131
00132
CMLOG(
CML_WORKER,
CMS_CM) KdPrint((
"CmDeleteValueKey\n"));
00133
00134
CmpLockRegistryExclusive();
00135
00136
try {
00137
00138
00139
00140
if (KeyControlBlock->Delete) {
00141
return STATUS_KEY_DELETED;
00142 }
00143
00144
Hive = KeyControlBlock->KeyHive;
00145
Cell = KeyControlBlock->KeyCell;
00146 pcell = KeyControlBlock->KeyNode;
00147
00148
00149
CmpMarkAllBinsReadOnly(
Hive);
00150
00151 status = STATUS_OBJECT_NAME_NOT_FOUND;
00152
00153 plist = &(pcell->
ValueList);
00154 ChildCell =
HCELL_NIL;
00155
00156
if (plist->
Count != 0) {
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168 ChildCell =
CmpFindNameInList(
Hive,
00169 plist,
00170 &
ValueName,
00171 &targetaddress,
00172 &targetindex);
00173
00174
if (ChildCell !=
HCELL_NIL) {
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
if (!(
HvMarkCellDirty(
Hive,
Cell) &&
00187
HvMarkCellDirty(
Hive, pcell->
ValueList.
List) &&
00188
HvMarkCellDirty(
Hive, ChildCell)))
00189
00190 {
00191
00192
CmpMarkAllBinsReadOnly(
Hive);
00193
00194
return STATUS_NO_LOG_SPACE;
00195 }
00196
00197
if (!
CmpIsHKeyValueSmall(realsize,targetaddress->
u.
KeyValue.
DataLength)) {
00198
00199
if (!
HvMarkCellDirty(
Hive, targetaddress->
u.
KeyValue.
Data)) {
00200
00201
00202
CmpMarkAllBinsReadOnly(
Hive);
00203
00204
return(STATUS_NO_LOG_SPACE);
00205 }
00206 }
00207
00208 newcount = plist->
Count - 1;
00209
00210
if (newcount > 0) {
00211
PCELL_DATA pvector;
00212
00213
00214
00215
00216 pvector =
HvGetCell(
Hive, plist->
List);
00217
for ( ; targetindex < newcount; targetindex++) {
00218 pvector->
u.
KeyList[ targetindex ] =
00219 pvector->
u.
KeyList[ targetindex+1 ];
00220 }
00221
00222 newcell =
HvReallocateCell(
00223
Hive,
00224 plist->
List,
00225 newcount *
sizeof(
HCELL_INDEX)
00226 );
00227
ASSERT(newcell !=
HCELL_NIL);
00228 plist->
List = newcell;
00229
00230 }
else {
00231
00232
00233
00234
00235
HvFreeCell(
Hive, plist->
List);
00236 }
00237 plist->
Count = newcount;
00238
CmpFreeValue(
Hive, ChildCell);
00239
00240
KeQuerySystemTime(&systemtime);
00241 pcell->
LastWriteTime = systemtime;
00242
00243
if (pcell->
ValueList.
Count == 0) {
00244 pcell->
MaxValueNameLen = 0;
00245 pcell->
MaxValueDataLen = 0;
00246 }
00247
00248
00249
00250
00251
00252
ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
00253
00254
00255
00256
00257
CmpCleanUpKcbValueCache(KeyControlBlock);
00258
00259 KeyControlBlock->ValueCache.Count = plist->
Count;
00260 KeyControlBlock->ValueCache.ValueList = (ULONG_PTR) plist->
List;
00261
00262
CmpReportNotify(
00263 KeyControlBlock,
00264 KeyControlBlock->KeyHive,
00265 KeyControlBlock->KeyCell,
00266 REG_NOTIFY_CHANGE_LAST_SET
00267 );
00268 status = STATUS_SUCCESS;
00269 }
else {
00270 status = STATUS_OBJECT_NAME_NOT_FOUND;
00271 }
00272 }
00273 } finally {
00274
CmpUnlockRegistry();
00275 }
00276
00277
00278
CmpMarkAllBinsReadOnly(
Hive);
00279
00280
return status;
00281 }
00282
00283
00284
NTSTATUS
00285 CmEnumerateKey(
00286 IN
PCM_KEY_CONTROL_BLOCK KeyControlBlock,
00287 IN ULONG Index,
00288 IN KEY_INFORMATION_CLASS KeyInformationClass,
00289 IN PVOID KeyInformation,
00290 IN ULONG Length,
00291 IN PULONG ResultLength
00292 )
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 {
00340
NTSTATUS status;
00341
HCELL_INDEX childcell;
00342
PHHIVE Hive;
00343
HCELL_INDEX Cell;
00344
PCM_KEY_NODE Node;
00345
00346
CMLOG(
CML_WORKER,
CMS_CM) KdPrint((
"CmEnumerateKey\n"));
00347
00348
00349
CmpLockRegistry();
00350
00351
if (KeyControlBlock->Delete) {
00352
CmpUnlockRegistry();
00353
return STATUS_KEY_DELETED;
00354 }
00355
00356
Hive = KeyControlBlock->KeyHive;
00357
Cell = KeyControlBlock->KeyCell;
00358
00359
00360
CmpMarkAllBinsReadOnly(
Hive);
00361
00362
00363
00364
00365
00366 childcell =
CmpFindSubKeyByNumber(
Hive, KeyControlBlock->KeyNode,
Index);
00367
if (childcell ==
HCELL_NIL) {
00368
00369
00370
00371
00372
CmpUnlockRegistry();
00373
00374
00375
CmpMarkAllBinsReadOnly(
Hive);
00376
00377
return STATUS_NO_MORE_ENTRIES;
00378 }
00379
00380 Node = (
PCM_KEY_NODE)
HvGetCell(
Hive,childcell);
00381
00382
try {
00383
00384
00385
00386
00387
00388 status =
CmpQueryKeyData(
Hive,
00389 Node,
00390 KeyInformationClass,
00391 KeyInformation,
00392 Length,
00393 ResultLength);
00394
00395 } except (
EXCEPTION_EXECUTE_HANDLER) {
00396
CmpUnlockRegistry();
00397 status = GetExceptionCode();
00398
00399
00400
CmpMarkAllBinsReadOnly(
Hive);
00401
00402
return status;
00403 }
00404
00405
CmpUnlockRegistry();
00406
00407
00408
CmpMarkAllBinsReadOnly(
Hive);
00409
00410
return status;
00411 }
00412
00413
00414
00415
NTSTATUS
00416 CmEnumerateValueKey(
00417 IN
PCM_KEY_CONTROL_BLOCK KeyControlBlock,
00418 IN ULONG Index,
00419 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
00420 IN PVOID KeyValueInformation,
00421 IN ULONG Length,
00422 IN PULONG ResultLength
00423 )
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471 {
00472
NTSTATUS status;
00473
PHHIVE Hive;
00474
PCM_KEY_NODE Node;
00475
PCELL_DATA ChildList;
00476
PCM_KEY_VALUE ValueData;
00477 BOOLEAN IndexCached;
00478 BOOLEAN ValueCached;
00479
PPCM_CACHED_VALUE ContainingList;
00480
00481
CMLOG(
CML_WORKER,
CMS_CM) KdPrint((
"CmEnumerateValueKey\n"));
00482
00483
00484
00485
00486
00487
00488
CmpLockRegistry();
00489
00490
if (KeyControlBlock->Delete) {
00491
CmpUnlockRegistry();
00492
return STATUS_KEY_DELETED;
00493 }
00494
Hive = KeyControlBlock->KeyHive;
00495 Node = KeyControlBlock->KeyNode;
00496
00497
00498
00499
00500
00501
00502
00503
if (
Index >= KeyControlBlock->ValueCache.Count) {
00504
00505
00506
00507
CmpUnlockRegistry();
00508
return(STATUS_NO_MORE_ENTRIES);
00509 }
00510
00511
00512
CmpMarkAllBinsReadOnly(
Hive);
00513
00514
LOCK_KCB_TREE();
00515
if (KeyControlBlock->ExtFlags &
CM_KCB_SYM_LINK_FOUND) {
00516
00517
00518
00519
00520
CmpDereferenceKeyControlBlockWithLock(KeyControlBlock->ValueCache.RealKcb);
00521 KeyControlBlock->ExtFlags &= ~
CM_KCB_SYM_LINK_FOUND;
00522
00523 KeyControlBlock->ValueCache.Count = KeyControlBlock->KeyNode->ValueList.Count;
00524 KeyControlBlock->ValueCache.ValueList = (ULONG_PTR) KeyControlBlock->KeyNode->ValueList.List;
00525 }
00526
00527 ChildList =
CmpGetValueListFromCache(
Hive, &(KeyControlBlock->ValueCache), &IndexCached);
00528 ValueData =
CmpGetValueKeyFromCache(
Hive, ChildList,
Index, &ContainingList, IndexCached, &ValueCached);
00529
00530
try {
00531
00532
00533
CmpMakeValueCacheReadWrite(ValueCached,
CMP_GET_CACHED_ADDRESS(KeyControlBlock->ValueCache.ValueList));
00534
00535
00536
00537
00538 status =
CmpQueryKeyValueData(
Hive,
00539 ContainingList,
00540 ValueData,
00541 ValueCached,
00542 KeyValueInformationClass,
00543 KeyValueInformation,
00544 Length,
00545 ResultLength);
00546
00547
00548
CmpMakeValueCacheReadOnly(ValueCached,
CMP_GET_CACHED_ADDRESS(KeyControlBlock->ValueCache.ValueList));
00549 } finally {
00550
00551
UNLOCK_KCB_TREE();
00552
CmpUnlockRegistry();
00553 }
00554
00555
00556
CmpMarkAllBinsReadOnly(
Hive);
00557
00558
return status;
00559 }
00560
00561
00562
00563
NTSTATUS
00564 CmFlushKey(
00565 IN
PHHIVE Hive,
00566 IN HCELL_INDEX Cell
00567 )
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593 {
00594
PCMHIVE CmHive;
00595
NTSTATUS status = STATUS_SUCCESS;
00596
extern PCMHIVE CmpMasterHive;
00597
00598
CMLOG(
CML_WORKER,
CMS_CM) KdPrint((
"CmFlushKey\n"));
00599
00600
00601
00602
00603
00604
00605
if (
CmpNoWrite) {
00606
return STATUS_SUCCESS;
00607 }
00608
00609
00610
00611
CmpMarkAllBinsReadOnly(
Hive);
00612
00613 CmHive = CONTAINING_RECORD(
Hive,
CMHIVE,
Hive);
00614
00615
00616
00617
00618
00619
00620
if (CmHive ==
CmpMasterHive) {
00621
CmpDoFlushAll();
00622 }
else {
00623
DCmCheckRegistry(CONTAINING_RECORD(
Hive,
CMHIVE,
Hive));
00624
00625
CmLockHive (CmHive);
00626
00627
if (!
HvSyncHive(
Hive)) {
00628
00629 status = STATUS_REGISTRY_IO_FAILED;
00630
00631
CMLOG(
CML_MAJOR,
CMS_IO_ERROR) {
00632 KdPrint((
"CmFlushKey: HvSyncHive failed\n"));
00633 }
00634 }
00635
00636
CmUnlockHive (CmHive);
00637 }
00638
00639
00640
CmpMarkAllBinsReadOnly(
Hive);
00641
00642
return status;
00643 }
00644
00645
00646
NTSTATUS
00647 CmQueryKey(
00648 IN
PCM_KEY_CONTROL_BLOCK KeyControlBlock,
00649 IN KEY_INFORMATION_CLASS KeyInformationClass,
00650 IN PVOID KeyInformation,
00651 IN ULONG Length,
00652 IN PULONG ResultLength
00653 )
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694 {
00695
NTSTATUS status;
00696
00697
CMLOG(
CML_WORKER,
CMS_CM) KdPrint((
"CmQueryKey\n"));
00698
00699
00700
00701
CmpLockRegistry();
00702
00703
00704
CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
00705
00706
try {
00707
00708
00709
00710
00711
if( KeyInformationClass == KeyNameInformation ) {
00712
if (KeyControlBlock->Delete ) {
00713
00714
00715
00716 status = STATUS_KEY_DELETED;
00717 }
else {
00718 status = STATUS_SUCCESS;
00719 }
00720
00721
if( KeyControlBlock->NameBlock ) {
00722
00723 PUNICODE_STRING
Name;
00724
Name =
CmpConstructName(KeyControlBlock);
00725
if (
Name ==
NULL) {
00726 status = STATUS_INSUFFICIENT_RESOURCES;
00727 }
else {
00728 ULONG requiredlength;
00729 ULONG minimumlength;
00730
USHORT NameLength;
00731 LONG leftlength;
00732
PKEY_INFORMATION pbuffer = (
PKEY_INFORMATION)KeyInformation;
00733
00734 NameLength =
Name->Length;
00735
00736 requiredlength = FIELD_OFFSET(KEY_NAME_INFORMATION,
Name) + NameLength;
00737
00738 minimumlength = FIELD_OFFSET(KEY_NAME_INFORMATION,
Name);
00739
00740 *ResultLength = requiredlength;
00741
if (Length < minimumlength) {
00742
00743 status = STATUS_BUFFER_TOO_SMALL;
00744
00745 }
else {
00746
00747
00748
00749 pbuffer->
KeyNameInformation.NameLength = NameLength;
00750
00751
00752
00753
00754 leftlength = Length - minimumlength;
00755 requiredlength = NameLength;
00756
if (leftlength < (LONG)requiredlength) {
00757 requiredlength = leftlength;
00758 status = STATUS_BUFFER_OVERFLOW;
00759 }
00760
00761
00762
00763
00764 RtlCopyMemory(
00765 &(pbuffer->
KeyNameInformation.Name[0]),
00766
Name->Buffer,
00767 requiredlength
00768 );
00769 }
00770
00771
ExFreePoolWithTag(
Name, CM_NAME_TAG |
PROTECTED_POOL);
00772 }
00773 }
00774 }
else if(KeyControlBlock->Delete ) {
00775
00776
00777
00778 status = STATUS_KEY_DELETED;
00779 }
else {
00780
00781
00782
00783
00784 status =
CmpQueryKeyData(KeyControlBlock->KeyHive,
00785 KeyControlBlock->KeyNode,
00786 KeyInformationClass,
00787 KeyInformation,
00788 Length,
00789 ResultLength);
00790 }
00791
00792 } finally {
00793
CmpUnlockRegistry();
00794 }
00795
00796
00797
CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
00798
00799
return status;
00800 }
00801
00802
00803
NTSTATUS
00804 CmQueryValueKey(
00805 IN
PCM_KEY_CONTROL_BLOCK KeyControlBlock,
00806 IN UNICODE_STRING ValueName,
00807 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
00808 IN PVOID KeyValueInformation,
00809 IN ULONG Length,
00810 IN PULONG ResultLength
00811 )
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851 {
00852
NTSTATUS status;
00853
HCELL_INDEX childcell;
00854
PHCELL_INDEX childindex;
00855
HCELL_INDEX Cell;
00856
PCM_KEY_VALUE ValueData;
00857 ULONG
Index;
00858 BOOLEAN ValueCached;
00859
PPCM_CACHED_VALUE ContainingList;
00860
00861
PAGED_CODE();
00862
CMLOG(
CML_WORKER,
CMS_CM) KdPrint((
"CmQueryValueKey\n"));
00863
00864
00865
CmpLockRegistry();
00866
00867
if (KeyControlBlock->Delete) {
00868
CmpUnlockRegistry();
00869
return STATUS_KEY_DELETED;
00870 }
00871
00872
00873
CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
00874
00875
LOCK_KCB_TREE();
00876
00877
if (KeyControlBlock->ExtFlags &
CM_KCB_SYM_LINK_FOUND) {
00878
00879
00880
00881
00882
CmpDereferenceKeyControlBlockWithLock(KeyControlBlock->ValueCache.RealKcb);
00883 KeyControlBlock->ExtFlags &= ~
CM_KCB_SYM_LINK_FOUND;
00884
00885 KeyControlBlock->ValueCache.Count = KeyControlBlock->KeyNode->ValueList.Count;
00886 KeyControlBlock->ValueCache.ValueList = (ULONG_PTR) KeyControlBlock->KeyNode->ValueList.List;
00887 }
00888
00889
00890
try {
00891
00892
00893
00894
00895 ValueData =
CmpFindValueByNameFromCache(KeyControlBlock->KeyHive,
00896 &(KeyControlBlock->ValueCache),
00897 &
ValueName,
00898 &ContainingList,
00899 &
Index,
00900 &ValueCached
00901 );
00902
if (ValueData) {
00903
00904
00905
CmpMakeValueCacheReadWrite(ValueCached,
CMP_GET_CACHED_ADDRESS(KeyControlBlock->ValueCache.ValueList));
00906
00907
00908
00909
00910
00911 status =
CmpQueryKeyValueData(KeyControlBlock->KeyHive,
00912 ContainingList,
00913 ValueData,
00914 ValueCached,
00915 KeyValueInformationClass,
00916 KeyValueInformation,
00917 Length,
00918 ResultLength);
00919
00920
00921
CmpMakeValueCacheReadOnly(ValueCached,
CMP_GET_CACHED_ADDRESS(KeyControlBlock->ValueCache.ValueList));
00922
00923 }
else {
00924 status = STATUS_OBJECT_NAME_NOT_FOUND;
00925 }
00926
00927 } finally {
00928
UNLOCK_KCB_TREE();
00929
CmpUnlockRegistry();
00930 }
00931
00932
00933
CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
00934
00935
return status;
00936 }
00937
00938
00939
NTSTATUS
00940 CmQueryMultipleValueKey(
00941 IN
PCM_KEY_CONTROL_BLOCK KeyControlBlock,
00942 IN PKEY_VALUE_ENTRY ValueEntries,
00943 IN ULONG EntryCount,
00944 IN PVOID ValueBuffer,
00945 IN OUT PULONG BufferLength,
00946 IN OPTIONAL PULONG ResultLength
00947 )
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977 {
00978
PHHIVE Hive;
00979
NTSTATUS Status;
00980 ULONG i;
00981 UNICODE_STRING CurrentName;
00982
HCELL_INDEX ValueCell;
00983
PCM_KEY_VALUE ValueNode;
00984 ULONG RequiredLength = 0;
00985 ULONG UsedLength = 0;
00986 ULONG DataLength;
00987 BOOLEAN BufferFull =
FALSE;
00988 BOOLEAN Small;
00989 PUCHAR Data;
00990
KPROCESSOR_MODE PreviousMode;
00991
00992
PAGED_CODE();
00993
CMLOG(
CML_WORKER,
CMS_CM) KdPrint((
"CmQueryMultipleValueKey\n"));
00994
00995
00996
CmpLockRegistry();
00997
if (KeyControlBlock->Delete) {
00998
CmpUnlockRegistry();
00999
return STATUS_KEY_DELETED;
01000 }
01001
Hive = KeyControlBlock->KeyHive;
01002
Status = STATUS_SUCCESS;
01003
01004
01005
CmpMarkAllBinsReadOnly(
Hive);
01006
01007 PreviousMode = KeGetPreviousMode();
01008
try {
01009
for (i=0; i < EntryCount; i++) {
01010
01011
01012
01013
if (PreviousMode ==
UserMode) {
01014 CurrentName =
ProbeAndReadUnicodeString(ValueEntries[i].
ValueName);
01015
ProbeForRead(CurrentName.Buffer,CurrentName.Length,
sizeof(WCHAR));
01016 }
else {
01017 CurrentName = *(ValueEntries[i].ValueName);
01018 }
01019 ValueCell =
CmpFindValueByName(
Hive,
01020 KeyControlBlock->KeyNode,
01021 &CurrentName);
01022
if (ValueCell !=
HCELL_NIL) {
01023
01024 ValueNode = (
PCM_KEY_VALUE)
HvGetCell(
Hive, ValueCell);
01025 Small =
CmpIsHKeyValueSmall(DataLength, ValueNode->
DataLength);
01026
01027
01028
01029
01030 UsedLength = (UsedLength +
sizeof(ULONG)-1) & ~(
sizeof(ULONG)-1);
01031 RequiredLength = (RequiredLength +
sizeof(ULONG)-1) & ~(
sizeof(ULONG)-1);
01032
01033
01034
01035
01036
01037
01038
01039
if ((UsedLength + DataLength <= *BufferLength) &&
01040 (!BufferFull)) {
01041
if (DataLength > 0) {
01042
if (Small) {
01043 Data = (PUCHAR)&ValueNode->
Data;
01044 }
else {
01045 Data = (PUCHAR)
HvGetCell(
Hive, ValueNode->
Data);
01046 }
01047 RtlCopyMemory((PUCHAR)
ValueBuffer + UsedLength,
01048 Data,
01049 DataLength);
01050 }
01051 ValueEntries[i].Type = ValueNode->
Type;
01052 ValueEntries[i].DataLength = DataLength;
01053 ValueEntries[i].DataOffset = UsedLength;
01054 UsedLength += DataLength;
01055 }
else {
01056 BufferFull =
TRUE;
01057
Status = STATUS_BUFFER_OVERFLOW;
01058 }
01059 RequiredLength += DataLength;
01060
01061 }
else {
01062
Status = STATUS_OBJECT_NAME_NOT_FOUND;
01063
break;
01064 }
01065 }
01066
01067
if (
NT_SUCCESS(
Status) ||
01068 (
Status == STATUS_BUFFER_OVERFLOW)) {
01069 *BufferLength = UsedLength;
01070
if (ARGUMENT_PRESENT(ResultLength)) {
01071 *ResultLength = RequiredLength;
01072 }
01073 }
01074
01075 } finally {
01076
CmpUnlockRegistry();
01077 }
01078
01079
01080
CmpMarkAllBinsReadOnly(
Hive);
01081
01082
return Status;
01083 }
01084
01085
01086
NTSTATUS
01087 CmSetValueKey(
01088 IN
PCM_KEY_CONTROL_BLOCK KeyControlBlock,
01089 IN PUNICODE_STRING ValueName,
01090 IN ULONG Type,
01091 IN PVOID Data,
01092 IN ULONG DataSize
01093 )
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128 {
01129
NTSTATUS status;
01130
PCM_KEY_NODE parent;
01131
HCELL_INDEX oldchild;
01132 ULONG count;
01133
PHHIVE Hive;
01134
HCELL_INDEX Cell;
01135 ULONG StorageType;
01136 ULONG TempData;
01137 BOOLEAN found;
01138
PCELL_DATA pdata;
01139 LARGE_INTEGER systemtime;
01140 ULONG compareSize,mustChange=
FALSE;
01141
01142
CMLOG(
CML_WORKER,
CMS_CM) KdPrint((
"CmSetValueKey\n"));
01143
01144
CmpLockRegistry();
01145
ASSERT(
sizeof(ULONG) ==
CM_KEY_VALUE_SMALL);
01146
01147
01148
CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
01149
01150
while (
TRUE) {
01151
01152
01153
01154
01155
if (KeyControlBlock->Delete ==
TRUE) {
01156 status = STATUS_KEY_DELETED;
01157
goto Exit;
01158 }
01159
01160
01161
01162
01163
01164
01165
01166
if (KeyControlBlock->KeyNode->Flags &
KEY_SYM_LINK &&
01167 (Type != REG_LINK ||
01168
ValueName ==
NULL ||
01169 !
RtlEqualUnicodeString(&
CmSymbolicLinkValueName,
ValueName,
TRUE)))
01170 {
01171
01172
01173
01174
01175
01176
01177
CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
01178
01179 status = STATUS_ACCESS_DENIED;
01180
goto Exit;
01181 }
01182
01183
01184
01185
01186
Hive = KeyControlBlock->KeyHive;
01187
Cell = KeyControlBlock->KeyCell;
01188 parent = KeyControlBlock->KeyNode;
01189
01190
01191
01192
01193 count = parent->
ValueList.
Count;
01194 found =
FALSE;
01195
01196
if (count > 0) {
01197 oldchild =
CmpFindNameInList(
Hive,
01198 &parent->
ValueList,
01199
ValueName,
01200 &pdata,
01201
NULL);
01202
01203
if (oldchild !=
HCELL_NIL) {
01204 found =
TRUE;
01205 }
01206 }
01207
01208
01209
01210
01211
01212
01213
01214
if (mustChange ==
TRUE) {
01215
break;
01216 }
01217
if ((found) &&
01218 (Type == pdata->
u.
KeyValue.
Type)) {
01219
01220
PCELL_DATA pcmpdata;
01221
01222
if (DataSize == (pdata->
u.
KeyValue.
DataLength & ~
CM_KEY_VALUE_SPECIAL_SIZE)) {
01223
01224
if (DataSize > 0) {
01225
01226
01227
01228
if (DataSize <=
CM_KEY_VALUE_SMALL ) {
01229 pcmpdata = (
PCELL_DATA)&pdata->
u.
KeyValue.
Data;
01230 }
else {
01231 pcmpdata =
HvGetCell(
Hive, pdata->
u.
KeyValue.
Data);
01232 }
01233
01234
try {
01235 compareSize = (ULONG)RtlCompareMemory ((PVOID)pcmpdata,Data,(DataSize & ~
CM_KEY_VALUE_SPECIAL_SIZE));
01236 } except (
EXCEPTION_EXECUTE_HANDLER) {
01237
01238
CMLOG(
CML_API,
CMS_EXCEPTION) {
01239 KdPrint((
"!!CmSetValueKey: code:%08lx\n", GetExceptionCode()));
01240 }
01241 status = GetExceptionCode();
01242
goto Exit;
01243 }
01244 }
else {
01245 compareSize = 0;
01246 }
01247
01248
if (compareSize == DataSize) {
01249 status = STATUS_SUCCESS;
01250
goto Exit;
01251 }
01252 }
01253
01254 }
01255
01256
01257
01258
01259 mustChange=
TRUE;
01260
01261
01262
01263
01264
01265
01266
CmpUnlockRegistry();
01267
CmpLockRegistryExclusive();
01268
01269 }
01270
01271
01272
01273
01274
if (!
HvMarkCellDirty(
Hive,
Cell)) {
01275 status = STATUS_NO_LOG_SPACE;
01276
goto Exit;
01277 }
01278
01279 StorageType =
HvGetCellType(
Cell);
01280
01281
01282
01283
01284 TempData = 0;
01285
if ((DataSize <=
CM_KEY_VALUE_SMALL) &&
01286 (DataSize > 0))
01287 {
01288
try {
01289 RtlMoveMemory(
01290 &TempData,
01291 Data,
01292 DataSize
01293 );
01294 } except (
EXCEPTION_EXECUTE_HANDLER) {
01295
CMLOG(
CML_API,
CMS_EXCEPTION) {
01296 KdPrint((
"!!CmSetValueKey: code:%08lx\n", GetExceptionCode()));
01297 }
01298 status = GetExceptionCode();
01299
goto Exit;
01300 }
01301 }
01302
01303
if (found) {
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313 status =
CmpSetValueKeyExisting(
Hive,
01314 oldchild,
01315 pdata,
01316 Type,
01317 Data,
01318 DataSize,
01319 StorageType,
01320 TempData);
01321
01322 }
else {
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333 status =
CmpSetValueKeyNew(
Hive,
01334 parent,
01335
ValueName,
01336 Type,
01337 Data,
01338 DataSize,
01339 StorageType,
01340 TempData);
01341 }
01342
01343
if (
NT_SUCCESS(status)) {
01344
01345
if (parent->
MaxValueNameLen <
ValueName->Length) {
01346 parent->
MaxValueNameLen =
ValueName->Length;
01347 }
01348
01349
if (parent->
MaxValueDataLen < DataSize) {
01350 parent->
MaxValueDataLen = DataSize;
01351 }
01352
01353
KeQuerySystemTime(&systemtime);
01354 parent->
LastWriteTime = systemtime;
01355
01356
01357
01358
01359
ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
01360
01361
CmpCleanUpKcbValueCache(KeyControlBlock);
01362
01363 KeyControlBlock->ValueCache.Count = parent->
ValueList.
Count;
01364 KeyControlBlock->ValueCache.ValueList = (ULONG_PTR) parent->
ValueList.
List;
01365
01366
CmpReportNotify(KeyControlBlock,
01367 KeyControlBlock->KeyHive,
01368 KeyControlBlock->KeyCell,
01369 REG_NOTIFY_CHANGE_LAST_SET);
01370 }
01371
01372 Exit:
01373
CmpUnlockRegistry();
01374
01375
01376
CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
01377
01378
return status;
01379 }
01380
01381
01382
NTSTATUS
01383 CmpSetValueKeyExisting(
01384 IN
PHHIVE Hive,
01385 IN HCELL_INDEX OldChild,
01386 IN
PCELL_DATA pvalue,
01387 IN ULONG Type,
01388 IN PVOID Data,
01389 IN ULONG DataSize,
01390 IN ULONG StorageType,
01391 IN ULONG TempData
01392 )
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422 {
01423
HCELL_INDEX DataCell;
01424
PCELL_DATA pdata;
01425
HCELL_INDEX NewCell;
01426 ULONG realsize;
01427 BOOLEAN small;
01428 PUCHAR StashBuffer;
01429 ULONG
BufferSize;
01430
01431
ASSERT_CM_LOCK_OWNED();
01432
01433
01434
01435
01436
01437
01438
01439
if (!
HvMarkCellDirty(
Hive, OldChild)) {
01440
return STATUS_NO_LOG_SPACE;
01441 }
01442
01443 small =
CmpIsHKeyValueSmall(realsize, pvalue->u.KeyValue.DataLength);
01444
01445
if (DataSize <=
CM_KEY_VALUE_SMALL) {
01446
01447
01448
01449
01450
if ((! small) && (realsize > 0))
01451 {
01452
01453
01454
01455
if (!
HvMarkCellDirty(
Hive, pvalue->u.KeyValue.Data)) {
01456
return STATUS_NO_LOG_SPACE;
01457 }
01458
HvFreeCell(
Hive, pvalue->u.KeyValue.Data);
01459 }
01460
01461
01462
01463
01464 pvalue->u.KeyValue.DataLength = DataSize +
CM_KEY_VALUE_SPECIAL_SIZE;
01465 pvalue->u.KeyValue.Data = TempData;
01466 pvalue->u.KeyValue.Type = Type;
01467
01468
return STATUS_SUCCESS;
01469
01470 }
else {
01471
01472
01473
01474
01475
01476
01477
01478
01479
if ((! small) && (realsize > 0)) {
01480
01481 DataCell = pvalue->u.KeyValue.Data;
01482
ASSERT(DataCell !=
HCELL_NIL);
01483 pdata =
HvGetCell(
Hive, DataCell);
01484
01485
ASSERT(
HvGetCellSize(
Hive, pdata) > 0);
01486
01487
if (DataSize <= (ULONG)(
HvGetCellSize(
Hive, pdata))) {
01488
01489
01490
01491
01492
01493
01494
01495
01496
if (!
HvMarkCellDirty(
Hive, DataCell)) {
01497
return STATUS_NO_LOG_SPACE;
01498 }
01499
01500 StashBuffer =
NULL;
01501
if (DataSize <=
CmpStashBufferSize) {
01502
01503 StashBuffer =
CmpStashBuffer;
01504
01505 }
else if (DataSize <=
CM_MAX_STASH) {
01506
01507
01508
01509
01510
01511
01512
BufferSize = ((DataSize +
PAGE_SIZE) & ~(
PAGE_SIZE-1));
01513
01514 StashBuffer =
ExAllocatePoolWithTag(
PagedPool,
BufferSize, 'bSmC');
01515
if (StashBuffer !=
NULL) {
01516
ExFreePool(
CmpStashBuffer);
01517
CmpStashBuffer = StashBuffer;
01518
CmpStashBufferSize =
BufferSize;
01519 }
01520 }
01521
01522
if (StashBuffer !=
NULL) {
01523
01524
01525
01526
try {
01527
01528 RtlCopyMemory(
01529 StashBuffer,
01530 Data,
01531 DataSize
01532 );
01533
01534 } except (
EXCEPTION_EXECUTE_HANDLER) {
01535
CMLOG(
CML_API,
CMS_EXCEPTION) {
01536 KdPrint((
"!!CmSetValueKey: code:%08lx\n", GetExceptionCode()));
01537 }
01538
return GetExceptionCode();
01539 }
01540
01541
01542
01543
01544
01545 RtlCopyMemory(
01546 pdata,
01547 StashBuffer,
01548 DataSize
01549 );
01550
01551
ASSERT(StashBuffer !=
NULL);
01552
01553 pvalue->u.KeyValue.DataLength = DataSize;
01554 pvalue->u.KeyValue.Type = Type;
01555
01556
return STATUS_SUCCESS;
01557
01558 }
01559 }
01560 }
01561 }
01562
01563
01564
01565
01566
01567
01568
01569
01570 NewCell =
HvAllocateCell(
Hive, DataSize, StorageType);
01571
01572
if (NewCell ==
HCELL_NIL) {
01573
return STATUS_INSUFFICIENT_RESOURCES;
01574 }
01575
01576
01577
01578
01579 pdata =
HvGetCell(
Hive, NewCell);
01580
try {
01581
01582 RtlMoveMemory(
01583 pdata,
01584 Data,
01585 DataSize
01586 );
01587
01588 } except (
EXCEPTION_EXECUTE_HANDLER) {
01589
CMLOG(
CML_API,
CMS_EXCEPTION) {
01590 KdPrint((
"!!CmSetValueKey: code:%08lx\n", GetExceptionCode()));
01591 }
01592
HvFreeCell(
Hive, NewCell);
01593
return GetExceptionCode();
01594 }
01595
01596
01597
01598
01599
if ((! small) && (realsize > 0)) {
01600
ASSERT(pvalue->u.KeyValue.Data !=
HCELL_NIL);
01601
if (!
HvMarkCellDirty(
Hive, pvalue->u.KeyValue.Data)) {
01602
HvFreeCell(
Hive, NewCell);
01603
return STATUS_NO_LOG_SPACE;
01604 }
01605
HvFreeCell(
Hive, pvalue->u.KeyValue.Data);
01606 }
01607
01608
01609
01610
01611 pvalue->u.KeyValue.DataLength = DataSize;
01612 pvalue->u.KeyValue.Data = NewCell;
01613 pvalue->u.KeyValue.Type = Type;
01614
01615
return STATUS_SUCCESS;
01616 }
01617
01618
NTSTATUS
01619 CmpSetValueKeyNew(
01620 IN
PHHIVE Hive,
01621 IN
PCM_KEY_NODE Parent,
01622 IN PUNICODE_STRING ValueName,
01623 IN ULONG Type,
01624 IN PVOID Data,
01625 IN ULONG DataSize,
01626 IN ULONG StorageType,
01627 IN ULONG TempData
01628 )
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665 {
01666
PCELL_DATA pvalue;
01667
HCELL_INDEX ValueCell;
01668
HCELL_INDEX DataCell;
01669
PCELL_DATA pdata;
01670 ULONG count;
01671
HCELL_INDEX NewCell;
01672 ULONG AllocateSize;
01673
01674
01675
01676
01677
01678
01679
if (Parent->ValueList.Count != 0) {
01680
ASSERT(Parent->ValueList.List !=
HCELL_NIL);
01681
if (!
HvMarkCellDirty(
Hive, Parent->ValueList.List)) {
01682
return STATUS_NO_LOG_SPACE;
01683 }
01684 }
01685
01686
01687
01688
01689 ValueCell =
HvAllocateCell(
01690
Hive,
01691
CmpHKeyValueSize(
Hive,
ValueName),
01692 StorageType
01693 );
01694
01695
if (ValueCell ==
HCELL_NIL) {
01696
return STATUS_INSUFFICIENT_RESOURCES;
01697 }
01698
01699 DataCell =
HCELL_NIL;
01700
if (DataSize >
CM_KEY_VALUE_SMALL) {
01701 DataCell =
HvAllocateCell(
Hive, DataSize, StorageType);
01702
if (DataCell ==
HCELL_NIL) {
01703
HvFreeCell(
Hive, ValueCell);
01704
return STATUS_INSUFFICIENT_RESOURCES;
01705 }
01706 }
01707
01708
01709
01710
01711 pvalue =
HvGetCell(
Hive, ValueCell);
01712 pvalue->
u.
KeyValue.
Signature =
CM_KEY_VALUE_SIGNATURE;
01713
01714
01715
01716
01717
01718
try {
01719
01720
01721
01722
01723 pvalue->
u.
KeyValue.
NameLength =
CmpCopyName(
Hive,
01724 pvalue->
u.
KeyValue.
Name,
01725
ValueName);
01726 } except (
EXCEPTION_EXECUTE_HANDLER) {
01727
CMLOG(
CML_API,
CMS_EXCEPTION) {
01728 KdPrint((
"!!CmSetValueKey: code:%08lx\n", GetExceptionCode()));
01729 }
01730
01731
01732
01733
01734
if (DataCell !=
HCELL_NIL) {
01735
HvFreeCell(
Hive, DataCell);
01736 }
01737
HvFreeCell(
Hive, ValueCell);
01738
return GetExceptionCode();
01739 }
01740
01741
if (pvalue->
u.
KeyValue.
NameLength <
ValueName->Length) {
01742 pvalue->
u.
KeyValue.
Flags =
VALUE_COMP_NAME;
01743 }
else {
01744 pvalue->
u.
KeyValue.
Flags = 0;
01745 }
01746
01747
01748
01749
01750
if (DataSize >
CM_KEY_VALUE_SMALL) {
01751 pdata =
HvGetCell(
Hive, DataCell);
01752
01753
try {
01754
01755 RtlMoveMemory(pdata, Data, DataSize);
01756
01757 } except (
EXCEPTION_EXECUTE_HANDLER) {
01758
CMLOG(
CML_API,
CMS_EXCEPTION) {
01759 KdPrint((
"!!CmSetValueKey: code:%08lx\n", GetExceptionCode()));
01760 }
01761
01762
01763
01764
01765
if (DataCell !=
HCELL_NIL) {
01766
HvFreeCell(
Hive, DataCell);
01767 }
01768
HvFreeCell(
Hive, ValueCell);
01769
return GetExceptionCode();
01770 }
01771
01772 pvalue->
u.
KeyValue.
DataLength = DataSize;
01773 pvalue->
u.
KeyValue.
Data = DataCell;
01774
01775 }
else {
01776 pvalue->
u.
KeyValue.
DataLength = DataSize +
CM_KEY_VALUE_SPECIAL_SIZE;
01777 pvalue->
u.
KeyValue.
Data = TempData;
01778 }
01779
01780
01781
01782
01783 count = Parent->ValueList.Count;
01784 count++;
01785
if (count > 1) {
01786
01787
if (count <
CM_MAX_REASONABLE_VALUES) {
01788
01789
01790
01791
01792
01793
01794 AllocateSize = count *
sizeof(
HCELL_INDEX);
01795 }
else {
01796
01797
01798
01799
01800
01801
01802 AllocateSize =
ROUND_UP(count,
CM_MAX_REASONABLE_VALUES) *
sizeof(
HCELL_INDEX);
01803
if (AllocateSize >
HBLOCK_SIZE) {
01804 AllocateSize =
ROUND_UP(AllocateSize,
HBLOCK_SIZE);
01805 }
01806 }
01807 NewCell =
HvReallocateCell(
01808
Hive,
01809 Parent->ValueList.List,
01810 AllocateSize
01811 );
01812 }
else {
01813 NewCell =
HvAllocateCell(
Hive,
sizeof(
HCELL_INDEX), StorageType);
01814 }
01815
01816
01817
01818
01819
if (NewCell !=
HCELL_NIL) {
01820 Parent->ValueList.List = NewCell;
01821 pdata =
HvGetCell(
Hive, NewCell);
01822
01823 pdata->
u.
KeyList[count-1] = ValueCell;
01824 Parent->ValueList.Count = count;
01825 pvalue->
u.
KeyValue.
Type = Type;
01826
01827
return STATUS_SUCCESS;
01828
01829 }
else {
01830
01831
if (DataCell !=
HCELL_NIL) {
01832
HvFreeCell(
Hive, DataCell);
01833 }
01834
HvFreeCell(
Hive, ValueCell);
01835
return STATUS_INSUFFICIENT_RESOURCES;
01836 }
01837 }
01838
01839
01840
NTSTATUS
01841 CmSetLastWriteTimeKey(
01842 IN
PCM_KEY_CONTROL_BLOCK KeyControlBlock,
01843 IN PLARGE_INTEGER LastWriteTime
01844 )
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865 {
01866
PCM_KEY_NODE parent;
01867
PHHIVE Hive;
01868
HCELL_INDEX Cell;
01869
NTSTATUS status = STATUS_SUCCESS;
01870
01871
CMLOG(
CML_WORKER,
CMS_CM) KdPrint((
"CmSetLastWriteTimeKey\n"));
01872
01873
CmpLockRegistryExclusive();
01874
01875
01876
01877
01878
01879
if (KeyControlBlock->Delete ==
TRUE) {
01880 status = STATUS_KEY_DELETED;
01881
goto Exit;
01882 }
01883
01884
Hive = KeyControlBlock->KeyHive;
01885
Cell = KeyControlBlock->KeyCell;
01886 parent = KeyControlBlock->KeyNode;
01887
if (!
HvMarkCellDirty(
Hive,
Cell)) {
01888 status = STATUS_NO_LOG_SPACE;
01889
goto Exit;
01890 }
01891
01892 parent->
LastWriteTime = *LastWriteTime;
01893
01894 Exit:
01895
CmpUnlockRegistry();
01896
return status;
01897 }
01898
01899
01900
NTSTATUS
01901 CmLoadKey(
01902 IN POBJECT_ATTRIBUTES TargetKey,
01903 IN POBJECT_ATTRIBUTES SourceFile,
01904 IN ULONG Flags
01905 )
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950 {
01951
PCMHIVE NewHive;
01952
NTSTATUS Status;
01953 BOOLEAN Allocate;
01954
REGISTRY_COMMAND Command;
01955 SECURITY_QUALITY_OF_SERVICE ServiceQos;
01956
SECURITY_CLIENT_CONTEXT ClientSecurityContext;
01957
01958
01959
01960
01961
01962
01963
01964
01965 ServiceQos.Length =
sizeof(SECURITY_QUALITY_OF_SERVICE);
01966 ServiceQos.ImpersonationLevel = SecurityImpersonation;
01967 ServiceQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
01968 ServiceQos.EffectiveOnly =
TRUE;
01969
Status =
SeCreateClientSecurity(CONTAINING_RECORD(
KeGetCurrentThread(),
ETHREAD,Tcb),
01970 &ServiceQos,
01971
FALSE,
01972 &ClientSecurityContext);
01973
if (!
NT_SUCCESS(
Status)) {
01974
return(
Status);
01975 }
01976
01977
01978
01979
01980
01981
01982
01983
01984 Command.
RegistryLockAquired =
FALSE;
01985 Command.
Command =
REG_CMD_HIVE_OPEN;
01986 Command.
Allocate =
TRUE;
01987 Command.
FileAttributes = SourceFile;
01988 Command.
ImpersonationContext = &ClientSecurityContext;
01989
01990
CmpWorker(&Command);
01991
Status = Command.
Status;
01992
01993
SeDeleteClientSecurity( &ClientSecurityContext );
01994
01995 NewHive = Command.
CmHive;
01996 Allocate = Command.
Allocate;
01997
01998
if (!
NT_SUCCESS(
Status)) {
01999
if( Command.
RegistryLockAquired ) {
02000
02001
CmpUnlockRegistry();
02002 }
02003
return(
Status);
02004 }
else {
02005
02006
02007
02008
ASSERT( Command.
RegistryLockAquired );
02009 }
02010
02011
02012
02013
02014
if (Flags & REG_NO_LAZY_FLUSH) {
02015 NewHive->
Hive.
HiveFlags |=
HIVE_NOLAZYFLUSH;
02016 }
02017
02018
02019
02020
02021
02022
Status =
CmpLinkHiveToMaster(TargetKey->ObjectName,
02023 TargetKey->RootDirectory,
02024 NewHive,
02025 Allocate,
02026 TargetKey->SecurityDescriptor);
02027
02028 Command.
CmHive = NewHive;
02029
if (
NT_SUCCESS(
Status)) {
02030
02031
02032
02033 Command.
Command =
REG_CMD_ADD_HIVE_LIST;
02034
02035 }
else {
02036
02037
02038
02039 Command.
Command =
REG_CMD_HIVE_CLOSE;
02040 }
02041
CmpWorker(&Command);
02042
02043
02044
02045
02046
if ((
CmpProfileLoaded ==
FALSE) &&
02047 (
CmpWasSetupBoot ==
FALSE)) {
02048
CmpProfileLoaded =
TRUE;
02049
CmpSetGlobalQuotaAllowed();
02050 }
02051
02052
CmpUnlockRegistry();
02053
return(
Status);
02054 }
02055
02056
#if DBG
02057
ULONG
02058 CmpUnloadKeyWorker(
02059
PCM_KEY_CONTROL_BLOCK Current,
02060 PVOID Context1,
02061 PVOID Context2
02062 )
02063 {
02064 PUNICODE_STRING ConstructedName;
02065
if (Current->
KeyHive ==
Context1) {
02066 ConstructedName =
CmpConstructName(Current);
02067
02068
if (ConstructedName) {
02069 KdPrint((
"%wZ\n", ConstructedName));
02070
ExFreePoolWithTag(ConstructedName, CM_NAME_TAG | PROTECTED_POOL);
02071 }
02072 }
02073
return KCB_WORKER_CONTINUE;
02074 }
02075
#endif
02076
02077
02078
NTSTATUS
02079 CmUnloadKey(
02080 IN
PHHIVE Hive,
02081 IN HCELL_INDEX Cell,
02082 IN
PCM_KEY_CONTROL_BLOCK Kcb
02083 )
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110 {
02111
PCMHIVE CmHive;
02112
REGISTRY_COMMAND Command;
02113 BOOLEAN Success;
02114
02115
CMLOG(
CML_WORKER,
CMS_CM) KdPrint((
"CmUnloadKey\n"));
02116
02117
CmpLockRegistryExclusive();
02118
02119
02120
02121
02122
if (
Cell !=
Hive->
BaseBlock->
RootCell) {
02123
CmpUnlockRegistry();
02124
return(STATUS_INVALID_PARAMETER);
02125 }
02126
02127
02128
02129
02130
02131
02132 CmHive = CONTAINING_RECORD(
Hive,
CMHIVE,
Hive);
02133
if ((
CmpSearchForOpenSubKeys(Kcb,
SearchIfExist) != 0) || (Kcb->RefCount != 1)) {
02134
#if DBG
02135
KdPrint((
"List of keys open against hive unload was attempted on:\n"));
02136
CmpSearchKeyControlBlockTree(
02137 CmpUnloadKeyWorker,
02138
Hive,
02139
NULL
02140 );
02141
#endif
02142
CmpUnlockRegistry();
02143
return(STATUS_CANNOT_DELETE);
02144 }
02145
02146
02147
02148
02149 Command.
Command =
REG_CMD_FLUSH_KEY;
02150 Command.
Hive =
Hive;
02151 Command.
Cell =
Cell;
02152
CmpWorker(&Command);
02153
02154
02155
02156
02157 Command.
Command =
REG_CMD_REMOVE_HIVE_LIST;
02158 Command.
CmHive = (
PCMHIVE)
Hive;
02159
CmpWorker(&Command);
02160
02161
02162
02163
02164 Success =
CmpDestroyHive(
Hive,
Cell);
02165
02166
CmpUnlockRegistry();
02167
02168
if (Success) {
02169
HvFreeHive(
Hive);
02170
02171
02172
02173
02174 Command.
Command =
REG_CMD_HIVE_CLOSE;
02175 Command.
CmHive = CmHive;
02176
CmpWorker(&Command);
02177
02178
02179
02180
02181
ASSERT( CmHive->
HiveLock );
02182
ExFreePool(CmHive->
HiveLock);
02183
CmpFree(CmHive,
sizeof(
CMHIVE));
02184
02185
return(STATUS_SUCCESS);
02186 }
else {
02187
return(STATUS_INSUFFICIENT_RESOURCES);
02188 }
02189
02190 }
02191
02192
02193
02194 BOOLEAN
02195 CmpDoFlushAll(
02196 VOID
02197 )
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219 {
02220
NTSTATUS Status;
02221 PLIST_ENTRY p;
02222
PCMHIVE h;
02223 BOOLEAN Result =
TRUE;
02224
02225
02226
02227
extern PCMHIVE CmpMasterHive;
02228
02229
02230
02231
02232
02233
02234
if (
CmpNoWrite) {
02235
return TRUE;
02236 }
02237
02238
02239
02240
02241 p =
CmpHiveListHead.Flink;
02242
while (p != &
CmpHiveListHead) {
02243
02244 h = CONTAINING_RECORD(p,
CMHIVE,
HiveList);
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258
if (!(h->
Hive.
HiveFlags &
HIVE_NOLAZYFLUSH)) {
02259
02260
02261
02262
02263
02264
02265
02266
CmLockHive (h);
02267
02268
Status =
HvSyncHive((
PHHIVE)h);
02269
02270
if( !
NT_SUCCESS(
Status ) ) {
02271 Result =
FALSE;
02272 }
02273
CmUnlockHive (h);
02274
02275
02276
02277
02278
02279
02280
02281
02282 }
02283
02284
02285 p = p->Flink;
02286 }
02287
02288
return Result;
02289 }
02290
02291
02292
NTSTATUS
02293 CmReplaceKey(
02294 IN
PHHIVE Hive,
02295 IN HCELL_INDEX Cell,
02296 IN PUNICODE_STRING NewHiveName,
02297 IN PUNICODE_STRING OldFileName
02298 )
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325
02326 {
02327
REGISTRY_COMMAND Command;
02328
CHAR ObjectInfoBuffer[512];
02329
NTSTATUS Status;
02330 OBJECT_ATTRIBUTES Attributes;
02331
PCMHIVE NewHive;
02332 POBJECT_NAME_INFORMATION NameInfo;
02333 ULONG OldQuotaAllowed;
02334 ULONG OldQuotaWarning;
02335
02336
CmpLockRegistryExclusive();
02337
02338
if (
Hive->
HiveFlags &
HIVE_HAS_BEEN_REPLACED) {
02339
CmpUnlockRegistry();
02340
return STATUS_FILE_RENAMED;
02341 }
02342
02343
02344
02345
02346 OldQuotaAllowed =
CmpGlobalQuotaAllowed;
02347 OldQuotaWarning =
CmpGlobalQuotaWarning;
02348
CmpGlobalQuotaAllowed =
CM_WRAP_LIMIT;
02349
CmpGlobalQuotaWarning =
CM_WRAP_LIMIT;
02350
02351
02352
02353
02354 InitializeObjectAttributes(&Attributes,
02355 NewHiveName,
02356 OBJ_CASE_INSENSITIVE,
02357
NULL,
02358
NULL);
02359
02360 Command.
RegistryLockAquired =
TRUE;
02361 Command.
Command =
REG_CMD_HIVE_OPEN;
02362 Command.
FileAttributes = &Attributes;
02363 Command.
Allocate =
FALSE;
02364 Command.
ImpersonationContext =
NULL;
02365
CmpWorker(&Command);
02366
Status = Command.
Status;
02367
if (!
NT_SUCCESS(
Status)) {
02368
goto ErrorExit;
02369 }
02370
ASSERT(Command.
Allocate ==
FALSE);
02371
02372 NewHive = Command.
CmHive;
02373
02374
02375
02376
02377
02378 Command.
Command =
REG_CMD_RENAME_HIVE;
02379 Command.
NewName = OldFileName;
02380 Command.
OldName = (POBJECT_NAME_INFORMATION)ObjectInfoBuffer;
02381 Command.
NameInfoLength =
sizeof(ObjectInfoBuffer);
02382 Command.
CmHive = CONTAINING_RECORD(
Hive,
CMHIVE,
Hive);
02383
CmpWorker(&Command);
02384
Status = Command.
Status;
02385
if (!
NT_SUCCESS(
Status)) {
02386
02387
02388
02389 Command.
CmHive = NewHive;
02390 Command.
Command =
REG_CMD_HIVE_CLOSE;
02391
CmpWorker(&Command);
02392
goto ErrorExit;
02393 }
02394
02395
02396
02397
02398
02399
02400
Hive->
HiveFlags |=
HIVE_HAS_BEEN_REPLACED;
02401 NameInfo = (POBJECT_NAME_INFORMATION)ObjectInfoBuffer;
02402 Command.
Command =
REG_CMD_RENAME_HIVE;
02403 Command.
NewName = &NameInfo->Name;
02404 Command.
OldName =
NULL;
02405 Command.
NameInfoLength = 0;
02406 Command.
CmHive = NewHive;
02407
CmpWorker(&Command);
02408
Status = Command.
Status;
02409
if (!
NT_SUCCESS(
Status)) {
02410
02411
02412
02413
02414 Command.
Command =
REG_CMD_HIVE_CLOSE;
02415 Command.
CmHive = NewHive;
02416
CmpWorker(&Command);
02417
02418
02419
02420
02421
02422
02423 Command.
Command =
REG_CMD_RENAME_HIVE;
02424 Command.
NewName = &NameInfo->Name;
02425 Command.
OldName =
NULL;
02426 Command.
NameInfoLength = 0;
02427 Command.
CmHive = CONTAINING_RECORD(
Hive,
CMHIVE,
Hive);
02428
CmpWorker(&Command);
02429
if (!
NT_SUCCESS(Command.
Status)) {
02430
CMLOG(
CML_BUGCHECK,
CMS_SAVRES) {
02431 KdPrint((
"CmReplaceKey: renamed existing hive file, but couldn't\n"));
02432 KdPrint((
" rename new hive file (%08lx) ",
Status));
02433 KdPrint((
" or replace old hive file (%08lx)!\n",Command.
Status));
02434 }
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448
Status = STATUS_REGISTRY_CORRUPT;
02449
02450 }
02451 }
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462 RemoveEntryList(&(NewHive->
HiveList));
02463
02464
HvFreeHive((
PHHIVE)NewHive);
02465
02466
ASSERT( NewHive->HiveLock );
02467
ExFreePool(NewHive->HiveLock);
02468
CmpFree(NewHive,
sizeof(
CMHIVE));
02469
02470
ErrorExit:
02471
02472
02473
02474
CmpGlobalQuotaAllowed = OldQuotaAllowed;
02475
CmpGlobalQuotaWarning = OldQuotaWarning;
02476
02477
CmpUnlockRegistry();
02478
return(
Status);
02479 }
02480
02481
#ifdef _WRITE_PROTECTED_REGISTRY_POOL
02482
02483
VOID
02484
CmpMarkAllBinsReadOnly(
02485
PHHIVE Hive
02486 )
02487
02488
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502
02503 {
02504
PHMAP_ENTRY t;
02505
PHBIN Bin;
02506
HCELL_INDEX p;
02507 ULONG Length;
02508
02509
02510
02511
02512 Length =
Hive->Storage[
Stable].Length;
02513
02514 p = 0;
02515
02516
02517
02518
02519
while (p < Length) {
02520
t =
HvpGetCellMap(Hive, p);
02521
VALIDATE_CELL_MAP(__LINE__,t,Hive,p);
02522
02523
Bin = (
PHBIN)((
t->BinAddress) &
HMAP_BASE);
02524
02525
if (
t->BinAddress &
HMAP_NEWALLOC) {
02526
02527
02528
02529
02530
HvpChangeBinAllocation(Bin,TRUE);
02531 }
02532
02533
02534 p = (ULONG)p +
Bin->
Size;
02535
02536 }
02537
02538 }
02539
02540
#endif
02541