Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

739 lines
18 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. op.cxx
  5. Abstract:
  6. Routines implementing the Operation object
  7. Author:
  8. Cliff Van Dyke (cliffv) 11-Apr-2001
  9. --*/
  10. #include "pch.hxx"
  11. //
  12. // Define the default values for all scalar attributes
  13. //
  14. ULONG AzGlDefOperationId = 0;
  15. AZP_DEFAULT_VALUE AzGlOperationDefaultValues[] = {
  16. { AZ_PROP_OPERATION_ID, AZ_DIRTY_OPERATION_ID, &AzGlDefOperationId },
  17. { 0, 0, NULL }
  18. };
  19. DWORD
  20. AzpOperationInit(
  21. IN PGENERIC_OBJECT ParentGenericObject,
  22. IN PGENERIC_OBJECT ChildGenericObject
  23. )
  24. /*++
  25. Routine Description:
  26. This routine is a worker routine for AzOperationCreate. It does any object specific
  27. initialization that needs to be done.
  28. On entry, AzGlResource must be locked exclusively.
  29. Arguments:
  30. ParentGenericObject - Specifies the parent object to add the child object onto.
  31. The reference count has been incremented on this object.
  32. ChildGenericObject - Specifies the newly allocated child object.
  33. The reference count has been incremented on this object.
  34. Return Value:
  35. NO_ERROR - The operation was successful
  36. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  37. Other exception status codes
  38. --*/
  39. {
  40. PAZP_OPERATION Operation = (PAZP_OPERATION) ChildGenericObject;
  41. //
  42. // Initialization
  43. //
  44. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  45. //
  46. // Sanity check the parent
  47. //
  48. ASSERT( ParentGenericObject->ObjectType == OBJECT_TYPE_APPLICATION );
  49. UNREFERENCED_PARAMETER( ParentGenericObject );
  50. //
  51. // Operations are referenced by "Tasks" and "Roles"
  52. // Let the generic object manager know all of the lists we support
  53. // This is a "back" link so we don't need to define which tasks can reference this operation.
  54. //
  55. ChildGenericObject->GenericObjectLists = &Operation->backTasks;
  56. // Back link to tasks
  57. ObInitObjectList( &Operation->backTasks,
  58. &Operation->backRoles,
  59. TRUE, // Backward link
  60. 0, // No link pair id
  61. 0, // No dirty bit on back link
  62. NULL,
  63. NULL,
  64. NULL );
  65. // Back link to roles
  66. ObInitObjectList( &Operation->backRoles,
  67. NULL,
  68. TRUE, // Backward link
  69. 0, // No link pair id
  70. 0, // No dirty bit on back link
  71. NULL,
  72. NULL,
  73. NULL );
  74. return NO_ERROR;
  75. }
  76. VOID
  77. AzpOperationFree(
  78. IN PGENERIC_OBJECT GenericObject
  79. )
  80. /*++
  81. Routine Description:
  82. This routine is a worker routine for Operation object free. It does any object specific
  83. cleanup that needs to be done.
  84. On entry, AzGlResource must be locked exclusively.
  85. Arguments:
  86. GenericObject - Specifies a pointer to the object to be deleted.
  87. Return Value:
  88. None
  89. --*/
  90. {
  91. // PAZP_OPERATION Operation = (PAZP_OPERATION) GenericObject;
  92. UNREFERENCED_PARAMETER( GenericObject );
  93. //
  94. // Initialization
  95. //
  96. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  97. //
  98. // Free any local strings
  99. //
  100. }
  101. DWORD
  102. AzpOperationNameConflict(
  103. IN PGENERIC_OBJECT ParentGenericObject,
  104. IN PAZP_STRING ChildObjectNameString
  105. )
  106. /*++
  107. Routine Description:
  108. This routine is a worker routine to determine if the specified ChildObjectNameString
  109. conflicts with the names of other objects that share a namespace with Operations.
  110. On entry, AzGlResource must be locked exclusively.
  111. Arguments:
  112. ParentGenericObject - Specifies the parent object to add the child object onto.
  113. The reference count has been incremented on this object.
  114. ChildObjectNameString - Specifies the name of the child object.
  115. Return Value:
  116. NO_ERROR - The operation was successful
  117. ERROR_ALREADY_EXISTS - An object by that name already exists
  118. --*/
  119. {
  120. ULONG WinStatus;
  121. PAZP_APPLICATION Application = (PAZP_APPLICATION) ParentGenericObject;
  122. PGENERIC_OBJECT ConflictGenericObject;
  123. //
  124. // Initialization
  125. //
  126. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  127. //
  128. // Sanity check the parent
  129. //
  130. ASSERT( ParentGenericObject->ObjectType == OBJECT_TYPE_APPLICATION );
  131. //
  132. // Operations and tasks share a namespace so ensure there isn't a task by this name.
  133. //
  134. WinStatus = ObReferenceObjectByName( &Application->Tasks,
  135. ChildObjectNameString,
  136. 0, // No special flags
  137. &ConflictGenericObject );
  138. if ( WinStatus == NO_ERROR ) {
  139. ObDereferenceObject( ConflictGenericObject );
  140. return ERROR_ALREADY_EXISTS;
  141. }
  142. //
  143. // Check tasks that are children of child scopes.
  144. //
  145. WinStatus = ObCheckNameConflict( &Application->Scopes,
  146. ChildObjectNameString,
  147. offsetof(_AZP_SCOPE, Tasks),
  148. 0,
  149. 0 );
  150. return WinStatus;
  151. }
  152. DWORD
  153. AzpOperationGetProperty(
  154. IN PGENERIC_OBJECT GenericObject,
  155. IN ULONG Flags,
  156. IN ULONG PropertyId,
  157. OUT PVOID *PropertyValue
  158. )
  159. /*++
  160. Routine Description:
  161. This routine is the Group specific worker routine for AzGetProperty.
  162. It does any object specific property gets.
  163. On entry, AzGlResource must be locked shared.
  164. Arguments:
  165. GenericObject - Specifies a pointer to the object to be queried
  166. Flags - Specifies internal flags
  167. AZP_FLAGS_BY_GUID - name lists should be returned as GUID lists
  168. AZP_FLAGS_PERSIST_* - Call is from the persistence provider
  169. PropertyId - Specifies which property to return.
  170. PropertyValue - Specifies a pointer to return the property in.
  171. The returned pointer must be freed using AzFreeMemory.
  172. The returned value and type depends in PropertyId. The valid values are:
  173. AZ_PROP_OPERATION_ID PULONG - Operation ID of the operation
  174. Return Value:
  175. Status of the operation
  176. --*/
  177. {
  178. DWORD WinStatus = NO_ERROR;
  179. PAZP_OPERATION Operation = (PAZP_OPERATION) GenericObject;
  180. UNREFERENCED_PARAMETER(Flags); //ignore
  181. //
  182. // Initialization
  183. //
  184. ASSERT( AzpIsLockedShared( &AzGlResource ) );
  185. //
  186. // Return any object specific attribute
  187. //
  188. // Return operation id to the caller
  189. //
  190. switch ( PropertyId ) {
  191. case AZ_PROP_OPERATION_ID:
  192. *PropertyValue = AzpGetUlongProperty( Operation->OperationId );
  193. if ( *PropertyValue == NULL ) {
  194. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  195. }
  196. break;
  197. default:
  198. AzPrint(( AZD_INVPARM, "AzpOperationGetProperty: invalid prop id %ld\n", PropertyId ));
  199. WinStatus = ERROR_INVALID_PARAMETER;
  200. break;
  201. }
  202. return WinStatus;
  203. }
  204. DWORD
  205. AzpOperationSetProperty(
  206. IN PGENERIC_OBJECT GenericObject,
  207. IN ULONG Flags,
  208. IN ULONG PropertyId,
  209. IN PVOID PropertyValue
  210. )
  211. /*++
  212. Routine Description:
  213. This routine is the Operation object specific worker routine for AzSetProperty.
  214. It does any object specific property sets.
  215. On entry, AzGlResource must be locked exclusive.
  216. Arguments:
  217. GenericObject - Specifies a pointer to the object to be modified
  218. Flags - Specifies flags controlling to operation of the routine
  219. AZP_FLAGS_SETTING_TO_DEFAULT - Property is being set to default value
  220. AZP_FLAGS_PERSIST_* - Call is from the persistence provider
  221. PropertyId - Specifies which property to set.
  222. PropertyValue - Specifies a pointer to the property.
  223. The specified value and type depends in PropertyId. The valid values are:
  224. AZ_PROP_OPERATION_ID PULONG - Operation ID of the operation
  225. Return Value:
  226. Status of the operation
  227. --*/
  228. {
  229. DWORD WinStatus;
  230. PAZP_OPERATION Operation = (PAZP_OPERATION) GenericObject;
  231. PAZP_OPERATION ReferencedOperation = NULL;
  232. LONG TempLong;
  233. BOOL bHasChanged = TRUE;
  234. //
  235. // Initialization
  236. //
  237. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  238. //
  239. // Return any object specific attribute
  240. //
  241. // Return ooperation id to the caller
  242. //
  243. switch ( PropertyId ) {
  244. case AZ_PROP_OPERATION_ID:
  245. BEGIN_SETPROP( &WinStatus, Operation, Flags, AZ_DIRTY_OPERATION_ID ) {
  246. WinStatus = AzpCaptureLong( PropertyValue, &TempLong );
  247. if ( WinStatus != NO_ERROR ) {
  248. goto Cleanup;
  249. }
  250. //
  251. // Do parameter validity checking
  252. //
  253. BEGIN_VALIDITY_CHECKING( Flags ) {
  254. if ( TempLong < 0) {
  255. AzPrint(( AZD_INVPARM, "AzpOperationSetProperty: Operation Id too small %ld\n", TempLong ));
  256. WinStatus = ERROR_INVALID_PARAMETER;
  257. goto Cleanup;
  258. }
  259. //
  260. // Ensure the operation id doesn't collide with another operation
  261. //
  262. WinStatus = AzpReferenceOperationByOpId(
  263. (PAZP_APPLICATION)ParentOfChild( GenericObject ),
  264. TempLong,
  265. FALSE,
  266. &ReferencedOperation );
  267. if ( WinStatus == NO_ERROR ) {
  268. if ( ReferencedOperation != Operation ) {
  269. AzPrint(( AZD_INVPARM, "AzpOperationSetProperty: Operation ID %ld is already used.\n", TempLong ));
  270. WinStatus = ERROR_ALREADY_EXISTS;
  271. goto Cleanup;
  272. }
  273. //
  274. // Allow setting our own operation ID back to its original value
  275. //
  276. WinStatus = ERROR_NOT_FOUND;
  277. }
  278. if ( WinStatus != ERROR_NOT_FOUND ) {
  279. goto Cleanup;
  280. }
  281. } END_VALIDITY_CHECKING;
  282. //
  283. // Set the operation ID on the object
  284. //
  285. Operation->OperationId = TempLong;
  286. WinStatus = NO_ERROR;
  287. } END_SETPROP(bHasChanged);
  288. break;
  289. default:
  290. AzPrint(( AZD_INVPARM, "AzpOperationSetProperty: invalid prop id %ld\n", PropertyId ));
  291. WinStatus = ERROR_INVALID_PARAMETER;
  292. break;
  293. }
  294. Cleanup:
  295. if ( ReferencedOperation != NULL ) {
  296. ObDereferenceObject( (PGENERIC_OBJECT)ReferencedOperation );
  297. }
  298. return WinStatus;
  299. }
  300. DWORD
  301. AzpReferenceOperationByOpId(
  302. IN PAZP_APPLICATION Application,
  303. IN LONG OperationId,
  304. IN BOOLEAN RefreshCache,
  305. OUT PAZP_OPERATION *RetOperation
  306. )
  307. /*++
  308. Routine Description
  309. This routine finds an operation object by the operationid
  310. On entry, AzGlResource must be locked shared.
  311. Arguments
  312. Application - Application that the operation is defined for
  313. OperationId - Operation id to look for
  314. RefreshCache - If TRUE, the returned object has its cache entry refreshed from
  315. the policy database if needed.
  316. If FALSE, the entry is returned unrefreshed.
  317. RetOperation - On success, returns a pointer to the operation object
  318. The returned pointer must be dereferenced using ObDereferenceObject.
  319. Return Value
  320. NO_ERROR: The object was returned
  321. ERROR_NOT_FOUND: The object could not be found
  322. Others: The object could not be refreshed
  323. --*/
  324. {
  325. DWORD WinStatus;
  326. PGENERIC_OBJECT GenericObject;
  327. PAZP_OPERATION Operation;
  328. PLIST_ENTRY ListEntry;
  329. PGENERIC_OBJECT_HEAD GenericObjectHead = &Application->Operations;
  330. //
  331. // Initialization
  332. //
  333. ASSERT( AzpIsLockedShared( &AzGlResource ) );
  334. *RetOperation = NULL;
  335. //
  336. // Loop trying to find the object
  337. //
  338. // ??? Consider doing a binary search. That would be possible if we maintained
  339. // a separate list sorted by operation id
  340. //
  341. for ( ListEntry = GenericObjectHead->Head.Flink ;
  342. ListEntry != &GenericObjectHead->Head ;
  343. ListEntry = ListEntry->Flink) {
  344. GenericObject = CONTAINING_RECORD( ListEntry,
  345. GENERIC_OBJECT,
  346. Next );
  347. Operation = (PAZP_OPERATION) GenericObject;
  348. //
  349. // Ignore deleted objects
  350. //
  351. if ( GenericObject->Flags & GENOBJ_FLAGS_DELETED ) {
  352. continue;
  353. }
  354. //
  355. // If we found the object,
  356. // grab a reference.
  357. //
  358. if ( Operation->OperationId == OperationId ) {
  359. //
  360. // If the caller wants the object to be refreshed,
  361. // do so now.
  362. //
  363. if ( RefreshCache &&
  364. (GenericObject->Flags & GENOBJ_FLAGS_REFRESH_ME) != 0 ) {
  365. //
  366. // Need exclusive access
  367. //
  368. AzpLockResourceSharedToExclusive( &AzGlResource );
  369. WinStatus = AzPersistRefresh( GenericObject );
  370. if ( WinStatus != NO_ERROR ) {
  371. return WinStatus;
  372. }
  373. }
  374. //
  375. // Return the object to the caller
  376. //
  377. InterlockedIncrement( &GenericObject->ReferenceCount );
  378. AzpDumpGoRef( "Ref by operation id", GenericObject );
  379. *RetOperation = Operation;
  380. return NO_ERROR;
  381. }
  382. }
  383. return ERROR_NOT_FOUND;
  384. }
  385. DWORD
  386. WINAPI
  387. AzOperationCreate(
  388. IN AZ_HANDLE ApplicationHandle,
  389. IN LPCWSTR OperationName,
  390. IN DWORD Reserved,
  391. OUT PAZ_HANDLE OperationHandle
  392. )
  393. /*++
  394. Routine Description:
  395. This routine adds an operation into the scope of the specified application.
  396. Arguments:
  397. ApplicationHandle - Specifies a handle to the application.
  398. OperationName - Specifies the name of the operation to add.
  399. Reserved - Reserved. Must by zero.
  400. OperationHandle - Return a handle to the operation.
  401. The caller must close this handle by calling AzCloseHandle.
  402. Return Value:
  403. NO_ERROR - The operation was successful
  404. ERROR_ALREADY_EXISTS - An object by that name already exists
  405. --*/
  406. {
  407. //
  408. // Call the common routine to do most of the work
  409. //
  410. return ObCommonCreateObject(
  411. (PGENERIC_OBJECT) ApplicationHandle,
  412. OBJECT_TYPE_APPLICATION,
  413. &(((PAZP_APPLICATION)ApplicationHandle)->Operations),
  414. OBJECT_TYPE_OPERATION,
  415. OperationName,
  416. Reserved,
  417. (PGENERIC_OBJECT *) OperationHandle );
  418. }
  419. DWORD
  420. WINAPI
  421. AzOperationOpen(
  422. IN AZ_HANDLE ApplicationHandle,
  423. IN LPCWSTR OperationName,
  424. IN DWORD Reserved,
  425. OUT PAZ_HANDLE OperationHandle
  426. )
  427. /*++
  428. Routine Description:
  429. This routine opens an operation into the scope of the specified application.
  430. Arguments:
  431. ApplicationHandle - Specifies a handle to the application.
  432. OperationName - Specifies the name of the operation to open
  433. Reserved - Reserved. Must by zero.
  434. OperationHandle - Return a handle to the operation.
  435. The caller must close this handle by calling AzCloseHandle.
  436. Return Value:
  437. NO_ERROR - The operation was successful
  438. ERROR_NOT_FOUND - There is no operation by that name
  439. --*/
  440. {
  441. //
  442. // Call the common routine to do most of the work
  443. //
  444. return ObCommonOpenObject(
  445. (PGENERIC_OBJECT) ApplicationHandle,
  446. OBJECT_TYPE_APPLICATION,
  447. &(((PAZP_APPLICATION)ApplicationHandle)->Operations),
  448. OBJECT_TYPE_OPERATION,
  449. OperationName,
  450. Reserved,
  451. (PGENERIC_OBJECT *) OperationHandle );
  452. }
  453. DWORD
  454. WINAPI
  455. AzOperationEnum(
  456. IN AZ_HANDLE ApplicationHandle,
  457. IN DWORD Reserved,
  458. IN OUT PULONG EnumerationContext,
  459. OUT PAZ_HANDLE OperationHandle
  460. )
  461. /*++
  462. Routine Description:
  463. Enumerates all of the operations for the specified application.
  464. Arguments:
  465. ApplicationHandle - Specifies a handle to the application.
  466. Reserved - Reserved. Must by zero.
  467. EnumerationContext - Specifies a context indicating the next operation to return
  468. On input for the first call, should point to zero.
  469. On input for subsequent calls, should point to the value returned on the previous call.
  470. On output, returns a value to be passed on the next call.
  471. OperationHandle - Returns a handle to the next operation object.
  472. The caller must close this handle by calling AzCloseHandle.
  473. Return Value:
  474. NO_ERROR - The operation was successful (a handle was returned)
  475. ERROR_NO_MORE_ITEMS - No more items were available for enumeration
  476. --*/
  477. {
  478. //
  479. // Call the common routine to do most of the work
  480. //
  481. return ObCommonEnumObjects(
  482. (PGENERIC_OBJECT) ApplicationHandle,
  483. OBJECT_TYPE_APPLICATION,
  484. &(((PAZP_APPLICATION)ApplicationHandle)->Operations),
  485. EnumerationContext,
  486. Reserved,
  487. (PGENERIC_OBJECT *) OperationHandle );
  488. }
  489. DWORD
  490. WINAPI
  491. AzOperationDelete(
  492. IN AZ_HANDLE ApplicationHandle,
  493. IN LPCWSTR OperationName,
  494. IN DWORD Reserved
  495. )
  496. /*++
  497. Routine Description:
  498. This routine deletes an operation from the scope of the specified application.
  499. Also deletes any child objects of OperationName.
  500. Arguments:
  501. ApplicationHandle - Specifies a handle to the application.
  502. OperationName - Specifies the name of the operation to delete.
  503. Reserved - Reserved. Must by zero.
  504. Return Value:
  505. NO_ERROR - The operation was successful
  506. ERROR_NOT_FOUND - An object by that name cannot be found
  507. --*/
  508. {
  509. //
  510. // Call the common routine to do most of the work
  511. //
  512. return ObCommonDeleteObject(
  513. (PGENERIC_OBJECT) ApplicationHandle,
  514. OBJECT_TYPE_APPLICATION,
  515. &(((PAZP_APPLICATION)ApplicationHandle)->Operations),
  516. OBJECT_TYPE_OPERATION,
  517. OperationName,
  518. Reserved );
  519. }