Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

cmsavres.c File Reference

#include "cmp.h"

Go to the source code of this file.

Defines

#define CM_SAVEKEYBUFSIZE   0x10000

Functions

PCMHIVE CmpCreateTemporaryHive (IN HANDLE FileHandle)
VOID CmpDestroyTemporaryHive (PCMHIVE CmHive)
NTSTATUS CmpLoadHiveVolatile (IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN HANDLE FileHandle)
NTSTATUS CmpRefreshHive (IN PCM_KEY_CONTROL_BLOCK KeyControlBlock)
NTSTATUS CmpSaveKeyByFileCopy (PCMHIVE Hive, HANDLE FileHandle)
ULONG CmpRefreshWorkerRoutine (PCM_KEY_CONTROL_BLOCK Current, PVOID Context1, PVOID Context2)
BOOLEAN CmpMergeKeyValues (PHHIVE SourceHive, HCELL_INDEX SourceKeyCell, PCM_KEY_NODE SourceKeyNode, PHHIVE TargetHive, HCELL_INDEX TargetKeyCell, PCM_KEY_NODE TargetKeyNode)
NTSTATUS CmRestoreKey (IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN HANDLE FileHandle, IN ULONG Flags)
NTSTATUS CmSaveKey (IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN HANDLE FileHandle)
NTSTATUS CmSaveMergedKeys (IN PCM_KEY_CONTROL_BLOCK HighPrecedenceKcb, IN PCM_KEY_CONTROL_BLOCK LowPrecedenceKcb, IN HANDLE FileHandle)

Variables

PCMHIVE CmpMasterHive
BOOLEAN CmpProfileLoaded
PUCHAR CmpStashBuffer
ULONG CmpGlobalQuotaAllowed
ULONG CmpGlobalQuotaWarning
ULONG CmpGlobalQuotaUsed


Define Documentation

#define CM_SAVEKEYBUFSIZE   0x10000
 

Definition at line 27 of file cmsavres.c.

Referenced by CmpSaveKeyByFileCopy().


Function Documentation

PCMHIVE CmpCreateTemporaryHive IN HANDLE  FileHandle  ) 
 

Definition at line 1439 of file cmsavres.c.

References CmpInitializeHive(), HINIT_CREATE, HIVE_VOLATILE, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, and Status.

Referenced by CmSaveKey(), and CmSaveMergedKeys().

01444 : 01445 01446 Allocates and inits a temporary hive. 01447 01448 Arguments: 01449 01450 FileHandle - Supplies the handle of the file to back the hive. 01451 01452 Return Value: 01453 01454 Pointer to CmHive. 01455 01456 If NULL the operation failed. 01457 01458 --*/ 01459 { 01460 PCMHIVE TempHive; 01461 NTSTATUS Status; 01462 01463 PAGED_CODE(); 01464 01465 // 01466 // NOTE: Hive will get put on CmpHiveListHead list. 01467 // Make sure CmpDestroyTemporaryHive gets called to remove it. 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 }

VOID CmpDestroyTemporaryHive PCMHIVE  CmHive  ) 
 

Definition at line 1490 of file cmsavres.c.

References ASSERT, CML_MINOR, CMLOG, CmpFree(), CMS_SAVRES, ExFreePool(), _CMHIVE::Hive, _CMHIVE::HiveList, _CMHIVE::HiveLock, HvFreeHive(), NULL, and PAGED_CODE.

Referenced by CmpLoadHiveVolatile(), CmRestoreKey(), CmSaveKey(), and CmSaveMergedKeys().

01495 : 01496 01497 Frees all the pieces of a hive. 01498 01499 Arguments: 01500 01501 CmHive - CM level hive structure to free 01502 01503 Return Value: 01504 01505 None. 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 // NOTE: Hive is on CmpHiveListHead list. 01521 // Remove it. 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 }

NTSTATUS CmpLoadHiveVolatile IN PCM_KEY_CONTROL_BLOCK  KeyControlBlock,
IN HANDLE  FileHandle
 

Definition at line 484 of file cmsavres.c.

References _HHIVE::BaseBlock, Cell, _REGISTRY_COMMAND::CmHive, CmpConstructName(), CmpCopyCompressedName(), CmpCopyKeyPartial(), CmpCopyTree, CmpDestroyTemporaryHive(), CmpHKeyNameLen, CmpInitializeHive(), CmpLinkHiveToMaster(), CmpLockRegistryExclusive(), CmpMasterHive, CmpProfileLoaded, CmpSetGlobalQuotaAllowed(), CmpUnlockRegistry(), CmpWorker(), _REGISTRY_COMMAND::Command, ExAllocatePool, ExFreePool(), ExFreePoolWithTag, FALSE, _CM_KEY_NODE::Flags, HCELL_INDEX, HCELL_NIL, HFILE_TYPE_PRIMARY, HINIT_CREATE, HINIT_FILE, _CMHIVE::Hive, Hive, HIVE_VOLATILE, HvGetCell, KEY_COMP_NAME, _CELL_DATA::_u::KeyNode, L, _CM_KEY_NODE::Name, _CM_KEY_NODE::NameLength, NewName, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PagedPool, PROTECTED_POOL, REG_CMD_ADD_HIVE_LIST, _HBASE_BLOCK::RootCell, RtlAppendUnicodeStringToString(), RtlAppendUnicodeToString(), RtlCopyUnicodeString(), Status, TRUE, _CELL_DATA::u, and USHORT.

