test: cmapi.c File Reference

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

# cmapi.c File Reference

`#include "cmp.h"`

Go to the source code of this file.

## Functions

NTSTATUS | CmpSetValueKeyExisting (IN PHHIVE Hive, IN HCELL_INDEX OldChild, IN PCELL_DATA Value, IN ULONG Type, IN PVOID Data, IN ULONG DataSize, IN ULONG StorageType, IN ULONG TempData)
NTSTATUS | CmpSetValueKeyNew (IN PHHIVE Hive, IN PCM_KEY_NODE Parent, IN PUNICODE_STRING ValueName, IN ULONG Type, IN PVOID Data, IN ULONG DataSize, IN ULONG StorageType, IN ULONG TempData)
NTSTATUS | CmDeleteValueKey (IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN UNICODE_STRING ValueName)
NTSTATUS | CmEnumerateKey (IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN ULONG Index, IN KEY_INFORMATION_CLASS KeyInformationClass, IN PVOID KeyInformation, IN ULONG Length, IN PULONG ResultLength)
NTSTATUS | CmEnumerateValueKey (IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN ULONG Index, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, IN PVOID KeyValueInformation, IN ULONG Length, IN PULONG ResultLength)
NTSTATUS | CmFlushKey (IN PHHIVE Hive, IN HCELL_INDEX Cell)
NTSTATUS | CmQueryKey (IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN KEY_INFORMATION_CLASS KeyInformationClass, IN PVOID KeyInformation, IN ULONG Length, IN PULONG ResultLength)
NTSTATUS | CmQueryValueKey (IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN UNICODE_STRING ValueName, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, IN PVOID KeyValueInformation, IN ULONG Length, IN PULONG ResultLength)
NTSTATUS | CmQueryMultipleValueKey (IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN PKEY_VALUE_ENTRY ValueEntries, IN ULONG EntryCount, IN PVOID ValueBuffer, IN OUT PULONG BufferLength, IN OPTIONAL PULONG ResultLength)
NTSTATUS | CmSetValueKey (IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN PUNICODE_STRING ValueName, IN ULONG Type, IN PVOID Data, IN ULONG DataSize)
NTSTATUS | CmSetLastWriteTimeKey (IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN PLARGE_INTEGER LastWriteTime)
NTSTATUS | CmLoadKey (IN POBJECT_ATTRIBUTES TargetKey, IN POBJECT_ATTRIBUTES SourceFile, IN ULONG Flags)
NTSTATUS | CmUnloadKey (IN PHHIVE Hive, IN HCELL_INDEX Cell, IN PCM_KEY_CONTROL_BLOCK Kcb)
BOOLEAN | CmpDoFlushAll (VOID)
NTSTATUS | CmReplaceKey (IN PHHIVE Hive, IN HCELL_INDEX Cell, IN PUNICODE_STRING NewHiveName, IN PUNICODE_STRING OldFileName)

## Variables

BOOLEAN | CmpNoWrite
LIST_ENTRY | CmpHiveListHead
BOOLEAN | CmpProfileLoaded
BOOLEAN | CmpWasSetupBoot
PUCHAR | CmpStashBuffer
ULONG | CmpStashBufferSize
UNICODE_STRING | CmSymbolicLinkValueName
ULONG | CmpGlobalQuotaAllowed
ULONG | CmpGlobalQuotaWarning

## Function Documentation

NTSTATUS CmDeleteValueKey | ( | IN PCM_KEY_CONTROL_BLOCK | KeyControlBlock,
|  | IN UNICODE_STRING | ValueName
| ) |

Definition at line 92 of file cmapi.c.

References ASSERT, ASSERT_CM_LOCK_OWNED_EXCLUSIVE, Cell, CML_WORKER, CMLOG, CmpCleanUpKcbValueCache(), CmpFindNameInList(), CmpFreeValue(), CmpIsHKeyValueSmall, CmpLockRegistryExclusive(), CmpMarkAllBinsReadOnly, CmpReportNotify(), CmpUnlockRegistry(), CMS_CM, _CHILD_LIST::Count, _CM_KEY_VALUE::Data, _CM_KEY_VALUE::DataLength, HCELL_INDEX, HCELL_NIL, Hive, HvFreeCell(), HvGetCell, HvMarkCellDirty(), HvReallocateCell(), KeQuerySystemTime(), _CELL_DATA::_u::KeyList, _CELL_DATA::_u::KeyValue, _CM_KEY_NODE::LastWriteTime, _CHILD_LIST::List, _CM_KEY_NODE::MaxValueDataLen, _CM_KEY_NODE::MaxValueNameLen, NTSTATUS(), PCHILD_LIST, PCM_KEY_CONTROL_BLOCK, _CELL_DATA::u, _CM_KEY_NODE::ValueList, and ValueName.

Referenced by EhDeleteValueKey(), and NtDeleteValueKey().

    00098                    :
    00099
    00100     One of the value entries of a registry key may be removed with this call.
    00101
    00102     The value entry with ValueName matching ValueName is removed from the key.
    00103     If no such entry exists, an error is returned.
    00104
    00105 Arguments:
    00106
    00107     KeyControlBlock - pointer to kcb for key to operate on
    00108
    00109     ValueName - The name of the value to be deleted.  NULL is a legal name.
    00110
    00111 Return Value:
    00112
    00113     NTSTATUS - Result code from call, among the following:
    00114
    00115         <TBS>
    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         // no edits, not even this one, on keys marked for deletion
    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         // Mark the hive as read only
    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             // The parent has at least one value, map in the list of
    00160             // values and call CmpFindChildInList
    00161             //
    00162
    00163             //
    00164             // plist -> the CHILD_LIST structure
    00165             // pchild -> the child node structure being examined
    00166             //
    00167
    00168             ChildCell = CmpFindNameInList(Hive,
    00169                                           plist,
    00170                                           &ValueName,
    00171                                           &targetaddress,
    00172                                           &targetindex);
    00173
    00174             if (ChildCell != HCELL_NIL) {
    00175
    00176                 //
    00177                 // 1. the desired target was found
    00178                 // 2. ChildCell is it's HCELL_INDEX
    00179                 // 3. targetaddress points to it
    00180                 // 4. targetindex is it's index
    00181                 //
    00182
    00183                 //
    00184                 // attempt to mark all relevent cells dirty
    00185                 //
    00186                 if (!(HvMarkCellDirty(Hive, Cell) &&
    00187                       HvMarkCellDirty(Hive, pcell->ValueList.List) &&
    00188                       HvMarkCellDirty(Hive, ChildCell)))
    00189
    00190                 {
    00191                     // Mark the hive as read only
    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                         // Mark the hive as read only
    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                     // more than one entry list, squeeze
    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                     // list is empty, free it
    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                 // We are changing the KCB cache. Since the registry is locked exclusively,
    00250                 // we do not need a KCB lock.
    00251                 //
    00252                 ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
    00253
    00254                 //
    00255                 // Invalidate the cache
    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     // Mark the hive as read only
    00278     CmpMarkAllBinsReadOnly(Hive);
    00279
    00280     return status;
    00281 }

NTSTATUS CmEnumerateKey | ( | IN PCM_KEY_CONTROL_BLOCK | KeyControlBlock,
|  | IN ULONG | Index,
|  | IN KEY_INFORMATION_CLASS | KeyInformationClass,
|  | IN PVOID | KeyInformation,
|  | IN ULONG | Length,
|  | IN PULONG | ResultLength
| ) |

Definition at line 285 of file cmapi.c.

References Cell, CML_WORKER, CMLOG, CmpFindSubKeyByNumber(), CmpLockRegistry(), CmpMarkAllBinsReadOnly, CmpQueryKeyData(), CmpUnlockRegistry(), CMS_CM, EXCEPTION_EXECUTE_HANDLER, HCELL_INDEX, HCELL_NIL, Hive, HvGetCell, Index, and NTSTATUS().

Referenced by EhEnumerateKey(), and NtEnumerateKey().

    00295                    :
    00296
    00297     Enumerate sub keys, return data on Index'th entry.
    00298
    00299     CmEnumerateKey returns the name of the Index'th sub key of the open
    00300     key specified.  The value STATUS_NO_MORE_ENTRIES will be
    00301     returned if value of Index is larger than the number of sub keys.
    00302
    00303     Note that Index is simply a way to select among child keys.  Two calls
    00304     to CmEnumerateKey with the same Index are NOT guaranteed to return
    00305     the same results.
    00306
    00307     If KeyInformation is not long enough to hold all requested data,
    00308     STATUS_BUFFER_OVERFLOW will be returned, and ResultLength will be
    00309     set to the number of bytes actually required.
    00310
    00311 Arguments:
    00312
    00313     KeyControlBlock - pointer to the KCB that describes the key
    00314
    00315     Index - Specifies the (0-based) number of the sub key to be returned.
    00316
    00317     KeyInformationClass - Specifies the type of information returned in
    00318         Buffer.  One of the following types:
    00319
    00320         KeyBasicInformation - return last write time, title index, and name.
    00321             (see KEY_BASIC_INFORMATION structure)
    00322
    00323         KeyNodeInformation - return last write time, title index, name, class.
    00324             (see KEY_NODE_INFORMATION structure)
    00325
    00326     KeyInformation -Supplies pointer to buffer to receive the data.
    00327
    00328     Length - Length of KeyInformation in bytes.
    00329
    00330     ResultLength - Number of bytes actually written into KeyInformation.
    00331
    00332 Return Value:
    00333
    00334     NTSTATUS - Result code from call, among the following:
    00335
    00336         <TBS>
    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     // Mark the hive as read only
    00360     CmpMarkAllBinsReadOnly(Hive);
    00361
    00362     //
    00363     // fetch the child of interest
    00364     //
    00365
    00366     childcell = CmpFindSubKeyByNumber(Hive, KeyControlBlock->KeyNode, Index);
    00367     if (childcell == HCELL_NIL) {
    00368         //
    00369         // no such child, clean up and return error
    00370         //
    00371
    00372         CmpUnlockRegistry();
    00373
    00374         // Mark the hive as read only
    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         // call a worker to perform data transfer
    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         // Mark the hive as read only
    00400         CmpMarkAllBinsReadOnly(Hive);
    00401
    00402         return status;
    00403     }
    00404
    00405     CmpUnlockRegistry();
    00406
    00407     // Mark the hive as read only
    00408     CmpMarkAllBinsReadOnly(Hive);
    00409
    00410     return status;
    00411 }

