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.

2818 lines
73 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. resprop.c
  5. Abstract:
  6. Implements the management of properties.
  7. Author:
  8. Rod Gamache (rodga) 19-Mar-1997
  9. Revision History:
  10. --*/
  11. #pragma warning( push )
  12. #pragma warning( disable : 4115 ) // Clusrtl - struct def in parentheses
  13. #pragma warning( disable : 4201 ) // SDK - nameless struct/union
  14. #define UNICODE 1
  15. #include "clusres.h"
  16. #include "clusrtl.h"
  17. #include "stdio.h"
  18. #include "stdlib.h"
  19. #pragma warning( pop )
  20. //
  21. // Cluster Registry API function pointers
  22. //
  23. CLUSTER_REG_APIS
  24. ResUtilClusterRegApis = {
  25. (PFNCLRTLCREATEKEY) ClusterRegCreateKey,
  26. (PFNCLRTLOPENKEY) ClusterRegOpenKey,
  27. (PFNCLRTLCLOSEKEY) ClusterRegCloseKey,
  28. (PFNCLRTLSETVALUE) ClusterRegSetValue,
  29. (PFNCLRTLQUERYVALUE) ClusterRegQueryValue,
  30. (PFNCLRTLENUMVALUE) ClusterRegEnumValue,
  31. (PFNCLRTLDELETEVALUE) ClusterRegDeleteValue,
  32. NULL,
  33. NULL,
  34. NULL
  35. };
  36. DWORD
  37. WINAPI
  38. ResUtilEnumProperties(
  39. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  40. OUT LPWSTR pszOutProperties,
  41. IN DWORD cbOutPropertiesSize,
  42. OUT LPDWORD pcbBytesReturned,
  43. OUT LPDWORD pcbRequired
  44. )
  45. /*++
  46. Routine Description:
  47. Enumerates the properties for a given object.
  48. Arguments:
  49. pPropertyTable - Pointer to the property table to process.
  50. pszOutProperties - Supplies the output buffer.
  51. cbOutPropertiesSize - Supplies the size of the output buffer.
  52. pcbBytesReturned - The number of bytes returned in pszOutProperties.
  53. pcbRequired - The required number of bytes if pszOutProperties is too small.
  54. Return Value:
  55. ERROR_SUCCESS - Operation was successful.
  56. ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
  57. A Win32 error code on failure.
  58. --*/
  59. {
  60. return( ClRtlEnumProperties( pPropertyTable,
  61. pszOutProperties,
  62. cbOutPropertiesSize,
  63. pcbBytesReturned,
  64. pcbRequired ) );
  65. } // ResUtilEnumProperties
  66. DWORD
  67. WINAPI
  68. ResUtilEnumPrivateProperties(
  69. IN HKEY hkeyClusterKey,
  70. OUT LPWSTR pszOutProperties,
  71. IN DWORD cbOutPropertiesSize,
  72. OUT LPDWORD pcbBytesReturned,
  73. OUT LPDWORD pcbRequired
  74. )
  75. /*++
  76. Routine Description:
  77. Enumerates the properties for a given object.
  78. Arguments:
  79. hkeyClusterKey - Supplies the handle to the key in the cluster database
  80. to read from.
  81. pszOutProperties - Supplies the output buffer.
  82. cbOutPropertiesSize - Supplies the size of the output buffer.
  83. pcbBytesReturned - The number of bytes returned in pszOutProperties.
  84. pcbRequired - The required number of bytes if pszOutProperties is too small.
  85. Return Value:
  86. ERROR_SUCCESS - Operation was successful.
  87. ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
  88. A Win32 error code on failure.
  89. --*/
  90. {
  91. return( ClRtlEnumPrivateProperties( hkeyClusterKey,
  92. &ResUtilClusterRegApis,
  93. pszOutProperties,
  94. cbOutPropertiesSize,
  95. pcbBytesReturned,
  96. pcbRequired ) );
  97. } // ResUtilEnumProperties
  98. DWORD
  99. WINAPI
  100. ResUtilGetProperties(
  101. IN HKEY hkeyClusterKey,
  102. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  103. OUT LPWSTR pPropertyList,
  104. IN DWORD cbPropertyListSize,
  105. OUT LPDWORD pcbBytesReturned,
  106. OUT LPDWORD pcbRequired
  107. )
  108. /*++
  109. Routine Description:
  110. Gets the properties for a given object.
  111. Arguments:
  112. hkeyClusterKey - Supplies the handle to the key in the cluster database
  113. to read from.
  114. pPropertyTable - Pointer to the property table to process.
  115. pPropertyList - Supplies the output buffer.
  116. cbPropertyListSize - Supplies the size of the output buffer.
  117. pcbBytesReturned - The number of bytes returned in pPropertyList.
  118. pcbRequired - The required number of bytes if pPropertyList is too small.
  119. Return Value:
  120. ERROR_SUCCESS - Operation was successful.
  121. ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
  122. ERROR_NOT_ENOUGH_MEMORY - Error allocating memory.
  123. A Win32 error code on failure.
  124. --*/
  125. {
  126. return( ClRtlGetProperties( hkeyClusterKey,
  127. &ResUtilClusterRegApis,
  128. pPropertyTable,
  129. pPropertyList,
  130. cbPropertyListSize,
  131. pcbBytesReturned,
  132. pcbRequired ) );
  133. } // ResUtilGetProperties
  134. DWORD
  135. WINAPI
  136. ResUtilGetAllProperties(
  137. IN HKEY hkeyClusterKey,
  138. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  139. OUT PVOID pPropertyList,
  140. IN DWORD cbPropertyListSize,
  141. OUT LPDWORD pcbBytesReturned,
  142. OUT LPDWORD pcbRequired
  143. )
  144. /*++
  145. Routine Description:
  146. Gets the default and 'unknown' properties for a given object.
  147. Arguments:
  148. hkeyClusterKey - Supplies the handle to the key in the cluster database
  149. to read from.
  150. pPropertyTable - Pointer to the property table to process.
  151. pPropertyList - Supplies the output buffer.
  152. cbPropertyListSize - Supplies the size of the output buffer.
  153. pcbBytesReturned - The number of bytes returned in pPropertyList.
  154. pcbRequired - The required number of bytes if pPropertyList is too small.
  155. Return Value:
  156. ERROR_SUCCESS - Operation was successful.
  157. ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
  158. ERROR_NOT_ENOUGH_MEMORY - Error allocating memory.
  159. A Win32 error code on failure.
  160. --*/
  161. {
  162. return( ClRtlGetAllProperties( hkeyClusterKey,
  163. &ResUtilClusterRegApis,
  164. pPropertyTable,
  165. pPropertyList,
  166. cbPropertyListSize,
  167. pcbBytesReturned,
  168. pcbRequired ) );
  169. } // ResUtilGetAllProperties
  170. DWORD
  171. WINAPI
  172. ResUtilGetPropertiesToParameterBlock(
  173. IN HKEY hkeyClusterKey,
  174. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  175. OUT LPBYTE pOutParams,
  176. IN BOOL bCheckForRequiredProperties,
  177. OUT OPTIONAL LPWSTR * pszNameOfPropInError
  178. )
  179. /*++
  180. Routine Description:
  181. Gets the default and 'unknown' properties for a given object and stores
  182. them in a parameter block.
  183. Arguments:
  184. hkeyClusterKey - Supplies the handle to the key in the cluster database
  185. to read from.
  186. pPropertyTable - Pointer to the property table to process.
  187. pOutParams - Supplies the output parameter block.
  188. bCheckForRequiredProperties - Boolean value specifying whether missing
  189. required properties should cause an error.
  190. pszNameOfPropInError - String pointer in which to return the name of the
  191. property in error (optional).
  192. Return Value:
  193. ERROR_SUCCESS - Operation was successful.
  194. ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
  195. ERROR_NOT_ENOUGH_MEMORY - Error allocating memory.
  196. A Win32 error code on failure.
  197. --*/
  198. {
  199. DWORD status;
  200. status = ClRtlGetPropertiesToParameterBlock( hkeyClusterKey,
  201. &ResUtilClusterRegApis,
  202. pPropertyTable,
  203. pOutParams,
  204. bCheckForRequiredProperties,
  205. pszNameOfPropInError );
  206. return(status);
  207. } // ResUtilGetPropertiesToParameterBlock
  208. DWORD
  209. WINAPI
  210. ResUtilPropertyListFromParameterBlock(
  211. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  212. OUT PVOID pOutPropertyList,
  213. IN OUT LPDWORD pcbOutPropertyListSize,
  214. IN const LPBYTE pInParams,
  215. OUT LPDWORD pcbBytesReturned,
  216. OUT LPDWORD pcbRequired
  217. )
  218. /*++
  219. Routine Description:
  220. Constructs a property list from a parameter block.
  221. Arguments:
  222. pPropertyTable - Pointer to the property table to process.
  223. pOutPropertyList - Supplies the output buffer.
  224. pcbOutPropertyListSize - Supplies the size of the output buffer.
  225. pInParams - Supplies the input parameter block.
  226. pcbBytesReturned - The number of bytes returned in pOutPropertyList.
  227. pcbRequired - The required number of bytes if pOutPropertyList is too small.
  228. Return Value:
  229. ERROR_SUCCESS - Operation was successful.
  230. ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
  231. ERROR_NOT_ENOUGH_MEMORY - Error allocating memory.
  232. A Win32 error code on failure.
  233. --*/
  234. {
  235. DWORD status;
  236. status = ClRtlPropertyListFromParameterBlock( pPropertyTable,
  237. pOutPropertyList,
  238. pcbOutPropertyListSize,
  239. pInParams,
  240. pcbBytesReturned,
  241. pcbRequired );
  242. return(status);
  243. } // ResUtilPropertyListFromParameterBlock
  244. DWORD
  245. WINAPI
  246. ResUtilGetPrivateProperties(
  247. IN HKEY hkeyClusterKey,
  248. OUT PVOID pOutPropertyList,
  249. IN DWORD cbOutPropertyListSize,
  250. OUT LPDWORD pcbBytesReturned,
  251. OUT LPDWORD pcbRequired
  252. )
  253. /*++
  254. Routine Description:
  255. Gets the private properties for a given object.
  256. This routine assumes that it uses the Cluster Registry API's for
  257. access to registry info.
  258. Arguments:
  259. hkeyClusterKey - Supplies the handle to the key in the cluster database
  260. to read from.
  261. pOutPropertyList - Supplies the output buffer.
  262. cbOutPropertyListSize - Supplies the size of the output buffer.
  263. pcbBytesReturned - The number of bytes returned in pOutPropertyList.
  264. pcbRequired - The required number of bytes if pOutPropertyList is too small.
  265. Return Value:
  266. ERROR_SUCCESS - Operation was successful.
  267. ERROR_NOT_ENOUGH_MEMORY - Error allocating memory.
  268. A Win32 error code on failure.
  269. --*/
  270. {
  271. return( ClRtlGetPrivateProperties( hkeyClusterKey,
  272. &ResUtilClusterRegApis,
  273. pOutPropertyList,
  274. cbOutPropertyListSize,
  275. pcbBytesReturned,
  276. pcbRequired ) );
  277. } // ResUtilGetPrivateProperties
  278. DWORD
  279. WINAPI
  280. ResUtilGetPropertySize(
  281. IN HKEY hkeyClusterKey,
  282. IN const PRESUTIL_PROPERTY_ITEM pPropertyTableItem,
  283. IN OUT LPDWORD pcbOutPropertyListSize,
  284. IN OUT LPDWORD pnPropertyCount
  285. )
  286. /*++
  287. Routine Description:
  288. Get the total number of bytes required for this property.
  289. Arguments:
  290. hkeyClusterKey - Supplies the handle to the key in the cluster database
  291. to read from.
  292. Return Value:
  293. --*/
  294. {
  295. return( ClRtlGetPropertySize( hkeyClusterKey,
  296. &ResUtilClusterRegApis,
  297. pPropertyTableItem,
  298. pcbOutPropertyListSize,
  299. pnPropertyCount ) );
  300. } // ResUtilGetPropertySize
  301. DWORD
  302. WINAPI
  303. ResUtilGetProperty(
  304. IN HKEY hkeyClusterKey,
  305. IN const PRESUTIL_PROPERTY_ITEM pPropertyTableItem,
  306. OUT PVOID * pOutPropertyItem,
  307. IN OUT LPDWORD pcbOutPropertyItemSize
  308. )
  309. /*++
  310. Routine Description:
  311. Arguments:
  312. Return Value:
  313. Notes:
  314. The buffer size has already been determined to be large enough to hold
  315. the return data.
  316. --*/
  317. {
  318. return( ClRtlGetProperty( hkeyClusterKey,
  319. &ResUtilClusterRegApis,
  320. pPropertyTableItem,
  321. pOutPropertyItem,
  322. pcbOutPropertyItemSize ) );
  323. } // ResUtilGetProperty
  324. DWORD
  325. WINAPI
  326. ResUtilVerifyPropertyTable(
  327. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  328. IN PVOID Reserved,
  329. IN BOOL bAllowUnknownProperties,
  330. IN const PVOID pInPropertyList,
  331. IN DWORD cbInPropertyListSize,
  332. OUT OPTIONAL PBYTE pOutParams
  333. )
  334. /*++
  335. Routine Description:
  336. Validate a property list.
  337. Arguments:
  338. pPropertyTable - Pointer to the property table to process.
  339. Reserved - Possible pointer to a future ReadOnly property table.
  340. bAllowUnknownProperties - TRUE if unknown properties should be accepted.
  341. pInPropertyList - The input buffer.
  342. cbInPropertyListSize - The input buffer size.
  343. pOutParams - Parameters block in which to return the data.
  344. Return Value:
  345. ERROR_SUCCESS if successful.
  346. A Win32 Error on failure.
  347. --*/
  348. {
  349. return( ClRtlVerifyPropertyTable( pPropertyTable,
  350. Reserved,
  351. bAllowUnknownProperties,
  352. pInPropertyList,
  353. cbInPropertyListSize,
  354. pOutParams ) );
  355. } // ResUtilVerifyPropertyTable
  356. DWORD
  357. WINAPI
  358. ResUtilSetPropertyTable(
  359. IN HKEY hkeyClusterKey,
  360. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  361. IN PVOID Reserved,
  362. IN BOOL bAllowUnknownProperties,
  363. IN const PVOID pInPropertyList,
  364. IN DWORD cbInPropertyListSize,
  365. OUT OPTIONAL PBYTE pOutParams
  366. )
  367. /*++
  368. Routine Description:
  369. Arguments:
  370. hkeyClusterKey - The opened registry key for this object's parameters.
  371. If not specified, the property list will only be validated.
  372. pPropertyTable - Pointer to the property table to process.
  373. Reserved - Possible pointer to a future ReadOnly property table.
  374. bAllowUnknownProperties - TRUE if unknown properties should be accepted.
  375. pInPropertyList - The input buffer.
  376. cbInPropertyListSize - The input buffer size.
  377. pOutParams - Parameters block in which to return the data.
  378. Return Value:
  379. ERROR_SUCCESS if successful.
  380. A Win32 Error on failure.
  381. --*/
  382. {
  383. return( ClRtlSetPropertyTable( NULL,
  384. hkeyClusterKey,
  385. &ResUtilClusterRegApis,
  386. pPropertyTable,
  387. Reserved,
  388. bAllowUnknownProperties,
  389. pInPropertyList,
  390. cbInPropertyListSize,
  391. FALSE, // bForceWrite
  392. pOutParams ) );
  393. } // ResUtilSetPropertyTable
  394. DWORD
  395. WINAPI
  396. ResUtilSetPropertyTableEx(
  397. IN HKEY hkeyClusterKey,
  398. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  399. IN PVOID Reserved,
  400. IN BOOL bAllowUnknownProperties,
  401. IN const PVOID pInPropertyList,
  402. IN DWORD cbInPropertyListSize,
  403. IN BOOL bForceWrite,
  404. OUT OPTIONAL PBYTE pOutParams
  405. )
  406. /*++
  407. Routine Description:
  408. Arguments:
  409. hkeyClusterKey - The opened registry key for this object's parameters.
  410. If not specified, the property list will only be validated.
  411. pPropertyTable - Pointer to the property table to process.
  412. Reserved - Possible pointer to a future ReadOnly property table.
  413. bAllowUnknownProperties - TRUE if unknown properties should be accepted.
  414. pInPropertyList - The input buffer.
  415. cbInPropertyListSize - The input buffer size.
  416. bForceWrite - TRUE = always write the properties to the cluster database.
  417. FALSE = only write the properties if they changed.
  418. pOutParams - Parameters block in which to return the data.
  419. Return Value:
  420. ERROR_SUCCESS if successful.
  421. A Win32 Error on failure.
  422. --*/
  423. {
  424. return( ClRtlSetPropertyTable( NULL,
  425. hkeyClusterKey,
  426. &ResUtilClusterRegApis,
  427. pPropertyTable,
  428. Reserved,
  429. bAllowUnknownProperties,
  430. pInPropertyList,
  431. cbInPropertyListSize,
  432. bForceWrite,
  433. pOutParams ) );
  434. } // ResUtilSetPropertyTableEx
  435. DWORD
  436. WINAPI
  437. ResUtilSetPropertyParameterBlock(
  438. IN HKEY hkeyClusterKey,
  439. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  440. IN PVOID Reserved,
  441. IN const LPBYTE pInParams,
  442. IN const PVOID pInPropertyList,
  443. IN DWORD cbInPropertyListSize,
  444. OUT OPTIONAL PBYTE pOutParams
  445. )
  446. /*++
  447. Routine Description:
  448. Arguments:
  449. hkeyClusterKey - The opened registry key for this object's parameters.
  450. If not specified, the property list will only be validated.
  451. pPropertyTable - Pointer to the property table to process.
  452. pInParams - Parameters block to set.
  453. pInPropertyList - Full Property list.
  454. cbInPropertyListSize - Size of the input full property list.
  455. pOutParams - Parameters block to copy pInParams to.
  456. Return Value:
  457. ERROR_SUCCESS if successful.
  458. A Win32 Error on failure.
  459. --*/
  460. {
  461. return( ClRtlSetPropertyParameterBlock( NULL, // IN HANDLE hXsaction,
  462. hkeyClusterKey,
  463. &ResUtilClusterRegApis,
  464. pPropertyTable,
  465. Reserved,
  466. pInParams,
  467. pInPropertyList,
  468. cbInPropertyListSize,
  469. FALSE, // bForceWrite
  470. pOutParams ) );
  471. } // ResUtilSetPropertyParameterBlock
  472. DWORD
  473. WINAPI
  474. ResUtilSetPropertyParameterBlockEx(
  475. IN HKEY hkeyClusterKey,
  476. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  477. IN PVOID Reserved,
  478. IN const LPBYTE pInParams,
  479. IN const PVOID pInPropertyList,
  480. IN DWORD cbInPropertyListSize,
  481. IN BOOL bForceWrite,
  482. OUT OPTIONAL PBYTE pOutParams
  483. )
  484. /*++
  485. Routine Description:
  486. Arguments:
  487. hkeyClusterKey - The opened registry key for this object's parameters.
  488. If not specified, the property list will only be validated.
  489. pPropertyTable - Pointer to the property table to process.
  490. pInParams - Parameters block to set.
  491. pInPropertyList - Full Property list.
  492. cbInPropertyListSize - Size of the input full property list.
  493. bForceWrite - TRUE = always write the properties to the cluster database.
  494. FALSE = only write the properties if they changed.
  495. pOutParams - Parameters block to copy pInParams to.
  496. Return Value:
  497. ERROR_SUCCESS if successful.
  498. A Win32 Error on failure.
  499. --*/
  500. {
  501. return( ClRtlSetPropertyParameterBlock( NULL, // IN HANDLE hXsaction,
  502. hkeyClusterKey,
  503. &ResUtilClusterRegApis,
  504. pPropertyTable,
  505. Reserved,
  506. pInParams,
  507. pInPropertyList,
  508. cbInPropertyListSize,
  509. bForceWrite,
  510. pOutParams ) );
  511. } // ResUtilSetPropertyParameterBlockEx
  512. DWORD
  513. WINAPI
  514. ResUtilSetUnknownProperties(
  515. IN HKEY hkeyClusterKey,
  516. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  517. IN const PVOID pInPropertyList,
  518. IN DWORD cbInPropertyListSize
  519. )
  520. /*++
  521. Routine Description:
  522. Set items that are not in the property table list.
  523. Arguments:
  524. hkeyClusterKey - The opened registry key for this object's parameters.
  525. If not specified, the property list will only be validated.
  526. pPropertyTable - Pointer to the property table to process.
  527. pInPropertyList - Full Property list.
  528. cbInPropertyListSize - Size of the input full property list.
  529. Return Value:
  530. ERROR_SUCCESS if successful.
  531. A Win32 Error on failure.
  532. --*/
  533. {
  534. return( ClRtlpSetNonPropertyTable( NULL, // IN HANDLE hXsaction
  535. hkeyClusterKey,
  536. &ResUtilClusterRegApis,
  537. pPropertyTable,
  538. NULL,
  539. pInPropertyList,
  540. cbInPropertyListSize ) );
  541. } // ResUtilSetUnknownProperties
  542. DWORD
  543. WINAPI
  544. ResUtilVerifyPrivatePropertyList(
  545. IN const PVOID pInPropertyList,
  546. IN DWORD cbInPropertyListSize
  547. )
  548. /*++
  549. Routine Description:
  550. Validate a private property list.
  551. Arguments:
  552. pInPropertyList - The input buffer.
  553. cbInPropertyListSize - The input buffer size.
  554. Return Value:
  555. ERROR_SUCCESS if successful.
  556. A Win32 Error on failure.
  557. --*/
  558. {
  559. return( ClRtlVerifyPrivatePropertyList( pInPropertyList, cbInPropertyListSize ) );
  560. } // ResUtilVerifyPrivatePropertyList
  561. DWORD
  562. WINAPI
  563. ResUtilSetPrivatePropertyList(
  564. IN HKEY hkeyClusterKey,
  565. IN const PVOID pInPropertyList,
  566. IN DWORD cbInPropertyListSize
  567. )
  568. /*++
  569. Routine Description:
  570. Arguments:
  571. hkeyClusterKey - The opened registry key for this resource's parameters.
  572. If not specified, the property list will only be validated.
  573. pInPropertyList - The input buffer.
  574. cbInPropertyListSize - The input buffer size.
  575. Return Value:
  576. ERROR_SUCCESS if successful.
  577. A Win32 Error on failure.
  578. --*/
  579. {
  580. return( ClRtlSetPrivatePropertyList( NULL, // IN HANDLE hXsaction
  581. hkeyClusterKey,
  582. &ResUtilClusterRegApis,
  583. pInPropertyList,
  584. cbInPropertyListSize ) );
  585. } // ResUtilSetPrivatePropertyList
  586. DWORD
  587. WINAPI
  588. ResUtilAddUnknownProperties(
  589. IN HKEY hkeyClusterKey,
  590. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  591. IN OUT PVOID pOutPropertyList,
  592. IN DWORD cbOutPropertyListSize,
  593. IN OUT LPDWORD pcbBytesReturned,
  594. IN OUT LPDWORD pcbRequired
  595. )
  596. /*++
  597. Routine Description:
  598. Adds the unknown properties for a given object to the end of a property
  599. list.
  600. Arguments:
  601. hkeyClusterKey - Supplies the handle to the key in the cluster database
  602. to read from.
  603. pPropertyTable - Pointer to the property table to process.
  604. pOutPropertyList - Supplies the output buffer.
  605. cbOutPropertyListSize - Supplies the size of the output buffer.
  606. pcbBytesReturned - On input, contains the number of bytes in use in the
  607. output buffer. On output, contains the total number of bytes in
  608. pOutPropertyList.
  609. pcbRequired - The required number of bytes if pOutPropertyList is too small.
  610. Return Value:
  611. ERROR_SUCCESS - Operation was successful.
  612. ERROR_NOT_ENOUGH_MEMORY - Error allocating memory.
  613. A Win32 error code on failure.
  614. --*/
  615. {
  616. DWORD status;
  617. status = ClRtlAddUnknownProperties( hkeyClusterKey,
  618. &ResUtilClusterRegApis,
  619. pPropertyTable,
  620. pOutPropertyList,
  621. cbOutPropertyListSize,
  622. pcbBytesReturned,
  623. pcbRequired );
  624. return(status);
  625. } // ResUtilAddUnknownProperties
  626. //***************************************************************************
  627. //
  628. // Utility routines to grovel though a Control Function item list buffer
  629. //
  630. //***************************************************************************
  631. DWORD
  632. WINAPI
  633. ResUtilFindSzProperty(
  634. IN PVOID pPropertyList,
  635. IN DWORD cbPropertyListSize,
  636. IN LPCWSTR pszPropertyName,
  637. OUT LPWSTR * pszPropertyValue
  638. )
  639. /*++
  640. Routine Description:
  641. Finds the specified string property in the Property List buffer pointed at
  642. by pPropertyList.
  643. Arguments:
  644. pPropertyList - a property list.
  645. cbPropertyListSize - the size in bytes of the data in pPropertyList.
  646. pszPropertyName - the property name to look for in the buffer.
  647. pszPropertyValue - the matching string value found.
  648. Return Value:
  649. ERROR_SUCCESS if successful.
  650. A Win32 error code on failure.
  651. --*/
  652. {
  653. return( ClRtlFindSzProperty( pPropertyList,
  654. cbPropertyListSize,
  655. pszPropertyName,
  656. pszPropertyValue ) );
  657. } // ResUtilFindSzProperty
  658. DWORD
  659. WINAPI
  660. ResUtilFindExpandSzProperty(
  661. IN PVOID pPropertyList,
  662. IN DWORD cbPropertyListSize,
  663. IN LPCWSTR pszPropertyName,
  664. OUT LPWSTR * pszPropertyValue
  665. )
  666. /*++
  667. Routine Description:
  668. Finds the specified EXPAND_SZ string property in the Property List buffer
  669. pointed at by pPropertyList.
  670. Arguments:
  671. pPropertyList - a property list.
  672. cbPropertyListSize - the size in bytes of the data in pPropertyList.
  673. pszPropertyName - the property name to look for in the buffer.
  674. pszPropertyValue - the matching string value found.
  675. Return Value:
  676. ERROR_SUCCESS if successful.
  677. A Win32 error code on failure.
  678. --*/
  679. {
  680. return( ClRtlFindExpandSzProperty(
  681. pPropertyList,
  682. cbPropertyListSize,
  683. pszPropertyName,
  684. pszPropertyValue ) );
  685. } // ResUtilFindExpandSzProperty
  686. DWORD
  687. WINAPI
  688. ResUtilFindExpandedSzProperty(
  689. IN PVOID pPropertyList,
  690. IN DWORD cbPropertyListSize,
  691. IN LPCWSTR pszPropertyName,
  692. OUT LPWSTR * pszPropertyValue
  693. )
  694. /*++
  695. Routine Description:
  696. Finds the specified string property in the Property List buffer pointed at
  697. by pPropertyList and returns it's expanded value.
  698. Arguments:
  699. pPropertyList - a property list.
  700. cbPropertyListSize - the size in bytes of the data in pPropertyList.
  701. pszPropertyName - the property name to look for in the buffer.
  702. pszPropertyValue - the matching string value found.
  703. Return Value:
  704. ERROR_SUCCESS if successful.
  705. A Win32 error code on failure.
  706. --*/
  707. {
  708. return( ClRtlFindExpandedSzProperty(
  709. pPropertyList,
  710. cbPropertyListSize,
  711. pszPropertyName,
  712. pszPropertyValue ) );
  713. } // ResUtilFindExpandedSzProperty
  714. DWORD
  715. WINAPI
  716. ResUtilFindDwordProperty(
  717. IN PVOID pPropertyList,
  718. IN DWORD cbPropertyListSize,
  719. IN LPCWSTR pszPropertyName,
  720. OUT LPDWORD pdwPropertyValue
  721. )
  722. /*++
  723. Routine Description:
  724. Finds the specified DWORD property in the Property List buffer pointed at
  725. by pPropertyList.
  726. Arguments:
  727. pPropertyList - a property list.
  728. cbPropertyListSize - the size in bytes of the data in pPropertyList.
  729. pszPropertyName - the property name to look for in the buffer.
  730. pdwPropertyValue - the matching DWORD value found.
  731. Return Value:
  732. ERROR_SUCCESS if successful.
  733. A Win32 error code on failure.
  734. --*/
  735. {
  736. return( ClRtlFindDwordProperty( pPropertyList,
  737. cbPropertyListSize,
  738. pszPropertyName,
  739. pdwPropertyValue ) );
  740. } // ResUtilFindDwordProperty
  741. DWORD
  742. WINAPI
  743. ResUtilFindLongProperty(
  744. IN PVOID pPropertyList,
  745. IN DWORD cbPropertyListSize,
  746. IN LPCWSTR pszPropertyName,
  747. OUT LPLONG plPropertyValue
  748. )
  749. /*++
  750. Routine Description:
  751. Finds the specified string in the Value List buffer pointed at by Buffer.
  752. Arguments:
  753. pPropertyList - a property list.
  754. cbPropertyListSize - the size in bytes of the data in pPropertyList.
  755. pszPropertyName - the property name to look for in the buffer.
  756. plPropertyValue - the matching long value found.
  757. Return Value:
  758. ERROR_SUCCESS if successful.
  759. A Win32 error code on failure.
  760. --*/
  761. {
  762. return( ClRtlFindLongProperty( pPropertyList,
  763. cbPropertyListSize,
  764. pszPropertyName,
  765. plPropertyValue ) );
  766. } // ResUtilFindLongProperty
  767. DWORD
  768. WINAPI
  769. ResUtilFindBinaryProperty(
  770. IN PVOID pPropertyList,
  771. IN DWORD cbPropertyListSize,
  772. IN LPCWSTR pszPropertyName,
  773. OUT LPBYTE * pbPropertyValue,
  774. OUT LPDWORD pcbPropertyValueSize
  775. )
  776. /*++
  777. Routine Description:
  778. Finds the specified binary property in the Property List buffer pointed at
  779. by pPropertyList.
  780. Arguments:
  781. pPropertyList - a property list.
  782. cbPropertyListSize - the size in bytes of the data in pPropertyList.
  783. pszPropertyName - the property name to look for in the buffer.
  784. pbPropertyValue - the matching binary value found.
  785. pcbPropertyValueSize - the length of the matching binary value found.
  786. Return Value:
  787. ERROR_SUCCESS if successful.
  788. A Win32 error code on failure.
  789. --*/
  790. {
  791. return( ClRtlFindBinaryProperty( pPropertyList,
  792. cbPropertyListSize,
  793. pszPropertyName,
  794. pbPropertyValue,
  795. pcbPropertyValueSize ) );
  796. } // ResUtilFindBinaryProperty
  797. DWORD
  798. WINAPI
  799. ResUtilFindMultiSzProperty(
  800. IN PVOID pPropertyList,
  801. IN DWORD cbPropertyListSize,
  802. IN LPCWSTR pszPropertyName,
  803. OUT LPWSTR * pszPropertyValue,
  804. OUT LPDWORD pcbPropertyValueSize
  805. )
  806. /*++
  807. Routine Description:
  808. Finds the specified multiple string property in the Proprety List buffer
  809. pointed at by pPropertyList.
  810. Arguments:
  811. pPropertyList - a property list.
  812. cbPropertyListSize - the size in bytes of the data in pPropertyList.
  813. pszPropertyName - the property name to look for in the buffer.
  814. pszPropertyValue - the matching multiple string value found.
  815. pcbPropertyValueSize - the length of the matching multiple string value found.
  816. Return Value:
  817. ERROR_SUCCESS if successful.
  818. A Win32 error code on failure.
  819. --*/
  820. {
  821. return( ClRtlFindMultiSzProperty( pPropertyList,
  822. cbPropertyListSize,
  823. pszPropertyName,
  824. pszPropertyValue,
  825. pcbPropertyValueSize ) );
  826. } // ResUtilFindMultiSzProperty
  827. DWORD
  828. WINAPI
  829. ResUtilDupParameterBlock(
  830. OUT LPBYTE pOutParams,
  831. IN const LPBYTE pInParams,
  832. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable
  833. )
  834. /*++
  835. Routine Description:
  836. Deallocates any buffers allocated for a parameter block that are
  837. different than the buffers used for the input parameter block.
  838. Arguments:
  839. pOutParams - Parameter block to return.
  840. pInParams - Reference parameter block.
  841. pPropertyTable - Pointer to the property table to process.
  842. Return Value:
  843. ERROR_SUCCESS - Parameter block duplicated successfully.
  844. --*/
  845. {
  846. DWORD status;
  847. status = ClRtlDupParameterBlock( pOutParams, pInParams, pPropertyTable );
  848. return(status);
  849. } // ResUtilDupParameterBlock
  850. void
  851. WINAPI
  852. ResUtilFreeParameterBlock(
  853. IN OUT LPBYTE pOutParams,
  854. IN const LPBYTE pInParams,
  855. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable
  856. )
  857. /*++
  858. Routine Description:
  859. Deallocates any buffers allocated for a parameter block that are
  860. different than the buffers used for the input parameter block.
  861. Arguments:
  862. pOutParams - Parameter block to free.
  863. pInParams - Reference parameter block.
  864. pPropertyTable - Pointer to the property table to process.
  865. Return Value:
  866. None.
  867. --*/
  868. {
  869. ClRtlFreeParameterBlock( pOutParams, pInParams, pPropertyTable );
  870. } // ResUtilFreeParameterBlock
  871. #define __INITIAL_NAME_LENGTH 256
  872. BOOL
  873. WINAPI
  874. ResUtilResourceTypesEqual(
  875. IN LPCWSTR lpszResourceTypeName,
  876. IN HRESOURCE hResource
  877. )
  878. /*++
  879. Routine Description:
  880. Checks to see if the resource names type matches
  881. Arguments:
  882. lpszResourceTypeName - The type of resource to check for
  883. hResource - A handle to the resource to check
  884. Return Value:
  885. TRUE - the resource type matches
  886. FALSE - the resource types do not match
  887. --*/
  888. {
  889. BOOL bIsEqual = FALSE;
  890. DWORD dwError;
  891. WCHAR szName[ __INITIAL_NAME_LENGTH ];
  892. LPWSTR pszName = szName;
  893. DWORD cbNameBufSize = __INITIAL_NAME_LENGTH * sizeof( szName[ 0 ] );
  894. DWORD cbRetSize;
  895. // Get the resource type name
  896. dwError = ClusterResourceControl(
  897. hResource, //Handle to the resource
  898. NULL, //Don't care about node
  899. CLUSCTL_RESOURCE_GET_RESOURCE_TYPE, //Get the type
  900. 0, // &InBuffer
  901. 0, // nInBufferSize,
  902. pszName, // &OutBuffer
  903. cbNameBufSize, // nOutBufferSize,
  904. &cbRetSize ); // returned size
  905. if ( dwError == ERROR_MORE_DATA )
  906. {
  907. //
  908. // Output name buffer is too small. Allocate a new one.
  909. //
  910. cbNameBufSize = cbRetSize + sizeof( WCHAR );
  911. pszName = LocalAlloc( LMEM_FIXED, cbNameBufSize );
  912. if ( pszName == NULL )
  913. {
  914. goto Cleanup;
  915. } // if: error allocating buffer
  916. dwError = ClusterResourceControl(
  917. hResource, //Handle to the resource
  918. NULL, //Don't care about node
  919. CLUSCTL_RESOURCE_GET_RESOURCE_TYPE, //Get the type
  920. 0, // &InBuffer
  921. 0, // nInBufferSize,
  922. pszName, // &OutBuffer
  923. cbNameBufSize, // nOutBufferSize,
  924. &cbRetSize ); // returned size
  925. } // if: name buffer too small
  926. if ( dwError != ERROR_SUCCESS )
  927. {
  928. goto Cleanup;
  929. }
  930. // See if it's like US
  931. if ( lstrcmpiW( lpszResourceTypeName, pszName ) == 0 )
  932. {
  933. bIsEqual = TRUE;
  934. }
  935. Cleanup:
  936. if ( pszName != szName )
  937. {
  938. LocalFree( pszName );
  939. } // if: we allocated the output name buffer
  940. return bIsEqual;
  941. } //*** ResUtilResourceTypesEqual()
  942. BOOL
  943. WINAPI
  944. ResUtilResourcesEqual(
  945. IN HRESOURCE hSelf,
  946. IN HRESOURCE hResource
  947. )
  948. /*++
  949. Routine Description:
  950. Check to See if the resources are the same
  951. Arguments:
  952. IN hSelf - a handle to the callee, or NULL to indicate not equal.
  953. IN hResource - a handle to the resource to compare
  954. Return Value:
  955. TRUE - Resource are equal
  956. FALSE - otherwise
  957. --*/
  958. {
  959. BOOL bIsEqual = FALSE;
  960. DWORD sc;
  961. LPWSTR pwszSelfName = NULL;
  962. DWORD cbSelfName = 0;
  963. LPWSTR pwszResName = NULL;
  964. DWORD cbResName = 0;
  965. DWORD cbRetSize = 0;
  966. if ( ( hSelf == NULL ) || ( hResource == NULL ) )
  967. {
  968. goto Cleanup;
  969. }
  970. // "Self" - Get the resource name
  971. sc = ClusterResourceControl(
  972. hSelf, //Handle to the resource
  973. NULL, //Don't care about node
  974. CLUSCTL_RESOURCE_GET_NAME, //Get the name
  975. NULL, // &InBuffer
  976. 0, // nInBufferSize,
  977. NULL, // &OutBuffer
  978. 0, // OutBufferSize,
  979. &cbRetSize // returned size
  980. );
  981. if ( sc != ERROR_SUCCESS )
  982. {
  983. goto Cleanup;
  984. }
  985. //
  986. // Allocate the necessary buffer.
  987. //
  988. cbSelfName = cbRetSize + sizeof( WCHAR ); // Add one for NULL.
  989. pwszSelfName = LocalAlloc( LMEM_FIXED, cbSelfName );
  990. if ( pwszSelfName == NULL )
  991. {
  992. goto Cleanup;
  993. } // if: error allocating buffer
  994. sc = ClusterResourceControl(
  995. hSelf, // Handle to the resource
  996. NULL, // Don't care about node
  997. CLUSCTL_RESOURCE_GET_NAME, // Get the name
  998. 0, // &InBuffer
  999. 0, // nInBufferSize,
  1000. pwszSelfName, // &OutBuffer
  1001. cbSelfName, // OutBufferSize,
  1002. &cbRetSize // returned size
  1003. );
  1004. if ( sc != ERROR_SUCCESS )
  1005. {
  1006. goto Cleanup;
  1007. }
  1008. // "Res" - Get the resource type name
  1009. sc = ClusterResourceControl(
  1010. hResource, //Handle to the resource
  1011. NULL, //Don't care about node
  1012. CLUSCTL_RESOURCE_GET_NAME, //Get the name
  1013. NULL, // &InBuffer
  1014. 0, // nInBufferSize,
  1015. NULL, // &OutBuffer
  1016. 0, // OutBufferSize,
  1017. &cbRetSize // returned size
  1018. );
  1019. if ( sc != ERROR_SUCCESS )
  1020. {
  1021. goto Cleanup;
  1022. }
  1023. //
  1024. // Output name buffer is too small. Allocate a new one.
  1025. //
  1026. cbResName = cbRetSize + sizeof( WCHAR ); // Add one for NULL.
  1027. pwszResName = LocalAlloc( LMEM_FIXED, cbResName );
  1028. if ( pwszResName == NULL )
  1029. {
  1030. goto Cleanup;
  1031. } // if: error allocating buffer
  1032. sc = ClusterResourceControl(
  1033. hResource, // Handle to the resource
  1034. NULL, // Don't care about node
  1035. CLUSCTL_RESOURCE_GET_NAME, // Get the name
  1036. NULL, // &InBuffer
  1037. 0, // nInBufferSize,
  1038. pwszResName, // &OutBuffer
  1039. cbResName , // OutBufferSize,
  1040. &cbRetSize // returned size
  1041. );
  1042. if ( sc != ERROR_SUCCESS )
  1043. {
  1044. goto Cleanup;
  1045. }
  1046. // See if were looking in a mirror
  1047. if ( ClRtlStrNICmp( pwszResName, pwszSelfName, cbResName ) == 0 )
  1048. {
  1049. bIsEqual = TRUE;
  1050. }
  1051. Cleanup:
  1052. LocalFree( pwszSelfName );
  1053. LocalFree( pwszResName );
  1054. return bIsEqual;
  1055. } //*** ResUtilResourcesEqual()
  1056. BOOL
  1057. WINAPI
  1058. ResUtilIsResourceClassEqual(
  1059. IN PCLUS_RESOURCE_CLASS_INFO prci,
  1060. IN HRESOURCE hResource
  1061. )
  1062. /*++
  1063. Routine Description:
  1064. Checks to see if the resource names type matches
  1065. Arguments:
  1066. prci - The resource class info to check for.
  1067. hResource - A handle to the resource to check.
  1068. Return Value:
  1069. TRUE - the resource type matches
  1070. FALSE - the resource types do not match
  1071. --*/
  1072. {
  1073. BOOL bIsEqual = FALSE;
  1074. DWORD sc;
  1075. DWORD cbRetSize;
  1076. CLUS_RESOURCE_CLASS_INFO rci;
  1077. // Get the resource class info
  1078. sc = ClusterResourceControl(
  1079. hResource, // Handle to the resource
  1080. NULL, // Don't care about node
  1081. CLUSCTL_RESOURCE_GET_CLASS_INFO, // Get the class info
  1082. 0, // &InBuffer
  1083. 0, // nInBufferSize,
  1084. &rci, // &OutBuffer
  1085. sizeof( rci ), // nOutBufferSize,
  1086. &cbRetSize ); // returned size
  1087. if ( sc != ERROR_SUCCESS )
  1088. {
  1089. goto Cleanup;
  1090. }
  1091. // See if it's like US
  1092. if ( rci.rc == prci->rc )
  1093. {
  1094. bIsEqual = TRUE;
  1095. }
  1096. Cleanup:
  1097. return bIsEqual;
  1098. } //*** ResUtilIsResourceClassEqual()
  1099. DWORD
  1100. WINAPI
  1101. ResUtilEnumResources(
  1102. IN HRESOURCE hSelf,
  1103. IN LPCWSTR lpszResTypeName,
  1104. IN LPRESOURCE_CALLBACK pResCallBack,
  1105. IN PVOID pParameter
  1106. )
  1107. /*++
  1108. Routine Description:
  1109. This is a generic resource walking routine. It enumerates all resources in
  1110. the cluster and invokes the callback function for each resource.
  1111. Arguments:
  1112. IN [OPTIONAL] hSelf
  1113. - A handle to the resource. When enumerating resources do
  1114. not invoke the callback when the enumerated resource is
  1115. hSelf.
  1116. IF NULL then invoke the callback for all resources
  1117. IN [OPTIONAL] lpszResTypeName
  1118. - This is an optional resource type name. If specified the
  1119. callback function will only be invoked for resources of
  1120. this type.
  1121. IN pResCallBack - Pointer to function that gets called for each enumerated
  1122. resource in the cluster
  1123. IN pParameter - An Opaque callback parameter
  1124. Return Value:
  1125. ERROR_SUCCESS if successful.
  1126. A Win32 error code on failure.
  1127. --*/
  1128. {
  1129. DWORD dwStatus = ERROR_SUCCESS;
  1130. HCLUSTER hCluster = NULL;
  1131. HCLUSENUM hClusEnum = NULL;
  1132. HRESOURCE hResource = NULL;
  1133. BOOL fExecuteCallBack;
  1134. WCHAR szName[ __INITIAL_NAME_LENGTH ];
  1135. LPWSTR lpszName = szName;
  1136. DWORD cchSize = __INITIAL_NAME_LENGTH;
  1137. DWORD cchRetSize;
  1138. DWORD dwIndex;
  1139. DWORD dwType;
  1140. //
  1141. // Open the cluster
  1142. //
  1143. hCluster = OpenCluster( NULL );
  1144. if( hCluster == NULL )
  1145. {
  1146. dwStatus = GetLastError();
  1147. goto Cleanup;
  1148. }
  1149. //
  1150. // Get a resource enumeration handle
  1151. //
  1152. hClusEnum = ClusterOpenEnum( hCluster, CLUSTER_ENUM_RESOURCE );
  1153. if ( hClusEnum == NULL )
  1154. {
  1155. dwStatus = GetLastError();
  1156. goto Cleanup;
  1157. }
  1158. //
  1159. // Enumerate each resource in the cluster
  1160. //
  1161. dwIndex = 0;
  1162. do
  1163. {
  1164. cchRetSize = cchSize;
  1165. dwStatus = ClusterEnum(
  1166. hClusEnum, //handle to enum
  1167. dwIndex, //Index
  1168. &dwType, //Type
  1169. lpszName, //Name
  1170. &cchRetSize //Size of name (in characters)
  1171. );
  1172. if ( dwStatus == ERROR_MORE_DATA )
  1173. {
  1174. //
  1175. // Output name buffer is too small. Allocate a new one.
  1176. //
  1177. cchSize = cchRetSize + 1; // Add room for terminating NULL
  1178. if ( lpszName != szName )
  1179. {
  1180. LocalFree( lpszName );
  1181. }
  1182. lpszName = LocalAlloc( LMEM_FIXED, cchSize * sizeof(WCHAR) );
  1183. if ( lpszName == NULL )
  1184. {
  1185. dwStatus = GetLastError();
  1186. break;
  1187. }
  1188. cchRetSize = cchSize;
  1189. dwStatus = ClusterEnum(
  1190. hClusEnum, //handle to enum
  1191. dwIndex, //Index
  1192. &dwType, //Type
  1193. lpszName, //Name
  1194. &cchRetSize //Size of name
  1195. );
  1196. }
  1197. if ( dwStatus == ERROR_SUCCESS )
  1198. {
  1199. //
  1200. // Try to open this resource
  1201. //
  1202. hResource = OpenClusterResource( hCluster, lpszName );
  1203. if ( hResource == NULL )
  1204. {
  1205. dwStatus = GetLastError();
  1206. if ( dwStatus == ERROR_RESOURCE_NOT_FOUND )
  1207. {
  1208. //
  1209. // If the resource cannot be found, assume it got deleted after
  1210. // you opened the enumeration. So, skip the resource and proceed.
  1211. //
  1212. dwIndex ++;
  1213. dwStatus = ERROR_SUCCESS;
  1214. continue;
  1215. }
  1216. break;
  1217. }
  1218. //
  1219. // Indicate that will invoke the callback
  1220. //
  1221. fExecuteCallBack = TRUE;
  1222. // Determine if we need to check the type
  1223. //
  1224. if ( lpszResTypeName != NULL )
  1225. {
  1226. fExecuteCallBack = ResUtilResourceTypesEqual( lpszResTypeName, hResource );
  1227. } //if lpszResTypeName
  1228. if ( fExecuteCallBack && ( hSelf != NULL ) )
  1229. {
  1230. // Don't execute callback if hResource is callee (i.e., hSelf)
  1231. fExecuteCallBack = !(ResUtilResourcesEqual( hSelf, hResource ));
  1232. } //if fExecuteCallBack && hSelf
  1233. if ( fExecuteCallBack )
  1234. {
  1235. dwStatus = pResCallBack( hSelf, hResource, pParameter );
  1236. if ( dwStatus != ERROR_SUCCESS )
  1237. {
  1238. break;
  1239. }
  1240. } //if fExecuteCallBack
  1241. CloseClusterResource( hResource );
  1242. hResource = NULL;
  1243. } // If ERROR_SUCCESS
  1244. dwIndex++;
  1245. } while ( dwStatus == ERROR_SUCCESS );
  1246. Cleanup:
  1247. if ( hClusEnum != NULL )
  1248. {
  1249. ClusterCloseEnum( hClusEnum );
  1250. }
  1251. if ( hCluster != NULL )
  1252. {
  1253. CloseCluster( hCluster );
  1254. }
  1255. if ( hResource != NULL )
  1256. {
  1257. CloseClusterResource( hResource );
  1258. }
  1259. if ( lpszName != szName )
  1260. {
  1261. LocalFree( lpszName );
  1262. }
  1263. if ( dwStatus == ERROR_NO_MORE_ITEMS )
  1264. {
  1265. dwStatus = ERROR_SUCCESS;
  1266. }
  1267. return dwStatus;
  1268. } //*** ResUtilEnumResources()
  1269. DWORD
  1270. WINAPI
  1271. ResUtilEnumResourcesEx(
  1272. IN HCLUSTER hCluster,
  1273. IN HRESOURCE hSelf,
  1274. IN LPCWSTR lpszResTypeName,
  1275. IN LPRESOURCE_CALLBACK_EX pResCallBack,
  1276. IN PVOID pParameter
  1277. )
  1278. /*++
  1279. Routine Description:
  1280. This is a generic resource walking routine. It enumerates all resources in
  1281. the cluster and invokes the callback function for each resource.
  1282. Arguments:
  1283. IN hCluster - A handle to the cluster to enumerate resources on.
  1284. IN [OPTIONAL] hSelf
  1285. - A handle to the resource. When enumerating resources do
  1286. not invoke the callback when the enumerated resource is
  1287. hSelf.
  1288. IF NULL then invoke the callback for all resources
  1289. IN [OPTIONAL] lpszResTypeName
  1290. - This is an optional resource type name. If specified the
  1291. callback function will only be invoked for resources of
  1292. this type.
  1293. IN pResCallBack - Pointer to function that gets called for each enumerated
  1294. resource in the cluster
  1295. IN pParameter - An Opaque callback parameter
  1296. Return Value:
  1297. ERROR_SUCCESS if successful.
  1298. A Win32 error code on failure.
  1299. --*/
  1300. {
  1301. DWORD dwStatus = ERROR_SUCCESS;
  1302. HCLUSENUM hClusEnum = NULL;
  1303. HRESOURCE hResource = NULL;
  1304. BOOL fExecuteCallBack;
  1305. WCHAR szName[ __INITIAL_NAME_LENGTH ];
  1306. LPWSTR lpszName = szName;
  1307. DWORD cchSize = __INITIAL_NAME_LENGTH;
  1308. DWORD cchRetSize;
  1309. DWORD dwIndex;
  1310. DWORD dwType;
  1311. //
  1312. // Get a resource enumeration handle
  1313. //
  1314. hClusEnum = ClusterOpenEnum( hCluster, CLUSTER_ENUM_RESOURCE );
  1315. if ( hClusEnum == NULL )
  1316. {
  1317. dwStatus = GetLastError();
  1318. goto Cleanup;
  1319. }
  1320. //
  1321. // Enumerate each resource in the cluster
  1322. //
  1323. dwIndex = 0;
  1324. do
  1325. {
  1326. cchRetSize = cchSize;
  1327. dwStatus = ClusterEnum(
  1328. hClusEnum, //handle to enum
  1329. dwIndex, //Index
  1330. &dwType, //Type
  1331. lpszName, //Name
  1332. &cchRetSize //Size of name
  1333. );
  1334. if ( dwStatus == ERROR_MORE_DATA )
  1335. {
  1336. //
  1337. // Output name buffer is too small. Allocate a new one.
  1338. //
  1339. cchSize = cchRetSize + 1; // Add room for terminating null
  1340. if ( lpszName != szName )
  1341. {
  1342. LocalFree( lpszName );
  1343. }
  1344. lpszName = LocalAlloc( LMEM_FIXED, cchSize * sizeof(WCHAR) );
  1345. if ( lpszName == NULL )
  1346. {
  1347. dwStatus = GetLastError();
  1348. break;
  1349. }
  1350. cchRetSize = cchSize;
  1351. dwStatus = ClusterEnum(
  1352. hClusEnum, //handle to enum
  1353. dwIndex, //Index
  1354. &dwType, //Type
  1355. lpszName, //Name
  1356. &cchRetSize //Size of name
  1357. );
  1358. }
  1359. if ( dwStatus == ERROR_SUCCESS )
  1360. {
  1361. //
  1362. // Try to open this resource
  1363. //
  1364. hResource = OpenClusterResource( hCluster, lpszName );
  1365. if ( hResource == NULL )
  1366. {
  1367. dwStatus = GetLastError();
  1368. if ( dwStatus == ERROR_RESOURCE_NOT_FOUND )
  1369. {
  1370. //
  1371. // If the resource cannot be found, assume it got deleted after
  1372. // you opened the enumeration. So, skip the resource and proceed.
  1373. //
  1374. dwIndex ++;
  1375. dwStatus = ERROR_SUCCESS;
  1376. continue;
  1377. }
  1378. break;
  1379. }
  1380. //
  1381. // Indicate that will invoke the callback
  1382. //
  1383. fExecuteCallBack = TRUE;
  1384. // Determine if we need to check the type
  1385. //
  1386. if ( lpszResTypeName != NULL )
  1387. {
  1388. fExecuteCallBack = ResUtilResourceTypesEqual( lpszResTypeName, hResource );
  1389. } //if lpszResTypeName
  1390. if ( fExecuteCallBack && ( hSelf != NULL ) )
  1391. {
  1392. // Don't execute callback if hResource is callee (i.e., hSelf)
  1393. fExecuteCallBack = !(ResUtilResourcesEqual( hSelf, hResource ));
  1394. } //if fExecuteCallBack && hSelf
  1395. if ( fExecuteCallBack )
  1396. {
  1397. dwStatus = pResCallBack( hCluster, hSelf, hResource, pParameter );
  1398. if ( dwStatus != ERROR_SUCCESS )
  1399. {
  1400. break;
  1401. }
  1402. } //if fExecuteCallBack
  1403. CloseClusterResource( hResource );
  1404. hResource = NULL;
  1405. } // If ERROR_SUCCESS
  1406. dwIndex++;
  1407. } while ( dwStatus == ERROR_SUCCESS );
  1408. Cleanup:
  1409. if ( hClusEnum != NULL )
  1410. {
  1411. ClusterCloseEnum( hClusEnum );
  1412. }
  1413. if ( hResource != NULL )
  1414. {
  1415. CloseClusterResource( hResource );
  1416. }
  1417. if ( lpszName != szName )
  1418. {
  1419. LocalFree( lpszName );
  1420. }
  1421. if ( dwStatus == ERROR_NO_MORE_ITEMS )
  1422. {
  1423. dwStatus = ERROR_SUCCESS;
  1424. }
  1425. return dwStatus;
  1426. } //*** ResUtilEnumResourcesEx()
  1427. HRESOURCE
  1428. WINAPI
  1429. ResUtilGetResourceDependency(
  1430. IN HANDLE hSelf,
  1431. IN LPCWSTR lpszResourceType
  1432. )
  1433. /*++
  1434. Routine Description:
  1435. Returns a dependent resource for the local cluster.
  1436. Arguments:
  1437. hSelf - A handle to the original resource.
  1438. lpszResourceType - the type of resource that it depends on
  1439. Return Value:
  1440. NULL - error (use GetLastError() to get further info)
  1441. NON-NULL - Handle to a resource of type ResourceType
  1442. --*/
  1443. {
  1444. HRESOURCE hResDepends = NULL;
  1445. HCLUSTER hCluster = NULL;
  1446. HRESENUM hResEnum = NULL;
  1447. WCHAR szName[ __INITIAL_NAME_LENGTH ];
  1448. LPWSTR pszName = szName;
  1449. DWORD cchSize = __INITIAL_NAME_LENGTH;
  1450. DWORD cchRetSize;
  1451. DWORD dwType = 0;
  1452. DWORD dwIndex = 0;
  1453. DWORD status = ERROR_SUCCESS;
  1454. hCluster = OpenCluster( NULL );
  1455. if ( hCluster == NULL ) {
  1456. return( NULL );
  1457. }
  1458. //
  1459. // Open the depends on enum (get resource dependencies)
  1460. //
  1461. hResEnum = ClusterResourceOpenEnum( hSelf, CLUSTER_RESOURCE_ENUM_DEPENDS );
  1462. if ( hResEnum == NULL ) {
  1463. status = GetLastError();
  1464. goto error_exit;
  1465. }
  1466. //
  1467. // Enumerate all the depends on keys
  1468. //
  1469. do {
  1470. cchRetSize = cchSize;
  1471. status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
  1472. if ( status == ERROR_MORE_DATA ) {
  1473. //
  1474. // Output name buffer is too small. Allocate a new one.
  1475. //
  1476. cchSize = cchRetSize + 1; // Add room for terminating null
  1477. if ( pszName != szName ) {
  1478. LocalFree( pszName );
  1479. }
  1480. pszName = LocalAlloc( LMEM_FIXED, cchSize * sizeof(WCHAR) );
  1481. if ( pszName == NULL ) {
  1482. status = GetLastError();
  1483. break;
  1484. } // if: error allocating memory
  1485. cchRetSize = cchSize;
  1486. status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
  1487. }
  1488. if ( status != ERROR_SUCCESS ) {
  1489. break;
  1490. }
  1491. //
  1492. // Determine the type of resource found
  1493. //
  1494. hResDepends = OpenClusterResource( hCluster, pszName );
  1495. if ( hResDepends == NULL ) {
  1496. status = GetLastError();
  1497. break;
  1498. }
  1499. if ( hResDepends != NULL ) {
  1500. //
  1501. // Valid resource now open the reg and get it's type
  1502. //
  1503. if ( ResUtilResourceTypesEqual( lpszResourceType, hResDepends ) ) {
  1504. break;
  1505. }
  1506. } //if !hResDepends
  1507. //
  1508. // Close all handles, key's
  1509. //
  1510. if ( hResDepends != NULL ) {
  1511. CloseClusterResource( hResDepends );
  1512. hResDepends = NULL;
  1513. }
  1514. dwIndex++;
  1515. } while ( status == ERROR_SUCCESS );
  1516. error_exit:
  1517. //
  1518. // At this point hResDepends is NULL if no match or non-null (success)
  1519. //
  1520. if ( hCluster != NULL ) {
  1521. CloseCluster( hCluster );
  1522. }
  1523. if ( hResEnum != NULL ) {
  1524. ClusterResourceCloseEnum( hResEnum );
  1525. }
  1526. if ( pszName != szName ) {
  1527. LocalFree( pszName );
  1528. }
  1529. if ( status != ERROR_SUCCESS ) {
  1530. SetLastError( status );
  1531. }
  1532. return(hResDepends);
  1533. } //*** ResUtilGetResourceDependency()
  1534. HRESOURCE
  1535. WINAPI
  1536. ResUtilGetResourceDependencyByName(
  1537. IN HCLUSTER hCluster,
  1538. IN HANDLE hSelf,
  1539. IN LPCWSTR lpszResourceType,
  1540. IN BOOL bRecurse
  1541. )
  1542. /*++
  1543. Routine Description:
  1544. Returns a dependent resource for a specified cluster based on the resource
  1545. type name.
  1546. Arguments:
  1547. hCluster - Cluster to query.
  1548. hSelf - A handle to the original resource.
  1549. lpszResourceType - The name of the resource type of the resource that the
  1550. specified resource depends on.
  1551. bRecurse - TRUE = check dependents of dependents. An immediate dependency
  1552. will be returned if there is one.
  1553. Return Value:
  1554. NULL - error (use GetLastError() to get further info)
  1555. NON-NULL - Handle to a resource of type lpszResourceType
  1556. --*/
  1557. {
  1558. HRESOURCE hResDepends = NULL;
  1559. HRESOURCE hResDepends2 = NULL;
  1560. HRESENUM hResEnum = NULL;
  1561. WCHAR szName[ __INITIAL_NAME_LENGTH ];
  1562. LPWSTR pszName = szName;
  1563. DWORD cchSize = __INITIAL_NAME_LENGTH;
  1564. DWORD cchRetSize;
  1565. DWORD dwType = 0;
  1566. DWORD dwIndex = 0;
  1567. DWORD status = ERROR_SUCCESS;
  1568. if ( ( hCluster == NULL ) || ( lpszResourceType == NULL ) )
  1569. {
  1570. SetLastError( ERROR_INVALID_PARAMETER );
  1571. return NULL;
  1572. } // if: no cluster handle or resource type name specified
  1573. //
  1574. // Open the depends on enum (get resource dependencies)
  1575. //
  1576. hResEnum = ClusterResourceOpenEnum( hSelf, CLUSTER_RESOURCE_ENUM_DEPENDS );
  1577. if ( hResEnum == NULL ) {
  1578. status = GetLastError();
  1579. goto error_exit;
  1580. }
  1581. //
  1582. // Enumerate all the depends on keys
  1583. //
  1584. do {
  1585. //
  1586. // Get the next dependent resource.
  1587. //
  1588. cchRetSize = cchSize;
  1589. status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
  1590. if ( status == ERROR_MORE_DATA ) {
  1591. //
  1592. // Output name buffer is too small. Allocate a new one.
  1593. //
  1594. cchSize = cchRetSize + 1; // Add room for terminating null
  1595. if ( pszName != szName ) {
  1596. LocalFree( pszName );
  1597. }
  1598. pszName = LocalAlloc( LMEM_FIXED, cchSize * sizeof(WCHAR) );
  1599. if ( pszName == NULL ) {
  1600. status = GetLastError();
  1601. break;
  1602. } // if: error allocating memory
  1603. cchRetSize = cchSize;
  1604. status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
  1605. }
  1606. if ( status != ERROR_SUCCESS ) {
  1607. break;
  1608. }
  1609. //
  1610. // Open the resource.
  1611. //
  1612. hResDepends = OpenClusterResource( hCluster, pszName );
  1613. if ( hResDepends == NULL ) {
  1614. status = GetLastError();
  1615. break;
  1616. }
  1617. //
  1618. // Resource is valid. Now see if it is the right type.
  1619. //
  1620. if ( ResUtilResourceTypesEqual( lpszResourceType, hResDepends ) ) {
  1621. break;
  1622. }
  1623. //
  1624. // Close all handles, key's
  1625. //
  1626. if ( hResDepends != NULL ) {
  1627. CloseClusterResource( hResDepends );
  1628. hResDepends = NULL;
  1629. }
  1630. dwIndex++;
  1631. } while ( status == ERROR_SUCCESS );
  1632. //
  1633. // If a match was not found, recurse the dependencies again looking for a
  1634. // dependency of the dependencies if the bDeep argument was specified.
  1635. //
  1636. if ( ( status == ERROR_SUCCESS ) && ( hResDepends == NULL ) && bRecurse ) {
  1637. //
  1638. // Open the depends on enum (get resource dependencies)
  1639. //
  1640. ClusterResourceCloseEnum( hResEnum );
  1641. hResEnum = ClusterResourceOpenEnum( hSelf, CLUSTER_RESOURCE_ENUM_DEPENDS );
  1642. if ( hResEnum == NULL ) {
  1643. status = GetLastError();
  1644. goto error_exit;
  1645. }
  1646. //
  1647. // Enumerate all the depends on keys
  1648. //
  1649. dwIndex = 0;
  1650. do {
  1651. //
  1652. // Get the next dependent resource.
  1653. //
  1654. cchRetSize = cchSize;
  1655. status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
  1656. if ( status == ERROR_MORE_DATA ) {
  1657. //
  1658. // Output name buffer is too small. Allocate a new one.
  1659. //
  1660. cchSize = cchRetSize + 1; // Add room for terminating null
  1661. if ( pszName != szName ) {
  1662. LocalFree( pszName );
  1663. }
  1664. pszName = LocalAlloc( LMEM_FIXED, cchSize * sizeof(WCHAR) );
  1665. if ( pszName == NULL ) {
  1666. status = GetLastError();
  1667. break;
  1668. } // if: error allocating memory
  1669. cchRetSize = cchSize;
  1670. status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
  1671. }
  1672. if ( status != ERROR_SUCCESS ) {
  1673. break;
  1674. }
  1675. //
  1676. // Open the resource.
  1677. //
  1678. hResDepends2 = OpenClusterResource( hCluster, pszName );
  1679. if ( hResDepends2 == NULL ) {
  1680. status = GetLastError();
  1681. break;
  1682. }
  1683. //
  1684. // Recursively call ourselves with this resource.
  1685. //
  1686. hResDepends = ResUtilGetResourceDependencyByName(
  1687. hCluster,
  1688. hResDepends2,
  1689. lpszResourceType,
  1690. bRecurse
  1691. );
  1692. if ( hResDepends != NULL ) {
  1693. break;
  1694. }
  1695. status = GetLastError();
  1696. if ( status != ERROR_RESOURCE_NOT_FOUND ) {
  1697. break;
  1698. }
  1699. status = ERROR_SUCCESS;
  1700. //
  1701. // Close all handles, key's
  1702. //
  1703. if ( hResDepends2 != NULL ) {
  1704. CloseClusterResource( hResDepends2 );
  1705. hResDepends2 = NULL;
  1706. }
  1707. dwIndex++;
  1708. } while ( status == ERROR_SUCCESS );
  1709. }
  1710. error_exit:
  1711. if ( hResEnum != NULL ) {
  1712. ClusterResourceCloseEnum( hResEnum );
  1713. }
  1714. if ( hResDepends2 != NULL ) {
  1715. CloseClusterResource( hResDepends2 );
  1716. }
  1717. if ( pszName != szName ) {
  1718. LocalFree( pszName );
  1719. }
  1720. if ( ( status == ERROR_SUCCESS ) && ( hResDepends == NULL ) ) {
  1721. status = ERROR_RESOURCE_NOT_FOUND;
  1722. }
  1723. if ( status != ERROR_SUCCESS ) {
  1724. SetLastError( status );
  1725. }
  1726. return hResDepends;
  1727. } //*** ResUtilGetResourceDependencyByName()
  1728. HRESOURCE
  1729. WINAPI
  1730. ResUtilGetResourceDependencyByClass(
  1731. IN HCLUSTER hCluster,
  1732. IN HANDLE hSelf,
  1733. IN PCLUS_RESOURCE_CLASS_INFO prci,
  1734. IN BOOL bRecurse
  1735. )
  1736. /*++
  1737. Routine Description:
  1738. Returns a dependent resource for a specified cluster based on the resource
  1739. type class information.
  1740. Arguments:
  1741. hCluster - Cluster to query.
  1742. hSelf - A handle to the original resource.
  1743. prci - The resource class info of the resource type of the resource that
  1744. the specified resource depends on.
  1745. bRecurse - TRUE = check dependents of dependents. An immediate dependency
  1746. will be returned if there is one.
  1747. Return Value:
  1748. NULL - error (use GetLastError() to get further info)
  1749. NON-NULL - Handle to a resource whose class is specified by prci.
  1750. --*/
  1751. {
  1752. HRESOURCE hResDepends = NULL;
  1753. HRESOURCE hResDepends2 = NULL;
  1754. HRESENUM hResEnum = NULL;
  1755. WCHAR szName[ __INITIAL_NAME_LENGTH ];
  1756. LPWSTR pszName = szName;
  1757. DWORD cchSize = __INITIAL_NAME_LENGTH;
  1758. DWORD cchRetSize;
  1759. DWORD dwType = 0;
  1760. DWORD dwIndex = 0;
  1761. DWORD status = ERROR_SUCCESS;
  1762. if ( ( hCluster == NULL ) || ( prci == NULL ) )
  1763. {
  1764. SetLastError( ERROR_INVALID_PARAMETER );
  1765. return NULL;
  1766. } // if: no cluster handle or class info specified
  1767. //
  1768. // Open the depends on enum (get resource dependencies)
  1769. //
  1770. hResEnum = ClusterResourceOpenEnum( hSelf, CLUSTER_RESOURCE_ENUM_DEPENDS );
  1771. if ( hResEnum == NULL ) {
  1772. status = GetLastError();
  1773. goto error_exit;
  1774. }
  1775. //
  1776. // Enumerate all the depends on keys
  1777. //
  1778. do {
  1779. //
  1780. // Get the next dependent resource.
  1781. //
  1782. cchRetSize = cchSize;
  1783. status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
  1784. if ( status == ERROR_MORE_DATA ) {
  1785. //
  1786. // Output name buffer is too small. Allocate a new one.
  1787. //
  1788. cchSize = cchRetSize + 1; // Add room for terminating null
  1789. if ( pszName != szName ) {
  1790. LocalFree( pszName );
  1791. }
  1792. pszName = LocalAlloc( LMEM_FIXED, cchSize * sizeof(WCHAR) );
  1793. if ( pszName == NULL ) {
  1794. status = GetLastError();
  1795. break;
  1796. } // if: error allocating memory
  1797. cchRetSize = cchSize;
  1798. status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
  1799. }
  1800. if ( status != ERROR_SUCCESS ) {
  1801. break;
  1802. }
  1803. //
  1804. // Determine the type of resource found
  1805. //
  1806. hResDepends = OpenClusterResource( hCluster, pszName );
  1807. if ( hResDepends == NULL ) {
  1808. status = GetLastError();
  1809. break;
  1810. }
  1811. //
  1812. // Resource is valid. Now see if it is the right class.
  1813. //
  1814. if ( ResUtilIsResourceClassEqual( prci, hResDepends ) ) {
  1815. break;
  1816. }
  1817. //
  1818. // Close all handles, key's
  1819. //
  1820. if ( hResDepends != NULL ) {
  1821. CloseClusterResource( hResDepends );
  1822. hResDepends = NULL;
  1823. }
  1824. dwIndex++;
  1825. } while ( status == ERROR_SUCCESS );
  1826. //
  1827. // If a match was not found, recurse the dependencies again looking for a
  1828. // dependency of the dependencies if the bDeep argument was specified.
  1829. //
  1830. if ( ( status == ERROR_SUCCESS ) && ( hResDepends == NULL ) && bRecurse ) {
  1831. //
  1832. // Open the depends on enum (get resource dependencies)
  1833. //
  1834. ClusterResourceCloseEnum( hResEnum );
  1835. hResEnum = ClusterResourceOpenEnum( hSelf, CLUSTER_RESOURCE_ENUM_DEPENDS );
  1836. if ( hResEnum == NULL ) {
  1837. status = GetLastError();
  1838. goto error_exit;
  1839. }
  1840. //
  1841. // Enumerate all the depends on keys
  1842. //
  1843. dwIndex = 0;
  1844. do {
  1845. //
  1846. // Get the next dependent resource.
  1847. //
  1848. cchRetSize = cchSize;
  1849. status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
  1850. if ( status == ERROR_MORE_DATA ) {
  1851. //
  1852. // Output name buffer is too small. Allocate a new one.
  1853. //
  1854. cchSize = cchRetSize + 1; // Add room for terminating null
  1855. if ( pszName != szName ) {
  1856. LocalFree( pszName );
  1857. }
  1858. pszName = LocalAlloc( LMEM_FIXED, cchSize * sizeof(WCHAR) );
  1859. if ( pszName == NULL ) {
  1860. status = GetLastError();
  1861. break;
  1862. } // if: error allocating memory
  1863. cchRetSize = cchSize;
  1864. status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
  1865. }
  1866. if ( status != ERROR_SUCCESS ) {
  1867. break;
  1868. }
  1869. //
  1870. // Open the resource.
  1871. //
  1872. hResDepends2 = OpenClusterResource( hCluster, pszName );
  1873. if ( hResDepends2 == NULL ) {
  1874. status = GetLastError();
  1875. break;
  1876. }
  1877. //
  1878. // Recursively call ourselves with this resource.
  1879. //
  1880. hResDepends = ResUtilGetResourceDependencyByClass(
  1881. hCluster,
  1882. hResDepends2,
  1883. prci,
  1884. bRecurse
  1885. );
  1886. if ( hResDepends != NULL ) {
  1887. break;
  1888. }
  1889. status = GetLastError();
  1890. if ( status != ERROR_RESOURCE_NOT_FOUND ) {
  1891. break;
  1892. }
  1893. status = ERROR_SUCCESS;
  1894. //
  1895. // Close all handles, key's
  1896. //
  1897. if ( hResDepends2 != NULL ) {
  1898. CloseClusterResource( hResDepends2 );
  1899. hResDepends2 = NULL;
  1900. }
  1901. dwIndex++;
  1902. } while ( status == ERROR_SUCCESS );
  1903. }
  1904. error_exit:
  1905. if ( hResEnum != NULL ) {
  1906. ClusterResourceCloseEnum( hResEnum );
  1907. }
  1908. if ( hResDepends2 != NULL ) {
  1909. CloseClusterResource( hResDepends2 );
  1910. }
  1911. if ( pszName != szName ) {
  1912. LocalFree( pszName );
  1913. }
  1914. if ( ( status == ERROR_SUCCESS ) && ( hResDepends == NULL ) ) {
  1915. status = ERROR_RESOURCE_NOT_FOUND;
  1916. }
  1917. if ( status != ERROR_SUCCESS ) {
  1918. SetLastError( status );
  1919. }
  1920. return hResDepends;
  1921. } //*** ResUtilGetResourceDependencyByClass()
  1922. HRESOURCE
  1923. WINAPI
  1924. ResUtilGetResourceNameDependency(
  1925. IN LPCWSTR lpszResourceName,
  1926. IN LPCWSTR lpszResourceType
  1927. )
  1928. /*++
  1929. Routine Description:
  1930. Returns a dependent resource
  1931. Arguments:
  1932. lpszResourceName - the name of the resource
  1933. lpszResourceType - the type of the resource that it depends on
  1934. Return Value:
  1935. NULL - error (use GetLastError() to get further info)
  1936. NON-NULL - Handle to a resource of type ResourceType
  1937. --*/
  1938. {
  1939. HRESOURCE hResDepends = NULL;
  1940. HCLUSTER hCluster = NULL;
  1941. HRESOURCE hSelf = NULL;
  1942. HRESENUM hResEnum = NULL;
  1943. WCHAR szName[ __INITIAL_NAME_LENGTH ];
  1944. LPWSTR pszName = szName;
  1945. DWORD cchSize = __INITIAL_NAME_LENGTH;
  1946. DWORD cchRetSize;
  1947. DWORD dwType = 0;
  1948. DWORD dwIndex = 0;
  1949. DWORD status = ERROR_SUCCESS;
  1950. if ( lpszResourceName == NULL ) {
  1951. SetLastError( ERROR_INVALID_PARAMETER );
  1952. return( NULL );
  1953. }
  1954. hCluster = OpenCluster( NULL );
  1955. if ( hCluster == NULL ) {
  1956. return( NULL );
  1957. }
  1958. //
  1959. // Open a handle to the passed in resource name.
  1960. //
  1961. hSelf = OpenClusterResource( hCluster, lpszResourceName );
  1962. if ( hSelf == NULL ) {
  1963. goto error_exit;
  1964. }
  1965. //
  1966. // Open the depends on enum (get resource dependencies)
  1967. //
  1968. hResEnum = ClusterResourceOpenEnum( hSelf, CLUSTER_RESOURCE_ENUM_DEPENDS );
  1969. if ( hResEnum == NULL ) {
  1970. goto error_exit;
  1971. }
  1972. //
  1973. // Enumerate all the depends on keys
  1974. //
  1975. do {
  1976. cchRetSize = cchSize;
  1977. status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
  1978. if ( status == ERROR_MORE_DATA ) {
  1979. //
  1980. // Output name buffer is too small. Allocate a new one.
  1981. //
  1982. cchSize = cchRetSize + 1; // Add room for terminating NULL
  1983. if ( pszName != szName ) {
  1984. LocalFree( pszName );
  1985. }
  1986. pszName = LocalAlloc( LMEM_FIXED, cchSize * sizeof(WCHAR) );
  1987. if ( pszName == NULL ) {
  1988. status = GetLastError();
  1989. break;
  1990. } // if: error allocating memory
  1991. cchRetSize = cchSize;
  1992. status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
  1993. }
  1994. if ( status != ERROR_SUCCESS ) {
  1995. break;
  1996. }
  1997. //
  1998. // Determine the type of resource found
  1999. //
  2000. hResDepends = OpenClusterResource( hCluster, pszName );
  2001. if ( hResDepends == NULL ) {
  2002. break;
  2003. }
  2004. //
  2005. // Valid resource now open the reg and get it's type
  2006. //
  2007. if ( ResUtilResourceTypesEqual( lpszResourceType, hResDepends ) ) {
  2008. break;
  2009. }
  2010. //
  2011. // Close all handles, key's
  2012. //
  2013. if ( hResDepends != NULL ) {
  2014. CloseClusterResource( hResDepends );
  2015. hResDepends = NULL;
  2016. }
  2017. dwIndex++;
  2018. } while (status == ERROR_SUCCESS);
  2019. error_exit:
  2020. //
  2021. // At this point hResDepends is NULL if no match or non-null (success)
  2022. //
  2023. if ( hCluster != NULL ) {
  2024. CloseCluster( hCluster );
  2025. }
  2026. if ( hSelf != NULL ) {
  2027. CloseClusterResource( hSelf );
  2028. }
  2029. if ( hResEnum != NULL ) {
  2030. ClusterResourceCloseEnum( hResEnum );
  2031. }
  2032. if ( pszName != szName ) {
  2033. LocalFree( pszName );
  2034. }
  2035. if ( status != ERROR_SUCCESS ) {
  2036. SetLastError( status );
  2037. }
  2038. return hResDepends;
  2039. } //*** ResUtilGetResourceNameDependency()
  2040. DWORD
  2041. WINAPI
  2042. ResUtilGetPropertyFormats(
  2043. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  2044. OUT PVOID pOutPropertyFormatList,
  2045. IN DWORD cbPropertyFormatListSize,
  2046. OUT LPDWORD pcbBytesReturned,
  2047. OUT LPDWORD pcbRequired
  2048. )
  2049. {
  2050. return( ClRtlGetPropertyFormats( pPropertyTable,
  2051. pOutPropertyFormatList,
  2052. cbPropertyFormatListSize,
  2053. pcbBytesReturned,
  2054. pcbRequired ) );
  2055. } // ResUtilGetPropertyFormats()