Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

797 lines
25 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. cmparse2.c
  5. Abstract:
  6. This module contains parse routines for the configuration manager, particularly
  7. the registry.
  8. Author:
  9. Bryan M. Willman (bryanwi) 10-Sep-1991
  10. Revision History:
  11. --*/
  12. #include "cmp.h"
  13. #ifdef ALLOC_PRAGMA
  14. #pragma alloc_text(PAGE,CmpDoCreate)
  15. #pragma alloc_text(PAGE,CmpDoCreateChild)
  16. #endif
  17. extern PCM_KEY_CONTROL_BLOCK CmpKeyControlBlockRoot;
  18. NTSTATUS
  19. CmpDoCreate(
  20. IN PHHIVE Hive,
  21. IN HCELL_INDEX Cell,
  22. IN PACCESS_STATE AccessState,
  23. IN PUNICODE_STRING Name,
  24. IN KPROCESSOR_MODE AccessMode,
  25. IN PCM_PARSE_CONTEXT Context,
  26. IN PCM_KEY_CONTROL_BLOCK ParentKcb,
  27. OUT PVOID *Object
  28. )
  29. /*++
  30. Routine Description:
  31. Performs the first step in the creation of a registry key. This
  32. routine checks to make sure the caller has the proper access to
  33. create a key here, and allocates space for the child in the parent
  34. cell. It then calls CmpDoCreateChild to initialize the key and
  35. create the key object.
  36. This two phase creation allows us to share the child creation code
  37. with the creation of link nodes.
  38. Arguments:
  39. Hive - supplies a pointer to the hive control structure for the hive
  40. Cell - supplies index of node to create child under.
  41. AccessState - Running security access state information for operation.
  42. Name - supplies pointer to a UNICODE string which is the name of
  43. the child to be created.
  44. AccessMode - Access mode of the original caller.
  45. Context - pointer to CM_PARSE_CONTEXT structure passed through
  46. the object manager
  47. BaseName - Name of object create is relative to
  48. KeyName - Relative name (to BaseName)
  49. Object - The address of a variable to receive the created key object, if
  50. any.
  51. Return Value:
  52. NTSTATUS
  53. --*/
  54. {
  55. NTSTATUS status;
  56. PCELL_DATA pdata;
  57. HCELL_INDEX KeyCell;
  58. ULONG ParentType;
  59. ACCESS_MASK AdditionalAccess;
  60. BOOLEAN CreateAccess;
  61. PCM_KEY_BODY KeyBody;
  62. PSECURITY_DESCRIPTOR SecurityDescriptor;
  63. LARGE_INTEGER TimeStamp;
  64. BOOLEAN BackupRestore;
  65. KPROCESSOR_MODE mode;
  66. PCM_KEY_NODE ParentNode;
  67. #ifdef CMP_KCB_CACHE_VALIDATION
  68. //
  69. // we this only for debug validation purposes. We shall delete it even
  70. // for debug code after we make sure it works OK.
  71. //
  72. ULONG Index;
  73. #endif //CMP_KCB_CACHE_VALIDATION
  74. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_PARSE,"CmpDoCreate:\n"));
  75. BackupRestore = FALSE;
  76. if (ARGUMENT_PRESENT(Context)) {
  77. if (Context->CreateOptions & REG_OPTION_BACKUP_RESTORE) {
  78. //
  79. // allow backup operators to create new keys
  80. //
  81. BackupRestore = TRUE;
  82. }
  83. //
  84. // Operation is a create, so set Disposition
  85. //
  86. Context->Disposition = REG_CREATED_NEW_KEY;
  87. }
  88. /*
  89. //
  90. // this is a create, so we need exclusive access on the registry
  91. // first get the time stamp to see if somebody messed with this key
  92. // this might be more easier if we decide to cache the LastWriteTime
  93. // in the KCB ; now it IS !!!
  94. //
  95. TimeStamp = ParentKcb->KcbLastWriteTime;
  96. */
  97. if( CmIsKcbReadOnly(ParentKcb) ) {
  98. //
  99. // key is protected
  100. //
  101. return STATUS_ACCESS_DENIED;
  102. }
  103. CmpUnlockRegistry();
  104. CmpLockRegistryExclusive();
  105. #ifdef CHECK_REGISTRY_USECOUNT
  106. CmpCheckRegistryUseCount();
  107. #endif //CHECK_REGISTRY_USECOUNT
  108. //
  109. // make sure nothing changed in between:
  110. // 1. ParentKcb is still valid
  111. // 2. Child was not already added by somebody else
  112. //
  113. if( ParentKcb->Delete ) {
  114. //
  115. // key was deleted in between
  116. //
  117. return STATUS_OBJECT_NAME_NOT_FOUND;
  118. }
  119. /*
  120. Apparently KeQuerySystemTime doesn't give us a fine resolution to copunt on
  121. //
  122. // we need to read the parent again (because of the mapping view stuff !)
  123. //
  124. if( TimeStamp.QuadPart != ParentKcb->KcbLastWriteTime.QuadPart ) {
  125. //
  126. // key was changed in between; possibly this key was already created ==> reparse
  127. //
  128. return STATUS_REPARSE;
  129. }
  130. */
  131. //
  132. // apparently, the KeQuerySystemTime doesn't give us a fine resolution
  133. // so we have to search if the child has not been created already
  134. //
  135. ParentNode = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
  136. if( ParentNode == NULL ) {
  137. //
  138. // we couldn't map the bin containing this cell
  139. //
  140. return STATUS_INSUFFICIENT_RESOURCES;
  141. }
  142. // release the cell right here as we are holding the reglock exclusive
  143. HvReleaseCell(Hive,Cell);
  144. if( CmpFindSubKeyByName(Hive,ParentNode,Name) != HCELL_NIL ) {
  145. //
  146. // key was changed in between; possibly this key was already created ==> reparse
  147. //
  148. #ifdef CHECK_REGISTRY_USECOUNT
  149. CmpCheckRegistryUseCount();
  150. #endif //CHECK_REGISTRY_USECOUNT
  151. return STATUS_REPARSE;
  152. }
  153. ASSERT( Cell == ParentKcb->KeyCell );
  154. #ifdef CMP_KCB_CACHE_VALIDATION
  155. //
  156. // Check to make sure the caller can create a sub-key here.
  157. //
  158. //
  159. // get the security descriptor from cache
  160. //
  161. if( CmpFindSecurityCellCacheIndex ((PCMHIVE)Hive,ParentNode->Security,&Index) == FALSE ) {
  162. #ifdef CHECK_REGISTRY_USECOUNT
  163. CmpCheckRegistryUseCount();
  164. #endif //CHECK_REGISTRY_USECOUNT
  165. return STATUS_INSUFFICIENT_RESOURCES;
  166. }
  167. ASSERT( ((PCMHIVE)Hive)->SecurityCache[Index].Cell == ParentNode->Security );
  168. ASSERT( ((PCMHIVE)Hive)->SecurityCache[Index].CachedSecurity == ParentKcb->CachedSecurity );
  169. #endif //CMP_KCB_CACHE_VALIDATION
  170. ASSERT( ParentKcb->CachedSecurity != NULL );
  171. SecurityDescriptor = &(ParentKcb->CachedSecurity->Descriptor);
  172. ParentType = HvGetCellType(Cell);
  173. if ( (ParentType == Volatile) &&
  174. ((Context->CreateOptions & REG_OPTION_VOLATILE) == 0) )
  175. {
  176. //
  177. // Trying to create stable child under volatile parent, report error
  178. //
  179. #ifdef CHECK_REGISTRY_USECOUNT
  180. CmpCheckRegistryUseCount();
  181. #endif //CHECK_REGISTRY_USECOUNT
  182. return STATUS_CHILD_MUST_BE_VOLATILE;
  183. }
  184. #ifdef CMP_KCB_CACHE_VALIDATION
  185. ASSERT( ParentNode->Flags == ParentKcb->Flags );
  186. #endif //CMP_KCB_CACHE_VALIDATION
  187. if (ParentKcb->Flags & KEY_SYM_LINK) {
  188. //
  189. // Disallow attempts to create anything under a symbolic link
  190. //
  191. #ifdef CHECK_REGISTRY_USECOUNT
  192. CmpCheckRegistryUseCount();
  193. #endif //CHECK_REGISTRY_USECOUNT
  194. return STATUS_ACCESS_DENIED;
  195. }
  196. AdditionalAccess = (Context->CreateOptions & REG_OPTION_CREATE_LINK) ? KEY_CREATE_LINK : 0;
  197. if( BackupRestore == TRUE ) {
  198. //
  199. // this is a create to support a backup or restore
  200. // operation, do the special case work
  201. //
  202. AccessState->RemainingDesiredAccess = 0;
  203. AccessState->PreviouslyGrantedAccess = 0;
  204. mode = KeGetPreviousMode();
  205. if (SeSinglePrivilegeCheck(SeBackupPrivilege, mode)) {
  206. AccessState->PreviouslyGrantedAccess |=
  207. KEY_READ | ACCESS_SYSTEM_SECURITY;
  208. }
  209. if (SeSinglePrivilegeCheck(SeRestorePrivilege, mode)) {
  210. AccessState->PreviouslyGrantedAccess |=
  211. KEY_WRITE | ACCESS_SYSTEM_SECURITY | WRITE_DAC | WRITE_OWNER;
  212. }
  213. if (AccessState->PreviouslyGrantedAccess == 0) {
  214. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_PARSE,"CmpDoCreate for backup restore: access denied\n"));
  215. status = STATUS_ACCESS_DENIED;
  216. //
  217. // this is not a backup-restore operator; deny the create
  218. //
  219. CreateAccess = FALSE;
  220. } else {
  221. //
  222. // allow backup operators to create new keys
  223. //
  224. CreateAccess = TRUE;
  225. }
  226. } else {
  227. //
  228. // The FullName is not used in the routine CmpCheckCreateAccess,
  229. //
  230. CreateAccess = CmpCheckCreateAccess(NULL,
  231. SecurityDescriptor,
  232. AccessState,
  233. AccessMode,
  234. AdditionalAccess,
  235. &status);
  236. }
  237. if (CreateAccess) {
  238. //
  239. // Security check passed, so we can go ahead and create
  240. // the sub-key.
  241. //
  242. if ( !HvMarkCellDirty(Hive, Cell) ) {
  243. #ifdef CHECK_REGISTRY_USECOUNT
  244. CmpCheckRegistryUseCount();
  245. #endif //CHECK_REGISTRY_USECOUNT
  246. return STATUS_NO_LOG_SPACE;
  247. }
  248. //
  249. // Create and initialize the new sub-key
  250. //
  251. status = CmpDoCreateChild( Hive,
  252. Cell,
  253. SecurityDescriptor,
  254. AccessState,
  255. Name,
  256. AccessMode,
  257. Context,
  258. ParentKcb,
  259. 0,
  260. &KeyCell,
  261. Object );
  262. if (NT_SUCCESS(status)) {
  263. PCM_KEY_NODE KeyNode;
  264. //
  265. // Child successfully created, add to parent's list.
  266. //
  267. if (! CmpAddSubKey(Hive, Cell, KeyCell)) {
  268. //
  269. // Unable to add child, so free it
  270. //
  271. CmpFreeKeyByCell(Hive, KeyCell, FALSE);
  272. #ifdef CHECK_REGISTRY_USECOUNT
  273. CmpCheckRegistryUseCount();
  274. #endif //CHECK_REGISTRY_USECOUNT
  275. return STATUS_INSUFFICIENT_RESOURCES;
  276. }
  277. KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
  278. if( KeyNode == NULL ) {
  279. //
  280. // we couldn't map the bin containing this cell
  281. // this shouldn't happen as we successfully marked the cell as dirty
  282. //
  283. ASSERT( FALSE );
  284. #ifdef CHECK_REGISTRY_USECOUNT
  285. CmpCheckRegistryUseCount();
  286. #endif //CHECK_REGISTRY_USECOUNT
  287. return STATUS_INSUFFICIENT_RESOURCES;
  288. }
  289. // release the cell right here as we are holding the reglock exclusive
  290. HvReleaseCell(Hive,Cell);
  291. KeyBody = (PCM_KEY_BODY)(*Object);
  292. //
  293. // A new key is created, invalid the subkey info of the parent KCB.
  294. //
  295. ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  296. CmpCleanUpSubKeyInfo (KeyBody->KeyControlBlock->ParentKcb);
  297. //
  298. // Update max keyname and class name length fields
  299. //
  300. //some sanity asserts first
  301. ASSERT( KeyBody->KeyControlBlock->ParentKcb->KeyCell == Cell );
  302. ASSERT( KeyBody->KeyControlBlock->ParentKcb->KeyHive == Hive );
  303. ASSERT( KeyBody->KeyControlBlock->ParentKcb == ParentKcb );
  304. ASSERT( KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen == KeyNode->MaxNameLen );
  305. //
  306. // update the LastWriteTime on both keynode and kcb;
  307. //
  308. KeQuerySystemTime(&TimeStamp);
  309. KeyNode->LastWriteTime = TimeStamp;
  310. KeyBody->KeyControlBlock->ParentKcb->KcbLastWriteTime = TimeStamp;
  311. if (KeyNode->MaxNameLen < Name->Length) {
  312. KeyNode->MaxNameLen = Name->Length;
  313. // update the kcb cache too
  314. KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen = Name->Length;
  315. }
  316. if (KeyNode->MaxClassLen < Context->Class.Length) {
  317. KeyNode->MaxClassLen = Context->Class.Length;
  318. }
  319. if (Context->CreateOptions & REG_OPTION_CREATE_LINK) {
  320. pdata = HvGetCell(Hive, KeyCell);
  321. if( pdata == NULL ) {
  322. //
  323. // we couldn't map the bin containing this cell
  324. // this shouldn't happen as we just allocated the cell
  325. // (i.e. it must be PINNED into memory at this point)
  326. //
  327. ASSERT( FALSE );
  328. #ifdef CHECK_REGISTRY_USECOUNT
  329. CmpCheckRegistryUseCount();
  330. #endif //CHECK_REGISTRY_USECOUNT
  331. return STATUS_INSUFFICIENT_RESOURCES;
  332. }
  333. // release the cell right here as we are holding the reglock exclusive
  334. HvReleaseCell(Hive,KeyCell);
  335. pdata->u.KeyNode.Flags |= KEY_SYM_LINK;
  336. KeyBody->KeyControlBlock->Flags = pdata->u.KeyNode.Flags;
  337. }
  338. #ifdef CM_BREAK_ON_KEY_OPEN
  339. if( KeyBody->KeyControlBlock->ParentKcb->Flags & KEY_BREAK_ON_OPEN ) {
  340. DbgPrint("\n\n Current process is creating a subkey to a key tagged as BREAK ON OPEN\n");
  341. DbgPrint("\nPlease type the following in the debugger window: !reg kcb %p\n\n\n",KeyBody->KeyControlBlock);
  342. try {
  343. DbgBreakPoint();
  344. } except (EXCEPTION_EXECUTE_HANDLER) {
  345. //
  346. // no debugger enabled, just keep going
  347. //
  348. }
  349. }
  350. #endif //CM_BREAK_ON_KEY_OPEN
  351. }
  352. }
  353. #ifdef CHECK_REGISTRY_USECOUNT
  354. CmpCheckRegistryUseCount();
  355. #endif //CHECK_REGISTRY_USECOUNT
  356. return status;
  357. }
  358. NTSTATUS
  359. CmpDoCreateChild(
  360. IN PHHIVE Hive,
  361. IN HCELL_INDEX ParentCell,
  362. IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
  363. IN PACCESS_STATE AccessState,
  364. IN PUNICODE_STRING Name,
  365. IN KPROCESSOR_MODE AccessMode,
  366. IN PCM_PARSE_CONTEXT Context,
  367. IN PCM_KEY_CONTROL_BLOCK ParentKcb,
  368. IN USHORT Flags,
  369. OUT PHCELL_INDEX KeyCell,
  370. OUT PVOID *Object
  371. )
  372. /*++
  373. Routine Description:
  374. Creates a new sub-key. This is called by CmpDoCreate to create child
  375. sub-keys and CmpCreateLinkNode to create root sub-keys.
  376. Arguments:
  377. Hive - supplies a pointer to the hive control structure for the hive
  378. ParentCell - supplies cell index of parent cell
  379. ParentDescriptor - Supplies security descriptor of parent key, for use
  380. in inheriting ACLs.
  381. AccessState - Running security access state information for operation.
  382. Name - Supplies pointer to a UNICODE string which is the name of the
  383. child to be created.
  384. AccessMode - Access mode of the original caller.
  385. Context - Supplies pointer to CM_PARSE_CONTEXT structure passed through
  386. the object manager.
  387. BaseName - Name of object create is relative to
  388. KeyName - Relative name (to BaseName)
  389. Flags - Supplies any flags to be set in the newly created node
  390. KeyCell - Receives the cell index of the newly created sub-key, if any.
  391. Object - Receives a pointer to the created key object, if any.
  392. Return Value:
  393. STATUS_SUCCESS - sub-key successfully created. New object is returned in
  394. Object, and the new cell's cell index is returned in KeyCell.
  395. !STATUS_SUCCESS - appropriate error message.
  396. --*/
  397. {
  398. ULONG clean=0;
  399. ULONG alloc=0;
  400. NTSTATUS Status = STATUS_SUCCESS;
  401. PCM_KEY_BODY KeyBody;
  402. HCELL_INDEX ClassCell=HCELL_NIL;
  403. PCM_KEY_NODE KeyNode;
  404. PCELL_DATA CellData;
  405. PCM_KEY_CONTROL_BLOCK kcb;
  406. PCM_KEY_CONTROL_BLOCK fkcb;
  407. LONG found;
  408. ULONG StorageType;
  409. PSECURITY_DESCRIPTOR NewDescriptor = NULL;
  410. LARGE_INTEGER systemtime;
  411. ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  412. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_PARSE,"CmpDoCreateChild:\n"));
  413. try {
  414. //
  415. // Get allocation type
  416. //
  417. StorageType = Stable;
  418. if (Context->CreateOptions & REG_OPTION_VOLATILE) {
  419. StorageType = Volatile;
  420. }
  421. //
  422. // Allocate child cell
  423. //
  424. *KeyCell = HvAllocateCell(
  425. Hive,
  426. CmpHKeyNodeSize(Hive, Name),
  427. StorageType,
  428. HCELL_NIL
  429. );
  430. if (*KeyCell == HCELL_NIL) {
  431. Status = STATUS_INSUFFICIENT_RESOURCES;
  432. leave;
  433. }
  434. alloc = 1;
  435. KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, *KeyCell);
  436. if( KeyNode == NULL ) {
  437. //
  438. // we couldn't map the bin containing this cell
  439. // this shouldn't happen as we just allocated the cell
  440. // (i.e. it must be PINNED into memory at this point)
  441. //
  442. ASSERT( FALSE );
  443. Status = STATUS_INSUFFICIENT_RESOURCES;
  444. leave;
  445. }
  446. // release the cell right here as we are holding the reglock exclusive
  447. HvReleaseCell(Hive,*KeyCell);
  448. //
  449. // Allocate cell for class name
  450. //
  451. if (Context->Class.Length > 0) {
  452. ClassCell = HvAllocateCell(Hive, Context->Class.Length, StorageType,*KeyCell);
  453. if (ClassCell == HCELL_NIL) {
  454. Status = STATUS_INSUFFICIENT_RESOURCES;
  455. leave;
  456. }
  457. }
  458. alloc = 2;
  459. //
  460. // Allocate the object manager object
  461. //
  462. Status = ObCreateObject(AccessMode,
  463. CmpKeyObjectType,
  464. NULL,
  465. AccessMode,
  466. NULL,
  467. sizeof(CM_KEY_BODY),
  468. 0,
  469. 0,
  470. Object);
  471. if (NT_SUCCESS(Status)) {
  472. KeyBody = (PCM_KEY_BODY)(*Object);
  473. //
  474. // We have managed to allocate all of the objects we need to,
  475. // so initialize them
  476. //
  477. //
  478. // Mark the object as uninitialized (in case we get an error too soon)
  479. //
  480. KeyBody->Type = KEY_BODY_TYPE;
  481. KeyBody->KeyControlBlock = NULL;
  482. //
  483. // Fill in the class name
  484. //
  485. if (Context->Class.Length > 0) {
  486. CellData = HvGetCell(Hive, ClassCell);
  487. if( CellData == NULL ) {
  488. //
  489. // we couldn't map the bin containing this cell
  490. // this shouldn't happen as we just allocated the cell
  491. // (i.e. it must be PINNED into memory at this point)
  492. //
  493. ASSERT( FALSE );
  494. Status = STATUS_INSUFFICIENT_RESOURCES;
  495. leave;
  496. }
  497. // release the cell right here as we are holding the reglock exclusive
  498. HvReleaseCell(Hive,ClassCell);
  499. try {
  500. RtlCopyMemory(
  501. &(CellData->u.KeyString[0]),
  502. Context->Class.Buffer,
  503. Context->Class.Length
  504. );
  505. } except(EXCEPTION_EXECUTE_HANDLER) {
  506. ObDereferenceObject(*Object);
  507. return GetExceptionCode();
  508. }
  509. }
  510. //
  511. // Fill in the new key itself
  512. //
  513. KeyNode->Signature = CM_KEY_NODE_SIGNATURE;
  514. KeyNode->Flags = Flags;
  515. KeQuerySystemTime(&systemtime);
  516. KeyNode->LastWriteTime = systemtime;
  517. KeyNode->Spare = 0;
  518. KeyNode->Parent = ParentCell;
  519. KeyNode->SubKeyCounts[Stable] = 0;
  520. KeyNode->SubKeyCounts[Volatile] = 0;
  521. KeyNode->SubKeyLists[Stable] = HCELL_NIL;
  522. KeyNode->SubKeyLists[Volatile] = HCELL_NIL;
  523. KeyNode->ValueList.Count = 0;
  524. KeyNode->ValueList.List = HCELL_NIL;
  525. KeyNode->Security = HCELL_NIL;
  526. KeyNode->Class = ClassCell;
  527. KeyNode->ClassLength = Context->Class.Length;
  528. KeyNode->MaxValueDataLen = 0;
  529. KeyNode->MaxNameLen = 0;
  530. KeyNode->MaxValueNameLen = 0;
  531. KeyNode->MaxClassLen = 0;
  532. KeyNode->NameLength = CmpCopyName(Hive,
  533. KeyNode->Name,
  534. Name);
  535. if (KeyNode->NameLength < Name->Length) {
  536. KeyNode->Flags |= KEY_COMP_NAME;
  537. }
  538. if (Context->CreateOptions & REG_OPTION_PREDEF_HANDLE) {
  539. KeyNode->ValueList.Count = (ULONG)((ULONG_PTR)Context->PredefinedHandle);
  540. KeyNode->Flags |= KEY_PREDEF_HANDLE;
  541. }
  542. //
  543. // Create kcb here so all data are filled in.
  544. //
  545. // Allocate a key control block
  546. //
  547. kcb = CmpCreateKeyControlBlock(Hive, *KeyCell, KeyNode, ParentKcb, FALSE, Name);
  548. if (kcb == NULL) {
  549. ObDereferenceObject(*Object);
  550. return STATUS_INSUFFICIENT_RESOURCES;
  551. }
  552. ASSERT(kcb->RefCount == 1);
  553. alloc = 3;
  554. #if DBG
  555. if( kcb->ExtFlags & CM_KCB_KEY_NON_EXIST ) {
  556. //
  557. // we shouldn't fall into this
  558. //
  559. ObDereferenceObject(*Object);
  560. DbgBreakPoint();
  561. return STATUS_OBJECT_NAME_NOT_FOUND;
  562. }
  563. #endif //DBG
  564. //
  565. // Fill in CM specific fields in the object
  566. //
  567. KeyBody->Type = KEY_BODY_TYPE;
  568. KeyBody->KeyControlBlock = kcb;
  569. KeyBody->NotifyBlock = NULL;
  570. KeyBody->Process = PsGetCurrentProcess();
  571. ENLIST_KEYBODY_IN_KEYBODY_LIST(KeyBody);
  572. //
  573. // Assign a security descriptor to the object. Note that since
  574. // registry keys are container objects, and ObAssignSecurity
  575. // assumes that the only container object in the world is
  576. // the ObpDirectoryObjectType, we have to call SeAssignSecurity
  577. // directly in order to get the right inheritance.
  578. //
  579. Status = SeAssignSecurity(ParentDescriptor,
  580. AccessState->SecurityDescriptor,
  581. &NewDescriptor,
  582. TRUE, // container object
  583. &AccessState->SubjectSecurityContext,
  584. &CmpKeyObjectType->TypeInfo.GenericMapping,
  585. CmpKeyObjectType->TypeInfo.PoolType);
  586. if (NT_SUCCESS(Status)) {
  587. Status = CmpSecurityMethod(*Object,
  588. AssignSecurityDescriptor,
  589. NULL,
  590. NewDescriptor,
  591. NULL,
  592. NULL,
  593. CmpKeyObjectType->TypeInfo.PoolType,
  594. &CmpKeyObjectType->TypeInfo.GenericMapping);
  595. }
  596. //
  597. // Since the security descriptor now lives in the hive,
  598. // free the in-memory copy
  599. //
  600. SeDeassignSecurity( &NewDescriptor );
  601. if (!NT_SUCCESS(Status)) {
  602. //
  603. // Note that the dereference will clean up the kcb, so
  604. // make sure and decrement the allocation count here.
  605. //
  606. // Also mark the kcb as deleted so it does not get
  607. // inappropriately cached.
  608. //
  609. ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  610. kcb->Delete = TRUE;
  611. CmpRemoveKeyControlBlock(kcb);
  612. ObDereferenceObject(*Object);
  613. alloc = 2;
  614. } else {
  615. CmpReportNotify(
  616. kcb,
  617. kcb->KeyHive,
  618. kcb->KeyCell,
  619. REG_NOTIFY_CHANGE_NAME
  620. );
  621. }
  622. }
  623. } finally {
  624. if (!NT_SUCCESS(Status)) {
  625. //
  626. // Clean up allocations
  627. //
  628. switch (alloc) {
  629. case 3:
  630. //
  631. // Mark KCB as deleted so it does not get inadvertently added to
  632. // the delayed close list. That would have fairly disastrous effects
  633. // as the KCB points to storage we are about to free.
  634. //
  635. ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  636. kcb->Delete = TRUE;
  637. CmpRemoveKeyControlBlock(kcb);
  638. CmpDereferenceKeyControlBlockWithLock(kcb);
  639. // DELIBERATE FALL
  640. case 2:
  641. if (Context->Class.Length > 0) {
  642. HvFreeCell(Hive, ClassCell);
  643. }
  644. // DELIBERATE FALL
  645. case 1:
  646. HvFreeCell(Hive, *KeyCell);
  647. // DELIBERATE FALL
  648. }
  649. #ifdef CM_CHECK_FOR_ORPHANED_KCBS
  650. DbgPrint("CmpDoCreateChild failed with status %lx for hive = %p , NodeName = %.*S\n",Status,Hive,Name->Length/2,Name->Buffer);
  651. #endif //CM_CHECK_FOR_ORPHANED_KCBS
  652. }
  653. }
  654. return(Status);
  655. }