NTSTATUS CmEnumerateValueKey | ( | IN PCM_KEY_CONTROL_BLOCK | KeyControlBlock,
|  | IN ULONG | Index,
|  | IN KEY_VALUE_INFORMATION_CLASS | KeyValueInformationClass,
|  | IN PVOID | KeyValueInformation,
|  | IN ULONG | Length,
|  | IN PULONG | ResultLength
| ) |

Definition at line 416 of file cmapi.c.

References CM_KCB_SYM_LINK_FOUND, CML_WORKER, CMLOG, CMP_GET_CACHED_ADDRESS, CmpDereferenceKeyControlBlockWithLock(), CmpGetValueKeyFromCache(), CmpGetValueListFromCache(), CmpLockRegistry(), CmpMakeValueCacheReadOnly, CmpMakeValueCacheReadWrite, CmpMarkAllBinsReadOnly, CmpQueryKeyValueData(), CmpUnlockRegistry(), CMS_CM, Hive, Index, LOCK_KCB_TREE, NTSTATUS(), PCM_KEY_VALUE, PPCM_CACHED_VALUE, and UNLOCK_KCB_TREE.

Referenced by EhEnumerateValueKey(), and NtEnumerateValueKey().

    00426                    :
    00427
    00428     The value entries of an open key may be enumerated.
    00429
    00430     CmEnumerateValueKey returns the name of the Index'th value
    00431     entry of the open key specified by KeyHandle.  The value
    00432     STATUS_NO_MORE_ENTRIES will be returned if value of Index is
    00433     larger than the number of sub keys.
    00434
    00435     Note that Index is simply a way to select among value
    00436     entries.  Two calls to NtEnumerateValueKey with the same Index
    00437     are NOT guaranteed to return the same results.
    00438
    00439     If KeyValueInformation is not long enough to hold all requested data,
    00440     STATUS_BUFFER_OVERFLOW will be returned, and ResultLength will be
    00441     set to the number of bytes actually required.
    00442
    00443 Arguments:
    00444
    00445     KeyControlBlock - pointer to the KCB that describes the key
    00446
    00447     Index - Specifies the (0-based) number of the sub key to be returned.
    00448
    00449     KeyValueInformationClass - Specifies the type of information returned
    00450     in Buffer. One of the following types:
    00451
    00452         KeyValueBasicInformation - return time of last write,
    00453             title index, and name.  (See KEY_VALUE_BASIC_INFORMATION)
    00454
    00455         KeyValueFullInformation - return time of last write,
    00456             title index, name, class.  (See KEY_VALUE_FULL_INFORMATION)
    00457
    00458     KeyValueInformation -Supplies pointer to buffer to receive the data.
    00459
    00460     Length - Length of KeyValueInformation in bytes.
    00461
    00462     ResultLength - Number of bytes actually written into KeyValueInformation.
    00463
    00464 Return Value:
    00465
    00466     NTSTATUS - Result code from call, among the following:
    00467
    00468         <TBS>
    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     // lock the parent cell
    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     // fetch the child of interest
    00499     //
    00500     //
    00501     // Do it using the cache
    00502     //
    00503     if (Index >= KeyControlBlock->ValueCache.Count) {
    00504         //
    00505         // No such child, clean up and return error.
    00506         //
    00507         CmpUnlockRegistry();
    00508         return(STATUS_NO_MORE_ENTRIES);
    00509     }
    00510
    00511     // Mark the hive as read only
    00512     CmpMarkAllBinsReadOnly(Hive);
    00513
    00514     LOCK_KCB_TREE();
    00515     if (KeyControlBlock->ExtFlags & CM_KCB_SYM_LINK_FOUND) {
    00516         //
    00517         // The value list is now set to the KCB for symbolic link,
    00518         // Clean it up and set the value right before we do the query.
    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         // Trying to catch the BAD guy who writes over our pool.
    00533         CmpMakeValueCacheReadWrite(ValueCached,CMP_GET_CACHED_ADDRESS(KeyControlBlock->ValueCache.ValueList));
    00534
    00535         //
    00536         // call a worker to perform data transfer
    00537         //
    00538         status = CmpQueryKeyValueData(Hive,
    00539                                   ContainingList,
    00540                                   ValueData,
    00541                                   ValueCached,
    00542                                   KeyValueInformationClass,
    00543                                   KeyValueInformation,
    00544                                   Length,
    00545                                   ResultLength);
    00546
    00547          // Trying to catch the BAD guy who writes over our pool.
    00548         CmpMakeValueCacheReadOnly(ValueCached,CMP_GET_CACHED_ADDRESS(KeyControlBlock->ValueCache.ValueList));
    00549     } finally {
    00550
    00551         UNLOCK_KCB_TREE();
    00552         CmpUnlockRegistry();
    00553     }
    00554
    00555     // Mark the hive as read only
    00556     CmpMarkAllBinsReadOnly(Hive);
    00557
    00558     return status;
    00559 }

NTSTATUS CmFlushKey | ( | IN PHHIVE | Hive,
|  | IN HCELL_INDEX | Cell
| ) |

