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
00026
00027 #define CM_SAVEKEYBUFSIZE 0x10000
00028
00029 extern PCMHIVE CmpMasterHive;
00030
00031 extern BOOLEAN
CmpProfileLoaded;
00032
00033 extern PUCHAR
CmpStashBuffer;
00034 extern ULONG
CmpGlobalQuotaAllowed;
00035 extern ULONG
CmpGlobalQuotaWarning;
00036 extern ULONG
CmpGlobalQuotaUsed;
00037
00038
PCMHIVE
00039
CmpCreateTemporaryHive(
00040 IN HANDLE FileHandle
00041 );
00042
00043
VOID
00044
CmpDestroyTemporaryHive(
00045
PCMHIVE CmHive
00046 );
00047
00048
NTSTATUS
00049
CmpLoadHiveVolatile(
00050 IN
PCM_KEY_CONTROL_BLOCK KeyControlBlock,
00051 IN HANDLE FileHandle
00052 );
00053
00054
NTSTATUS
00055
CmpRefreshHive(
00056 IN
PCM_KEY_CONTROL_BLOCK KeyControlBlock
00057 );
00058
00059
NTSTATUS
00060
CmpSaveKeyByFileCopy(
00061
PCMHIVE Hive,
00062 HANDLE FileHandle
00063 );
00064
00065 ULONG
00066
CmpRefreshWorkerRoutine(
00067
PCM_KEY_CONTROL_BLOCK Current,
00068 PVOID Context1,
00069 PVOID Context2
00070 );
00071
00072 BOOLEAN
00073
CmpMergeKeyValues(
00074
PHHIVE SourceHive,
00075 HCELL_INDEX SourceKeyCell,
00076
PCM_KEY_NODE SourceKeyNode,
00077
PHHIVE TargetHive,
00078 HCELL_INDEX TargetKeyCell,
00079
PCM_KEY_NODE TargetKeyNode
00080 );
00081
00082
#ifdef ALLOC_PRAGMA
00083
#pragma alloc_text(PAGE,CmRestoreKey)
00084
#pragma alloc_text(PAGE,CmpLoadHiveVolatile)
00085
#pragma alloc_text(PAGE,CmpRefreshHive)
00086
#pragma alloc_text(PAGE,CmSaveKey)
00087
#pragma alloc_text(PAGE,CmSaveMergedKeys)
00088
#pragma alloc_text(PAGE,CmpCreateTemporaryHive)
00089
#pragma alloc_text(PAGE,CmpDestroyTemporaryHive)
00090
#pragma alloc_text(PAGE,CmpRefreshWorkerRoutine)
00091
#pragma alloc_text(PAGE,CmpSaveKeyByFileCopy)
00092
#endif
00093
00094
00095
00096
NTSTATUS
00097 CmRestoreKey(
00098 IN
PCM_KEY_CONTROL_BLOCK KeyControlBlock,
00099 IN HANDLE FileHandle,
00100 IN ULONG Flags
00101 )
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 {
00145
NTSTATUS status;
00146
PCELL_DATA ptar;
00147
PCELL_DATA psrc;
00148
PCMHIVE TmpCmHive;
00149
HCELL_INDEX newroot;
00150
HCELL_INDEX newcell;
00151
HCELL_INDEX parent;
00152
HCELL_INDEX list;
00153 ULONG count;
00154 ULONG i;
00155 ULONG j;
00156 LONG size;
00157
PHHIVE Hive;
00158
HCELL_INDEX Cell;
00159
HSTORAGE_TYPE Type;
00160 ULONG NumberLeaves;
00161
PHCELL_INDEX LeafArray;
00162
PCM_KEY_INDEX Leaf;
00163
PCM_KEY_FAST_INDEX FastLeaf;
00164
00165
PAGED_CODE();
00166
CMLOG(
CML_MAJOR,
CMS_SAVRES) {
00167 KdPrint((
"CmRestoreKey:\n"));
00168 KdPrint((
"\tKCB=%08lx\n",KeyControlBlock));
00169 KdPrint((
"\tFileHandle=%08lx\n",FileHandle));
00170 }
00171
00172
if (Flags & REG_REFRESH_HIVE) {
00173
if ((Flags & ~REG_REFRESH_HIVE) != 0) {
00174
00175
00176
00177
return STATUS_INVALID_PARAMETER;
00178 }
00179 }
00180
00181
00182
00183
00184
if (Flags & REG_WHOLE_HIVE_VOLATILE) {
00185
return(
CmpLoadHiveVolatile(KeyControlBlock, FileHandle));
00186 }
00187
00188
00189
00190
00191
if (Flags & REG_REFRESH_HIVE) {
00192
CmpLockRegistryExclusive();
00193 status =
CmpRefreshHive(KeyControlBlock);
00194
CmpUnlockRegistry();
00195
return status;
00196 }
00197
00198
Hive = KeyControlBlock->KeyHive;
00199
Cell = KeyControlBlock->KeyCell;
00200
00201
00202
00203
00204
if (
Hive == &
CmpMasterHive->
Hive) {
00205
return STATUS_ACCESS_DENIED;
00206 }
00207
00208
CmpLockRegistryExclusive();
00209
00210
00211
00212
00213
if (KeyControlBlock->Delete) {
00214
CmpUnlockRegistry();
00215
return(STATUS_CANNOT_DELETE);
00216 }
00217
00218
DCmCheckRegistry(CONTAINING_RECORD(
Hive,
CMHIVE,
Hive));
00219
00220
00221
00222
00223
if (
CmpSearchForOpenSubKeys(KeyControlBlock,(Flags®_FORCE_RESTORE)?SearchAndDeref:SearchIfExist) != 0) {
00224
00225
00226
00227
00228
00229
00230
CmpUnlockRegistry();
00231
return(STATUS_CANNOT_DELETE);
00232 }
00233
00234
00235
00236
00237
if (KeyControlBlock->RefCount != 1 && !(Flags®_FORCE_RESTORE)) {
00238
CmpUnlockRegistry();
00239
return(STATUS_CANNOT_DELETE);
00240 }
00241
00242 ptar =
HvGetCell(
Hive,
Cell);
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 status =
CmpInitializeHive(&TmpCmHive,
00254
HINIT_FILE,
00255 0,
00256
HFILE_TYPE_PRIMARY,
00257
NULL,
00258 FileHandle,
00259
NULL,
00260
NULL,
00261
NULL,
00262
NULL);
00263
00264
if (!
NT_SUCCESS(status)) {
00265
goto ErrorExit1;
00266 }
00267
00268
00269
00270
00271
if (ptar->
u.
KeyNode.
Flags &
KEY_HIVE_ENTRY) {
00272 parent =
HCELL_NIL;
00273 }
else {
00274 parent = ptar->
u.
KeyNode.
Parent;
00275 }
00276
00277 newroot =
CmpCopyKeyPartial(&(TmpCmHive->
Hive),
00278 TmpCmHive->
Hive.
BaseBlock->
RootCell,
00279
Hive,
00280 parent,
00281
TRUE);
00282
if (newroot ==
HCELL_NIL) {
00283 status = STATUS_INSUFFICIENT_RESOURCES;
00284
goto ErrorExit2;
00285 }
00286
00287
00288
00289
00290
00291
00292 psrc =
HvGetCell(
Hive,
Cell);
00293 ptar =
HvGetCell(
Hive, newroot);
00294 size = FIELD_OFFSET(
CM_KEY_NODE,
Name) + psrc->
u.
KeyNode.
NameLength;
00295
00296
00297
00298
00299
00300 newcell =
HvReallocateCell(
Hive, newroot, size);
00301
if (newcell ==
HCELL_NIL) {
00302 status = STATUS_INSUFFICIENT_RESOURCES;
00303
goto ErrorExit2;
00304 }
00305 newroot = newcell;
00306 ptar =
HvGetCell(
Hive, newroot);
00307
00308 status = STATUS_SUCCESS;
00309
00310 RtlMoveMemory((PVOID)&(ptar->
u.
KeyNode.
Name[0]),
00311 (PVOID)&(psrc->
u.
KeyNode.
Name[0]),
00312 psrc->
u.
KeyNode.
NameLength);
00313
00314 ptar->
u.
KeyNode.
NameLength = psrc->
u.
KeyNode.
NameLength;
00315
if (psrc->
u.
KeyNode.
Flags &
KEY_COMP_NAME) {
00316 ptar->
u.
KeyNode.
Flags |=
KEY_COMP_NAME;
00317 }
else {
00318 ptar->
u.
KeyNode.
Flags &= ~
KEY_COMP_NAME;
00319 }
00320
00321
00322
00323
00324
if (
CmpCopyTree(&(TmpCmHive->
Hive),
00325 TmpCmHive->
Hive.
BaseBlock->
RootCell,
00326
Hive,
00327 newroot) ==
FALSE)
00328 {
00329 status = STATUS_INSUFFICIENT_RESOURCES;
00330
goto ErrorExit2;
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340 ptar =
HvGetCell(
Hive,
Cell);
00341 parent = ptar->
u.
KeyNode.
Parent;
00342
00343
if (ptar->
u.
KeyNode.
Flags &
KEY_HIVE_ENTRY) {
00344
00345
00346
00347
00348
00349
00350 ptar =
HvGetCell( (&(
CmpMasterHive->
Hive)), parent);
00351 ptar->
u.
KeyNode.
ChildHiveReference.
KeyCell = newroot;
00352 ptar =
HvGetCell(
Hive, newroot);
00353 ptar->
u.
KeyNode.
Parent = parent;
00354
Hive->
BaseBlock->
RootCell = newroot;
00355
00356
00357 }
else {
00358
00359
00360
00361
00362
00363
00364
00365 ptar =
HvGetCell(
Hive, parent);
00366 Type =
HvGetCellType(
Cell);
00367 list = ptar->
u.
KeyNode.
SubKeyLists[Type];
00368 count = ptar->
u.
KeyNode.
SubKeyCounts[Type];
00369
00370 ptar =
HvGetCell(
Hive, list);
00371
if (ptar->
u.
KeyIndex.
Signature ==
CM_KEY_INDEX_ROOT) {
00372 NumberLeaves = ptar->
u.
KeyIndex.
Count;
00373 LeafArray = &ptar->
u.
KeyIndex.
List[0];
00374 }
else {
00375 NumberLeaves = 1;
00376 LeafArray = &list;
00377 }
00378
00379
00380
00381
00382
for (i = 0; i < NumberLeaves; i++) {
00383 Leaf = (
PCM_KEY_INDEX)
HvGetCell(
Hive, LeafArray[i]);
00384
if (Leaf->
Signature ==
CM_KEY_FAST_LEAF) {
00385 FastLeaf = (
PCM_KEY_FAST_INDEX)Leaf;
00386
for (j=0; j < FastLeaf->
Count; j++) {
00387
if (FastLeaf->
List[j].
Cell ==
Cell) {
00388 FastLeaf->
List[j].
Cell = newroot;
00389
goto FoundCell;
00390 }
00391 }
00392 }
else {
00393
for (j=0; j < Leaf->
Count; j++) {
00394
if (Leaf->
List[j] ==
Cell) {
00395
00396 Leaf->
List[j] = newroot;
00397
goto FoundCell;
00398 }
00399 }
00400 }
00401 }
00402
ASSERT(
FALSE);
00403
00404 }
00405
00406 FoundCell:
00407
00408
00409
00410
00411
00412 KeyControlBlock->KeyCell = newroot;
00413 KeyControlBlock->KeyNode = (
PCM_KEY_NODE)
HvGetCell(
Hive, newroot);
00414
00415
00416
00417
00418
00419
ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
00420
00421
CmpCleanUpKcbValueCache(KeyControlBlock);
00422
00423
if (KeyControlBlock->ExtFlags &
CM_KCB_SUBKEY_HINT) {
00424
00425
00426
00427
ExFreePoolWithTag(KeyControlBlock->IndexHint, CM_CACHE_INDEX_TAG |
PROTECTED_POOL);
00428 }
00429
00430 KeyControlBlock->ValueCache.Count = KeyControlBlock->KeyNode->ValueList.Count;
00431 KeyControlBlock->ValueCache.ValueList = (ULONG_PTR) (KeyControlBlock->KeyNode->ValueList.List);
00432 KeyControlBlock->Flags = KeyControlBlock->KeyNode->Flags;
00433 KeyControlBlock->Security = KeyControlBlock->KeyNode->Security;
00434
00435 KeyControlBlock->ExtFlags = 0;
00436
00437
00438
00439
00440
CmpDeleteTree(
Hive,
Cell);
00441
CmpFreeKeyByCell(
Hive,
Cell,
FALSE);
00442
00443
00444
00445
00446
CmpReportNotify(KeyControlBlock,
00447 KeyControlBlock->KeyHive,
00448 KeyControlBlock->KeyCell,
00449 REG_NOTIFY_CHANGE_NAME);
00450
00451
00452
00453
00454
00455
CmpDestroyTemporaryHive(TmpCmHive);
00456
00457
00458
00459
00460
if (
CmpProfileLoaded ==
FALSE) {
00461
CmpProfileLoaded =
TRUE;
00462
CmpSetGlobalQuotaAllowed();
00463 }
00464
00465
DCmCheckRegistry(CONTAINING_RECORD(
Hive,
CMHIVE,
Hive));
00466
CmpUnlockRegistry();
00467
return status;
00468
00469
00470
00471
00472
00473 ErrorExit2:
00474
CmpDestroyTemporaryHive(TmpCmHive);
00475 ErrorExit1:
00476
DCmCheckRegistry(CONTAINING_RECORD(
Hive,
CMHIVE,
Hive));
00477
CmpUnlockRegistry();
00478
00479
return status;
00480 }
00481
00482
00483
NTSTATUS
00484 CmpLoadHiveVolatile(
00485 IN
PCM_KEY_CONTROL_BLOCK KeyControlBlock,
00486 IN HANDLE FileHandle
00487 )
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514 {
00515
NTSTATUS status;
00516
PHHIVE Hive;
00517
PCELL_DATA RootData;
00518
PCMHIVE NewHive;
00519
PCMHIVE TempHive;
00520
HCELL_INDEX Cell;
00521
HCELL_INDEX Root;
00522
REGISTRY_COMMAND Command;
00523
NTSTATUS Status;
00524 UNICODE_STRING RootName;
00525 UNICODE_STRING
NewName;
00526
USHORT NewNameLength;
00527 PUNICODE_STRING ConstructedName;
00528
00529
PAGED_CODE();
00530
CmpLockRegistryExclusive();
00531
00532
if (KeyControlBlock->Delete) {
00533
CmpUnlockRegistry();
00534
return(STATUS_KEY_DELETED);
00535 }
00536
Hive = KeyControlBlock->KeyHive;
00537
Cell = KeyControlBlock->KeyCell;
00538
00539
00540
00541
00542
00543
if (
Hive != &
CmpMasterHive->
Hive) {
00544
CmpUnlockRegistry();
00545
return(STATUS_INVALID_PARAMETER);
00546 }
00547
00548
00549
00550
00551 status =
CmpInitializeHive(&TempHive,
00552
HINIT_FILE,
00553 0,
00554
HFILE_TYPE_PRIMARY,
00555
NULL,
00556 FileHandle,
00557
NULL,
00558
NULL,
00559
NULL,
00560
NULL);
00561
if (!
NT_SUCCESS(status)) {
00562
CmpUnlockRegistry();
00563
return(status);
00564 }
00565
00566
00567
00568
00569 status =
CmpInitializeHive(&NewHive,
00570
HINIT_CREATE,
00571
HIVE_VOLATILE,
00572 0,
00573
NULL,
00574
NULL,
00575
NULL,
00576
NULL,
00577
NULL,
00578
NULL);
00579
if (!
NT_SUCCESS(status)) {
00580
CmpDestroyTemporaryHive(TempHive);
00581
CmpUnlockRegistry();
00582
return(status);
00583 }
00584
00585
00586
00587
00588 Root =
CmpCopyKeyPartial(&TempHive->
Hive,
00589 TempHive->
Hive.
BaseBlock->
RootCell,
00590 &NewHive->
Hive,
00591
HCELL_NIL,
00592
FALSE);
00593
if (Root ==
HCELL_NIL) {
00594
CmpDestroyTemporaryHive(TempHive);
00595
CmpDestroyTemporaryHive(NewHive);
00596
CmpUnlockRegistry();
00597
return(STATUS_INSUFFICIENT_RESOURCES);
00598 }
00599 NewHive->
Hive.
BaseBlock->
RootCell = Root;
00600
00601
00602
00603
00604
if (!
CmpCopyTree(&TempHive->
Hive,
00605 TempHive->
Hive.
BaseBlock->
RootCell,
00606 &NewHive->
Hive,
00607 Root))
00608 {
00609
CmpDestroyTemporaryHive(TempHive);
00610
CmpDestroyTemporaryHive(NewHive);
00611
CmpUnlockRegistry();
00612
return(STATUS_INSUFFICIENT_RESOURCES);
00613 }
00614
00615
00616
00617
00618
00619 RootData =
HvGetCell(&NewHive->
Hive,Root);
00620 ConstructedName =
CmpConstructName(KeyControlBlock);
00621
00622 NewNameLength = ConstructedName->Length +
00623
CmpHKeyNameLen(&RootData->
u.
KeyNode) +
00624
sizeof(WCHAR);
00625
NewName.Buffer =
ExAllocatePool(
PagedPool, NewNameLength);
00626
if (
NewName.Buffer ==
NULL) {
00627
CmpDestroyTemporaryHive(TempHive);
00628
CmpDestroyTemporaryHive(NewHive);
00629
CmpUnlockRegistry();
00630
ExFreePoolWithTag(ConstructedName, CM_NAME_TAG |
PROTECTED_POOL);
00631
return(STATUS_INSUFFICIENT_RESOURCES);
00632 }
00633
NewName.Length =
NewName.MaximumLength = NewNameLength;
00634
RtlCopyUnicodeString(&
NewName, ConstructedName);
00635
ExFreePoolWithTag(ConstructedName, CM_NAME_TAG |
PROTECTED_POOL);
00636
RtlAppendUnicodeToString(&
NewName,
L"\\");
00637
00638
if (RootData->
u.
KeyNode.
Flags &
KEY_COMP_NAME) {
00639
CmpCopyCompressedName(
NewName.Buffer + (
NewName.Length /
sizeof(WCHAR)),
00640
NewName.MaximumLength -
NewName.Length,
00641 RootData->
u.
KeyNode.
Name,
00642
CmpHKeyNameLen(&RootData->
u.
KeyNode));
00643
NewName.Length +=
CmpHKeyNameLen(&RootData->
u.
KeyNode);
00644 }
else {
00645 RootName.Buffer = RootData->
u.
KeyNode.
Name;
00646 RootName.Length = RootName.MaximumLength = RootData->
u.
KeyNode.
NameLength;
00647
00648
RtlAppendUnicodeStringToString(&
NewName,&RootName);
00649 }
00650
00651
Status =
CmpLinkHiveToMaster(&
NewName,
00652
NULL,
00653 NewHive,
00654
FALSE,
00655
NULL);
00656
if (
NT_SUCCESS(
Status)) {
00657 Command.
CmHive = NewHive;
00658 Command.
Command =
REG_CMD_ADD_HIVE_LIST;
00659
CmpWorker(&Command);
00660 }
else {
00661
CmpDestroyTemporaryHive(NewHive);
00662 }
00663
CmpDestroyTemporaryHive(TempHive);
00664
00665
ExFreePool(
NewName.Buffer);
00666
00667
if (
NT_SUCCESS(
Status)) {
00668
00669
00670
00671
if (
CmpProfileLoaded ==
FALSE) {
00672
CmpProfileLoaded =
TRUE;
00673
CmpSetGlobalQuotaAllowed();
00674 }
00675 }
00676
00677
CmpUnlockRegistry();
00678
return(
Status);
00679 }
00680
00681
00682
00683 ULONG
00684 CmpRefreshWorkerRoutine(
00685
PCM_KEY_CONTROL_BLOCK Current,
00686 PVOID Context1,
00687 PVOID Context2
00688 )
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714 {
00715
PAGED_CODE();
00716
if (Current->
KeyHive == (
PHHIVE)
Context1) {
00717
00718
00719
00720
00721 Current->
Delete =
TRUE;
00722 Current->
KeyHive =
NULL;
00723 Current->
KeyCell = 0;
00724
return(
KCB_WORKER_DELETE);
00725 }
00726
return KCB_WORKER_CONTINUE;
00727 }
00728
00729
00730
NTSTATUS
00731 CmpRefreshHive(
00732 IN
PCM_KEY_CONTROL_BLOCK KeyControlBlock
00733 )
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769 {
00770
PHHIVE Hive;
00771
HCELL_INDEX Cell;
00772
PCELL_DATA pcell;
00773
REGISTRY_COMMAND CommandArea;
00774 PLIST_ENTRY ptr;
00775
PCM_NOTIFY_BLOCK node;
00776
00777
PAGED_CODE();
00778
00779
00780
00781
if (!
SeSinglePrivilegeCheck(
SeTcbPrivilege, KeGetPreviousMode())) {
00782
return STATUS_PRIVILEGE_NOT_HELD;
00783 }
00784
00785
if (KeyControlBlock->Delete) {
00786
return(STATUS_KEY_DELETED);
00787 }
00788
CmpLockRegistryExclusive();
00789
Hive = KeyControlBlock->KeyHive;
00790
Cell = KeyControlBlock->KeyCell;
00791
00792
00793
00794
00795
if ( ! (
Hive->
HiveFlags &
HIVE_NOLAZYFLUSH)) {
00796
CmpUnlockRegistry();
00797
return STATUS_INVALID_PARAMETER;
00798 }
00799
00800
00801
00802
00803
if (
Hive->Storage[
Volatile].Length != 0) {
00804
CmpUnlockRegistry();
00805
return STATUS_UNSUCCESSFUL;
00806 }
00807
00808
00809
00810
00811 pcell =
HvGetCell(
Hive,
Cell);
00812
if ( ! (pcell->
u.
KeyNode.
Flags &
KEY_HIVE_ENTRY)) {
00813
CmpUnlockRegistry();
00814
return STATUS_INVALID_PARAMETER;
00815 }
00816
00817
00818
00819
00820
while (
TRUE) {
00821
00822
00823
00824
00825 ptr = &(((
PCMHIVE)
Hive)->NotifyList);
00826
if (ptr->Flink ==
NULL) {
00827
break;
00828 }
00829
00830 ptr = ptr->Flink;
00831 node = CONTAINING_RECORD(ptr,
CM_NOTIFY_BLOCK,
HiveList);
00832
ASSERT((node->
KeyBody)->NotifyBlock == node);
00833
CmpFlushNotify(node->
KeyBody);
00834 }
00835
00836
00837
00838
00839
CmpSearchKeyControlBlockTree(
00840
CmpRefreshWorkerRoutine,
00841 (PVOID)
Hive,
00842
NULL
00843 );
00844
00845
00846
00847
00848
00849
CommandArea.
Command =
REG_CMD_REFRESH_HIVE;
00850
CommandArea.
Hive =
Hive;
00851
CmpWorker(&
CommandArea);
00852
CmpUnlockRegistry();
00853
00854
00855
00856
return STATUS_SUCCESS;
00857 }
00858
00859
00860
00861
NTSTATUS
00862 CmSaveKey(
00863 IN
PCM_KEY_CONTROL_BLOCK KeyControlBlock,
00864 IN HANDLE FileHandle
00865 )
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883 {
00884
NTSTATUS status;
00885
PCELL_DATA proot;
00886
USHORT flags;
00887
PCMHIVE TmpCmHive;
00888
PCMHIVE CmHive;
00889
HCELL_INDEX newroot;
00890
PHHIVE Hive;
00891
HCELL_INDEX Cell;
00892 ULONG OldQuotaAllowed;
00893 ULONG OldQuotaWarning;
00894
#if DBG
00895
ULONG OldQuotaUsed;
00896
#endif
00897
00898
PAGED_CODE();
00899
CMLOG(
CML_MAJOR,
CMS_SAVRES) {
00900 KdPrint((
"CmSaveKey:\n"));
00901 KdPrint((
"\tKCB=%08lx",KeyControlBlock));
00902 KdPrint((
"\tFileHandle=%08lx\n",FileHandle));
00903 }
00904
00905
00906
00907
00908
Hive = KeyControlBlock->KeyHive;
00909
Cell = KeyControlBlock->KeyCell;
00910
00911
if (
Hive == &
CmpMasterHive->
Hive) {
00912
return STATUS_ACCESS_DENIED;
00913 }
00914
00915
CmpLockRegistryExclusive();
00916
00917
if (KeyControlBlock->Delete) {
00918
CmpUnlockRegistry();
00919
return STATUS_KEY_DELETED;
00920 }
00921
00922
DCmCheckRegistry(CONTAINING_RECORD(
Hive,
CMHIVE,
Hive));
00923
00924
if ( (
Hive->
HiveFlags &
HIVE_NOLAZYFLUSH) &&
00925 (
Hive->
DirtyCount != 0))
00926 {
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940 status =
CmpSaveKeyByFileCopy((
PCMHIVE)
Hive, FileHandle);
00941
CmpUnlockRegistry();
00942
return status;
00943 }
00944
00945 proot =
HvGetCell(
Hive,
Cell);
00946 flags = proot->
u.
KeyNode.
Flags;
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
CMLOG(
CML_FLOW,
CMS_SAVRES) KdPrint((
"\tSave of partial hive\n"));
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967 OldQuotaAllowed =
CmpGlobalQuotaAllowed;
00968 OldQuotaWarning =
CmpGlobalQuotaWarning;
00969
CmpGlobalQuotaAllowed =
CM_WRAP_LIMIT;
00970
CmpGlobalQuotaWarning =
CM_WRAP_LIMIT;
00971
00972
#if DBG
00973
OldQuotaUsed =
CmpGlobalQuotaUsed;
00974
#endif
00975
00976
00977
00978
00979
00980 TmpCmHive =
CmpCreateTemporaryHive(FileHandle);
00981
if (TmpCmHive ==
NULL) {
00982 status = STATUS_INSUFFICIENT_RESOURCES;
00983
goto ErrorInsufficientResources;
00984 }
00985
00986
00987
00988
00989
00990 newroot =
CmpCopyKeyPartial(
00991
Hive,
00992
Cell,
00993 &(TmpCmHive->
Hive),
00994
HCELL_NIL,
00995
TRUE);
00996
if (newroot ==
HCELL_NIL) {
00997 status = STATUS_INSUFFICIENT_RESOURCES;
00998
goto ErrorInsufficientResources;
00999 }
01000 TmpCmHive->
Hive.
BaseBlock->
RootCell = newroot;
01001
01002
01003
01004
01005
if (
CmpCopyTree(
Hive,
Cell, &(TmpCmHive->
Hive), newroot) ==
FALSE) {
01006 status = STATUS_INSUFFICIENT_RESOURCES;
01007
goto ErrorInsufficientResources;
01008 }
01009
01010
01011
01012
01013 TmpCmHive->
FileHandles[
HFILE_TYPE_EXTERNAL] = FileHandle;
01014 status =
HvWriteHive(&(TmpCmHive->
Hive));
01015 TmpCmHive->
FileHandles[
HFILE_TYPE_EXTERNAL] =
NULL;
01016
01017
01018
01019
01020 ErrorInsufficientResources:
01021
01022
01023
01024
01025
if (TmpCmHive !=
NULL) {
01026
CmpDestroyTemporaryHive(TmpCmHive);
01027 }
01028
01029
#if DBG
01030
01031
01032
01033
ASSERT( OldQuotaUsed ==
CmpGlobalQuotaUsed );
01034
#endif
01035
01036
01037
01038
01039
CmpGlobalQuotaAllowed = OldQuotaAllowed;
01040
CmpGlobalQuotaWarning = OldQuotaWarning;
01041
DCmCheckRegistry(CONTAINING_RECORD(
Hive,
CMHIVE,
Hive));
01042
CmpUnlockRegistry();
01043
return status;
01044 }
01045
01046
NTSTATUS
01047 CmSaveMergedKeys(
01048 IN
PCM_KEY_CONTROL_BLOCK HighPrecedenceKcb,
01049 IN
PCM_KEY_CONTROL_BLOCK LowPrecedenceKcb,
01050 IN HANDLE FileHandle
01051 )
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073 {
01074
NTSTATUS status;
01075
PCELL_DATA proot;
01076
USHORT flags;
01077
PCMHIVE TmpCmHive;
01078
HCELL_INDEX newroot;
01079
PHHIVE HighHive;
01080
PHHIVE LowHive;
01081
HCELL_INDEX HighCell;
01082
HCELL_INDEX LowCell;
01083 ULONG OldQuotaAllowed;
01084 ULONG OldQuotaWarning;
01085
PCM_KEY_NODE HighNode,LowNode;
01086
#if DBG
01087
ULONG OldQuotaUsed;
01088
#endif
01089
01090
PAGED_CODE();
01091
CMLOG(
CML_MAJOR,
CMS_SAVRES) {
01092 KdPrint((
"CmSaveMergedKeys:\n"));
01093 KdPrint((
"\tHighKCB=%08lx",HighPrecedenceKcb));
01094 KdPrint((
"\tLowKCB=%08lx",LowPrecedenceKcb));
01095 KdPrint((
"\tFileHandle=%08lx\n",FileHandle));
01096 }
01097
01098
01099
01100
01101
01102 HighHive = HighPrecedenceKcb->KeyHive;
01103 HighCell = HighPrecedenceKcb->KeyCell;
01104 LowHive = LowPrecedenceKcb->KeyHive;
01105 LowCell = LowPrecedenceKcb->KeyCell;
01106
01107
if (LowHive == HighHive ) {
01108
return STATUS_INVALID_PARAMETER;
01109 }
01110
01111
CmpLockRegistryExclusive();
01112
01113
if (HighPrecedenceKcb->Delete || LowPrecedenceKcb->Delete) {
01114
01115
01116
01117
CmpUnlockRegistry();
01118
return STATUS_KEY_DELETED;
01119 }
01120
01121
DCmCheckRegistry(CONTAINING_RECORD(HighHive,
CMHIVE,
Hive));
01122
DCmCheckRegistry(CONTAINING_RECORD(LowHive,
CMHIVE,
Hive));
01123
01124
01125
if( ((HighHive->
HiveFlags &
HIVE_NOLAZYFLUSH) && (HighHive->
DirtyCount != 0)) ||
01126 ((LowHive->
HiveFlags &
HIVE_NOLAZYFLUSH) && (LowHive->
DirtyCount != 0)) ) {
01127
01128
01129
01130
01131
01132 status = STATUS_INVALID_PARAMETER;
01133
CmpUnlockRegistry();
01134
return status;
01135 }
01136
01137 proot =
HvGetCell(LowHive, LowCell);
01138 flags = proot->
u.
KeyNode.
Flags;
01139
01140
01141
CMLOG(
CML_FLOW,
CMS_SAVRES) KdPrint((
"\tCopy of partial HighHive\n"));
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154 OldQuotaAllowed =
CmpGlobalQuotaAllowed;
01155 OldQuotaWarning =
CmpGlobalQuotaWarning;
01156
CmpGlobalQuotaAllowed =
CM_WRAP_LIMIT;
01157
CmpGlobalQuotaWarning =
CM_WRAP_LIMIT;
01158
01159
#if DBG
01160
OldQuotaUsed =
CmpGlobalQuotaUsed;
01161
#endif
01162
01163
01164
01165
01166
01167 TmpCmHive =
CmpCreateTemporaryHive(FileHandle);
01168
if (TmpCmHive ==
NULL) {
01169 status = STATUS_INSUFFICIENT_RESOURCES;
01170
goto ErrorInsufficientResources;
01171 }
01172
01173
01174
01175
01176
01177 newroot =
CmpCopyKeyPartial(
01178 HighHive,
01179 HighCell,
01180 &(TmpCmHive->
Hive),
01181
HCELL_NIL,
01182
TRUE);
01183
if (newroot ==
HCELL_NIL) {
01184 status = STATUS_INSUFFICIENT_RESOURCES;
01185
goto ErrorInsufficientResources;
01186 }
01187 TmpCmHive->
Hive.
BaseBlock->
RootCell = newroot;
01188
01189
01190
01191
01192
if (
CmpCopyTree(HighHive, HighCell, &(TmpCmHive->
Hive), newroot) ==
FALSE) {
01193 status = STATUS_INSUFFICIENT_RESOURCES;
01194
goto ErrorInsufficientResources;
01195 }
01196
01197
01198
01199
01200 LowNode = (
PCM_KEY_NODE)
HvGetCell(LowHive, LowCell);
01201 HighNode = (
PCM_KEY_NODE)
HvGetCell(&(TmpCmHive->
Hive),newroot);
01202
01203
if (
CmpMergeKeyValues(LowHive, LowCell, LowNode, &(TmpCmHive->
Hive), newroot, HighNode) ==
FALSE ){
01204 status = STATUS_INSUFFICIENT_RESOURCES;
01205
goto ErrorInsufficientResources;
01206 }
01207
01208
CMLOG(
CML_FLOW,
CMS_SAVRES) KdPrint((
"\tMerge partial LowHive over the HighHive\n"));
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
if (
CmpMergeTrees(LowHive, LowCell, &(TmpCmHive->
Hive), newroot) ==
FALSE) {
01220 status = STATUS_INSUFFICIENT_RESOURCES;
01221
goto ErrorInsufficientResources;
01222 }
01223
01224
01225
01226
01227 TmpCmHive->
FileHandles[
HFILE_TYPE_EXTERNAL] = FileHandle;
01228 status =
HvWriteHive(&(TmpCmHive->
Hive));
01229 TmpCmHive->
FileHandles[
HFILE_TYPE_EXTERNAL] =
NULL;
01230
01231
01232
01233
01234 ErrorInsufficientResources:
01235
01236
01237
01238
if (TmpCmHive !=
NULL) {
01239
CmpDestroyTemporaryHive(TmpCmHive);
01240 }
01241
01242
#if DBG
01243
01244
01245
01246
ASSERT( OldQuotaUsed ==
CmpGlobalQuotaUsed );
01247
#endif
01248
01249
01250
01251
CmpGlobalQuotaAllowed = OldQuotaAllowed;
01252
CmpGlobalQuotaWarning = OldQuotaWarning;
01253
DCmCheckRegistry(CONTAINING_RECORD(HighHive,
CMHIVE,
Hive));
01254
DCmCheckRegistry(CONTAINING_RECORD(LowHive,
CMHIVE,
Hive));
01255
CmpUnlockRegistry();
01256
return status;
01257 }
01258
01259
01260
NTSTATUS
01261 CmpSaveKeyByFileCopy(
01262
PCMHIVE CmHive,
01263 HANDLE FileHandle
01264 )
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282 {
01283
PHBASE_BLOCK BaseBlock;
01284
NTSTATUS status;
01285 ULONG
Offset;
01286 ULONG Length;
01287 ULONG Position;
01288
REGISTRY_COMMAND CommandArea;
01289 PUCHAR CopyBuffer;
01290 ULONG BufferLength;
01291 ULONG BytesToCopy;
01292
CMP_OFFSET_ARRAY offsetElement;
01293
01294
PAGED_CODE();
01295
01296
01297
01298
01299
01300 BufferLength =
CM_SAVEKEYBUFSIZE;
01301
try {
01302 CopyBuffer =
ExAllocatePoolWithQuota(
PagedPoolCacheAligned,
01303 BufferLength);
01304 } except(
EXCEPTION_EXECUTE_HANDLER) {
01305 CopyBuffer =
NULL;
01306 }
01307
CmpLockRegistryExclusive();
01308
if (CopyBuffer ==
NULL) {
01309 CopyBuffer =
CmpStashBuffer;
01310 BufferLength =
HBLOCK_SIZE;
01311 }
01312
01313
01314
01315 status = STATUS_REGISTRY_IO_FAILED;
01316
01317 CmHive->
FileHandles[
HFILE_TYPE_EXTERNAL] = FileHandle;
01318
01319
Offset = 0;
01320
CommandArea.
Command =
REG_CMD_HIVE_READ;
01321
CommandArea.
CmHive = CmHive;
01322
CommandArea.
FileType =
HFILE_TYPE_PRIMARY;
01323
CommandArea.
Offset = &
Offset;
01324
CommandArea.
Buffer = CopyBuffer;
01325
CommandArea.
FileSize =
HBLOCK_SIZE;
01326
CmpWorker(&
CommandArea);
01327
if (!
NT_SUCCESS(
CommandArea.
Status)) {
01328
goto ErrorExit;
01329 }
01330
01331 BaseBlock = (
PHBASE_BLOCK)CopyBuffer;
01332 Length = BaseBlock->
Length;
01333
01334 BaseBlock->
Sequence1++;
01335
01336
Offset = 0;
01337 offsetElement.
FileOffset =
Offset;
01338 offsetElement.
DataBuffer = CopyBuffer;
01339 offsetElement.
DataLength =
HBLOCK_SIZE;
01340
if ( !
CmpFileWrite((
PHHIVE)CmHive,
HFILE_TYPE_EXTERNAL, &offsetElement,
01341 1, &
Offset))
01342 {
01343
goto ErrorExit;
01344 }
01345
01346
01347
01348
01349
if (
CmpFileFlush((
PHHIVE)CmHive,
HFILE_TYPE_EXTERNAL)) {
01350 status = STATUS_SUCCESS;
01351 }
01352
01353
01354
01355
01356
for (Position = 0; Position < Length; Position += BytesToCopy) {
01357
01358
Offset = Position +
HBLOCK_SIZE;
01359 BytesToCopy = Length-Position;
01360
if (BytesToCopy > BufferLength) {
01361 BytesToCopy = BufferLength;
01362 }
01363
01364
CommandArea.
Command =
REG_CMD_HIVE_READ;
01365
CommandArea.
CmHive = CmHive;
01366
CommandArea.
FileType =
HFILE_TYPE_PRIMARY;
01367
CommandArea.
Offset = &
Offset;
01368
CommandArea.
Buffer = CopyBuffer;
01369
CommandArea.
FileSize = BytesToCopy;
01370
CmpWorker(&
CommandArea);
01371
if (!
NT_SUCCESS(
CommandArea.
Status)) {
01372
goto ErrorExit;
01373 }
01374
01375
Offset = Position +
HBLOCK_SIZE;
01376 offsetElement.
FileOffset =
Offset;
01377 offsetElement.
DataBuffer = CopyBuffer;
01378 offsetElement.
DataLength = BytesToCopy;
01379
if ( !
CmpFileWrite((
PHHIVE)CmHive,
HFILE_TYPE_EXTERNAL, &offsetElement,
01380 1, &
Offset))
01381 {
01382
goto ErrorExit;
01383 }
01384 }
01385
01386
01387
01388
01389
if (
CmpFileFlush((
PHHIVE)CmHive,
HFILE_TYPE_EXTERNAL)) {
01390 status = STATUS_SUCCESS;
01391 }
01392
01393
01394
01395
01396
01397
Offset = 0;
01398
CommandArea.
Command =
REG_CMD_HIVE_READ;
01399
CommandArea.
CmHive = CmHive;
01400
CommandArea.
FileType =
HFILE_TYPE_PRIMARY;
01401
CommandArea.
Offset = &
Offset;
01402
CommandArea.
Buffer = CopyBuffer;
01403
CommandArea.
FileSize =
HBLOCK_SIZE;
01404
CmpWorker(&
CommandArea);
01405
if (!
NT_SUCCESS(
CommandArea.
Status)) {
01406
goto ErrorExit;
01407 }
01408 BaseBlock->
Sequence1++;
01409 BaseBlock->
Sequence2++;
01410
01411
Offset = 0;
01412 offsetElement.
FileOffset =
Offset;
01413 offsetElement.
DataBuffer = CopyBuffer;
01414 offsetElement.
DataLength =
HBLOCK_SIZE;
01415
if ( !
CmpFileWrite((
PHHIVE)CmHive,
HFILE_TYPE_EXTERNAL, &offsetElement,
01416 1, &
Offset))
01417 {
01418
goto ErrorExit;
01419 }
01420
01421
01422
01423
01424
if (
CmpFileFlush((
PHHIVE)CmHive,
HFILE_TYPE_EXTERNAL)) {
01425 status = STATUS_SUCCESS;
01426 }
01427
01428
ErrorExit:
01429
if (CopyBuffer !=
CmpStashBuffer) {
01430
ExFreePool(CopyBuffer);
01431 }
01432 CmHive->FileHandles[
HFILE_TYPE_EXTERNAL] =
NULL;
01433
CmpUnlockRegistry();
01434
return status;
01435 }
01436
01437
01438
PCMHIVE
01439 CmpCreateTemporaryHive(
01440 IN HANDLE FileHandle
01441 )
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459 {
01460
PCMHIVE TempHive;
01461
NTSTATUS Status;
01462
01463
PAGED_CODE();
01464
01465
01466
01467
01468
01469
01470
Status =
CmpInitializeHive(&TempHive,
01471
HINIT_CREATE,
01472
HIVE_VOLATILE,
01473 0,
01474
NULL,
01475
NULL,
01476
NULL,
01477
NULL,
01478
NULL,
01479
NULL);
01480
if (
NT_SUCCESS(
Status)) {
01481
return(TempHive);
01482 }
else {
01483
return(
NULL);
01484 }
01485
01486 }
01487
01488
01489
VOID
01490 CmpDestroyTemporaryHive(
01491
PCMHIVE CmHive
01492 )
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508 {
01509
PAGED_CODE();
01510
CMLOG(
CML_MINOR,
CMS_SAVRES) {
01511 KdPrint((
"CmpDestroyTemporaryHive:\n"));
01512 KdPrint((
"\tCmHive=%08lx\n", CmHive));
01513 }
01514
01515
if (CmHive ==
NULL) {
01516
return;
01517 }
01518
01519
01520
01521
01522
01523 RemoveEntryList(&CmHive->
HiveList);
01524
01525
HvFreeHive(&(CmHive->
Hive));
01526
ASSERT( CmHive->
HiveLock );
01527
ExFreePool(CmHive->
HiveLock);
01528
CmpFree(CmHive,
sizeof(
CMHIVE));
01529
01530
return;
01531 }
01532
01533