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.

972 lines
25 KiB

  1. /*++
  2. Copyright (c) 1990-1994 Microsoft Corporation
  3. All rights reserved
  4. Module Name:
  5. Cluster registry apis.
  6. Abstract:
  7. Determines whether ClusterReg or Reg apis should be used.
  8. The printer information is stored in the registry. When we access
  9. local printers, we hit the local registry; when we access cluster
  10. printers, we hit the cluster registry.
  11. Author:
  12. Albert Ting (AlbertT) 8-Oct-96
  13. Environment:
  14. User Mode -Win32
  15. Revision History:
  16. Felix Maxa (amaxa) 18-Jun-2000
  17. Added ClusterGetResourceID
  18. ClusterGetResourceDriveLetter
  19. --*/
  20. #include "precomp.h"
  21. #pragma hdrstop
  22. #include <clusapi.h>
  23. #include "clusspl.h"
  24. enum
  25. {
  26. kDriveLetterStringSize = 3,
  27. kGuidStringSize = 40
  28. };
  29. /********************************************************************
  30. Globals.
  31. ********************************************************************/
  32. typedef struct _CLUSAPI {
  33. HCLUSTER
  34. (*pfnOpenCluster)(
  35. IN LPCWSTR lpszClusterName
  36. );
  37. BOOL
  38. (*pfnCloseCluster)(
  39. IN HCLUSTER hCluster
  40. );
  41. HRESOURCE
  42. (*pfnOpenClusterResource)(
  43. IN HCLUSTER hCluster,
  44. IN LPCWSTR lpszResourceName
  45. );
  46. BOOL
  47. (*pfnCloseClusterResource)(
  48. IN HRESOURCE hResource
  49. );
  50. HKEY
  51. (*pfnGetClusterKey)(
  52. IN HCLUSTER hCluster,
  53. IN REGSAM samDesired
  54. );
  55. HKEY
  56. (*pfnGetClusterResourceKey)(
  57. IN HRESOURCE hResource,
  58. IN REGSAM samDesired
  59. );
  60. LONG
  61. (*pfnClusterRegCreateKey)(
  62. IN HKEY hKey,
  63. IN LPCWSTR lpszSubKey,
  64. IN DWORD dwOptions,
  65. IN REGSAM samDesired,
  66. IN LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  67. OUT PHKEY phkResult,
  68. OUT OPTIONAL LPDWORD lpdwDisposition
  69. );
  70. LONG
  71. (*pfnClusterRegOpenKey)(
  72. IN HKEY hKey,
  73. IN LPCWSTR lpszSubKey,
  74. IN REGSAM samDesired,
  75. OUT PHKEY phkResult
  76. );
  77. LONG
  78. (*pfnClusterRegDeleteKey)(
  79. IN HKEY hKey,
  80. IN LPCWSTR lpszSubKey
  81. );
  82. LONG
  83. (*pfnClusterRegCloseKey)(
  84. IN HKEY hKey
  85. );
  86. LONG
  87. (*pfnClusterRegEnumKey)(
  88. IN HKEY hKey,
  89. IN DWORD dwIndex,
  90. OUT LPWSTR lpszName,
  91. IN OUT LPDWORD lpcbName,
  92. OUT PFILETIME lpftLastWriteTime
  93. );
  94. DWORD
  95. (*pfnClusterRegSetValue)(
  96. IN HKEY hKey,
  97. IN LPCWSTR lpszValueName,
  98. IN DWORD dwType,
  99. IN CONST BYTE* lpData,
  100. IN DWORD cbData
  101. );
  102. DWORD
  103. (*pfnClusterRegDeleteValue)(
  104. IN HKEY hKey,
  105. IN LPCWSTR lpszValueName
  106. );
  107. LONG
  108. (*pfnClusterRegQueryValue)(
  109. IN HKEY hKey,
  110. IN LPCWSTR lpszValueName,
  111. OUT LPDWORD lpValueType,
  112. OUT LPBYTE lpData,
  113. IN OUT LPDWORD lpcbData
  114. );
  115. DWORD
  116. (*pfnClusterRegEnumValue)(
  117. IN HKEY hKey,
  118. IN DWORD dwIndex,
  119. OUT LPWSTR lpszValueName,
  120. IN OUT LPDWORD lpcbValueName,
  121. OUT LPDWORD lpType,
  122. OUT LPBYTE lpData,
  123. IN OUT LPDWORD lpcbData
  124. );
  125. LONG
  126. (*pfnClusterRegQueryInfoKey)(
  127. HKEY hKey,
  128. LPDWORD lpcSubKeys,
  129. LPDWORD lpcbMaxSubKeyLen,
  130. LPDWORD lpcValues,
  131. LPDWORD lpcbMaxValueNameLen,
  132. LPDWORD lpcbMaxValueLen,
  133. LPDWORD lpcbSecurityDescriptor,
  134. PFILETIME lpftLastWriteTime
  135. );
  136. DWORD
  137. (*pfnClusterResourceControl)(
  138. HRESOURCE hResource,
  139. HNODE hHostNode,
  140. DWORD dwControlCode,
  141. LPVOID lpInBuffer,
  142. DWORD cbInBufferSize,
  143. LPVOID lpOutBuffer,
  144. DWORD cbOutBufferSize,
  145. LPDWORD lpcbBytesReturned
  146. );
  147. } CLUSAPI, *PCLUSAPI;
  148. CLUSAPI ClusApi;
  149. LPCSTR aszClusApi[] = {
  150. "OpenCluster",
  151. "CloseCluster",
  152. "OpenClusterResource",
  153. "CloseClusterResource",
  154. "GetClusterKey",
  155. "GetClusterResourceKey",
  156. "ClusterRegCreateKey",
  157. "ClusterRegOpenKey",
  158. "ClusterRegDeleteKey",
  159. "ClusterRegCloseKey",
  160. "ClusterRegEnumKey",
  161. "ClusterRegSetValue",
  162. "ClusterRegDeleteValue",
  163. "ClusterRegQueryValue",
  164. "ClusterRegEnumValue",
  165. "ClusterRegQueryInfoKey",
  166. "ClusterResourceControl"
  167. };
  168. /********************************************************************
  169. OpenCluster
  170. CloseCluster
  171. OpenClusterResource
  172. CloseClusterResource
  173. GetClusterResourceKey
  174. ClusterRegCreateKey
  175. ClusterRegOpenKey
  176. ClusterRegDeleteKey
  177. ClusterRegCloseKey
  178. ClusterRegEnumKey
  179. ClusterRegSetValue
  180. ClusterRegDeleteValue
  181. ClusterRegQueryValue
  182. ClusterRegEnumValue
  183. ClusterRegQueryInfoKey
  184. ********************************************************************/
  185. BOOL
  186. LoadClusterFunctions(
  187. VOID
  188. )
  189. /*++
  190. Routine Description:
  191. Load ClusApi functions. Must be called before any cluster api
  192. is used.
  193. Arguments:
  194. Return Value:
  195. TRUE - Success
  196. FALSE - Fail
  197. --*/
  198. {
  199. HANDLE hLibrary;
  200. UINT i;
  201. FARPROC* pFarProc = (FARPROC*)&ClusApi;
  202. //
  203. // Size of string table and structure are identical.
  204. //
  205. SPLASSERT( COUNTOF( aszClusApi ) == sizeof( ClusApi )/sizeof( FARPROC ));
  206. if( ClusApi.pfnOpenCluster ){
  207. return TRUE;
  208. }
  209. i = SetErrorMode(SEM_FAILCRITICALERRORS);
  210. hLibrary = LoadLibrary( TEXT( "clusapi.dll" ));
  211. SetErrorMode(i);
  212. if( !hLibrary ){
  213. goto Fail;
  214. }
  215. for( i=0; i< COUNTOF( aszClusApi ); ++i, ++pFarProc) {
  216. *pFarProc = GetProcAddress( hLibrary, aszClusApi[i] );
  217. if( !*pFarProc ){
  218. DBGMSG( DBG_WARN,
  219. ( "LoadClusterFunctions: Loading function %hs failed %d\n",
  220. aszClusApi[i], GetLastError( )));
  221. goto Fail;
  222. }
  223. }
  224. return TRUE;
  225. Fail:
  226. if( hLibrary ){
  227. FreeLibrary( hLibrary );
  228. }
  229. ClusApi.pfnOpenCluster = NULL;
  230. return FALSE;
  231. }
  232. HKEY
  233. OpenClusterParameterKey(
  234. IN LPCTSTR pszResource
  235. )
  236. /*++
  237. Routine Description:
  238. Based on a resource string, open the cluster key with FULL access.
  239. Arguments:
  240. pszResource - Name of the resource key.
  241. Return Value:
  242. HKEY - Success. Key must be closed with
  243. NULL - Failure. LastError set.
  244. --*/
  245. {
  246. HCLUSTER hCluster;
  247. HRESOURCE hResource = NULL;
  248. HKEY hKeyResource = NULL;
  249. HKEY hKey = NULL;
  250. DWORD Status;
  251. DWORD dwDisposition;
  252. if( !LoadClusterFunctions( )){
  253. return NULL;
  254. }
  255. hCluster = ClusApi.pfnOpenCluster( NULL );
  256. if( !hCluster ){
  257. DBGMSG( DBG_WARN,
  258. ( "OpenClusterResourceKey: failed to open cluster %d\n",
  259. GetLastError() ));
  260. goto Fail;
  261. }
  262. hResource = ClusApi.pfnOpenClusterResource( hCluster, pszResource );
  263. if( !hResource ){
  264. DBGMSG( DBG_WARN,
  265. ( "OpenClusterResourceKey: failed to open resource "TSTR" %d\n",
  266. pszResource, GetLastError() ));
  267. goto Fail;
  268. }
  269. hKeyResource = ClusApi.pfnGetClusterResourceKey( hResource,
  270. KEY_ALL_ACCESS );
  271. if( !hKeyResource ){
  272. DBGMSG( DBG_WARN,
  273. ( "OpenClusterResourceKey: failed to open resource key %d\n",
  274. GetLastError() ));
  275. goto Fail;
  276. }
  277. if((Status = ClusApi.pfnClusterRegOpenKey( hKeyResource,
  278. szParameters,
  279. KEY_CREATE_SUB_KEY | KEY_ALL_ACCESS,
  280. &hKey )) == ERROR_FILE_NOT_FOUND)
  281. {
  282. Status = ClusApi.pfnClusterRegCreateKey( hKeyResource,
  283. szParameters,
  284. 0,
  285. KEY_ALL_ACCESS,
  286. NULL,
  287. &hKey,
  288. &dwDisposition );
  289. }
  290. if( Status != ERROR_SUCCESS ){
  291. SetLastError( Status );
  292. hKey = NULL;
  293. DBGMSG( DBG_WARN,
  294. ( "OpenClusterResourceKey: failed to create resource key %d\n",
  295. Status ));
  296. }
  297. Fail:
  298. if( hKeyResource ){
  299. ClusApi.pfnClusterRegCloseKey( hKeyResource );
  300. }
  301. if( hResource ){
  302. ClusApi.pfnCloseClusterResource( hResource );
  303. }
  304. if( hCluster ){
  305. ClusApi.pfnCloseCluster( hCluster );
  306. }
  307. return hKey;
  308. }
  309. /********************************************************************
  310. SplReg*Key functions:
  311. Used for printer registry access.
  312. ********************************************************************/
  313. LONG
  314. SplRegCreateKey(
  315. IN HKEY hKey,
  316. IN LPCTSTR pszSubKey,
  317. IN DWORD dwOptions,
  318. IN REGSAM samDesired,
  319. IN PSECURITY_ATTRIBUTES pSecurityAttributes,
  320. OUT PHKEY phkResult,
  321. OUT PDWORD pdwDisposition,
  322. IN PINISPOOLER pIniSpooler OPTIONAL
  323. )
  324. {
  325. DWORD dwDisposition;
  326. DWORD Status;
  327. if( !pdwDisposition ){
  328. pdwDisposition = &dwDisposition;
  329. }
  330. if( pIniSpooler && pIniSpooler->SpoolerFlags & SPL_CLUSTER_REG )
  331. {
  332. if( !LoadClusterFunctions( ))
  333. {
  334. return GetLastError();
  335. }
  336. if((Status = ClusApi.pfnClusterRegOpenKey( hKey,
  337. pszSubKey,
  338. KEY_CREATE_SUB_KEY | samDesired,
  339. phkResult)) == ERROR_FILE_NOT_FOUND)
  340. {
  341. Status = ClusApi.pfnClusterRegCreateKey( hKey,
  342. pszSubKey,
  343. dwOptions,
  344. samDesired,
  345. pSecurityAttributes,
  346. phkResult,
  347. &dwDisposition );
  348. }
  349. }
  350. else
  351. {
  352. Status = RegCreateKeyEx( hKey,
  353. pszSubKey,
  354. 0,
  355. NULL,
  356. dwOptions,
  357. samDesired,
  358. pSecurityAttributes,
  359. phkResult,
  360. &dwDisposition );
  361. }
  362. return(Status);
  363. }
  364. LONG
  365. SplRegOpenKey(
  366. IN HKEY hKey,
  367. IN LPCTSTR pszSubKey,
  368. IN REGSAM samDesired,
  369. OUT PHKEY phkResult,
  370. IN PINISPOOLER pIniSpooler OPTIONAL
  371. )
  372. {
  373. if( pIniSpooler && pIniSpooler->SpoolerFlags & SPL_CLUSTER_REG ){
  374. if( !LoadClusterFunctions( )){
  375. return GetLastError();
  376. }
  377. return ClusApi.pfnClusterRegOpenKey( hKey,
  378. pszSubKey,
  379. samDesired,
  380. phkResult );
  381. }
  382. return RegOpenKeyEx( hKey,
  383. pszSubKey,
  384. 0,
  385. samDesired,
  386. phkResult );
  387. }
  388. LONG
  389. SplRegCloseKey(
  390. IN HKEY hKey,
  391. IN PINISPOOLER pIniSpooler OPTIONAL
  392. )
  393. {
  394. if( pIniSpooler && pIniSpooler->SpoolerFlags & SPL_CLUSTER_REG ){
  395. if( !LoadClusterFunctions( )){
  396. return GetLastError();
  397. }
  398. return ClusApi.pfnClusterRegCloseKey( hKey );
  399. }
  400. return RegCloseKey( hKey );
  401. }
  402. LONG
  403. SplRegDeleteKey(
  404. IN HKEY hKey,
  405. IN LPCTSTR pszSubKey,
  406. IN PINISPOOLER pIniSpooler OPTIONAL
  407. )
  408. {
  409. if( pIniSpooler && pIniSpooler->SpoolerFlags & SPL_CLUSTER_REG ){
  410. if( !LoadClusterFunctions( )){
  411. return GetLastError();
  412. }
  413. return ClusApi.pfnClusterRegDeleteKey( hKey, pszSubKey );
  414. }
  415. return RegDeleteKey( hKey, pszSubKey );
  416. }
  417. LONG
  418. SplRegEnumKey(
  419. IN HKEY hKey,
  420. IN DWORD dwIndex,
  421. IN LPTSTR pszName,
  422. IN OUT PDWORD pcchName,
  423. OUT PFILETIME pft,
  424. IN PINISPOOLER pIniSpooler OPTIONAL
  425. )
  426. {
  427. FILETIME ft;
  428. if( !pft ){
  429. pft = &ft;
  430. }
  431. if( pIniSpooler && pIniSpooler->SpoolerFlags & SPL_CLUSTER_REG ){
  432. if( !LoadClusterFunctions( )){
  433. return GetLastError();
  434. }
  435. return ClusApi.pfnClusterRegEnumKey( hKey,
  436. dwIndex,
  437. pszName,
  438. pcchName,
  439. pft );
  440. }
  441. return RegEnumKeyEx( hKey,
  442. dwIndex,
  443. pszName,
  444. pcchName,
  445. NULL,
  446. NULL,
  447. NULL,
  448. pft );
  449. }
  450. LONG
  451. SplRegSetValue(
  452. IN HKEY hKey,
  453. IN LPCTSTR pszValue,
  454. IN DWORD dwType,
  455. IN const BYTE* pData,
  456. IN DWORD cbData,
  457. IN PINISPOOLER pIniSpooler OPTIONAL
  458. )
  459. {
  460. if( pIniSpooler && pIniSpooler->SpoolerFlags & SPL_CLUSTER_REG ){
  461. if( !LoadClusterFunctions( )){
  462. return GetLastError();
  463. }
  464. //
  465. // ClusterRegSetValue doesn't like NULL pointers.
  466. //
  467. if( cbData == 0 ){
  468. pData = (PBYTE)&cbData;
  469. }
  470. return ClusApi.pfnClusterRegSetValue( hKey,
  471. pszValue,
  472. dwType,
  473. pData,
  474. cbData );
  475. }
  476. return RegSetValueEx( hKey,
  477. pszValue,
  478. 0,
  479. dwType,
  480. pData,
  481. cbData );
  482. }
  483. LONG
  484. SplRegDeleteValue(
  485. IN HKEY hKey,
  486. IN LPCTSTR pszValue,
  487. IN PINISPOOLER pIniSpooler OPTIONAL
  488. )
  489. {
  490. if( pIniSpooler && pIniSpooler->SpoolerFlags & SPL_CLUSTER_REG ){
  491. if( !LoadClusterFunctions( )){
  492. return GetLastError();
  493. }
  494. return ClusApi.pfnClusterRegDeleteValue( hKey, pszValue );
  495. }
  496. return RegDeleteValue( hKey, pszValue );
  497. }
  498. LONG
  499. SplRegQueryValue(
  500. IN HKEY hKey,
  501. IN LPCTSTR pszValue,
  502. OUT PDWORD pType, OPTIONAL
  503. OUT PBYTE pData,
  504. IN OUT PDWORD pcbData,
  505. IN PINISPOOLER pIniSpooler OPTIONAL
  506. )
  507. {
  508. if( pIniSpooler && pIniSpooler->SpoolerFlags & SPL_CLUSTER_REG ){
  509. if( !LoadClusterFunctions( )){
  510. return GetLastError();
  511. }
  512. return ClusApi.pfnClusterRegQueryValue( hKey,
  513. pszValue,
  514. pType,
  515. pData,
  516. pcbData );
  517. }
  518. return RegQueryValueEx( hKey,
  519. pszValue,
  520. NULL,
  521. pType,
  522. pData,
  523. pcbData );
  524. }
  525. LONG
  526. SplRegEnumValue(
  527. IN HKEY hKey,
  528. IN DWORD dwIndex,
  529. OUT LPTSTR pszValue,
  530. IN OUT PDWORD pcbValue,
  531. OUT PDWORD pType, OPTIONAL
  532. OUT PBYTE pData,
  533. IN OUT PDWORD pcbData,
  534. IN PINISPOOLER pIniSpooler OPTIONAL
  535. )
  536. {
  537. if( pIniSpooler && pIniSpooler->SpoolerFlags & SPL_CLUSTER_REG ){
  538. if( !LoadClusterFunctions( )){
  539. return GetLastError();
  540. }
  541. return ClusApi.pfnClusterRegEnumValue( hKey,
  542. dwIndex,
  543. pszValue,
  544. pcbValue,
  545. pType,
  546. pData,
  547. pcbData );
  548. }
  549. return RegEnumValue( hKey,
  550. dwIndex,
  551. pszValue,
  552. pcbValue,
  553. NULL,
  554. pType,
  555. pData,
  556. pcbData );
  557. }
  558. LONG
  559. SplRegQueryInfoKey(
  560. HKEY hKey,
  561. PDWORD pcSubKeys,
  562. PDWORD pcbKey,
  563. PDWORD pcValues,
  564. PDWORD pcbValue,
  565. PDWORD pcbData,
  566. PDWORD pcbSecurityDescriptor,
  567. PFILETIME pftLastWriteTime,
  568. PINISPOOLER pIniSpooler
  569. )
  570. {
  571. LONG rc;
  572. if( pIniSpooler && pIniSpooler->SpoolerFlags & SPL_CLUSTER_REG ){
  573. if( !LoadClusterFunctions( )){
  574. return GetLastError();
  575. }
  576. rc = ClusApi.pfnClusterRegQueryInfoKey( hKey,
  577. pcSubKeys,
  578. pcbKey,
  579. pcValues,
  580. pcbValue,
  581. pcbData,
  582. pcbSecurityDescriptor,
  583. pftLastWriteTime);
  584. } else {
  585. rc = RegQueryInfoKey( hKey, // Key
  586. NULL, // lpClass
  587. NULL, // lpcbClass
  588. NULL, // lpReserved
  589. pcSubKeys, // lpcSubKeys
  590. pcbKey, // lpcbMaxSubKeyLen
  591. NULL, // lpcbMaxClassLen
  592. pcValues, // lpcValues
  593. pcbValue, // lpcbMaxValueNameLen
  594. pcbData, // lpcbMaxValueLen
  595. pcbSecurityDescriptor, // lpcbSecurityDescriptor
  596. pftLastWriteTime // lpftLastWriteTime
  597. );
  598. }
  599. if( pcbValue ){
  600. *pcbValue = ( *pcbValue + 1 ) * sizeof(WCHAR);
  601. }
  602. return rc;
  603. }
  604. /*++
  605. Routine Name:
  606. ClusterGetResourceDriveLetter
  607. Routine Description:
  608. Gets the dependent disk for a cluster resource
  609. (a cluster spooler resource)
  610. Arguments:
  611. pszResource - spooler resource name
  612. ppszClusResDriveLetter - pointer that will get the pointer to string
  613. Must be freed by caller using FreeSplMem()
  614. Return Value:
  615. Win32 error code
  616. --*/
  617. DWORD
  618. ClusterGetResourceDriveLetter(
  619. IN LPCWSTR pszResource,
  620. OUT LPWSTR *ppszClusResDriveLetter
  621. )
  622. {
  623. DWORD dwError = ERROR_INVALID_PARAMETER;
  624. if (pszResource && ppszClusResDriveLetter)
  625. {
  626. HCLUSTER hCluster = NULL;
  627. HRESOURCE hRes = NULL;
  628. LPCWSTR pszDllName = L"resutils.dll";
  629. HMODULE hModule = NULL;
  630. typedef DWORD (WINAPI *PFNFINDDISK)(HCLUSTER, HRESOURCE, LPWSTR, LPDWORD);
  631. PFNFINDDISK pfnFindDisk;
  632. //
  633. // Don't leave the out var uninitialized
  634. //
  635. *ppszClusResDriveLetter = NULL;
  636. if (LoadClusterFunctions() &&
  637. (hCluster = ClusApi.pfnOpenCluster(NULL)) &&
  638. (hRes = ClusApi.pfnOpenClusterResource(hCluster, pszResource)) &&
  639. (hModule = LoadLibrary(pszDllName)) &&
  640. (pfnFindDisk = (PFNFINDDISK)GetProcAddress(hModule, "ResUtilFindDependentDiskResourceDriveLetter")))
  641. {
  642. //
  643. // We make a guess for how large the buffer must be. We may not have to call
  644. // the resutil function twice. Driver letter + colon + NULL = 3
  645. //
  646. DWORD cchDriveLetter = kDriveLetterStringSize;
  647. dwError = ERROR_NOT_ENOUGH_MEMORY;
  648. if (*ppszClusResDriveLetter = AllocSplMem(cchDriveLetter * sizeof(WCHAR)))
  649. {
  650. dwError = pfnFindDisk(hCluster, hRes, *ppszClusResDriveLetter, &cchDriveLetter);
  651. //
  652. // Reallocate buffer if it was not sufficient
  653. //
  654. if (dwError == ERROR_MORE_DATA)
  655. {
  656. FreeSplMem(*ppszClusResDriveLetter);
  657. dwError = ERROR_NOT_ENOUGH_MEMORY;
  658. if (*ppszClusResDriveLetter = AllocSplMem(cchDriveLetter * sizeof(WCHAR)))
  659. {
  660. dwError = pfnFindDisk(hCluster, hRes, *ppszClusResDriveLetter, &cchDriveLetter);
  661. }
  662. }
  663. if (dwError != ERROR_SUCCESS)
  664. {
  665. //
  666. // Clean up in case of failure
  667. //
  668. FreeSplMem(*ppszClusResDriveLetter);
  669. *ppszClusResDriveLetter = NULL;
  670. }
  671. }
  672. }
  673. else
  674. {
  675. dwError = GetLastError();
  676. }
  677. if (hCluster)
  678. {
  679. ClusApi.pfnCloseCluster(hCluster);
  680. }
  681. if (hRes)
  682. {
  683. ClusApi.pfnCloseClusterResource(hRes);
  684. }
  685. if (hModule)
  686. {
  687. FreeLibrary(hModule);
  688. }
  689. }
  690. DBGMSG(DBG_CLUSTER, ("ClusterGetResourceDriveLetter returns Win32 error %u\n", dwError));
  691. return dwError;
  692. }
  693. /*++
  694. Routine Name:
  695. ClusterGetResourceID
  696. Routine Description:
  697. Gets the resource id (guid) for a specified cluster resource.
  698. Arguments:
  699. pszResource - spooler resource name
  700. ppszClusResID - pointer that will get the pointer to string
  701. Must be freed by caller using FreeSplMem()
  702. Return Value:
  703. Win32 error code
  704. --*/
  705. DWORD
  706. ClusterGetResourceID(
  707. IN LPCWSTR pszResource,
  708. OUT LPWSTR *ppszClusResID
  709. )
  710. {
  711. DWORD dwError = ERROR_INVALID_PARAMETER;
  712. if (pszResource && ppszClusResID)
  713. {
  714. HCLUSTER hCluster = NULL;
  715. HRESOURCE hRes = NULL;
  716. *ppszClusResID = NULL;
  717. if (LoadClusterFunctions() &&
  718. (hCluster = ClusApi.pfnOpenCluster(NULL)) &&
  719. (hRes = ClusApi.pfnOpenClusterResource(hCluster, pszResource)))
  720. {
  721. //
  722. // The resource ID is a GUID. We make a gues for its size, maybe we
  723. // get around calling the function ClusterResourceControl twice.
  724. //
  725. DWORD cbIDString = kGuidStringSize * sizeof(WCHAR);
  726. dwError = ERROR_NOT_ENOUGH_MEMORY;
  727. if (*ppszClusResID = AllocSplMem(cbIDString))
  728. {
  729. dwError = ClusApi.pfnClusterResourceControl(hRes,
  730. NULL,
  731. CLUSCTL_RESOURCE_GET_ID,
  732. NULL,
  733. 0,
  734. *ppszClusResID,
  735. cbIDString,
  736. &cbIDString);
  737. //
  738. // Reallocate buffer if it was not sufficiently large
  739. //
  740. if (dwError == ERROR_MORE_DATA)
  741. {
  742. FreeSplMem(*ppszClusResID);
  743. dwError = ERROR_NOT_ENOUGH_MEMORY;
  744. if (*ppszClusResID = AllocSplMem(cbIDString ))
  745. {
  746. dwError = ClusApi.pfnClusterResourceControl(hRes,
  747. NULL,
  748. CLUSCTL_RESOURCE_GET_ID,
  749. NULL,
  750. 0,
  751. *ppszClusResID,
  752. cbIDString,
  753. &cbIDString);
  754. }
  755. }
  756. if (dwError != ERROR_SUCCESS)
  757. {
  758. //
  759. // Clean up in case of failure
  760. //
  761. FreeSplMem(*ppszClusResID);
  762. *ppszClusResID = NULL;
  763. }
  764. }
  765. }
  766. else
  767. {
  768. dwError = GetLastError();
  769. }
  770. if (hRes)
  771. {
  772. ClusApi.pfnCloseClusterResource(hRes);
  773. }
  774. if (hCluster)
  775. {
  776. ClusApi.pfnCloseCluster(hCluster);
  777. }
  778. }
  779. DBGMSG(DBG_CLUSTER, ("ClusterGetResourceID returns Win32 error %u\n", dwError));
  780. return dwError;
  781. }