Definition at line 564 of file cmapi.c.

References CMHIVE, CML_MAJOR, CML_WORKER, CmLockHive, CMLOG, CmpDoFlushAll(), CmpMarkAllBinsReadOnly, CmpMasterHive, CmpNoWrite, CMS_CM, CMS_IO_ERROR, CmUnlockHive, DCmCheckRegistry, Hive, HvSyncHive(), NTSTATUS(), and PCMHIVE.

Referenced by CmpWorker(), and CmpWorkerCommand().

    00570                    :
    00571
    00572     Forces changes made to a key to disk.
    00573
    00574     CmFlushKey will not return to its caller until any changed data
    00575     associated with the key has been written out.
    00576
    00577     WARNING: CmFlushKey will flush the entire registry tree, and thus will
    00578     burn cycles and I/O.
    00579
    00580 Arguments:
    00581
    00582     Hive - supplies a pointer to the hive control structure for the hive
    00583
    00584     Cell - supplies index of node to whose sub keys are to be found
    00585
    00586 Return Value:
    00587
    00588     NTSTATUS - Result code from call, among the following:
    00589
    00590         <TBS>
    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     // If writes are not working, lie and say we succeeded, will
    00602     // clean up in a short time.  Only early system init code
    00603     // will ever know the difference.
    00604     //
    00605     if (CmpNoWrite) {
    00606         return STATUS_SUCCESS;
    00607     }
    00608
    00609
    00610     // Mark the hive as read only
    00611     CmpMarkAllBinsReadOnly(Hive);
    00612
    00613     CmHive = CONTAINING_RECORD(Hive, CMHIVE, Hive);
    00614
    00615     //
    00616     // Don't flush the master hive.  If somebody asks for a flushkey on
    00617     // the master hive, do a CmpDoFlushAll instead.  CmpDoFlushAll flushes
    00618     // every hive except the master hive, which is what they REALLY want.
    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     // Mark the hive as read only
    00640     CmpMarkAllBinsReadOnly(Hive);
    00641
    00642     return  status;
    00643 }

NTSTATUS CmLoadKey | ( | IN POBJECT_ATTRIBUTES | TargetKey,
|  | IN POBJECT_ATTRIBUTES | SourceFile,
|  | IN ULONG | Flags
| ) |

Definition at line 1901 of file cmapi.c.

References _REGISTRY_COMMAND::Allocate, ASSERT, _REGISTRY_COMMAND::CmHive, CmpLinkHiveToMaster(), CmpProfileLoaded, CmpSetGlobalQuotaAllowed(), CmpUnlockRegistry(), CmpWasSetupBoot, CmpWorker(), _REGISTRY_COMMAND::Command, FALSE, _REGISTRY_COMMAND::FileAttributes, _CMHIVE::Hive, HIVE_NOLAZYFLUSH, _HHIVE::HiveFlags, _REGISTRY_COMMAND::ImpersonationContext, KeGetCurrentThread, NT_SUCCESS, NTSTATUS(), REG_CMD_ADD_HIVE_LIST, REG_CMD_HIVE_CLOSE, REG_CMD_HIVE_OPEN, REGISTRY_COMMAND, _REGISTRY_COMMAND::RegistryLockAquired, SeCreateClientSecurity(), SECURITY_CLIENT_CONTEXT, SeDeleteClientSecurity, Status, _REGISTRY_COMMAND::Status, and TRUE.

Referenced by NtLoadKey2().

    01909                    :
    01910
    01911     A hive (file in the format created by NtSaveKey) may be linked
    01912     into the active registry with this call.  UNLIKE NtRestoreKey,
    01913     the file specified to NtLoadKey will become the actual backing
    01914     store of part of the registry (that is, it will NOT be copied.)
    01915
    01916     The file may have an associated .log file.
    01917
    01918     If the hive file is marked as needing a .log file, and one is
    01919     not present, the call will fail.
    01920
    01921     The name specified by SourceFile must be such that ".log" can
    01922     be appended to it to generate the name of the log file.  Thus,
    01923     on FAT file systems, the hive file may not have an extension.
    01924
    01925     This call is used by logon to make the user's profile available
    01926     in the registry.  It is not intended for use doing backup,
    01927     restore, etc.  Use NtRestoreKey for that.
    01928
    01929     N.B.  This routine assumes that the object attributes for the file
    01930           to be opened have been captured into kernel space so that
    01931           they can safely be passed to the worker thread to open the file
    01932           and do the actual I/O.
    01933
    01934 Arguments:
    01935
    01936     TargetKey - specifies the path to a key to link the hive to.
    01937                 path must be of the form "\registry\user<username>"
    01938
    01939     SourceFile - specifies a file.  while file could be remote,
    01940                 that is strongly discouraged.
    01941
    01942     Flags - specifies any flags that should be used for the load operation.
    01943             The only valid flag is REG_NO_LAZY_FLUSH.
    01944
    01945 Return Value:
    01946
    01947     NTSTATUS - values TBS.
    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     // Obtain the security context here so we can use it
    01961     // later to impersonate the user, which we will do
    01962     // if we cannot access the file as SYSTEM.  This
    01963     // usually occurs if the file is on a remote machine.
    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     // Do not lock the registry; Instead set the RegistryLockAquired member
    01979     // of REGISTRY_COMMAND so CmpWorker can lock it after opening the hive files
    01980     //
    01981     //CmpLockRegistryExclusive();
    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             // if CmpWorker has locked the registry, unlock it now.
    02001             CmpUnlockRegistry();
    02002         }
    02003         return(Status);
    02004     } else {
    02005         //
    02006         // if we got here, CmpWorker should have locked the registry exclusive.
    02007         //
    02008         ASSERT( Command.RegistryLockAquired );
    02009     }
    02010
    02011     //
    02012     // if this is a NO_LAZY_FLUSH hive, set the appropriate bit.
    02013     //
    02014     if (Flags & REG_NO_LAZY_FLUSH) {
    02015         NewHive->Hive.HiveFlags |= HIVE_NOLAZYFLUSH;
    02016     }
    02017
    02018     //
    02019     // We now have a succesfully loaded and initialized CmHive, so we
    02020     // just need to link that into the appropriate spot in the master hive.
    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         // add new hive to hivelist
    02032         //
    02033         Command.Command = REG_CMD_ADD_HIVE_LIST;
    02034
    02035     } else {
    02036         //
    02037         // Close the files we've opened.
    02038         //
    02039         Command.Command = REG_CMD_HIVE_CLOSE;
    02040     }
    02041     CmpWorker(&Command);
    02042
    02043     //
    02044     // We've given user chance to log on, so turn on quota
    02045     //
    02046     if ((CmpProfileLoaded == FALSE) &&
    02047         (CmpWasSetupBoot == FALSE)) {
    02048         CmpProfileLoaded = TRUE;
    02049         CmpSetGlobalQuotaAllowed();
    02050     }
    02051
    02052     CmpUnlockRegistry();
    02053     return(Status);
    02054 }

BOOLEAN CmpDoFlushAll | ( | VOID |  | ) |

Definition at line 2195 of file cmapi.c.

References CmLockHive, CmpHiveListHead, CmpMasterHive, CmpNoWrite, CmUnlockHive, FALSE, _CMHIVE::Hive, HIVE_NOLAZYFLUSH, _HHIVE::HiveFlags, HiveList, HvSyncHive(), NT_SUCCESS, NTSTATUS(), Status, and TRUE.

