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.

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