Leaked source code of windows server 2003
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.

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