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.

879 lines
21 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. role.cxx
  5. Abstract:
  6. Routines implementing the Role object
  7. Author:
  8. Cliff Van Dyke (cliffv) 11-Apr-2001
  9. --*/
  10. #include "pch.hxx"
  11. DWORD
  12. AzpRoleInit(
  13. IN PGENERIC_OBJECT ParentGenericObject,
  14. IN PGENERIC_OBJECT ChildGenericObject
  15. )
  16. /*++
  17. Routine Description:
  18. This routine is a worker routine for AzRoleCreate. It does any object specific
  19. initialization that needs to be done.
  20. On entry, AzGlResource must be locked exclusively.
  21. Arguments:
  22. ParentGenericObject - Specifies the parent object to add the child object onto.
  23. The reference count has been incremented on this object.
  24. ChildGenericObject - Specifies the newly allocated child object.
  25. The reference count has been incremented on this object.
  26. Return Value:
  27. NO_ERROR - The operation was successful
  28. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  29. Other exception status codes
  30. --*/
  31. {
  32. PAZP_ROLE Role = (PAZP_ROLE) ChildGenericObject;
  33. PAZP_ADMIN_MANAGER AdminManager = NULL;
  34. PAZP_APPLICATION Application = NULL;
  35. PAZP_SCOPE Scope = NULL;
  36. PGENERIC_OBJECT_HEAD ParentSids = NULL;
  37. //
  38. // Initialization
  39. //
  40. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  41. //
  42. // Behave differently depending on the object type of the parent object
  43. //
  44. // A role references SID objects that are siblings of itself.
  45. // That way, the back links on the SID object references just the roles
  46. // that are siblings of the SID object.
  47. //
  48. if ( ParentGenericObject->ObjectType == OBJECT_TYPE_APPLICATION ) {
  49. AdminManager = ParentGenericObject->AdminManagerObject;
  50. Application = (PAZP_APPLICATION) ParentGenericObject;
  51. ParentSids = &Application->AzpSids;
  52. } else if ( ParentGenericObject->ObjectType == OBJECT_TYPE_SCOPE ) {
  53. AdminManager = ParentGenericObject->AdminManagerObject;
  54. Application = (PAZP_APPLICATION) ParentGenericObject->ParentGenericObjectHead->ParentGenericObject;
  55. Scope = (PAZP_SCOPE) ParentGenericObject;
  56. ParentSids = &Scope->AzpSids;
  57. } else {
  58. ASSERT( FALSE );
  59. }
  60. //
  61. // Roles reference groups, operations, and scopes.
  62. // These other groups can be siblings of this group or siblings of our parents.
  63. //
  64. // Let the generic object manager know all of the lists we support
  65. //
  66. ChildGenericObject->GenericObjectLists = &Role->AppMembers,
  67. // List of Groups
  68. ObInitObjectList( &Role->AppMembers,
  69. &Role->Operations,
  70. FALSE, // Forward link
  71. 0, // No link pair id
  72. &AdminManager->Groups,
  73. &Application->Groups,
  74. Scope == NULL ? NULL : &Scope->Groups );
  75. // List of Operations
  76. ObInitObjectList( &Role->Operations,
  77. &Role->Scopes,
  78. FALSE, // Forward link
  79. 0, // No link pair id
  80. &Application->Operations,
  81. NULL,
  82. NULL );
  83. // List of Scopes
  84. ObInitObjectList( &Role->Scopes,
  85. &Role->SidMembers,
  86. FALSE, // Forward link
  87. 0, // No link pair id
  88. &Application->Scopes,
  89. NULL,
  90. NULL );
  91. // Role reference SID objects
  92. ObInitObjectList( &Role->SidMembers,
  93. NULL,
  94. FALSE, // Forward link
  95. 0, // No link pair id
  96. ParentSids,
  97. NULL,
  98. NULL );
  99. return NO_ERROR;
  100. }
  101. VOID
  102. AzpRoleFree(
  103. IN PGENERIC_OBJECT GenericObject
  104. )
  105. /*++
  106. Routine Description:
  107. This routine is a worker routine for Role object free. It does any object specific
  108. cleanup that needs to be done.
  109. On entry, AzGlResource must be locked exclusively.
  110. Arguments:
  111. GenericObject - Specifies a pointer to the object to be deleted.
  112. Return Value:
  113. None
  114. --*/
  115. {
  116. // PAZP_ROLE Role = (PAZP_ROLE) GenericObject;
  117. UNREFERENCED_PARAMETER( GenericObject );
  118. //
  119. // Initialization
  120. //
  121. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  122. //
  123. // Free any local strings
  124. //
  125. }
  126. DWORD
  127. AzpRoleGetProperty(
  128. IN PGENERIC_OBJECT GenericObject,
  129. IN ULONG PropertyId,
  130. OUT PVOID *PropertyValue
  131. )
  132. /*++
  133. Routine Description:
  134. This routine is a worker routine for AzRoleGetProperty. It does any object specific
  135. property gets.
  136. On entry, AzGlResource must be locked shared.
  137. Arguments:
  138. GenericObject - Specifies a pointer to the object to be queried
  139. PropertyId - Specifies which property to return.
  140. PropertyValue - Specifies a pointer to return the property in.
  141. The returned pointer must be freed using AzFreeMemory.
  142. The returned value and type depends in PropertyId. The valid values are:
  143. AZ_PROP_ROLE_APP_MEMBERS AZ_STRING_ARRAY - Application groups that are members of this role
  144. AZ_PROP_ROLE_MEMBERS AZ_SID_ARRAY - NT Sids that are members of this role
  145. AZ_PROP_ROLE_OPERATIONS AZ_STRING_ARRAY - Operations the can be performed by this role
  146. AZ_PROP_ROLE_SCOPES AZ_STRING_ARRAY - Scopes this role applies to
  147. Return Value:
  148. Status of the operation
  149. --*/
  150. {
  151. DWORD WinStatus = NO_ERROR;
  152. PAZP_ROLE Role = (PAZP_ROLE) GenericObject;
  153. //
  154. // Initialization
  155. //
  156. ASSERT( AzpIsLockedShared( &AzGlResource ) );
  157. //
  158. // Return any object specific attribute
  159. //
  160. //
  161. switch ( PropertyId ) {
  162. // Return the set of app members to the caller
  163. case AZ_PROP_ROLE_APP_MEMBERS:
  164. *PropertyValue = ObGetPropertyItems( &Role->AppMembers );
  165. if ( *PropertyValue == NULL ) {
  166. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  167. }
  168. break;
  169. // Return the set of SID members to the caller
  170. case AZ_PROP_ROLE_MEMBERS:
  171. *PropertyValue = ObGetPropertyItems( &Role->SidMembers );
  172. if ( *PropertyValue == NULL ) {
  173. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  174. }
  175. break;
  176. // Return the set of operations to the caller
  177. case AZ_PROP_ROLE_OPERATIONS:
  178. *PropertyValue = ObGetPropertyItems( &Role->Operations );
  179. if ( *PropertyValue == NULL ) {
  180. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  181. }
  182. break;
  183. // Return the set of scopes to the caller
  184. case AZ_PROP_ROLE_SCOPES:
  185. *PropertyValue = ObGetPropertyItems( &Role->Scopes );
  186. if ( *PropertyValue == NULL ) {
  187. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  188. }
  189. break;
  190. default:
  191. AzPrint(( AZD_INVPARM, "AzpRoleGetProperty: invalid prop id %ld\n", PropertyId ));
  192. WinStatus = ERROR_INVALID_PARAMETER;
  193. break;
  194. }
  195. return WinStatus;
  196. }
  197. DWORD
  198. AzpRoleGetGenericChildHead(
  199. IN AZ_HANDLE ParentHandle,
  200. OUT PULONG ObjectType,
  201. OUT PGENERIC_OBJECT_HEAD *GenericChildHead
  202. )
  203. /*++
  204. Routine Description:
  205. This routine determines whether ParentHandle supports Role objects as
  206. children.
  207. Arguments:
  208. ParentHandle - Specifies a handle to the object that is the parent of the role.
  209. This may be an Application Handle or a Scope handle.
  210. ObjectType - Returns the object type of the ParentHandle.
  211. GenericChildHead - Returns a pointer to the head of the list of roles objects
  212. that are children of the object specified by ParentHandle. This in an unverified
  213. pointer. The pointer is only valid after ParentHandle has been validated.
  214. Return Value:
  215. Status of the operation.
  216. --*/
  217. {
  218. DWORD WinStatus;
  219. //
  220. // Determine the type of the parent handle
  221. //
  222. WinStatus = ObGetHandleType( (PGENERIC_OBJECT)ParentHandle,
  223. FALSE, // ignore deleted objects
  224. ObjectType );
  225. if ( WinStatus != NO_ERROR ) {
  226. return WinStatus;
  227. }
  228. //
  229. // Verify that the specified handle support children roles.
  230. //
  231. switch ( *ObjectType ) {
  232. case OBJECT_TYPE_APPLICATION:
  233. *GenericChildHead = &(((PAZP_APPLICATION)ParentHandle)->Roles);
  234. break;
  235. case OBJECT_TYPE_SCOPE:
  236. *GenericChildHead = &(((PAZP_SCOPE)ParentHandle)->Roles);
  237. break;
  238. default:
  239. return ERROR_INVALID_HANDLE;
  240. }
  241. return NO_ERROR;
  242. }
  243. DWORD
  244. WINAPI
  245. AzRoleCreate(
  246. IN AZ_HANDLE ParentHandle,
  247. IN LPCWSTR RoleName,
  248. IN DWORD Reserved,
  249. OUT PAZ_HANDLE RoleHandle
  250. )
  251. /*++
  252. Routine Description:
  253. This routine adds a role into the scope of the specified parent object.
  254. Arguments:
  255. ParentHandle - Specifies a handle to the object that is the parent of the role.
  256. This may be an Application Handle or a Scope handle.
  257. RoleName - Specifies the name of the role to add.
  258. Reserved - Reserved. Must by zero.
  259. RoleHandle - Return a handle to the role.
  260. The caller must close this handle by calling AzCloseHandle.
  261. Return Value:
  262. NO_ERROR - The operation was successful
  263. ERROR_ALREADY_EXISTS - An object by that name already exists
  264. --*/
  265. {
  266. DWORD WinStatus;
  267. DWORD ObjectType;
  268. PGENERIC_OBJECT_HEAD GenericChildHead;
  269. //
  270. // Determine that the parent handle supports roles as children
  271. //
  272. WinStatus = AzpRoleGetGenericChildHead( ParentHandle,
  273. &ObjectType,
  274. &GenericChildHead );
  275. if ( WinStatus != NO_ERROR ) {
  276. return WinStatus;
  277. }
  278. //
  279. // Call the common routine to do most of the work
  280. //
  281. return ObCommonCreateObject(
  282. (PGENERIC_OBJECT) ParentHandle,
  283. ObjectType,
  284. GenericChildHead,
  285. OBJECT_TYPE_ROLE,
  286. RoleName,
  287. Reserved,
  288. (PGENERIC_OBJECT *) RoleHandle );
  289. }
  290. DWORD
  291. WINAPI
  292. AzRoleOpen(
  293. IN AZ_HANDLE ParentHandle,
  294. IN LPCWSTR RoleName,
  295. IN DWORD Reserved,
  296. OUT PAZ_HANDLE RoleHandle
  297. )
  298. /*++
  299. Routine Description:
  300. This routine opens a role into the scope of the specified parent object.
  301. Arguments:
  302. ParentHandle - Specifies a handle to the object that is the parent of the role.
  303. This may be an Application Handle or a Scope handle.
  304. RoleName - Specifies the name of the role to open
  305. Reserved - Reserved. Must by zero.
  306. RoleHandle - Return a handle to the role.
  307. The caller must close this handle by calling AzCloseHandle.
  308. Return Value:
  309. NO_ERROR - The operation was successful
  310. ERROR_NOT_FOUND - There is no role by that name
  311. --*/
  312. {
  313. DWORD WinStatus;
  314. DWORD ObjectType;
  315. PGENERIC_OBJECT_HEAD GenericChildHead;
  316. //
  317. // Determine that the parent handle supports roles as children
  318. //
  319. WinStatus = AzpRoleGetGenericChildHead( ParentHandle,
  320. &ObjectType,
  321. &GenericChildHead );
  322. if ( WinStatus != NO_ERROR ) {
  323. return WinStatus;
  324. }
  325. //
  326. // Call the common routine to do most of the work
  327. //
  328. return ObCommonOpenObject(
  329. (PGENERIC_OBJECT) ParentHandle,
  330. ObjectType,
  331. GenericChildHead,
  332. OBJECT_TYPE_ROLE,
  333. RoleName,
  334. Reserved,
  335. (PGENERIC_OBJECT *) RoleHandle );
  336. }
  337. DWORD
  338. WINAPI
  339. AzRoleEnum(
  340. IN AZ_HANDLE ParentHandle,
  341. IN DWORD Reserved,
  342. IN OUT PULONG EnumerationContext,
  343. OUT PAZ_HANDLE RoleHandle
  344. )
  345. /*++
  346. Routine Description:
  347. Enumerates all of the roles for the specified parent object.
  348. Arguments:
  349. ParentHandle - Specifies a handle to the object that is the parent of the role.
  350. This may be an Application Handle or a Scope handle.
  351. Reserved - Reserved. Must by zero.
  352. EnumerationContext - Specifies a context indicating the next role to return
  353. On input for the first call, should point to zero.
  354. On input for subsequent calls, should point to the value returned on the previous call.
  355. On output, returns a value to be passed on the next call.
  356. RoleHandle - Returns a handle to the next role object.
  357. The caller must close this handle by calling AzCloseHandle.
  358. Return Value:
  359. NO_ERROR - The operation was successful (a handle was returned)
  360. ERROR_NO_MORE_ITEMS - No more items were available for enumeration
  361. --*/
  362. {
  363. DWORD WinStatus;
  364. DWORD ObjectType;
  365. PGENERIC_OBJECT_HEAD GenericChildHead;
  366. //
  367. // Determine that the parent handle supports roles as children
  368. //
  369. WinStatus = AzpRoleGetGenericChildHead( ParentHandle,
  370. &ObjectType,
  371. &GenericChildHead );
  372. if ( WinStatus != NO_ERROR ) {
  373. return WinStatus;
  374. }
  375. //
  376. // Call the common routine to do most of the work
  377. //
  378. return ObCommonEnumObjects(
  379. (PGENERIC_OBJECT) ParentHandle,
  380. ObjectType,
  381. GenericChildHead,
  382. EnumerationContext,
  383. Reserved,
  384. (PGENERIC_OBJECT *) RoleHandle );
  385. }
  386. DWORD
  387. WINAPI
  388. AzRoleGetProperty(
  389. IN AZ_HANDLE RoleHandle,
  390. IN ULONG PropertyId,
  391. IN DWORD Reserved,
  392. OUT PVOID *PropertyValue
  393. )
  394. /*++
  395. Routine Description:
  396. Returns the specified property for a role.
  397. Arguments:
  398. RoleHandle - Specifies a handle to the role
  399. PropertyId - Specifies which property to return.
  400. Reserved - Reserved. Must by zero.
  401. PropertyValue - Specifies a pointer to return the property in.
  402. The returned pointer must be freed using AzFreeMemory.
  403. The returned value and type depends in PropertyId. The valid values are:
  404. AZ_PROP_NAME LPWSTR - Object name of the object
  405. AZ_PROP_DESCRIPTION LPWSTR - Description of the object
  406. AZ_PROP_ROLE_APP_MEMBERS AZ_STRING_ARRAY - Application groups that are members of this role
  407. AZ_PROP_ROLE_MEMBERS AZ_SID_ARRAY - NT Sids that are members of this role
  408. AZ_PROP_ROLE_OPERATIONS AZ_STRING_ARRAY - Operations the can be performed by this role
  409. AZ_PROP_ROLE_SCOPES AZ_STRING_ARRAY - Scopes this role applies to
  410. Return Value:
  411. NO_ERROR - The operation was successful
  412. ERROR_INVALID_PARAMETER - PropertyId isn't valid
  413. --*/
  414. {
  415. //
  416. // Call the common routine to do most of the work
  417. //
  418. return ObCommonGetProperty(
  419. (PGENERIC_OBJECT) RoleHandle,
  420. OBJECT_TYPE_ROLE,
  421. PropertyId,
  422. Reserved,
  423. PropertyValue );
  424. }
  425. DWORD
  426. WINAPI
  427. AzRoleSetProperty(
  428. IN AZ_HANDLE RoleHandle,
  429. IN ULONG PropertyId,
  430. IN DWORD Reserved,
  431. IN PVOID PropertyValue
  432. )
  433. /*++
  434. Routine Description:
  435. Sets the specified property for a role.
  436. Arguments:
  437. RoleHandle - Specifies a handle to the role
  438. PropertyId - Specifies which property to set
  439. Reserved - Reserved. Must by zero.
  440. PropertyValue - Specifies a pointer to the property.
  441. The specified value and type depends in PropertyId. The valid values are:
  442. AZ_PROP_NAME LPWSTR - Object name of the object
  443. AZ_PROP_DESCRIPTION LPWSTR - Description of the object
  444. AZ_PROP_ROLE_TYPE PULONG - Role type of the role
  445. Return Value:
  446. NO_ERROR - The operation was successful
  447. ERROR_INVALID_PARAMETER - PropertyId isn't valid
  448. --*/
  449. {
  450. //
  451. // Call the common routine to do most of the work
  452. //
  453. return ObCommonSetProperty(
  454. (PGENERIC_OBJECT) RoleHandle,
  455. OBJECT_TYPE_ROLE,
  456. PropertyId,
  457. Reserved,
  458. PropertyValue );
  459. }
  460. DWORD
  461. WINAPI
  462. AzRoleAddPropertyItem(
  463. IN AZ_HANDLE RoleHandle,
  464. IN ULONG PropertyId,
  465. IN DWORD Reserved,
  466. IN PVOID PropertyValue
  467. )
  468. /*++
  469. Routine Description:
  470. Adds an item to the list of items specified by PropertyId.
  471. Arguments:
  472. RoleHandle - Specifies a handle to the task
  473. PropertyId - Specifies which property to modify
  474. Reserved - Reserved. Must by zero.
  475. PropertyValue - Specifies a pointer to item to add.
  476. The specified value and type depends on PropertyId. The valid values are:
  477. AZ_PROP_ROLE_APP_MEMBERS LPWSTR - Application groups that are members of this role
  478. AZ_PROP_ROLE_MEMBERS PSID - NT Sids that are members of this role
  479. AZ_PROP_ROLE_OPERATIONS LPWSTR - Operations the can be performed by this role
  480. AZ_PROP_ROLE_SCOPES LPWSTR - Scopes this role applies to
  481. Return Value:
  482. NO_ERROR - The operation was successful
  483. ERROR_INVALID_PARAMETER - PropertyId isn't valid
  484. ERROR_NOT_FOUND - There is no object by that name
  485. ERROR_ALREADY_EXISTS - An item by that name already exists in the list
  486. --*/
  487. {
  488. PGENERIC_OBJECT_LIST GenericObjectList;
  489. //
  490. // Validate the Property ID
  491. //
  492. switch ( PropertyId ) {
  493. case AZ_PROP_ROLE_APP_MEMBERS:
  494. GenericObjectList = &((PAZP_ROLE)RoleHandle)->AppMembers;
  495. break;
  496. case AZ_PROP_ROLE_MEMBERS:
  497. GenericObjectList = &((PAZP_ROLE)RoleHandle)->SidMembers;
  498. break;
  499. case AZ_PROP_ROLE_OPERATIONS:
  500. GenericObjectList = &((PAZP_ROLE)RoleHandle)->Operations;
  501. break;
  502. case AZ_PROP_ROLE_SCOPES:
  503. GenericObjectList = &((PAZP_ROLE)RoleHandle)->Scopes;
  504. break;
  505. default:
  506. AzPrint(( AZD_INVPARM, "AzRoleAddPropertyItem: invalid prop id %ld\n", PropertyId ));
  507. return ERROR_INVALID_PARAMETER;
  508. }
  509. //
  510. // Call the common routine to do most of the work
  511. //
  512. return ObCommonAddPropertyItem(
  513. (PGENERIC_OBJECT) RoleHandle,
  514. OBJECT_TYPE_ROLE,
  515. GenericObjectList,
  516. Reserved,
  517. (LPWSTR) PropertyValue );
  518. }
  519. DWORD
  520. WINAPI
  521. AzRoleRemovePropertyItem(
  522. IN AZ_HANDLE RoleHandle,
  523. IN ULONG PropertyId,
  524. IN DWORD Reserved,
  525. IN PVOID PropertyValue
  526. )
  527. /*++
  528. Routine Description:
  529. Remove an item from the list of items specified by PropertyId.
  530. Arguments:
  531. RoleHandle - Specifies a handle to the task
  532. PropertyId - Specifies which property to modify
  533. Reserved - Reserved. Must by zero.
  534. PropertyValue - Specifies a pointer to item to remove.
  535. The specified value and type depends on PropertyId. The valid values are:
  536. AZ_PROP_ROLE_APP_MEMBERS LPWSTR - Application groups that are members of this role
  537. AZ_PROP_ROLE_MEMBERS PSID - NT Sids that are members of this role
  538. AZ_PROP_ROLE_OPERATIONS LPWSTR - Operations the can be performed by this role
  539. AZ_PROP_ROLE_SCOPES LPWSTR - Scopes this role applies to
  540. Return Value:
  541. NO_ERROR - The operation was successful
  542. ERROR_INVALID_PARAMETER - PropertyId isn't valid
  543. ERROR_NOT_FOUND - There is no item by that name in the list
  544. --*/
  545. {
  546. PGENERIC_OBJECT_LIST GenericObjectList;
  547. //
  548. // Validate the Property ID
  549. //
  550. switch ( PropertyId ) {
  551. case AZ_PROP_ROLE_APP_MEMBERS:
  552. GenericObjectList = &((PAZP_ROLE)RoleHandle)->AppMembers;
  553. break;
  554. case AZ_PROP_ROLE_MEMBERS:
  555. GenericObjectList = &((PAZP_ROLE)RoleHandle)->SidMembers;
  556. break;
  557. case AZ_PROP_ROLE_OPERATIONS:
  558. GenericObjectList = &((PAZP_ROLE)RoleHandle)->Operations;
  559. break;
  560. case AZ_PROP_ROLE_SCOPES:
  561. GenericObjectList = &((PAZP_ROLE)RoleHandle)->Scopes;
  562. break;
  563. default:
  564. AzPrint(( AZD_INVPARM, "AzRoleRemovePropertyItem: invalid prop id %ld\n", PropertyId ));
  565. return ERROR_INVALID_PARAMETER;
  566. }
  567. //
  568. // Call the common routine to do most of the work
  569. //
  570. return ObCommonRemovePropertyItem (
  571. (PGENERIC_OBJECT) RoleHandle,
  572. OBJECT_TYPE_ROLE,
  573. GenericObjectList,
  574. Reserved,
  575. (LPWSTR) PropertyValue );
  576. }
  577. DWORD
  578. WINAPI
  579. AzRoleDelete(
  580. IN AZ_HANDLE ParentHandle,
  581. IN LPCWSTR RoleName,
  582. IN DWORD Reserved
  583. )
  584. /*++
  585. Routine Description:
  586. This routine deletes a role from the scope of the specified parent object.
  587. Also deletes any child objects of RoleName.
  588. Arguments:
  589. ParentHandle - Specifies a handle to the object that is the parent of the role.
  590. This may be an Application Handle or a Scope handle.
  591. RoleName - Specifies the name of the role to delete.
  592. Reserved - Reserved. Must by zero.
  593. Return Value:
  594. NO_ERROR - The operation was successful
  595. ERROR_NOT_FOUND - An object by that name cannot be found
  596. --*/
  597. {
  598. DWORD WinStatus;
  599. DWORD ObjectType;
  600. PGENERIC_OBJECT_HEAD GenericChildHead;
  601. //
  602. // Determine that the parent handle supports roles as children
  603. //
  604. WinStatus = AzpRoleGetGenericChildHead( ParentHandle,
  605. &ObjectType,
  606. &GenericChildHead );
  607. if ( WinStatus != NO_ERROR ) {
  608. return WinStatus;
  609. }
  610. //
  611. // Call the common routine to do most of the work
  612. //
  613. return ObCommonDeleteObject(
  614. (PGENERIC_OBJECT) ParentHandle,
  615. ObjectType,
  616. GenericChildHead,
  617. OBJECT_TYPE_ROLE,
  618. RoleName,
  619. Reserved );
  620. }