Referenced by CmFlushKey(), CmpLazyFlushWorker(), and CmpWorker().

    02200                    :
    02201
    02202     Flush all hives.
    02203
    02204     Runs in the context of the CmpWorkerThread.
    02205
    02206     Runs down list of Hives and applies HvSyncHive to them.
    02207
    02208     NOTE: Hives which are marked as HV_NOLAZYFLUSH are *NOT* flushed
    02209           by this call.  You must call HvSyncHive explicitly to flush
    02210           a hive marked as HV_NOLAZYFLUSH.
    02211
    02212 Arguments:
    02213
    02214 Return Value:
    02215
    02216     NONE
    02217
    02218 --*/
    02219 {
    02220     NTSTATUS    Status;
    02221     PLIST_ENTRY p;
    02222     PCMHIVE     h;
    02223     BOOLEAN     Result = TRUE;
    02224 /*
    02225     ULONG rc;
    02226 */
    02227     extern PCMHIVE CmpMasterHive;
    02228
    02229     //
    02230     // If writes are not working, lie and say we succeeded, will
    02231     // clean up in a short time.  Only early system init code
    02232     // will ever know the difference.
    02233     //
    02234     if (CmpNoWrite) {
    02235         return TRUE;
    02236     }
    02237
    02238     //
    02239     // traverse list of hives, sync each one
    02240     //
    02241     p = CmpHiveListHead.Flink;
    02242     while (p != &CmpHiveListHead) {
    02243
    02244         h = CONTAINING_RECORD(p, CMHIVE, HiveList);
    02245
    02246 /*
    02247 #if DBG
    02248         if (h!=CmpMasterHive) {
    02249             rc = CmCheckRegistry(h, FALSE);
    02250
    02251             if (rc!=0) {
    02252                 KdPrint(("CmpDoFlushAll: corrupt hive, rc = %08lx\n",rc));
    02253                 DbgBreakPoint();
    02254             }
    02255         }
    02256 #endif
    02257 */
    02258         if (!(h->Hive.HiveFlags & HIVE_NOLAZYFLUSH)) {
    02259
    02260             //
    02261             //Lock the hive before we flush it.
    02262             //-- since we now allow multiple readers
    02263             // during a flush (a flush is considered a read)
    02264             // we have to force a serialization on the vector table
    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             // WARNNOTE - the above means that a lazy flush or
    02276             //            or shutdown flush did not work.  we don't
    02277             //            know why.  there is noone to report an error
    02278             //            to, so continue on and hope for the best.
    02279             //            (in theory, worst that can happen is user changes
    02280             //             are lost.)
    02281             //
    02282         }
    02283
    02284
    02285         p = p->Flink;
    02286     }
    02287
    02288     return Result;
    02289 }

NTSTATUS CmpSetValueKeyExisting | ( | IN PHHIVE | Hive,
|  | IN HCELL_INDEX | OldChild,
|  | IN PCELL_DATA | Value,
|  | IN ULONG | Type,
|  | IN PVOID | Data,
|  | IN ULONG | DataSize,
|  | IN ULONG | StorageType,
|  | IN ULONG | TempData
| ) |

Definition at line 1383 of file cmapi.c.

References ASSERT, ASSERT_CM_LOCK_OWNED, BufferSize, CM_KEY_VALUE_SMALL, CM_KEY_VALUE_SPECIAL_SIZE, CM_MAX_STASH, CML_API, CMLOG, CmpIsHKeyValueSmall, CmpStashBuffer, CmpStashBufferSize, CMS_EXCEPTION, ExAllocatePoolWithTag, EXCEPTION_EXECUTE_HANDLER, ExFreePool(), HCELL_INDEX, HCELL_NIL, Hive, HvAllocateCell(), HvFreeCell(), HvGetCell, HvGetCellSize(), HvMarkCellDirty(), NULL, PAGE_SIZE, and PagedPool.

Referenced by CmSetValueKey().

    01395                    :
    01396
    01397     Helper for CmSetValueKey, implements the case where the value entry
    01398     being set already exists.
    01399
    01400 Arguments:
    01401
    01402     Hive - hive of interest
    01403
    01404     OldChild - hcell_index of the value entry body to which we are to
    01405                     set new data
    01406
    01407     Type - The integer type number of the value entry.
    01408
    01409     Data - Pointer to buffer with actual data for the value entry.
    01410
    01411     DataSize - Size of Data buffer.
    01412
    01413     StorageType - stable or volatile
    01414
    01415     TempData - small values are passed here
    01416
    01417 Return Value:
    01418
    01419     STATUS_SUCCESS if it worked, appropriate status code if it did not
    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     // value entry by the specified name already exists
    01436     // oldchild is hcell_index of its value entry body
    01437     //  which we will always edit, so mark it dirty
    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) {               // small
    01446
    01447         //
    01448         // We are storing a small datum, TempData has data.
    01449         //
    01450         if ((! small) && (realsize > 0))
    01451         {
    01452             //
    01453             // value entry has existing external data to free
    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         // write our new small data into value entry body
    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 {                                            // large
    01471
    01472         //
    01473         // We are storing a "large" datum
    01474         //
    01475
    01476         //
    01477         // See if we can write data on top of existing cell
    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                 // The existing data cell is big enough to hold the
    01491                 // new data.  Attempt to copy to stash buffer. if
    01492                 // we succeed we can copy directly onto the old cell.
    01493                 // if we fail, we must allocate and fill a new cell,
    01494                 // and replace the old one with it.
    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                     // Try to allocate a bigger stash buffer.  If it works, keep it and
    01509                     // free the old one.  This prevents pool from becoming too fragmented
    01510                     // if somebody (like SAM) is repeatedly setting very large values
    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                     // We have a stash buffer
    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                     // We have filled the stash buffer, copy data and finish
    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                  } // else stashbuffer == null
    01559             } // else existing cell is too small
    01560         } // else there is no existing cell
    01561     } // new cell needed (always large)
    01562
    01563     //
    01564     // Either the existing cell is not large enough, or does
    01565     // not exist, or we couldn't stash successfully.
    01566     //
    01567     // Allocate and fill a new cell.  Free the old one.  Store
    01568     // the new's index into the value entry body.
    01569     //
    01570     NewCell = HvAllocateCell(Hive, DataSize, StorageType);
    01571
    01572     if (NewCell == HCELL_NIL) {
    01573         return STATUS_INSUFFICIENT_RESOURCES;
    01574     }
    01575
    01576     //
    01577     // fill the new data cell
    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     // free the old data cell
    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     // set body
    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 }

NTSTATUS CmpSetValueKeyNew | ( | IN PHHIVE | Hive,
|  | IN PCM_KEY_NODE | Parent,
|  | IN PUNICODE_STRING | ValueName,
|  | IN ULONG | Type,
|  | IN PVOID | Data,
|  | IN ULONG | DataSize,
|  | IN ULONG | StorageType,
|  | IN ULONG | TempData
| ) |

Definition at line 1619 of file cmapi.c.

References ASSERT, CM_KEY_VALUE_SIGNATURE, CM_KEY_VALUE_SMALL, CM_KEY_VALUE_SPECIAL_SIZE, CM_MAX_REASONABLE_VALUES, CML_API, CMLOG, CmpCopyName(), CmpHKeyValueSize, CMS_EXCEPTION, _CM_KEY_VALUE::Data, _CM_KEY_VALUE::DataLength, EXCEPTION_EXECUTE_HANDLER, _CM_KEY_VALUE::Flags, HBLOCK_SIZE, HCELL_INDEX, HCELL_NIL, Hive, HvAllocateCell(), HvFreeCell(), HvGetCell, HvMarkCellDirty(), HvReallocateCell(), _CELL_DATA::_u::KeyList, _CELL_DATA::_u::KeyValue, _CM_KEY_VALUE::Name, _CM_KEY_VALUE::NameLength, ROUND_UP, _CM_KEY_VALUE::Signature, _CM_KEY_VALUE::Type, _CELL_DATA::u, VALUE_COMP_NAME, and ValueName.

