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

3637 lines
90 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. //
  14. // Table of sizes of the specific objects
  15. //
  16. DWORD SpecificObjectSize[OBJECT_TYPE_MAXIMUM] = {
  17. 0, // OBJECT_TYPE_ROOT
  18. sizeof(AZP_ADMIN_MANAGER), // OBJECT_TYPE_ADMIN_MANAGER
  19. sizeof(AZP_APPLICATION), // OBJECT_TYPE_APPLICATION
  20. sizeof(AZP_OPERATION), // OBJECT_TYPE_OPERATION
  21. sizeof(AZP_TASK), // OBJECT_TYPE_TASK
  22. sizeof(AZP_SCOPE), // OBJECT_TYPE_SCOPE
  23. sizeof(AZP_GROUP), // OBJECT_TYPE_GROUP
  24. sizeof(AZP_ROLE), // OBJECT_TYPE_ROLE
  25. sizeof(AZP_JUNCTION_POINT), // OBJECT_TYPE_JUNCTION_POINT
  26. sizeof(AZP_SID), // OBJECT_TYPE_SID
  27. sizeof(AZP_CLIENT_CONTEXT), // OBJECT_TYPE_CLIENT_CONTEXT
  28. };
  29. //
  30. // Maximum length of the object name
  31. //
  32. DWORD MaxObjectNameLength[OBJECT_TYPE_MAXIMUM] = {
  33. 0, // OBJECT_TYPE_ROOT
  34. 0, // OBJECT_TYPE_ADMIN_MANAGER
  35. AZ_MAX_APPLICATION_NAME_LENGTH,
  36. AZ_MAX_OPERATION_NAME_LENGTH,
  37. AZ_MAX_TASK_NAME_LENGTH,
  38. AZ_MAX_SCOPE_NAME_LENGTH,
  39. AZ_MAX_GROUP_NAME_LENGTH,
  40. AZ_MAX_ROLE_NAME_LENGTH,
  41. AZ_MAX_JUNCTION_POINT_NAME_LENGTH,
  42. 0, // OBJECT_TYPE_SID
  43. 0, // OBJECT_TYPE_CLIENT_CONTEXT
  44. };
  45. //
  46. // Table of object init routines
  47. //
  48. // Specifies a routine to call to initialize the object type specific fields
  49. // when adding a generic object.
  50. //
  51. OBJECT_INIT_ROUTINE *ObjectInitRoutine[OBJECT_TYPE_MAXIMUM] = {
  52. NULL, // OBJECT_TYPE_ROOT
  53. &AzpAdminManagerInit, // OBJECT_TYPE_ADMIN_MANAGER
  54. &AzpApplicationInit, // OBJECT_TYPE_APPLICATION
  55. &AzpOperationInit, // OBJECT_TYPE_OPERATION
  56. &AzpTaskInit, // OBJECT_TYPE_TASK
  57. &AzpScopeInit, // OBJECT_TYPE_SCOPE
  58. &AzpGroupInit, // OBJECT_TYPE_GROUP
  59. &AzpRoleInit, // OBJECT_TYPE_ROLE
  60. &AzpJunctionPointInit, // OBJECT_TYPE_JUNCTION_POINT
  61. &AzpSidInit, // OBJECT_TYPE_SID
  62. &AzpClientContextInit, // OBJECT_TYPE_CLIENT_CONTEXT
  63. };
  64. //
  65. // Table of object free routines
  66. //
  67. // Specifies a routine to call to free the object type specific fields
  68. // when freeing a generic object.
  69. //
  70. OBJECT_FREE_ROUTINE *ObjectFreeRoutine[OBJECT_TYPE_MAXIMUM] = {
  71. NULL, // OBJECT_TYPE_ROOT
  72. &AzpAdminManagerFree, // OBJECT_TYPE_ADMIN_MANAGER
  73. &AzpApplicationFree, // OBJECT_TYPE_APPLICATION
  74. &AzpOperationFree, // OBJECT_TYPE_OPERATION
  75. &AzpTaskFree, // OBJECT_TYPE_TASK
  76. &AzpScopeFree, // OBJECT_TYPE_SCOPE
  77. &AzpGroupFree, // OBJECT_TYPE_GROUP
  78. &AzpRoleFree, // OBJECT_TYPE_ROLE
  79. &AzpJunctionPointFree, // OBJECT_TYPE_JUNCTION_POINT
  80. &AzpSidFree, // OBJECT_TYPE_SID
  81. &AzpClientContextFree, // OBJECT_TYPE_CLIENT_CONTEXT
  82. };
  83. //
  84. // Table of object specific GetProperty routines
  85. //
  86. // Specifies a routine to call to get object type specific fields
  87. // when querying a generic object.
  88. //
  89. // NULL means there are no object specific fields.
  90. //
  91. OBJECT_GET_PROPERTY_ROUTINE *ObjectGetPropertyRoutine[OBJECT_TYPE_MAXIMUM] = {
  92. NULL, // OBJECT_TYPE_ROOT
  93. NULL, // OBJECT_TYPE_ADMIN_MANAGER
  94. NULL, // OBJECT_TYPE_APPLICATION
  95. &AzpOperationGetProperty, // OBJECT_TYPE_OPERATION
  96. &AzpTaskGetProperty, // OBJECT_TYPE_TASK
  97. NULL, // OBJECT_TYPE_SCOPE
  98. &AzpGroupGetProperty, // OBJECT_TYPE_GROUP
  99. &AzpRoleGetProperty, // OBJECT_TYPE_ROLE
  100. &AzpJunctionPointGetProperty, // OBJECT_TYPE_JUNCTION_POINT
  101. NULL, // OBJECT_TYPE_SID
  102. NULL, // OBJECT_TYPE_CLIENT_CONTEXT
  103. };
  104. //
  105. // Table of object specific SetProperty routines
  106. //
  107. // Specifies a routine to call to set object type specific fields
  108. // when modifying a generic object.
  109. //
  110. // NULL means there are no object specific fields.
  111. //
  112. OBJECT_SET_PROPERTY_ROUTINE *ObjectSetPropertyRoutine[OBJECT_TYPE_MAXIMUM] = {
  113. NULL, // OBJECT_TYPE_ROOT
  114. NULL, // OBJECT_TYPE_ADMIN_MANAGER
  115. NULL, // OBJECT_TYPE_APPLICATION
  116. &AzpOperationSetProperty, // OBJECT_TYPE_OPERATION
  117. &AzpTaskSetProperty, // OBJECT_TYPE_TASK
  118. NULL, // OBJECT_TYPE_SCOPE
  119. &AzpGroupSetProperty, // OBJECT_TYPE_GROUP
  120. NULL, // OBJECT_TYPE_ROLE
  121. &AzpJunctionPointSetProperty, // OBJECT_TYPE_JUNCTION_POINT
  122. NULL, // OBJECT_TYPE_SID
  123. NULL, // OBJECT_TYPE_CLIENT_CONTEXT
  124. };
  125. //
  126. // Table of object specific AddPropertyItem routines
  127. //
  128. // Specifies a routine to call to add property type specific fields.
  129. //
  130. // NULL means there is no object specific action to take
  131. //
  132. OBJECT_ADD_PROPERTY_ITEM_ROUTINE *ObjectAddPropertyItemRoutine[OBJECT_TYPE_MAXIMUM] = {
  133. NULL, // OBJECT_TYPE_ROOT
  134. NULL, // OBJECT_TYPE_ADMIN_MANAGER
  135. NULL, // OBJECT_TYPE_APPLICATION
  136. NULL, // OBJECT_TYPE_OPERATION
  137. NULL, // OBJECT_TYPE_TASK
  138. NULL, // OBJECT_TYPE_SCOPE
  139. &AzpGroupAddPropertyItem, // OBJECT_TYPE_GROUP
  140. NULL, // OBJECT_TYPE_ROLE
  141. &AzpJunctionPointAddPropertyItem, // OBJECT_TYPE_JUNCTION_POINT
  142. NULL, // OBJECT_TYPE_SID
  143. NULL, // OBJECT_TYPE_CLIENT_CONTEXT
  144. };
  145. VOID
  146. ObInitGenericHead(
  147. IN PGENERIC_OBJECT_HEAD GenericObjectHead,
  148. IN ULONG ObjectType,
  149. IN PGENERIC_OBJECT ParentGenericObject,
  150. IN PGENERIC_OBJECT_HEAD SiblingGenericObjectHead OPTIONAL,
  151. IN PGENERIC_OBJECT_HEAD SharedNamespace OPTIONAL
  152. )
  153. /*++
  154. Routine Description
  155. Initialize the head of a list of generic objects
  156. On entry, AzGlResource must be locked exclusive.
  157. Arguments
  158. GenericObjectHead - Specifies the list head to initialize
  159. ObjectType - Specifies the type of objects in the list
  160. ParentGenericObject - Specifies a back link to parent generic object
  161. that host the object head being initialized.
  162. SiblingGenericObjectHead - Specifies a pointer to an object head that
  163. is a sibling of the one being initialized.
  164. SharedNamespace - Specifies a pointer to an object head that shares
  165. a namespace with the objects in the list being initialized.
  166. The structure pointed to by SharedNamespace must already be initialized.
  167. Return Value
  168. None
  169. --*/
  170. {
  171. //
  172. // Initialization
  173. //
  174. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  175. //
  176. // Initialize the linked list
  177. //
  178. InitializeListHead( &GenericObjectHead->Head );
  179. //
  180. // Initialize the sequence number
  181. // Start at 1 since a zero EnumerationContext means beginning of list.
  182. //
  183. GenericObjectHead->NextSequenceNumber = 1;
  184. //
  185. // Initialize the list of shared namespaces
  186. //
  187. if ( SharedNamespace == NULL ) {
  188. InitializeListHead( &GenericObjectHead->SharedNamespace );
  189. } else {
  190. InsertHeadList( &SharedNamespace->SharedNamespace, &GenericObjectHead->SharedNamespace );
  191. }
  192. //
  193. // Store the ObjectType
  194. //
  195. GenericObjectHead->ObjectType = ObjectType;
  196. //
  197. // Store the back pointer to the parent generic object
  198. //
  199. GenericObjectHead->ParentGenericObject = ParentGenericObject;
  200. //
  201. // Store the link to the next Generic head
  202. //
  203. GenericObjectHead->SiblingGenericObjectHead = SiblingGenericObjectHead;
  204. }
  205. VOID
  206. ObFreeGenericHead(
  207. IN PGENERIC_OBJECT_HEAD GenericObjectHead
  208. )
  209. /*++
  210. Routine Description
  211. Free any ojects on a generic head structure
  212. On entry, AzGlResource must be locked exclusive.
  213. Arguments
  214. GenericObjectHead - Specifies the list head to free
  215. Return Value
  216. None
  217. --*/
  218. {
  219. PLIST_ENTRY ListEntry;
  220. PGENERIC_OBJECT GenericObject;
  221. //
  222. // Initialization
  223. //
  224. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  225. //
  226. // Walk the list of child objects dereferencing each.
  227. //
  228. while ( !IsListEmpty( &GenericObjectHead->Head ) ) {
  229. //
  230. // Remove the entry from the list
  231. //
  232. ListEntry = RemoveHeadList( &GenericObjectHead->Head );
  233. GenericObject = CONTAINING_RECORD( ListEntry,
  234. GENERIC_OBJECT,
  235. Next );
  236. ObDereferenceObject( GenericObject );
  237. }
  238. //
  239. // Remove ourselves from the shared namespace list
  240. //
  241. RemoveEntryList( &GenericObjectHead->SharedNamespace );
  242. }
  243. PGENERIC_OBJECT
  244. ObAllocateGenericObject(
  245. IN ULONG ObjectType,
  246. IN PAZP_STRING ObjectName
  247. )
  248. /*++
  249. Routine Description
  250. Allocate memory for the private object structure of the specified type
  251. Arguments
  252. ObjectType - Specifies the type of object to create
  253. ObjectName - Name of the object
  254. Return Value
  255. Returns a pointer to the allocated object. The caller should dereference the
  256. returned object by calling ObDereferenceObject.
  257. NULL: not enough memory
  258. --*/
  259. {
  260. ULONG WinStatus;
  261. PGENERIC_OBJECT GenericObject;
  262. ULONG BaseSize;
  263. //
  264. // Ensure the object is supported
  265. //
  266. if ( ObjectType > OBJECT_TYPE_MAXIMUM ||
  267. SpecificObjectSize[ObjectType] == 0 ) {
  268. ASSERT( ObjectType <= OBJECT_TYPE_MAXIMUM );
  269. ASSERT( SpecificObjectSize[ObjectType] != 0 );
  270. return NULL;
  271. }
  272. BaseSize = SpecificObjectSize[ObjectType];
  273. ASSERT( BaseSize >= sizeof(GENERIC_OBJECT) );
  274. //
  275. // Allocate the memory
  276. //
  277. GenericObject = (PGENERIC_OBJECT) AzpAllocateHeap( BaseSize );
  278. if ( GenericObject == NULL ) {
  279. return NULL;
  280. }
  281. //
  282. // Initialize it
  283. //
  284. RtlZeroMemory( GenericObject, BaseSize );
  285. InitializeListHead( &GenericObject->Next );
  286. GenericObject->ObjectType = ObjectType;
  287. GenericObject->ReferenceCount = 1;
  288. AzPrint(( AZD_REF, "0x%lx %ld (%ld): Allocate object\n", GenericObject, GenericObject->ObjectType, GenericObject->ReferenceCount ));
  289. //
  290. // Initialize the string name
  291. //
  292. WinStatus = AzpDuplicateString( &GenericObject->ObjectName, ObjectName );
  293. if ( WinStatus != NO_ERROR ) {
  294. AzpFreeHeap( GenericObject );
  295. GenericObject = NULL;
  296. }
  297. return GenericObject;
  298. }
  299. VOID
  300. ObFreeGenericObject(
  301. IN PGENERIC_OBJECT GenericObject,
  302. IN BOOLEAN JustRefresh
  303. )
  304. /*++
  305. Routine Description
  306. Free memory for the private object structure of the specified type
  307. On entry, AzGlResource must be locked exclusive.
  308. Arguments
  309. GenericObject - Specifies the pointer to the generic object to free
  310. JustRefresh - TRUE if only those attributes that can be refreshed from the
  311. policy store are to be freed.
  312. FALSE if all attributes are to be freed.
  313. Return Value
  314. None.
  315. --*/
  316. {
  317. PGENERIC_OBJECT_HEAD ChildGenericObjectHead;
  318. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  319. if ( !JustRefresh ) {
  320. ASSERT( GenericObject->HandleReferenceCount == 0 );
  321. ASSERT( GenericObject->ReferenceCount == 0 );
  322. }
  323. //
  324. // Delink the entry from the parent
  325. //
  326. if ( !JustRefresh ) {
  327. RemoveEntryList( &GenericObject->Next );
  328. }
  329. //
  330. // Call the routine to do object type specific freeing
  331. //
  332. if ( ObjectFreeRoutine[GenericObject->ObjectType] == NULL ) {
  333. ASSERT( ObjectFreeRoutine[GenericObject->ObjectType] != NULL );
  334. } else {
  335. ObjectFreeRoutine[GenericObject->ObjectType](GenericObject );
  336. }
  337. //
  338. // Free children of this object
  339. // Loop for each type of child
  340. //
  341. if ( !JustRefresh ) {
  342. for ( ChildGenericObjectHead = GenericObject->ChildGenericObjectHead;
  343. ChildGenericObjectHead != NULL;
  344. ChildGenericObjectHead = ChildGenericObjectHead->SiblingGenericObjectHead ) {
  345. ObFreeGenericHead( ChildGenericObjectHead );
  346. }
  347. }
  348. //
  349. // Remove all references to/from this object
  350. // If we're just refreshing, only remove the forward links
  351. //
  352. ObRemoveObjectListLinks( GenericObject, !JustRefresh );
  353. //
  354. // Free the fields
  355. // Leave the name on 'JustRefresh' to support lookups by name.
  356. //
  357. if ( !JustRefresh ) {
  358. AzpFreeString( &GenericObject->ObjectName );
  359. }
  360. AzpFreeString( &GenericObject->Description );
  361. //
  362. // Free the object itself
  363. //
  364. if ( !JustRefresh ) {
  365. AzpFreeHeap( GenericObject );
  366. }
  367. }
  368. VOID
  369. ObInsertGenericObject(
  370. IN PGENERIC_OBJECT_HEAD ParentGenericObjectHead,
  371. IN PGENERIC_OBJECT ChildGenericObject
  372. )
  373. /*++
  374. Routine Description
  375. Insert the specified object into the specified list.
  376. On entry, AzGlResource must be locked exclusive.
  377. Arguments
  378. ParentGenericObjectHead - Specifies the list head of the list to insert into
  379. ChildGenericObject - Specifies the object to insert into the list
  380. Return Value
  381. None
  382. --*/
  383. {
  384. //
  385. // Initialization
  386. //
  387. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  388. //
  389. // Set the sequence number
  390. //
  391. ChildGenericObject->SequenceNumber = ParentGenericObjectHead->NextSequenceNumber;
  392. ParentGenericObjectHead->NextSequenceNumber ++;
  393. //
  394. // Insert the object
  395. // Insert at the tail to keep the list in sequence number order.
  396. //
  397. ASSERT( ParentGenericObjectHead->ObjectType == ChildGenericObject->ObjectType );
  398. InsertTailList( &ParentGenericObjectHead->Head, &ChildGenericObject->Next );
  399. //
  400. // Provide a back link
  401. //
  402. ASSERT( ChildGenericObject->ParentGenericObjectHead == NULL );
  403. ChildGenericObject->ParentGenericObjectHead = ParentGenericObjectHead;
  404. //
  405. // Increment the reference count to ensure the object isn't deleted
  406. //
  407. InterlockedIncrement( &ChildGenericObject->ReferenceCount );
  408. AzPrint(( AZD_REF, "0x%lx %ld (%ld): Insert object\n", ChildGenericObject, ChildGenericObject->ObjectType, ChildGenericObject->ReferenceCount ));
  409. }
  410. VOID
  411. ObIncrHandleRefCount(
  412. IN PGENERIC_OBJECT GenericObject
  413. )
  414. /*++
  415. Routine Description
  416. Increment the "handle" reference count on an object.
  417. On entry, AzGlResource must be locked shared.
  418. Arguments
  419. GenericObject - Specifies the object to insert into the list
  420. Return Value
  421. None
  422. --*/
  423. {
  424. //
  425. // Initialization
  426. //
  427. ASSERT( AzpIsLockedShared( &AzGlResource ) );
  428. //
  429. // Keep a reference to our parent object.
  430. // We validate the handle by inspecting walking the list of children in our parent.
  431. // So, prevent our parent from being deleted as long as the user has a handle to the child.
  432. //
  433. if ( GenericObject->ParentGenericObjectHead->ParentGenericObject != NULL ) {
  434. InterlockedIncrement ( &GenericObject->ParentGenericObjectHead->ParentGenericObject->ReferenceCount );
  435. AzPrint(( AZD_REF, "0x%lx %ld (%ld): Child handle ref\n", GenericObject->ParentGenericObjectHead->ParentGenericObject, GenericObject->ParentGenericObjectHead->ParentGenericObject->ObjectType, GenericObject->ParentGenericObjectHead->ParentGenericObject->ReferenceCount ));
  436. }
  437. //
  438. // The handle ref count is a real ref count. Increment it too.
  439. //
  440. InterlockedIncrement( &GenericObject->ReferenceCount );
  441. AzPrint(( AZD_REF, "0x%lx %ld (%ld): Handle ref\n", GenericObject, GenericObject->ObjectType, GenericObject->ReferenceCount ));
  442. //
  443. // Increment the handle ref count
  444. //
  445. InterlockedIncrement( &GenericObject->HandleReferenceCount );
  446. AzPrint(( AZD_HANDLE, "0x%lx %ld (%ld): Open Handle\n", GenericObject, GenericObject->ObjectType, GenericObject->HandleReferenceCount ));
  447. //
  448. // Increment the total handle reference count on the entire tree of objects
  449. //
  450. InterlockedIncrement( &GenericObject->AdminManagerObject->TotalHandleReferenceCount );
  451. }
  452. VOID
  453. ObDecrHandleRefCount(
  454. IN PGENERIC_OBJECT GenericObject
  455. )
  456. /*++
  457. Routine Description
  458. Decrement the "handle" reference count on an object.
  459. On entry, AzGlResource must be locked shared.
  460. Arguments
  461. GenericObject - Specifies the object to insert into the list
  462. Return Value
  463. None
  464. --*/
  465. {
  466. //
  467. // Initialization
  468. //
  469. ASSERT( AzpIsLockedShared( &AzGlResource ) );
  470. //
  471. // Decrement the handle ref count
  472. //
  473. InterlockedDecrement( &GenericObject->HandleReferenceCount );
  474. AzPrint(( AZD_HANDLE, "0x%lx %ld (%ld): Close Handle\n", GenericObject, GenericObject->ObjectType, GenericObject->HandleReferenceCount ));
  475. //
  476. // Decrement the total handle reference count on the entire tree of objects
  477. //
  478. InterlockedDecrement( &GenericObject->AdminManagerObject->TotalHandleReferenceCount );
  479. //
  480. // The handle ref count is a real ref count. Decrement it too.
  481. //
  482. ObDereferenceObject( GenericObject );
  483. //
  484. // Finally, decrement the ref count we have on our parent.
  485. //
  486. if ( GenericObject->ParentGenericObjectHead->ParentGenericObject != NULL ) {
  487. ObDereferenceObject( GenericObject->ParentGenericObjectHead->ParentGenericObject );
  488. }
  489. }
  490. DWORD
  491. ObGetHandleType(
  492. IN PGENERIC_OBJECT Handle,
  493. IN BOOL AllowDeletedObjects,
  494. OUT PULONG ObjectType
  495. )
  496. /*++
  497. Routine Description
  498. This routine takes a handle passed by an application and safely determines what the
  499. handle type is.
  500. This routine allows a caller to support various handle types rather than being
  501. limited to one.
  502. Arguments
  503. Handle - Handle to check
  504. AllowDeletedObjects - TRUE if it is OK to use a handle to a deleted object
  505. ObjectType - Returns the type of object the handle represents
  506. Return Value
  507. NO_ERROR - the handle is OK
  508. ERROR_INVALID_HANDLE - the handle isn't OK
  509. --*/
  510. {
  511. DWORD WinStatus;
  512. PGENERIC_OBJECT GenericObject = Handle;
  513. //
  514. // Initialization
  515. //
  516. if ( Handle == NULL ) {
  517. AzPrint(( AZD_HANDLE, "0x%lx: NULL handle is invalid\n", Handle ));
  518. return ERROR_INVALID_HANDLE;
  519. }
  520. //
  521. // Use a try/except since we're touching memory assuming the handle is valid
  522. //
  523. WinStatus = NO_ERROR;
  524. __try {
  525. //
  526. // Sanity check the scalar values on the object
  527. //
  528. if ( GenericObject->ObjectType >= OBJECT_TYPE_MAXIMUM ) {
  529. AzPrint(( AZD_HANDLE, "0x%lx %ld: Handle Object type is too large.\n", GenericObject, GenericObject->ObjectType ));
  530. WinStatus = ERROR_INVALID_HANDLE;
  531. } else if ( GenericObject->HandleReferenceCount <= 0 ) {
  532. AzPrint(( AZD_HANDLE, "0x%lx %ld: Handle has no handle reference count.\n", GenericObject, GenericObject->ObjectType ));
  533. WinStatus = ERROR_INVALID_HANDLE;
  534. } else if ( GenericObject->ParentGenericObjectHead == NULL ) {
  535. AzPrint(( AZD_HANDLE, "0x%lx %ld: Handle has no ParentGenericObjectHead.\n", GenericObject, GenericObject->ObjectType ));
  536. WinStatus = ERROR_INVALID_HANDLE;
  537. } else if ( !AllowDeletedObjects &&
  538. (GenericObject->Flags & GENOBJ_FLAGS_DELETED) != 0 ) {
  539. AzPrint(( AZD_HANDLE, "0x%lx %ld: Object is deleted.\n", GenericObject, GenericObject->ObjectType ));
  540. WinStatus = ERROR_INVALID_HANDLE;
  541. } else {
  542. PGENERIC_OBJECT_HEAD ParentGenericObjectHead = GenericObject->ParentGenericObjectHead;
  543. //
  544. // Sanity check the object with its head
  545. //
  546. if ( ParentGenericObjectHead->ObjectType != GenericObject->ObjectType ) {
  547. AzPrint(( AZD_HANDLE, "0x%lx %ld: Object type doesn't match parent.\n", GenericObject, GenericObject->ObjectType ));
  548. WinStatus = ERROR_INVALID_HANDLE;
  549. } else if ( GenericObject->SequenceNumber >= ParentGenericObjectHead->NextSequenceNumber ) {
  550. AzPrint(( AZD_HANDLE, "0x%lx %ld: Sequence number doesn't match parent.\n", GenericObject, GenericObject->ObjectType ));
  551. WinStatus = ERROR_INVALID_HANDLE;
  552. } else {
  553. *ObjectType = GenericObject->ObjectType;
  554. }
  555. }
  556. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  557. AzPrint(( AZD_HANDLE, "0x%lx: AV accessing handle\n", GenericObject ));
  558. WinStatus = ERROR_INVALID_HANDLE;
  559. }
  560. return WinStatus;
  561. }
  562. DWORD
  563. ObReferenceObjectByName(
  564. IN PGENERIC_OBJECT_HEAD GenericObjectHead,
  565. IN PAZP_STRING ObjectName,
  566. IN BOOLEAN RefreshCache,
  567. OUT PGENERIC_OBJECT *RetGenericObject
  568. )
  569. /*++
  570. Routine Description
  571. This routine finds an object by the specified name.
  572. On entry, AzGlResource must be locked shared.
  573. Arguments
  574. GenericObjectHead - Head of the list of objects to check
  575. ObjectName - Object Name of the object to look for
  576. RefreshCache - If TRUE, the returned object has its cache entry refreshed from
  577. the policy database if needed.
  578. If FALSE, the entry is returned unrefreshed.
  579. RetGenericObject - On success, returns a pointer to the object
  580. The returned pointer must be dereferenced using ObDereferenceObject.
  581. Return Value
  582. NO_ERROR: The object was returned
  583. ERROR_NOT_FOUND: The object could not be found
  584. Others: The object could not be refreshed
  585. --*/
  586. {
  587. DWORD WinStatus;
  588. PGENERIC_OBJECT GenericObject;
  589. PLIST_ENTRY ListEntry;
  590. //
  591. // Initialization
  592. //
  593. ASSERT( AzpIsLockedShared( &AzGlResource ) );
  594. *RetGenericObject = NULL;
  595. //
  596. // Loop trying to find the named object
  597. //
  598. for ( ListEntry = GenericObjectHead->Head.Flink ;
  599. ListEntry != &GenericObjectHead->Head ;
  600. ListEntry = ListEntry->Flink) {
  601. GenericObject = CONTAINING_RECORD( ListEntry,
  602. GENERIC_OBJECT,
  603. Next );
  604. //
  605. // Ignore deleted objects
  606. //
  607. if ( GenericObject->Flags & GENOBJ_FLAGS_DELETED ) {
  608. continue;
  609. }
  610. //
  611. // If we found the object,
  612. // grab a reference.
  613. //
  614. if ( AzpEqualStrings( &GenericObject->ObjectName, ObjectName ) ) {
  615. //
  616. // If the caller wants the object to be refreshed,
  617. // do so now.
  618. //
  619. if ( RefreshCache &&
  620. (GenericObject->Flags & GENOBJ_FLAGS_REFRESH_ME) != 0 ) {
  621. //
  622. // Need exclusive access
  623. //
  624. AzpLockResourceSharedToExclusive( &AzGlResource );
  625. WinStatus = AzpPersistRefresh( GenericObject );
  626. if ( WinStatus != NO_ERROR ) {
  627. return WinStatus;
  628. }
  629. }
  630. //
  631. // Return the object to the caller
  632. //
  633. InterlockedIncrement( &GenericObject->ReferenceCount );
  634. AzPrint(( AZD_REF, "0x%lx %ld (%ld): Ref by name\n", GenericObject, GenericObject->ObjectType, GenericObject->ReferenceCount ));
  635. *RetGenericObject = GenericObject;
  636. return NO_ERROR;
  637. }
  638. }
  639. return ERROR_NOT_FOUND;
  640. }
  641. DWORD
  642. ObReferenceObjectByHandle(
  643. IN PGENERIC_OBJECT Handle,
  644. IN BOOL AllowDeletedObjects,
  645. IN BOOLEAN RefreshCache,
  646. IN ULONG ObjectType
  647. )
  648. /*++
  649. Routine Description
  650. This routine takes a handle passed by an application and safely determines whether
  651. it is a valid handle. If so, this routine increments the reference count on the
  652. handle to prevent the handle from being closed.
  653. On entry, AzGlResource must be locked shared.
  654. Arguments
  655. Handle - Handle to check
  656. AllowDeletedObjects - TRUE if it is OK to use a handle to a deleted object
  657. RefreshCache - If TRUE, the returned object has its cache entry refreshed from
  658. the policy database if needed.
  659. If FALSE, the entry is returned unrefreshed.
  660. ObjectType - Specifies the type of object the caller expects the handle to be
  661. Return Value
  662. NO_ERROR - the handle is OK
  663. ERROR_INVALID_HANDLE - the handle isn't OK
  664. --*/
  665. {
  666. DWORD WinStatus;
  667. PGENERIC_OBJECT GenericObject = Handle;
  668. ULONG LocalObjectType;
  669. PGENERIC_OBJECT Current;
  670. PLIST_ENTRY ListEntry;
  671. //
  672. // Initialization
  673. //
  674. ASSERT( AzpIsLockedShared( &AzGlResource ) );
  675. if ( Handle == NULL ) {
  676. AzPrint(( AZD_HANDLE, "0x%lx: NULL handle not allowed.\n", NULL ));
  677. return ERROR_INVALID_HANDLE;
  678. }
  679. //
  680. // Use a try/except since we're touching memory assuming the handle is valid
  681. //
  682. __try {
  683. WinStatus = ObGetHandleType( Handle, AllowDeletedObjects, &LocalObjectType );
  684. if ( WinStatus == NO_ERROR ) {
  685. if ( ObjectType != LocalObjectType ) {
  686. AzPrint(( AZD_HANDLE, "0x%lx %ld: Object Type not local object type\n", GenericObject, GenericObject->ObjectType ));
  687. WinStatus = ERROR_INVALID_HANDLE;
  688. } else {
  689. PGENERIC_OBJECT_HEAD ParentGenericObjectHead = GenericObject->ParentGenericObjectHead;
  690. //
  691. // Ensure the object is actually in the list
  692. //
  693. WinStatus = ERROR_INVALID_HANDLE;
  694. for ( ListEntry = ParentGenericObjectHead->Head.Flink ;
  695. ListEntry != &ParentGenericObjectHead->Head ;
  696. ListEntry = ListEntry->Flink) {
  697. Current = CONTAINING_RECORD( ListEntry,
  698. GENERIC_OBJECT,
  699. Next );
  700. //
  701. // If we found the object,
  702. // grab a reference.
  703. //
  704. if ( Current == GenericObject ) {
  705. //
  706. // If the caller wants the object to be refreshed,
  707. // do so now.
  708. //
  709. if ( RefreshCache &&
  710. (GenericObject->Flags & GENOBJ_FLAGS_REFRESH_ME) != 0 ) {
  711. //
  712. // Need exclusive access
  713. //
  714. AzpLockResourceSharedToExclusive( &AzGlResource );
  715. WinStatus = AzpPersistRefresh( GenericObject );
  716. if ( WinStatus != NO_ERROR ) {
  717. break;
  718. }
  719. }
  720. //
  721. // Grab a reference to the object
  722. //
  723. InterlockedIncrement( &GenericObject->ReferenceCount );
  724. AzPrint(( AZD_REF, "0x%lx %ld (%ld): Ref by Handle\n", GenericObject, GenericObject->ObjectType, GenericObject->ReferenceCount ));
  725. WinStatus = NO_ERROR;
  726. break;
  727. }
  728. }
  729. //
  730. // If not,
  731. // the handle is invalid.
  732. //
  733. if ( WinStatus == ERROR_INVALID_HANDLE ) {
  734. AzPrint(( AZD_HANDLE, "0x%lx %ld: Handle not in list.\n", GenericObject, GenericObject->ObjectType ));
  735. }
  736. }
  737. }
  738. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  739. AzPrint(( AZD_HANDLE, "0x%lx: AV accessing handle\n", GenericObject ));
  740. WinStatus = ERROR_INVALID_HANDLE;
  741. }
  742. return WinStatus;
  743. }
  744. VOID
  745. ObDereferenceObject(
  746. IN PGENERIC_OBJECT GenericObject
  747. )
  748. /*++
  749. Routine Description
  750. Decrement the reference count on an object.
  751. When the last reference count is removed, delete the object.
  752. On entry, AzGlResource must be locked shared. If the ref count reaches zero,
  753. AzGlResource must be locked exclusively. We can get away with that because
  754. we force the ref count to zero only when closing the AdminManager object.
  755. Arguments
  756. GenericObject - Specifies the object to insert into the list
  757. Return Value
  758. None
  759. --*/
  760. {
  761. ULONG RefCount;
  762. //
  763. // Initialization
  764. //
  765. ASSERT( AzpIsLockedShared( &AzGlResource ) );
  766. //
  767. // Decrement the reference count
  768. //
  769. RefCount = InterlockedDecrement( &GenericObject->ReferenceCount );
  770. AzPrint(( AZD_REF, "0x%lx %ld (%ld): Deref\n", GenericObject, GenericObject->ObjectType, GenericObject->ReferenceCount ));
  771. //
  772. // Check if the object is no longer referenced
  773. //
  774. if ( RefCount == 0 ) {
  775. //
  776. // Grab the lock exclusively
  777. //
  778. ASSERT( GenericObject->HandleReferenceCount == 0 );
  779. AzpLockResourceSharedToExclusive( &AzGlResource );
  780. //
  781. // Free the object itself
  782. //
  783. ObFreeGenericObject( GenericObject, FALSE );
  784. }
  785. }
  786. DWORD
  787. ObCreateObject(
  788. IN PGENERIC_OBJECT ParentGenericObject,
  789. IN PGENERIC_OBJECT_HEAD GenericChildHead,
  790. IN ULONG ChildObjectType,
  791. IN PAZP_STRING ChildObjectNameString,
  792. OUT PGENERIC_OBJECT *RetChildGenericObject
  793. )
  794. /*++
  795. Routine Description:
  796. This routine creates a child object in the scope of the specified parent object.
  797. On entry, AzGlResource must be locked exclusive.
  798. Arguments:
  799. ParentGenericObject - Specifies the parent object to add the child object onto.
  800. be verified.
  801. GenericChildHead - Specifies a pointer to the head of the list of children of
  802. ParentGenericObject.
  803. ChildObjectType - Specifies the object type RetChildGenericObject.
  804. ChildObjectNameString - Specifies the name of the child object.
  805. This name must be unique at the current scope.
  806. RetChildGenericObject - Returns a pointer to the allocated generic child object
  807. This pointer must be dereferenced using ObDereferenceObject.
  808. Return Value:
  809. NO_ERROR - The operation was successful
  810. ERROR_ALREADY_EXISTS - An object by that name already exists
  811. --*/
  812. {
  813. DWORD WinStatus;
  814. PGENERIC_OBJECT_HEAD CurrentObjectHead;
  815. PGENERIC_OBJECT ChildGenericObject = NULL;
  816. //
  817. // Initialization
  818. //
  819. ASSERT( ChildObjectType != OBJECT_TYPE_ROOT );
  820. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  821. //
  822. // Do duplicate detection
  823. //
  824. // Loop through all of the lists that share a namespace
  825. //
  826. CurrentObjectHead = GenericChildHead;
  827. for (;;) {
  828. PLIST_ENTRY ListEntry;
  829. //
  830. // Ensure the new name doesn't exist in the current list
  831. //
  832. WinStatus = ObReferenceObjectByName( CurrentObjectHead,
  833. ChildObjectNameString,
  834. FALSE, // No need to refresh the cache
  835. &ChildGenericObject );
  836. if ( WinStatus == NO_ERROR ) {
  837. WinStatus = ERROR_ALREADY_EXISTS;
  838. goto Cleanup;
  839. }
  840. //
  841. // If we've tried all of the lists,
  842. // we're done.
  843. //
  844. ListEntry = CurrentObjectHead->SharedNamespace.Flink;
  845. CurrentObjectHead = CONTAINING_RECORD( ListEntry,
  846. GENERIC_OBJECT_HEAD,
  847. SharedNamespace );
  848. if ( CurrentObjectHead == GenericChildHead ) {
  849. break;
  850. }
  851. }
  852. //
  853. // Allocate the structure to return to the caller
  854. //
  855. ChildGenericObject = ObAllocateGenericObject( ChildObjectType, ChildObjectNameString );
  856. if ( ChildGenericObject == NULL ) {
  857. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  858. goto Cleanup;
  859. }
  860. //
  861. // Keep a pointer to the object at the root of the tree
  862. // Back pointers don't increment reference count.
  863. //
  864. if ( ChildObjectType == OBJECT_TYPE_ADMIN_MANAGER ) {
  865. ChildGenericObject->AdminManagerObject = (PAZP_ADMIN_MANAGER) ChildGenericObject;
  866. } else {
  867. ChildGenericObject->AdminManagerObject = (PAZP_ADMIN_MANAGER)
  868. ParentGenericObject->AdminManagerObject;
  869. }
  870. //
  871. // Call the routine to do object type specific initialization
  872. //
  873. if ( ObjectInitRoutine[ChildObjectType] == NULL ) {
  874. ASSERT( ObjectInitRoutine[ChildObjectType] != NULL );
  875. WinStatus = ERROR_INVALID_PARAMETER;
  876. goto Cleanup;
  877. }
  878. WinStatus = ObjectInitRoutine[ChildObjectType](
  879. ParentGenericObject,
  880. ChildGenericObject );
  881. if ( WinStatus != NO_ERROR ) {
  882. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  883. goto Cleanup;
  884. }
  885. //
  886. // Insert the child into the list of children for this parent
  887. //
  888. ObInsertGenericObject( GenericChildHead, ChildGenericObject );
  889. //
  890. // Return the pointer to the new structure
  891. //
  892. *RetChildGenericObject = ChildGenericObject;
  893. WinStatus = NO_ERROR;
  894. //
  895. // Free locally used resources
  896. //
  897. Cleanup:
  898. if ( WinStatus != NO_ERROR && ChildGenericObject != NULL ) {
  899. ObDereferenceObject( ChildGenericObject );
  900. }
  901. return WinStatus;
  902. }
  903. DWORD
  904. ObCommonCreateObject(
  905. IN PGENERIC_OBJECT ParentGenericObject,
  906. IN ULONG ParentObjectType,
  907. IN PGENERIC_OBJECT_HEAD GenericChildHead,
  908. IN ULONG ChildObjectType,
  909. IN LPCWSTR ChildObjectName,
  910. IN DWORD Reserved,
  911. OUT PGENERIC_OBJECT *RetChildGenericObject
  912. )
  913. /*++
  914. Routine Description:
  915. This routine creates a child object in the scope of the specified parent object.
  916. Arguments:
  917. ParentGenericObject - Specifies a handle to the parent object to add the child
  918. object onto. This "handle" has been passed from the application and needs to
  919. be verified.
  920. ParentObjectType - Specifies the object type ParentGenericObject.
  921. GenericChildHead - Specifies a pointer to the head of the list of children of
  922. ParentGenericObject. This is a computed pointer and is considered untrustworthy
  923. until ParentGenericObject has been verified.
  924. ChildObjectType - Specifies the object type RetChildGenericObject.
  925. ChildObjectName - Specifies the name of the child object.
  926. This name must be unique at the current scope.
  927. This name is passed from the application and needs to be verified.
  928. Reserved - Reserved. Must by zero.
  929. RetChildGenericObject - Return a handle to the generic child object
  930. The caller must close this handle by calling AzCloseHandle.
  931. Return Value:
  932. NO_ERROR - The operation was successful
  933. ERROR_ALREADY_EXISTS - An object by that name already exists
  934. --*/
  935. {
  936. DWORD WinStatus;
  937. PGENERIC_OBJECT ReferencedParentObject = NULL;
  938. PGENERIC_OBJECT ChildGenericObject = NULL;
  939. AZP_STRING ChildObjectNameString;
  940. //
  941. // Grab the global lock
  942. //
  943. ASSERT( ParentObjectType != OBJECT_TYPE_ROOT );
  944. ASSERT( ChildObjectType != OBJECT_TYPE_ADMIN_MANAGER );
  945. AzpLockResourceExclusive( &AzGlResource );
  946. AzpInitString( &ChildObjectNameString, NULL );
  947. //
  948. // Initialization
  949. //
  950. __try {
  951. *RetChildGenericObject = NULL;
  952. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  953. WinStatus = RtlNtStatusToDosError( GetExceptionCode());
  954. goto Cleanup;
  955. }
  956. //
  957. // Validate the input parameters
  958. //
  959. if ( Reserved != 0 ) {
  960. AzPrint(( AZD_INVPARM, "ObCommonCreateObject: Reserved != 0\n" ));
  961. WinStatus = ERROR_INVALID_PARAMETER;
  962. goto Cleanup;
  963. }
  964. //
  965. // Validate the passed in handle
  966. //
  967. WinStatus = ObReferenceObjectByHandle( ParentGenericObject,
  968. FALSE, // Don't allow deleted objects
  969. TRUE, // Refresh the cache
  970. ParentObjectType );
  971. if ( WinStatus != NO_ERROR ) {
  972. goto Cleanup;
  973. }
  974. ReferencedParentObject = ParentGenericObject;
  975. //
  976. // Capture the object name string from the caller
  977. //
  978. WinStatus = AzpCaptureString( &ChildObjectNameString,
  979. ChildObjectName,
  980. MaxObjectNameLength[ChildObjectType],
  981. FALSE ); // NULL names not OK
  982. if ( WinStatus != NO_ERROR ) {
  983. goto Cleanup;
  984. }
  985. //
  986. // Create the object
  987. //
  988. WinStatus = ObCreateObject(
  989. ParentGenericObject,
  990. GenericChildHead,
  991. ChildObjectType,
  992. &ChildObjectNameString,
  993. &ChildGenericObject );
  994. if ( WinStatus != NO_ERROR ) {
  995. goto Cleanup;
  996. }
  997. //
  998. // Mark the object as needing to be written
  999. //
  1000. ChildGenericObject->Flags |= GENOBJ_FLAGS_DIRTY;
  1001. //
  1002. // Return the handle to the caller
  1003. //
  1004. ObIncrHandleRefCount( ChildGenericObject );
  1005. *RetChildGenericObject = ChildGenericObject;
  1006. WinStatus = NO_ERROR;
  1007. //
  1008. // Free locally used resources
  1009. //
  1010. Cleanup:
  1011. if ( ReferencedParentObject != NULL ) {
  1012. ObDereferenceObject( ReferencedParentObject );
  1013. }
  1014. if ( ChildGenericObject != NULL ) {
  1015. ObDereferenceObject( ChildGenericObject );
  1016. }
  1017. AzpFreeString( &ChildObjectNameString );
  1018. //
  1019. // Drop the global lock
  1020. //
  1021. AzpUnlockResource( &AzGlResource );
  1022. return WinStatus;
  1023. }
  1024. DWORD
  1025. ObCommonOpenObject(
  1026. IN PGENERIC_OBJECT ParentGenericObject,
  1027. IN ULONG ParentObjectType,
  1028. IN PGENERIC_OBJECT_HEAD GenericChildHead,
  1029. IN ULONG ChildObjectType,
  1030. IN LPCWSTR ChildObjectName,
  1031. IN DWORD Reserved,
  1032. OUT PGENERIC_OBJECT *RetChildGenericObject
  1033. )
  1034. /*++
  1035. Routine Description:
  1036. This routine opens a child object in the scope of the specified parent object.
  1037. Arguments:
  1038. ParentGenericObject - Specifies a handle to the parent object to open the child
  1039. object from. This "handle" has been passed from the application and needs to
  1040. be verified.
  1041. ParentObjectType - Specifies the object type ParentGenericObject.
  1042. GenericChildHead - Specifies a pointer to the head of the list of children of
  1043. ParentGenericObject. This is a computed pointer and is considered untrustworthy
  1044. until ParentGenericObject has been verified.
  1045. ChildObjectType - Specifies the object type RetChildGenericObject.
  1046. ChildObjectName - Specifies the name of the child object.
  1047. This name is passed from the application and needs to be verified.
  1048. Reserved - Reserved. Must by zero.
  1049. RetChildGenericObject - Return a handle to the generic child object
  1050. The caller must close this handle by calling AzCloseHandle.
  1051. Return Value:
  1052. NO_ERROR - The operation was successful
  1053. ERROR_NOT_FOUND - There is no object by that name
  1054. --*/
  1055. {
  1056. DWORD WinStatus;
  1057. PGENERIC_OBJECT ReferencedParentObject = NULL;
  1058. PGENERIC_OBJECT ChildGenericObject = NULL;
  1059. AZP_STRING ChildObjectNameString;
  1060. //
  1061. // Grab the global lock
  1062. //
  1063. AzpLockResourceShared( &AzGlResource );
  1064. ASSERT( ParentObjectType != OBJECT_TYPE_ROOT );
  1065. ASSERT( ChildObjectType != OBJECT_TYPE_ADMIN_MANAGER );
  1066. //
  1067. // Initialization
  1068. //
  1069. AzpInitString( &ChildObjectNameString, NULL );
  1070. __try {
  1071. *RetChildGenericObject = NULL;
  1072. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  1073. WinStatus = RtlNtStatusToDosError( GetExceptionCode());
  1074. goto Cleanup;
  1075. }
  1076. //
  1077. // Validate the input parameters
  1078. //
  1079. if ( Reserved != 0 ) {
  1080. AzPrint(( AZD_INVPARM, "ObCommonOpenObject: Reserved != 0\n" ));
  1081. WinStatus = ERROR_INVALID_PARAMETER;
  1082. goto Cleanup;
  1083. }
  1084. //
  1085. // Validate the passed in handle
  1086. //
  1087. WinStatus = ObReferenceObjectByHandle( ParentGenericObject,
  1088. FALSE, // Don't allow deleted objects
  1089. TRUE, // Refresh the cache
  1090. ParentObjectType );
  1091. if ( WinStatus != NO_ERROR ) {
  1092. goto Cleanup;
  1093. }
  1094. ReferencedParentObject = ParentGenericObject;
  1095. //
  1096. // Capture the object name string from the caller
  1097. //
  1098. WinStatus = AzpCaptureString( &ChildObjectNameString,
  1099. ChildObjectName,
  1100. MaxObjectNameLength[ChildObjectType],
  1101. FALSE ); // NULL names not OK
  1102. if ( WinStatus != NO_ERROR ) {
  1103. goto Cleanup;
  1104. }
  1105. //
  1106. // Find the named object
  1107. //
  1108. WinStatus = ObReferenceObjectByName( GenericChildHead,
  1109. &ChildObjectNameString,
  1110. TRUE, // Refresh the cache for this object
  1111. &ChildGenericObject );
  1112. if ( WinStatus != NO_ERROR ) {
  1113. goto Cleanup;
  1114. }
  1115. //
  1116. // Return the handle to the caller
  1117. //
  1118. ObIncrHandleRefCount( ChildGenericObject );
  1119. *RetChildGenericObject = ChildGenericObject;
  1120. WinStatus = NO_ERROR;
  1121. //
  1122. // Free locally used resources
  1123. //
  1124. Cleanup:
  1125. if ( ReferencedParentObject != NULL ) {
  1126. ObDereferenceObject( ReferencedParentObject );
  1127. }
  1128. if ( ChildGenericObject != NULL ) {
  1129. ObDereferenceObject( ChildGenericObject );
  1130. }
  1131. AzpFreeString( &ChildObjectNameString );
  1132. //
  1133. // Drop the global lock
  1134. //
  1135. AzpUnlockResource( &AzGlResource );
  1136. return WinStatus;
  1137. }
  1138. DWORD
  1139. ObEnumObjects(
  1140. IN PGENERIC_OBJECT_HEAD GenericChildHead,
  1141. IN BOOL EnumerateDeletedObjects,
  1142. IN BOOL RefreshCache,
  1143. IN OUT PULONG EnumerationContext,
  1144. OUT PGENERIC_OBJECT *RetChildGenericObject
  1145. )
  1146. /*++
  1147. Routine Description:
  1148. This routine enumerates the next child object from the scope of the specified parent object.
  1149. On entry, AzGlResource must be locked shared.
  1150. Arguments:
  1151. GenericChildHead - Specifies a pointer to the head of the list of children of
  1152. ParentGenericObject.
  1153. EnumerateDeletedObjects - Specifies whether deleted objects are to be returned
  1154. in the enumeration.
  1155. RefreshCache - If TRUE, the returned object has its cache entry refreshed from
  1156. the policy database if needed.
  1157. If FALSE, the entry is returned unrefreshed.
  1158. EnumerationContext - Specifies a context indicating the next object to return
  1159. On input for the first call, should point to zero.
  1160. On input for subsequent calls, should point to the value returned on the previous call.
  1161. On output, returns a value to be passed on the next call.
  1162. RetChildGenericObject - Returns a pointer to the generic child object
  1163. Return Value:
  1164. NO_ERROR - The operation was successful (a handle was returned)
  1165. ERROR_NO_MORE_ITEMS - No more items were available for enumeration
  1166. --*/
  1167. {
  1168. DWORD WinStatus;
  1169. PLIST_ENTRY ListEntry;
  1170. PGENERIC_OBJECT ChildGenericObject = NULL;
  1171. //
  1172. // If we've already returned the whole list,
  1173. // don't bother walking the list.
  1174. //
  1175. ASSERT( AzpIsLockedShared( &AzGlResource ) );
  1176. if ( *EnumerationContext >= GenericChildHead->NextSequenceNumber ) {
  1177. WinStatus = ERROR_NO_MORE_ITEMS;
  1178. goto Cleanup;
  1179. }
  1180. //
  1181. // Walk the list of children finding where we left off
  1182. //
  1183. for ( ListEntry = GenericChildHead->Head.Flink ;
  1184. ListEntry != &GenericChildHead->Head ;
  1185. ListEntry = ListEntry->Flink) {
  1186. ChildGenericObject = CONTAINING_RECORD( ListEntry,
  1187. GENERIC_OBJECT,
  1188. Next );
  1189. //
  1190. // See if this is it
  1191. //
  1192. if ( ChildGenericObject->SequenceNumber > *EnumerationContext ) {
  1193. //
  1194. // Ignore deleted object if the caller doesn't want to see them
  1195. //
  1196. // If this is not a deleted object,
  1197. // or the caller wants deleted objects to be returned,
  1198. // return it.
  1199. //
  1200. if ((ChildGenericObject->Flags & GENOBJ_FLAGS_DELETED) == 0 ||
  1201. EnumerateDeletedObjects ) {
  1202. break;
  1203. }
  1204. }
  1205. ChildGenericObject = NULL;
  1206. }
  1207. //
  1208. // If we've already returned the whole list,
  1209. // indicate so.
  1210. //
  1211. if ( ChildGenericObject == NULL ) {
  1212. WinStatus = ERROR_NO_MORE_ITEMS;
  1213. goto Cleanup;
  1214. }
  1215. //
  1216. // If the caller wants the object to be refreshed,
  1217. // do so now.
  1218. //
  1219. if ( RefreshCache &&
  1220. (ChildGenericObject->Flags & GENOBJ_FLAGS_REFRESH_ME) != 0 ) {
  1221. //
  1222. // Need exclusive access
  1223. //
  1224. AzpLockResourceSharedToExclusive( &AzGlResource );
  1225. WinStatus = AzpPersistRefresh( ChildGenericObject );
  1226. if ( WinStatus != NO_ERROR ) {
  1227. goto Cleanup;
  1228. }
  1229. }
  1230. //
  1231. // Return the handle to the caller
  1232. //
  1233. *EnumerationContext = ChildGenericObject->SequenceNumber;
  1234. *RetChildGenericObject = ChildGenericObject;
  1235. WinStatus = NO_ERROR;
  1236. //
  1237. // Free locally used resources
  1238. //
  1239. Cleanup:
  1240. return WinStatus;
  1241. }
  1242. DWORD
  1243. ObCommonEnumObjects(
  1244. IN PGENERIC_OBJECT ParentGenericObject,
  1245. IN ULONG ParentObjectType,
  1246. IN PGENERIC_OBJECT_HEAD GenericChildHead,
  1247. IN OUT PULONG EnumerationContext,
  1248. IN DWORD Reserved,
  1249. OUT PGENERIC_OBJECT *RetChildGenericObject
  1250. )
  1251. /*++
  1252. Routine Description:
  1253. This routine enumerates the next child object from the scope of the specified parent object.
  1254. Arguments:
  1255. ParentGenericObject - Specifies a handle to the parent object to enumerate the child
  1256. objects of.
  1257. This "handle" has been passed from the application and needs to be verified.
  1258. ParentObjectType - Specifies the object type ParentGenericObject.
  1259. GenericChildHead - Specifies a pointer to the head of the list of children of
  1260. ParentGenericObject. This is a computed pointer and is considered untrustworthy
  1261. until ParentGenericObject has been verified.
  1262. EnumerationContext - Specifies a context indicating the next object to return
  1263. On input for the first call, should point to zero.
  1264. On input for subsequent calls, should point to the value returned on the previous call.
  1265. On output, returns a value to be passed on the next call.
  1266. Reserved - Reserved. Must by zero.
  1267. RetChildGenericObject - Returns a handle to the generic child object
  1268. The caller must close this handle by calling AzpDzCloseHandle.
  1269. Return Value:
  1270. NO_ERROR - The operation was successful (a handle was returned)
  1271. ERROR_NO_MORE_ITEMS - No more items were available for enumeration
  1272. --*/
  1273. {
  1274. DWORD WinStatus;
  1275. PGENERIC_OBJECT ReferencedParentObject = NULL;
  1276. PGENERIC_OBJECT ChildGenericObject = NULL;
  1277. //
  1278. // Grab the global lock
  1279. //
  1280. ASSERT( ParentObjectType != OBJECT_TYPE_ROOT );
  1281. AzpLockResourceShared( &AzGlResource );
  1282. //
  1283. // Initialize the return handle
  1284. //
  1285. __try {
  1286. *RetChildGenericObject = NULL;
  1287. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  1288. WinStatus = RtlNtStatusToDosError( GetExceptionCode());
  1289. goto Cleanup;
  1290. }
  1291. //
  1292. // Validate the input parameters
  1293. //
  1294. if ( Reserved != 0 ) {
  1295. AzPrint(( AZD_INVPARM, "ObCommonEnumObjects: Reserved != 0\n" ));
  1296. WinStatus = ERROR_INVALID_PARAMETER;
  1297. goto Cleanup;
  1298. }
  1299. //
  1300. // Validate the passed in handle
  1301. //
  1302. WinStatus = ObReferenceObjectByHandle( ParentGenericObject,
  1303. FALSE, // Don't allow deleted objects
  1304. TRUE, // Refresh the cache
  1305. ParentObjectType );
  1306. if ( WinStatus != NO_ERROR ) {
  1307. goto Cleanup;
  1308. }
  1309. ReferencedParentObject = ParentGenericObject;
  1310. //
  1311. // Call the common routine to do the actual enumeration
  1312. //
  1313. WinStatus = ObEnumObjects( GenericChildHead,
  1314. FALSE, // Don't enumerate deleted objects
  1315. TRUE, // Refresh the cache
  1316. EnumerationContext,
  1317. &ChildGenericObject );
  1318. if ( WinStatus != NO_ERROR ) {
  1319. goto Cleanup;
  1320. }
  1321. //
  1322. // Return the handle to the caller
  1323. //
  1324. ObIncrHandleRefCount( ChildGenericObject );
  1325. *RetChildGenericObject = ChildGenericObject;
  1326. WinStatus = NO_ERROR;
  1327. //
  1328. // Free locally used resources
  1329. //
  1330. Cleanup:
  1331. if ( ReferencedParentObject != NULL ) {
  1332. ObDereferenceObject( ReferencedParentObject );
  1333. }
  1334. //
  1335. // Drop the global lock
  1336. //
  1337. AzpUnlockResource( &AzGlResource );
  1338. return WinStatus;
  1339. }
  1340. DWORD
  1341. ObCommonGetProperty(
  1342. IN PGENERIC_OBJECT GenericObject,
  1343. IN ULONG ObjectType,
  1344. IN ULONG PropertyId,
  1345. IN DWORD Reserved,
  1346. OUT PVOID *PropertyValue
  1347. )
  1348. /*++
  1349. Routine Description:
  1350. Returns the specified property for a generic object.
  1351. Arguments:
  1352. GenericObject - Specifies a handle to the object to get the property from.
  1353. This "handle" has been passed from the application and needs to be verified.
  1354. ObjectType - Specifies the expected object type GenericObject.
  1355. PropertyId - Specifies which property to return.
  1356. Reserved - Reserved. Must by zero.
  1357. PropertyValue - Specifies a pointer to return the property in.
  1358. The returned pointer must be freed using AzFreeMemory.
  1359. The returned value and type depends in PropertyId. The valid values are:
  1360. AZ_PROP_NAME LPWSTR - Object name of the object
  1361. AZ_PROP_DESCRIPTION LPWSTR - Description of the object
  1362. Any object specific properties.
  1363. Return Value:
  1364. NO_ERROR - The operation was successful
  1365. ERROR_INVALID_PARAMETER - PropertyId isn't valid
  1366. --*/
  1367. {
  1368. DWORD WinStatus;
  1369. PGENERIC_OBJECT ReferencedGenericObject = NULL;
  1370. //
  1371. // Grab the global lock
  1372. //
  1373. AzpLockResourceShared( &AzGlResource );
  1374. //
  1375. // Initialize the return value
  1376. //
  1377. __try {
  1378. *PropertyValue = NULL;
  1379. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  1380. WinStatus = RtlNtStatusToDosError( GetExceptionCode());
  1381. goto Cleanup;
  1382. }
  1383. //
  1384. // Validate the input parameters
  1385. //
  1386. if ( Reserved != 0 ) {
  1387. AzPrint(( AZD_INVPARM, "ObCommonGetProperty: Reserved != 0\n" ));
  1388. WinStatus = ERROR_INVALID_PARAMETER;
  1389. goto Cleanup;
  1390. }
  1391. //
  1392. // Validate the passed in handle
  1393. //
  1394. WinStatus = ObReferenceObjectByHandle( GenericObject,
  1395. FALSE, // Don't allow deleted objects
  1396. TRUE, // Refresh the cache
  1397. ObjectType );
  1398. if ( WinStatus != NO_ERROR ) {
  1399. goto Cleanup;
  1400. }
  1401. ReferencedGenericObject = GenericObject;
  1402. //
  1403. // Return any common attribute
  1404. //
  1405. // Return object name to the caller
  1406. //
  1407. switch ( PropertyId ) {
  1408. case AZ_PROP_NAME:
  1409. *PropertyValue = AzpGetStringProperty( &GenericObject->ObjectName );
  1410. if ( *PropertyValue == NULL ) {
  1411. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  1412. goto Cleanup;
  1413. }
  1414. break;
  1415. //
  1416. // Return object description to the caller
  1417. //
  1418. case AZ_PROP_DESCRIPTION:
  1419. *PropertyValue = AzpGetStringProperty( &GenericObject->Description );
  1420. if ( *PropertyValue == NULL ) {
  1421. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  1422. goto Cleanup;
  1423. }
  1424. break;
  1425. default:
  1426. ASSERT ( PropertyId >= AZ_PROP_FIRST_SPECIFIC );
  1427. //
  1428. // Call the routine to do object type specific querying
  1429. //
  1430. if ( ObjectGetPropertyRoutine[GenericObject->ObjectType] != NULL ) {
  1431. WinStatus = ObjectGetPropertyRoutine[GenericObject->ObjectType](
  1432. GenericObject,
  1433. PropertyId,
  1434. PropertyValue );
  1435. } else {
  1436. AzPrint(( AZD_INVPARM, "ObCommonGetProperty: No get property routine.\n", GenericObject->ObjectType, PropertyId ));
  1437. WinStatus = ERROR_INVALID_PARAMETER;
  1438. }
  1439. break;
  1440. }
  1441. //
  1442. // Return the value to the caller
  1443. //
  1444. WinStatus = NO_ERROR;
  1445. //
  1446. // Free locally used resources
  1447. //
  1448. Cleanup:
  1449. if ( ReferencedGenericObject != NULL ) {
  1450. ObDereferenceObject( ReferencedGenericObject );
  1451. }
  1452. //
  1453. // Drop the global lock
  1454. //
  1455. AzpUnlockResource( &AzGlResource );
  1456. return WinStatus;
  1457. }
  1458. DWORD
  1459. ObCommonSetProperty(
  1460. IN PGENERIC_OBJECT GenericObject,
  1461. IN ULONG ObjectType,
  1462. IN ULONG PropertyId,
  1463. IN DWORD Reserved,
  1464. IN PVOID PropertyValue
  1465. )
  1466. /*++
  1467. Routine Description:
  1468. Sets the specified property for a generic object.
  1469. Arguments:
  1470. GenericObject - Specifies a handle to the object to modify.
  1471. This "handle" has been passed from the application and needs to be verified.
  1472. ObjectType - Specifies the expected object type GenericObject.
  1473. PropertyId - Specifies which property to return.
  1474. Reserved - Reserved. Must by zero.
  1475. PropertyValue - Specifies a pointer to the property.
  1476. The specified value and type depends in PropertyId. The valid values are:
  1477. AZ_PROP_NAME LPWSTR - Object name of the object
  1478. AZ_PROP_DESCRIPTION LPWSTR - Description of the object
  1479. Any object specific properties.
  1480. Return Value:
  1481. NO_ERROR - The operation was successful
  1482. ERROR_INVALID_PARAMETER - PropertyId isn't valid
  1483. --*/
  1484. {
  1485. DWORD WinStatus;
  1486. PGENERIC_OBJECT ReferencedGenericObject = NULL;
  1487. AZP_STRING CapturedString;
  1488. //
  1489. // Grab the global lock
  1490. //
  1491. AzpInitString( &CapturedString, NULL );
  1492. AzpLockResourceExclusive( &AzGlResource );
  1493. //
  1494. // Validate the input parameters
  1495. //
  1496. if ( Reserved != 0 ) {
  1497. AzPrint(( AZD_INVPARM, "ObCommonSetProperty: Reserved != 0\n" ));
  1498. WinStatus = ERROR_INVALID_PARAMETER;
  1499. goto Cleanup;
  1500. }
  1501. //
  1502. // Validate the passed in handle
  1503. //
  1504. WinStatus = ObReferenceObjectByHandle( GenericObject,
  1505. FALSE, // Don't allow deleted objects
  1506. TRUE, // Refresh the cache
  1507. ObjectType );
  1508. if ( WinStatus != NO_ERROR ) {
  1509. goto Cleanup;
  1510. }
  1511. ReferencedGenericObject = GenericObject;
  1512. //
  1513. // Return any common attribute
  1514. //
  1515. // Return object name to the caller
  1516. //
  1517. switch ( PropertyId ) {
  1518. case AZ_PROP_NAME:
  1519. //
  1520. // Capture the input string
  1521. //
  1522. WinStatus = AzpCaptureString( &CapturedString,
  1523. (LPWSTR) PropertyValue,
  1524. MaxObjectNameLength[ObjectType],
  1525. FALSE ); // NULL not ok
  1526. if ( WinStatus != NO_ERROR ) {
  1527. goto Cleanup;
  1528. }
  1529. //
  1530. // Check to see if the name conflicts with an existing name
  1531. // ???
  1532. //
  1533. // Swap the old/new names
  1534. //
  1535. AzpSwapStrings( &CapturedString, &GenericObject->ObjectName );
  1536. break;
  1537. //
  1538. // Return object description to the caller
  1539. //
  1540. case AZ_PROP_DESCRIPTION:
  1541. //
  1542. // Capture the input string
  1543. //
  1544. WinStatus = AzpCaptureString( &CapturedString,
  1545. (LPWSTR) PropertyValue,
  1546. AZ_MAX_DESCRIPTION_LENGTH,
  1547. TRUE ); // NULL is OK
  1548. if ( WinStatus != NO_ERROR ) {
  1549. goto Cleanup;
  1550. }
  1551. //
  1552. // Swap the old/new names
  1553. //
  1554. AzpSwapStrings( &CapturedString, &GenericObject->Description );
  1555. break;
  1556. default:
  1557. ASSERT ( PropertyId >= AZ_PROP_FIRST_SPECIFIC );
  1558. //
  1559. // Call the routine to do object type specific set property
  1560. //
  1561. if ( ObjectSetPropertyRoutine[GenericObject->ObjectType] != NULL ) {
  1562. WinStatus = ObjectSetPropertyRoutine[GenericObject->ObjectType](
  1563. GenericObject,
  1564. PropertyId,
  1565. PropertyValue );
  1566. if ( WinStatus != NO_ERROR ) {
  1567. goto Cleanup;
  1568. }
  1569. } else {
  1570. AzPrint(( AZD_INVPARM, "ObCommonSetProperty: non set property routine\n", GenericObject->ObjectType, PropertyId ));
  1571. WinStatus = ERROR_INVALID_PARAMETER;
  1572. goto Cleanup;
  1573. }
  1574. break;
  1575. }
  1576. //
  1577. // Mark the object as needing to be written
  1578. //
  1579. GenericObject->Flags |= GENOBJ_FLAGS_DIRTY;
  1580. //
  1581. // Return the value to the caller
  1582. //
  1583. WinStatus = NO_ERROR;
  1584. //
  1585. // Free locally used resources
  1586. //
  1587. Cleanup:
  1588. if ( ReferencedGenericObject != NULL ) {
  1589. ObDereferenceObject( ReferencedGenericObject );
  1590. }
  1591. AzpFreeString( &CapturedString );
  1592. //
  1593. // Drop the global lock
  1594. //
  1595. AzpUnlockResource( &AzGlResource );
  1596. return WinStatus;
  1597. }
  1598. VOID
  1599. ObMarkObjectDeleted(
  1600. IN PGENERIC_OBJECT GenericObject
  1601. )
  1602. /*++
  1603. Routine Description
  1604. Mark this object and all child objects as deleted.
  1605. On entry, AzGlResource must be locked exclusive.
  1606. Arguments
  1607. GenericObject - Specifies the object to mark
  1608. Return Value
  1609. None
  1610. --*/
  1611. {
  1612. PGENERIC_OBJECT_HEAD ChildGenericObjectHead;
  1613. PGENERIC_OBJECT ChildGenericObject;
  1614. PLIST_ENTRY ListEntry;
  1615. //
  1616. // Initialization
  1617. //
  1618. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  1619. //
  1620. // Mark the entry as deleted
  1621. //
  1622. GenericObject->Flags |= GENOBJ_FLAGS_DELETED;
  1623. //
  1624. // Delete all children of this object
  1625. //
  1626. // Loop for each type of child object
  1627. //
  1628. for ( ChildGenericObjectHead = GenericObject->ChildGenericObjectHead;
  1629. ChildGenericObjectHead != NULL;
  1630. ChildGenericObjectHead = ChildGenericObjectHead->SiblingGenericObjectHead ) {
  1631. //
  1632. // Loop for each child object
  1633. //
  1634. for ( ListEntry = ChildGenericObjectHead->Head.Flink ;
  1635. ListEntry != &ChildGenericObjectHead->Head ;
  1636. ListEntry = ListEntry->Flink) {
  1637. ChildGenericObject = CONTAINING_RECORD( ListEntry,
  1638. GENERIC_OBJECT,
  1639. Next );
  1640. //
  1641. // Mark that object
  1642. //
  1643. ObMarkObjectDeleted( ChildGenericObject );
  1644. }
  1645. }
  1646. //
  1647. // Delete all references to this object
  1648. //
  1649. ObRemoveObjectListLinks( GenericObject, TRUE );
  1650. }
  1651. DWORD
  1652. ObCommonDeleteObject(
  1653. IN PGENERIC_OBJECT ParentGenericObject,
  1654. IN ULONG ParentObjectType,
  1655. IN PGENERIC_OBJECT_HEAD GenericChildHead,
  1656. IN ULONG ChildObjectType,
  1657. IN LPCWSTR ChildObjectName,
  1658. IN DWORD Reserved
  1659. )
  1660. /*++
  1661. Routine Description:
  1662. This routine deletes a child object from the scope of the specified parent object.
  1663. Arguments:
  1664. ParentGenericObject - Specifies a handle to the parent object to delete the child
  1665. object from. This "handle" has been passed from the application and needs to
  1666. be verified.
  1667. ParentObjectType - Specifies the object type ParentGenericObject.
  1668. GenericChildHead - Specifies a pointer to the head of the list of children of
  1669. ParentGenericObject. This is a computed pointer and is considered untrustworthy
  1670. until ParentGenericObject has been verified.
  1671. ChildObjectType - Specifies the object type RetChildGenericObject.
  1672. ChildObjectName - Specifies the name of the child object.
  1673. This name is passed from the application and needs to be verified.
  1674. Reserved - Reserved. Must by zero.
  1675. Return Value:
  1676. NO_ERROR - The operation was successful
  1677. ERROR_NOT_FOUND - An object by that name cannot be found
  1678. --*/
  1679. {
  1680. DWORD WinStatus;
  1681. PGENERIC_OBJECT ReferencedParentObject = NULL;
  1682. PGENERIC_OBJECT ChildGenericObject = NULL;
  1683. AZP_STRING ChildObjectNameString;
  1684. //
  1685. // Initialization
  1686. //
  1687. AzpInitString( &ChildObjectNameString, NULL );
  1688. ASSERT( ParentObjectType != OBJECT_TYPE_ROOT );
  1689. ASSERT( ChildObjectType != OBJECT_TYPE_ADMIN_MANAGER );
  1690. //
  1691. // Grab the global lock
  1692. //
  1693. AzpLockResourceExclusive( &AzGlResource );
  1694. //
  1695. // Validate the input parameters
  1696. //
  1697. if ( Reserved != 0 ) {
  1698. AzPrint(( AZD_INVPARM, "ObCommonDeleteObject: Reserved != 0\n" ));
  1699. WinStatus = ERROR_INVALID_PARAMETER;
  1700. goto Cleanup;
  1701. }
  1702. //
  1703. // Validate the passed in handle
  1704. //
  1705. WinStatus = ObReferenceObjectByHandle( ParentGenericObject,
  1706. FALSE, // Don't allow deleted objects
  1707. FALSE, // No need to refresh the cache on a delete
  1708. ParentObjectType );
  1709. if ( WinStatus != NO_ERROR ) {
  1710. goto Cleanup;
  1711. }
  1712. ReferencedParentObject = ParentGenericObject;
  1713. //
  1714. // Capture the object name string from the caller
  1715. //
  1716. WinStatus = AzpCaptureString( &ChildObjectNameString,
  1717. ChildObjectName,
  1718. MaxObjectNameLength[ChildObjectType],
  1719. FALSE ); // NULL names not OK
  1720. if ( WinStatus != NO_ERROR ) {
  1721. goto Cleanup;
  1722. }
  1723. //
  1724. // Find the object to delete.
  1725. //
  1726. WinStatus = ObReferenceObjectByName( GenericChildHead,
  1727. &ChildObjectNameString,
  1728. FALSE, // no need to refresh the cache
  1729. &ChildGenericObject );
  1730. if ( WinStatus != NO_ERROR ) {
  1731. goto Cleanup;
  1732. }
  1733. //
  1734. // Actually, delete the object
  1735. //
  1736. WinStatus = AzpPersistSubmit( ChildGenericObject, TRUE );
  1737. if ( WinStatus != NO_ERROR ) {
  1738. goto Cleanup;
  1739. }
  1740. //
  1741. // Mark the entry (and its child objects) as deleted
  1742. // We do this since other threads may have references to the objects.
  1743. // We want to ensure those threads know the objects are deleted.
  1744. //
  1745. ObMarkObjectDeleted( ChildGenericObject );
  1746. //
  1747. // Remove the reference representing the list from the parent.
  1748. //
  1749. ObDereferenceObject( ChildGenericObject );
  1750. //
  1751. // Return to the caller
  1752. //
  1753. WinStatus = NO_ERROR;
  1754. //
  1755. // Free locally used resources
  1756. //
  1757. Cleanup:
  1758. if ( ReferencedParentObject != NULL ) {
  1759. ObDereferenceObject( ReferencedParentObject );
  1760. }
  1761. if ( ChildGenericObject != NULL ) {
  1762. ObDereferenceObject( ChildGenericObject );
  1763. }
  1764. AzpFreeString( &ChildObjectNameString );
  1765. //
  1766. // Drop the global lock
  1767. //
  1768. AzpUnlockResource( &AzGlResource );
  1769. return WinStatus;
  1770. }
  1771. VOID
  1772. ObInitObjectList(
  1773. IN OUT PGENERIC_OBJECT_LIST GenericObjectList,
  1774. IN PGENERIC_OBJECT_LIST NextGenericObjectList OPTIONAL,
  1775. IN BOOL IsBackLink,
  1776. IN ULONG LinkPairId,
  1777. IN PGENERIC_OBJECT_HEAD GenericObjectHead0 OPTIONAL,
  1778. IN PGENERIC_OBJECT_HEAD GenericObjectHead1 OPTIONAL,
  1779. IN PGENERIC_OBJECT_HEAD GenericObjectHead2 OPTIONAL
  1780. )
  1781. /*++
  1782. Routine Description
  1783. Initialize a list of generic objects.
  1784. The caller must call ObFreeObjectList after calling this routine.
  1785. Arguments
  1786. GenericObjectList - Specifies the object list to initialize
  1787. NextGenericObjectList - Specifies a pointer to the next GenericObjectList
  1788. that is hosted in the same generic object as this one.
  1789. IsBackLink - TRUE if the link is a backlink
  1790. See GENERIC_OBJECT_LIST definition.
  1791. LinkPairId - LinkPairId for this object list.
  1792. See GENERIC_OBJECT_LIST definition.
  1793. GenericObjectHeadN - Specifies a pointer to the head of the list of objects
  1794. that are candidates for being pointed to by the object list.
  1795. If this object list is maintained by an external API (and not a "back" list),
  1796. then at least one GenericObjectHead must be specified.
  1797. If this is a back list, all GenericObjectHeads must be NULL.
  1798. Return Value
  1799. None
  1800. --*/
  1801. {
  1802. //
  1803. // Initialize most fields to zero
  1804. //
  1805. RtlZeroMemory( GenericObjectList, sizeof(*GenericObjectList) );
  1806. //
  1807. // Initialize the pointer to the next generic object list for this object
  1808. //
  1809. GenericObjectList->NextGenericObjectList = NextGenericObjectList;
  1810. //
  1811. // Initialize the link pair information
  1812. //
  1813. GenericObjectList->IsBackLink = IsBackLink;
  1814. GenericObjectList->LinkPairId = LinkPairId;
  1815. //
  1816. // Initialize the pointers to the object heads
  1817. //
  1818. GenericObjectList->GenericObjectHeads[0] = GenericObjectHead0;
  1819. GenericObjectList->GenericObjectHeads[1] = GenericObjectHead1;
  1820. GenericObjectList->GenericObjectHeads[2] = GenericObjectHead2;
  1821. AzPrint(( AZD_OBJLIST, "0x%lx: 0x%lx: ObInitObjectList\n", &GenericObjectList->GenericObjects, GenericObjectList->GenericObjects.Array ));
  1822. }
  1823. //
  1824. // Table of mappings to backlink object list tables
  1825. //
  1826. struct {
  1827. ULONG LinkFromObjectType;
  1828. ULONG LinkToObjectType;
  1829. BOOL IsBackLink;
  1830. ULONG LinkPairId;
  1831. ULONG ObjectListOffset;
  1832. } ObjectListOffsetTable[] = {
  1833. { OBJECT_TYPE_TASK, OBJECT_TYPE_OPERATION, FALSE, 0, offsetof(_AZP_TASK, Operations) },
  1834. { OBJECT_TYPE_OPERATION, OBJECT_TYPE_TASK, TRUE, 0, offsetof(_AZP_OPERATION, backTasks) },
  1835. { OBJECT_TYPE_GROUP, OBJECT_TYPE_GROUP, FALSE, AZP_LINKPAIR_MEMBERS, offsetof(_AZP_GROUP, AppMembers) },
  1836. { OBJECT_TYPE_GROUP, OBJECT_TYPE_GROUP, TRUE, AZP_LINKPAIR_MEMBERS, offsetof(_AZP_GROUP, backAppMembers) },
  1837. { OBJECT_TYPE_GROUP, OBJECT_TYPE_GROUP, FALSE, AZP_LINKPAIR_NON_MEMBERS, offsetof(_AZP_GROUP, AppNonMembers) },
  1838. { OBJECT_TYPE_GROUP, OBJECT_TYPE_GROUP, TRUE, AZP_LINKPAIR_NON_MEMBERS, offsetof(_AZP_GROUP, backAppNonMembers) },
  1839. { OBJECT_TYPE_ROLE, OBJECT_TYPE_GROUP, FALSE, 0, offsetof(_AZP_ROLE, AppMembers) },
  1840. { OBJECT_TYPE_GROUP, OBJECT_TYPE_ROLE, TRUE, 0, offsetof(_AZP_GROUP, backRoles) },
  1841. { OBJECT_TYPE_ROLE, OBJECT_TYPE_OPERATION, FALSE, 0, offsetof(_AZP_ROLE, Operations) },
  1842. { OBJECT_TYPE_OPERATION, OBJECT_TYPE_ROLE, TRUE, 0, offsetof(_AZP_OPERATION, backRoles) },
  1843. { OBJECT_TYPE_ROLE, OBJECT_TYPE_SCOPE, FALSE, 0, offsetof(_AZP_ROLE, Scopes) },
  1844. { OBJECT_TYPE_SCOPE, OBJECT_TYPE_ROLE, TRUE, 0, offsetof(_AZP_SCOPE, backRoles) },
  1845. { OBJECT_TYPE_JUNCTION_POINT, OBJECT_TYPE_APPLICATION, FALSE, 0, offsetof(_AZP_JUNCTION_POINT, Applications) },
  1846. { OBJECT_TYPE_APPLICATION, OBJECT_TYPE_JUNCTION_POINT, TRUE, 0, offsetof(_AZP_APPLICATION, backJunctionPoints) },
  1847. { OBJECT_TYPE_GROUP, OBJECT_TYPE_SID, FALSE, AZP_LINKPAIR_SID_MEMBERS, offsetof(_AZP_GROUP, SidMembers) },
  1848. { OBJECT_TYPE_SID, OBJECT_TYPE_GROUP, TRUE, AZP_LINKPAIR_SID_MEMBERS, offsetof(_AZP_SID, backGroupMembers) },
  1849. { OBJECT_TYPE_GROUP, OBJECT_TYPE_SID, FALSE, AZP_LINKPAIR_SID_NON_MEMBERS, offsetof(_AZP_GROUP, SidNonMembers) },
  1850. { OBJECT_TYPE_SID, OBJECT_TYPE_GROUP, TRUE, AZP_LINKPAIR_SID_NON_MEMBERS, offsetof(_AZP_SID, backGroupNonMembers) },
  1851. { OBJECT_TYPE_ROLE, OBJECT_TYPE_SID, FALSE, 0, offsetof(_AZP_ROLE, SidMembers) },
  1852. { OBJECT_TYPE_SID, OBJECT_TYPE_ROLE, TRUE, 0, offsetof(_AZP_SID, backRoles) },
  1853. };
  1854. PGENERIC_OBJECT_LIST
  1855. ObGetObjectListPtr(
  1856. IN PGENERIC_OBJECT GenericObject,
  1857. IN ULONG LinkToObjectType,
  1858. IN PGENERIC_OBJECT_LIST LinkToGenericObjectList
  1859. )
  1860. /*++
  1861. Routine Description
  1862. Returns a pointer to a GENERIC_OBJECT_LIST structure within the passed in
  1863. GenericObject the is suitable for linking an object of type LinkToObjectType
  1864. into.
  1865. Arguments
  1866. GenericObject - Specifies the object the link is from.
  1867. LinkToObjectType - Specifies the object type the link is to.
  1868. LinkToGenericObjectList - Specifies a pointer to the generic object list
  1869. structure that is within the LinkToGenericObject.
  1870. Return Value
  1871. Returns a pointer to the generic object list.
  1872. --*/
  1873. {
  1874. PGENERIC_OBJECT_LIST GenericObjectList = NULL;
  1875. ULONG i;
  1876. //
  1877. // Compute the address of the generic address list the object is in.
  1878. // We could do this more generically, but that would scatter this data
  1879. // over too wide an array.
  1880. //
  1881. for ( i=0; i<sizeof(ObjectListOffsetTable)/sizeof(ObjectListOffsetTable[0]); i++ ) {
  1882. //
  1883. // Find the entry in the table that matches our situation
  1884. //
  1885. if ( GenericObject->ObjectType == ObjectListOffsetTable[i].LinkFromObjectType &&
  1886. LinkToObjectType == ObjectListOffsetTable[i].LinkToObjectType &&
  1887. LinkToGenericObjectList->IsBackLink != ObjectListOffsetTable[i].IsBackLink &&
  1888. LinkToGenericObjectList->LinkPairId == ObjectListOffsetTable[i].LinkPairId ) {
  1889. GenericObjectList = (PGENERIC_OBJECT_LIST)
  1890. (((LPBYTE)GenericObject)+(ObjectListOffsetTable[i].ObjectListOffset));
  1891. }
  1892. }
  1893. ASSERT( GenericObjectList != NULL );
  1894. return GenericObjectList;
  1895. }
  1896. VOID
  1897. ObRemoveObjectListLink(
  1898. IN PGENERIC_OBJECT LinkFromGenericObject,
  1899. IN PGENERIC_OBJECT LinkToGenericObject,
  1900. IN PGENERIC_OBJECT_LIST LinkToGenericObjectList
  1901. )
  1902. /*++
  1903. Routine Description
  1904. Remove the link from LinkedFromGenericObject to LinkToGenericObject.
  1905. On entry, AzGlResource must be locked exclusive.
  1906. Arguments
  1907. LinkFromGenericObject - Specifies the object the link is from
  1908. LinkToGenericObject - Specifies the object the link is to
  1909. LinkToGenericObjectList - Specifies a pointer to the generic object list
  1910. structure that is within the LinkToGenericObject. (Notice, this isn't
  1911. the object list we're removing LinkFromGenericObject from. This is the
  1912. 'other' object list.)
  1913. Return Value
  1914. None
  1915. --*/
  1916. {
  1917. PGENERIC_OBJECT_LIST GenericObjectList;
  1918. //
  1919. // Initialization
  1920. //
  1921. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  1922. //
  1923. // Get a pointer to the object list to remove this entry from
  1924. //
  1925. GenericObjectList = ObGetObjectListPtr( LinkFromGenericObject,
  1926. LinkToGenericObject->ObjectType,
  1927. LinkToGenericObjectList );
  1928. ASSERT( GenericObjectList != NULL );
  1929. //
  1930. // Remove the entry from the list
  1931. //
  1932. AzpRemovePtrByPtr( &GenericObjectList->GenericObjects, LinkToGenericObject );
  1933. }
  1934. DWORD
  1935. ObLookupPropertyItem(
  1936. IN PGENERIC_OBJECT_LIST GenericObjectList,
  1937. IN PAZP_STRING ObjectName,
  1938. OUT PULONG InsertionPoint OPTIONAL
  1939. )
  1940. /*++
  1941. Routine Description:
  1942. This routine determins if the specified object name is already in the
  1943. object list.
  1944. On entry, AzGlResource must be locked share
  1945. Arguments:
  1946. GenericObjectList - Specifies the object list to be searched
  1947. ObjectName - Specifies the ObjectName to lookup
  1948. InsertionPoint - On ERROR_NOT_FOUND, returns the point where one would insert the named
  1949. object. On ERROR_ALREADY_EXISTS, returns an index to the object.
  1950. Return Value:
  1951. ERROR_ALREADY_EXISTS - An object by that name already exists in the list
  1952. ERROR_NOT_FOUND - There is no object by that name
  1953. Misc other failure statuses.
  1954. --*/
  1955. {
  1956. DWORD WinStatus = NO_ERROR;
  1957. ULONG i;
  1958. //
  1959. // Initialization
  1960. //
  1961. ASSERT( AzpIsLockedShared( &AzGlResource ) );
  1962. //
  1963. // Loop through the existing list of names finding the insertion point.
  1964. // The list is maintained in alphabetical order.
  1965. // ??? Could be binary search
  1966. //
  1967. for ( i=0; i<GenericObjectList->GenericObjects.UsedCount; i++ ) {
  1968. PGENERIC_OBJECT ExistingObject;
  1969. LONG CompareResult;
  1970. ExistingObject= (PGENERIC_OBJECT) (GenericObjectList->GenericObjects.Array[i]);
  1971. CompareResult = AzpCompareStrings( ObjectName,
  1972. &ExistingObject->ObjectName );
  1973. if ( CompareResult == 0 ) {
  1974. WinStatus = GetLastError();
  1975. goto Cleanup;
  1976. } else if ( CompareResult == CSTR_EQUAL ) {
  1977. if ( InsertionPoint != NULL ) {
  1978. *InsertionPoint = i;
  1979. }
  1980. WinStatus = ERROR_ALREADY_EXISTS;
  1981. goto Cleanup;
  1982. } else if ( CompareResult == CSTR_LESS_THAN ) {
  1983. break;
  1984. }
  1985. }
  1986. if ( InsertionPoint != NULL ) {
  1987. *InsertionPoint = i;
  1988. }
  1989. WinStatus = ERROR_NOT_FOUND;
  1990. //
  1991. // Free any local resources
  1992. //
  1993. Cleanup:
  1994. return WinStatus;
  1995. }
  1996. DWORD
  1997. ObAddPropertyItem(
  1998. IN PGENERIC_OBJECT GenericObject,
  1999. IN PGENERIC_OBJECT_LIST GenericObjectList,
  2000. IN PAZP_STRING ObjectName
  2001. )
  2002. /*++
  2003. Routine Description:
  2004. Adds an object to the list of objects specified by GenericObjectList.
  2005. On entry, AzGlResource must be locked exclusive.
  2006. Arguments:
  2007. GenericObject - Specifies a pointer to the object the link is from
  2008. GenericObjectList - Specifies the object list to add the object into.
  2009. ObjectName - Specifies a pointer to name of the object to add.
  2010. Return Value:
  2011. NO_ERROR - The operation was successful.
  2012. ERROR_NOT_FOUND - There is no object by that name
  2013. ERROR_ALREADY_EXISTS - An object by that name already exists in the list
  2014. --*/
  2015. {
  2016. DWORD WinStatus;
  2017. ULONG InsertionPoint;
  2018. ULONG ObjectTypeIndex;
  2019. PGENERIC_OBJECT FoundGenericObject = NULL;
  2020. PGENERIC_OBJECT_LIST BackGenericObjectList;
  2021. //
  2022. // Initialization
  2023. //
  2024. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  2025. //
  2026. // Loop through the various lists of objects that can be referenced
  2027. //
  2028. for ( ObjectTypeIndex=0; ObjectTypeIndex<GEN_OBJECT_HEAD_COUNT; ObjectTypeIndex++ ) {
  2029. //
  2030. // Stop when there are no more lists to search
  2031. //
  2032. if ( GenericObjectList->GenericObjectHeads[ObjectTypeIndex] == NULL ) {
  2033. break;
  2034. }
  2035. //
  2036. // Find the specified object in this list
  2037. //
  2038. WinStatus = ObReferenceObjectByName(
  2039. GenericObjectList->GenericObjectHeads[ObjectTypeIndex],
  2040. ObjectName,
  2041. FALSE, // No need to refresh the cache
  2042. &FoundGenericObject );
  2043. if ( WinStatus == NO_ERROR ) {
  2044. break;
  2045. }
  2046. //
  2047. // If this is a link to a SID object,
  2048. // create the SID object.
  2049. //
  2050. // AzpSids are pseudo objects that come into existence as they are needed.
  2051. //
  2052. if ( AzpIsSidList( GenericObjectList ) ) {
  2053. WinStatus = ObCreateObject(
  2054. GenericObjectList->GenericObjectHeads[0]->ParentGenericObject,
  2055. GenericObjectList->GenericObjectHeads[0],
  2056. OBJECT_TYPE_SID,
  2057. ObjectName,
  2058. &FoundGenericObject );
  2059. if ( WinStatus != NO_ERROR ) {
  2060. goto Cleanup;
  2061. }
  2062. }
  2063. }
  2064. //
  2065. // If none of the lists had an object by the requested name,
  2066. // complain.
  2067. //
  2068. if ( FoundGenericObject == NULL ) {
  2069. WinStatus = ERROR_NOT_FOUND;
  2070. goto Cleanup;
  2071. }
  2072. //
  2073. // Prevent a reference to ourself
  2074. //
  2075. if ( GenericObject == FoundGenericObject ) {
  2076. AzPrint(( AZD_INVPARM, "Reference to self\n" ));
  2077. WinStatus = ERROR_DS_LOOP_DETECT;
  2078. goto Cleanup;
  2079. }
  2080. //
  2081. // Call the object specific routine to validate the request
  2082. //
  2083. if ( ObjectAddPropertyItemRoutine[GenericObject->ObjectType] != NULL ) {
  2084. WinStatus = ObjectAddPropertyItemRoutine[GenericObject->ObjectType](
  2085. GenericObject,
  2086. GenericObjectList,
  2087. FoundGenericObject );
  2088. if ( WinStatus != NO_ERROR ) {
  2089. goto Cleanup;
  2090. }
  2091. }
  2092. //
  2093. // Find the insertion point for this name.
  2094. //
  2095. WinStatus = ObLookupPropertyItem( GenericObjectList,
  2096. ObjectName,
  2097. &InsertionPoint );
  2098. if ( WinStatus != ERROR_NOT_FOUND ) {
  2099. goto Cleanup;
  2100. }
  2101. //
  2102. // Insert the generic object into the list
  2103. //
  2104. WinStatus = AzpAddPtr(
  2105. &GenericObjectList->GenericObjects,
  2106. FoundGenericObject,
  2107. InsertionPoint );
  2108. if ( WinStatus != NO_ERROR ) {
  2109. goto Cleanup;
  2110. }
  2111. //
  2112. // Get a pointer to the backlink object list
  2113. //
  2114. BackGenericObjectList = ObGetObjectListPtr( FoundGenericObject,
  2115. GenericObject->ObjectType,
  2116. GenericObjectList );
  2117. ASSERT( BackGenericObjectList != NULL );
  2118. //
  2119. // Maintain a back link from the generic object we just linked to back
  2120. // to this object.
  2121. //
  2122. WinStatus = AzpAddPtr(
  2123. &BackGenericObjectList->GenericObjects,
  2124. GenericObject,
  2125. AZP_ADD_ENDOFLIST );
  2126. if ( WinStatus != NO_ERROR ) {
  2127. // Undo the forward link
  2128. AzpRemovePtrByIndex( &GenericObjectList->GenericObjects, InsertionPoint );
  2129. goto Cleanup;
  2130. }
  2131. //
  2132. // Return to the caller
  2133. //
  2134. WinStatus = NO_ERROR;
  2135. //
  2136. // Free locally used resources
  2137. //
  2138. Cleanup:
  2139. if ( FoundGenericObject != NULL ) {
  2140. ObDereferenceObject( FoundGenericObject );
  2141. }
  2142. return WinStatus;
  2143. }
  2144. DWORD
  2145. ObCommonAddPropertyItem(
  2146. IN PGENERIC_OBJECT GenericObject,
  2147. IN ULONG ObjectType,
  2148. IN PGENERIC_OBJECT_LIST GenericObjectList,
  2149. IN DWORD Reserved,
  2150. IN LPWSTR ObjectName
  2151. )
  2152. /*++
  2153. Routine Description:
  2154. Adds an object to the list of objects specified by GenericObjectList.
  2155. Arguments:
  2156. GenericObject - Specifies a handle to the object to add the object to.
  2157. This "handle" has been passed from the application and needs to be verified.
  2158. ObjectType - Specifies the object type of GenericObject.
  2159. GenericObjectList - Specifies the object list to add the object into.
  2160. This is a computed pointer and is considered untrustworthy
  2161. until GenericObject has been verified.
  2162. Reserved - Reserved. Must by zero.
  2163. ObjectName - Specifies a pointer to name of the object to add.
  2164. Return Value:
  2165. NO_ERROR - The operation was successful.
  2166. ERROR_NOT_FOUND - There is no object by that name
  2167. ERROR_ALREADY_EXISTS - An object by that name already exists in the list
  2168. --*/
  2169. {
  2170. DWORD WinStatus;
  2171. PGENERIC_OBJECT ReferencedObject = NULL;
  2172. AZP_STRING ObjectNameString;
  2173. //
  2174. // Initialization
  2175. //
  2176. AzpInitString( &ObjectNameString, NULL );
  2177. //
  2178. // Grab the global lock
  2179. //
  2180. AzpLockResourceExclusive( &AzGlResource );
  2181. //
  2182. // Validate the input parameters
  2183. //
  2184. if ( Reserved != 0 ) {
  2185. AzPrint(( AZD_INVPARM, "ObCommonAddPropertyItem: Reserved != 0\n" ));
  2186. WinStatus = ERROR_INVALID_PARAMETER;
  2187. goto Cleanup;
  2188. }
  2189. //
  2190. // Validate the passed in handle
  2191. //
  2192. WinStatus = ObReferenceObjectByHandle( GenericObject,
  2193. FALSE, // Don't allow deleted objects
  2194. TRUE, // Refresh the cache
  2195. ObjectType );
  2196. if ( WinStatus != NO_ERROR ) {
  2197. goto Cleanup;
  2198. }
  2199. ReferencedObject = GenericObject;
  2200. //
  2201. // Capture the object name string from the caller
  2202. //
  2203. if ( AzpIsSidList( GenericObjectList ) ) {
  2204. WinStatus = AzpCaptureSid( &ObjectNameString,
  2205. ObjectName );
  2206. } else {
  2207. WinStatus = AzpCaptureString( &ObjectNameString,
  2208. ObjectName,
  2209. AZ_MAX_NAME_LENGTH, // Don't need to validate size exactly
  2210. FALSE ); // NULL names not OK
  2211. }
  2212. if ( WinStatus != NO_ERROR ) {
  2213. goto Cleanup;
  2214. }
  2215. //
  2216. // Actually add the property item
  2217. //
  2218. WinStatus = ObAddPropertyItem( GenericObject,
  2219. GenericObjectList,
  2220. &ObjectNameString );
  2221. //
  2222. // Free locally used resources
  2223. //
  2224. Cleanup:
  2225. if ( ReferencedObject != NULL ) {
  2226. ObDereferenceObject( ReferencedObject );
  2227. }
  2228. AzpFreeString( &ObjectNameString );
  2229. //
  2230. // Drop the global lock
  2231. //
  2232. AzpUnlockResource( &AzGlResource );
  2233. return WinStatus;
  2234. }
  2235. DWORD
  2236. ObRemovePropertyItem(
  2237. IN PGENERIC_OBJECT GenericObject,
  2238. IN PGENERIC_OBJECT_LIST GenericObjectList,
  2239. IN PAZP_STRING ObjectName
  2240. )
  2241. /*++
  2242. Routine Description:
  2243. Removes a generic object from the list of items specified by GenericObjectList
  2244. On entry, AzGlResource must be locked exclusive.
  2245. Arguments:
  2246. GenericObject - Specifies the object the link is from.
  2247. GenericObjectList - Specifies the obejct list to remote the object from.
  2248. ObjectName - Specifies a pointer to the name of the object to remove.
  2249. Return Value:
  2250. NO_ERROR - The operation was successful.
  2251. ERROR_NOT_FOUND - There is no object by that name in the list
  2252. --*/
  2253. {
  2254. DWORD WinStatus;
  2255. PGENERIC_OBJECT FoundGenericObject;
  2256. ULONG InsertionPoint;
  2257. //
  2258. // Initialization
  2259. //
  2260. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  2261. //
  2262. // Lookup that name in the object list
  2263. //
  2264. WinStatus = ObLookupPropertyItem( GenericObjectList,
  2265. ObjectName,
  2266. &InsertionPoint );
  2267. if ( WinStatus != ERROR_ALREADY_EXISTS ) {
  2268. return WinStatus;
  2269. }
  2270. FoundGenericObject = (PGENERIC_OBJECT) (GenericObjectList->GenericObjects.Array[InsertionPoint]);
  2271. //
  2272. // Remove the object from the list
  2273. //
  2274. AzpRemovePtrByIndex( &GenericObjectList->GenericObjects, InsertionPoint );
  2275. //
  2276. // Remove the back link, too
  2277. //
  2278. ObRemoveObjectListLink( FoundGenericObject, GenericObject, GenericObjectList );
  2279. //
  2280. // Return to the caller
  2281. //
  2282. return NO_ERROR;
  2283. }
  2284. DWORD
  2285. ObCommonRemovePropertyItem(
  2286. IN PGENERIC_OBJECT GenericObject,
  2287. IN ULONG ObjectType,
  2288. IN PGENERIC_OBJECT_LIST GenericObjectList,
  2289. IN DWORD Reserved,
  2290. IN LPWSTR ObjectName
  2291. )
  2292. /*++
  2293. Routine Description:
  2294. Removes a generic object from the list of items specified by GenericObjectList
  2295. Arguments:
  2296. GenericObject - Specifies a handle to the object to remove the object from.
  2297. This "handle" has been passed from the application and needs to be verified.
  2298. ObjectType - Specifies the object type of GenericObject.
  2299. GenericObjectList - Specifies the obejct list to remote the object from.
  2300. This is a computed pointer and is considered untrustworthy
  2301. until GenericObject has been verified.
  2302. Reserved - Reserved. Must by zero.
  2303. ObjectName - Specifies a pointer to the name of the object to remove.
  2304. Return Value:
  2305. NO_ERROR - The operation was successful.
  2306. ERROR_NOT_FOUND - There is no object by that name in the list
  2307. --*/
  2308. {
  2309. DWORD WinStatus;
  2310. PGENERIC_OBJECT ReferencedObject = NULL;
  2311. AZP_STRING ObjectNameString;
  2312. //
  2313. // Initialization
  2314. //
  2315. AzpInitString( &ObjectNameString, NULL );
  2316. //
  2317. // Grab the global lock
  2318. //
  2319. AzpLockResourceExclusive( &AzGlResource );
  2320. //
  2321. // Validate the input parameters
  2322. //
  2323. if ( Reserved != 0 ) {
  2324. AzPrint(( AZD_INVPARM, "ObCommonRemovePropertyItem: Reserved != 0\n" ));
  2325. WinStatus = ERROR_INVALID_PARAMETER;
  2326. goto Cleanup;
  2327. }
  2328. //
  2329. // Validate the passed in handle
  2330. //
  2331. WinStatus = ObReferenceObjectByHandle( GenericObject,
  2332. FALSE, // Don't allow deleted objects
  2333. TRUE, // Refresh the cache
  2334. ObjectType );
  2335. if ( WinStatus != NO_ERROR ) {
  2336. goto Cleanup;
  2337. }
  2338. ReferencedObject = GenericObject;
  2339. //
  2340. // Capture the object name string from the caller
  2341. //
  2342. if ( AzpIsSidList( GenericObjectList ) ) {
  2343. WinStatus = AzpCaptureSid( &ObjectNameString,
  2344. ObjectName );
  2345. } else {
  2346. WinStatus = AzpCaptureString( &ObjectNameString,
  2347. ObjectName,
  2348. AZ_MAX_NAME_LENGTH, // Don't need to validate size exactly
  2349. FALSE ); // NULL names not OK
  2350. }
  2351. if ( WinStatus != NO_ERROR ) {
  2352. goto Cleanup;
  2353. }
  2354. //
  2355. // Remove the item from the list and backlist
  2356. //
  2357. WinStatus = ObRemovePropertyItem( GenericObject,
  2358. GenericObjectList,
  2359. &ObjectNameString );
  2360. if ( WinStatus != NO_ERROR ) {
  2361. goto Cleanup;
  2362. }
  2363. //
  2364. // Mark the object as needing to be written
  2365. //
  2366. GenericObject->Flags |= GENOBJ_FLAGS_DIRTY;
  2367. //
  2368. // Free locally used resources
  2369. //
  2370. Cleanup:
  2371. if ( ReferencedObject != NULL ) {
  2372. ObDereferenceObject( ReferencedObject );
  2373. }
  2374. AzpFreeString( &ObjectNameString );
  2375. //
  2376. // Drop the global lock
  2377. //
  2378. AzpUnlockResource( &AzGlResource );
  2379. return WinStatus;
  2380. }
  2381. PAZ_STRING_ARRAY
  2382. ObGetPropertyItems(
  2383. IN PGENERIC_OBJECT_LIST GenericObjectList
  2384. )
  2385. /*++
  2386. Routine Description:
  2387. Return a list of generic object names as an array of object name strings.
  2388. On entry, AzGlResource must be locked shared
  2389. Arguments:
  2390. GenericObjectList - Specifies the object list to get the entries for.
  2391. Return Value:
  2392. Returns the array of object name strings in a single allocated buffer.
  2393. Free the buffer using AzFreeMemory.
  2394. NULL - Not enough memory was available to allocate the string
  2395. --*/
  2396. {
  2397. PAZP_PTR_ARRAY GenericObjects;
  2398. ULONG i;
  2399. ULONG Size;
  2400. LPBYTE Where;
  2401. PGENERIC_OBJECT GenericObject;
  2402. PAZ_STRING_ARRAY StringArray;
  2403. //
  2404. // Initialization
  2405. //
  2406. ASSERT( AzpIsLockedShared( &AzGlResource ) );
  2407. GenericObjects = &GenericObjectList->GenericObjects;
  2408. //
  2409. // Loop through the list of objects computing the size of the buffer to allocate
  2410. //
  2411. Size = 0;
  2412. for ( i=0; i<GenericObjects->UsedCount; i++ ) {
  2413. GenericObject = (PGENERIC_OBJECT) (GenericObjects->Array[i]);
  2414. Size += GenericObject->ObjectName.StringSize;
  2415. }
  2416. //
  2417. // Allocate a buffer to return to the caller
  2418. //
  2419. Size += sizeof(AZ_STRING_ARRAY) + (GenericObjects->UsedCount * sizeof(LPWSTR));
  2420. StringArray = (PAZ_STRING_ARRAY) AzpAllocateHeap( Size );
  2421. if ( StringArray == NULL ) {
  2422. return NULL;
  2423. }
  2424. StringArray->StringCount = GenericObjects->UsedCount;
  2425. StringArray->Strings = (LPWSTR *)(StringArray+1);
  2426. Where = (LPBYTE)(&StringArray->Strings[GenericObjects->UsedCount]);
  2427. //
  2428. // Loop through the list of objects copying the names into the return buffer
  2429. //
  2430. for ( i=0; i<GenericObjects->UsedCount; i++ ) {
  2431. GenericObject = (PGENERIC_OBJECT) (GenericObjects->Array[i]);
  2432. StringArray->Strings[i] = (LPWSTR) Where;
  2433. RtlCopyMemory( Where,
  2434. GenericObject->ObjectName.String,
  2435. GenericObject->ObjectName.StringSize );
  2436. Where += GenericObject->ObjectName.StringSize;
  2437. }
  2438. ASSERT( (ULONG)(Where - (LPBYTE)StringArray) == Size );
  2439. return StringArray;
  2440. }
  2441. VOID
  2442. ObRemoveObjectListLinks(
  2443. IN PGENERIC_OBJECT GenericObject,
  2444. IN BOOLEAN BackwardLinksToo
  2445. )
  2446. /*++
  2447. Routine Description
  2448. Remove any links to/from the specified object.
  2449. On entry, AzGlResource must be locked exclusive.
  2450. Arguments
  2451. GenericObject - Specifies the object to remove links to/from
  2452. BackwardLinksToo - TRUE if the back links are to be removed to.
  2453. Return Value
  2454. None
  2455. --*/
  2456. {
  2457. PGENERIC_OBJECT_LIST GenericObjectList;
  2458. PGENERIC_OBJECT OtherGenericObject;
  2459. ULONG Index;
  2460. //
  2461. // Initialization
  2462. //
  2463. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  2464. //
  2465. // Walk all of the GenericObjectLists rooted on by this object
  2466. //
  2467. // The GenericObjectList may be forward links or backward links. We don't care.
  2468. // All links must be removed.
  2469. //
  2470. for ( GenericObjectList = GenericObject->GenericObjectLists;
  2471. GenericObjectList != NULL;
  2472. GenericObjectList = GenericObjectList->NextGenericObjectList ) {
  2473. //
  2474. // Skip back links if the caller wants them left
  2475. //
  2476. if ( !BackwardLinksToo && GenericObjectList->IsBackLink ) {
  2477. continue;
  2478. }
  2479. AzPrint(( AZD_OBJLIST, "0x%lx: 0x%lx: %ld: ObRemoveObjectListLinks\n", &GenericObjectList->GenericObjects, GenericObjectList->GenericObjects.Array, GenericObjectList->GenericObjects.UsedCount ));
  2480. //
  2481. // Walk the list removing the current entry and removing the corresponding
  2482. // pointer back.
  2483. //
  2484. while ( GenericObjectList->GenericObjects.UsedCount != 0 ) {
  2485. //
  2486. // Remove the last entry in the list
  2487. //
  2488. Index = GenericObjectList->GenericObjects.UsedCount - 1;
  2489. OtherGenericObject = (PGENERIC_OBJECT)
  2490. (GenericObjectList->GenericObjects.Array[Index]);
  2491. AzpRemovePtrByIndex( &GenericObjectList->GenericObjects,
  2492. Index );
  2493. //
  2494. // Remove the entry in the opposite direction
  2495. //
  2496. ObRemoveObjectListLink( OtherGenericObject,
  2497. GenericObject,
  2498. GenericObjectList );
  2499. }
  2500. //
  2501. // Free the array itself
  2502. //
  2503. ObFreeObjectList( GenericObjectList );
  2504. }
  2505. }
  2506. VOID
  2507. ObFreeObjectList(
  2508. IN OUT PGENERIC_OBJECT_LIST GenericObjectList
  2509. )
  2510. /*++
  2511. Routine Description:
  2512. Free any memory pointed to by an array of object name strings.
  2513. On entry, AzGlResource must be locked exclusive.
  2514. Arguments:
  2515. GenericObjectList - Specifies the object list to free.
  2516. Return Value:
  2517. Returns the array of object name strings in a single allocated buffer.
  2518. Free the buffer using AzFreeMemory.
  2519. NULL - Not enough memory was available to allocate the string
  2520. --*/
  2521. {
  2522. PAZP_PTR_ARRAY GenericObjects;
  2523. //
  2524. // Initialization
  2525. //
  2526. AzPrint(( AZD_OBJLIST, "0x%lx: 0x%lx: ObFreeObjectList\n", &GenericObjectList->GenericObjects, GenericObjectList->GenericObjects.Array ));
  2527. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  2528. GenericObjects = &GenericObjectList->GenericObjects;
  2529. ASSERT( GenericObjects->UsedCount == 0 );
  2530. //
  2531. // Free the actual array
  2532. //
  2533. if ( GenericObjects->Array != NULL ) {
  2534. AzPrint(( AZD_OBJLIST, "0x%lx: 0x%lx: Free array\n", GenericObjects, GenericObjects->Array ));
  2535. AzpFreeHeap( GenericObjects->Array );
  2536. GenericObjects->Array = NULL;
  2537. }
  2538. }