Referenced by CmRestoreKey().

00491 : 00492 00493 Creates a VOLATILE hive and loads it underneath the given Hive and Cell. 00494 The data for the volatile hive is copied out of the given file. The 00495 file is *NOT* in use by the registry when this returns. 00496 00497 Arguments: 00498 00499 Hive - Supplies the hive that the new hive is to be created under. 00500 Currently this must be the Master Hive. 00501 00502 Cell - Supplies the HCELL_INDEX of the new hive's parent. (Usually 00503 will by \Registry\User) 00504 00505 FileHandle - Supplies a handle to the hive file that will be copied 00506 into the volatile hive. 00507 00508 Return Value: 00509 00510 NTSTATUS 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 // New hives can be created only under the master hive. 00541 // 00542 00543 if (Hive != &CmpMasterHive->Hive) { 00544 CmpUnlockRegistry(); 00545 return(STATUS_INVALID_PARAMETER); 00546 } 00547 00548 // 00549 // Create a temporary hive and load the file into it 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 // Create the volatile hive. 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 // Create the target root 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 // Copy the temporary hive into the volatile hive 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 // The volatile hive now has all the right stuff in all the right places, 00617 // we just need to link it into the master hive. 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 // We've given user chance to log on, so turn on quota 00670 // 00671 if (CmpProfileLoaded == FALSE) { 00672 CmpProfileLoaded = TRUE; 00673 CmpSetGlobalQuotaAllowed(); 00674 } 00675 } 00676 00677 CmpUnlockRegistry(); 00678 return(Status); 00679 }

BOOLEAN CmpMergeKeyValues PHHIVE  SourceHive,
HCELL_INDEX  SourceKeyCell,
PCM_KEY_NODE  SourceKeyNode,
PHHIVE  TargetHive,
HCELL_INDEX  TargetKeyCell,
PCM_KEY_NODE  TargetKeyNode
 

Definition at line 1150 of file cmtrecpy.c.

References ASSERT, CmpCopyValue(), CmpFindNameInList(), CmpInitializeValueNameString(), CmpSyncKeyValues(), _CHILD_LIST::Count, ExAllocatePool, ExFreePool(), FALSE, HCELL_INDEX, HCELL_NIL, HvFreeCell(), HvGetCell, HvGetCellType, HvReallocateCell(), _CELL_DATA::_u::KeyList, _CHILD_LIST::List, MAX_KEY_VALUE_NAME_LENGTH, _CM_KEY_NODE::MaxValueDataLen, _CM_KEY_NODE::MaxValueNameLen, NTSTATUS(), NULL, PagedPool, TRUE, _CELL_DATA::u, _CM_KEY_NODE::ValueList, and ValueName.