Referenced by CmSetValueKey().

    01631                    :
    01632
    01633     Helper for CmSetValueKey, implements the case where the value entry
    01634     being set does not exist.  Will create new value entry and data,
    01635     place in list (which may be created)
    01636
    01637 Arguments:
    01638
    01639     Hive - hive of interest
    01640
    01641     Parent - pointer to key node value entry is for
    01642
    01643     ValueName - The unique (relative to the containing key) name
    01644         of the value entry.  May be NULL.
    01645
    01646     TitleIndex - Supplies the title index for ValueName.  The title
    01647         index specifies the index of the localized alias for the ValueName.
    01648
    01649     Type - The integer type number of the value entry.
    01650
    01651     Data - Pointer to buffer with actual data for the value entry.
    01652
    01653     DataSize - Size of Data buffer.
    01654
    01655     StorageType - stable or volatile
    01656
    01657     TempData - small data values passed here
    01658
    01659
    01660 Return Value:
    01661
    01662     STATUS_SUCCESS if it worked, appropriate status code if it did not
    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     // Either Count == 0 (no list) or our entry is simply not in
    01676     // the list.  Create a new value entry body, and data.  Add to list.
    01677     // (May create the list.)
    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     // allocate the body of the value entry, and the data
    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     // map in the body, and fill in its fixed portion
    01710     //
    01711     pvalue = HvGetCell(Hive, ValueCell);
    01712     pvalue->u.KeyValue.Signature = CM_KEY_VALUE_SIGNATURE;
    01713
    01714     //
    01715     // fill in the variable portions of the new value entry,  name and
    01716     // and data are copied from caller space, could fault.
    01717     //
    01718     try {
    01719
    01720         //
    01721         // fill in the name
    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         // We have bombed out loading user data, clean up and exit.
    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     // fill in the data
    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             // We have bombed out loading user data, clean up and exit.
    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     // either add ourselves to list, or make new one with us in it.
    01782     //
    01783     count = Parent->ValueList.Count;
    01784     count++;
    01785     if (count > 1) {
    01786
    01787         if (count < CM_MAX_REASONABLE_VALUES) {
    01788
    01789             //
    01790             // A reasonable number of values, allocate just enough
    01791             // space.
    01792             //
    01793
    01794             AllocateSize = count * sizeof(HCELL_INDEX);
    01795         } else {
    01796
    01797             //
    01798             // An excessive number of values, pad the allocation out
    01799             // to avoid fragmentation. (if there's this many values,
    01800             // there'll probably be more pretty soon)
    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     // put ourselves on the list
    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         // out of space, free all allocated stuff
    01831         if (DataCell != HCELL_NIL) {
    01832             HvFreeCell(Hive, DataCell);
    01833         }
    01834         HvFreeCell(Hive, ValueCell);
    01835         return STATUS_INSUFFICIENT_RESOURCES;
    01836     }
    01837 }

NTSTATUS CmQueryKey | ( | IN PCM_KEY_CONTROL_BLOCK | KeyControlBlock,
|  | IN KEY_INFORMATION_CLASS | KeyInformationClass,
|  | IN PVOID | KeyInformation,
|  | IN ULONG | Length,
|  | IN PULONG | ResultLength
| ) |

Definition at line 647 of file cmapi.c.

References CML_WORKER, CMLOG, CmpConstructName(), CmpLockRegistry(), CmpMarkAllBinsReadOnly, CmpQueryKeyData(), CmpUnlockRegistry(), CMS_CM, ExFreePoolWithTag, _KEY_INFORMATION::KeyNameInformation, Name, NTSTATUS(), NULL, PKEY_INFORMATION, PROTECTED_POOL, and USHORT.

Referenced by EhQueryKey(), and NtQueryKey().

    00656                    :
    00657
    00658     Data about the class of a key, and the numbers and sizes of its
    00659     children and value entries may be queried with CmQueryKey.
    00660
    00661     NOTE: The returned lengths are guaranteed to be at least as
    00662           long as the described values, but may be longer in
    00663           some circumstances.
    00664
    00665 Arguments:
    00666
    00667     KeyControlBlock - pointer to the KCB that describes the key
    00668
    00669     KeyInformationClass - Specifies the type of information
    00670         returned in Buffer.  One of the following types:
    00671
    00672         KeyBasicInformation - return last write time, title index, and name.
    00673             (See KEY_BASIC_INFORMATION)
    00674
    00675         KeyNodeInformation - return last write time, title index, name, class.
    00676             (See KEY_NODE_INFORMATION)
    00677
    00678         KeyFullInformation - return all data except for name and security.
    00679             (See KEY_FULL_INFORMATION)
    00680
    00681     KeyInformation -Supplies pointer to buffer to receive the data.
    00682
    00683     Length - Length of KeyInformation in bytes.
    00684
    00685     ResultLength - Number of bytes actually written into KeyInformation.
    00686
    00687 Return Value:
    00688
    00689     NTSTATUS - Result code from call, among the following:
    00690
    00691         <TBS>
    00692
    00693 --*/
    00694 {
    00695     NTSTATUS    status;
    00696
    00697     CMLOG(CML_WORKER, CMS_CM) KdPrint(("CmQueryKey\n"));
    00698
    00699
    00700
    00701     CmpLockRegistry();
    00702
    00703     // Mark the hive as read only
    00704     CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
    00705
    00706     try {
    00707
    00708         //
    00709         // request for the FULL path of the key
    00710         //
    00711         if( KeyInformationClass == KeyNameInformation ) {
    00712             if (KeyControlBlock->Delete ) {
    00713                 //
    00714                 // special case: return key deleted status, but still fill the full name of the key.
    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                         // Fill in the length of the name
    00748                         //
    00749                         pbuffer->KeyNameInformation.NameLength = NameLength;
    00750
    00751                         //
    00752                         // Now copy the full name into the user buffer, if enough space
    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                         // If not enough space, copy how much we can and return overflow
    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             // key already deleted
    00777             //
    00778             status = STATUS_KEY_DELETED;
    00779         } else {
    00780             //
    00781             // call a worker to perform data transfer
    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     // Mark the hive as read only
    00797     CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
    00798
    00799     return status;
    00800 }

NTSTATUS CmQueryMultipleValueKey | ( | IN PCM_KEY_CONTROL_BLOCK | KeyControlBlock,
|  | IN PKEY_VALUE_ENTRY | ValueEntries,
|  | IN ULONG | EntryCount,
|  | IN PVOID | ValueBuffer,
|  | IN OUT PULONG | BufferLength,
|  | IN OPTIONAL PULONG | ResultLength
| ) |

Definition at line 940 of file cmapi.c.

References CML_WORKER, CMLOG, CmpFindValueByName, CmpIsHKeyValueSmall, CmpLockRegistry(), CmpMarkAllBinsReadOnly, CmpUnlockRegistry(), CMS_CM, _CM_KEY_VALUE::Data, _CM_KEY_VALUE::DataLength, FALSE, HCELL_INDEX, HCELL_NIL, Hive, HvGetCell, KPROCESSOR_MODE, NT_SUCCESS, NTSTATUS(), PAGED_CODE, ProbeAndReadUnicodeString, ProbeForRead, Status, TRUE, _CM_KEY_VALUE::Type, UserMode, ValueBuffer, and ValueName.

Referenced by NtQueryMultipleValueKey().

    00950                    :
    00951
    00952     Multiple values of any key may be queried atomically with
    00953     this api.
    00954
    00955 Arguments:
    00956
    00957     KeyControlBlock - Supplies the key to be queried.
    00958
    00959     ValueEntries - Returns an array of KEY_VALUE_ENTRY structures, one for each value.
    00960
    00961     EntryCount - Supplies the number of entries in the ValueNames and ValueEntries arrays
    00962
    00963     ValueBuffer - Returns the value data for each value.
    00964
    00965     BufferLength - Supplies the length of the ValueBuffer array in bytes.
    00966                    Returns the length of the ValueBuffer array that was filled in.
    00967
    00968     ResultLength - if present, Returns the length in bytes of the ValueBuffer
    00969                     array required to return the requested values of this key.
    00970
    00971 Return Value:
    00972
    00973     NTSTATUS
    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     // Mark the hive as read only
    01005     CmpMarkAllBinsReadOnly(Hive);
    01006
    01007     PreviousMode = KeGetPreviousMode();
    01008     try {
    01009         for (i=0; i < EntryCount; i++) {
    01010             //
    01011             // find the data
    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                 // Round up UsedLength and RequiredLength to a ULONG boundary
    01029                 //
    01030                 UsedLength = (UsedLength + sizeof(ULONG)-1) & ~(sizeof(ULONG)-1);
    01031                 RequiredLength = (RequiredLength + sizeof(ULONG)-1) & ~(sizeof(ULONG)-1);
    01032
    01033                 //
    01034                 // If there is enough room for this data value in the buffer,
    01035                 // fill it in now. Otherwise, mark the buffer as full. We must
    01036                 // keep iterating through the values in order to determine the
    01037                 // RequiredLength.
    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     // Mark the hive as read only
    01080     CmpMarkAllBinsReadOnly(Hive);
    01081
    01082     return Status;
    01083 }

NTSTATUS CmQueryValueKey | ( | IN PCM_KEY_CONTROL_BLOCK | KeyControlBlock,
|  | IN UNICODE_STRING | ValueName,
|  | IN KEY_VALUE_INFORMATION_CLASS | KeyValueInformationClass,
|  | IN PVOID | KeyValueInformation,
|  | IN ULONG | Length,
|  | IN PULONG | ResultLength
| ) |

Definition at line 804 of file cmapi.c.

References Cell, CM_KCB_SYM_LINK_FOUND, CML_WORKER, CMLOG, CMP_GET_CACHED_ADDRESS, CmpDereferenceKeyControlBlockWithLock(), CmpFindValueByNameFromCache(), CmpLockRegistry(), CmpMakeValueCacheReadOnly, CmpMakeValueCacheReadWrite, CmpMarkAllBinsReadOnly, CmpQueryKeyValueData(), CmpUnlockRegistry(), CMS_CM, HCELL_INDEX, Index, LOCK_KCB_TREE, NTSTATUS(), PAGED_CODE, PHCELL_INDEX, UNLOCK_KCB_TREE, and ValueName.

Referenced by EhQueryValueKey(), and NtQueryValueKey().

    00814                    :
    00815
    00816     The ValueName, TitleIndex, Type, and Data for any one of a key's
    00817     value entries may be queried with CmQueryValueKey.
    00818
    00819     If KeyValueInformation is not long enough to hold all requested data,
    00820     STATUS_BUFFER_OVERFLOW will be returned, and ResultLength will be
    00821     set to the number of bytes actually required.
    00822
    00823 Arguments:
    00824
    00825     KeyControlBlock - pointer to the KCB that describes the key
    00826
    00827     ValueName  - The name of the value entry to return data for.
    00828
    00829     KeyValueInformationClass - Specifies the type of information
    00830         returned in KeyValueInformation.  One of the following types:
    00831
    00832         KeyValueBasicInformation - return time of last write, title
    00833             index, and name.  (See KEY_VALUE_BASIC_INFORMATION)
    00834
    00835         KeyValueFullInformation - return time of last write, title
    00836             index, name, class.  (See KEY_VALUE_FULL_INFORMATION)
    00837
    00838     KeyValueInformation -Supplies pointer to buffer to receive the data.
    00839
    00840     Length - Length of KeyValueInformation in bytes.
    00841
    00842     ResultLength - Number of bytes actually written into KeyValueInformation.
    00843
    00844 Return Value:
    00845
    00846     NTSTATUS - Result code from call, among the following:
    00847
    00848         <TBS>
    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     // Mark the hive as read only
    00873     CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
    00874
    00875     LOCK_KCB_TREE();
    00876
    00877     if (KeyControlBlock->ExtFlags & CM_KCB_SYM_LINK_FOUND) {
    00878         //
    00879         // The value list is now set to the KCB for symbolic link,
    00880         // Clean it up and set the value right before we do the query.
    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         // Find the data
    00893         //
    00894
    00895         ValueData = CmpFindValueByNameFromCache(KeyControlBlock->KeyHive,
    00896                                                 &(KeyControlBlock->ValueCache),
    00897                                                 &ValueName,
    00898                                                 &ContainingList,
    00899                                                 &Index,
    00900                                                 &ValueCached
    00901                                                 );
    00902         if (ValueData) {
    00903
    00904             // Trying to catch the BAD guy who writes over our pool.
    00905             CmpMakeValueCacheReadWrite(ValueCached,CMP_GET_CACHED_ADDRESS(KeyControlBlock->ValueCache.ValueList));
    00906
    00907             //
    00908             // call a worker to perform data transfer
    00909             //
    00910
    00911             status = CmpQueryKeyValueData(KeyControlBlock->KeyHive,
    00912                                           ContainingList,
    00913                                           ValueData,
    00914                                           ValueCached,
    00915                                           KeyValueInformationClass,
    00916                                           KeyValueInformation,
    00917                                           Length,
    00918                                           ResultLength);
    00919
    00920             // Trying to catch the BAD guy who writes over our pool.
    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     // Mark the hive as read only
    00933     CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
    00934
    00935     return status;
    00936 }

NTSTATUS CmReplaceKey | ( | IN PHHIVE | Hive,
|  | IN HCELL_INDEX | Cell,
|  | IN PUNICODE_STRING | NewHiveName,
|  | IN PUNICODE_STRING | OldFileName
| ) |

Definition at line 2293 of file cmapi.c.

References _REGISTRY_COMMAND::Allocate, ASSERT, CHAR, CM_WRAP_LIMIT, _REGISTRY_COMMAND::CmHive, CML_BUGCHECK, CMLOG, CmpFree(), CmpGlobalQuotaAllowed, CmpGlobalQuotaWarning, CmpLockRegistryExclusive(), CmpUnlockRegistry(), CmpWorker(), CMS_SAVRES, _REGISTRY_COMMAND::Command, ErrorExit(), ExFreePool(), FALSE, _REGISTRY_COMMAND::FileAttributes, Hive, HIVE_HAS_BEEN_REPLACED, _HHIVE::HiveFlags, _CMHIVE::HiveList, HvFreeHive(), _REGISTRY_COMMAND::ImpersonationContext, _REGISTRY_COMMAND::NameInfoLength, _REGISTRY_COMMAND::NewName, NT_SUCCESS, NTSTATUS(), NULL, _REGISTRY_COMMAND::OldName, REG_CMD_HIVE_CLOSE, REG_CMD_HIVE_OPEN, REG_CMD_RENAME_HIVE, _REGISTRY_COMMAND::RegistryLockAquired, Status, _REGISTRY_COMMAND::Status, and TRUE.

Referenced by NtReplaceKey().

    02302                    :
    02303
    02304     Renames the hive file for a running system and replaces it with a new
    02305     file.  The new file is not actually used until the next boot.
    02306
    02307 Arguments:
    02308
    02309     Hive - Supplies a hive control structure for the hive to be replaced.
    02310
    02311     Cell - Supplies the HCELL_INDEX of the root cell of the hive to be
    02312            replaced.
    02313
    02314     NewHiveName - Supplies the name of the file which is to be installed
    02315             as the new hive.
    02316
    02317     OldFileName - Supplies the name of the file which the existing hive
    02318             file is to be renamed to.
    02319
    02320 Return Value:
    02321
    02322     NTSTATUS
    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     // temporarily disable registry quota as we will be giving this memory back immediately!
    02345     //
    02346     OldQuotaAllowed = CmpGlobalQuotaAllowed;
    02347     OldQuotaWarning = CmpGlobalQuotaWarning;
    02348     CmpGlobalQuotaAllowed = CM_WRAP_LIMIT;
    02349     CmpGlobalQuotaWarning = CM_WRAP_LIMIT;
    02350
    02351     //
    02352     // First open the new hive file and check to make sure it is valid.
    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     // The new hive exists, and is consistent, and we have it open.
    02376     // Now rename the current hive file.
    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         // rename failed, close the files associated with the new hive
    02388         //
    02389         Command.CmHive = NewHive;
    02390         Command.Command = REG_CMD_HIVE_CLOSE;
    02391         CmpWorker(&Command);
    02392         goto ErrorExit;
    02393     }
    02394
    02395     //
    02396     // The existing hive was successfully renamed, so try to rename the
    02397     // new file to what the old hive file was named.  (which was returned
    02398     // into ObjectInfoBuffer by the worker thread)
    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         // Close the handles to the new hive
    02413         //
    02414         Command.Command = REG_CMD_HIVE_CLOSE;
    02415         Command.CmHive = NewHive;
    02416         CmpWorker(&Command);
    02417
    02418         //
    02419         // We are in trouble now.  We have renamed the existing hive file,
    02420         // but we couldn't rename the new hive file!  Try to rename the
    02421         // existing hive file back to where it was.
    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             // WARNNOTE:
    02438             //      To get into this state, the user must have relevent
    02439             //      privileges, deliberately screw with system in an attempt
    02440             //      to defeat it, AND get it done in a narrow timing window.
    02441             //
    02442             //      Further, if it's a user profile, the system will
    02443             //      still come up.
    02444             //
    02445             //      Therefore, return an error code and go on.
    02446             //
    02447
    02448             Status = STATUS_REGISTRY_CORRUPT;
    02449
    02450         }
    02451     }
    02452
    02453     //
    02454     // All of the renaming is done.  However, we are holding an in-memory
    02455     // image of the new hive.  Release it, since it will not actually
    02456     // be used until next boot.
    02457     //
    02458     // Do not close the open file handles to the new hive, we need to
    02459     // keep it locked exclusively until the system is rebooted to prevent
    02460     // people from mucking with it.
    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     // Set global quota back to what it was.
    02473     //
    02474     CmpGlobalQuotaAllowed = OldQuotaAllowed;
    02475     CmpGlobalQuotaWarning = OldQuotaWarning;
    02476
    02477     CmpUnlockRegistry();
    02478     return(Status);
    02479 }

NTSTATUS CmSetLastWriteTimeKey | ( | IN PCM_KEY_CONTROL_BLOCK | KeyControlBlock,
|  | IN PLARGE_INTEGER | LastWriteTime
| ) |

Definition at line 1841 of file cmapi.c.

References Cell, CML_WORKER, CMLOG, CmpLockRegistryExclusive(), CmpUnlockRegistry(), CMS_CM, HCELL_INDEX, Hive, HvMarkCellDirty(), _CM_KEY_NODE::LastWriteTime, NTSTATUS(), and TRUE.

Referenced by NtSetInformationKey().

    01847                    :
    01848
    01849     The LastWriteTime associated with a key node can be set with
    01850     CmSetLastWriteTimeKey
    01851
    01852 Arguments:
    01853
    01854     KeyControlBlock - pointer to kcb for the key to operate on
    01855
    01856     LastWriteTime - new time for key
    01857
    01858 Return Value:
    01859
    01860     NTSTATUS - Result code from call, among the following:
    01861
    01862         <TBS>
    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     // Check that we are not being asked to modify a key
    01877     // that has been deleted
    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 }

NTSTATUS CmSetValueKey | ( | IN PCM_KEY_CONTROL_BLOCK | KeyControlBlock,
|  | IN PUNICODE_STRING | ValueName,
|  | IN ULONG | Type,
|  | IN PVOID | Data,
|  | IN ULONG | DataSize
| ) |

Definition at line 1087 of file cmapi.c.

References ASSERT, ASSERT_CM_LOCK_OWNED_EXCLUSIVE, Cell, CM_KEY_VALUE_SMALL, CM_KEY_VALUE_SPECIAL_SIZE, CML_API, CML_WORKER, CMLOG, CmpCleanUpKcbValueCache(), CmpFindNameInList(), CmpLockRegistry(), CmpLockRegistryExclusive(), CmpMarkAllBinsReadOnly, CmpReportNotify(), CmpSetValueKeyExisting(), CmpSetValueKeyNew(), CmpUnlockRegistry(), CMS_CM, CMS_EXCEPTION, CmSymbolicLinkValueName, _CHILD_LIST::Count, _CM_KEY_VALUE::Data, _CM_KEY_VALUE::DataLength, EXCEPTION_EXECUTE_HANDLER, FALSE, HCELL_INDEX, HCELL_NIL, Hive, HvGetCell, HvGetCellType, HvMarkCellDirty(), KeQuerySystemTime(), KEY_SYM_LINK, _CELL_DATA::_u::KeyValue, _CM_KEY_NODE::LastWriteTime, _CHILD_LIST::List, _CM_KEY_NODE::MaxValueDataLen, _CM_KEY_NODE::MaxValueNameLen, NT_SUCCESS, NTSTATUS(), NULL, RtlEqualUnicodeString(), TRUE, _CM_KEY_VALUE::Type, _CELL_DATA::u, _CM_KEY_NODE::ValueList, and ValueName.

Referenced by EhSetValueKey(), and NtSetValueKey().

    01096                    :
    01097
    01098     A value entry may be created or replaced with CmSetValueKey.
    01099
    01100     If a value entry with a Value ID (i.e. name) matching the
    01101     one specified by ValueName exists, it is deleted and replaced
    01102     with the one specified.  If no such value entry exists, a new
    01103     one is created.  NULL is a legal Value ID.  While Value IDs must
    01104     be unique within any given key, the same Value ID may appear
    01105     in many different keys.
    01106
    01107 Arguments:
    01108
    01109     KeyControlBlock - pointer to kcb for the key to operate on
    01110
    01111     ValueName - The unique (relative to the containing key) name
    01112         of the value entry.  May be NULL.
    01113
    01114     Type - The integer type number of the value entry.
    01115
    01116     Data - Pointer to buffer with actual data for the value entry.
    01117
    01118     DataSize - Size of Data buffer.
    01119
    01120
    01121 Return Value:
    01122
    01123     NTSTATUS - Result code from call, among the following:
    01124
    01125         <TBS>
    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     // Mark the hive as read only
    01148     CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
    01149
    01150     while (TRUE) {
    01151         //
    01152         // Check that we are not being asked to add a value to a key
    01153         // that has been deleted
    01154         //
    01155         if (KeyControlBlock->Delete == TRUE) {
    01156             status = STATUS_KEY_DELETED;
    01157             goto Exit;
    01158         }
    01159
    01160         //
    01161         // Check to see if this is a symbolic link node.  If so caller
    01162         // is only allowed to create/change the SymbolicLinkValue
    01163         // value name
    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             // Disallow attempts to manipulate any value names under a symbolic link
    01173             // except for the "SymbolicLinkValue" value name or type other than REG_LINK
    01174             //
    01175
    01176             // Mark the hive as read only
    01177             CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
    01178
    01179             status = STATUS_ACCESS_DENIED;
    01180             goto Exit;
    01181         }
    01182
    01183         //
    01184         // get reference to parent key,
    01185         //
    01186         Hive = KeyControlBlock->KeyHive;
    01187         Cell = KeyControlBlock->KeyCell;
    01188         parent = KeyControlBlock->KeyNode;
    01189
    01190         //
    01191         // try to find an existing value entry by the same name
    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         // Performance Hack:
    01209         // If a Set is asking us to set a key to the current value (IE does this a lot)
    01210         // drop it (and, therefore, the last modified time) on the floor, but return success
    01211         // this stops the page from being dirtied, and us having to flush the registry.
    01212         //
    01213         //
    01214         if (mustChange == TRUE) {
    01215             break; //while
    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                     //check for small values
    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         // To Get here, we must either be changing a value, or setting a new one
    01258         //
    01259         mustChange=TRUE;
    01260         //
    01261         // We're going through these gyrations so that if someone does come in and try and delete the
    01262         // key we're setting we're safe. Once we know we have to change the key, take the
    01263         // Exclusive (write) lock then restart
    01264         //
    01265         //
    01266         CmpUnlockRegistry();
    01267         CmpLockRegistryExclusive();
    01268
    01269     }// while
    01270
    01271     // It's a different or new value, mark it dirty, since we'll
    01272     // at least set its time stamp
    01273
    01274     if (! HvMarkCellDirty(Hive, Cell)) {
    01275         status = STATUS_NO_LOG_SPACE;
    01276         goto Exit;
    01277     }
    01278
    01279     StorageType = HvGetCellType(Cell);
    01280
    01281     //
    01282     // stash small data if relevent
    01283     //
    01284     TempData = 0;
    01285     if ((DataSize <= CM_KEY_VALUE_SMALL) &&
    01286         (DataSize > 0))
    01287     {
    01288         try {
    01289             RtlMoveMemory(          // yes, move memory, could be 1 byte
    01290                 &TempData,          // at the end of a page.
    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         // ----- Existing Value Entry Path -----
    01307         //
    01308
    01309         //
    01310         // An existing value entry of the specified name exists,
    01311         // set our data into it.
    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         // ----- New Value Entry Path -----
    01326         //
    01327
    01328         //
    01329         // Either there are no existing value entries, or the one
    01330         // specified is not in the list.  In either case, create and
    01331         // fill a new one, and add it to the list
    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         // Update the cache, no need for KCB lock as the registry is locked exclusively.
    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     // Mark the hive as read only
    01376     CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
    01377
    01378     return status;
    01379 }

NTSTATUS CmUnloadKey | ( | IN PHHIVE | Hive,
|  | IN HCELL_INDEX | Cell,
|  | IN PCM_KEY_CONTROL_BLOCK | Kcb
| ) |

Definition at line 2079 of file cmapi.c.

References ASSERT, _HHIVE::BaseBlock, Cell, _REGISTRY_COMMAND::Cell, _REGISTRY_COMMAND::CmHive, CML_WORKER, CMLOG, CmpDestroyHive(), CmpFree(), CmpLockRegistryExclusive(), CmpSearchForOpenSubKeys(), CmpSearchKeyControlBlockTree(), CmpUnlockRegistry(), CmpWorker(), CMS_CM, _REGISTRY_COMMAND::Command, ExFreePool(), Hive, _REGISTRY_COMMAND::Hive, _CMHIVE::HiveLock, HvFreeHive(), NULL, REG_CMD_FLUSH_KEY, REG_CMD_HIVE_CLOSE, REG_CMD_REMOVE_HIVE_LIST, _HBASE_BLOCK::RootCell, and SearchIfExist.

Referenced by NtUnloadKey().

    02087                    :
    02088
    02089     Unlinks a hive from its location in the registry, closes its file
    02090     handles, and deallocates all its memory.
    02091
    02092     There must be no key control blocks currently referencing the hive
    02093     to be unloaded.
    02094
    02095 Arguments:
    02096
    02097     Hive - Supplies a pointer to the hive control structure for the
    02098            hive to be unloaded
    02099
    02100     Cell - supplies the HCELL_INDEX for the root cell of the hive.
    02101
    02102     Kcb - Supplies the key control block
    02103
    02104 Return Value:
    02105
    02106     NTSTATUS
    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     // Make sure the cell passed in is the root cell of the hive.
    02121     //
    02122     if (Cell != Hive->BaseBlock->RootCell) {
    02123         CmpUnlockRegistry();
    02124         return(STATUS_INVALID_PARAMETER);
    02125     }
    02126
    02127     //
    02128     // Make sure there are no open references to key control blocks
    02129     // for this hive.  If there are none, then we can unload the hive.
    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     // Flush any dirty data to disk. If this fails, too bad.
    02148     //
    02149     Command.Command = REG_CMD_FLUSH_KEY;
    02150     Command.Hive = Hive;
    02151     Command.Cell = Cell;
    02152     CmpWorker(&Command);
    02153
    02154     //
    02155     // Remove the hive from the HiveFileList
    02156     //
    02157     Command.Command = REG_CMD_REMOVE_HIVE_LIST;
    02158     Command.CmHive = (PCMHIVE)Hive;
    02159     CmpWorker(&Command);
    02160
    02161     //
    02162     // Unlink from master hive, remove from list
    02163     //
    02164     Success = CmpDestroyHive(Hive, Cell);
    02165
    02166     CmpUnlockRegistry();
    02167
    02168     if (Success) {
    02169         HvFreeHive(Hive);
    02170
    02171         //
    02172         // Close the hive files
    02173         //
    02174         Command.Command = REG_CMD_HIVE_CLOSE;
    02175         Command.CmHive = CmHive;
    02176         CmpWorker(&Command);
    02177
    02178         //
    02179         // free the cm level structure
    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 }

## Variable Documentation

ULONG CmpGlobalQuotaAllowed

| Definition at line 37 of file cmapi.c. Referenced by CmpClaimGlobalQuota(), CmpSetGlobalQuotaAllowed(), CmReplaceKey(), CmSaveKey(), CmSaveMergedKeys(), and CmSetRegistryQuotaInformation().

ULONG CmpGlobalQuotaWarning

| Definition at line 38 of file cmapi.c. Referenced by CmpClaimGlobalQuota(), CmpComputeGlobalQuotaAllowed(), CmReplaceKey(), CmSaveKey(), CmSaveMergedKeys(), and CmSetRegistryQuotaInformation().

LIST_ENTRY CmpHiveListHead

| Definition at line 27 of file cmapi.c. Referenced by CmInitSystem1(), CmpDoFlushAll(), CmpInitializeHive(), CmpWorker(), and EhOpenHive().

BOOLEAN CmpNoWrite

| Definition at line 25 of file cmapi.c. Referenced by CmFlushKey(), CmpDoFlushAll(), CmpFileFlush(), CmpFileWrite(), CmpInitializeHiveList(), CmpLazyFlush(), and CmpWorker().

BOOLEAN CmpProfileLoaded

| Definition at line 29 of file cmapi.c. Referenced by CmLoadKey(), CmpDiskFullWarning(), CmpLoadHiveVolatile(), and CmRestoreKey().

PUCHAR CmpStashBuffer

| Definition at line 32 of file cmapi.c. Referenced by CmInitSystem1(), CmpSaveKeyByFileCopy(), and CmpSetValueKeyExisting().

ULONG CmpStashBufferSize

| Definition at line 33 of file cmapi.c. Referenced by CmInitSystem1(), and CmpSetValueKeyExisting().

BOOLEAN CmpWasSetupBoot

| Definition at line 30 of file cmapi.c. Referenced by CmLoadKey(), and CmpWorker().

UNICODE_STRING CmSymbolicLinkValueName

| Definition at line 35 of file cmapi.c. Referenced by CmpCreateControlSet(), CmpGetSymbolicLink(), CmpInitializeRegistryNames(), CmpLinkKeyToHive(), CmSetAcpiHwProfile(), and CmSetValueKey().