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.

7153 lines
193 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. genobj.cxx
  5. Abstract:
  6. Generic object implementation.
  7. AZ roles has so many objects that need creation, enumeration, etc
  8. that it seems prudent to have a single body of code for doing those operations
  9. Author:
  10. Cliff Van Dyke (cliffv) 11-Apr-2001
  11. --*/
  12. #include "pch.hxx"
  13. // Procedure forwards
  14. PGENERIC_OBJECT_LIST
  15. ObGetObjectListPtr(
  16. IN PGENERIC_OBJECT GenericObject,
  17. IN ULONG LinkToObjectType,
  18. IN PGENERIC_OBJECT_LIST LinkToGenericObjectList
  19. );
  20. //
  21. // Table of sizes of the specific objects
  22. //
  23. DWORD SpecificObjectSize[OBJECT_TYPE_MAXIMUM] = {
  24. sizeof(AZP_AZSTORE), // OBJECT_TYPE_AZAUTHSTORE
  25. sizeof(AZP_APPLICATION), // OBJECT_TYPE_APPLICATION
  26. sizeof(AZP_OPERATION), // OBJECT_TYPE_OPERATION
  27. sizeof(AZP_TASK), // OBJECT_TYPE_TASK
  28. sizeof(AZP_SCOPE), // OBJECT_TYPE_SCOPE
  29. sizeof(AZP_GROUP), // OBJECT_TYPE_GROUP
  30. sizeof(AZP_ROLE), // OBJECT_TYPE_ROLE
  31. sizeof(AZP_SID), // OBJECT_TYPE_SID
  32. sizeof(AZP_CLIENT_CONTEXT), // OBJECT_TYPE_CLIENT_CONTEXT
  33. 0, // OBJECT_TYPE_ROOT
  34. };
  35. //
  36. // Maximum length of the object name
  37. //
  38. DWORD MaxObjectNameLength[OBJECT_TYPE_MAXIMUM] = {
  39. 0, // OBJECT_TYPE_AZAUTHSTORE
  40. AZ_MAX_APPLICATION_NAME_LENGTH,
  41. AZ_MAX_OPERATION_NAME_LENGTH,
  42. AZ_MAX_TASK_NAME_LENGTH,
  43. AZ_MAX_SCOPE_NAME_LENGTH,
  44. AZ_MAX_GROUP_NAME_LENGTH,
  45. AZ_MAX_ROLE_NAME_LENGTH,
  46. 0, // OBJECT_TYPE_SID
  47. 0, // OBJECT_TYPE_CLIENT_CONTEXT
  48. 0, // OBJECT_TYPE_ROOT
  49. };
  50. //
  51. // Table of object init routines
  52. //
  53. // Specifies a routine to call to initialize the object type specific fields
  54. // when adding a generic object.
  55. //
  56. OBJECT_INIT_ROUTINE *ObjectInitRoutine[OBJECT_TYPE_MAXIMUM] = {
  57. &AzpAzStoreInit, // OBJECT_TYPE_AZAUTHSTORE
  58. &AzpApplicationInit, // OBJECT_TYPE_APPLICATION
  59. &AzpOperationInit, // OBJECT_TYPE_OPERATION
  60. &AzpTaskInit, // OBJECT_TYPE_TASK
  61. &AzpScopeInit, // OBJECT_TYPE_SCOPE
  62. &AzpGroupInit, // OBJECT_TYPE_GROUP
  63. &AzpRoleInit, // OBJECT_TYPE_ROLE
  64. &AzpSidInit, // OBJECT_TYPE_SID
  65. &AzpClientContextInit, // OBJECT_TYPE_CLIENT_CONTEXT
  66. NULL, // OBJECT_TYPE_ROOT
  67. };
  68. //
  69. // Table of object free routines
  70. //
  71. // Specifies a routine to call to free the object type specific fields
  72. // when freeing a generic object.
  73. //
  74. OBJECT_FREE_ROUTINE *ObjectFreeRoutine[OBJECT_TYPE_MAXIMUM] = {
  75. &AzpAzStoreFree, // OBJECT_TYPE_AZAUTHSTORE
  76. &AzpApplicationFree, // OBJECT_TYPE_APPLICATION
  77. &AzpOperationFree, // OBJECT_TYPE_OPERATION
  78. &AzpTaskFree, // OBJECT_TYPE_TASK
  79. &AzpScopeFree, // OBJECT_TYPE_SCOPE
  80. &AzpGroupFree, // OBJECT_TYPE_GROUP
  81. &AzpRoleFree, // OBJECT_TYPE_ROLE
  82. &AzpSidFree, // OBJECT_TYPE_SID
  83. &AzpClientContextFree, // OBJECT_TYPE_CLIENT_CONTEXT
  84. NULL, // OBJECT_TYPE_ROOT
  85. };
  86. //
  87. // Table of name conflict check routines.
  88. //
  89. // Specifies a routine to call to determine whether a specified name conflicts
  90. // with other objects.
  91. //
  92. // NULL means that the name has not special conflict rules
  93. //
  94. OBJECT_NAME_CONFLICT_ROUTINE *ObjectNameConflictRoutine[OBJECT_TYPE_MAXIMUM] = {
  95. NULL, // OBJECT_TYPE_AZAUTHSTORE
  96. NULL, // OBJECT_TYPE_APPLICATION
  97. &AzpOperationNameConflict, // OBJECT_TYPE_OPERATION
  98. &AzpTaskNameConflict, // OBJECT_TYPE_TASK
  99. NULL, // OBJECT_TYPE_SCOPE
  100. &AzpGroupNameConflict, // OBJECT_TYPE_GROUP
  101. &AzpRoleNameConflict, // OBJECT_TYPE_ROLE
  102. NULL, // OBJECT_TYPE_SID
  103. NULL, // OBJECT_TYPE_CLIENT_CONTEXT
  104. NULL, // OBJECT_TYPE_ROOT
  105. };
  106. //
  107. // Table of object specific GetProperty routines
  108. //
  109. // Specifies a routine to call to get object type specific fields
  110. // when querying a generic object.
  111. //
  112. // NULL means there are no object specific fields.
  113. //
  114. OBJECT_GET_PROPERTY_ROUTINE *ObjectGetPropertyRoutine[OBJECT_TYPE_MAXIMUM] = {
  115. &AzpAzStoreGetProperty, // OBJECT_TYPE_AZAUTHSTORE
  116. &AzpApplicationGetProperty, // OBJECT_TYPE_APPLICATION
  117. &AzpOperationGetProperty, // OBJECT_TYPE_OPERATION
  118. &AzpTaskGetProperty, // OBJECT_TYPE_TASK
  119. &AzpScopeGetProperty, // OBJECT_TYPE_SCOPE
  120. &AzpGroupGetProperty, // OBJECT_TYPE_GROUP
  121. &AzpRoleGetProperty, // OBJECT_TYPE_ROLE
  122. NULL, // OBJECT_TYPE_SID
  123. &AzpClientContextGetProperty, // OBJECT_TYPE_CLIENT_CONTEXT
  124. NULL, // OBJECT_TYPE_ROOT
  125. };
  126. //
  127. // Table of object specific SetProperty routines
  128. //
  129. // Specifies a routine to call to set object type specific fields
  130. // when modifying a generic object.
  131. //
  132. // NULL means there are no object specific fields.
  133. //
  134. OBJECT_SET_PROPERTY_ROUTINE *ObjectSetPropertyRoutine[OBJECT_TYPE_MAXIMUM] = {
  135. &AzpAzStoreSetProperty, // OBJECT_TYPE_AZAUTHSTORE
  136. &AzpApplicationSetProperty, // OBJECT_TYPE_APPLICATION
  137. &AzpOperationSetProperty, // OBJECT_TYPE_OPERATION
  138. &AzpTaskSetProperty, // OBJECT_TYPE_TASK
  139. NULL, // OBJECT_TYPE_SCOPE
  140. &AzpGroupSetProperty, // OBJECT_TYPE_GROUP
  141. NULL, // OBJECT_TYPE_ROLE
  142. NULL, // OBJECT_TYPE_SID
  143. &AzpClientContextSetProperty, // OBJECT_TYPE_CLIENT_CONTEXT
  144. NULL, // OBJECT_TYPE_ROOT
  145. };
  146. //
  147. // Table of object specific dirty bits
  148. //
  149. // Specifies the maximum set of dirty bits applicable for each object type
  150. //
  151. // 0 means there are no object specific fields.
  152. //
  153. DWORD AzGlObjectAllDirtyBits[OBJECT_TYPE_MAXIMUM] = {
  154. AZ_DIRTY_AZSTORE_ALL, // OBJECT_TYPE_AZAUTHSTORE
  155. AZ_DIRTY_APPLICATION_ALL, // OBJECT_TYPE_APPLICATION
  156. AZ_DIRTY_OPERATION_ALL, // OBJECT_TYPE_OPERATION
  157. AZ_DIRTY_TASK_ALL, // OBJECT_TYPE_TASK
  158. AZ_DIRTY_SCOPE_ALL, // OBJECT_TYPE_SCOPE
  159. AZ_DIRTY_GROUP_ALL, // OBJECT_TYPE_GROUP
  160. AZ_DIRTY_ROLE_ALL, // OBJECT_TYPE_ROLE
  161. 0, // OBJECT_TYPE_SID
  162. 0, // OBJECT_TYPE_CLIENT_CONTEXT
  163. 0, // OBJECT_TYPE_ROOT
  164. };
  165. //
  166. // Table of object specific dirty bits.
  167. //
  168. // Specifies the maximum set of dirty bits applicable for each object type
  169. // This list includes only attributes that are scalars.
  170. //
  171. // 0 means there are no object specific fields.
  172. //
  173. DWORD ObjectAllScalarDirtyBits[OBJECT_TYPE_MAXIMUM] = {
  174. AZ_DIRTY_AZSTORE_ALL_SCALAR, // OBJECT_TYPE_AZAUTHSTORE
  175. AZ_DIRTY_APPLICATION_ALL_SCALAR, // OBJECT_TYPE_APPLICATION
  176. AZ_DIRTY_OPERATION_ALL_SCALAR, // OBJECT_TYPE_OPERATION
  177. AZ_DIRTY_TASK_ALL_SCALAR, // OBJECT_TYPE_TASK
  178. AZ_DIRTY_SCOPE_ALL_SCALAR, // OBJECT_TYPE_SCOPE
  179. AZ_DIRTY_GROUP_ALL_SCALAR, // OBJECT_TYPE_GROUP
  180. AZ_DIRTY_ROLE_ALL_SCALAR, // OBJECT_TYPE_ROLE
  181. 0, // OBJECT_TYPE_SID
  182. 0, // OBJECT_TYPE_CLIENT_CONTEXT
  183. 0, // OBJECT_TYPE_ROOT
  184. };
  185. //
  186. // Table of object specific default values for scalars
  187. //
  188. // This table does double duty as an object specific mapping between dirty bits and property ids
  189. //
  190. // NULL means there are no object specific scalars for the object type
  191. //
  192. AZP_DEFAULT_VALUE *ObjectDefaultValuesArray[OBJECT_TYPE_MAXIMUM] = {
  193. AzGlAzStoreDefaultValues, // OBJECT_TYPE_AZAUTHSTORE
  194. AzGlApplicationDefaultValues, // OBJECT_TYPE_APPLICATION
  195. AzGlOperationDefaultValues, // OBJECT_TYPE_OPERATION
  196. AzGlTaskDefaultValues, // OBJECT_TYPE_TASK
  197. NULL, // OBJECT_TYPE_SCOPE
  198. AzGlGroupDefaultValues, // OBJECT_TYPE_GROUP
  199. NULL, // OBJECT_TYPE_ROLE
  200. NULL, // OBJECT_TYPE_SID
  201. NULL, // OBJECT_TYPE_CLIENT_CONTEXT
  202. NULL, // OBJECT_TYPE_ROOT
  203. };
  204. //
  205. // Table of object specific AddPropertyItem routines
  206. //
  207. // Specifies a routine to call to add property type specific fields.
  208. //
  209. // NULL means there is no object specific action to take
  210. //
  211. OBJECT_ADD_PROPERTY_ITEM_ROUTINE *ObjectAddPropertyItemRoutine[OBJECT_TYPE_MAXIMUM] = {
  212. NULL, // OBJECT_TYPE_AZAUTHSTORE
  213. NULL, // OBJECT_TYPE_APPLICATION
  214. NULL, // OBJECT_TYPE_OPERATION
  215. &AzpTaskAddPropertyItem, // OBJECT_TYPE_TASK
  216. NULL, // OBJECT_TYPE_SCOPE
  217. &AzpGroupAddPropertyItem, // OBJECT_TYPE_GROUP
  218. NULL, // OBJECT_TYPE_ROLE
  219. NULL, // OBJECT_TYPE_SID
  220. NULL, // OBJECT_TYPE_CLIENT_CONTEXT
  221. NULL, // OBJECT_TYPE_ROOT
  222. };
  223. DWORD
  224. ObCloseHandle(
  225. IN PGENERIC_OBJECT GenericObject
  226. )
  227. /*++
  228. Routine Description:
  229. Close a handle forcefully for a generic object.
  230. On entry, the global lock must be held exclusively
  231. Arguments:
  232. GenericObject - Object whose handle needs to be closed.
  233. Return Value:
  234. NO_ERROR - The operation was successful.
  235. --*/
  236. {
  237. DWORD WinStatus;
  238. PGENERIC_OBJECT ReferencedGenericObject = NULL;
  239. PGENERIC_OBJECT AzStoreGenericObject = NULL;
  240. DWORD ObjectType;
  241. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  242. ObjectType = GenericObject->ObjectType;
  243. //
  244. // Grab a reference to the object
  245. //
  246. WinStatus = ObReferenceObjectByHandle( GenericObject,
  247. TRUE, // Allow deleted objects
  248. FALSE, // No need to refresh cache on a close
  249. ObjectType );
  250. if ( WinStatus != NO_ERROR ) {
  251. goto Cleanup;
  252. }
  253. ReferencedGenericObject = GenericObject;
  254. //
  255. // Grab a reference to the root of the core cache
  256. //
  257. AzStoreGenericObject = &GenericObject->AzStoreObject->GenericObject;
  258. InterlockedIncrement( &AzStoreGenericObject->ReferenceCount );
  259. AzpDumpGoRef( "AzAuthorizationStore in ObCloseHandle ref", AzStoreGenericObject );
  260. //
  261. // For a client context,
  262. // remove the link from the parent when the handle closes
  263. //
  264. if ( ObjectType == OBJECT_TYPE_CLIENT_CONTEXT ) {
  265. ASSERT( GenericObject->HandleReferenceCount == 1 );
  266. // No longer in the global list
  267. ObDereferenceObject( GenericObject );
  268. }
  269. //
  270. // Actually close the handle
  271. //
  272. WinStatus = ObDecrHandleRefCount( GenericObject );
  273. if ( WinStatus != NO_ERROR ) {
  274. goto Cleanup;
  275. }
  276. //
  277. // Done
  278. //
  279. WinStatus = NO_ERROR;
  280. //
  281. // Free locally used resources
  282. //
  283. Cleanup:
  284. if ( ReferencedGenericObject != NULL ) {
  285. ObDereferenceObject( ReferencedGenericObject );
  286. }
  287. if ( AzStoreGenericObject != NULL ) {
  288. // This dereference might delete the entire cache
  289. ObDereferenceObject( AzStoreGenericObject );
  290. }
  291. return WinStatus;
  292. }
  293. RTL_GENERIC_COMPARE_RESULTS
  294. AzpAvlCompare(
  295. IN PRTL_GENERIC_TABLE Table,
  296. IN PVOID FirstStruct,
  297. IN PVOID SecondStruct
  298. )
  299. /*++
  300. Routine Description:
  301. This routine will compare two generic object names
  302. Arguments:
  303. IN PRTL_GENERIC_TABLE - Supplies the table containing the announcements
  304. IN PVOID FirstStuct - The first structure to compare.
  305. IN PVOID SecondStruct - The second structure to compare.
  306. Return Value:
  307. Result of the comparison.
  308. --*/
  309. {
  310. PGENERIC_OBJECT_NAME Name1 = (PGENERIC_OBJECT_NAME) FirstStruct;
  311. PGENERIC_OBJECT_NAME Name2 = (PGENERIC_OBJECT_NAME) SecondStruct;
  312. LONG CompareResult;
  313. CompareResult = AzpCompareStrings( &Name1->ObjectName, &Name2->ObjectName );
  314. if ( CompareResult == CSTR_LESS_THAN ) {
  315. return GenericLessThan;
  316. } else if ( CompareResult == CSTR_GREATER_THAN ) {
  317. return GenericGreaterThan;
  318. } else {
  319. return GenericEqual;
  320. }
  321. UNREFERENCED_PARAMETER(Table);
  322. }
  323. VOID
  324. ObInitGenericHead(
  325. IN PGENERIC_OBJECT_HEAD GenericObjectHead,
  326. IN ULONG ObjectType,
  327. IN PGENERIC_OBJECT ParentGenericObject,
  328. IN PGENERIC_OBJECT_HEAD SiblingGenericObjectHead OPTIONAL
  329. )
  330. /*++
  331. Routine Description
  332. Initialize the head of a list of generic objects
  333. On entry, AzGlResource must be locked exclusive.
  334. Arguments
  335. GenericObjectHead - Specifies the list head to initialize
  336. ObjectType - Specifies the type of objects in the list
  337. ParentGenericObject - Specifies a back link to parent generic object
  338. that host the object head being initialized.
  339. SiblingGenericObjectHead - Specifies a pointer to an object head that
  340. is a sibling of the one being initialized.
  341. Return Value
  342. None
  343. --*/
  344. {
  345. //
  346. // Initialization
  347. //
  348. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  349. //
  350. // Initialize the linked list
  351. //
  352. InitializeListHead( &GenericObjectHead->Head );
  353. GenericObjectHead->ObjectCount = 0;
  354. //
  355. // Initialize the AVL tree of child objects
  356. //
  357. RtlInitializeGenericTable( &GenericObjectHead->AvlTree,
  358. AzpAvlCompare,
  359. AzpAvlAllocate,
  360. AzpAvlFree,
  361. NULL);
  362. //
  363. // Initialize the sequence number
  364. // Start at 1 since a zero EnumerationContext means beginning of list.
  365. //
  366. GenericObjectHead->NextSequenceNumber = 1;
  367. //
  368. // Store the ObjectType
  369. //
  370. GenericObjectHead->ObjectType = ObjectType;
  371. //
  372. // Store the back pointer to the parent generic object
  373. //
  374. GenericObjectHead->ParentGenericObject = ParentGenericObject;
  375. //
  376. // Store the link to the next Generic head
  377. //
  378. GenericObjectHead->SiblingGenericObjectHead = SiblingGenericObjectHead;
  379. //
  380. // If the parent (parent AzApplication/AzScope only) needs to be loaded before objects
  381. // in the list of this head can be enumerated, then set the flag to do so
  382. //
  383. if ( ParentGenericObject != NULL &&
  384. (ParentGenericObject->ObjectType == OBJECT_TYPE_APPLICATION ||
  385. ParentGenericObject->ObjectType == OBJECT_TYPE_SCOPE) ) {
  386. GenericObjectHead->LoadParentBeforeReferencing = TRUE;
  387. } else {
  388. GenericObjectHead->LoadParentBeforeReferencing = FALSE;
  389. }
  390. }
  391. VOID
  392. ObFreeGenericHead(
  393. IN PGENERIC_OBJECT_HEAD GenericObjectHead
  394. )
  395. /*++
  396. Routine Description
  397. Free any ojects on a generic head structure
  398. On entry, AzGlResource must be locked exclusive.
  399. Arguments
  400. GenericObjectHead - Specifies the list head to free
  401. Return Value
  402. None
  403. --*/
  404. {
  405. PLIST_ENTRY ListEntry;
  406. PGENERIC_OBJECT GenericObject;
  407. //
  408. // Initialization
  409. //
  410. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  411. //
  412. // Walk the list of child objects dereferencing each.
  413. //
  414. while ( !IsListEmpty( &GenericObjectHead->Head ) ) {
  415. //
  416. // Grab the first entry and dereference it.
  417. //
  418. ListEntry = GenericObjectHead->Head.Flink;
  419. GenericObject = CONTAINING_RECORD( ListEntry,
  420. GENERIC_OBJECT,
  421. Next );
  422. ASSERT( GenericObject->ReferenceCount == 1 );
  423. ObDereferenceObject( GenericObject );
  424. }
  425. }
  426. DWORD
  427. ObUnloadChildGenericHeads(
  428. IN PGENERIC_OBJECT pParentObject
  429. )
  430. /*++
  431. Routine Description:
  432. This routine is called to unload all the children of a parent object
  433. from the cache. The parent object is marked closed, and no operations
  434. pertaining to its children will be allowed.
  435. On entry, AzGlResource must be locked exclusive
  436. Arguments:
  437. pParentObject - Pointer to parent whose children need to be unloaded from cache
  438. Return Value:
  439. NO_ERROR - Operation completed successfully
  440. Other status codes
  441. --*/
  442. {
  443. DWORD WinStatus = NO_ERROR;
  444. PLIST_ENTRY pListEntry;
  445. PLIST_ENTRY pPrevEntry;
  446. PGENERIC_OBJECT pGenericObject;
  447. PGENERIC_OBJECT_HEAD pGenericObjectHead;
  448. DWORD ObjectCount = 0;
  449. //
  450. // Validation
  451. //
  452. ASSERT( pParentObject != NULL );
  453. ASSERT( AzpIsLockedExclusive(&AzGlResource) );
  454. //
  455. // If the parent object has been closed by another thread, then return
  456. //
  457. if ( !(pParentObject->AreChildrenLoaded) ) {
  458. return NO_ERROR;
  459. }
  460. //
  461. // Free children of this object
  462. // Loop for each type of child
  463. //
  464. for ( pGenericObjectHead = pParentObject->ChildGenericObjectHead;
  465. pGenericObjectHead != NULL;
  466. pGenericObjectHead = pGenericObjectHead->SiblingGenericObjectHead ) {
  467. //
  468. // Walk the list of child objects freeing them in the process
  469. //
  470. pPrevEntry = &pGenericObjectHead->Head;
  471. for ( pListEntry = pPrevEntry->Flink;
  472. pListEntry != &pGenericObjectHead->Head ;
  473. pListEntry = pPrevEntry->Flink ) {
  474. ObjectCount = pGenericObjectHead->ObjectCount;
  475. pGenericObject = CONTAINING_RECORD( pListEntry,
  476. GENERIC_OBJECT,
  477. Next
  478. );
  479. //
  480. // if the object is a parent object, then release all
  481. // its children first
  482. //
  483. DWORD ObjectType = pGenericObject->ObjectType;
  484. if ( IsContainerObject( ObjectType ) ) {
  485. WinStatus = ObUnloadChildGenericHeads( pGenericObject );
  486. if ( WinStatus != NO_ERROR ) {
  487. goto Cleanup;
  488. }
  489. }
  490. //
  491. // If there are any open handles, close the handle
  492. // repeatedly. After that, there are no references to
  493. // this object. We can then release the object.
  494. //
  495. // If closing the handle, releases the object, then
  496. // close handle API will return INVALID_HANDLE_VALUE.
  497. // We do not need to release the object after that since
  498. // its already released.
  499. //
  500. DWORD HandleRefCount = pGenericObject->HandleReferenceCount;
  501. while( HandleRefCount != 0 ) {
  502. WinStatus = ObCloseHandle( pGenericObject );
  503. if ( WinStatus == ERROR_INVALID_HANDLE || ObjectType == OBJECT_TYPE_CLIENT_CONTEXT ) {
  504. break;
  505. } else if ( WinStatus != NO_ERROR ) {
  506. goto Cleanup;
  507. }
  508. HandleRefCount = pGenericObject->HandleReferenceCount;
  509. }
  510. //
  511. // By the time we get to this, we should only have one more reference count
  512. // because only the global resource list holds onto it. All other reference
  513. // count should have already been released by the previous loop of closing
  514. // handles.
  515. //
  516. if ( WinStatus == NO_ERROR && ObjectType != OBJECT_TYPE_CLIENT_CONTEXT ) {
  517. //
  518. // Now, decrement the reference count on the object
  519. //
  520. ObDereferenceObject( pGenericObject );
  521. }
  522. //
  523. // Initialize the sequence number for the generic head,
  524. // if there are no other children of the same type
  525. //
  526. if ( pGenericObjectHead->ObjectCount == 0 ) {
  527. pGenericObjectHead->NextSequenceNumber = 1;
  528. }
  529. if ( pGenericObjectHead->ObjectCount == ObjectCount ) {
  530. pPrevEntry = pListEntry;
  531. }
  532. WinStatus = NO_ERROR;
  533. }
  534. }
  535. //
  536. // reset unloading the parent object to FALSE since we have just unloaded it.
  537. // Mark the object as closed.
  538. //
  539. // We want to decrement the handle count to the application object to 0 as well
  540. //
  541. if ( pParentObject->ObjectType == OBJECT_TYPE_APPLICATION ) {
  542. while ( pParentObject->HandleReferenceCount != 0 ) {
  543. WinStatus = ObCloseHandle( pParentObject );
  544. if ( WinStatus != NO_ERROR ) {
  545. goto Cleanup;
  546. }
  547. }
  548. ((PAZP_APPLICATION)pParentObject)->UnloadApplicationObject = FALSE;
  549. pParentObject->ObjectClosed = TRUE;
  550. //
  551. // Increment the AppSequenceNumber to catch any invalid COM handles
  552. // to this closed object
  553. //
  554. ((PAZP_APPLICATION)pParentObject)->AppSequenceNumber++;
  555. }
  556. WinStatus = NO_ERROR;
  557. Cleanup:
  558. return WinStatus;
  559. }
  560. PGENERIC_OBJECT_NAME
  561. ObInsertNameIntoAvlTree(
  562. IN PGENERIC_OBJECT_HEAD ParentGenericObjectHead,
  563. IN PAZP_STRING ObjectName
  564. )
  565. /*++
  566. Routine Description
  567. Allocates a GENERIC_OBJECT_NAME structure and inserts it into the AvlTree.
  568. On entry, AzGlResource must be locked exclusive.
  569. Arguments
  570. ParentGenericObjectHead - Specifies the list head of the list to insert into
  571. ObjectName - Name of the object
  572. Return Value
  573. Returns a pointer to the inserted object.
  574. NULL: not enough memory
  575. --*/
  576. {
  577. PGENERIC_OBJECT_NAME TemplateObjectName = NULL;
  578. PGENERIC_OBJECT_NAME InsertedObjectName = NULL;
  579. BOOLEAN NewElement;
  580. ULONG NameSize;
  581. //
  582. // Initialization
  583. //
  584. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  585. //
  586. // Allocate memory on a stack for a template of the object name.
  587. //
  588. NameSize = sizeof(GENERIC_OBJECT_NAME) + ObjectName->StringSize;
  589. SafeAllocaAllocate( TemplateObjectName, NameSize );
  590. if ( TemplateObjectName == NULL ) {
  591. goto Cleanup;
  592. }
  593. //
  594. // Initialize the template of the object name
  595. //
  596. TemplateObjectName->GenericObject = NULL;
  597. TemplateObjectName->ObjectName = *ObjectName;
  598. TemplateObjectName->ObjectName.String = (LPWSTR)(TemplateObjectName+1);
  599. RtlCopyMemory( TemplateObjectName->ObjectName.String,
  600. ObjectName->String,
  601. ObjectName->StringSize );
  602. //
  603. // Put it in the AVL tree
  604. //
  605. InsertedObjectName = (PGENERIC_OBJECT_NAME) RtlInsertElementGenericTable (
  606. &ParentGenericObjectHead->AvlTree,
  607. TemplateObjectName,
  608. NameSize,
  609. &NewElement );
  610. if ( InsertedObjectName == NULL ) {
  611. goto Cleanup;
  612. }
  613. ASSERT( NewElement );
  614. //
  615. // Relocate the pointer to the object name string
  616. //
  617. InsertedObjectName->ObjectName.String = (LPWSTR)(InsertedObjectName+1);
  618. //
  619. // Free any locally used resources
  620. //
  621. Cleanup:
  622. if ( TemplateObjectName != NULL ) {
  623. SafeAllocaFree( TemplateObjectName );
  624. }
  625. return InsertedObjectName;
  626. }
  627. PGENERIC_OBJECT
  628. ObAllocateGenericObject(
  629. IN PGENERIC_OBJECT_HEAD ParentGenericObjectHead,
  630. IN PAZP_STRING ObjectName
  631. )
  632. /*++
  633. Routine Description
  634. Allocate memory for the private object structure of the specified type and inserts
  635. it into the list of such objects maintained by the parent object.
  636. On entry, AzGlResource must be locked exclusive.
  637. Arguments
  638. ParentGenericObjectHead - Specifies the list head of the list to insert into
  639. ObjectName - Name of the object
  640. Return Value
  641. Returns a pointer to the allocated object. The caller should dereference the
  642. returned object by calling ObDereferenceObject. (There is a second reference representing
  643. the fact that the entry has been inserted in the ParentGenericObjectHead. The
  644. caller should wait to decrement this second reference count until the caller wants the object
  645. to be removed from the parent list.)
  646. NULL: not enough memory
  647. --*/
  648. {
  649. ULONG ObjectType = ParentGenericObjectHead->ObjectType;
  650. PGENERIC_OBJECT_NAME InsertedObjectName = NULL;
  651. PGENERIC_OBJECT GenericObject = NULL;
  652. ULONG BaseSize;
  653. //
  654. // Initialization
  655. //
  656. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  657. //
  658. // Ensure the object is supported
  659. //
  660. if ( ObjectType > OBJECT_TYPE_MAXIMUM ||
  661. SpecificObjectSize[ObjectType] == 0 ) {
  662. ASSERT( ObjectType <= OBJECT_TYPE_MAXIMUM );
  663. ASSERT( SpecificObjectSize[ObjectType] != 0 );
  664. goto Cleanup;
  665. }
  666. BaseSize = SpecificObjectSize[ObjectType];
  667. ASSERT( BaseSize >= sizeof(GENERIC_OBJECT) );
  668. //
  669. // Add the object name to the AVL tree (If it is a named object)
  670. //
  671. if ( ObjectName->String != NULL ) {
  672. InsertedObjectName = ObInsertNameIntoAvlTree(
  673. ParentGenericObjectHead,
  674. ObjectName );
  675. if ( InsertedObjectName == NULL ) {
  676. goto Cleanup;
  677. }
  678. }
  679. //
  680. // Allocate the memory for the generic object itself
  681. //
  682. GenericObject = (PGENERIC_OBJECT) AzpAllocateHeap( BaseSize, "GENOBJ" );
  683. if ( GenericObject == NULL ) {
  684. goto Cleanup;
  685. }
  686. //
  687. // Initialize it
  688. //
  689. RtlZeroMemory( GenericObject, BaseSize );
  690. GenericObject->ObjectType = ObjectType;
  691. if ( InsertedObjectName != NULL ) {
  692. GenericObject->ObjectName = InsertedObjectName;
  693. InsertedObjectName->GenericObject = GenericObject;
  694. InsertedObjectName = NULL; // For this point it'll be freed as a part of the generic object
  695. }
  696. InitializeListHead( &GenericObject->Next );
  697. // One for being in the global list (being in the AVL tree doesn't count as a reference)
  698. // One for returning a reference to our caller
  699. GenericObject->ReferenceCount = 2;
  700. AzpDumpGoRef( "Allocate object", GenericObject );
  701. //
  702. // Set the sequence number
  703. //
  704. GenericObject->SequenceNumber = ParentGenericObjectHead->NextSequenceNumber;
  705. ParentGenericObjectHead->NextSequenceNumber ++;
  706. //
  707. // Insert the object
  708. // Insert at the tail to keep the list in sequence number order.
  709. //
  710. ASSERT( ParentGenericObjectHead->ObjectType == GenericObject->ObjectType );
  711. InsertTailList( &ParentGenericObjectHead->Head, &GenericObject->Next );
  712. ParentGenericObjectHead->ObjectCount ++;
  713. //
  714. // Provide a back link
  715. //
  716. ASSERT( GenericObject->ParentGenericObjectHead == NULL );
  717. GenericObject->ParentGenericObjectHead = ParentGenericObjectHead;
  718. //
  719. // Free any locally used resources
  720. //
  721. Cleanup:
  722. if ( InsertedObjectName != NULL ) {
  723. if (!RtlDeleteElementGenericTable (
  724. &ParentGenericObjectHead->AvlTree,
  725. InsertedObjectName ) ) {
  726. ASSERT( FALSE );
  727. }
  728. }
  729. return GenericObject;
  730. }
  731. VOID
  732. ObFreeGenericObject(
  733. IN PGENERIC_OBJECT GenericObject
  734. )
  735. /*++
  736. Routine Description
  737. Free memory for the private object structure of the specified type
  738. On entry, AzGlResource must be locked exclusive.
  739. Arguments
  740. GenericObject - Specifies the pointer to the generic object to free
  741. Return Value
  742. None.
  743. --*/
  744. {
  745. PGENERIC_OBJECT_HEAD ChildGenericObjectHead;
  746. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  747. ASSERT( GenericObject->HandleReferenceCount == 0 );
  748. ASSERT( GenericObject->ReferenceCount == 0 );
  749. //
  750. // Call the routine to do provider specific freeing
  751. //
  752. if ( GenericObject->ProviderData != NULL ) {
  753. AzpeFreeMemory( GenericObject->ProviderData );
  754. GenericObject->ProviderData = NULL;
  755. }
  756. //
  757. // Delink the entry from the parent
  758. //
  759. ASSERT( !IsListEmpty( &GenericObject->Next ));
  760. RemoveEntryList( &GenericObject->Next );
  761. GenericObject->ParentGenericObjectHead->ObjectCount --;
  762. //
  763. // Free children of this object
  764. // Loop for each type of child
  765. //
  766. for ( ChildGenericObjectHead = GenericObject->ChildGenericObjectHead;
  767. ChildGenericObjectHead != NULL;
  768. ChildGenericObjectHead = ChildGenericObjectHead->SiblingGenericObjectHead ) {
  769. ObFreeGenericHead( ChildGenericObjectHead );
  770. }
  771. //
  772. // Remove all references to/from this object
  773. //
  774. ObRemoveObjectListLinks( GenericObject );
  775. //
  776. // Call the routine to do object type specific freeing
  777. //
  778. if ( ObjectFreeRoutine[GenericObject->ObjectType] == NULL ) {
  779. ASSERT( ObjectFreeRoutine[GenericObject->ObjectType] != NULL );
  780. } else {
  781. ObjectFreeRoutine[GenericObject->ObjectType](GenericObject );
  782. }
  783. //
  784. // Free the common fields
  785. //
  786. AzpFreeString( &GenericObject->Description );
  787. AzpFreeString( &GenericObject->ApplicationData );
  788. //
  789. // Free the object itself
  790. //
  791. PGENERIC_OBJECT_HEAD ParentGenericObjectHead = GenericObject->ParentGenericObjectHead;
  792. PGENERIC_OBJECT_NAME InsertedObjectName = GenericObject->ObjectName;
  793. AzpFreeHeap( GenericObject );
  794. //
  795. // Free the object name
  796. //
  797. if ( InsertedObjectName != NULL ) {
  798. if (!RtlDeleteElementGenericTable (
  799. &ParentGenericObjectHead->AvlTree,
  800. InsertedObjectName ) ) {
  801. InsertedObjectName->GenericObject = NULL;
  802. ASSERT( FALSE );
  803. }
  804. }
  805. }
  806. VOID
  807. ObIncrHandleRefCount(
  808. IN PGENERIC_OBJECT GenericObject
  809. )
  810. /*++
  811. Routine Description
  812. Increment the "handle" reference count on an object.
  813. On entry, AzGlResource must be locked shared.
  814. Arguments
  815. GenericObject - Specifies the object to insert into the list
  816. Return Value
  817. None
  818. --*/
  819. {
  820. //
  821. // Initialization
  822. //
  823. ASSERT( AzpIsLockedShared( &AzGlResource ) );
  824. //
  825. // Keep a reference to our parent object.
  826. // We validate the handle by walking the list of children in our parent.
  827. // So, prevent our parent from being deleted as long as the user has a handle to the child.
  828. //
  829. if ( ParentOfChild( GenericObject ) != NULL ) {
  830. InterlockedIncrement ( &(ParentOfChild( GenericObject )->ReferenceCount) );
  831. AzpDumpGoRef( "Child handle ref", ParentOfChild( GenericObject ));
  832. }
  833. //
  834. // The handle ref count is a real ref count. Increment it too.
  835. //
  836. InterlockedIncrement( &GenericObject->ReferenceCount );
  837. AzpDumpGoRef( "Handle ref", GenericObject );
  838. //
  839. // Increment the handle ref count
  840. //
  841. InterlockedIncrement( &GenericObject->HandleReferenceCount );
  842. AzPrint(( AZD_HANDLE, "0x%lx %ld (%ld): Open Handle\n", GenericObject, GenericObject->ObjectType, GenericObject->HandleReferenceCount ));
  843. //
  844. // Increment the reference count on the object at the root of the cache
  845. // This object has pointer to several objects in the cache. We don't
  846. // maintain references to those objects because that would lead to circular references.
  847. //
  848. InterlockedIncrement( &GenericObject->AzStoreObject->GenericObject.ReferenceCount );
  849. AzpDumpGoRef( "Authorization Store Handle ref", &GenericObject->AzStoreObject->GenericObject );
  850. }
  851. DWORD
  852. ObDecrHandleRefCount(
  853. IN PGENERIC_OBJECT GenericObject
  854. )
  855. /*++
  856. Routine Description
  857. Decrement the "handle" reference count on an object.
  858. On entry, AzGlResource must be locked shared.
  859. Arguments
  860. GenericObject - Specifies the object to insert into the list
  861. Return Value
  862. NO_ERROR - Handle was decremented successfully
  863. Other status codes
  864. --*/
  865. {
  866. DWORD WinStatus = NO_ERROR;
  867. //
  868. // Initialization
  869. //
  870. ASSERT( AzpIsLockedShared( &AzGlResource ) );
  871. //
  872. // Decrement the handle ref count
  873. //
  874. InterlockedDecrement( &GenericObject->HandleReferenceCount );
  875. AzPrint(( AZD_HANDLE, "0x%lx %ld (%ld): Close Handle\n", GenericObject, GenericObject->ObjectType, GenericObject->HandleReferenceCount ));
  876. //
  877. // Decrement the reference count on the entire tree of objects
  878. //
  879. AzpDumpGoRef( "Authorization Store Handle deref", &GenericObject->AzStoreObject->GenericObject );
  880. ObDereferenceObject( &GenericObject->AzStoreObject->GenericObject );
  881. //
  882. // The handle ref count is a real ref count. Decrement it too.
  883. //
  884. AzpDumpGoRef( "Handle deref", GenericObject );
  885. ObDereferenceObject( GenericObject );
  886. //
  887. // Decrement the ref count we have on our parent.
  888. //
  889. if ( ParentOfChild( GenericObject ) != NULL ) {
  890. AzpDumpGoRef( "Child handle deref", ParentOfChild( GenericObject ) );
  891. ObDereferenceObject( ParentOfChild( GenericObject ) );
  892. }
  893. //
  894. // Finally, if object whose handle ref count is being decreased is an application object,
  895. // then unload the children if the handle reference count is 0
  896. //
  897. if ( (GenericObject->HandleReferenceCount == 0) &&
  898. (GenericObject->ObjectType == OBJECT_TYPE_APPLICATION) ) {
  899. if ( ((PAZP_APPLICATION)GenericObject)->UnloadApplicationObject ) {
  900. AzpLockResourceSharedToExclusive( &AzGlResource );
  901. WinStatus = ObUnloadChildGenericHeads(GenericObject);
  902. if ( WinStatus != ERROR_NOT_SUPPORTED && WinStatus != NO_ERROR ) {
  903. //
  904. // Update the children cache of this application object
  905. //
  906. DWORD TempWinStatus = NO_ERROR;
  907. TempWinStatus = AzPersistUpdateChildrenCache( GenericObject );
  908. if ( TempWinStatus != NO_ERROR ) {
  909. AzPrint(( AZD_REF,
  910. "ObDecrHandleRefCount: Cannot reload children on failure of unload: %ld\n",
  911. TempWinStatus
  912. ));
  913. }
  914. goto Cleanup;
  915. }
  916. GenericObject->AreChildrenLoaded = FALSE;
  917. }
  918. }
  919. WinStatus = NO_ERROR;
  920. Cleanup:
  921. return WinStatus;
  922. }
  923. DWORD
  924. ObGetHandleType(
  925. IN PGENERIC_OBJECT Handle,
  926. IN BOOL AllowDeletedObjects,
  927. OUT PULONG ObjectType
  928. )
  929. /*++
  930. Routine Description
  931. This routine takes a handle passed by an application and safely determines what the
  932. handle type is.
  933. This routine allows a caller to support various handle types rather than being
  934. limited to one.
  935. Arguments
  936. Handle - Handle to check
  937. AllowDeletedObjects - TRUE if it is OK to use a handle to a deleted object
  938. ObjectType - Returns the type of object the handle represents
  939. Return Value
  940. NO_ERROR - the handle is OK
  941. ERROR_INVALID_HANDLE - the handle isn't OK
  942. --*/
  943. {
  944. DWORD WinStatus;
  945. PGENERIC_OBJECT GenericObject = Handle;
  946. //
  947. // Initialization
  948. //
  949. if ( Handle == NULL ) {
  950. AzPrint(( AZD_CRITICAL, "0x%lx: NULL handle is invalid\n", Handle ));
  951. return ERROR_INVALID_HANDLE;
  952. }
  953. //
  954. // Use a try/except since we're touching memory assuming the handle is valid
  955. //
  956. WinStatus = NO_ERROR;
  957. __try {
  958. //
  959. // Sanity check the scalar values on the object
  960. //
  961. if ( GenericObject->ObjectType >= OBJECT_TYPE_MAXIMUM ) {
  962. AzPrint(( AZD_CRITICAL, "0x%lx %ld: Handle Object type is too large.\n", GenericObject, GenericObject->ObjectType ));
  963. WinStatus = ERROR_INVALID_HANDLE;
  964. } else if ( GenericObject->HandleReferenceCount <= 0 ) {
  965. AzPrint(( AZD_HANDLE, "0x%lx %ld: Handle has no handle reference count.\n", GenericObject, GenericObject->ObjectType ));
  966. WinStatus = ERROR_INVALID_HANDLE;
  967. } else if ( GenericObject->ParentGenericObjectHead == NULL ) {
  968. AzPrint(( AZD_CRITICAL, "0x%lx %ld: Handle has no ParentGenericObjectHead.\n", GenericObject, GenericObject->ObjectType ));
  969. WinStatus = ERROR_INVALID_HANDLE;
  970. } else if ( !AllowDeletedObjects &&
  971. (GenericObject->Flags & GENOBJ_FLAGS_DELETED) != 0 ) {
  972. AzPrint(( AZD_CRITICAL, "0x%lx %ld: Object is deleted.\n", GenericObject, GenericObject->ObjectType ));
  973. WinStatus = ERROR_INVALID_HANDLE;
  974. } else {
  975. PGENERIC_OBJECT_HEAD ParentGenericObjectHead = GenericObject->ParentGenericObjectHead;
  976. //
  977. // Sanity check the object with its head
  978. //
  979. if ( ParentGenericObjectHead->ObjectType != GenericObject->ObjectType ) {
  980. AzPrint(( AZD_CRITICAL, "0x%lx %ld: Object type doesn't match parent.\n", GenericObject, GenericObject->ObjectType ));
  981. WinStatus = ERROR_INVALID_HANDLE;
  982. } else if ( GenericObject->SequenceNumber >= ParentGenericObjectHead->NextSequenceNumber ) {
  983. AzPrint(( AZD_CRITICAL, "0x%lx %ld: Sequence number doesn't match parent.\n", GenericObject, GenericObject->ObjectType ));
  984. WinStatus = ERROR_INVALID_HANDLE;
  985. } else {
  986. *ObjectType = GenericObject->ObjectType;
  987. }
  988. }
  989. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  990. AzPrint(( AZD_CRITICAL, "0x%lx: AV accessing handle\n", GenericObject ));
  991. WinStatus = ERROR_INVALID_HANDLE;
  992. }
  993. return WinStatus;
  994. }
  995. DWORD
  996. ObReferenceObjectByName(
  997. IN PGENERIC_OBJECT_HEAD GenericObjectHead,
  998. IN PAZP_STRING ObjectName,
  999. IN ULONG Flags,
  1000. OUT PGENERIC_OBJECT *RetGenericObject
  1001. )
  1002. /*++
  1003. Routine Description
  1004. This routine finds an object by the specified name.
  1005. On entry, AzGlResource must be locked shared.
  1006. Arguments
  1007. GenericObjectHead - Head of the list of objects to check
  1008. ObjectName - Object Name of the object to look for
  1009. Flags - Specifies internal flags
  1010. AZP_FLAGS_BY_GUID - name lists should be returned as GUID lists
  1011. AZP_FLAGS_ALLOW_DELETED_OBJECTS - Allow deleted objects to be found
  1012. AZP_FLAGS_REFRESH_CACHE - Ensure cache entry is up to date
  1013. AZP_FLAGS_RECONCILE - Call is from AzpPersistReconcile
  1014. RetGenericObject - On success, returns a pointer to the object
  1015. The returned pointer must be dereferenced using ObDereferenceObject.
  1016. Return Value
  1017. NO_ERROR: The object was returned
  1018. ERROR_NOT_FOUND: The object could not be found
  1019. Others: The object could not be refreshed
  1020. --*/
  1021. {
  1022. DWORD WinStatus;
  1023. PGENERIC_OBJECT GenericObject = NULL;
  1024. PGENERIC_OBJECT_NAME InsertedObjectName;
  1025. GENERIC_OBJECT_NAME TemplateObjectName;
  1026. PLIST_ENTRY ListEntry;
  1027. BOOL fGuidFound = FALSE;
  1028. //
  1029. // Initialization
  1030. //
  1031. ASSERT( AzpIsLockedShared( &AzGlResource ) );
  1032. *RetGenericObject = NULL;
  1033. if ( Flags & AZP_FLAGS_BY_GUID )
  1034. {
  1035. GUID *ObjectGuid = (GUID *)ObjectName;
  1036. AzPrint(( AZD_REF, "ObReferenceObjectByName (by guid): " ));
  1037. AzpDumpGuid( AZD_REF, ObjectGuid );
  1038. AzPrint(( AZD_REF, "\n" ));
  1039. for ( ListEntry = GenericObjectHead->Head.Flink ;
  1040. ListEntry != &GenericObjectHead->Head ;
  1041. ListEntry = ListEntry->Flink)
  1042. {
  1043. GenericObject = CONTAINING_RECORD( ListEntry,
  1044. GENERIC_OBJECT,
  1045. Next );
  1046. // compare guid
  1047. if (IsEqualGUID(*ObjectGuid, GenericObject->PersistenceGuid))
  1048. {
  1049. // find the object
  1050. fGuidFound = TRUE;
  1051. break;
  1052. }
  1053. }
  1054. if (!fGuidFound || NULL == GenericObject)
  1055. {
  1056. // not found
  1057. return ERROR_NOT_FOUND;
  1058. }
  1059. }
  1060. else
  1061. {
  1062. //
  1063. // Lookup the name in the AVL tree
  1064. //
  1065. TemplateObjectName.ObjectName = *ObjectName;
  1066. TemplateObjectName.GenericObject = NULL;
  1067. InsertedObjectName = (PGENERIC_OBJECT_NAME) RtlLookupElementGenericTable (
  1068. &GenericObjectHead->AvlTree,
  1069. &TemplateObjectName );
  1070. if ( InsertedObjectName == NULL ) {
  1071. return ERROR_NOT_FOUND;
  1072. }
  1073. GenericObject = InsertedObjectName->GenericObject;
  1074. }
  1075. ASSERT(NULL != GenericObject);
  1076. //
  1077. // Ignore deleted objects
  1078. //
  1079. if ( (Flags & AZP_FLAGS_ALLOW_DELETED_OBJECTS) == 0 &&
  1080. (GenericObject->Flags & GENOBJ_FLAGS_DELETED) != 0 ) {
  1081. return ERROR_NOT_FOUND;
  1082. }
  1083. //
  1084. // If the caller wants the object to be refreshed,
  1085. // do so now.
  1086. //
  1087. if ( (Flags & AZP_FLAGS_REFRESH_CACHE) != 0 &&
  1088. (GenericObject->Flags & GENOBJ_FLAGS_REFRESH_ME) != 0 ) {
  1089. AzpLockResourceSharedToExclusive( &AzGlResource );
  1090. WinStatus = AzPersistRefresh( GenericObject );
  1091. if ( WinStatus != NO_ERROR ) {
  1092. return WinStatus;
  1093. }
  1094. }
  1095. //
  1096. // Return the object to the caller
  1097. //
  1098. InterlockedIncrement( &GenericObject->ReferenceCount );
  1099. AzpDumpGoRef( "Ref by name", GenericObject );
  1100. *RetGenericObject = GenericObject;
  1101. return NO_ERROR;
  1102. }
  1103. DWORD
  1104. ObReferenceObjectByHandle(
  1105. IN PGENERIC_OBJECT Handle,
  1106. IN BOOL AllowDeletedObjects,
  1107. IN BOOLEAN RefreshCache,
  1108. IN ULONG ObjectType
  1109. )
  1110. /*++
  1111. Routine Description
  1112. This routine takes a handle passed by an application and safely determines whether
  1113. it is a valid handle. If so, this routine increments the reference count on the
  1114. handle to prevent the handle from being closed.
  1115. On entry, AzGlResource must be locked shared.
  1116. Arguments
  1117. Handle - Handle to check
  1118. AllowDeletedObjects - TRUE if it is OK to use a handle to a deleted object
  1119. RefreshCache - If TRUE, the returned object has its cache entry refreshed from
  1120. the policy database if needed.
  1121. If FALSE, the entry is returned unrefreshed.
  1122. ObjectType - Specifies the type of object the caller expects the handle to be
  1123. Return Value
  1124. NO_ERROR - the handle is OK
  1125. The handle must be dereferenced using ObDereferenceObject.
  1126. ERROR_INVALID_HANDLE - the handle isn't OK
  1127. --*/
  1128. {
  1129. DWORD WinStatus;
  1130. PGENERIC_OBJECT GenericObject = Handle;
  1131. ULONG LocalObjectType;
  1132. PGENERIC_OBJECT Current;
  1133. //
  1134. // Initialization
  1135. //
  1136. ASSERT( AzpIsLockedShared( &AzGlResource ) );
  1137. if ( Handle == NULL ) {
  1138. AzPrint(( AZD_CRITICAL, "0x%lx: NULL handle not allowed.\n", NULL ));
  1139. return ERROR_INVALID_HANDLE;
  1140. }
  1141. //
  1142. // Use a try/except since we're touching memory assuming the handle is valid
  1143. //
  1144. __try {
  1145. WinStatus = ObGetHandleType( Handle, AllowDeletedObjects, &LocalObjectType );
  1146. if ( WinStatus == NO_ERROR ) {
  1147. if ( ObjectType != LocalObjectType ) {
  1148. AzPrint(( AZD_HANDLE, "0x%lx %ld: Object Type not local object type\n", GenericObject, GenericObject->ObjectType ));
  1149. WinStatus = ERROR_INVALID_HANDLE;
  1150. } else {
  1151. PGENERIC_OBJECT_HEAD ParentGenericObjectHead = GenericObject->ParentGenericObjectHead;
  1152. //
  1153. // Ensure the object is actually in the list
  1154. //
  1155. // If the object has no name,
  1156. // search the linear list
  1157. //
  1158. if ( GenericObject->ObjectName == NULL ) {
  1159. PLIST_ENTRY ListEntry;
  1160. WinStatus = ERROR_INVALID_HANDLE;
  1161. for ( ListEntry = ParentGenericObjectHead->Head.Flink ;
  1162. ListEntry != &ParentGenericObjectHead->Head ;
  1163. ListEntry = ListEntry->Flink) {
  1164. Current = CONTAINING_RECORD( ListEntry,
  1165. GENERIC_OBJECT,
  1166. Next );
  1167. //
  1168. // If we found the object,
  1169. // grab a reference.
  1170. //
  1171. if ( Current == GenericObject ) {
  1172. //
  1173. // If the caller wants the object to be refreshed,
  1174. // do so now.
  1175. //
  1176. if ( RefreshCache &&
  1177. (GenericObject->Flags & GENOBJ_FLAGS_REFRESH_ME) != 0 ) {
  1178. //
  1179. // Need exclusive access
  1180. //
  1181. AzpLockResourceSharedToExclusive( &AzGlResource );
  1182. WinStatus = AzPersistRefresh( GenericObject );
  1183. if ( WinStatus != NO_ERROR ) {
  1184. break;
  1185. }
  1186. }
  1187. //
  1188. // Grab a reference to the object
  1189. //
  1190. InterlockedIncrement( &GenericObject->ReferenceCount );
  1191. AzpDumpGoRef( "Ref by Handle", GenericObject );
  1192. WinStatus = NO_ERROR;
  1193. break;
  1194. }
  1195. }
  1196. //
  1197. // If not,
  1198. // the handle is invalid.
  1199. //
  1200. if ( WinStatus == ERROR_INVALID_HANDLE ) {
  1201. AzPrint(( AZD_HANDLE, "0x%lx %ld: Handle not in list.\n", GenericObject, GenericObject->ObjectType ));
  1202. }
  1203. //
  1204. // If the object has a name,
  1205. // search the AVL name tree since there may be large numbers of such
  1206. // handles. We want to avoid a linear search.
  1207. //
  1208. } else {
  1209. WinStatus = ObReferenceObjectByName(
  1210. ParentGenericObjectHead,
  1211. &GenericObject->ObjectName->ObjectName,
  1212. (RefreshCache ? AZP_FLAGS_REFRESH_CACHE : 0) |
  1213. (AllowDeletedObjects ? AZP_FLAGS_ALLOW_DELETED_OBJECTS : 0 ),
  1214. &Current );
  1215. if ( WinStatus != NO_ERROR ) {
  1216. if ( WinStatus == ERROR_NOT_FOUND ) {
  1217. AzPrint(( AZD_CRITICAL, "0x%lx %ld: Object not in list.\n", GenericObject, GenericObject->ObjectType ));
  1218. WinStatus = ERROR_INVALID_HANDLE;
  1219. }
  1220. } else if ( Current != GenericObject ) {
  1221. WinStatus = ERROR_INVALID_HANDLE;
  1222. AzPrint(( AZD_CRITICAL, "0x%lx %ld: Found wrong object with name.\n", GenericObject, GenericObject->ObjectType ));
  1223. ObDereferenceObject( Current );
  1224. }
  1225. }
  1226. }
  1227. }
  1228. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  1229. AzPrint(( AZD_CRITICAL, "0x%lx: AV accessing handle\n", GenericObject ));
  1230. WinStatus = ERROR_INVALID_HANDLE;
  1231. }
  1232. return WinStatus;
  1233. }
  1234. VOID
  1235. ObDereferenceObject(
  1236. IN PGENERIC_OBJECT GenericObject
  1237. )
  1238. /*++
  1239. Routine Description
  1240. Decrement the reference count on an object.
  1241. When the last reference count is removed, delete the object.
  1242. On entry, AzGlResource must be locked shared. If the ref count reaches zero,
  1243. AzGlResource must be locked exclusively. We can get away with that because
  1244. we force the ref count to zero only when closing the AzAuthorizationStore object.
  1245. Arguments
  1246. GenericObject - Specifies the object to insert into the list
  1247. Return Value
  1248. None
  1249. --*/
  1250. {
  1251. ULONG RefCount;
  1252. //
  1253. // Initialization
  1254. //
  1255. ASSERT( AzpIsLockedShared( &AzGlResource ) );
  1256. //
  1257. // Decrement the reference count
  1258. //
  1259. RefCount = InterlockedDecrement( &GenericObject->ReferenceCount );
  1260. AzpDumpGoRef( "Deref", GenericObject );
  1261. //
  1262. // Check if the object is no longer referenced
  1263. //
  1264. if ( RefCount == 0 ) {
  1265. //
  1266. // Grab the lock exclusively
  1267. // If we are unloading the children of a parent object,
  1268. // we might already have the lock exclusively
  1269. //
  1270. ASSERT( GenericObject->HandleReferenceCount == 0 );
  1271. AzpLockResourceSharedToExclusive( &AzGlResource );
  1272. //
  1273. // Free the object itself
  1274. //
  1275. ObFreeGenericObject( GenericObject );
  1276. }
  1277. }
  1278. DWORD
  1279. AzpValidateName(
  1280. IN PAZP_STRING ObjectName,
  1281. IN ULONG ObjectType
  1282. )
  1283. /*++
  1284. Routine Description:
  1285. This routine does a syntax check to ensure that the object name string contains
  1286. only valid characters.
  1287. Arguments:
  1288. ObjectName - Specifies the name of the object to validate.
  1289. ObjectType - Specifies the type of the named object
  1290. Return Value:
  1291. NO_ERROR - The operation was successful
  1292. ERROR_INVALID_NAME - the syntax of the name is invalid
  1293. --*/
  1294. {
  1295. LPWSTR Result;
  1296. #define CTRL_CHARS_0 L"\001\002\003\004\005\006\007"
  1297. #define CTRL_CHARS_1 L"\010\011\012\013\014\015\016\017"
  1298. #define CTRL_CHARS_2 L"\020\021\022\023\024\025\026\027"
  1299. #define CTRL_CHARS_3 L"\030\031\032\033\034\035\036\037"
  1300. #define CTRL_CHARS_STR CTRL_CHARS_0 CTRL_CHARS_1 CTRL_CHARS_2 CTRL_CHARS_3
  1301. #define SCOPE_INVALID_CHARS (CTRL_CHARS_STR)
  1302. #define ALL_INVALID_CHARS (L"\"*/:<>?\\|" CTRL_CHARS_STR)
  1303. //
  1304. // No need to validate SID names.
  1305. // All sid names are generated internally.
  1306. //
  1307. if ( ObjectType == OBJECT_TYPE_SID ) {
  1308. ASSERT( ObjectName->IsSid );
  1309. return NO_ERROR;
  1310. }
  1311. ASSERT( !ObjectName->IsSid );
  1312. //
  1313. // Allow NULL names for objects without names
  1314. //
  1315. if ( MaxObjectNameLength[ObjectType] == 0 ) {
  1316. if ( ObjectName->String == NULL ) {
  1317. return NO_ERROR;
  1318. } else {
  1319. return ERROR_INVALID_NAME;
  1320. }
  1321. }
  1322. //
  1323. // Non-null names must have valid characters
  1324. //
  1325. //
  1326. // we disallow any leading and trailing spaces
  1327. //
  1328. if (ObjectName->StringSize <= 1 ||
  1329. ObjectName->String[0] == L' ' ||
  1330. ObjectName->String[(ObjectName->StringSize)/sizeof(ObjectName->String[0]) - 1] == L' ')
  1331. {
  1332. return ERROR_INVALID_NAME;
  1333. }
  1334. Result = wcspbrk( ObjectName->String,
  1335. ObjectType == OBJECT_TYPE_SCOPE ?
  1336. SCOPE_INVALID_CHARS :
  1337. ALL_INVALID_CHARS );
  1338. return Result == NULL ? NO_ERROR : ERROR_INVALID_NAME;
  1339. }
  1340. DWORD
  1341. ObBuildGuidizedName(
  1342. IN ULONG ObjectType,
  1343. IN PAZP_STRING ObjectName,
  1344. IN GUID *ObjectGuid,
  1345. OUT PAZP_STRING BuiltObjectName
  1346. )
  1347. /*++
  1348. Routine Description:
  1349. This routine builds a unique name for an object given its real name and a GUID.
  1350. This built name is used to resolve conflicts caused by renames, differences in the
  1351. underlying store and the cache, and naming problems in the underlying store.
  1352. The built name will be
  1353. <ObjectName>-<ObjectGuid>
  1354. Where <ObjectName> will be truncated on the right to meet maximum length restrictions
  1355. for the object type.
  1356. On entry, AzGlResource must be locked exclusive.
  1357. Arguments:
  1358. ObjectType - Specifies the object type of the object
  1359. ObjectName - Specifies the conflicting name of the object
  1360. ObjectGuid - Specifies the GUID of the object.
  1361. This GUID uniquely identifies the child object.
  1362. BuiltObjectName - Returns a pointer to the built name.
  1363. This string must be freed using AzpFreeString.
  1364. Return Value:
  1365. NO_ERROR - The operation was successful
  1366. ERROR_NOT_ENOUGH_MEMORY - There isn't enough memory to allocate the string
  1367. --*/
  1368. {
  1369. DWORD WinStatus;
  1370. LPWSTR GuidString;
  1371. ULONG GuidLength;
  1372. ULONG NameLength;
  1373. LPWSTR BuiltString;
  1374. //
  1375. // Convert UUID to a string
  1376. //
  1377. WinStatus = UuidToString( ObjectGuid, &GuidString );
  1378. if ( WinStatus != NO_ERROR ) {
  1379. return WinStatus;
  1380. }
  1381. GuidLength = (ULONG) wcslen( GuidString );
  1382. //
  1383. // Compute the number of characters to use from ObjectName
  1384. //
  1385. ASSERT( MaxObjectNameLength[ObjectType] != 0 );
  1386. ASSERT( MaxObjectNameLength[ObjectType] > GuidLength+1 );
  1387. NameLength = (ObjectName->StringSize/sizeof(WCHAR))-1;
  1388. if ( NameLength + 1 + GuidLength > MaxObjectNameLength[ObjectType] ) {
  1389. NameLength = MaxObjectNameLength[ObjectType] - 1 - GuidLength;
  1390. }
  1391. //
  1392. // Allocate a buffer for the return string
  1393. //
  1394. BuiltString = (LPWSTR) AzpAllocateHeap( (NameLength + 1 + GuidLength + 1) * sizeof(WCHAR), "GNGUIDNM" );
  1395. if ( BuiltString == NULL ) {
  1396. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  1397. goto Cleanup;
  1398. }
  1399. //
  1400. // Copy the strings to the allocated buffer
  1401. //
  1402. RtlCopyMemory( BuiltString, ObjectName->String, NameLength*sizeof(WCHAR) );
  1403. BuiltString[NameLength] = L'-';
  1404. RtlCopyMemory( &BuiltString[NameLength+1], GuidString, (GuidLength+1) * sizeof(WCHAR) );
  1405. //
  1406. // Return the built string to the caller
  1407. //
  1408. AzpInitString( BuiltObjectName, BuiltString );
  1409. WinStatus = NO_ERROR;
  1410. Cleanup:
  1411. RpcStringFree( &GuidString );
  1412. return WinStatus;
  1413. }
  1414. DWORD
  1415. ObCreateObject(
  1416. IN PGENERIC_OBJECT ParentGenericObject,
  1417. IN PGENERIC_OBJECT_HEAD GenericChildHead,
  1418. IN ULONG ChildObjectType,
  1419. IN PAZP_STRING ChildObjectNameString,
  1420. IN GUID *ChildObjectGuid OPTIONAL,
  1421. IN ULONG Flags,
  1422. OUT PGENERIC_OBJECT *RetChildGenericObject
  1423. )
  1424. /*++
  1425. Routine Description:
  1426. This routine creates a child object in the scope of the specified parent object.
  1427. On entry, AzGlResource must be locked exclusive.
  1428. Arguments:
  1429. ParentGenericObject - Specifies the parent object to add the child object onto.
  1430. be verified.
  1431. GenericChildHead - Specifies a pointer to the head of the list of children of
  1432. ParentGenericObject.
  1433. ChildObjectType - Specifies the object type RetChildGenericObject.
  1434. ChildObjectNameString - Specifies the name of the child object.
  1435. This name must be unique at the current scope.
  1436. ChildObjectGuid - Specifies the GUID of the child object.
  1437. This GUID uniquely identifies the child object.
  1438. This parameter is only specified in AzpModeInit.
  1439. If not specified, only the name of the object will be used to identify the child
  1440. and the GUID will be set to zero.
  1441. Flags - Specifies internal flags
  1442. AZP_FLAGS_BY_GUID - ChildObjectGuid is passed in (This flag is superfluous but is sanity checked.)
  1443. AZP_FLAGS_PERSIST_* - Call is from the persistence provider
  1444. AZP_FLAGS_RECONCILE - Call is from AzpPersistReconcile
  1445. RetChildGenericObject - Returns a pointer to the allocated generic child object
  1446. This pointer must be dereferenced using ObDereferenceObject.
  1447. Return Value:
  1448. NO_ERROR - The operation was successful
  1449. ERROR_ALREADY_EXISTS - An object by that name already exists
  1450. --*/
  1451. {
  1452. DWORD WinStatus;
  1453. ULONG DirtyBits;
  1454. PGENERIC_OBJECT ChildGenericObject = NULL;
  1455. PGENERIC_OBJECT FoundGenericObject = NULL;
  1456. BOOLEAN WeLinkedInObject = FALSE;
  1457. BOOLEAN NameConflicts = FALSE;
  1458. AZP_STRING BuiltChildObjectNameString;
  1459. //
  1460. // Initialization
  1461. //
  1462. ASSERT( ChildObjectType != OBJECT_TYPE_ROOT );
  1463. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  1464. AzpInitString( &BuiltChildObjectNameString, NULL );
  1465. //
  1466. // first things first, let's check if the AuthorizatioStore's versions support write
  1467. //
  1468. if (ParentGenericObject != NULL && IsNormalFlags(Flags) &&
  1469. !AzpAzStoreVersionAllowWrite(ParentGenericObject->AzStoreObject) )
  1470. {
  1471. WinStatus = ERROR_REVISION_MISMATCH;
  1472. goto Cleanup;
  1473. }
  1474. //
  1475. // Validate the name
  1476. // Don't complain to the persist provider
  1477. // Skip this test for SID object creation since they are
  1478. // never persisted
  1479. //
  1480. if ( (ChildObjectType != OBJECT_TYPE_SID ) &&
  1481. IsNormalFlags(Flags) ) {
  1482. //
  1483. // If the parent object has never been submitted,
  1484. // complain.
  1485. //
  1486. if ( ParentGenericObject != NULL &&
  1487. (ParentGenericObject->DirtyBits & AZ_DIRTY_CREATE) != 0 ) {
  1488. WinStatus = ERROR_DS_NO_PARENT_OBJECT;
  1489. goto Cleanup;
  1490. }
  1491. //
  1492. // Validate the syntax of the name
  1493. //
  1494. WinStatus = AzpValidateName( ChildObjectNameString, ChildObjectType );
  1495. if ( WinStatus != NO_ERROR ) {
  1496. goto Cleanup;
  1497. }
  1498. }
  1499. //
  1500. // If the GUID was passed in,
  1501. // determine if an object by this guid already exists
  1502. //
  1503. if ( ChildObjectGuid != NULL ) {
  1504. AzPrint(( AZD_REF, "ObCreateObject: %ws ", ChildObjectNameString->String ));
  1505. AzpDumpGuid( AZD_REF, ChildObjectGuid );
  1506. AzPrint(( AZD_REF, "\n" ));
  1507. ASSERT( Flags & AZP_FLAGS_BY_GUID );
  1508. ASSERT( Flags & (AZPE_FLAGS_PERSIST_MASK) );
  1509. WinStatus = ObReferenceObjectByName(
  1510. GenericChildHead,
  1511. (PAZP_STRING)ChildObjectGuid,
  1512. AZP_FLAGS_BY_GUID,
  1513. &ChildGenericObject );
  1514. if ( WinStatus == NO_ERROR ) {
  1515. ASSERT( ChildGenericObject->ObjectType == ChildObjectType );
  1516. } else if ( WinStatus == ERROR_NOT_FOUND ) {
  1517. ChildGenericObject = NULL;
  1518. } else {
  1519. goto Cleanup;
  1520. }
  1521. } else {
  1522. ASSERT( (Flags & AZP_FLAGS_BY_GUID) == 0 );
  1523. }
  1524. //
  1525. // Don't do name collision detection for client contexts.
  1526. // Client contexts don't have names
  1527. //
  1528. if ( ChildObjectType != OBJECT_TYPE_CLIENT_CONTEXT ) {
  1529. //
  1530. // Ensure the new name doesn't exist in the current list
  1531. // Deleted objects conflict since they consume our entry in the AVL tree.
  1532. // The caller should close the deleted object.
  1533. //
  1534. WinStatus = ObReferenceObjectByName( GenericChildHead,
  1535. ChildObjectNameString,
  1536. AZP_FLAGS_ALLOW_DELETED_OBJECTS,
  1537. &FoundGenericObject );
  1538. if ( WinStatus == NO_ERROR ) {
  1539. NameConflicts = TRUE;
  1540. } else if ( WinStatus == ERROR_NOT_FOUND ) {
  1541. //
  1542. // Ensure the name doesn't conflict with the names of other objects that share the namespace.
  1543. //
  1544. if ( ObjectNameConflictRoutine[ChildObjectType] != NULL ) {
  1545. WinStatus = ObjectNameConflictRoutine[ChildObjectType](
  1546. ParentGenericObject,
  1547. ChildObjectNameString );
  1548. if ( WinStatus != NO_ERROR ) {
  1549. NameConflicts = TRUE;
  1550. }
  1551. }
  1552. } else {
  1553. goto Cleanup;
  1554. }
  1555. //
  1556. // Handle name conflicts
  1557. //
  1558. if ( NameConflicts ) {
  1559. //
  1560. // If we're creating by GUID,
  1561. // then we don't care about the conflict
  1562. //
  1563. if ( ChildObjectGuid != NULL ) {
  1564. //
  1565. // If we found the object by GUID,
  1566. // and we found the same object by name,
  1567. // ignore the collision.
  1568. //
  1569. if ( FoundGenericObject == ChildGenericObject ) {
  1570. /* Drop through */
  1571. //
  1572. // If we collided with a different object,
  1573. // rename this one
  1574. //
  1575. } else {
  1576. WinStatus = ObBuildGuidizedName(
  1577. ChildObjectType,
  1578. ChildObjectNameString,
  1579. ChildObjectGuid,
  1580. &BuiltChildObjectNameString );
  1581. if ( WinStatus != NO_ERROR ) {
  1582. goto Cleanup;
  1583. }
  1584. }
  1585. } else {
  1586. WinStatus = ERROR_ALREADY_EXISTS;
  1587. goto Cleanup;
  1588. }
  1589. }
  1590. }
  1591. //
  1592. // If we found the object by GUID,
  1593. // set the name on the object
  1594. //
  1595. if ( ChildGenericObject != NULL ) {
  1596. //
  1597. // If the object doesn't yet have the correct name,
  1598. // set the name on the object.
  1599. //
  1600. if ( FoundGenericObject != ChildGenericObject ) {
  1601. WinStatus = ObSetProperty(
  1602. ChildGenericObject,
  1603. Flags,
  1604. AZ_PROP_NAME,
  1605. BuiltChildObjectNameString.StringSize ?
  1606. BuiltChildObjectNameString.String :
  1607. ChildObjectNameString->String );
  1608. if ( WinStatus != NO_ERROR ) {
  1609. goto Cleanup;
  1610. }
  1611. }
  1612. //
  1613. // If we didn't find the existing object by GUID,
  1614. // allocate a new one.
  1615. //
  1616. } else {
  1617. //
  1618. // Allocate the structure to return to the caller
  1619. // (And insert it into the list of children of this parent.)
  1620. //
  1621. ChildGenericObject = ObAllocateGenericObject(
  1622. GenericChildHead,
  1623. BuiltChildObjectNameString.StringSize ?
  1624. &BuiltChildObjectNameString :
  1625. ChildObjectNameString );
  1626. if ( ChildGenericObject == NULL ) {
  1627. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  1628. goto Cleanup;
  1629. }
  1630. ChildGenericObject->DirtyBits = 0;
  1631. //
  1632. // Set the optional characteristics to a default value. These will be changed
  1633. // subsequently, if required.
  1634. //
  1635. //
  1636. // Since we are creating the object, assume that it is writable. If not, the value will
  1637. // be changed from the provider
  1638. //
  1639. ChildGenericObject->IsWritable = TRUE;
  1640. ChildGenericObject->CanCreateChildren = TRUE;
  1641. ChildGenericObject->IsAclSupported = FALSE;
  1642. ChildGenericObject->IsDelegationSupported = FALSE;
  1643. ChildGenericObject->IsSACLSupported = FALSE;
  1644. WeLinkedInObject = TRUE;
  1645. //
  1646. // Keep a pointer to the object at the root of the tree
  1647. // Back pointers don't increment reference count.
  1648. //
  1649. if ( ChildObjectType == OBJECT_TYPE_AZAUTHSTORE ) {
  1650. ChildGenericObject->AzStoreObject = (PAZP_AZSTORE) ChildGenericObject;
  1651. } else {
  1652. ChildGenericObject->AzStoreObject = (PAZP_AZSTORE)
  1653. ParentGenericObject->AzStoreObject;
  1654. }
  1655. //
  1656. // Set AreChildrenLoaded to TRUE. This will be set to the appropriate value
  1657. // for AzApplication and AzScope objects in their respective init routines
  1658. //
  1659. ChildGenericObject->AreChildrenLoaded = TRUE;
  1660. //
  1661. // Call the routine to do object type specific initialization
  1662. //
  1663. if ( ObjectInitRoutine[ChildObjectType] == NULL ) {
  1664. ASSERT( ObjectInitRoutine[ChildObjectType] != NULL );
  1665. WinStatus = ERROR_INVALID_PARAMETER;
  1666. goto Cleanup;
  1667. }
  1668. WinStatus = ObjectInitRoutine[ChildObjectType](
  1669. ParentGenericObject,
  1670. ChildGenericObject );
  1671. if ( WinStatus != NO_ERROR ) {
  1672. goto Cleanup;
  1673. }
  1674. //
  1675. // If the object is of type OBJECT_TYPE_AUTHORIZATION_STORE or
  1676. // OBJECT_TYPE_APPLICATION or OBJECT_TYPE_SCOPE,
  1677. // then set the PolicyAdmins and PolicyReaders list
  1678. //
  1679. if ( IsContainerObject( ChildObjectType ) ) {
  1680. // ??? when one of these objects do object specific intialization
  1681. // we'll have to be careful to not destroy the existing pointer.
  1682. ChildGenericObject->GenericObjectLists =
  1683. &(ChildGenericObject->PolicyAdmins);
  1684. // policy admins
  1685. ObInitObjectList( &ChildGenericObject->PolicyAdmins,
  1686. &ChildGenericObject->PolicyReaders,
  1687. FALSE, // forward link
  1688. AZP_LINKPAIR_POLICY_ADMINS,
  1689. AZ_DIRTY_POLICY_ADMINS,
  1690. &ChildGenericObject->AzpSids,
  1691. NULL,
  1692. NULL
  1693. );
  1694. if ( !IsDelegatorObject( ChildObjectType ) ) {
  1695. // policy readers
  1696. ObInitObjectList( &ChildGenericObject->PolicyReaders,
  1697. NULL,
  1698. FALSE, // Forward link
  1699. AZP_LINKPAIR_POLICY_READERS, //diff admins and readers
  1700. AZ_DIRTY_POLICY_READERS,
  1701. &ChildGenericObject->AzpSids,
  1702. NULL,
  1703. NULL);
  1704. } else {
  1705. // policy readers
  1706. ObInitObjectList( &ChildGenericObject->PolicyReaders,
  1707. &ChildGenericObject->DelegatedPolicyUsers,
  1708. FALSE, // Forward link
  1709. AZP_LINKPAIR_POLICY_READERS, //diff admins and readers
  1710. AZ_DIRTY_POLICY_READERS,
  1711. &ChildGenericObject->AzpSids,
  1712. NULL,
  1713. NULL);
  1714. // policy readers
  1715. ObInitObjectList( &ChildGenericObject->DelegatedPolicyUsers,
  1716. NULL,
  1717. FALSE, // Forward link
  1718. AZP_LINKPAIR_DELEGATED_POLICY_USERS,
  1719. AZ_DIRTY_DELEGATED_POLICY_USERS,
  1720. &ChildGenericObject->AzpSids,
  1721. NULL,
  1722. NULL);
  1723. }
  1724. } // if object type is AzAuthStore or application or scope
  1725. }
  1726. //
  1727. // Remember the GUID
  1728. //
  1729. if ( ChildObjectGuid != NULL ) {
  1730. ChildGenericObject->PersistenceGuid = *ChildObjectGuid;
  1731. //
  1732. // If we had to make up a name for the object,
  1733. // and this call is from AzPersistUpdateCache,
  1734. // leave the new name lying around for AzpPersistReconcile to find so it can try to fix the issue.
  1735. //
  1736. if ( BuiltChildObjectNameString.StringSize != 0 &&
  1737. (Flags & AZPE_FLAGS_PERSIST_UPDATE_CACHE) != 0 ) {
  1738. if ( !ObAllocateNewName(
  1739. ChildGenericObject,
  1740. ChildObjectNameString ) ) {
  1741. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  1742. goto Cleanup;
  1743. }
  1744. }
  1745. }
  1746. //
  1747. // Set all of the object specific default scalar values
  1748. // Skip when call from persist provider since we'll catch this in AzpPersistReconcile
  1749. if ( IsNormalFlags(Flags) ) {
  1750. WinStatus = ObSetPropertyToDefault(
  1751. ChildGenericObject,
  1752. ObjectAllScalarDirtyBits[ChildObjectType] &
  1753. AZ_DIRTY_OBJECT_SPECIFIC );
  1754. if ( WinStatus != NO_ERROR ) {
  1755. goto Cleanup;
  1756. }
  1757. }
  1758. //
  1759. // Mark the object as needing to be written.
  1760. // Only the name has been set. All other attributes have been defaulted.
  1761. // Only named objects are dirty after creation.
  1762. //
  1763. DirtyBits = AzGlObjectAllDirtyBits[ChildObjectType] & (AZ_DIRTY_NAME|AZ_DIRTY_CREATE);
  1764. if ( IsNormalFlags(Flags) ) {
  1765. ChildGenericObject->DirtyBits |= DirtyBits;
  1766. } else {
  1767. ASSERT( AzpIsCritsectLocked( &ChildGenericObject->AzStoreObject->PersistCritSect ) );
  1768. ASSERT( (ChildGenericObject->Flags & GENOBJ_FLAGS_PERSIST_OK) == 0 );
  1769. ChildGenericObject->PersistDirtyBits = DirtyBits;
  1770. }
  1771. //
  1772. // Return the pointer to the new structure
  1773. //
  1774. *RetChildGenericObject = ChildGenericObject;
  1775. ChildGenericObject = NULL;
  1776. WinStatus = NO_ERROR;
  1777. //
  1778. // Free locally used resources
  1779. //
  1780. Cleanup:
  1781. if ( ChildGenericObject != NULL ) {
  1782. // Remove the local reference
  1783. ObDereferenceObject( ChildGenericObject );
  1784. if ( WeLinkedInObject ) {
  1785. // Remove the reference for being in the global list
  1786. ObDereferenceObject( ChildGenericObject );
  1787. }
  1788. }
  1789. if ( FoundGenericObject != NULL ) {
  1790. ObDereferenceObject( FoundGenericObject );
  1791. }
  1792. AzpFreeString( &BuiltChildObjectNameString );
  1793. return WinStatus;
  1794. }
  1795. DWORD
  1796. ObCommonCreateObject(
  1797. IN PGENERIC_OBJECT ParentGenericObject,
  1798. IN ULONG ParentObjectType,
  1799. IN PGENERIC_OBJECT_HEAD GenericChildHead,
  1800. IN ULONG ChildObjectType,
  1801. IN LPCWSTR ChildObjectName,
  1802. IN DWORD Reserved,
  1803. OUT PGENERIC_OBJECT *RetChildGenericObject
  1804. )
  1805. /*++
  1806. Routine Description:
  1807. This routine creates a child object in the scope of the specified parent object.
  1808. Arguments:
  1809. ParentGenericObject - Specifies a handle to the parent object to add the child
  1810. object onto. This "handle" has been passed from the application and needs to
  1811. be verified.
  1812. ParentObjectType - Specifies the object type ParentGenericObject.
  1813. GenericChildHead - Specifies a pointer to the head of the list of children of
  1814. ParentGenericObject. This is a computed pointer and is considered untrustworthy
  1815. until ParentGenericObject has been verified.
  1816. ChildObjectType - Specifies the object type RetChildGenericObject.
  1817. ChildObjectName - Specifies the name of the child object.
  1818. This name must be unique at the current scope.
  1819. This name is passed from the application and needs to be verified.
  1820. Reserved - Reserved. Must by zero.
  1821. RetChildGenericObject - Return a handle to the generic child object
  1822. The caller must close this handle by calling AzCloseHandle.
  1823. Return Value:
  1824. NO_ERROR - The operation was successful
  1825. ERROR_ALREADY_EXISTS - An object by that name already exists
  1826. --*/
  1827. {
  1828. DWORD WinStatus;
  1829. PGENERIC_OBJECT ReferencedParentObject = NULL;
  1830. PGENERIC_OBJECT ChildGenericObject = NULL;
  1831. AZP_STRING ChildObjectNameString;
  1832. //
  1833. // Grab the global lock
  1834. //
  1835. ASSERT( ParentObjectType != OBJECT_TYPE_ROOT );
  1836. ASSERT( ChildObjectType != OBJECT_TYPE_AZAUTHSTORE );
  1837. AzpLockResourceExclusive( &AzGlResource );
  1838. AzpInitString( &ChildObjectNameString, NULL );
  1839. //
  1840. // Initialization
  1841. //
  1842. __try {
  1843. *RetChildGenericObject = NULL;
  1844. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  1845. WinStatus = RtlNtStatusToDosError( GetExceptionCode());
  1846. goto Cleanup;
  1847. }
  1848. //
  1849. // Validate the input parameters
  1850. //
  1851. if ( Reserved != 0 ) {
  1852. AzPrint(( AZD_INVPARM, "ObCommonCreateObject: Reserved != 0\n" ));
  1853. WinStatus = ERROR_INVALID_PARAMETER;
  1854. goto Cleanup;
  1855. }
  1856. //
  1857. // Validate the passed in handle
  1858. //
  1859. WinStatus = ObReferenceObjectByHandle( ParentGenericObject,
  1860. FALSE, // Don't allow deleted objects
  1861. TRUE, // Refresh the cache
  1862. ParentObjectType );
  1863. if ( WinStatus != NO_ERROR ) {
  1864. goto Cleanup;
  1865. }
  1866. ReferencedParentObject = ParentGenericObject;
  1867. //
  1868. // first, let's make sure that caller can create new object
  1869. //
  1870. if ( ReferencedParentObject->CanCreateChildren == 0 && ChildObjectType != OBJECT_TYPE_CLIENT_CONTEXT ) {
  1871. WinStatus = ERROR_ACCESS_DENIED;
  1872. goto Cleanup;
  1873. }
  1874. //
  1875. // If the parent has not been loaded, then load the parent first
  1876. //
  1877. if ( !(ReferencedParentObject->AreChildrenLoaded) ) {
  1878. WinStatus = AzPersistUpdateChildrenCache(
  1879. ReferencedParentObject
  1880. );
  1881. if ( WinStatus != NO_ERROR ) {
  1882. goto Cleanup;
  1883. }
  1884. }
  1885. //
  1886. // Capture the object name string from the caller
  1887. //
  1888. WinStatus = AzpCaptureString( &ChildObjectNameString,
  1889. ChildObjectName,
  1890. MaxObjectNameLength[ChildObjectType],
  1891. ChildObjectType == OBJECT_TYPE_CLIENT_CONTEXT ); // NULL names only OK for client context
  1892. if ( WinStatus != NO_ERROR ) {
  1893. goto Cleanup;
  1894. }
  1895. //
  1896. // Create the object
  1897. //
  1898. WinStatus = ObCreateObject(
  1899. ParentGenericObject,
  1900. GenericChildHead,
  1901. ChildObjectType,
  1902. &ChildObjectNameString,
  1903. NULL, // Guid not known
  1904. 0, // No special flags
  1905. &ChildGenericObject );
  1906. if ( WinStatus != NO_ERROR ) {
  1907. goto Cleanup;
  1908. }
  1909. //
  1910. // Return the handle to the caller
  1911. //
  1912. ObIncrHandleRefCount( ChildGenericObject );
  1913. *RetChildGenericObject = ChildGenericObject;
  1914. WinStatus = NO_ERROR;
  1915. //
  1916. // Free locally used resources
  1917. //
  1918. Cleanup:
  1919. if ( ReferencedParentObject != NULL ) {
  1920. ObDereferenceObject( ReferencedParentObject );
  1921. }
  1922. if ( ChildGenericObject != NULL ) {
  1923. ObDereferenceObject( ChildGenericObject );
  1924. }
  1925. AzpFreeString( &ChildObjectNameString );
  1926. //
  1927. // Drop the global lock
  1928. //
  1929. AzpUnlockResource( &AzGlResource );
  1930. return WinStatus;
  1931. }
  1932. DWORD
  1933. ObCommonOpenObject(
  1934. IN PGENERIC_OBJECT ParentGenericObject,
  1935. IN ULONG ParentObjectType,
  1936. IN PGENERIC_OBJECT_HEAD GenericChildHead,
  1937. IN ULONG ChildObjectType,
  1938. IN LPCWSTR ChildObjectName,
  1939. IN DWORD Reserved,
  1940. OUT PGENERIC_OBJECT *RetChildGenericObject
  1941. )
  1942. /*++
  1943. Routine Description:
  1944. This routine opens a child object in the scope of the specified parent object.
  1945. Arguments:
  1946. ParentGenericObject - Specifies a handle to the parent object to open the child
  1947. object from. This "handle" has been passed from the application and needs to
  1948. be verified.
  1949. ParentObjectType - Specifies the object type ParentGenericObject.
  1950. GenericChildHead - Specifies a pointer to the head of the list of children of
  1951. ParentGenericObject. This is a computed pointer and is considered untrustworthy
  1952. until ParentGenericObject has been verified.
  1953. ChildObjectType - Specifies the object type RetChildGenericObject.
  1954. ChildObjectName - Specifies the name of the child object.
  1955. This name is passed from the application and needs to be verified.
  1956. Reserved - Reserved. Must by zero.
  1957. RetChildGenericObject - Return a handle to the generic child object
  1958. The caller must close this handle by calling AzCloseHandle.
  1959. Return Value:
  1960. NO_ERROR - The operation was successful
  1961. ERROR_NOT_FOUND - There is no object by that name
  1962. --*/
  1963. {
  1964. DWORD WinStatus;
  1965. PGENERIC_OBJECT ReferencedParentObject = NULL;
  1966. PGENERIC_OBJECT ChildGenericObject = NULL;
  1967. AZP_STRING ChildObjectNameString;
  1968. //
  1969. // Grab the global lock
  1970. //
  1971. AzpLockResourceShared( &AzGlResource );
  1972. ASSERT( ParentObjectType != OBJECT_TYPE_ROOT );
  1973. ASSERT( ChildObjectType != OBJECT_TYPE_AZAUTHSTORE );
  1974. //
  1975. // Initialization
  1976. //
  1977. AzpInitString( &ChildObjectNameString, NULL );
  1978. __try {
  1979. *RetChildGenericObject = NULL;
  1980. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  1981. WinStatus = RtlNtStatusToDosError( GetExceptionCode());
  1982. goto Cleanup;
  1983. }
  1984. //
  1985. // Validate the input parameters
  1986. //
  1987. if ( Reserved != 0 ) {
  1988. AzPrint(( AZD_INVPARM, "ObCommonOpenObject: Reserved != 0\n" ));
  1989. WinStatus = ERROR_INVALID_PARAMETER;
  1990. goto Cleanup;
  1991. }
  1992. //
  1993. // Validate the passed in handle
  1994. //
  1995. WinStatus = ObReferenceObjectByHandle( ParentGenericObject,
  1996. FALSE, // Don't allow deleted objects
  1997. TRUE, // Refresh the cache
  1998. ParentObjectType );
  1999. if ( WinStatus != NO_ERROR ) {
  2000. goto Cleanup;
  2001. }
  2002. ReferencedParentObject = ParentGenericObject;
  2003. //
  2004. // If the parent has not been loaded, then load the parent first
  2005. //
  2006. if ( !(ParentGenericObject->AreChildrenLoaded) ) {
  2007. //
  2008. // grab the resource lock exclusively
  2009. //
  2010. AzpLockResourceSharedToExclusive( &AzGlResource );
  2011. WinStatus = AzPersistUpdateChildrenCache(
  2012. ParentGenericObject
  2013. );
  2014. AzpLockResourceExclusiveToShared( &AzGlResource );
  2015. if ( WinStatus != NO_ERROR ) {
  2016. goto Cleanup;
  2017. }
  2018. }
  2019. //
  2020. // Capture the object name string from the caller
  2021. //
  2022. WinStatus = AzpCaptureString( &ChildObjectNameString,
  2023. ChildObjectName,
  2024. MaxObjectNameLength[ChildObjectType],
  2025. FALSE ); // NULL names not OK
  2026. if ( WinStatus != NO_ERROR ) {
  2027. goto Cleanup;
  2028. }
  2029. //
  2030. // Find the named object
  2031. //
  2032. WinStatus = ObReferenceObjectByName( GenericChildHead,
  2033. &ChildObjectNameString,
  2034. AZP_FLAGS_REFRESH_CACHE,
  2035. &ChildGenericObject );
  2036. if ( WinStatus != NO_ERROR ) {
  2037. goto Cleanup;
  2038. }
  2039. //
  2040. // Return the handle to the caller
  2041. //
  2042. ObIncrHandleRefCount( ChildGenericObject );
  2043. *RetChildGenericObject = ChildGenericObject;
  2044. WinStatus = NO_ERROR;
  2045. //
  2046. // Free locally used resources
  2047. //
  2048. Cleanup:
  2049. if ( ReferencedParentObject != NULL ) {
  2050. ObDereferenceObject( ReferencedParentObject );
  2051. }
  2052. if ( ChildGenericObject != NULL ) {
  2053. ObDereferenceObject( ChildGenericObject );
  2054. }
  2055. AzpFreeString( &ChildObjectNameString );
  2056. //
  2057. // Drop the global lock
  2058. //
  2059. AzpUnlockResource( &AzGlResource );
  2060. return WinStatus;
  2061. }
  2062. DWORD
  2063. ObEnumObjects(
  2064. IN PGENERIC_OBJECT_HEAD GenericChildHead,
  2065. IN BOOL EnumerateDeletedObjects,
  2066. IN BOOL RefreshCache,
  2067. IN OUT PULONG EnumerationContext,
  2068. OUT PGENERIC_OBJECT *RetChildGenericObject
  2069. )
  2070. /*++
  2071. Routine Description:
  2072. This routine enumerates the next child object from the scope of the specified parent object.
  2073. On entry, AzGlResource must be locked shared.
  2074. Arguments:
  2075. GenericChildHead - Specifies a pointer to the head of the list of children of
  2076. ParentGenericObject.
  2077. EnumerateDeletedObjects - Specifies whether deleted objects are to be returned
  2078. in the enumeration.
  2079. RefreshCache - If TRUE, the returned object has its cache entry refreshed from
  2080. the policy database if needed.
  2081. If FALSE, the entry is returned unrefreshed.
  2082. EnumerationContext - Specifies a context indicating the next object to return
  2083. On input for the first call, should point to zero.
  2084. On input for subsequent calls, should point to the value returned on the previous call.
  2085. On output, returns a value to be passed on the next call.
  2086. RetChildGenericObject - Returns a pointer to the generic child object
  2087. Return Value:
  2088. NO_ERROR - The operation was successful (a handle was returned)
  2089. ERROR_NO_MORE_ITEMS - No more items were available for enumeration
  2090. --*/
  2091. {
  2092. DWORD WinStatus;
  2093. PLIST_ENTRY ListEntry;
  2094. PGENERIC_OBJECT ChildGenericObject = NULL;
  2095. //
  2096. // If we've already returned the whole list,
  2097. // don't bother walking the list.
  2098. //
  2099. ASSERT( AzpIsLockedShared( &AzGlResource ) );
  2100. if ( *EnumerationContext >= GenericChildHead->NextSequenceNumber ) {
  2101. WinStatus = ERROR_NO_MORE_ITEMS;
  2102. goto Cleanup;
  2103. }
  2104. //
  2105. // Walk the list of children finding where we left off
  2106. //
  2107. for ( ListEntry = GenericChildHead->Head.Flink ;
  2108. ListEntry != &GenericChildHead->Head ;
  2109. ListEntry = ListEntry->Flink) {
  2110. ChildGenericObject = CONTAINING_RECORD( ListEntry,
  2111. GENERIC_OBJECT,
  2112. Next );
  2113. //
  2114. // See if this is it
  2115. //
  2116. if ( ChildGenericObject->SequenceNumber > *EnumerationContext ) {
  2117. //
  2118. // Ignore deleted object if the caller doesn't want to see them
  2119. //
  2120. // If this is not a deleted object,
  2121. // or the caller wants deleted objects to be returned,
  2122. // return it.
  2123. //
  2124. if ((ChildGenericObject->Flags & GENOBJ_FLAGS_DELETED) == 0 ||
  2125. EnumerateDeletedObjects ) {
  2126. break;
  2127. }
  2128. }
  2129. ChildGenericObject = NULL;
  2130. }
  2131. //
  2132. // If we've already returned the whole list,
  2133. // indicate so.
  2134. //
  2135. if ( ChildGenericObject == NULL ) {
  2136. WinStatus = ERROR_NO_MORE_ITEMS;
  2137. goto Cleanup;
  2138. }
  2139. //
  2140. // If the caller wants the object to be refreshed,
  2141. // do so now.
  2142. //
  2143. if ( RefreshCache &&
  2144. (ChildGenericObject->Flags & GENOBJ_FLAGS_REFRESH_ME) != 0 ) {
  2145. //
  2146. // Need exclusive access
  2147. //
  2148. AzpLockResourceSharedToExclusive( &AzGlResource );
  2149. WinStatus = AzPersistRefresh( ChildGenericObject );
  2150. if ( WinStatus != NO_ERROR ) {
  2151. goto Cleanup;
  2152. }
  2153. }
  2154. //
  2155. // Return the handle to the caller
  2156. //
  2157. *EnumerationContext = ChildGenericObject->SequenceNumber;
  2158. *RetChildGenericObject = ChildGenericObject;
  2159. WinStatus = NO_ERROR;
  2160. //
  2161. // Free locally used resources
  2162. //
  2163. Cleanup:
  2164. return WinStatus;
  2165. }
  2166. DWORD
  2167. ObCommonEnumObjects(
  2168. IN PGENERIC_OBJECT ParentGenericObject,
  2169. IN ULONG ParentObjectType,
  2170. IN PGENERIC_OBJECT_HEAD GenericChildHead,
  2171. IN OUT PULONG EnumerationContext,
  2172. IN DWORD Reserved,
  2173. OUT PGENERIC_OBJECT *RetChildGenericObject
  2174. )
  2175. /*++
  2176. Routine Description:
  2177. This routine enumerates the next child object from the scope of the specified parent object.
  2178. If the children of the parent have not yet been loaded, call the persistence provider routine
  2179. to load all the children of the parent object.
  2180. Arguments:
  2181. ParentGenericObject - Specifies a handle to the parent object to enumerate the child
  2182. objects of.
  2183. This "handle" has been passed from the application and needs to be verified.
  2184. ParentObjectType - Specifies the object type ParentGenericObject.
  2185. GenericChildHead - Specifies a pointer to the head of the list of children of
  2186. ParentGenericObject. This is a computed pointer and is considered untrustworthy
  2187. until ParentGenericObject has been verified.
  2188. EnumerationContext - Specifies a context indicating the next object to return
  2189. On input for the first call, should point to zero.
  2190. On input for subsequent calls, should point to the value returned on the previous call.
  2191. On output, returns a value to be passed on the next call.
  2192. Reserved - Reserved. Must by zero.
  2193. RetChildGenericObject - Returns a handle to the generic child object
  2194. The caller must close this handle by calling AzpDzCloseHandle.
  2195. Return Value:
  2196. NO_ERROR - The operation was successful (a handle was returned)
  2197. ERROR_NO_MORE_ITEMS - No more items were available for enumeration
  2198. --*/
  2199. {
  2200. DWORD WinStatus;
  2201. PGENERIC_OBJECT ReferencedParentObject = NULL;
  2202. PGENERIC_OBJECT ChildGenericObject = NULL;
  2203. //
  2204. // Grab the global lock
  2205. //
  2206. ASSERT( ParentObjectType != OBJECT_TYPE_ROOT );
  2207. AzpLockResourceShared( &AzGlResource );
  2208. //
  2209. // Initialize the return handle
  2210. //
  2211. __try {
  2212. *RetChildGenericObject = NULL;
  2213. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  2214. WinStatus = RtlNtStatusToDosError( GetExceptionCode());
  2215. goto Cleanup;
  2216. }
  2217. //
  2218. // Validate the input parameters
  2219. //
  2220. if ( Reserved != 0 ) {
  2221. AzPrint(( AZD_INVPARM, "ObCommonEnumObjects: Reserved != 0\n" ));
  2222. WinStatus = ERROR_INVALID_PARAMETER;
  2223. goto Cleanup;
  2224. }
  2225. //
  2226. // Validate the passed in handle
  2227. //
  2228. WinStatus = ObReferenceObjectByHandle( ParentGenericObject,
  2229. FALSE, // Don't allow deleted objects
  2230. TRUE, // Refresh the cache
  2231. ParentObjectType );
  2232. if ( WinStatus != NO_ERROR ) {
  2233. goto Cleanup;
  2234. }
  2235. //
  2236. // If the parent needs to be loaded for its children, then do it now
  2237. // If the parent has not been submitted, then no need to do so
  2238. //
  2239. if ( GenericChildHead->LoadParentBeforeReferencing &&
  2240. !(ParentGenericObject->AreChildrenLoaded) ) {
  2241. //
  2242. // Grab the resource lock exclusively
  2243. //
  2244. AzpLockResourceSharedToExclusive( &AzGlResource );
  2245. WinStatus = AzPersistUpdateChildrenCache( ParentGenericObject );
  2246. AzpLockResourceExclusiveToShared( &AzGlResource );
  2247. if ( WinStatus != NO_ERROR ) {
  2248. goto Cleanup;
  2249. }
  2250. ParentGenericObject->AreChildrenLoaded = TRUE;
  2251. }
  2252. ReferencedParentObject = ParentGenericObject;
  2253. //
  2254. // Call the common routine to do the actual enumeration
  2255. //
  2256. WinStatus = ObEnumObjects( GenericChildHead,
  2257. FALSE, // Don't enumerate deleted objects
  2258. TRUE, // Refresh the cache
  2259. EnumerationContext,
  2260. &ChildGenericObject );
  2261. if ( WinStatus != NO_ERROR ) {
  2262. goto Cleanup;
  2263. }
  2264. //
  2265. // Return the handle to the caller
  2266. //
  2267. ObIncrHandleRefCount( ChildGenericObject );
  2268. *RetChildGenericObject = ChildGenericObject;
  2269. WinStatus = NO_ERROR;
  2270. //
  2271. // Free locally used resources
  2272. //
  2273. Cleanup:
  2274. if ( ReferencedParentObject != NULL ) {
  2275. ObDereferenceObject( ReferencedParentObject );
  2276. }
  2277. //
  2278. // Drop the global lock
  2279. //
  2280. AzpUnlockResource( &AzGlResource );
  2281. return WinStatus;
  2282. }
  2283. DWORD
  2284. ObCommonGetProperty(
  2285. IN PGENERIC_OBJECT GenericObject,
  2286. IN ULONG Flags,
  2287. IN ULONG PropertyId,
  2288. IN DWORD Reserved,
  2289. OUT PVOID *PropertyValue
  2290. )
  2291. /*++
  2292. Routine Description:
  2293. Returns the specified property for a generic object.
  2294. Arguments:
  2295. GenericObject - Specifies a handle to the object to get the property from.
  2296. This "handle" has been passed from the application and needs to be verified.
  2297. Flags - Specifies internal flags
  2298. AZP_FLAGS_BY_GUID - name lists should be returned as GUID lists
  2299. AZP_FLAGS_PERSIST_* - Call is from the persistence provider
  2300. PropertyId - Specifies which property to return.
  2301. Reserved - Reserved. Must by zero.
  2302. PropertyValue - Specifies a pointer to return the property in.
  2303. The returned pointer must be freed using AzFreeMemory.
  2304. The returned value and type depends in PropertyId. The valid values are:
  2305. AZ_PROP_NAME LPWSTR - Object name of the object
  2306. AZ_PROP_DESCRIPTION LPWSTR - Description of the object
  2307. AZ_PROP_APPLICATION_DATA LPWSTR - Opaque data stored by an application
  2308. AZ_PROP_POLICY_ADMINS PAZ_SID_ARRAY - List of policy admins
  2309. AZ_PROP_POLICY_READERS PAZ_SID_ARRAY - List of policy reader
  2310. AZ_PROP_DELEGATED_POLICY_USERS PAZ_SID_ARRAY - List of delegated policy users
  2311. Any object specific properties.
  2312. Return Value:
  2313. NO_ERROR - The operation was successful
  2314. ERROR_INVALID_PARAMETER - PropertyId isn't valid
  2315. --*/
  2316. {
  2317. DWORD WinStatus;
  2318. ULONG ObjectType;
  2319. PGENERIC_OBJECT ReferencedGenericObject = NULL;
  2320. //
  2321. // Grab the global lock
  2322. //
  2323. AzpLockResourceShared( &AzGlResource );
  2324. //
  2325. // Initialize the return value
  2326. //
  2327. __try {
  2328. *PropertyValue = NULL;
  2329. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  2330. WinStatus = RtlNtStatusToDosError( GetExceptionCode());
  2331. goto Cleanup;
  2332. }
  2333. //
  2334. // Validate the input parameters
  2335. //
  2336. if ( Reserved != 0 ) {
  2337. AzPrint(( AZD_INVPARM, "ObCommonGetProperty: Reserved != 0\n" ));
  2338. WinStatus = ERROR_INVALID_PARAMETER;
  2339. goto Cleanup;
  2340. }
  2341. //
  2342. // Determine the type of the object
  2343. //
  2344. WinStatus = ObGetHandleType( GenericObject,
  2345. FALSE, // Don't allow deleted objects
  2346. &ObjectType );
  2347. if ( WinStatus != NO_ERROR ) {
  2348. goto Cleanup;
  2349. }
  2350. //
  2351. // Validate the passed in handle
  2352. //
  2353. WinStatus = ObReferenceObjectByHandle( GenericObject,
  2354. FALSE, // Don't allow deleted objects
  2355. TRUE, // Refresh the cache
  2356. ObjectType );
  2357. if ( WinStatus != NO_ERROR ) {
  2358. goto Cleanup;
  2359. }
  2360. ReferencedGenericObject = GenericObject;
  2361. //
  2362. // Call the common routine
  2363. //
  2364. WinStatus = ObGetProperty( GenericObject,
  2365. Flags,
  2366. PropertyId,
  2367. PropertyValue );
  2368. //
  2369. // Free locally used resources
  2370. //
  2371. Cleanup:
  2372. if ( ReferencedGenericObject != NULL ) {
  2373. ObDereferenceObject( ReferencedGenericObject );
  2374. }
  2375. //
  2376. // Drop the global lock
  2377. //
  2378. AzpUnlockResource( &AzGlResource );
  2379. return WinStatus;
  2380. }
  2381. DWORD
  2382. ObGetProperty(
  2383. IN PGENERIC_OBJECT GenericObject,
  2384. IN ULONG Flags,
  2385. IN ULONG PropertyId,
  2386. OUT PVOID *PropertyValue
  2387. )
  2388. /*++
  2389. Routine Description:
  2390. Returns the specified property for a generic object.
  2391. Arguments:
  2392. GenericObject - Specifies a handle to the object to get the property from.
  2393. This "handle" has been passed from the application and needs to be verified.
  2394. Flags - Specifies internal flags
  2395. AZP_FLAGS_BY_GUID - name lists should be returned as GUID lists
  2396. AZP_FLAGS_PERSIST_* - Call is from the persistence provider
  2397. PropertyId - Specifies which property to return.
  2398. Reserved - Reserved. Must by zero.
  2399. PropertyValue - Specifies a pointer to return the property in.
  2400. The returned pointer must be freed using AzFreeMemory.
  2401. The returned value and type depends in PropertyId. The valid values are:
  2402. AZ_PROP_NAME LPWSTR - Object name of the object
  2403. AZ_PROP_DESCRIPTION LPWSTR - Description of the object
  2404. AZ_PROP_APPLICATION_DATA LPWSTR - Opaque data stored by an application
  2405. AZ_PROP_POLICY_ADMINS PAZ_SID_ARRAY - List of policy admins
  2406. AZ_PROP_POLICY_READERS PAZ_SID_ARRAY - List of policy reader
  2407. AZ_PROP_GENERATE_AUDITS ULONG - whether the object's auditing flag is set
  2408. AZ_PROP_APPLY_STORE_SACL LONG - whether the object's apply sacl flag is set
  2409. Any object specific properties.
  2410. Return Value:
  2411. NO_ERROR - The operation was successful
  2412. ERROR_INVALID_PARAMETER - PropertyId isn't valid
  2413. --*/
  2414. {
  2415. DWORD WinStatus;
  2416. //
  2417. // Initialize the return value
  2418. //
  2419. *PropertyValue = NULL;
  2420. //
  2421. // Return any common attribute
  2422. //
  2423. // Return object name to the caller
  2424. //
  2425. switch ( PropertyId ) {
  2426. case AZ_PROP_NAME:
  2427. //
  2428. // Fail if the object is unnamed
  2429. //
  2430. if ( (AzGlObjectAllDirtyBits[GenericObject->ObjectType] & AZ_DIRTY_NAME) == 0 ) {
  2431. AzPrint(( AZD_INVPARM, "ObCommonGetProperty: Object has no name\n" ));
  2432. WinStatus = ERROR_INVALID_PARAMETER;
  2433. goto Cleanup;
  2434. }
  2435. *PropertyValue = AzpGetStringProperty( &GenericObject->ObjectName->ObjectName );
  2436. if ( *PropertyValue == NULL ) {
  2437. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  2438. goto Cleanup;
  2439. }
  2440. break;
  2441. //
  2442. // Return object decription to the caller
  2443. //
  2444. case AZ_PROP_DESCRIPTION:
  2445. //
  2446. // Fail if the object has no description
  2447. //
  2448. if ( (AzGlObjectAllDirtyBits[GenericObject->ObjectType] & AZ_DIRTY_DESCRIPTION) == 0 ) {
  2449. AzPrint(( AZD_INVPARM, "ObCommonGetProperty: Object has no description\n" ));
  2450. WinStatus = ERROR_INVALID_PARAMETER;
  2451. goto Cleanup;
  2452. }
  2453. *PropertyValue = AzpGetStringProperty( &GenericObject->Description );
  2454. if ( *PropertyValue == NULL ) {
  2455. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  2456. goto Cleanup;
  2457. }
  2458. break;
  2459. //
  2460. // Return object application data to the caller
  2461. //
  2462. case AZ_PROP_APPLICATION_DATA:
  2463. //
  2464. // Fail if the object has no application data
  2465. //
  2466. if ( (AzGlObjectAllDirtyBits[GenericObject->ObjectType] & AZ_DIRTY_APPLICATION_DATA) == 0 ) {
  2467. AzPrint(( AZD_INVPARM, "ObCommonGetProperty:"
  2468. "Object has no application data\n" ));
  2469. WinStatus = ERROR_INVALID_PARAMETER;
  2470. goto Cleanup;
  2471. }
  2472. *PropertyValue = AzpGetStringProperty( &GenericObject->ApplicationData );
  2473. if ( *PropertyValue == NULL ) {
  2474. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  2475. goto Cleanup;
  2476. }
  2477. break;
  2478. //
  2479. // Return audit boolean flag
  2480. //
  2481. case AZ_PROP_GENERATE_AUDITS:
  2482. //
  2483. // Ensure the call has privilege
  2484. //
  2485. if ( IsNormalFlags(Flags) ) {
  2486. if ( !GenericObject->AzStoreObject->HasSecurityPrivilege ) {
  2487. WinStatus = ERROR_ACCESS_DENIED;
  2488. goto Cleanup;
  2489. }
  2490. }
  2491. if ( (AzGlObjectAllDirtyBits[GenericObject->ObjectType] & AZ_DIRTY_GENERATE_AUDITS) == 0 ) {
  2492. AzPrint(( AZD_INVPARM, "ObCommonGetProperty: Object has no generate-audits data\n" ));
  2493. WinStatus = ERROR_INVALID_PARAMETER;
  2494. goto Cleanup;
  2495. }
  2496. *PropertyValue = AzpGetUlongProperty((GenericObject->IsGeneratingAudits) ? 1 : 0);
  2497. if ( *PropertyValue == NULL ) {
  2498. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  2499. goto Cleanup;
  2500. }
  2501. break;
  2502. //
  2503. // return apply SACL LONG
  2504. //
  2505. case AZ_PROP_APPLY_STORE_SACL:
  2506. //
  2507. // Ensure the caller has privilege
  2508. //
  2509. if ( IsNormalFlags(Flags) ) {
  2510. if ( !GenericObject->AzStoreObject->HasSecurityPrivilege ) {
  2511. WinStatus = ERROR_ACCESS_DENIED;
  2512. goto Cleanup;
  2513. }
  2514. }
  2515. if ( (AzGlObjectAllDirtyBits[GenericObject->ObjectType] & AZ_DIRTY_APPLY_STORE_SACL) == 0 ) {
  2516. AzPrint(( AZD_INVPARM, "ObCommonGetProperty: Object has no apply-store-sacl data\n" ));
  2517. WinStatus = ERROR_INVALID_PARAMETER;
  2518. goto Cleanup;
  2519. }
  2520. if ( !(GenericObject->IsSACLSupported) ) {
  2521. AzPrint(( AZD_INVPARM, "ObCommonGetProperty:"
  2522. "Object has no apply-store-sacl data\n" ));
  2523. WinStatus = ERROR_NOT_SUPPORTED;
  2524. goto Cleanup;
  2525. }
  2526. *PropertyValue = AzpGetUlongProperty( (GenericObject->ApplySacl) ? 1 : 0 );
  2527. if ( *PropertyValue == NULL ) {
  2528. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  2529. goto Cleanup;
  2530. }
  2531. break;
  2532. //
  2533. // Return object write permission to the caller
  2534. //
  2535. case AZ_PROP_WRITABLE:
  2536. *PropertyValue = AzpGetUlongProperty( (GenericObject->IsWritable) ? 1 : 0 );
  2537. if ( *PropertyValue == NULL ) {
  2538. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  2539. goto Cleanup;
  2540. }
  2541. break;
  2542. //
  2543. // Return object child create permissions to the caller
  2544. //
  2545. case AZ_PROP_CHILD_CREATE:
  2546. *PropertyValue = AzpGetUlongProperty( (GenericObject->CanCreateChildren) ? 1 : 0 );
  2547. if ( *PropertyValue == NULL ) {
  2548. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  2549. goto Cleanup;
  2550. }
  2551. break;
  2552. //
  2553. // Return the list of policy admins/readers
  2554. //
  2555. case AZ_PROP_POLICY_ADMINS:
  2556. case AZ_PROP_POLICY_READERS:
  2557. WinStatus = CHECK_ACL_SUPPORT(GenericObject);
  2558. if ( WinStatus != NO_ERROR ) {
  2559. goto Cleanup;
  2560. }
  2561. if ( PropertyId == AZ_PROP_POLICY_ADMINS ) {
  2562. *PropertyValue = ObGetPropertyItems( &GenericObject->PolicyAdmins );
  2563. } else {
  2564. *PropertyValue = ObGetPropertyItems( &GenericObject->PolicyReaders );
  2565. }
  2566. if ( *PropertyValue == NULL ) {
  2567. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  2568. goto Cleanup;
  2569. }
  2570. break;
  2571. //
  2572. // Return the list of delegated policy users
  2573. //
  2574. case AZ_PROP_DELEGATED_POLICY_USERS:
  2575. WinStatus = CHECK_DELEGATION_SUPPORT(GenericObject);
  2576. if ( WinStatus != NO_ERROR ) {
  2577. goto Cleanup;
  2578. }
  2579. *PropertyValue = ObGetPropertyItems( &GenericObject->DelegatedPolicyUsers );
  2580. if ( *PropertyValue == NULL ) {
  2581. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  2582. goto Cleanup;
  2583. }
  2584. break;
  2585. default:
  2586. ASSERT ( PropertyId >= AZ_PROP_FIRST_SPECIFIC );
  2587. //
  2588. // Call the routine to do object type specific querying
  2589. //
  2590. if ( ObjectGetPropertyRoutine[GenericObject->ObjectType] != NULL ) {
  2591. WinStatus = ObjectGetPropertyRoutine[GenericObject->ObjectType](
  2592. GenericObject,
  2593. Flags,
  2594. PropertyId,
  2595. PropertyValue );
  2596. if ( WinStatus != NO_ERROR ) {
  2597. goto Cleanup;
  2598. }
  2599. } else {
  2600. AzPrint(( AZD_INVPARM, "ObCommonGetProperty: No get property routine.\n", GenericObject->ObjectType, PropertyId ));
  2601. WinStatus = ERROR_INVALID_PARAMETER;
  2602. goto Cleanup;
  2603. }
  2604. break;
  2605. }
  2606. //
  2607. // Return the value to the caller
  2608. //
  2609. WinStatus = NO_ERROR;
  2610. //
  2611. // Free locally used resources
  2612. //
  2613. Cleanup:
  2614. return WinStatus;
  2615. }
  2616. DWORD
  2617. ObSetProperty(
  2618. IN PGENERIC_OBJECT GenericObject,
  2619. IN ULONG Flags,
  2620. IN ULONG PropertyId,
  2621. IN PVOID PropertyValue
  2622. )
  2623. /*++
  2624. Routine Description:
  2625. Sets the specified property for a generic object.
  2626. Arguments:
  2627. GenericObject - Specifies a handle to the object to modify.
  2628. Flags - Specifies flags controlling to operation of the routine
  2629. AZP_FLAGS_SETTING_TO_DEFAULT - Property is being set to default value
  2630. AZP_FLAGS_PERSIST_* - Call is from the persistence provider
  2631. PropertyId - Specifies which property to return.
  2632. PropertyValue - Specifies a pointer to the property.
  2633. The specified value and type depends in PropertyId. The valid values are:
  2634. AZ_PROP_NAME LPWSTR - Object name of the object
  2635. AZ_PROP_DESCRIPTION LPWSTR - Description of the object
  2636. AZ_PROP_APPLICATION_DATA LPWSTR - Opaque data stored by an application
  2637. AZ_PROP_GENERATE_AUDITS PULONG - whether the audit flag is set
  2638. AZ_PROP_APPLY_STORE_SACL PLONG - whether the sacl flag is set
  2639. Any object specific properties.
  2640. Return Value:
  2641. NO_ERROR - The operation was successful
  2642. ERROR_INVALID_PARAMETER - PropertyId isn't valid
  2643. --*/
  2644. {
  2645. DWORD WinStatus;
  2646. AZP_STRING CapturedString;
  2647. PGENERIC_OBJECT_NAME NewObjectName = NULL;
  2648. BOOL bHasChanged = TRUE;
  2649. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  2650. AzpInitString( &CapturedString, NULL );
  2651. if ( IsNormalFlags(Flags) &&
  2652. ((Flags & AZP_FLAGS_SETTING_TO_DEFAULT) == 0) &&
  2653. GenericObject->IsWritable == 0 &&
  2654. GenericObject->ObjectType != OBJECT_TYPE_CLIENT_CONTEXT)
  2655. {
  2656. WinStatus = ERROR_ACCESS_DENIED;
  2657. goto Cleanup;
  2658. }
  2659. //
  2660. // Set any common attribute
  2661. //
  2662. // Set the object name
  2663. //
  2664. switch ( PropertyId ) {
  2665. case AZ_PROP_NAME:
  2666. BEGIN_SETPROP( &WinStatus, GenericObject, Flags, AZ_DIRTY_NAME ) {
  2667. PGENERIC_OBJECT ChildGenericObject;
  2668. PGENERIC_OBJECT_LIST GenericObjectList;
  2669. //
  2670. // Capture the input string
  2671. //
  2672. WinStatus = AzpCaptureString( &CapturedString,
  2673. (LPWSTR) PropertyValue,
  2674. CHECK_STRING_LENGTH( Flags, MaxObjectNameLength[GenericObject->ObjectType]),
  2675. FALSE ); // NULL not ok
  2676. if ( WinStatus != NO_ERROR ) {
  2677. goto Cleanup;
  2678. }
  2679. //
  2680. // Validate the syntax of the name
  2681. //
  2682. WinStatus = AzpValidateName( &CapturedString, GenericObject->ObjectType );
  2683. if ( WinStatus != NO_ERROR ) {
  2684. goto Cleanup;
  2685. }
  2686. //
  2687. // Check to see if the name conflicts with an existing name
  2688. //
  2689. // Ensure the new name doesn't exist in the current list
  2690. // Deleted objects conflict since they consume our entry in the AVL tree.
  2691. // The caller should close the deleted object.
  2692. //
  2693. WinStatus = ObReferenceObjectByName( GenericObject->ParentGenericObjectHead,
  2694. &CapturedString,
  2695. AZP_FLAGS_ALLOW_DELETED_OBJECTS,
  2696. &ChildGenericObject );
  2697. if ( WinStatus == NO_ERROR ) {
  2698. ObDereferenceObject( ChildGenericObject );
  2699. WinStatus = ERROR_ALREADY_EXISTS;
  2700. goto Cleanup;
  2701. }
  2702. //
  2703. // Ensure the name doesn't conflict with the names of other objects that share the namespace.
  2704. //
  2705. if ( ObjectNameConflictRoutine[GenericObject->ObjectType] != NULL ) {
  2706. WinStatus = ObjectNameConflictRoutine[GenericObject->ObjectType](
  2707. ParentOfChild(GenericObject),
  2708. &CapturedString );
  2709. if ( WinStatus != NO_ERROR ) {
  2710. goto Cleanup;
  2711. }
  2712. }
  2713. //
  2714. // Insert the new name into the AVL tree
  2715. //
  2716. NewObjectName = ObInsertNameIntoAvlTree(
  2717. GenericObject->ParentGenericObjectHead,
  2718. &CapturedString );
  2719. if ( NewObjectName == NULL ) {
  2720. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  2721. goto Cleanup;
  2722. }
  2723. NewObjectName->GenericObject = GenericObject;
  2724. //
  2725. // Update all links to this object to be links to the new name
  2726. // Forward links are maintained in order sorted by name
  2727. //
  2728. // Walk all of the GenericObjectLists rooted on by this object
  2729. //
  2730. for ( GenericObjectList = GenericObject->GenericObjectLists;
  2731. GenericObjectList != NULL;
  2732. GenericObjectList = GenericObjectList->NextGenericObjectList ) {
  2733. ULONG Index;
  2734. //
  2735. // Skip forward links since they represent linke 'from' this object
  2736. //
  2737. if ( !GenericObjectList->IsBackLink ) {
  2738. continue;
  2739. }
  2740. //
  2741. // Follow each backlink to the forward link back to us
  2742. //
  2743. for ( Index=0; Index<GenericObjectList->GenericObjects.UsedCount; Index++ ) {
  2744. PGENERIC_OBJECT OtherGenericObject;
  2745. PGENERIC_OBJECT_LIST OtherGenericObjectList;
  2746. ULONG OtherIndex;
  2747. //
  2748. // Grab a pointer to the object the points to us
  2749. //
  2750. OtherGenericObject = (PGENERIC_OBJECT)
  2751. (GenericObjectList->GenericObjects.Array[Index]);
  2752. //
  2753. // Get a pointer to the object list that our entry is in
  2754. //
  2755. OtherGenericObjectList = ObGetObjectListPtr( OtherGenericObject,
  2756. GenericObject->ObjectType,
  2757. GenericObjectList );
  2758. ASSERT( OtherGenericObjectList != NULL );
  2759. ASSERT( !OtherGenericObjectList->IsBackLink );
  2760. //
  2761. // Lookup our old name in the object list that our entry is in.
  2762. // It has to be there since we have a back link.
  2763. //
  2764. WinStatus = ObLookupPropertyItem( OtherGenericObjectList,
  2765. &GenericObject->ObjectName->ObjectName,
  2766. &OtherIndex );
  2767. ASSERT( WinStatus == ERROR_ALREADY_EXISTS );
  2768. //
  2769. // Remove the old entry
  2770. //
  2771. AzpRemovePtrByIndex( &OtherGenericObjectList->GenericObjects, OtherIndex );
  2772. //
  2773. // Lookup our new name in the object list that our entry is in.
  2774. // It can't be there since we already did conflict detection.
  2775. //
  2776. WinStatus = ObLookupPropertyItem( OtherGenericObjectList,
  2777. &CapturedString,
  2778. &OtherIndex );
  2779. ASSERT( WinStatus == ERROR_NOT_FOUND );
  2780. //
  2781. // Add the new entry
  2782. // This can't fail because of no memory since we just freed up a slot
  2783. //
  2784. WinStatus = AzpAddPtr(
  2785. &OtherGenericObjectList->GenericObjects,
  2786. GenericObject,
  2787. OtherIndex );
  2788. ASSERT( WinStatus == NO_ERROR );
  2789. }
  2790. }
  2791. //
  2792. // Remove the old name from the AVL tree
  2793. //
  2794. if (!RtlDeleteElementGenericTable (
  2795. &GenericObject->ParentGenericObjectHead->AvlTree,
  2796. GenericObject->ObjectName ) ) {
  2797. GenericObject->ObjectName->GenericObject = NULL;
  2798. ASSERT( FALSE );
  2799. }
  2800. GenericObject->ObjectName = NewObjectName;
  2801. WinStatus = NO_ERROR;
  2802. } END_SETPROP(bHasChanged);
  2803. break;
  2804. //
  2805. // Set object description
  2806. //
  2807. case AZ_PROP_DESCRIPTION:
  2808. BEGIN_SETPROP( &WinStatus, GenericObject, Flags, AZ_DIRTY_DESCRIPTION ) {
  2809. //
  2810. // Capture the input string
  2811. //
  2812. WinStatus = AzpCaptureString( &CapturedString,
  2813. (LPWSTR) PropertyValue,
  2814. CHECK_STRING_LENGTH( Flags, AZ_MAX_DESCRIPTION_LENGTH),
  2815. TRUE ); // NULL is OK
  2816. if ( WinStatus != NO_ERROR ) {
  2817. goto Cleanup;
  2818. }
  2819. //
  2820. // Swap the old/new names
  2821. //
  2822. AzpSwapStrings( &CapturedString, &GenericObject->Description );
  2823. WinStatus = NO_ERROR;
  2824. } END_SETPROP(bHasChanged);
  2825. break;
  2826. //
  2827. // Set application data
  2828. //
  2829. case AZ_PROP_APPLICATION_DATA:
  2830. BEGIN_SETPROP( &WinStatus, GenericObject, Flags, AZ_DIRTY_APPLICATION_DATA ) {
  2831. //
  2832. // Capture the input string
  2833. //
  2834. WinStatus = AzpCaptureString( &CapturedString,
  2835. (LPWSTR) PropertyValue,
  2836. CHECK_STRING_LENGTH(
  2837. Flags,
  2838. AZ_MAX_APPLICATION_DATA_LENGTH),
  2839. TRUE ); // NULL is OK
  2840. if ( WinStatus != NO_ERROR ) {
  2841. goto Cleanup;
  2842. }
  2843. //
  2844. // Swap the old/new names
  2845. //
  2846. AzpSwapStrings( &CapturedString, &GenericObject->ApplicationData );
  2847. WinStatus = NO_ERROR;
  2848. } END_SETPROP(bHasChanged);
  2849. break;
  2850. //
  2851. // to set audit, check pirvilege 1st. If previously known that the user
  2852. // does not have the privilege, no need to make the call into the provider
  2853. //
  2854. case AZ_PROP_GENERATE_AUDITS:
  2855. BEGIN_SETPROP( &WinStatus, GenericObject, Flags, AZ_DIRTY_GENERATE_AUDITS ) {
  2856. //
  2857. // Do parameter validity checking
  2858. //
  2859. WinStatus = AzpCaptureLong( PropertyValue, &GenericObject->IsGeneratingAudits);
  2860. if ( WinStatus != NO_ERROR ) {
  2861. goto Cleanup;
  2862. }
  2863. } END_SETPROP(bHasChanged);
  2864. break;
  2865. //
  2866. // Set whether or not a SACL should be stored
  2867. //
  2868. case AZ_PROP_APPLY_STORE_SACL:
  2869. BEGIN_SETPROP( &WinStatus, GenericObject, Flags, AZ_DIRTY_APPLY_STORE_SACL ) {
  2870. //
  2871. // Do parameter validity checking
  2872. //
  2873. BEGIN_VALIDITY_CHECKING( Flags ) {
  2874. if ( !(GenericObject->IsSACLSupported) ) {
  2875. AzPrint(( AZD_INVPARM, "ObCommonGetProperty:"
  2876. "Object has no apply-store-sacl data\n" ));
  2877. WinStatus = ERROR_NOT_SUPPORTED;
  2878. goto Cleanup;
  2879. }
  2880. //
  2881. // Ensure the caller has privilege
  2882. //
  2883. if ( !GenericObject->AzStoreObject->HasSecurityPrivilege ) {
  2884. WinStatus = ERROR_ACCESS_DENIED;
  2885. goto Cleanup;
  2886. }
  2887. } END_VALIDITY_CHECKING;
  2888. WinStatus = AzpCaptureLong( PropertyValue, &GenericObject->ApplySacl);
  2889. if ( WinStatus != NO_ERROR ) {
  2890. goto Cleanup;
  2891. }
  2892. } END_SETPROP(bHasChanged);
  2893. break;
  2894. default:
  2895. ASSERT ( PropertyId >= AZ_PROP_FIRST_SPECIFIC );
  2896. //
  2897. // Call the routine to do object type specific set property
  2898. //
  2899. if ( ObjectSetPropertyRoutine[GenericObject->ObjectType] != NULL ) {
  2900. WinStatus = ObjectSetPropertyRoutine[GenericObject->ObjectType](
  2901. GenericObject,
  2902. Flags,
  2903. PropertyId,
  2904. PropertyValue );
  2905. if ( WinStatus != NO_ERROR ) {
  2906. goto Cleanup;
  2907. }
  2908. } else {
  2909. AzPrint(( AZD_INVPARM, "ObSetProperty: no set property routine: %ld %ld\n", GenericObject->ObjectType, PropertyId ));
  2910. WinStatus = ERROR_INVALID_PARAMETER;
  2911. goto Cleanup;
  2912. }
  2913. break;
  2914. }
  2915. //
  2916. // Free locally used resources
  2917. //
  2918. Cleanup:
  2919. AzpFreeString( &CapturedString );
  2920. //
  2921. // Mark that the operation caches need flushing
  2922. // ... any change to the object cache invalidates the cache
  2923. //
  2924. // ??? This is really sub-optimal. We really want to know if the attribute has
  2925. // *changed*. Otherwise, calling AzUpdateCache will increment the serial number.
  2926. // It should. But only if the attribute becomes different.
  2927. //
  2928. if ( WinStatus == NO_ERROR ) {
  2929. GenericObject->AzStoreObject->OpCacheSerialNumber ++;
  2930. AzPrint(( AZD_ACCESS_MORE, "ObSetProperty: OpCacheSerialNumber set to %ld\n",
  2931. GenericObject->AzStoreObject->OpCacheSerialNumber ));
  2932. }
  2933. return WinStatus;
  2934. }
  2935. PAZP_DEFAULT_VALUE
  2936. ObDirtyBitToDefaultValue(
  2937. IN ULONG ObjectType,
  2938. IN ULONG DirtyBit
  2939. )
  2940. /*++
  2941. Routine Description:
  2942. This routine finds the default value structure for a particular dirty bit.
  2943. Arguments:
  2944. ObjectType - Specifies the object type of the object the DirtyBits apply to
  2945. DirtyBits - Specifies the dirty bit to lookup
  2946. Return Value:
  2947. NULL if there is no translation
  2948. --*/
  2949. {
  2950. PAZP_DEFAULT_VALUE DefaultValues;
  2951. //
  2952. // Grab the array for this particular object type
  2953. //
  2954. DefaultValues = ObjectDefaultValuesArray[ObjectType];
  2955. if ( DefaultValues == NULL ) {
  2956. return NULL;
  2957. }
  2958. //
  2959. // Loop through the list finding the correct entry
  2960. //
  2961. while ( DefaultValues->DirtyBit != 0 ) {
  2962. if ( DefaultValues->DirtyBit == DirtyBit ) {
  2963. return DefaultValues;
  2964. }
  2965. DefaultValues++;
  2966. }
  2967. return NULL;
  2968. }
  2969. DWORD
  2970. ObSetPropertyToDefault(
  2971. IN PGENERIC_OBJECT GenericObject,
  2972. IN ULONG DirtyBits
  2973. )
  2974. /*++
  2975. Routine Description:
  2976. Sets the properties corresponding to "DirtyBits" to their default value.
  2977. This routine only sets attributes that are scalars to their default value.
  2978. The caller is responsible for setting attributes that are "lists".
  2979. Arguments:
  2980. GenericObject - Specifies a handle to the object to modify.
  2981. This "handle" has been passed from the application and needs to be verified.
  2982. DirtyBits - Specifies a bit mask of attributes which are to be set to their default value.
  2983. The caller is allowed to pass in bits that don't apply to this object.
  2984. Such bits are silently ignored.
  2985. Return Value:
  2986. Status of the operation
  2987. --*/
  2988. {
  2989. DWORD WinStatus = NO_ERROR;
  2990. //
  2991. // Silently ignore bits that don't apply to this object
  2992. //
  2993. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  2994. DirtyBits &= ObjectAllScalarDirtyBits[GenericObject->ObjectType];
  2995. //
  2996. // Handle any common attributes
  2997. // Handle the object name
  2998. //
  2999. if ( DirtyBits & AZ_DIRTY_NAME ) {
  3000. DirtyBits &= ~AZ_DIRTY_NAME;
  3001. }
  3002. //
  3003. // Handle object description
  3004. //
  3005. if ( DirtyBits & AZ_DIRTY_DESCRIPTION ) {
  3006. //
  3007. // Free the old string
  3008. //
  3009. AzpFreeString( &GenericObject->Description );
  3010. DirtyBits &= ~AZ_DIRTY_DESCRIPTION;
  3011. }
  3012. //
  3013. // Handle object application data
  3014. //
  3015. if ( DirtyBits & AZ_DIRTY_APPLICATION_DATA ) {
  3016. //
  3017. // Free the old string
  3018. //
  3019. AzpFreeString( &GenericObject->ApplicationData );
  3020. DirtyBits &= ~AZ_DIRTY_APPLICATION_DATA;
  3021. }
  3022. //
  3023. // Handle ApplyStoreSacl
  3024. //
  3025. if ( DirtyBits & AZ_DIRTY_APPLY_STORE_SACL ) {
  3026. //
  3027. // Only define the bit for container objects
  3028. //
  3029. if ( IsContainerObject( GenericObject->ObjectType ) ) {
  3030. if ( GenericObject->ObjectType == OBJECT_TYPE_AZAUTHSTORE ) {
  3031. GenericObject->ApplySacl = GenericObject->AzStoreObject->HasSecurityPrivilege;
  3032. } else {
  3033. GenericObject->ApplySacl = FALSE;
  3034. }
  3035. }
  3036. DirtyBits &= ~AZ_DIRTY_APPLY_STORE_SACL;
  3037. }
  3038. //
  3039. // Handle IsGeneratingAudits
  3040. //
  3041. if ( DirtyBits & AZ_DIRTY_GENERATE_AUDITS ) {
  3042. //
  3043. // Only define the bit at the authorization store and application level
  3044. //
  3045. if ( GenericObject->ObjectType == OBJECT_TYPE_AZAUTHSTORE ||
  3046. GenericObject->ObjectType == OBJECT_TYPE_APPLICATION ) {
  3047. GenericObject->IsGeneratingAudits = TRUE;
  3048. }
  3049. DirtyBits &= ~AZ_DIRTY_GENERATE_AUDITS;
  3050. }
  3051. //
  3052. // Loop handling one bit at a time
  3053. //
  3054. while ( DirtyBits != 0 ) {
  3055. ULONG DirtyBit;
  3056. PAZP_DEFAULT_VALUE DefaultValue;
  3057. DWORD TempStatus;
  3058. ASSERT( (DirtyBits & ~AZ_DIRTY_OBJECT_SPECIFIC) == 0 );
  3059. //
  3060. // Grab the next bit
  3061. //
  3062. DirtyBit = DirtyBits & ~(DirtyBits & (DirtyBits-1));
  3063. //
  3064. // Lookup the default value
  3065. //
  3066. DefaultValue = ObDirtyBitToDefaultValue(
  3067. GenericObject->ObjectType,
  3068. DirtyBit );
  3069. ASSERT( DefaultValue != NULL );
  3070. //
  3071. // Set the property to its default value
  3072. // We should ignore bits where the default value isn't in
  3073. // the default table
  3074. //
  3075. if ( DefaultValue != NULL ) {
  3076. TempStatus = ObSetProperty( GenericObject,
  3077. AZP_FLAGS_SETTING_TO_DEFAULT,
  3078. DefaultValue->PropertyId,
  3079. DefaultValue->DefaultValue );
  3080. if ( TempStatus != NO_ERROR ) {
  3081. WinStatus = TempStatus;
  3082. }
  3083. }
  3084. // Turn off the processed bit
  3085. DirtyBits &= ~DirtyBit;
  3086. }
  3087. return WinStatus;
  3088. }
  3089. DWORD
  3090. ObCommonSetProperty(
  3091. IN PGENERIC_OBJECT GenericObject,
  3092. IN ULONG PropertyId,
  3093. IN DWORD Reserved,
  3094. IN PVOID PropertyValue
  3095. )
  3096. /*++
  3097. Routine Description:
  3098. Sets the specified property for a generic object.
  3099. Arguments:
  3100. GenericObject - Specifies a handle to the object to modify.
  3101. This "handle" has been passed from the application and needs to be verified.
  3102. PropertyId - Specifies which property to return.
  3103. Reserved - Reserved. Must by zero.
  3104. PropertyValue - Specifies a pointer to the property.
  3105. The specified value and type depends in PropertyId. The valid values are:
  3106. AZ_PROP_NAME LPWSTR - Object name of the object
  3107. AZ_PROP_DESCRIPTION LPWSTR - Description of the object
  3108. AZ_PROP_APPLICATION_DATA LPWSTR - Opaque data stored by an application
  3109. Any object specific properties.
  3110. Return Value:
  3111. NO_ERROR - The operation was successful
  3112. ERROR_INVALID_PARAMETER - PropertyId isn't valid
  3113. --*/
  3114. {
  3115. DWORD WinStatus;
  3116. ULONG ObjectType;
  3117. PGENERIC_OBJECT ReferencedGenericObject = NULL;
  3118. //
  3119. // Grab the global lock
  3120. //
  3121. AzpLockResourceExclusive( &AzGlResource );
  3122. //
  3123. // Validate the input parameters
  3124. //
  3125. if ( Reserved != 0 ) {
  3126. AzPrint(( AZD_INVPARM, "ObCommonSetProperty: Reserved != 0\n" ));
  3127. WinStatus = ERROR_INVALID_PARAMETER;
  3128. goto Cleanup;
  3129. }
  3130. //
  3131. // Determine the type of the object
  3132. //
  3133. WinStatus = ObGetHandleType( GenericObject,
  3134. FALSE, // Don't allow deleted objects
  3135. &ObjectType );
  3136. if ( WinStatus != NO_ERROR ) {
  3137. goto Cleanup;
  3138. }
  3139. //
  3140. // Validate the passed in handle
  3141. //
  3142. WinStatus = ObReferenceObjectByHandle( GenericObject,
  3143. FALSE, // Don't allow deleted objects
  3144. TRUE, // Refresh the cache
  3145. ObjectType );
  3146. if ( WinStatus != NO_ERROR ) {
  3147. goto Cleanup;
  3148. }
  3149. ReferencedGenericObject = GenericObject;
  3150. WinStatus = ObSetProperty(
  3151. GenericObject,
  3152. 0, // No flags
  3153. PropertyId,
  3154. PropertyValue);
  3155. if ( WinStatus != NO_ERROR ) {
  3156. goto Cleanup;
  3157. }
  3158. //
  3159. // Ensure the object was marked as needing to be written
  3160. //
  3161. ASSERT( (GenericObject->DirtyBits & ~AzGlObjectAllDirtyBits[ObjectType]) == 0);
  3162. //
  3163. // Return the value to the caller
  3164. //
  3165. WinStatus = NO_ERROR;
  3166. //
  3167. // Free locally used resources
  3168. //
  3169. Cleanup:
  3170. if ( ReferencedGenericObject != NULL ) {
  3171. ObDereferenceObject( ReferencedGenericObject );
  3172. }
  3173. //
  3174. // Drop the global lock
  3175. //
  3176. AzpUnlockResource( &AzGlResource );
  3177. return WinStatus;
  3178. }
  3179. VOID
  3180. ObMarkObjectDeletedEx(
  3181. IN PGENERIC_OBJECT GenericObject,
  3182. IN BOOLEAN DoingChild
  3183. )
  3184. /*++
  3185. Routine Description
  3186. Mark this object and all child objects as deleted.
  3187. On entry, AzGlResource must be locked exclusive.
  3188. Arguments
  3189. GenericObject - Specifies the object to mark
  3190. DoingChild - True if this is a recursive call
  3191. Return Value
  3192. None
  3193. --*/
  3194. {
  3195. PGENERIC_OBJECT_HEAD ChildGenericObjectHead;
  3196. PGENERIC_OBJECT ChildGenericObject;
  3197. PLIST_ENTRY ListEntry;
  3198. //
  3199. // Initialization
  3200. //
  3201. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  3202. //
  3203. // Only mark the object if it is not already marked
  3204. //
  3205. if ( (GenericObject->Flags & GENOBJ_FLAGS_DELETED) == 0 ) {
  3206. //
  3207. // Mark the entry as deleted
  3208. //
  3209. GenericObject->Flags |= GENOBJ_FLAGS_DELETED;
  3210. //
  3211. // Delete all children of this object
  3212. //
  3213. // Loop for each type of child object
  3214. //
  3215. for ( ChildGenericObjectHead = GenericObject->ChildGenericObjectHead;
  3216. ChildGenericObjectHead != NULL;
  3217. ChildGenericObjectHead = ChildGenericObjectHead->SiblingGenericObjectHead ) {
  3218. //
  3219. // Loop for each child object
  3220. //
  3221. for ( ListEntry = ChildGenericObjectHead->Head.Flink ;
  3222. ListEntry != &ChildGenericObjectHead->Head ;
  3223. ListEntry = ListEntry->Flink) {
  3224. ChildGenericObject = CONTAINING_RECORD( ListEntry,
  3225. GENERIC_OBJECT,
  3226. Next );
  3227. //
  3228. // Mark that object
  3229. //
  3230. ObMarkObjectDeletedEx( ChildGenericObject, TRUE );
  3231. }
  3232. }
  3233. //
  3234. // Delete all references to/from this object
  3235. //
  3236. ObRemoveObjectListLinks( GenericObject );
  3237. //
  3238. // The object actually being deleted is delinked from its parent.
  3239. // That ensures it goes away when the last reference goes away
  3240. //
  3241. if ( !DoingChild ) {
  3242. ObDereferenceObject( GenericObject );
  3243. }
  3244. }
  3245. }
  3246. VOID
  3247. ObMarkObjectDeleted(
  3248. IN PGENERIC_OBJECT GenericObject
  3249. )
  3250. /*++
  3251. Routine Description
  3252. Mark this object and all child objects as deleted.
  3253. On entry, AzGlResource must be locked exclusive.
  3254. Arguments
  3255. GenericObject - Specifies the object to mark
  3256. Return Value
  3257. None
  3258. --*/
  3259. {
  3260. ObMarkObjectDeletedEx( GenericObject, FALSE );
  3261. }
  3262. DWORD
  3263. ObCommonDeleteObject(
  3264. IN PGENERIC_OBJECT ParentGenericObject,
  3265. IN ULONG ParentObjectType,
  3266. IN PGENERIC_OBJECT_HEAD GenericChildHead,
  3267. IN ULONG ChildObjectType,
  3268. IN LPCWSTR ChildObjectName,
  3269. IN DWORD Reserved
  3270. )
  3271. /*++
  3272. Routine Description:
  3273. This routine deletes a child object from the scope of the specified parent object.
  3274. Arguments:
  3275. ParentGenericObject - Specifies a handle to the parent object to delete the child
  3276. object from. This "handle" has been passed from the application and needs to
  3277. be verified.
  3278. ParentObjectType - Specifies the object type ParentGenericObject.
  3279. GenericChildHead - Specifies a pointer to the head of the list of children of
  3280. ParentGenericObject. This is a computed pointer and is considered untrustworthy
  3281. until ParentGenericObject has been verified.
  3282. ChildObjectType - Specifies the object type RetChildGenericObject.
  3283. ChildObjectName - Specifies the name of the child object.
  3284. This name is passed from the application and needs to be verified.
  3285. Reserved - Reserved. Must by zero.
  3286. Return Value:
  3287. NO_ERROR - The operation was successful
  3288. ERROR_NOT_FOUND - An object by that name cannot be found
  3289. --*/
  3290. {
  3291. DWORD WinStatus;
  3292. PGENERIC_OBJECT ReferencedParentObject = NULL;
  3293. PGENERIC_OBJECT ChildGenericObject = NULL;
  3294. AZP_STRING ChildObjectNameString;
  3295. //
  3296. // Initialization
  3297. //
  3298. AzpInitString( &ChildObjectNameString, NULL );
  3299. ASSERT( ParentObjectType != OBJECT_TYPE_ROOT );
  3300. ASSERT( ChildObjectType != OBJECT_TYPE_AZAUTHSTORE );
  3301. //
  3302. // Grab the global lock
  3303. //
  3304. AzpLockResourceExclusive( &AzGlResource );
  3305. //
  3306. // Validate the input parameters
  3307. //
  3308. if ( Reserved != 0 ) {
  3309. AzPrint(( AZD_INVPARM, "ObCommonDeleteObject: Reserved != 0\n" ));
  3310. WinStatus = ERROR_INVALID_PARAMETER;
  3311. goto Cleanup;
  3312. }
  3313. //
  3314. // Validate the passed in handle
  3315. //
  3316. WinStatus = ObReferenceObjectByHandle( ParentGenericObject,
  3317. FALSE, // Don't allow deleted objects
  3318. FALSE, // No need to refresh the cache on a delete
  3319. ParentObjectType );
  3320. if ( WinStatus != NO_ERROR ) {
  3321. goto Cleanup;
  3322. }
  3323. ReferencedParentObject = ParentGenericObject;
  3324. //
  3325. // If the parent has not been loaded, then load the parent first
  3326. //
  3327. if ( !(ReferencedParentObject->AreChildrenLoaded) ) {
  3328. WinStatus = AzPersistUpdateChildrenCache(
  3329. ReferencedParentObject
  3330. );
  3331. if ( WinStatus != NO_ERROR ) {
  3332. goto Cleanup;
  3333. }
  3334. }
  3335. //
  3336. // Capture the object name string from the caller
  3337. //
  3338. WinStatus = AzpCaptureString( &ChildObjectNameString,
  3339. ChildObjectName,
  3340. MaxObjectNameLength[ChildObjectType],
  3341. FALSE ); // NULL names not OK
  3342. if ( WinStatus != NO_ERROR ) {
  3343. goto Cleanup;
  3344. }
  3345. //
  3346. // Find the object to delete.
  3347. //
  3348. WinStatus = ObReferenceObjectByName( GenericChildHead,
  3349. &ChildObjectNameString,
  3350. 0, // No special flags
  3351. &ChildGenericObject );
  3352. if ( WinStatus != NO_ERROR ) {
  3353. goto Cleanup;
  3354. }
  3355. //
  3356. // Actually, delete the object
  3357. //
  3358. WinStatus = AzPersistSubmit( ChildGenericObject, TRUE );
  3359. if ( WinStatus != NO_ERROR ) {
  3360. goto Cleanup;
  3361. }
  3362. //
  3363. // Mark the entry (and its child objects) as deleted
  3364. // We do this since other threads may have references to the objects.
  3365. // We want to ensure those threads know the objects are deleted.
  3366. //
  3367. ObMarkObjectDeleted( ChildGenericObject );
  3368. //
  3369. // Return to the caller
  3370. //
  3371. WinStatus = NO_ERROR;
  3372. //
  3373. // Free locally used resources
  3374. //
  3375. Cleanup:
  3376. if ( ReferencedParentObject != NULL ) {
  3377. ObDereferenceObject( ReferencedParentObject );
  3378. }
  3379. if ( ChildGenericObject != NULL ) {
  3380. ObDereferenceObject( ChildGenericObject );
  3381. }
  3382. AzpFreeString( &ChildObjectNameString );
  3383. //
  3384. // Drop the global lock
  3385. //
  3386. AzpUnlockResource( &AzGlResource );
  3387. return WinStatus;
  3388. }
  3389. LONG
  3390. AzpCompareDeltaEntries(
  3391. const void *DeltaEntry1,
  3392. const void *DeltaEntry2
  3393. )
  3394. /*++
  3395. Routine description:
  3396. Compare two AZP_DELTA_ENTRYs
  3397. Arguments:
  3398. DeltaEntry1 - First entry to compare
  3399. DeltaEntry2 - Second entry to compare
  3400. Returns:
  3401. CSTR_LESS_THAN: Entry 1 is less than entry 2
  3402. CSTR_EQUAL: Entry 1 is equal to entry 2
  3403. CSTR_GREATER_THAN: Entry 1 is greater than entry 2
  3404. --*/
  3405. {
  3406. LONG Result;
  3407. PAZP_DELTA_ENTRY Delta1 = (PAZP_DELTA_ENTRY)DeltaEntry1;
  3408. PAZP_DELTA_ENTRY Delta2 = (PAZP_DELTA_ENTRY)DeltaEntry2;
  3409. //
  3410. // If these entries are SIDs,
  3411. // compare them
  3412. //
  3413. if ( Delta1->DeltaFlags & AZP_DELTA_SID ) {
  3414. ASSERT( Delta2->DeltaFlags & AZP_DELTA_SID );
  3415. Result = AzpCompareSid( Delta1->Sid, Delta2->Sid );
  3416. //
  3417. // If these entries are GUIDs,
  3418. // compare them
  3419. //
  3420. } else {
  3421. GUID *Guid1 = &Delta1->Guid;
  3422. GUID *Guid2 = &Delta2->Guid;
  3423. ULONG i;
  3424. ASSERT( (Delta2->DeltaFlags & AZP_DELTA_SID) == 0 );
  3425. //
  3426. // Compare the individual bytes
  3427. //
  3428. Result = CSTR_EQUAL;
  3429. for ( i = 0; i < (sizeof(GUID)/4); i++ ) {
  3430. const ULONG& b1 = ((PULONG)(Guid1))[i];
  3431. const ULONG& b2 = ((PULONG)(Guid2))[i];
  3432. if ( b1 == b2 ) {
  3433. continue;
  3434. } else if ( b1 < b2 ) {
  3435. Result = CSTR_LESS_THAN;
  3436. } else {
  3437. Result = CSTR_GREATER_THAN;
  3438. }
  3439. break;
  3440. }
  3441. }
  3442. return Result;
  3443. }
  3444. BOOLEAN
  3445. ObLookupDelta(
  3446. IN ULONG DeltaFlags,
  3447. IN GUID *Guid,
  3448. IN PAZP_PTR_ARRAY AzpPtrArray,
  3449. OUT PULONG InsertionPoint OPTIONAL
  3450. )
  3451. /*++
  3452. Routine Description:
  3453. This routine determines if a delta is already in the delta array
  3454. On entry, AzGlResource must be locked share
  3455. Arguments:
  3456. DeltaFlags - Specifies flags describing the delta. This is a set of the
  3457. AZP_DELTA_* flags.
  3458. Guid - Specifies the GUID to lookup ino the array
  3459. If AZP_DELTA_SID is specified, this field is a pointer to a AZP_STRING
  3460. structure describing a SID.
  3461. AzpPtrArray - Specifies the array to lookup the delta in.
  3462. InsertionPoint - On FALSE, returns the point where one would insert the named object.
  3463. On TRUE, returns an index to the object.
  3464. Return Value:
  3465. TRUE - Object was found
  3466. FALSE - Object was not found
  3467. --*/
  3468. {
  3469. AZP_DELTA_ENTRY DeltaEntryTemplate;
  3470. //
  3471. // Initialization
  3472. //
  3473. ASSERT( AzpIsLockedShared( &AzGlResource ) );
  3474. //
  3475. // Determine if the GUID is already in the array.
  3476. //
  3477. DeltaEntryTemplate.DeltaFlags = DeltaFlags;
  3478. if ( DeltaFlags & AZP_DELTA_SID ) {
  3479. DeltaEntryTemplate.Sid = (PSID)(((PAZP_STRING)Guid)->String);
  3480. ASSERT( RtlValidSid( DeltaEntryTemplate.Sid ));
  3481. } else {
  3482. DeltaEntryTemplate.Guid = *Guid;
  3483. ASSERT( !IsEqualGUID( DeltaEntryTemplate.Guid, AzGlZeroGuid));
  3484. }
  3485. return AzpBsearchPtr( AzpPtrArray,
  3486. &DeltaEntryTemplate,
  3487. AzpCompareDeltaEntries,
  3488. InsertionPoint );
  3489. }
  3490. DWORD
  3491. ObAddDeltaToArray(
  3492. IN ULONG DeltaFlags,
  3493. IN GUID *Guid,
  3494. IN PAZP_PTR_ARRAY AzpPtrArray,
  3495. IN BOOLEAN DiscardDeletes
  3496. )
  3497. /*++
  3498. Routine Description:
  3499. Adds a delta to an array of deltas.
  3500. If the delta is already in the list, the DeltaFlags of the current entry are
  3501. updated.
  3502. On entry, AzGlResource must be locked exclusive.
  3503. Arguments:
  3504. DeltaFlags - Specifies flags describing the delta. This is a set of the
  3505. AZP_DELTA_* flags.
  3506. Guid - Specifies the GUID to add to the array
  3507. If AZP_DELTA_SID is specified, this field is a pointer to a AZP_STRING
  3508. structure describing a SID.
  3509. AzpPtrArray - Specifies the array to add the GUID to.
  3510. DiscardDeletes - TRUE if a Deletion entry should delete the corresponding entry
  3511. and not add the deletion entry to the AzpPtrArray
  3512. Return Value:
  3513. NO_ERROR - The operation was successful.
  3514. ERROR_NOT_ENOUGH_MEMORY - There was not enough memory to extend the array.
  3515. --*/
  3516. {
  3517. DWORD WinStatus;
  3518. ULONG InsertionPoint;
  3519. PAZP_DELTA_ENTRY DeltaEntry = NULL;
  3520. ULONG SidSize;
  3521. BOOLEAN DiscardMe;
  3522. //
  3523. // Initialization
  3524. //
  3525. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  3526. DiscardMe = DiscardDeletes && (DeltaFlags & AZP_DELTA_ADD) == 0 ;
  3527. //
  3528. // Determine if the GUID is already in the array.
  3529. //
  3530. if ( ObLookupDelta( DeltaFlags,
  3531. Guid,
  3532. AzpPtrArray,
  3533. &InsertionPoint ) ) {
  3534. PULONG OldDeltaFlags = &((PAZP_DELTA_ENTRY)(AzpPtrArray->Array[InsertionPoint]))->DeltaFlags;
  3535. //
  3536. // Found it
  3537. //
  3538. // If the entry being added is from the persistence provider,
  3539. // don't overwrite the existing entry.
  3540. // The one added by the application is more applicable.
  3541. //
  3542. if ( DeltaFlags & AZP_DELTA_PERSIST_PROVIDER ) {
  3543. // This assert is over active. The provider certainly shouldn't add the same link
  3544. // twice. But we can simply ignore the second entry.
  3545. //ASSERT( (*OldDeltaFlags & AZP_DELTA_PERSIST_PROVIDER) == 0 );
  3546. //
  3547. // If we are to discard the entry,
  3548. // free the allocated memory and its slot in the array.
  3549. //
  3550. } else if ( DiscardMe ) {
  3551. // Free the memory
  3552. AzpFreeHeap( (PAZP_DELTA_ENTRY)(AzpPtrArray->Array[InsertionPoint]) );
  3553. // Free the slot in the array
  3554. AzpRemovePtrByIndex( AzpPtrArray, InsertionPoint );
  3555. //
  3556. // If the entry being added is from the app,
  3557. // simply overwrite the previous entry.
  3558. //
  3559. } else {
  3560. ASSERT( (*OldDeltaFlags & AZP_DELTA_PERSIST_PROVIDER) == 0 );
  3561. *OldDeltaFlags = DeltaFlags;
  3562. }
  3563. return NO_ERROR;
  3564. }
  3565. //
  3566. // If we are to discard this entry,
  3567. // we're done.
  3568. //
  3569. if ( DiscardMe ) {
  3570. WinStatus = NO_ERROR;
  3571. goto Cleanup;
  3572. }
  3573. //
  3574. // Allocate an entry to link into the array
  3575. //
  3576. if ( DeltaFlags & AZP_DELTA_SID ) {
  3577. SidSize = ((PAZP_STRING)Guid)->StringSize;
  3578. } else {
  3579. ASSERT( !IsEqualGUID( *Guid, AzGlZeroGuid));
  3580. SidSize = 0;
  3581. }
  3582. DeltaEntry = (PAZP_DELTA_ENTRY) AzpAllocateHeap( sizeof(*DeltaEntry) + SidSize, "GEDELTA" );
  3583. if ( DeltaEntry == NULL ) {
  3584. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  3585. goto Cleanup;
  3586. }
  3587. DeltaEntry->DeltaFlags = DeltaFlags;
  3588. if ( DeltaFlags & AZP_DELTA_SID ) {
  3589. DeltaEntry->Sid = (PSID)(&(DeltaEntry->Sid)+1);
  3590. RtlCopyMemory( DeltaEntry->Sid,
  3591. ((PAZP_STRING)Guid)->String,
  3592. SidSize );
  3593. } else {
  3594. DeltaEntry->Guid = *Guid;
  3595. }
  3596. //
  3597. // Insert the entry into the list
  3598. //
  3599. WinStatus = AzpAddPtr(
  3600. AzpPtrArray,
  3601. DeltaEntry,
  3602. InsertionPoint );
  3603. if ( WinStatus != NO_ERROR ) {
  3604. goto Cleanup;
  3605. }
  3606. DeltaEntry = NULL;
  3607. //
  3608. // Free locally used resources
  3609. //
  3610. Cleanup:
  3611. if ( DeltaEntry != NULL ) {
  3612. AzpFreeHeap( DeltaEntry );
  3613. }
  3614. return WinStatus;
  3615. }
  3616. VOID
  3617. ObFreeDeltaArray(
  3618. IN PAZP_PTR_ARRAY DeltaArray,
  3619. IN BOOLEAN FreeAllEntries
  3620. )
  3621. /*++
  3622. Routine Description:
  3623. Frees an array of deltas.
  3624. On entry, AzGlResource must be locked exclusive.
  3625. Arguments:
  3626. DeltaArray - Pointer to the delta array to free
  3627. FreeAllEntries - If TRUE all entries are freed.
  3628. If FALSE, only persistence provider entries are freed.
  3629. Return Value:
  3630. None
  3631. --*/
  3632. {
  3633. LONG Index;
  3634. PAZP_DELTA_ENTRY DeltaEntry;
  3635. //
  3636. // Initialization
  3637. //
  3638. AzPrint(( AZD_OBJLIST, "0x%lx: 0x%lx: %ld: ObFreeDeltaArray\n", DeltaArray, DeltaArray->Array, FreeAllEntries ));
  3639. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  3640. //
  3641. // Free each entry in the delta array
  3642. // Walk the array from the top to avoid continually compacting the array
  3643. //
  3644. for ( Index=DeltaArray->UsedCount-1;
  3645. Index>=0;
  3646. Index-- ) {
  3647. //
  3648. // If all entries are to be removed,
  3649. // or the entry was added by the persist provider
  3650. // remove it
  3651. //
  3652. DeltaEntry = (PAZP_DELTA_ENTRY)DeltaArray->Array[Index];
  3653. if ( FreeAllEntries ||
  3654. (DeltaEntry->DeltaFlags & AZP_DELTA_PERSIST_PROVIDER) != 0 ) {
  3655. // Free the memory
  3656. AzpFreeHeap( DeltaEntry );
  3657. // Free the slot in the array
  3658. AzpRemovePtrByIndex( DeltaArray, Index );
  3659. }
  3660. }
  3661. //
  3662. // If the DeltaArray is now empty,
  3663. // delete the array itself
  3664. //
  3665. if ( DeltaArray->UsedCount == 0 && DeltaArray->Array != NULL ) {
  3666. AzpFreeHeap( DeltaArray->Array );
  3667. DeltaArray->Array = NULL;
  3668. DeltaArray->AllocatedCount = 0;
  3669. }
  3670. }
  3671. VOID
  3672. ObInitObjectList(
  3673. IN OUT PGENERIC_OBJECT_LIST GenericObjectList,
  3674. IN PGENERIC_OBJECT_LIST NextGenericObjectList OPTIONAL,
  3675. IN BOOL IsBackLink,
  3676. IN ULONG LinkPairId,
  3677. IN ULONG DirtyBit,
  3678. IN PGENERIC_OBJECT_HEAD GenericObjectHead0 OPTIONAL,
  3679. IN PGENERIC_OBJECT_HEAD GenericObjectHead1 OPTIONAL,
  3680. IN PGENERIC_OBJECT_HEAD GenericObjectHead2 OPTIONAL
  3681. )
  3682. /*++
  3683. Routine Description
  3684. Initialize a list of generic objects.
  3685. The caller must call ObFreeObjectList after calling this routine.
  3686. Arguments
  3687. GenericObjectList - Specifies the object list to initialize
  3688. NextGenericObjectList - Specifies a pointer to the next GenericObjectList
  3689. that is hosted in the same generic object as this one.
  3690. IsBackLink - TRUE if the link is a backlink
  3691. See GENERIC_OBJECT_LIST definition.
  3692. LinkPairId - LinkPairId for this object list.
  3693. See GENERIC_OBJECT_LIST definition.
  3694. DirtyBit - Specifies the dirty bit that should be set when this object list is modified.
  3695. Should be zero for back links.
  3696. GenericObjectHeadN - Specifies a pointer to the head of the list of objects
  3697. that are candidates for being pointed to by the object list.
  3698. If this object list is maintained by an external API (and not a "back" list),
  3699. then at least one GenericObjectHead must be specified.
  3700. If this is a back link, all GenericObjectHeads must be NULL.
  3701. Return Value
  3702. None
  3703. --*/
  3704. {
  3705. //
  3706. // Initialize most fields to zero
  3707. //
  3708. RtlZeroMemory( GenericObjectList, sizeof(*GenericObjectList) );
  3709. //
  3710. // Initialize the pointer to the next generic object list for this object
  3711. //
  3712. GenericObjectList->NextGenericObjectList = NextGenericObjectList;
  3713. //
  3714. // Initialize the link pair information
  3715. //
  3716. GenericObjectList->IsBackLink = IsBackLink;
  3717. GenericObjectList->LinkPairId = LinkPairId;
  3718. GenericObjectList->DirtyBit = DirtyBit;
  3719. if ( IsBackLink ) {
  3720. ASSERT( DirtyBit == 0 );
  3721. ASSERT( GenericObjectHead0 == NULL );
  3722. ASSERT( GenericObjectHead1 == NULL );
  3723. ASSERT( GenericObjectHead2 == NULL );
  3724. }
  3725. //
  3726. // Initialize the pointers to the object heads
  3727. //
  3728. GenericObjectList->GenericObjectHeads[0] = GenericObjectHead0;
  3729. GenericObjectList->GenericObjectHeads[1] = GenericObjectHead1;
  3730. GenericObjectList->GenericObjectHeads[2] = GenericObjectHead2;
  3731. AzPrint(( AZD_OBJLIST, "0x%lx: 0x%lx: ObInitObjectList\n", &GenericObjectList->GenericObjects, GenericObjectList->GenericObjects.Array ));
  3732. }
  3733. //
  3734. // TABLE of mappings to backlink object list tables
  3735. //
  3736. struct {
  3737. ULONG LinkFromObjectType;
  3738. ULONG LinkToObjectType;
  3739. BOOL IsBackLink;
  3740. ULONG LinkPairId;
  3741. ULONG ObjectListOffset;
  3742. } ObjectListOffsetTable[] = {
  3743. { OBJECT_TYPE_TASK, OBJECT_TYPE_OPERATION, FALSE, 0, offsetof(_AZP_TASK, Operations) },
  3744. { OBJECT_TYPE_OPERATION, OBJECT_TYPE_TASK, TRUE, 0, offsetof(_AZP_OPERATION, backTasks) },
  3745. { OBJECT_TYPE_TASK, OBJECT_TYPE_TASK, FALSE, 0, offsetof(_AZP_TASK, Tasks) },
  3746. { OBJECT_TYPE_TASK, OBJECT_TYPE_TASK, TRUE, 0, offsetof(_AZP_TASK, backTasks) },
  3747. { OBJECT_TYPE_GROUP, OBJECT_TYPE_GROUP, FALSE, AZP_LINKPAIR_MEMBERS, offsetof(_AZP_GROUP, AppMembers) },
  3748. { OBJECT_TYPE_GROUP, OBJECT_TYPE_GROUP, TRUE, AZP_LINKPAIR_MEMBERS, offsetof(_AZP_GROUP, backAppMembers) },
  3749. { OBJECT_TYPE_GROUP, OBJECT_TYPE_GROUP, FALSE, AZP_LINKPAIR_NON_MEMBERS, offsetof(_AZP_GROUP, AppNonMembers) },
  3750. { OBJECT_TYPE_GROUP, OBJECT_TYPE_GROUP, TRUE, AZP_LINKPAIR_NON_MEMBERS, offsetof(_AZP_GROUP, backAppNonMembers) },
  3751. { OBJECT_TYPE_ROLE, OBJECT_TYPE_GROUP, FALSE, 0, offsetof(_AZP_ROLE, AppMembers) },
  3752. { OBJECT_TYPE_GROUP, OBJECT_TYPE_ROLE, TRUE, 0, offsetof(_AZP_GROUP, backRoles) },
  3753. { OBJECT_TYPE_ROLE, OBJECT_TYPE_OPERATION, FALSE, 0, offsetof(_AZP_ROLE, Operations) },
  3754. { OBJECT_TYPE_OPERATION, OBJECT_TYPE_ROLE, TRUE, 0, offsetof(_AZP_OPERATION, backRoles) },
  3755. { OBJECT_TYPE_ROLE, OBJECT_TYPE_TASK, FALSE, 0, offsetof(_AZP_ROLE, Tasks) },
  3756. { OBJECT_TYPE_TASK, OBJECT_TYPE_ROLE, TRUE, 0, offsetof(_AZP_TASK, backRoles) },
  3757. { OBJECT_TYPE_GROUP, OBJECT_TYPE_SID, FALSE, AZP_LINKPAIR_SID_MEMBERS, offsetof(_AZP_GROUP, SidMembers) },
  3758. { OBJECT_TYPE_SID, OBJECT_TYPE_GROUP, TRUE, AZP_LINKPAIR_SID_MEMBERS, offsetof(_AZP_SID, backGroupMembers) },
  3759. { OBJECT_TYPE_GROUP, OBJECT_TYPE_SID, FALSE, AZP_LINKPAIR_SID_NON_MEMBERS, offsetof(_AZP_GROUP, SidNonMembers) },
  3760. { OBJECT_TYPE_SID, OBJECT_TYPE_GROUP, TRUE, AZP_LINKPAIR_SID_NON_MEMBERS, offsetof(_AZP_SID, backGroupNonMembers) },
  3761. { OBJECT_TYPE_ROLE, OBJECT_TYPE_SID, FALSE, 0, offsetof(_AZP_ROLE, SidMembers) },
  3762. { OBJECT_TYPE_SID, OBJECT_TYPE_ROLE, TRUE, 0, offsetof(_AZP_SID, backRoles) },
  3763. { OBJECT_TYPE_AZAUTHSTORE, OBJECT_TYPE_SID, FALSE, AZP_LINKPAIR_POLICY_ADMINS, offsetof(_GENERIC_OBJECT, PolicyAdmins) },
  3764. { OBJECT_TYPE_SID, OBJECT_TYPE_AZAUTHSTORE, TRUE, AZP_LINKPAIR_POLICY_ADMINS, offsetof(_AZP_SID, backAdmins) },
  3765. { OBJECT_TYPE_AZAUTHSTORE, OBJECT_TYPE_SID, FALSE, AZP_LINKPAIR_POLICY_READERS, offsetof(_GENERIC_OBJECT, PolicyReaders) },
  3766. { OBJECT_TYPE_SID, OBJECT_TYPE_AZAUTHSTORE, TRUE, AZP_LINKPAIR_POLICY_READERS, offsetof(_AZP_SID, backReaders) },
  3767. { OBJECT_TYPE_APPLICATION, OBJECT_TYPE_SID, FALSE, AZP_LINKPAIR_POLICY_ADMINS, offsetof(_GENERIC_OBJECT, PolicyAdmins) },
  3768. { OBJECT_TYPE_SID, OBJECT_TYPE_APPLICATION, TRUE, AZP_LINKPAIR_POLICY_ADMINS, offsetof(_AZP_SID, backAdmins) },
  3769. { OBJECT_TYPE_APPLICATION, OBJECT_TYPE_SID, FALSE, AZP_LINKPAIR_POLICY_READERS, offsetof(_GENERIC_OBJECT, PolicyReaders) },
  3770. { OBJECT_TYPE_SID, OBJECT_TYPE_APPLICATION, TRUE, AZP_LINKPAIR_POLICY_READERS, offsetof(_AZP_SID, backReaders) },
  3771. { OBJECT_TYPE_SCOPE, OBJECT_TYPE_SID, FALSE, AZP_LINKPAIR_POLICY_ADMINS, offsetof(_GENERIC_OBJECT, PolicyAdmins) },
  3772. { OBJECT_TYPE_SID, OBJECT_TYPE_SCOPE, TRUE, AZP_LINKPAIR_POLICY_ADMINS, offsetof(_AZP_SID, backAdmins) },
  3773. { OBJECT_TYPE_SCOPE, OBJECT_TYPE_SID, FALSE, AZP_LINKPAIR_POLICY_READERS, offsetof(_GENERIC_OBJECT, PolicyReaders) },
  3774. { OBJECT_TYPE_SID, OBJECT_TYPE_SCOPE, TRUE, AZP_LINKPAIR_POLICY_READERS, offsetof(_AZP_SID, backReaders) },
  3775. { OBJECT_TYPE_AZAUTHSTORE, OBJECT_TYPE_SID, FALSE, AZP_LINKPAIR_DELEGATED_POLICY_USERS, offsetof(_GENERIC_OBJECT, DelegatedPolicyUsers) },
  3776. {OBJECT_TYPE_SID, OBJECT_TYPE_AZAUTHSTORE, TRUE, AZP_LINKPAIR_DELEGATED_POLICY_USERS, offsetof(_AZP_SID, backDelegatedPolicyUsers) },
  3777. { OBJECT_TYPE_APPLICATION, OBJECT_TYPE_SID, FALSE, AZP_LINKPAIR_DELEGATED_POLICY_USERS, offsetof(_GENERIC_OBJECT, DelegatedPolicyUsers) },
  3778. {OBJECT_TYPE_SID, OBJECT_TYPE_APPLICATION, TRUE, AZP_LINKPAIR_DELEGATED_POLICY_USERS, offsetof(_AZP_SID, backDelegatedPolicyUsers) },
  3779. };
  3780. PGENERIC_OBJECT_LIST
  3781. ObGetObjectListPtr(
  3782. IN PGENERIC_OBJECT GenericObject,
  3783. IN ULONG LinkToObjectType,
  3784. IN PGENERIC_OBJECT_LIST LinkToGenericObjectList
  3785. )
  3786. /*++
  3787. Routine Description
  3788. Returns a pointer to a GENERIC_OBJECT_LIST structure within the passed in
  3789. GenericObject that is suitable for linking an object of type LinkToObjectType
  3790. into.
  3791. Arguments
  3792. GenericObject - Specifies the object the link is from.
  3793. LinkToObjectType - Specifies the object type the link is to.
  3794. LinkToGenericObjectList - Specifies a pointer to the generic object list
  3795. structure that is within the LinkToGenericObject.
  3796. Return Value
  3797. Returns a pointer to the generic object list.
  3798. --*/
  3799. {
  3800. PGENERIC_OBJECT_LIST GenericObjectList = NULL;
  3801. ULONG i;
  3802. //
  3803. // Compute the address of the generic address list the object is in.
  3804. // We could do this more generically, but that would scatter this data
  3805. // over too wide an array.
  3806. //
  3807. for ( i=0; i<sizeof(ObjectListOffsetTable)/sizeof(ObjectListOffsetTable[0]); i++ ) {
  3808. //
  3809. // Find the entry in the table that matches our situation
  3810. //
  3811. if ( GenericObject->ObjectType == ObjectListOffsetTable[i].LinkFromObjectType &&
  3812. LinkToObjectType == ObjectListOffsetTable[i].LinkToObjectType &&
  3813. LinkToGenericObjectList->IsBackLink != ObjectListOffsetTable[i].IsBackLink &&
  3814. LinkToGenericObjectList->LinkPairId == ObjectListOffsetTable[i].LinkPairId ) {
  3815. GenericObjectList = (PGENERIC_OBJECT_LIST)
  3816. (((LPBYTE)GenericObject)+(ObjectListOffsetTable[i].ObjectListOffset));
  3817. }
  3818. }
  3819. ASSERT( GenericObjectList != NULL );
  3820. return GenericObjectList;
  3821. }
  3822. VOID
  3823. ObRemoveObjectListLink(
  3824. IN PGENERIC_OBJECT GenericObject,
  3825. IN PGENERIC_OBJECT_LIST GenericObjectList,
  3826. IN ULONG Index
  3827. )
  3828. /*++
  3829. Routine Description
  3830. Remove the links between generic objects in both directions
  3831. On entry, AzGlResource must be locked exclusive.
  3832. Arguments
  3833. GenericObject - Specifies an object the link is from
  3834. GenericObjectList - Specifies a pointer to the generic object list
  3835. structure that is within the GenericObject.
  3836. Index - Specifies the index within GenericObjectList that is to be removed.
  3837. Return Value
  3838. None
  3839. --*/
  3840. {
  3841. DWORD WinStatus;
  3842. PGENERIC_OBJECT OtherGenericObject;
  3843. PGENERIC_OBJECT_LIST OtherGenericObjectList;
  3844. ULONG OtherIndex;
  3845. BOOL fRemoveByPtr = FALSE;
  3846. //
  3847. // Initialization
  3848. //
  3849. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  3850. //
  3851. // Grab a pointer to the linked-to object
  3852. //
  3853. OtherGenericObject = (PGENERIC_OBJECT)
  3854. (GenericObjectList->GenericObjects.Array[Index]);
  3855. //
  3856. // Remove that pointer from our array
  3857. //
  3858. AzpRemovePtrByIndex( &GenericObjectList->GenericObjects,
  3859. Index );
  3860. //
  3861. // Get a pointer to the object list that our entry is in
  3862. //
  3863. OtherGenericObjectList = ObGetObjectListPtr( OtherGenericObject,
  3864. GenericObject->ObjectType,
  3865. GenericObjectList );
  3866. ASSERT( OtherGenericObjectList != NULL );
  3867. if (NULL != GenericObject->ObjectName &&
  3868. !OtherGenericObjectList->IsBackLink)
  3869. {
  3870. //
  3871. // Lookup our name in the object list that our entry is in
  3872. // Back links are not maintained in order since names are not unique
  3873. //
  3874. WinStatus = ObLookupPropertyItem( OtherGenericObjectList,
  3875. &GenericObject->ObjectName->ObjectName,
  3876. &OtherIndex );
  3877. //
  3878. // If found,
  3879. // remove it quickly
  3880. //
  3881. if ( WinStatus == ERROR_ALREADY_EXISTS ) {
  3882. AzpRemovePtrByIndex( &OtherGenericObjectList->GenericObjects, OtherIndex );
  3883. } else {
  3884. //
  3885. // In all other cases
  3886. //
  3887. fRemoveByPtr = TRUE;
  3888. }
  3889. } else {
  3890. // either back link or AzAuthStore object
  3891. // all objects have name except AzAuthStore
  3892. fRemoveByPtr = TRUE;
  3893. }
  3894. if (fRemoveByPtr) {
  3895. AzpRemovePtrByPtr( &OtherGenericObjectList->GenericObjects, GenericObject );
  3896. }
  3897. //
  3898. // Mark that the operation caches need flushing
  3899. // ... any change to the object cache invalidates the cache
  3900. //
  3901. GenericObject->AzStoreObject->OpCacheSerialNumber ++;
  3902. AzPrint(( AZD_ACCESS_MORE, "ObRemoveObjectListLink: OpCacheSerialNumber set to %ld\n",
  3903. GenericObject->AzStoreObject->OpCacheSerialNumber ));
  3904. }
  3905. LONG
  3906. AzpCompareGenericObjectEntries(
  3907. const void *Object1,
  3908. const void *Object2
  3909. )
  3910. /*++
  3911. Routine description:
  3912. Compare names of two GENERIC_OBJECTS
  3913. Arguments:
  3914. Object1 - First entry to compare
  3915. Object2 - Second entry to compare
  3916. Returns:
  3917. CSTR_LESS_THAN: Entry 1 is less than entry 2
  3918. CSTR_EQUAL: Entry 1 is equal to entry 2
  3919. CSTR_GREATER_THAN: Entry 1 is greater than entry 2
  3920. --*/
  3921. {
  3922. LONG Result;
  3923. PGENERIC_OBJECT GenericObject1 = (PGENERIC_OBJECT) Object1;
  3924. PGENERIC_OBJECT GenericObject2 = (PGENERIC_OBJECT) Object2;
  3925. //
  3926. // Compare the names
  3927. //
  3928. ASSERT( GenericObject1->ObjectName != NULL );
  3929. ASSERT( GenericObject2->ObjectName != NULL );
  3930. Result = AzpCompareStrings(
  3931. &GenericObject1->ObjectName->ObjectName,
  3932. &GenericObject2->ObjectName->ObjectName );
  3933. #if 0
  3934. AzPrint(( AZD_CRITICAL, "Compare: '%ws' '%ws' %ld\n",
  3935. GenericObject1->ObjectName->ObjectName.String,
  3936. GenericObject2->ObjectName->ObjectName.String,
  3937. Result ));
  3938. #endif // 0
  3939. return Result;
  3940. }
  3941. DWORD
  3942. ObLookupPropertyItem(
  3943. IN PGENERIC_OBJECT_LIST GenericObjectList,
  3944. IN PAZP_STRING ObjectName,
  3945. OUT PULONG InsertionPoint OPTIONAL
  3946. )
  3947. /*++
  3948. Routine Description:
  3949. This routine determins if the specified object name is already in the
  3950. object list.
  3951. On entry, AzGlResource must be locked share
  3952. Arguments:
  3953. GenericObjectList - Specifies the object list to be searched
  3954. ObjectName - Specifies the ObjectName to lookup
  3955. InsertionPoint - On ERROR_NOT_FOUND, returns the point where one would insert the named
  3956. object. On ERROR_ALREADY_EXISTS, returns an index to the object.
  3957. Return Value:
  3958. ERROR_ALREADY_EXISTS - An object by that name already exists in the list
  3959. ERROR_NOT_FOUND - There is no object by that name
  3960. Misc other failure statuses.
  3961. --*/
  3962. {
  3963. GENERIC_OBJECT GenericObjectTemplate;
  3964. GENERIC_OBJECT_NAME GenericObjectName;
  3965. // Back links are not maintained in order since names are not unique
  3966. ASSERT( !GenericObjectList->IsBackLink );
  3967. //
  3968. // Initialization
  3969. //
  3970. ASSERT( AzpIsLockedShared( &AzGlResource ) );
  3971. // AzPrint(( AZD_CRITICAL, "Lookup: 0x%lx %ws\n", GenericObjectList, ObjectName->String ));
  3972. //
  3973. // Build a template of the object to search for
  3974. //
  3975. GenericObjectTemplate.ObjectName = &GenericObjectName;
  3976. GenericObjectName.ObjectName = *ObjectName;
  3977. //
  3978. // Find the object in the array
  3979. //
  3980. if ( AzpBsearchPtr(
  3981. &GenericObjectList->GenericObjects,
  3982. &GenericObjectTemplate,
  3983. AzpCompareGenericObjectEntries,
  3984. InsertionPoint ) ) {
  3985. // AzPrint(( AZD_CRITICAL, "Lookup: 0x%lx %ws found %ld\n", GenericObjectList, ObjectName->String, *InsertionPoint ));
  3986. return ERROR_ALREADY_EXISTS;
  3987. }
  3988. // AzPrint(( AZD_CRITICAL, "Lookup: 0x%lx %ws not found %ld\n", GenericObjectList, ObjectName->String, *InsertionPoint ));
  3989. return ERROR_NOT_FOUND;
  3990. }
  3991. DWORD
  3992. ObAddPropertyItem(
  3993. IN PGENERIC_OBJECT GenericObject,
  3994. IN PGENERIC_OBJECT_LIST GenericObjectList,
  3995. IN ULONG Flags,
  3996. IN PAZP_STRING ObjectName
  3997. )
  3998. /*++
  3999. Routine Description:
  4000. Adds an object to the list of objects specified by GenericObjectList.
  4001. On entry, AzGlResource must be locked exclusive.
  4002. Arguments:
  4003. GenericObject - Specifies a pointer to the object the link is from
  4004. Flags - Specifies internal flags
  4005. AZP_FLAGS_BY_GUID - ObjectName is a pointer to a GUID
  4006. AZP_FLAGS_PERSIST_* - Call is from the persistence provider
  4007. AZP_FLAGS_RECONCILE - Call is from AzpPersistReconcile
  4008. GenericObjectList - Specifies the object list to add the object into.
  4009. ObjectName - Specifies a pointer to name of the object to add.
  4010. Return Value:
  4011. NO_ERROR - The operation was successful.
  4012. ERROR_NOT_FOUND - There is no object by that name
  4013. ERROR_ALREADY_EXISTS - An object by that name already exists in the list
  4014. --*/
  4015. {
  4016. DWORD WinStatus;
  4017. ULONG InsertionPoint;
  4018. ULONG BackInsertionPoint;
  4019. ULONG ObjectTypeIndex;
  4020. PGENERIC_OBJECT FoundGenericObject = NULL;
  4021. PGENERIC_OBJECT_LIST BackGenericObjectList;
  4022. ULONG DeltaFlags = AZP_DELTA_ADD;
  4023. GUID *DeltaGuid;
  4024. //
  4025. // Initialization
  4026. //
  4027. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  4028. if (IsNormalFlags(Flags) &&
  4029. GenericObject->IsWritable == 0 &&
  4030. GenericObject->ObjectType != OBJECT_TYPE_CLIENT_CONTEXT)
  4031. {
  4032. WinStatus = ERROR_ACCESS_DENIED;
  4033. goto Cleanup;
  4034. }
  4035. //
  4036. // first things first, let's check if the AzAuthStore's versions support writing
  4037. //
  4038. if ( IsNormalFlags(Flags) &&
  4039. !AzpAzStoreVersionAllowWrite(GenericObject->AzStoreObject) )
  4040. {
  4041. WinStatus = ERROR_REVISION_MISMATCH;
  4042. goto Cleanup;
  4043. }
  4044. //
  4045. // If this is the provider calling,
  4046. // we can't be guaranteed that the linked-to object exists.
  4047. // So just remember the GUID (or Sid) for now
  4048. //
  4049. if ( Flags & AZPE_FLAGS_PERSIST_MASK ) {
  4050. // Delta is from the persist provider
  4051. DeltaFlags |= AZP_DELTA_PERSIST_PROVIDER;
  4052. // Link is to a SID
  4053. if ( (Flags & AZP_FLAGS_BY_GUID) == 0 ) {
  4054. DeltaFlags |= AZP_DELTA_SID;
  4055. ASSERT( AzpIsSidList( GenericObjectList ) );
  4056. if ( !AzpIsSidList( GenericObjectList ) ) {
  4057. WinStatus = ERROR_INVALID_PARAMETER;
  4058. goto Cleanup;
  4059. }
  4060. } else {
  4061. ASSERT( !AzpIsSidList( GenericObjectList ) );
  4062. if ( AzpIsSidList( GenericObjectList ) ) {
  4063. WinStatus = ERROR_INVALID_PARAMETER;
  4064. goto Cleanup;
  4065. }
  4066. AzPrint(( AZD_REF, "ObAddPropertyItem (by guid): " ));
  4067. AzpDumpGuid( AZD_REF, (GUID *)ObjectName );
  4068. AzPrint(( AZD_REF, "\n" ));
  4069. }
  4070. //
  4071. // Just remember the delta
  4072. //
  4073. WinStatus = ObAddDeltaToArray(
  4074. DeltaFlags,
  4075. (GUID *)ObjectName,
  4076. &GenericObjectList->DeltaArray,
  4077. FALSE ); // Allow deletion entries in the array
  4078. if ( WinStatus != NO_ERROR ) {
  4079. goto Cleanup;
  4080. }
  4081. //
  4082. // Remember that the provider changed the attribute
  4083. //
  4084. ASSERT( AzpIsCritsectLocked( &GenericObject->AzStoreObject->PersistCritSect ) );
  4085. ASSERT( (GenericObject->Flags & GENOBJ_FLAGS_PERSIST_OK) == 0 );
  4086. GenericObject->PersistDirtyBits |= GenericObjectList->DirtyBit;
  4087. //
  4088. // If this is the app calling or AzpPersistReconcile calling,
  4089. // we know the linked-to object should exist.
  4090. //
  4091. } else {
  4092. //
  4093. // Don't allow creator/owner on any sid list.
  4094. // The sids only apply to inheritable ACEs.
  4095. // On the readers/admins/delegators lists, it ends up getting morphed.
  4096. // So simply disallow to prevent confusion.
  4097. //
  4098. if ( IsNormalFlags(Flags) && AzpIsSidList( GenericObjectList ) ) {
  4099. PSID Sid = (PSID) ObjectName->String;
  4100. ASSERT( ObjectName->IsSid );
  4101. if ( RtlEqualSid( Sid, AzGlCreatorOwnerSid )) {
  4102. WinStatus = ERROR_INVALID_PARAMETER;
  4103. AzPrint(( AZD_INVPARM, "ObAddPropertyItem: Cannot set creator owner sid\n" ));
  4104. goto Cleanup;
  4105. }
  4106. if ( RtlEqualSid( Sid, AzGlCreatorGroupSid )) {
  4107. WinStatus = ERROR_INVALID_PARAMETER;
  4108. AzPrint(( AZD_INVPARM, "ObAddPropertyItem: Cannot set creator group sid\n" ));
  4109. goto Cleanup;
  4110. }
  4111. }
  4112. //
  4113. // Loop through the various lists of objects that can be referenced
  4114. //
  4115. for ( ObjectTypeIndex=0; ObjectTypeIndex<GEN_OBJECT_HEAD_COUNT; ObjectTypeIndex++ ) {
  4116. //
  4117. // Stop when there are no more lists to search
  4118. //
  4119. if ( GenericObjectList->GenericObjectHeads[ObjectTypeIndex] == NULL ) {
  4120. break;
  4121. }
  4122. //
  4123. // Find the specified object in this list
  4124. //
  4125. WinStatus = ObReferenceObjectByName(
  4126. GenericObjectList->GenericObjectHeads[ObjectTypeIndex],
  4127. ObjectName,
  4128. Flags,
  4129. &FoundGenericObject );
  4130. if ( WinStatus == NO_ERROR ) {
  4131. break;
  4132. }
  4133. //
  4134. // If this is a link to a SID object,
  4135. // create the SID object.
  4136. //
  4137. // AzpSids are pseudo objects that come into existence as they are needed.
  4138. //
  4139. if ( AzpIsSidList( GenericObjectList ) ) {
  4140. ASSERT( ObjectTypeIndex == 0 ); // There is only one list of sids
  4141. WinStatus = ObCreateObject(
  4142. GenericObjectList->GenericObjectHeads[0]->ParentGenericObject,
  4143. GenericObjectList->GenericObjectHeads[0],
  4144. OBJECT_TYPE_SID,
  4145. ObjectName,
  4146. NULL, // Guid not known
  4147. Flags, // Flags from our caller
  4148. &FoundGenericObject );
  4149. if ( WinStatus != NO_ERROR ) {
  4150. goto Cleanup;
  4151. }
  4152. }
  4153. }
  4154. //
  4155. // If none of the lists had an object by the requested name,
  4156. // or the found object has *never* been submited,
  4157. // complain.
  4158. //
  4159. if ( FoundGenericObject == NULL ||
  4160. (FoundGenericObject->DirtyBits & AZ_DIRTY_CREATE) != 0 ) {
  4161. WinStatus = ERROR_NOT_FOUND;
  4162. goto Cleanup;
  4163. }
  4164. //
  4165. // Prevent a reference to ourself
  4166. //
  4167. if ( GenericObject == FoundGenericObject ) {
  4168. AzPrint(( AZD_INVPARM, "Reference to self\n" ));
  4169. WinStatus = ERROR_DS_LOOP_DETECT;
  4170. goto Cleanup;
  4171. }
  4172. //
  4173. // Call the object specific routine to validate the request
  4174. //
  4175. if ( ObjectAddPropertyItemRoutine[GenericObject->ObjectType] != NULL ) {
  4176. WinStatus = ObjectAddPropertyItemRoutine[GenericObject->ObjectType](
  4177. GenericObject,
  4178. GenericObjectList,
  4179. FoundGenericObject );
  4180. if ( WinStatus != NO_ERROR ) {
  4181. goto Cleanup;
  4182. }
  4183. }
  4184. //
  4185. // Find the insertion point for this name.
  4186. //
  4187. WinStatus = ObLookupPropertyItem( GenericObjectList,
  4188. &FoundGenericObject->ObjectName->ObjectName,
  4189. &InsertionPoint );
  4190. if ( WinStatus != ERROR_NOT_FOUND ) {
  4191. goto Cleanup;
  4192. }
  4193. //
  4194. // Insert the generic object into the list
  4195. //
  4196. WinStatus = AzpAddPtr(
  4197. &GenericObjectList->GenericObjects,
  4198. FoundGenericObject,
  4199. InsertionPoint );
  4200. if ( WinStatus != NO_ERROR ) {
  4201. goto Cleanup;
  4202. }
  4203. //
  4204. // Get a pointer to the backlink object list
  4205. //
  4206. BackGenericObjectList = ObGetObjectListPtr( FoundGenericObject,
  4207. GenericObject->ObjectType,
  4208. GenericObjectList );
  4209. ASSERT( BackGenericObjectList != NULL );
  4210. //
  4211. // Maintain a back link from the generic object we just linked to back
  4212. // to this object.
  4213. //
  4214. // Back links are not maintained in order since names are not unique
  4215. //
  4216. BackInsertionPoint = BackGenericObjectList->GenericObjects.UsedCount;
  4217. WinStatus = AzpAddPtr(
  4218. &BackGenericObjectList->GenericObjects,
  4219. GenericObject,
  4220. BackInsertionPoint );
  4221. if ( WinStatus != NO_ERROR ) {
  4222. // Undo the forward link
  4223. AzpRemovePtrByIndex( &GenericObjectList->GenericObjects, InsertionPoint );
  4224. goto Cleanup;
  4225. }
  4226. //
  4227. // Let the persist provider know of the change
  4228. //
  4229. if ( IsNormalFlags(Flags) ) {
  4230. if ( AzpIsSidList( GenericObjectList ) ) {
  4231. DeltaGuid = (GUID *)ObjectName;
  4232. DeltaFlags |= AZP_DELTA_SID;
  4233. } else {
  4234. DeltaGuid = &FoundGenericObject->PersistenceGuid;
  4235. }
  4236. WinStatus = ObAddDeltaToArray(
  4237. DeltaFlags,
  4238. DeltaGuid,
  4239. &GenericObjectList->DeltaArray,
  4240. FALSE ); // Allow deletion entries in the array
  4241. if ( WinStatus != NO_ERROR ) {
  4242. // Undo the forward link
  4243. AzpRemovePtrByIndex( &GenericObjectList->GenericObjects, InsertionPoint );
  4244. // Undo the back link
  4245. AzpRemovePtrByIndex( &BackGenericObjectList->GenericObjects, BackInsertionPoint );
  4246. goto Cleanup;
  4247. }
  4248. }
  4249. //
  4250. // Mark that the group membership caches need flushing
  4251. //
  4252. if ( GenericObject->ObjectType == OBJECT_TYPE_GROUP ) {
  4253. GenericObject->AzStoreObject->GroupEvalSerialNumber ++;
  4254. AzPrint(( AZD_ACCESS_MORE, "ObAddPropertyItem: GroupEvalSerialNumber set to %ld\n",
  4255. GenericObject->AzStoreObject->GroupEvalSerialNumber ));
  4256. }
  4257. //
  4258. // Finally set the dirty bit
  4259. //
  4260. if ( IsNormalFlags(Flags) ) {
  4261. GenericObject->DirtyBits |= GenericObjectList->DirtyBit;
  4262. }
  4263. //
  4264. // Mark that the operation caches need flushing
  4265. // ... any change to the object cache invalidates the cache
  4266. //
  4267. GenericObject->AzStoreObject->OpCacheSerialNumber ++;
  4268. AzPrint(( AZD_ACCESS_MORE, "ObAddPropertyItem: OpCacheSerialNumber set to %ld\n",
  4269. GenericObject->AzStoreObject->OpCacheSerialNumber ));
  4270. //
  4271. // Return to the caller
  4272. //
  4273. WinStatus = NO_ERROR;
  4274. }
  4275. //
  4276. // Free locally used resources
  4277. //
  4278. Cleanup:
  4279. if ( FoundGenericObject != NULL ) {
  4280. ObDereferenceObject( FoundGenericObject );
  4281. }
  4282. return WinStatus;
  4283. }
  4284. DWORD
  4285. WINAPI
  4286. AzAddPropertyItem(
  4287. IN AZ_HANDLE AzHandle,
  4288. IN ULONG PropertyId,
  4289. IN DWORD Reserved,
  4290. IN PVOID PropertyValue
  4291. )
  4292. /*++
  4293. Routine Description:
  4294. Adds an item to the list of items specified by PropertyId.
  4295. Arguments:
  4296. AzHandle - Specifies a handle to the object to add a property item for
  4297. PropertyId - Specifies which property to modify
  4298. Reserved - Reserved. Must by zero.
  4299. PropertyValue - Specifies a pointer to item to add.
  4300. The specified value and type depends on PropertyId.
  4301. Return Value:
  4302. NO_ERROR - The operation was successful
  4303. ERROR_INVALID_PARAMETER - PropertyId isn't valid
  4304. ERROR_NOT_FOUND - There is no object by that name
  4305. ERROR_ALREADY_EXISTS - An item by that name already exists in the list
  4306. --*/
  4307. {
  4308. DWORD WinStatus;
  4309. PGENERIC_OBJECT GenericObject = (PGENERIC_OBJECT) AzHandle;
  4310. PGENERIC_OBJECT ReferencedObject = NULL;
  4311. PGENERIC_OBJECT_LIST GenericObjectList;
  4312. ULONG ObjectType;
  4313. AZP_STRING ObjectNameString;
  4314. //
  4315. // Initialization
  4316. //
  4317. AzpInitString( &ObjectNameString, NULL );
  4318. //
  4319. // Grab the global lock
  4320. //
  4321. AzpLockResourceExclusive( &AzGlResource );
  4322. //
  4323. // Validate the input parameters
  4324. //
  4325. if ( Reserved != 0 ) {
  4326. AzPrint(( AZD_INVPARM, "AzAddPropertyItem: Reserved != 0\n" ));
  4327. WinStatus = ERROR_INVALID_PARAMETER;
  4328. goto Cleanup;
  4329. }
  4330. //
  4331. // if this is ACL related property items
  4332. // quick check to see if it is valid
  4333. // we really want this to happen early
  4334. //
  4335. if (AZ_PROP_POLICY_ADMINS == PropertyId ||
  4336. AZ_PROP_POLICY_READERS == PropertyId)
  4337. {
  4338. WinStatus = CHECK_ACL_SUPPORT(GenericObject);
  4339. if ( WinStatus != NO_ERROR ) {
  4340. goto Cleanup;
  4341. }
  4342. } else if ( PropertyId == AZ_PROP_DELEGATED_POLICY_USERS ) {
  4343. WinStatus = CHECK_DELEGATION_SUPPORT(GenericObject);
  4344. if ( WinStatus != NO_ERROR ) {
  4345. goto Cleanup;
  4346. }
  4347. }
  4348. //
  4349. // Validate the Property ID
  4350. //
  4351. WinStatus = ObMapPropIdToObjectList(
  4352. (PGENERIC_OBJECT)AzHandle,
  4353. PropertyId,
  4354. &GenericObjectList,
  4355. &ObjectType );
  4356. if ( WinStatus != NO_ERROR ) {
  4357. AzPrint(( AZD_INVPARM, "AzAddPropertyItem: invalid prop id %ld\n", PropertyId ));
  4358. return WinStatus;
  4359. }
  4360. //
  4361. // Validate the passed in handle
  4362. //
  4363. WinStatus = ObReferenceObjectByHandle( GenericObject,
  4364. FALSE, // Don't allow deleted objects
  4365. TRUE, // Refresh the cache
  4366. ObjectType );
  4367. if ( WinStatus != NO_ERROR ) {
  4368. goto Cleanup;
  4369. }
  4370. ReferencedObject = GenericObject;
  4371. //
  4372. // if policy admins is to be modified for an scope object,
  4373. // we need to check if it's allowed (w/ bizrules)
  4374. //
  4375. if ( PropertyId == AZ_PROP_POLICY_ADMINS &&
  4376. ObjectType == OBJECT_TYPE_SCOPE ) {
  4377. //
  4378. // currently it's not delegated
  4379. //
  4380. WinStatus = AzpScopeCanBeDelegated(GenericObject, FALSE);
  4381. if ( WinStatus != ERROR_SUCCESS ) {
  4382. //
  4383. // if scope cannot be delegated or some error occurs detecting the delegation,
  4384. // do not allow changes to policy admins
  4385. //
  4386. goto Cleanup;
  4387. }
  4388. }
  4389. //
  4390. // Capture the object name string from the caller
  4391. //
  4392. if ( AzpIsSidList( GenericObjectList ) ) {
  4393. WinStatus = AzpCaptureSid( &ObjectNameString,
  4394. PropertyValue );
  4395. } else {
  4396. WinStatus = AzpCaptureString( &ObjectNameString,
  4397. (LPWSTR)PropertyValue,
  4398. AZ_MAX_NAME_LENGTH, // Don't need to validate size exactly
  4399. FALSE ); // NULL names not OK
  4400. }
  4401. if ( WinStatus != NO_ERROR ) {
  4402. goto Cleanup;
  4403. }
  4404. //
  4405. // Actually add the property item
  4406. //
  4407. WinStatus = ObAddPropertyItem( GenericObject,
  4408. GenericObjectList,
  4409. 0, // No flags
  4410. &ObjectNameString );
  4411. if ( WinStatus != NO_ERROR ) {
  4412. goto Cleanup;
  4413. }
  4414. //
  4415. // Ensure the object was marked as needing to be written
  4416. //
  4417. ASSERT( GenericObject->DirtyBits != 0 );
  4418. ASSERT( (GenericObject->DirtyBits & ~AzGlObjectAllDirtyBits[ObjectType]) == 0);
  4419. //
  4420. // Free locally used resources
  4421. //
  4422. Cleanup:
  4423. if ( ReferencedObject != NULL ) {
  4424. ObDereferenceObject( ReferencedObject );
  4425. }
  4426. AzpFreeString( &ObjectNameString );
  4427. //
  4428. // Drop the global lock
  4429. //
  4430. AzpUnlockResource( &AzGlResource );
  4431. return WinStatus;
  4432. }
  4433. DWORD
  4434. ObRemovePropertyItem(
  4435. IN PGENERIC_OBJECT GenericObject,
  4436. IN PGENERIC_OBJECT_LIST GenericObjectList,
  4437. IN PAZP_STRING ObjectName
  4438. )
  4439. /*++
  4440. Routine Description:
  4441. Removes a generic object from the list of items specified by GenericObjectList
  4442. On entry, AzGlResource must be locked exclusive.
  4443. Arguments:
  4444. GenericObject - Specifies the object the link is from.
  4445. GenericObjectList - Specifies the obejct list to remote the object from.
  4446. ObjectName - Specifies a pointer to the name of the object to remove.
  4447. Return Value:
  4448. NO_ERROR - The operation was successful.
  4449. ERROR_NOT_FOUND - There is no object by that name in the list
  4450. --*/
  4451. {
  4452. DWORD WinStatus;
  4453. ULONG InsertionPoint;
  4454. ULONG DeltaFlags = 0;
  4455. GUID *DeltaGuid;
  4456. //
  4457. // Initialization
  4458. //
  4459. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  4460. //
  4461. // first things first, let's check version support write
  4462. //
  4463. if ( !AzpAzStoreVersionAllowWrite(GenericObject->AzStoreObject) )
  4464. {
  4465. WinStatus = ERROR_REVISION_MISMATCH;
  4466. goto Cleanup;
  4467. }
  4468. //
  4469. // Lookup that name in the object list
  4470. //
  4471. WinStatus = ObLookupPropertyItem( GenericObjectList,
  4472. ObjectName,
  4473. &InsertionPoint );
  4474. if ( WinStatus != ERROR_ALREADY_EXISTS ) {
  4475. goto Cleanup;
  4476. }
  4477. //
  4478. // Let the persist provider know of the change
  4479. //
  4480. if ( AzpIsSidList( GenericObjectList ) ) {
  4481. DeltaGuid = (GUID *)ObjectName;
  4482. DeltaFlags |= AZP_DELTA_SID;
  4483. } else {
  4484. DeltaGuid = &((PGENERIC_OBJECT)GenericObjectList->GenericObjects.Array[InsertionPoint])->PersistenceGuid;
  4485. }
  4486. WinStatus = ObAddDeltaToArray(
  4487. DeltaFlags,
  4488. DeltaGuid,
  4489. &GenericObjectList->DeltaArray,
  4490. FALSE ); // Allow deletion entries in the array
  4491. if ( WinStatus != NO_ERROR ) {
  4492. goto Cleanup;
  4493. }
  4494. //
  4495. // Remove the links in both directions
  4496. //
  4497. ObRemoveObjectListLink( GenericObject, GenericObjectList, InsertionPoint );
  4498. //
  4499. // Mark that the group membership caches need flushing
  4500. //
  4501. if ( GenericObject->ObjectType == OBJECT_TYPE_GROUP ) {
  4502. GenericObject->AzStoreObject->GroupEvalSerialNumber ++;
  4503. AzPrint(( AZD_ACCESS_MORE, "ObRemovePropertyItem: GroupEvalSerialNumber set to %ld\n",
  4504. GenericObject->AzStoreObject->GroupEvalSerialNumber ));
  4505. }
  4506. //
  4507. // Finally set the dirty bit
  4508. //
  4509. GenericObject->DirtyBits |= GenericObjectList->DirtyBit;
  4510. WinStatus = NO_ERROR;
  4511. //
  4512. // Return to the caller
  4513. //
  4514. Cleanup:
  4515. return WinStatus;
  4516. }
  4517. DWORD
  4518. WINAPI
  4519. AzRemovePropertyItem(
  4520. IN AZ_HANDLE AzHandle,
  4521. IN ULONG PropertyId,
  4522. IN DWORD Reserved,
  4523. IN PVOID PropertyValue
  4524. )
  4525. /*++
  4526. Routine Description:
  4527. Remove an item from the list of items specified by PropertyId.
  4528. Arguments:
  4529. AzHandle - Specifies a handle to the object to add a property item for
  4530. PropertyId - Specifies which property to modify
  4531. Reserved - Reserved. Must by zero.
  4532. PropertyValue - Specifies a pointer to item to remove.
  4533. The specified value and type depends on PropertyId.
  4534. Return Value:
  4535. NO_ERROR - The operation was successful
  4536. ERROR_INVALID_PARAMETER - PropertyId isn't valid
  4537. ERROR_NOT_FOUND - There is no item by that name in the list
  4538. --*/
  4539. {
  4540. DWORD WinStatus;
  4541. PGENERIC_OBJECT GenericObject = (PGENERIC_OBJECT) AzHandle;
  4542. PGENERIC_OBJECT ReferencedObject = NULL;
  4543. AZP_STRING ObjectNameString;
  4544. PGENERIC_OBJECT_LIST GenericObjectList;
  4545. ULONG ObjectType;
  4546. //
  4547. // Initialization
  4548. //
  4549. AzpInitString( &ObjectNameString, NULL );
  4550. //
  4551. // Grab the global lock
  4552. //
  4553. AzpLockResourceExclusive( &AzGlResource );
  4554. //
  4555. // Validate the input parameters
  4556. //
  4557. if ( Reserved != 0 ) {
  4558. AzPrint(( AZD_INVPARM, "AzRemovePropertyItem: Reserved != 0\n" ));
  4559. WinStatus = ERROR_INVALID_PARAMETER;
  4560. goto Cleanup;
  4561. }
  4562. //
  4563. // Validate the Property ID
  4564. //
  4565. WinStatus = ObMapPropIdToObjectList(
  4566. GenericObject,
  4567. PropertyId,
  4568. &GenericObjectList,
  4569. &ObjectType );
  4570. if ( WinStatus != NO_ERROR ) {
  4571. AzPrint(( AZD_INVPARM, "AzRemovePropertyItem: invalid prop id %ld\n", PropertyId ));
  4572. goto Cleanup;
  4573. }
  4574. //
  4575. // Validate the passed in handle
  4576. //
  4577. WinStatus = ObReferenceObjectByHandle( GenericObject,
  4578. FALSE, // Don't allow deleted objects
  4579. TRUE, // Refresh the cache
  4580. ObjectType );
  4581. if ( WinStatus != NO_ERROR ) {
  4582. goto Cleanup;
  4583. }
  4584. ReferencedObject = GenericObject;
  4585. //
  4586. // Capture the object name string from the caller
  4587. //
  4588. if ( AzpIsSidList( GenericObjectList ) ) {
  4589. WinStatus = AzpCaptureSid( &ObjectNameString,
  4590. PropertyValue );
  4591. } else {
  4592. WinStatus = AzpCaptureString( &ObjectNameString,
  4593. (LPWSTR)PropertyValue,
  4594. AZ_MAX_NAME_LENGTH, // Don't need to validate size exactly
  4595. FALSE ); // NULL names not OK
  4596. }
  4597. if ( WinStatus != NO_ERROR ) {
  4598. goto Cleanup;
  4599. }
  4600. //
  4601. // Remove the item from the list and backlist
  4602. //
  4603. WinStatus = ObRemovePropertyItem( GenericObject,
  4604. GenericObjectList,
  4605. &ObjectNameString );
  4606. if ( WinStatus != NO_ERROR ) {
  4607. goto Cleanup;
  4608. }
  4609. //
  4610. // Ensure the object was marked as needing to be written
  4611. //
  4612. ASSERT( GenericObject->DirtyBits != 0 );
  4613. ASSERT( (GenericObject->DirtyBits & ~AzGlObjectAllDirtyBits[ObjectType]) == 0);
  4614. //
  4615. // Free locally used resources
  4616. //
  4617. Cleanup:
  4618. if ( ReferencedObject != NULL ) {
  4619. ObDereferenceObject( ReferencedObject );
  4620. }
  4621. AzpFreeString( &ObjectNameString );
  4622. //
  4623. // Drop the global lock
  4624. //
  4625. AzpUnlockResource( &AzGlResource );
  4626. return WinStatus;
  4627. }
  4628. PAZ_STRING_ARRAY
  4629. ObGetPropertyItems(
  4630. IN PGENERIC_OBJECT_LIST GenericObjectList
  4631. )
  4632. /*++
  4633. Routine Description:
  4634. Return a list of generic object names as an array of object name strings.
  4635. On entry, AzGlResource must be locked shared
  4636. Arguments:
  4637. GenericObjectList - Specifies the object list to get the entries for.
  4638. Return Value:
  4639. Returns the array of object name strings in a single allocated buffer.
  4640. Free the buffer using AzFreeMemory.
  4641. NULL - Not enough memory was available to allocate the string
  4642. --*/
  4643. {
  4644. PAZP_PTR_ARRAY GenericObjects;
  4645. ULONG i;
  4646. ULONG Size;
  4647. LPBYTE Where;
  4648. PGENERIC_OBJECT GenericObject;
  4649. PAZ_STRING_ARRAY StringArray;
  4650. //
  4651. // Initialization
  4652. //
  4653. ASSERT( AzpIsLockedShared( &AzGlResource ) );
  4654. GenericObjects = &GenericObjectList->GenericObjects;
  4655. //
  4656. // Loop through the list of objects computing the size of the buffer to allocate
  4657. //
  4658. Size = 0;
  4659. for ( i=0; i<GenericObjects->UsedCount; i++ ) {
  4660. GenericObject = (PGENERIC_OBJECT) (GenericObjects->Array[i]);
  4661. Size += GenericObject->ObjectName->ObjectName.StringSize;
  4662. }
  4663. //
  4664. // Allocate a buffer to return to the caller
  4665. //
  4666. Size += sizeof(AZ_STRING_ARRAY) + (GenericObjects->UsedCount * sizeof(LPWSTR));
  4667. StringArray = (PAZ_STRING_ARRAY) AzpAllocateHeap( Size, "GEGETITM" );
  4668. if ( StringArray == NULL ) {
  4669. return NULL;
  4670. }
  4671. StringArray->StringCount = GenericObjects->UsedCount;
  4672. StringArray->Strings = (LPWSTR *)(StringArray+1);
  4673. Where = (LPBYTE)(&StringArray->Strings[GenericObjects->UsedCount]);
  4674. //
  4675. // Loop through the list of objects copying the names into the return buffer
  4676. //
  4677. for ( i=0; i<GenericObjects->UsedCount; i++ ) {
  4678. GenericObject = (PGENERIC_OBJECT) (GenericObjects->Array[i]);
  4679. StringArray->Strings[i] = (LPWSTR) Where;
  4680. RtlCopyMemory( Where,
  4681. GenericObject->ObjectName->ObjectName.String,
  4682. GenericObject->ObjectName->ObjectName.StringSize );
  4683. Where += GenericObject->ObjectName->ObjectName.StringSize;
  4684. }
  4685. ASSERT( (ULONG)(Where - (LPBYTE)StringArray) == Size );
  4686. return StringArray;
  4687. }
  4688. PAZ_GUID_ARRAY
  4689. ObGetPropertyItemGuids(
  4690. IN PGENERIC_OBJECT_LIST GenericObjectList
  4691. )
  4692. /*++
  4693. Routine Description:
  4694. Return a list of generic object guids as an array of object guids
  4695. On entry, AzGlResource must be locked shared
  4696. Arguments:
  4697. GenericObjectList - Specifies the object list to get the entries for.
  4698. Return Value:
  4699. Returns the array of object guids in a single allocated buffer.
  4700. Free the buffer using AzFreeMemory.
  4701. NULL - Not enough memory was available to allocate the string
  4702. --*/
  4703. {
  4704. PAZP_PTR_ARRAY GenericObjects;
  4705. ULONG i;
  4706. ULONG Size;
  4707. LPBYTE Where;
  4708. PGENERIC_OBJECT GenericObject;
  4709. PAZ_GUID_ARRAY GuidArray;
  4710. //
  4711. // Initialization
  4712. //
  4713. ASSERT( AzpIsLockedShared( &AzGlResource ) );
  4714. GenericObjects = &GenericObjectList->GenericObjects;
  4715. //
  4716. // calculate the size of single buffer
  4717. //
  4718. Size = sizeof(AZ_GUID_ARRAY) +
  4719. (GenericObjects->UsedCount * sizeof(GUID*)) +
  4720. GenericObjects->UsedCount * sizeof(GUID);
  4721. GuidArray = (PAZ_GUID_ARRAY) AzpAllocateHeap( Size, "GEGUIDAR" );
  4722. if ( GuidArray == NULL ) {
  4723. return NULL;
  4724. }
  4725. GuidArray->GuidCount = GenericObjects->UsedCount;
  4726. GuidArray->Guids = (GUID **)(GuidArray+1);
  4727. // point to memory location for guid data
  4728. Where = (LPBYTE)(&GuidArray->Guids[GenericObjects->UsedCount]);
  4729. //
  4730. // Loop through the list of objects copying the guids into the return buffer
  4731. //
  4732. for ( i=0; i<GenericObjects->UsedCount; i++ ) {
  4733. GenericObject = (PGENERIC_OBJECT) (GenericObjects->Array[i]);
  4734. GuidArray->Guids[i] = (GUID*) Where;
  4735. RtlCopyMemory( Where,
  4736. &GenericObject->PersistenceGuid,
  4737. sizeof(GUID) );
  4738. Where += sizeof(GUID);
  4739. }
  4740. ASSERT( (ULONG)(Where - (LPBYTE)GuidArray) == Size );
  4741. return GuidArray;
  4742. }
  4743. VOID
  4744. ObRemoveObjectListLinks(
  4745. IN PGENERIC_OBJECT GenericObject
  4746. )
  4747. /*++
  4748. Routine Description
  4749. Remove any links to/from the specified object.
  4750. On entry, AzGlResource must be locked exclusive.
  4751. Arguments
  4752. GenericObject - Specifies the object to remove links to/from
  4753. Return Value
  4754. None
  4755. --*/
  4756. {
  4757. PGENERIC_OBJECT_LIST GenericObjectList;
  4758. //
  4759. // Initialization
  4760. //
  4761. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  4762. //
  4763. // Walk all of the GenericObjectLists rooted on by this object
  4764. //
  4765. // The GenericObjectList may be forward links or backward links. We don't care.
  4766. // All links must be removed.
  4767. //
  4768. for ( GenericObjectList = GenericObject->GenericObjectLists;
  4769. GenericObjectList != NULL;
  4770. GenericObjectList = GenericObjectList->NextGenericObjectList ) {
  4771. AzPrint(( AZD_OBJLIST, "0x%lx: 0x%lx: %ld: ObRemoveObjectListLinks\n", &GenericObjectList->GenericObjects, GenericObjectList->GenericObjects.Array, GenericObjectList->GenericObjects.UsedCount ));
  4772. //
  4773. // Free the array itself
  4774. //
  4775. ObFreeObjectList( GenericObject, GenericObjectList );
  4776. }
  4777. }
  4778. VOID
  4779. ObFreeObjectList(
  4780. IN PGENERIC_OBJECT GenericObject,
  4781. IN OUT PGENERIC_OBJECT_LIST GenericObjectList
  4782. )
  4783. /*++
  4784. Routine Description:
  4785. Free any memory pointed to by an array of object name strings.
  4786. On entry, AzGlResource must be locked exclusive.
  4787. Arguments:
  4788. GenericObject - Specifies the obect containing GenericObjectList
  4789. GenericObjectList - Specifies the object list to free.
  4790. Return Value:
  4791. Returns the array of object name strings in a single allocated buffer.
  4792. Free the buffer using AzFreeMemory.
  4793. NULL - Not enough memory was available to allocate the string
  4794. --*/
  4795. {
  4796. PAZP_PTR_ARRAY GenericObjects;
  4797. ULONG Index;
  4798. //
  4799. // Initialization
  4800. //
  4801. AzPrint(( AZD_OBJLIST, "0x%lx: 0x%lx: ObFreeObjectList\n", &GenericObjectList->GenericObjects, GenericObjectList->GenericObjects.Array ));
  4802. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  4803. //
  4804. // Walk the list of links to other objects removing the link and removing the corresponding
  4805. // pointer back.
  4806. //
  4807. GenericObjects = &GenericObjectList->GenericObjects;
  4808. while ( GenericObjects->UsedCount != 0 ) {
  4809. //
  4810. // Remove the last entry in the list
  4811. //
  4812. Index = GenericObjects->UsedCount - 1;
  4813. //
  4814. // Remove the links in both directions
  4815. //
  4816. ObRemoveObjectListLink( GenericObject,
  4817. GenericObjectList,
  4818. Index );
  4819. }
  4820. //
  4821. // Free the actual array
  4822. //
  4823. if ( GenericObjects->Array != NULL ) {
  4824. AzPrint(( AZD_OBJLIST, "0x%lx: 0x%lx: Free array\n", GenericObjects, GenericObjects->Array ));
  4825. AzpFreeHeap( GenericObjects->Array );
  4826. GenericObjects->Array = NULL;
  4827. GenericObjects->AllocatedCount = 0;
  4828. }
  4829. //
  4830. // Free the delta array, too
  4831. //
  4832. ObFreeDeltaArray( &GenericObjectList->DeltaArray, TRUE );
  4833. }
  4834. DWORD
  4835. ObCheckNameConflict(
  4836. IN PGENERIC_OBJECT_HEAD GenericObjectHead,
  4837. IN PAZP_STRING ObjectNameString,
  4838. IN ULONG ConflictListOffset,
  4839. IN ULONG GrandchildListOffset,
  4840. IN ULONG GrandChildConflictListOffset
  4841. )
  4842. /*++
  4843. Routine Description:
  4844. This routine checks to see if there is a name conflict between the name specified and
  4845. the name of objects that are children of any of the objects in a list of objects.
  4846. Optionally, this routine will recurse to check grandchildren.
  4847. On entry, AzGlResource must be locked exclusive.
  4848. Arguments:
  4849. GenericObjectHead - Specifies the head of the list of objects that have children to be checked.
  4850. ObjectNameString - Specifies the name of the object to check.
  4851. ConflictListOffset - For each of the objects in GenericObjectHead, this is the offset to
  4852. the GENERIC_OBJECT_HEAD structure containing the list of objects to check for name conflict.
  4853. GrandchildListOffset - For each of the objects in GenericObjectHead, this is the offst to
  4854. the GENERIC_OBJECT_HEAD structure containing the list of objects that contain grandchild
  4855. objects to check.
  4856. GrandChildConflictListOffset - For each of the objects in the list specified by GrandchildListOffset,
  4857. this is the offset to the GENERIC_OBJECT_HEAD structure containing the list of objects to
  4858. check for name conflict.
  4859. Return Value:
  4860. NO_ERROR - The operation was successful
  4861. ERROR_ALREADY_EXISTS - An object by that name already exists
  4862. --*/
  4863. {
  4864. DWORD WinStatus;
  4865. PGENERIC_OBJECT GenericObject;
  4866. PLIST_ENTRY ListEntry;
  4867. PGENERIC_OBJECT ConflictGenericObject;
  4868. //
  4869. // Initialization
  4870. //
  4871. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  4872. //
  4873. // Loop through each object in the list
  4874. //
  4875. for ( ListEntry = GenericObjectHead->Head.Flink ;
  4876. ListEntry != &GenericObjectHead->Head ;
  4877. ListEntry = ListEntry->Flink) {
  4878. GenericObject = CONTAINING_RECORD( ListEntry,
  4879. GENERIC_OBJECT,
  4880. Next );
  4881. //
  4882. // Ignore deleted objects
  4883. //
  4884. if ( GenericObject->Flags & GENOBJ_FLAGS_DELETED ) {
  4885. continue;
  4886. }
  4887. //
  4888. // Check all children to make sure there is no name conflict
  4889. //
  4890. WinStatus = ObReferenceObjectByName(
  4891. (PGENERIC_OBJECT_HEAD)( ((LPBYTE)GenericObject) + ConflictListOffset ),
  4892. ObjectNameString,
  4893. 0, // No special flags
  4894. &ConflictGenericObject );
  4895. if ( WinStatus == NO_ERROR ) {
  4896. ObDereferenceObject( ConflictGenericObject );
  4897. return ERROR_ALREADY_EXISTS;
  4898. }
  4899. //
  4900. // If we're to check grandchildren,
  4901. // do so now.
  4902. //
  4903. if ( GrandchildListOffset != 0 ) {
  4904. WinStatus = ObCheckNameConflict(
  4905. (PGENERIC_OBJECT_HEAD)( ((LPBYTE)GenericObject) + GrandchildListOffset ),
  4906. ObjectNameString,
  4907. GrandChildConflictListOffset,
  4908. 0,
  4909. 0 );
  4910. if ( WinStatus != NO_ERROR ) {
  4911. return WinStatus;
  4912. }
  4913. }
  4914. }
  4915. return NO_ERROR;
  4916. }
  4917. DWORD
  4918. ObMapPropIdToObjectList(
  4919. IN PGENERIC_OBJECT GenericObject,
  4920. IN ULONG PropertyId,
  4921. OUT PGENERIC_OBJECT_LIST *GenericObjectList,
  4922. OUT PULONG ObjectType
  4923. )
  4924. /*++
  4925. Routine Description:
  4926. Map a property ID to the object type that it pertains to and the
  4927. generic object list containing the linked to objects
  4928. Arguments:
  4929. GenericObject - Specifies the object being linked from.
  4930. This parameter is used only to compute GenericObjectList. It may simply be
  4931. an unverified handle passed by the app.
  4932. PropertyId - Specifies which property to map
  4933. GenericObjectList - On success, returns the address of the generic object list
  4934. within GenericObject to link the objects to.
  4935. ObjectType - On success, returns the object type that PropertyId pertains to.
  4936. Return Value:
  4937. NO_ERROR - The operation was successful
  4938. ERROR_INVALID_PARAMETER - PropertyId doesn't correspond to a linked property
  4939. --*/
  4940. {
  4941. // get object type
  4942. __try {
  4943. *ObjectType = GenericObject->ObjectType;
  4944. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  4945. return RtlNtStatusToDosError( GetExceptionCode());
  4946. }
  4947. //
  4948. // Validate the Property ID
  4949. //
  4950. switch ( PropertyId ) {
  4951. case AZ_PROP_GROUP_APP_MEMBERS:
  4952. *GenericObjectList = &((PAZP_GROUP)GenericObject)->AppMembers;
  4953. ASSERT(*ObjectType == OBJECT_TYPE_GROUP);
  4954. break;
  4955. case AZ_PROP_GROUP_APP_NON_MEMBERS:
  4956. *GenericObjectList = &((PAZP_GROUP)GenericObject)->AppNonMembers;
  4957. ASSERT(*ObjectType == OBJECT_TYPE_GROUP);
  4958. break;
  4959. case AZ_PROP_GROUP_MEMBERS:
  4960. *GenericObjectList = &((PAZP_GROUP)GenericObject)->SidMembers;
  4961. ASSERT(*ObjectType == OBJECT_TYPE_GROUP);
  4962. break;
  4963. case AZ_PROP_GROUP_NON_MEMBERS:
  4964. *GenericObjectList = &((PAZP_GROUP)GenericObject)->SidNonMembers;
  4965. ASSERT(*ObjectType == OBJECT_TYPE_GROUP);
  4966. break;
  4967. case AZ_PROP_TASK_OPERATIONS:
  4968. *GenericObjectList = &((PAZP_TASK)GenericObject)->Operations;
  4969. ASSERT(*ObjectType == OBJECT_TYPE_TASK);
  4970. break;
  4971. case AZ_PROP_TASK_TASKS:
  4972. *GenericObjectList = &((PAZP_TASK)GenericObject)->Tasks;
  4973. ASSERT(*ObjectType == OBJECT_TYPE_TASK);
  4974. break;
  4975. case AZ_PROP_ROLE_APP_MEMBERS:
  4976. *GenericObjectList = &((PAZP_ROLE)GenericObject)->AppMembers;
  4977. ASSERT(*ObjectType == OBJECT_TYPE_ROLE);
  4978. break;
  4979. case AZ_PROP_ROLE_MEMBERS:
  4980. *GenericObjectList = &((PAZP_ROLE)GenericObject)->SidMembers;
  4981. ASSERT(*ObjectType == OBJECT_TYPE_ROLE);
  4982. break;
  4983. case AZ_PROP_ROLE_OPERATIONS:
  4984. *GenericObjectList = &((PAZP_ROLE)GenericObject)->Operations;
  4985. ASSERT(*ObjectType == OBJECT_TYPE_ROLE);
  4986. break;
  4987. case AZ_PROP_ROLE_TASKS:
  4988. *GenericObjectList = &((PAZP_ROLE)GenericObject)->Tasks;
  4989. ASSERT(*ObjectType == OBJECT_TYPE_ROLE);
  4990. break;
  4991. case AZ_PROP_POLICY_ADMINS:
  4992. *GenericObjectList = &(GenericObject)->PolicyAdmins;
  4993. break;
  4994. case AZ_PROP_POLICY_READERS:
  4995. *GenericObjectList = &(GenericObject)->PolicyReaders;
  4996. break;
  4997. case AZ_PROP_DELEGATED_POLICY_USERS:
  4998. *GenericObjectList = &(GenericObject)->DelegatedPolicyUsers;
  4999. break;
  5000. default:
  5001. return ERROR_INVALID_PARAMETER;
  5002. }
  5003. return NO_ERROR;
  5004. }
  5005. BOOLEAN
  5006. ObAllocateNewName(
  5007. IN PGENERIC_OBJECT GenericObject,
  5008. IN PAZP_STRING ObjectName
  5009. )
  5010. /*++
  5011. Routine Description
  5012. Allocates the structure describing the new name of a generic object.
  5013. On entry, PersistCritSect must be locked.
  5014. Arguments
  5015. GenericObject - Pointer to the GenericObject being renamed
  5016. ObjectName - New name of the object
  5017. Return Value
  5018. TRUE - New name has been properly allocated and linked
  5019. FALSE - not enough memory
  5020. --*/
  5021. {
  5022. PNEW_OBJECT_NAME NewObjectName = NULL;
  5023. PAZP_AZSTORE AzAuthorizationStore = GenericObject->AzStoreObject;
  5024. //
  5025. // Initialization
  5026. //
  5027. ASSERT( AzpIsCritsectLocked( &AzAuthorizationStore->PersistCritSect ) );
  5028. //
  5029. // Allocate memory for the new of the object name.
  5030. //
  5031. NewObjectName = (PNEW_OBJECT_NAME) AzpAllocateHeap( sizeof(NEW_OBJECT_NAME) + ObjectName->StringSize, "GENAME" );
  5032. if ( NewObjectName == NULL ) {
  5033. return FALSE;
  5034. }
  5035. //
  5036. // Reference the renamed object
  5037. // The reference count really doesn't need to be incremented since we *know*
  5038. // that AzpPersistReconcile won't delete the object, but ...
  5039. //
  5040. NewObjectName->GenericObject = GenericObject;
  5041. InterlockedIncrement( &GenericObject->ReferenceCount );
  5042. AzpDumpGoRef( "Reference from NewName", GenericObject );
  5043. //
  5044. // Initialize the name
  5045. //
  5046. NewObjectName->ObjectName = *ObjectName;
  5047. NewObjectName->ObjectName.String = (LPWSTR)(NewObjectName+1);
  5048. RtlCopyMemory( &NewObjectName->ObjectName.String,
  5049. ObjectName->String,
  5050. ObjectName->StringSize );
  5051. //
  5052. // Link the structure onto the authorization store where AzpReconcile can find it
  5053. //
  5054. InsertHeadList( &AzAuthorizationStore->NewNames, &NewObjectName->Next );
  5055. return TRUE;
  5056. }
  5057. VOID
  5058. ObFreeNewName(
  5059. IN PNEW_OBJECT_NAME NewObjectName
  5060. )
  5061. /*++
  5062. Routine Description
  5063. Free the structure describing the new name of a generic object.
  5064. On entry, PersistCritSect must be locked.
  5065. Arguments
  5066. NewObjectName - Pointer to the structure to free
  5067. Return Value
  5068. None
  5069. --*/
  5070. {
  5071. //
  5072. // Initialization
  5073. //
  5074. ASSERT( AzpIsCritsectLocked( &NewObjectName->GenericObject->AzStoreObject->PersistCritSect ) );
  5075. //
  5076. // Dereference the renamed object
  5077. //
  5078. ObDereferenceObject( NewObjectName->GenericObject );
  5079. //
  5080. // Remove the entry from the list on the authorization store object
  5081. //
  5082. RemoveEntryList( &NewObjectName->Next );
  5083. //
  5084. // Finally, free the structure
  5085. //
  5086. AzpFreeHeap( NewObjectName );
  5087. }