01160 : 01161 Merges the values from the two key-nodes provided. 01162 Rules for the merge: 01163 1. The target values are not touched! 01164 2. Only values from the source that are not present in the 01165 target are taken into account by this routine. They are added 01166 to the target node value list "as they are". 01167 01168 Arguments: 01169 01170 SourceHive - Hive of the source key 01171 SourceKeyCell - The source key's cell 01172 SourceKeyNode - The source key's body 01173 01174 TargetHive - Hive of the target key 01175 TargetKeyCell - The target key's cell 01176 TargetKeyNode - The target key's body 01177 01178 Return Value: 01179 01180 TRUE of successful, FALSE otherwise. 01181 01182 --*/ 01183 { 01184 NTSTATUS status; 01185 BOOLEAN success = FALSE; 01186 PCELL_DATA psrclist, ptarlist; 01187 HCELL_INDEX newvalue, newlist = HCELL_NIL; 01188 ULONG i, count, Type; 01189 PCM_KEY_VALUE poldvalue; 01190 WCHAR *NameBuffer = NULL; 01191 UNICODE_STRING ValueName; 01192 01193 01194 if(TargetKeyNode->MaxValueNameLen < SourceKeyNode->MaxValueNameLen) { 01195 TargetKeyNode->MaxValueNameLen = SourceKeyNode->MaxValueNameLen; 01196 } 01197 01198 if(TargetKeyNode->MaxValueDataLen < SourceKeyNode->MaxValueDataLen) { 01199 TargetKeyNode->MaxValueDataLen = SourceKeyNode->MaxValueDataLen; 01200 } 01201 01202 if(TargetKeyNode->ValueList.Count == 0) { 01203 // 01204 // No Values in Target, do a sync 01205 // 01206 return CmpSyncKeyValues(SourceHive, SourceKeyCell, SourceKeyNode, TargetHive, TargetKeyCell, TargetKeyNode); 01207 } 01208 // 01209 // Set up the value list 01210 // 01211 count = SourceKeyNode->ValueList.Count; 01212 01213 if (count == 0) { 01214 01215 // No values in source, no update to the list needed. 01216 success = TRUE; 01217 } else { 01218 01219 NameBuffer = ExAllocatePool(PagedPool, MAX_KEY_VALUE_NAME_LENGTH); 01220 if(!NameBuffer) return FALSE; 01221 01222 // 01223 // The type of the new cells will be the same as that 01224 // of the target cell. 01225 // 01226 01227 Type = HvGetCellType(TargetKeyCell); 01228 01229 // 01230 // Reallocate the value list for target to fit the new size 01231 // Worst case: all values from the source node will be added 01232 // to the target node 01233 // 01234 01235 psrclist = HvGetCell(SourceHive, SourceKeyNode->ValueList.List); 01236 01237 newlist = HvReallocateCell( 01238 TargetHive, 01239 TargetKeyNode->ValueList.List, 01240 (TargetKeyNode->ValueList.Count + count) * sizeof(HCELL_INDEX) 01241 ); 01242 01243 // Growing up may fail 01244 if (newlist == HCELL_NIL) { 01245 goto EndValueMerge; 01246 } 01247 TargetKeyNode->ValueList.List = newlist; 01248 ptarlist = HvGetCell(TargetHive, newlist); 01249 01250 01251 // 01252 // Copy the values 01253 // 01254 for (i = 0; i < count; i++) { 01255 01256 poldvalue = (PCM_KEY_VALUE)HvGetCell(SourceHive, psrclist->u.KeyList[i]); 01257 01258 // 01259 // get the name 01260 // 01261 CmpInitializeValueNameString(poldvalue,&ValueName,NameBuffer); 01262 01263 01264 // 01265 // check if this particular values doesn't exist in the target node already 01266 // 01267 if(HCELL_NIL == CmpFindNameInList(TargetHive,&(TargetKeyNode->ValueList),&ValueName,NULL,NULL)) { 01268 01269 // 01270 // No, it doesn't, so add it 01271 // 01272 newvalue = CmpCopyValue( 01273 SourceHive, 01274 psrclist->u.KeyList[i], 01275 TargetHive, 01276 Type 01277 ); 01278 01279 if (newvalue != HCELL_NIL) { 01280 01281 ptarlist->u.KeyList[TargetKeyNode->ValueList.Count++] = newvalue; 01282 01283 } else { 01284 01285 // Delete all the copied values on an error. 01286 01287 for (; i > 0; i--) { 01288 HvFreeCell( 01289 TargetHive, 01290 ptarlist->u.KeyList[--TargetKeyNode->ValueList.Count] 01291 ); 01292 } 01293 goto EndValueMerge; 01294 } 01295 } 01296 } 01297 01298 // 01299 // adjust the Value list to the new count. 01300 // This call shouldn't fail (the new size is smaller or in the worst case equal to the old one) 01301 // 01302 newlist = HvReallocateCell( 01303 TargetHive, 01304 TargetKeyNode->ValueList.List, 01305 TargetKeyNode->ValueList.Count * sizeof(HCELL_INDEX) 01306 ); 01307 01308 ASSERT(newlist != HCELL_NIL); 01309 TargetKeyNode->ValueList.List = newlist; 01310 01311 success = TRUE; 01312 } 01313 01314 EndValueMerge: 01315 if (NameBuffer) ExFreePool(NameBuffer); 01316 01317 if (success == FALSE) { 01318 01319 // Clean-up on failure 01320 // Revert to the original size 01321 if (newlist != HCELL_NIL) { 01322 newlist = HvReallocateCell( 01323 TargetHive, 01324 TargetKeyNode->ValueList.List, 01325 TargetKeyNode->ValueList.Count * sizeof(HCELL_INDEX) 01326 ); 01327 01328 ASSERT(newlist != HCELL_NIL); 01329 TargetKeyNode->ValueList.List = newlist; 01330 } 01331 01332 } 01333 01334 return success; 01335 }

NTSTATUS CmpRefreshHive IN PCM_KEY_CONTROL_BLOCK  KeyControlBlock  ) 
 

Definition at line 731 of file cmsavres.c.

References ASSERT, Cell, CmpFlushNotify(), CmpLockRegistryExclusive(), CmpRefreshWorkerRoutine(), CmpSearchKeyControlBlockTree(), CmpUnlockRegistry(), CmpWorker(), _REGISTRY_COMMAND::Command, CommandArea, _CM_KEY_NODE::Flags, HCELL_INDEX, _REGISTRY_COMMAND::Hive, Hive, HIVE_NOLAZYFLUSH, _HHIVE::HiveFlags, HiveList, HvGetCell, KEY_HIVE_ENTRY, _CM_NOTIFY_BLOCK::KeyBody, _CELL_DATA::_u::KeyNode, NULL, PAGED_CODE, REG_CMD_REFRESH_HIVE, SeSinglePrivilegeCheck(), SeTcbPrivilege, TRUE, _CELL_DATA::u, and Volatile.

Referenced by CmRestoreKey().

00736 : 00737 00738 Backs out all changes to a hives since it was last flushed. 00739 Used as a transaction abort by the security system. 00740 00741 Caller must have SeTcbPrivilege. 00742 00743 The target hive must have HIVE_NOLAZYFLUSH set. 00744 00745 KeyControlBlock must refer to the root of the hive (HIVE_ENTRY must 00746 be set in the key.) 00747 00748 Any kcbs that point into this hive (and thus any handles open 00749 against it) will be force to DELETED state. (If we do any work.) 00750 00751 All notifies pending against the hive will be flushed. 00752 00753 When we're done, only the tombstone kcbs, handles, and attached 00754 notify blocks will be left. 00755 00756 WARNNOTE: Once reads have begun, if the operation fails, the hive 00757 will be corrupt, so we will bugcheck. 00758 00759 Arguments: 00760 00761 KeyControlBlock - provides a reference to the root of the hive 00762 we wish to refresh. 00763 00764 Return Value: 00765 00766 NTSTATUS 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 // Check to see if the caller has the privilege to make this call. 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 // check to see if hive is of proper type 00794 // 00795 if ( ! (Hive->HiveFlags & HIVE_NOLAZYFLUSH)) { 00796 CmpUnlockRegistry(); 00797 return STATUS_INVALID_PARAMETER; 00798 } 00799 00800 // 00801 // punt if any volatile storage has been allocated 00802 // 00803 if (Hive->Storage[Volatile].Length != 0) { 00804 CmpUnlockRegistry(); 00805 return STATUS_UNSUCCESSFUL; 00806 } 00807 00808 // 00809 // check to see if call was applied to the root of the hive 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 // Flush all NotifyBlocks attached to this hive 00819 // 00820 while (TRUE) { 00821 00822 // 00823 // flush below will edit list, so restart at beginning each time 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 // Force all kcbs that refer to this hive to the deleted state. 00838 // 00839 CmpSearchKeyControlBlockTree( 00840 CmpRefreshWorkerRoutine, 00841 (PVOID)Hive, 00842 NULL 00843 ); 00844 00845 // 00846 // We cannot do the relevent I/O from this context, so send a 00847 // command to the worker code. 00848 // 00849 CommandArea.Command = REG_CMD_REFRESH_HIVE; 00850 CommandArea.Hive = Hive; 00851 CmpWorker(&CommandArea); 00852 CmpUnlockRegistry(); 00853 // 00854 // we're back (rather than bugchecked) so it worked 00855 // 00856 return STATUS_SUCCESS; 00857 }

ULONG CmpRefreshWorkerRoutine PCM_KEY_CONTROL_BLOCK  Current,
PVOID  Context1,
PVOID  Context2
 

Definition at line 684 of file cmsavres.c.

References Context1, _CM_KEY_CONTROL_BLOCK::Delete, KCB_WORKER_CONTINUE, KCB_WORKER_DELETE, _CM_KEY_CONTROL_BLOCK::KeyCell, _CM_KEY_CONTROL_BLOCK::KeyHive, NULL, PAGED_CODE, and TRUE.

Referenced by CmpRefreshHive().

00691 : 00692 00693 Helper used by CmpRefreshHive when calling 00694 CmpSearchKeyControlBlockTree. 00695 00696 If a match is found, the KCB is deleted and restart is returned. 00697 Else, continue is returned. 00698 00699 Arguments: 00700 00701 Current - the kcb to examine 00702 00703 Context1 - the hive to match against 00704 00705 Context2 - nothing 00706 00707 Return Value: 00708 00709 if no match, return continue. 00710 00711 if match, return restart. 00712 00713 --*/ 00714 { 00715 PAGED_CODE(); 00716 if (Current->KeyHive == (PHHIVE)Context1) { 00717 00718 // 00719 // match. set deleted flag. continue search. 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 }

NTSTATUS CmpSaveKeyByFileCopy PCMHIVE  Hive,
HANDLE  FileHandle
 

Definition at line 1261 of file cmsavres.c.

References _REGISTRY_COMMAND::Buffer, CM_SAVEKEYBUFSIZE, _REGISTRY_COMMAND::CmHive, CmpFileFlush(), CmpFileWrite(), CmpLockRegistryExclusive(), CmpStashBuffer, CmpUnlockRegistry(), CmpWorker(), _REGISTRY_COMMAND::Command, CommandArea, CMP_OFFSET_ARRAY::DataBuffer, CMP_OFFSET_ARRAY::DataLength, ErrorExit(), ExAllocatePoolWithQuota, EXCEPTION_EXECUTE_HANDLER, ExFreePool(), _CMHIVE::FileHandles, CMP_OFFSET_ARRAY::FileOffset, _REGISTRY_COMMAND::FileSize, _REGISTRY_COMMAND::FileType, HBLOCK_SIZE, HFILE_TYPE_EXTERNAL, HFILE_TYPE_PRIMARY, _HBASE_BLOCK::Length, NT_SUCCESS, NTSTATUS(), NULL, _REGISTRY_COMMAND::Offset, Offset, PAGED_CODE, PagedPoolCacheAligned, REG_CMD_HIVE_READ, _HBASE_BLOCK::Sequence1, _HBASE_BLOCK::Sequence2, and _REGISTRY_COMMAND::Status.

Referenced by CmSaveKey().

01267 : 01268 01269 Do special case of SaveKey by copying the hive file 01270 01271 Arguments: 01272 01273 CmHive - supplies a pointer to an HHive 01274 01275 FileHandle - open handle to target file 01276 01277 Return Value: 01278 01279 NTSTATUS - Result code from call, among the following: 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 // Attempt to allocate large buffer for copying stuff around. If 01298 // we can't get one, just use the stash buffer. 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 // Read the base block, step the sequence number, and write it out 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 // Flush the external, so header will show corrupt until we're done 01348 // 01349 if (CmpFileFlush((PHHIVE)CmHive, HFILE_TYPE_EXTERNAL)) { 01350 status = STATUS_SUCCESS; 01351 } 01352 01353 // 01354 // For span of data, read from master and write to external 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 // Flush the external, so data is there before we update the header 01388 // 01389 if (CmpFileFlush((PHHIVE)CmHive, HFILE_TYPE_EXTERNAL)) { 01390 status = STATUS_SUCCESS; 01391 } 01392 01393 // 01394 // Reread the base block, sync the seq #, rewrite it. 01395 // (Brute force, but means no memory alloc - always works) 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++; // it got trampled when we reread it 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 // Flush the external, and we are done 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 }

NTSTATUS CmRestoreKey IN PCM_KEY_CONTROL_BLOCK  KeyControlBlock,
IN HANDLE  FileHandle,
IN ULONG  Flags
 

Definition at line 97 of file cmsavres.c.

References ASSERT, ASSERT_CM_LOCK_OWNED_EXCLUSIVE, _HHIVE::BaseBlock, _CM_INDEX::Cell, Cell, _CM_KEY_NODE::ChildHiveReference, CM_KCB_SUBKEY_HINT, CM_KEY_FAST_LEAF, CM_KEY_INDEX_ROOT, CML_MAJOR, CMLOG, CmpCleanUpKcbValueCache(), CmpCopyKeyPartial(), CmpCopyTree, CmpDeleteTree(), CmpDestroyTemporaryHive(), CmpFreeKeyByCell(), CmpInitializeHive(), CmpLoadHiveVolatile(), CmpLockRegistryExclusive(), CmpMasterHive, CmpProfileLoaded, CmpRefreshHive(), CmpReportNotify(), CmpSearchForOpenSubKeys(), CmpSetGlobalQuotaAllowed(), CmpUnlockRegistry(), CMS_SAVRES, _CM_KEY_FAST_INDEX::Count, _CM_KEY_INDEX::Count, DCmCheckRegistry, ExFreePoolWithTag, FALSE, _CM_KEY_NODE::Flags, HCELL_INDEX, HCELL_NIL, HFILE_TYPE_PRIMARY, HINIT_FILE, _CMHIVE::Hive, Hive, HSTORAGE_TYPE, HvGetCell, HvGetCellType, HvReallocateCell(), KEY_COMP_NAME, KEY_HIVE_ENTRY, _CM_KEY_REFERENCE::KeyCell, _CELL_DATA::_u::KeyIndex, _CELL_DATA::_u::KeyNode, _CM_KEY_FAST_INDEX::List, _CM_KEY_INDEX::List, _CM_KEY_NODE::Name, Name, _CM_KEY_NODE::NameLength, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, _CM_KEY_NODE::Parent, PHCELL_INDEX, PROTECTED_POOL, _HBASE_BLOCK::RootCell, _CM_KEY_INDEX::Signature, _CM_KEY_NODE::SubKeyCounts, _CM_KEY_NODE::SubKeyLists, TRUE, and _CELL_DATA::u.

Referenced by NtRestoreKey().

00104 : 00105 00106 This copies the data from an on-disk hive into the registry. The file 00107 is not loaded into the registry, and the system will NOT be using 00108 the source file after the call returns. 00109 00110 If the flag REG_WHOLE_HIVE_VOLATILE is not set, the given key is replaced 00111 by the root of the hive file. The root's name is changed to the name 00112 of the given key. 00113 00114 If the flag REG_WHOLE_HIVE_VOLATILE is set, a volatile hive is created, 00115 the hive file is copied into it, and the resulting hive is linked to 00116 the master hive. The given key must be in the master hive. (Usually 00117 will be \Registry\User) 00118 00119 If the flag REG_REFRESH_HIVE is set (must be only flag) then the 00120 the Hive will be restored to its state as of the last flush. 00121 (The hive must be marked NOLAZY_FLUSH, and the caller must have 00122 TCB privilege, and the handle must point to the root of the hive. 00123 If the refresh fails, the hive will be corrupt, and the system 00124 will bugcheck.) 00125 00126 If the flag REG_FORCE_RESTORE is set, the restore operation is done even 00127 if there areopen handles underneath the key we are restoring to. 00128 00129 Arguments: 00130 00131 Hive - supplies a pointer to the hive control structure for the hive 00132 00133 Cell - supplies index of node at root of tree to restore into 00134 00135 FileHandle - handle of the file to read from. 00136 00137 Return Value: 00138 00139 NTSTATUS - Result code from call, among the following: 00140 00141 <TBS> 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 // Refresh must be alone 00176 // 00177 return STATUS_INVALID_PARAMETER; 00178 } 00179 } 00180 00181 // 00182 // If they want to do WHOLE_HIVE_VOLATILE, it's a completely different API. 00183 // 00184 if (Flags & REG_WHOLE_HIVE_VOLATILE) { 00185 return(CmpLoadHiveVolatile(KeyControlBlock, FileHandle)); 00186 } 00187 00188 // 00189 // If they want to do REFRESH_HIVE, that's a completely different api too. 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 // Disallow attempts to "restore" the master hive 00203 // 00204 if (Hive == &CmpMasterHive->Hive) { 00205 return STATUS_ACCESS_DENIED; 00206 } 00207 00208 CmpLockRegistryExclusive(); 00209 00210 // 00211 // Make sure this key has not been deleted 00212 // 00213 if (KeyControlBlock->Delete) { 00214 CmpUnlockRegistry(); 00215 return(STATUS_CANNOT_DELETE); 00216 } 00217 00218 DCmCheckRegistry(CONTAINING_RECORD(Hive, CMHIVE, Hive)); 00219 00220 // 00221 // Check for any open handles underneath the key we are restoring to. 00222 // 00223 if (CmpSearchForOpenSubKeys(KeyControlBlock,(Flags&REG_FORCE_RESTORE)?SearchAndDeref:SearchIfExist) != 0) { 00224 00225 // 00226 // Cannot restore over a subtree with open handles in it, or the open handles to subkeys 00227 // successfully marked as closed. 00228 // 00229 00230 CmpUnlockRegistry(); 00231 return(STATUS_CANNOT_DELETE); 00232 } 00233 00234 // 00235 // Make sure this is the only handle open for this key 00236 // 00237 if (KeyControlBlock->RefCount != 1 && !(Flags&REG_FORCE_RESTORE)) { 00238 CmpUnlockRegistry(); 00239 return(STATUS_CANNOT_DELETE); 00240 } 00241 00242 ptar = HvGetCell(Hive, Cell); 00243 00244 // 00245 // The subtree the caller wants does not exactly match a 00246 // subtree. Make a temporary hive, load the file into it, 00247 // tree copy the temporary to the active, and free the temporary. 00248 // 00249 00250 // 00251 // Create the temporary hive 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 // Create a new target root, under which we will copy the new tree 00270 // 00271 if (ptar->u.KeyNode.Flags & KEY_HIVE_ENTRY) { 00272 parent = HCELL_NIL; // root of hive, so parent is 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 // newroot has all the correct stuff, except that it has the 00289 // source root's name, when it needs to have the target root's. 00290 // So edit its name. 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 // make sure that new root has correct amount of space 00298 // to hold name from old root 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 // newroot is now ready to have subtree copied under it, do tree copy 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 // The new root and the tree under it now look the way we want. 00335 // 00336 00337 // 00338 // Swap the new tree in for the old one. 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 // root is actually the root of the hive. parent doesn't 00347 // refer to it via a child list, but rather with an inter hive 00348 // pointer. also, must update base block 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 // Notice that new root is *always* name of existing target, 00361 // therefore, even in b-tree, old and new cell can share 00362 // the same reference slot in the parent. So simply edit 00363 // the new cell_index on the top of the old. 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 // Look in each leaf for the HCELL_INDEX we need to replace 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); // implies we didn't find it 00403 // we should never get here 00404 } 00405 00406 FoundCell: 00407 00408 00409 // 00410 // Fix up the key control block to point to the new root 00411 // 00412 KeyControlBlock->KeyCell = newroot; 00413 KeyControlBlock->KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, newroot); 00414 00415 // 00416 // Kcb has changed, update the cache information. 00417 // Registry locked exclusively, no need for KCB lock. 00418 // 00419 ASSERT_CM_LOCK_OWNED_EXCLUSIVE(); 00420 00421 CmpCleanUpKcbValueCache(KeyControlBlock); 00422 00423 if (KeyControlBlock->ExtFlags & CM_KCB_SUBKEY_HINT) { 00424 // 00425 // Now free the HintIndex allocation 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 // Delete the old subtree and it's root cell 00439 // 00440 CmpDeleteTree(Hive, Cell); 00441 CmpFreeKeyByCell(Hive, Cell, FALSE); 00442 00443 // 00444 // Report the notify event 00445 // 00446 CmpReportNotify(KeyControlBlock, 00447 KeyControlBlock->KeyHive, 00448 KeyControlBlock->KeyCell, 00449 REG_NOTIFY_CHANGE_NAME); 00450 00451 00452 // 00453 // Free the temporary hive 00454 // 00455 CmpDestroyTemporaryHive(TmpCmHive); 00456 00457 // 00458 // We've given user chance to log on, so turn on quota 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 // Error exits 00472 // 00473 ErrorExit2: 00474 CmpDestroyTemporaryHive(TmpCmHive); 00475 ErrorExit1: 00476 DCmCheckRegistry(CONTAINING_RECORD(Hive, CMHIVE, Hive)); 00477 CmpUnlockRegistry(); 00478 00479 return status; 00480 }

NTSTATUS CmSaveKey IN PCM_KEY_CONTROL_BLOCK  KeyControlBlock,
IN HANDLE  FileHandle
 

Definition at line 862 of file cmsavres.c.

References ASSERT, _HHIVE::BaseBlock, Cell, CM_WRAP_LIMIT, CML_FLOW, CML_MAJOR, CMLOG, CmpCopyKeyPartial(), CmpCopyTree, CmpCreateTemporaryHive(), CmpDestroyTemporaryHive(), CmpGlobalQuotaAllowed, CmpGlobalQuotaUsed, CmpGlobalQuotaWarning, CmpLockRegistryExclusive(), CmpMasterHive, CmpSaveKeyByFileCopy(), CmpUnlockRegistry(), CMS_SAVRES, DCmCheckRegistry, _HHIVE::DirtyCount, FALSE, _CMHIVE::FileHandles, _CM_KEY_NODE::Flags, HCELL_INDEX, HCELL_NIL, HFILE_TYPE_EXTERNAL, _CMHIVE::Hive, Hive, HIVE_NOLAZYFLUSH, _HHIVE::HiveFlags, HvGetCell, HvWriteHive(), _CELL_DATA::_u::KeyNode, NTSTATUS(), NULL, PAGED_CODE, _HBASE_BLOCK::RootCell, TRUE, _CELL_DATA::u, and USHORT.

Referenced by NtSaveKey().

00868 : 00869 00870 Arguments: 00871 00872 KeyControlBlock - pointer to the KCB that describes the key 00873 00874 FileHandle - handle of the file to dump to. 00875 00876 Return Value: 00877 00878 NTSTATUS - Result code from call, among the following: 00879 00880 <TBS> 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 // Disallow attempts to "save" the master hive 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 // It's a NOLAZY hive, and there's some dirty data, so writing 00929 // out a snapshot of what's in memory will not give the caller 00930 // consistent user data. Therefore, copy the on disk image 00931 // instead of the memory image 00932 // 00933 00934 // 00935 // Note that this will generate weird results if the key 00936 // being saved is not the root of the hive, since the 00937 // resulting file will always be a copy of the entire hive, not 00938 // just the subtree they asked for. 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 // Always try to copy the hive and write it out. This has the 00951 // effect of compressing out unused free storage. 00952 // If there isn't space, and the savekey is of the root of the 00953 // hive, then just write it out directly. (i.e. don't fail on 00954 // a whole hive restore just because we're out of memory.) 00955 // 00956 CMLOG(CML_FLOW, CMS_SAVRES) KdPrint(("\tSave of partial hive\n")); 00957 00958 // 00959 // The subtree the caller wants does not exactly match a 00960 // subtree. Make a temporary hive, tree copy the source 00961 // to temp, write out the temporary, free the temporary. 00962 // 00963 00964 // 00965 // temporarily disable registry quota as we will be giving this memory back immediately! 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 // Create the temporary hive 00978 // 00979 00980 TmpCmHive = CmpCreateTemporaryHive(FileHandle); 00981 if (TmpCmHive == NULL) { 00982 status = STATUS_INSUFFICIENT_RESOURCES; 00983 goto ErrorInsufficientResources; 00984 } 00985 00986 // 00987 // Create a root cell, mark it as such 00988 // 00989 00990 newroot = CmpCopyKeyPartial( 00991 Hive, 00992 Cell, 00993 &(TmpCmHive->Hive), 00994 HCELL_NIL, // will force KEY_HIVE_ENTRY set 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 // Do a tree copy 01004 // 01005 if (CmpCopyTree(Hive, Cell, &(TmpCmHive->Hive), newroot) == FALSE) { 01006 status = STATUS_INSUFFICIENT_RESOURCES; 01007 goto ErrorInsufficientResources; 01008 } 01009 01010 // 01011 // Write the file 01012 // 01013 TmpCmHive->FileHandles[HFILE_TYPE_EXTERNAL] = FileHandle; 01014 status = HvWriteHive(&(TmpCmHive->Hive)); 01015 TmpCmHive->FileHandles[HFILE_TYPE_EXTERNAL] = NULL; 01016 01017 // 01018 // Error exits 01019 // 01020 ErrorInsufficientResources: 01021 01022 // 01023 // Free the temporary hive 01024 // 01025 if (TmpCmHive != NULL) { 01026 CmpDestroyTemporaryHive(TmpCmHive); 01027 } 01028 01029 #if DBG 01030 // 01031 // Sanity check: when this assert fires, we have leaks in the copy routine. 01032 // 01033 ASSERT( OldQuotaUsed == CmpGlobalQuotaUsed ); 01034 #endif 01035 01036 // 01037 // Set global quota back to what it was. 01038 // 01039 CmpGlobalQuotaAllowed = OldQuotaAllowed; 01040 CmpGlobalQuotaWarning = OldQuotaWarning; 01041 DCmCheckRegistry(CONTAINING_RECORD(Hive, CMHIVE, Hive)); 01042 CmpUnlockRegistry(); 01043 return status; 01044 }

NTSTATUS CmSaveMergedKeys IN PCM_KEY_CONTROL_BLOCK  HighPrecedenceKcb,
IN PCM_KEY_CONTROL_BLOCK  LowPrecedenceKcb,
IN HANDLE  FileHandle
 

Definition at line 1047 of file cmsavres.c.

References ASSERT, _HHIVE::BaseBlock, CM_WRAP_LIMIT, CML_FLOW, CML_MAJOR, CMLOG, CmpCopyKeyPartial(), CmpCopyTree, CmpCreateTemporaryHive(), CmpDestroyTemporaryHive(), CmpGlobalQuotaAllowed, CmpGlobalQuotaUsed, CmpGlobalQuotaWarning, CmpLockRegistryExclusive(), CmpMergeKeyValues(), CmpMergeTrees, CmpUnlockRegistry(), CMS_SAVRES, DCmCheckRegistry, _HHIVE::DirtyCount, FALSE, _CMHIVE::FileHandles, _CM_KEY_NODE::Flags, HCELL_INDEX, HCELL_NIL, HFILE_TYPE_EXTERNAL, _CMHIVE::Hive, Hive, HIVE_NOLAZYFLUSH, _HHIVE::HiveFlags, HvGetCell, HvWriteHive(), _CELL_DATA::_u::KeyNode, NTSTATUS(), NULL, PAGED_CODE, _HBASE_BLOCK::RootCell, TRUE, _CELL_DATA::u, and USHORT.

Referenced by NtSaveMergedKeys().

01054 : 01055 01056 Arguments: 01057 01058 HighPrecedenceKcb - pointer to the KCB that describes the High precedence key 01059 (the one that wins in a duplicate key case) 01060 01061 LowPrecedenceKcb - pointer to the KCB that describes the Low precedence key 01062 (the one that gets overwritten in a duplicate key case) 01063 01064 FileHandle - handle of the file to dump to. 01065 01066 Return Value: 01067 01068 NTSTATUS - Result code from call, among the following: 01069 01070 <TBS> 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 // Disallow attempts to "merge" keys located in the same hive 01100 // A brutal way to avoid recursivity 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 // Unlock the registry and fail if one of the keys are marked as deleted 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 // Reject the call when one of the hives is a NOLAZY hive and there's 01129 // some dirty data. Another alternative will be to save only one of the 01130 // trees (if a valid one exists) or an entire hive (see CmSaveKey) 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 // Make a temporary hive, tree copy the key subtree from 01145 // HighHive hive to temp, tree-merge with the key subtree from 01146 // LowHive hive, write out the temporary, free the temporary. 01147 // Always write the HighHive subtree first, so its afterwise 01148 // only add new keys/values 01149 // 01150 01151 // 01152 // temporarily disable registry quota as we will be giving this memory back immediately! 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 // Create the temporary hive 01165 // 01166 01167 TmpCmHive = CmpCreateTemporaryHive(FileHandle); 01168 if (TmpCmHive == NULL) { 01169 status = STATUS_INSUFFICIENT_RESOURCES; 01170 goto ErrorInsufficientResources; 01171 } 01172 01173 // 01174 // Create a root cell, mark it as such 01175 // 01176 01177 newroot = CmpCopyKeyPartial( 01178 HighHive, 01179 HighCell, 01180 &(TmpCmHive->Hive), 01181 HCELL_NIL, // will force KEY_HIVE_ENTRY set 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 // Do a tree copy. Copy the HighCell tree from HighHive first. 01191 // 01192 if (CmpCopyTree(HighHive, HighCell, &(TmpCmHive->Hive), newroot) == FALSE) { 01193 status = STATUS_INSUFFICIENT_RESOURCES; 01194 goto ErrorInsufficientResources; 01195 } 01196 01197 // 01198 // Merge the values in the root node of the merged subtrees 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 // Merge the two trees. A Merge operation is a sync that obeys 01212 // the following aditional rules: 01213 // 1. keys the exist in the taget tree and does not exist 01214 // in the source tree remain as they are (don't get deleted) 01215 // 2. keys the doesn't exist both in the target tree are added 01216 // "as they are" from the source tree (always the target tree 01217 // has a higher precedence) 01218 // 01219 if (CmpMergeTrees(LowHive, LowCell, &(TmpCmHive->Hive), newroot) == FALSE) { 01220 status = STATUS_INSUFFICIENT_RESOURCES; 01221 goto ErrorInsufficientResources; 01222 } 01223 01224 // 01225 // Write the file 01226 // 01227 TmpCmHive->FileHandles[HFILE_TYPE_EXTERNAL] = FileHandle; 01228 status = HvWriteHive(&(TmpCmHive->Hive)); 01229 TmpCmHive->FileHandles[HFILE_TYPE_EXTERNAL] = NULL; 01230 01231 // 01232 // Error exits 01233 // 01234 ErrorInsufficientResources: 01235 // 01236 // Free the temporary hive 01237 // 01238 if (TmpCmHive != NULL) { 01239 CmpDestroyTemporaryHive(TmpCmHive); 01240 } 01241 01242 #if DBG 01243 // 01244 // Sanity check: when this assert fires, we have leaks in the merge routine. 01245 // 01246 ASSERT( OldQuotaUsed == CmpGlobalQuotaUsed ); 01247 #endif 01248 // 01249 // Set global quota back to what it was. 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 }


Variable Documentation

ULONG CmpGlobalQuotaAllowed
 

Definition at line 34 of file cmsavres.c.

ULONG CmpGlobalQuotaUsed
 

Definition at line 36 of file cmsavres.c.

Referenced by CmpClaimGlobalQuota(), CmpReleaseGlobalQuota(), CmQueryRegistryQuotaInformation(), CmSaveKey(), and CmSaveMergedKeys().

ULONG CmpGlobalQuotaWarning
 

Definition at line 35 of file cmsavres.c.

PCMHIVE CmpMasterHive
 

Definition at line 29 of file cmsavres.c.

BOOLEAN CmpProfileLoaded
 

Definition at line 31 of file cmsavres.c.

PUCHAR CmpStashBuffer
 

Definition at line 33 of file cmsavres.c.


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