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.

829 lines
19 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. junction.cxx
  5. Abstract:
  6. Routines implementing the JunctionPoint object
  7. Author:
  8. Cliff Van Dyke (cliffv) 11-Apr-2001
  9. --*/
  10. #include "pch.hxx"
  11. DWORD
  12. AzpJunctionPointInit(
  13. IN PGENERIC_OBJECT ParentGenericObject,
  14. IN PGENERIC_OBJECT ChildGenericObject
  15. )
  16. /*++
  17. Routine Description:
  18. This routine is a worker routine for AzJunctionPointCreate. 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_JUNCTION_POINT JunctionPoint = (PAZP_JUNCTION_POINT) ChildGenericObject;
  33. // PAZP_APPLICATION Application = (PAZP_APPLICATION) ParentGenericObject;
  34. PAZP_ADMIN_MANAGER AdminManager;
  35. //
  36. // Initialization
  37. //
  38. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  39. //
  40. // Sanity check the parent
  41. //
  42. ASSERT( ParentGenericObject->ObjectType == OBJECT_TYPE_APPLICATION );
  43. AdminManager = ParentGenericObject->AdminManagerObject;
  44. //
  45. // JunctionPoints reference 'Applications' that are children of the same 'AdminManager' as the JunctionPoint object
  46. // Let the generic object manager know all of the lists we support
  47. //
  48. ChildGenericObject->GenericObjectLists = &JunctionPoint->Applications,
  49. ObInitObjectList( &JunctionPoint->Applications,
  50. NULL,
  51. FALSE, // Forward link
  52. 0, // No link pair id
  53. &AdminManager->Applications,
  54. NULL,
  55. NULL );
  56. return NO_ERROR;
  57. }
  58. VOID
  59. AzpJunctionPointFree(
  60. IN PGENERIC_OBJECT GenericObject
  61. )
  62. /*++
  63. Routine Description:
  64. This routine is a worker routine for JunctionPoint object free. It does any object specific
  65. cleanup that needs to be done.
  66. On entry, AzGlResource must be locked exclusively.
  67. Arguments:
  68. GenericObject - Specifies a pointer to the object to be deleted.
  69. Return Value:
  70. None
  71. --*/
  72. {
  73. // PAZP_JUNCTION_POINT JunctionPoint = (PAZP_JUNCTION_POINT) GenericObject;
  74. UNREFERENCED_PARAMETER( GenericObject );
  75. //
  76. // Initialization
  77. //
  78. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  79. //
  80. // Free any local strings
  81. //
  82. }
  83. DWORD
  84. AzpJunctionPointGetProperty(
  85. IN PGENERIC_OBJECT GenericObject,
  86. IN ULONG PropertyId,
  87. OUT PVOID *PropertyValue
  88. )
  89. /*++
  90. Routine Description:
  91. This routine is a worker routine for AzJunctionPointGetProperty. It does any object specific
  92. property gets.
  93. On entry, AzGlResource must be locked shared.
  94. Arguments:
  95. GenericObject - Specifies a pointer to the object to be queried
  96. PropertyId - Specifies which property to return.
  97. PropertyValue - Specifies a pointer to return the property in.
  98. The returned pointer must be freed using AzFreeMemory.
  99. The returned value and type depends in PropertyId. The valid values are:
  100. AZ_PROP_JUNCTION_POINT_APPLICATION LPWSTR - Application linked to this junction point
  101. Return Value:
  102. Status of the operation
  103. --*/
  104. {
  105. DWORD WinStatus = NO_ERROR;
  106. PAZP_JUNCTION_POINT JunctionPoint = (PAZP_JUNCTION_POINT) GenericObject;
  107. PAZ_STRING_ARRAY TempStringArray = NULL;
  108. AZP_STRING TempString;
  109. //
  110. // Initialization
  111. //
  112. ASSERT( AzpIsLockedShared( &AzGlResource ) );
  113. AzpInitString( &TempString, NULL );
  114. //
  115. // Return any object specific attribute
  116. //
  117. switch ( PropertyId ) {
  118. //
  119. // Return the application name to the caller
  120. //
  121. case AZ_PROP_JUNCTION_POINT_APPLICATION:
  122. //
  123. // The link is stored as an array since that's the common mechanism of
  124. // keeping links between objects
  125. //
  126. TempStringArray = ObGetPropertyItems( &JunctionPoint->Applications );
  127. if ( TempStringArray == NULL ) {
  128. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  129. goto Cleanup;
  130. }
  131. //
  132. // If there is a string to return,
  133. // return just that one.
  134. //
  135. ASSERT( TempStringArray->StringCount <= 1 );
  136. if ( TempStringArray->StringCount != 0 ) {
  137. AzpInitString( &TempString, TempStringArray->Strings[0] );
  138. }
  139. //
  140. // Allocate it and return it
  141. //
  142. *PropertyValue = AzpGetStringProperty( &TempString );
  143. if ( *PropertyValue == NULL ) {
  144. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  145. }
  146. break;
  147. default:
  148. AzPrint(( AZD_INVPARM, "AzpJunctionPointGetProperty: invalid prop id %ld\n", PropertyId ));
  149. WinStatus = ERROR_INVALID_PARAMETER;
  150. break;
  151. }
  152. //
  153. // Free any local resources
  154. //
  155. Cleanup:
  156. if ( TempStringArray != NULL ) {
  157. AzFreeMemory( TempStringArray );
  158. }
  159. return WinStatus;
  160. }
  161. DWORD
  162. AzpJunctionPointSetProperty(
  163. IN PGENERIC_OBJECT GenericObject,
  164. IN ULONG PropertyId,
  165. IN PVOID PropertyValue
  166. )
  167. /*++
  168. Routine Description:
  169. This routine is a worker routine for AzJunctionPointSetProperty. It does any object specific
  170. property sets.
  171. On entry, AzGlResource must be locked exclusive.
  172. Arguments:
  173. GenericObject - Specifies a pointer to the object to be modified
  174. PropertyId - Specifies which property to set.
  175. PropertyValue - Specifies a pointer to the property.
  176. The specified value and type depends in PropertyId. The valid values are:
  177. AZ_PROP_JUNCTION_POINT_APPLICATION LPWSTR - Application linked to this junction point
  178. Return Value:
  179. Status of the operation
  180. --*/
  181. {
  182. DWORD WinStatus = NO_ERROR;
  183. PAZP_JUNCTION_POINT JunctionPoint = (PAZP_JUNCTION_POINT) GenericObject;
  184. PAZ_STRING_ARRAY TempStringArray = NULL;
  185. AZP_STRING CapturedString;
  186. AZP_STRING TempString;
  187. ULONG i;
  188. //
  189. // Initialization
  190. //
  191. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  192. AzpInitString( &CapturedString, NULL );
  193. //
  194. // Set any object specific attribute
  195. //
  196. switch ( PropertyId ) {
  197. //
  198. // Set the application name
  199. //
  200. case AZ_PROP_JUNCTION_POINT_APPLICATION:
  201. //
  202. // Get the current list of items.
  203. //
  204. TempStringArray = ObGetPropertyItems( &JunctionPoint->Applications );
  205. if ( TempStringArray == NULL ) {
  206. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  207. goto Cleanup;
  208. }
  209. //
  210. // Capture the the new application name
  211. //
  212. WinStatus = AzpCaptureString( &CapturedString,
  213. (LPWSTR) PropertyValue,
  214. AZ_MAX_APPLICATION_NAME_LENGTH,
  215. FALSE );
  216. if ( WinStatus != NO_ERROR ) {
  217. goto Cleanup;
  218. }
  219. //
  220. // Add the new application name
  221. //
  222. WinStatus = ObAddPropertyItem(
  223. GenericObject,
  224. &JunctionPoint->Applications,
  225. &CapturedString );
  226. if ( WinStatus != NO_ERROR ) {
  227. goto Cleanup;
  228. }
  229. //
  230. // Remove any old names
  231. // Remove them all even if there is more than one
  232. //
  233. //
  234. for ( i=0; i<TempStringArray->StringCount; i++ ) {
  235. //
  236. // Ignore errors. This is done on a best-effort basis
  237. //
  238. AzpInitString( &TempString, TempStringArray->Strings[i] );
  239. WinStatus = ObRemovePropertyItem(
  240. GenericObject,
  241. &JunctionPoint->Applications,
  242. &TempString );
  243. ASSERT(WinStatus == NO_ERROR);
  244. }
  245. break;
  246. default:
  247. AzPrint(( AZD_INVPARM, "AzpJunctionPointSetProperty: invalid prop id %ld\n", PropertyId ));
  248. WinStatus = ERROR_INVALID_PARAMETER;
  249. goto Cleanup;
  250. }
  251. WinStatus = NO_ERROR;
  252. //
  253. // Free any local resources
  254. //
  255. Cleanup:
  256. if ( TempStringArray != NULL ) {
  257. AzFreeMemory( TempStringArray );
  258. }
  259. AzpFreeString( &CapturedString );
  260. return WinStatus;
  261. }
  262. DWORD
  263. AzpJunctionPointCheckRefLoop(
  264. IN PAZP_JUNCTION_POINT ParentJunctionPoint,
  265. IN PAZP_APPLICATION CurrentApplication
  266. )
  267. /*++
  268. Routine Description:
  269. This routine determines whether the junction points of "CurrentApplication"
  270. reference the application that hosts "ParentJunctionPoint".
  271. This is done to detect loops where the
  272. junction point of one application references itself directly or indirectly.
  273. On entry, AzGlResource must be locked shared.
  274. Arguments:
  275. ParentJunctionPoint - JunctionPoint object that is being modified.
  276. CurrentApplication - Application that is directly or indirectly referenced by the
  277. junction point.
  278. Return Value:
  279. Status of the operation
  280. ERROR_DS_LOOP_DETECT - A loop has been detected.
  281. --*/
  282. {
  283. ULONG WinStatus;
  284. ULONG i;
  285. PLIST_ENTRY ListEntry;
  286. PAZP_APPLICATION ParentApplication;
  287. PAZP_JUNCTION_POINT JunctionPoint;
  288. PAZP_APPLICATION NextApplication;
  289. //
  290. // Check for a reference to ourself
  291. //
  292. ASSERT( AzpIsLockedShared( &AzGlResource ) );
  293. ParentApplication = (PAZP_APPLICATION)
  294. ParentJunctionPoint->GenericObject.ParentGenericObjectHead->ParentGenericObject;
  295. if ( ParentApplication == CurrentApplication ) {
  296. return ERROR_DS_LOOP_DETECT;
  297. }
  298. //
  299. // Check all junction points of the current application
  300. //
  301. for ( ListEntry = CurrentApplication->JunctionPoints.Head.Flink ;
  302. ListEntry != &CurrentApplication->JunctionPoints.Head ;
  303. ListEntry = ListEntry->Flink) {
  304. JunctionPoint = (PAZP_JUNCTION_POINT)
  305. CONTAINING_RECORD( ListEntry,
  306. GENERIC_OBJECT,
  307. Next );
  308. //
  309. // Check all applications (there should only be zero or one) linked to that junction point
  310. //
  311. for ( i=0; i<JunctionPoint->Applications.GenericObjects.UsedCount; i++ ) {
  312. NextApplication = (PAZP_APPLICATION)
  313. (JunctionPoint->Applications.GenericObjects.Array[i]);
  314. WinStatus = AzpJunctionPointCheckRefLoop( ParentJunctionPoint,
  315. NextApplication );
  316. if ( WinStatus != NO_ERROR ) {
  317. return WinStatus;
  318. }
  319. }
  320. }
  321. return NO_ERROR;
  322. }
  323. DWORD
  324. AzpJunctionPointAddPropertyItem(
  325. IN PGENERIC_OBJECT GenericObject,
  326. IN PGENERIC_OBJECT_LIST GenericObjectList,
  327. IN PGENERIC_OBJECT LinkedToObject
  328. )
  329. /*++
  330. Routine Description:
  331. This routine is a worker routine for AzJunctionPointAddPropertyItem.
  332. It does any object specific property adds
  333. On entry, AzGlResource must be locked exclusive.
  334. Arguments:
  335. GenericObject - Specifies a pointer to the junction point object to be modified
  336. GenericObjectList - Specifies the object list the object is to be added to
  337. LinkedToObject - Specifies the application object that is being linked to
  338. Return Value:
  339. Status of the operation
  340. --*/
  341. {
  342. DWORD WinStatus = NO_ERROR;
  343. PAZP_JUNCTION_POINT JunctionPoint = (PAZP_JUNCTION_POINT) GenericObject;
  344. UNREFERENCED_PARAMETER( GenericObjectList );
  345. //
  346. // Initialization
  347. //
  348. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  349. //
  350. // Ensure this newly added application doesn't cause a loop
  351. //
  352. WinStatus = AzpJunctionPointCheckRefLoop(
  353. JunctionPoint,
  354. (PAZP_APPLICATION)LinkedToObject );
  355. //
  356. // Free any local resources
  357. //
  358. return WinStatus;
  359. }
  360. DWORD
  361. WINAPI
  362. AzJunctionPointCreate(
  363. IN AZ_HANDLE ApplicationHandle,
  364. IN LPCWSTR JunctionPointName,
  365. IN DWORD Reserved,
  366. OUT PAZ_HANDLE JunctionPointHandle
  367. )
  368. /*++
  369. Routine Description:
  370. This routine adds a junction point into the scope of the specified application.
  371. Arguments:
  372. ApplicationHandle - Specifies a handle to the application.
  373. JunctionPointName - Specifies the name of the junction point to add.
  374. Reserved - Reserved. Must by zero.
  375. JunctionPointHandle - Return a handle to the junction point.
  376. The caller must close this handle by calling AzCloseHandle.
  377. Return Value:
  378. NO_ERROR - The operation was successful
  379. ERROR_ALREADY_EXISTS - An object by that name already exists
  380. --*/
  381. {
  382. //
  383. // Call the common routine to do most of the work
  384. //
  385. return ObCommonCreateObject(
  386. (PGENERIC_OBJECT) ApplicationHandle,
  387. OBJECT_TYPE_APPLICATION,
  388. &(((PAZP_APPLICATION)ApplicationHandle)->JunctionPoints),
  389. OBJECT_TYPE_JUNCTION_POINT,
  390. JunctionPointName,
  391. Reserved,
  392. (PGENERIC_OBJECT *) JunctionPointHandle );
  393. }
  394. DWORD
  395. WINAPI
  396. AzJunctionPointOpen(
  397. IN AZ_HANDLE ApplicationHandle,
  398. IN LPCWSTR JunctionPointName,
  399. IN DWORD Reserved,
  400. OUT PAZ_HANDLE JunctionPointHandle
  401. )
  402. /*++
  403. Routine Description:
  404. This routine opens a junction point into the scope of the specified application.
  405. Arguments:
  406. ApplicationHandle - Specifies a handle to the application.
  407. JunctionPointName - Specifies the name of the junction point to open
  408. Reserved - Reserved. Must by zero.
  409. JunctionPointHandle - Return a handle to the junction point.
  410. The caller must close this handle by calling AzCloseHandle.
  411. Return Value:
  412. NO_ERROR - The operation was successful
  413. ERROR_NOT_FOUND - There is no junction point by that name
  414. --*/
  415. {
  416. //
  417. // Call the common routine to do most of the work
  418. //
  419. return ObCommonOpenObject(
  420. (PGENERIC_OBJECT) ApplicationHandle,
  421. OBJECT_TYPE_APPLICATION,
  422. &(((PAZP_APPLICATION)ApplicationHandle)->JunctionPoints),
  423. OBJECT_TYPE_JUNCTION_POINT,
  424. JunctionPointName,
  425. Reserved,
  426. (PGENERIC_OBJECT *) JunctionPointHandle );
  427. }
  428. DWORD
  429. WINAPI
  430. AzJunctionPointEnum(
  431. IN AZ_HANDLE ApplicationHandle,
  432. IN DWORD Reserved,
  433. IN OUT PULONG EnumerationContext,
  434. OUT PAZ_HANDLE JunctionPointHandle
  435. )
  436. /*++
  437. Routine Description:
  438. Enumerates all of the junction points for the specified application.
  439. Arguments:
  440. ApplicationHandle - Specifies a handle to the application.
  441. Reserved - Reserved. Must by zero.
  442. EnumerationContext - Specifies a context indicating the next junction point to return
  443. On input for the first call, should point to zero.
  444. On input for subsequent calls, should point to the value returned on the previous call.
  445. On output, returns a value to be passed on the next call.
  446. JunctionPointHandle - Returns a handle to the next junction point object.
  447. The caller must close this handle by calling AzCloseHandle.
  448. Return Value:
  449. NO_ERROR - The operation was successful (a handle was returned)
  450. ERROR_NO_MORE_ITEMS - No more items were available for enumeration
  451. --*/
  452. {
  453. //
  454. // Call the common routine to do most of the work
  455. //
  456. return ObCommonEnumObjects(
  457. (PGENERIC_OBJECT) ApplicationHandle,
  458. OBJECT_TYPE_APPLICATION,
  459. &(((PAZP_APPLICATION)ApplicationHandle)->JunctionPoints),
  460. EnumerationContext,
  461. Reserved,
  462. (PGENERIC_OBJECT *) JunctionPointHandle );
  463. }
  464. DWORD
  465. WINAPI
  466. AzJunctionPointGetProperty(
  467. IN AZ_HANDLE JunctionPointHandle,
  468. IN ULONG PropertyId,
  469. IN DWORD Reserved,
  470. OUT PVOID *PropertyValue
  471. )
  472. /*++
  473. Routine Description:
  474. Returns the specified property for a junction point.
  475. Arguments:
  476. JunctionPointHandle - Specifies a handle to the junction point
  477. PropertyId - Specifies which property to return.
  478. Reserved - Reserved. Must by zero.
  479. PropertyValue - Specifies a pointer to return the property in.
  480. The returned pointer must be freed using AzFreeMemory.
  481. The returned value and type depends in PropertyId. The valid values are:
  482. AZ_PROP_NAME LPWSTR - Object name of the object
  483. AZ_PROP_DESCRIPTION LPWSTR - Description of the object
  484. AZ_PROP_JUNCTION_POINT_APPLICATION LPWSTR - Application linked to this junction point
  485. Return Value:
  486. NO_ERROR - The operation was successful
  487. ERROR_INVALID_PARAMETER - PropertyId isn't valid
  488. --*/
  489. {
  490. //
  491. // Call the common routine to do most of the work
  492. //
  493. return ObCommonGetProperty(
  494. (PGENERIC_OBJECT) JunctionPointHandle,
  495. OBJECT_TYPE_JUNCTION_POINT,
  496. PropertyId,
  497. Reserved,
  498. PropertyValue );
  499. }
  500. DWORD
  501. WINAPI
  502. AzJunctionPointSetProperty(
  503. IN AZ_HANDLE JunctionPointHandle,
  504. IN ULONG PropertyId,
  505. IN DWORD Reserved,
  506. IN PVOID PropertyValue
  507. )
  508. /*++
  509. Routine Description:
  510. Sets the specified property for a junction point.
  511. Arguments:
  512. JunctionPointHandle - Specifies a handle to the junction point
  513. PropertyId - Specifies which property to set
  514. Reserved - Reserved. Must by zero.
  515. PropertyValue - Specifies a pointer to the property.
  516. The specified value and type depends in PropertyId. The valid values are:
  517. AZ_PROP_NAME LPWSTR - Object name of the object
  518. AZ_PROP_DESCRIPTION LPWSTR - Description of the object
  519. AZ_PROP_JUNCTION_POINT_APPLICATION LPWSTR - Application linked to this junction point
  520. Return Value:
  521. NO_ERROR - The operation was successful
  522. ERROR_INVALID_PARAMETER - PropertyId isn't valid
  523. --*/
  524. {
  525. //
  526. // Call the common routine to do most of the work
  527. //
  528. return ObCommonSetProperty(
  529. (PGENERIC_OBJECT) JunctionPointHandle,
  530. OBJECT_TYPE_JUNCTION_POINT,
  531. PropertyId,
  532. Reserved,
  533. PropertyValue );
  534. }
  535. DWORD
  536. WINAPI
  537. AzJunctionPointDelete(
  538. IN AZ_HANDLE ApplicationHandle,
  539. IN LPCWSTR JunctionPointName,
  540. IN DWORD Reserved
  541. )
  542. /*++
  543. Routine Description:
  544. This routine deletes a junction point from the scope of the specified application.
  545. Also deletes any child objects of JunctionPointName.
  546. Arguments:
  547. ApplicationHandle - Specifies a handle to the application.
  548. JunctionPointName - Specifies the name of the junction point to delete.
  549. Reserved - Reserved. Must by zero.
  550. Return Value:
  551. NO_ERROR - The operation was successful
  552. ERROR_NOT_FOUND - An object by that name cannot be found
  553. --*/
  554. {
  555. //
  556. // Call the common routine to do most of the work
  557. //
  558. return ObCommonDeleteObject(
  559. (PGENERIC_OBJECT) ApplicationHandle,
  560. OBJECT_TYPE_APPLICATION,
  561. &(((PAZP_APPLICATION)ApplicationHandle)->JunctionPoints),
  562. OBJECT_TYPE_JUNCTION_POINT,
  563. JunctionPointName,
  564. Reserved );
  565. }