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.

835 lines
29 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1999 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. cluster.cpp
  7. handles starting/stopping cluster resources
  8. FILE HISTORY:
  9. */
  10. //define USE_CCLUSPROPLIST // tells Clushead.h to compile for the CClusPropList class
  11. //include "clushead.h" // the Sample Include Header
  12. #include "stdafx.h"
  13. #include "cluster.h"
  14. #include "objplus.h"
  15. #include "ipaddres.h"
  16. #ifdef _DEBUG
  17. #define new DEBUG_NEW
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21. DynamicDLL g_ClusDLL( _T("CLUSAPI.DLL"), g_apchClusFunctionNames );
  22. DynamicDLL g_ResUtilsDLL( _T("RESUTILS.DLL"), g_apchResUtilsFunctionNames );
  23. //////////////////////////////////////////////////////////////////////
  24. //
  25. // ControlClusterService()
  26. //
  27. // Finds the cluster name using the following procedure:
  28. // 1. Opens a handle to the local cluster (using NULL cluster name).
  29. // 1. Enumerates the resources in the cluster.
  30. // 2. Checks each resource to see if it is the core
  31. // Network Name resource.
  32. // 5. Finds the cluster name by retrieving the private properties
  33. // of the core Network Name resource.
  34. // 6. Online/Offline the service
  35. //
  36. // Arguments: ServiceName, start/stop flag
  37. //
  38. // Return value: Error code
  39. //
  40. //////////////////////////////////////////////////////////////////////
  41. DWORD
  42. ControlClusterService(LPCTSTR pszComputer, LPCTSTR pszResourceType, LPCTSTR pszServiceDesc, BOOL fStart)
  43. {
  44. HCLUSTER hCluster = NULL; // cluster handle
  45. HCLUSENUM hClusEnum = NULL; // enumeration handle
  46. HRESOURCE hRes = NULL; // resource handle
  47. DWORD dwError = ERROR_SUCCESS; // captures return values
  48. DWORD dwIndex = 0; // enumeration index; incremented to loop through all resources
  49. DWORD dwResFlags = 0; // describes the flags set for a resource
  50. DWORD dwEnumType = CLUSTER_ENUM_RESOURCE; // bitmask describing the cluster object(s) to enumerate
  51. DWORD cchResNameSize = 0; // actual size (count of characters) of lpszResName
  52. DWORD cchResNameAlloc = MAX_NAME_SIZE; // allocated size of lpszResName; MAX_NAME_SIZE = 256 (defined in clushead.h)
  53. LPWSTR lpszResName = (LPWSTR)LocalAlloc(LPTR, MAX_NAME_SIZE); // enumerated resource name
  54. LPWSTR lpszResType = (LPWSTR)LocalAlloc(LPTR, MAX_NAME_SIZE); // the resource type of the current resource name
  55. BOOL bDoLoop = TRUE; // loop exit condition
  56. int iResult = 0; // for return values
  57. if ( !g_ClusDLL.LoadFunctionPointers() )
  58. return dwError;
  59. //
  60. // Open a cluster handle.
  61. // The NULL cluster name opens a handle to the local cluster.
  62. //
  63. hCluster = ((OPENCLUSTER) g_ClusDLL[CLUS_OPEN_CLUSTER])( pszComputer );
  64. if (hCluster == NULL)
  65. {
  66. dwError = GetLastError();
  67. Trace1("OpenCluster failed %d!", dwError );
  68. goto ExitFunc;
  69. }
  70. //
  71. // Open an enumeration handle
  72. //
  73. hClusEnum = ((CLUSTEROPENENUM) g_ClusDLL[CLUS_CLUSTER_OPEN_ENUM])( hCluster, dwEnumType );
  74. if (hClusEnum == NULL)
  75. {
  76. dwError = GetLastError();
  77. Trace1( "ClusterOpenEnum failed %d", dwError );
  78. goto ExitFunc;
  79. }
  80. //
  81. // Enumeration loop
  82. //
  83. while( bDoLoop == TRUE )
  84. {
  85. //
  86. // Reset the name size for each iteration
  87. //
  88. cchResNameSize = cchResNameAlloc;
  89. //
  90. // Enumerate resource #<dwIndex>
  91. //
  92. dwError = ((CLUSTERENUM) g_ClusDLL[CLUS_CLUSTER_ENUM])( hClusEnum,
  93. dwIndex,
  94. &dwEnumType,
  95. lpszResName,
  96. &cchResNameSize );
  97. //
  98. // If the lpszResName buffer was too small, reallocate
  99. // according to the size returned by cchResNameSize
  100. //
  101. if ( dwError == ERROR_MORE_DATA )
  102. {
  103. LocalFree( lpszResName );
  104. cchResNameAlloc = cchResNameSize;
  105. lpszResName = (LPWSTR) LocalAlloc( LPTR, cchResNameAlloc );
  106. dwError = ((CLUSTERENUM) g_ClusDLL[CLUS_CLUSTER_ENUM])( hClusEnum,
  107. dwIndex,
  108. &dwEnumType,
  109. lpszResName,
  110. &cchResNameSize );
  111. }
  112. //
  113. // Exit loop on any non-success.
  114. // Includes ERROR_NO_MORE_ITEMS (no more objects to enumerate)
  115. //
  116. if ( dwError != ERROR_SUCCESS )
  117. break;
  118. //
  119. // Open resource handle
  120. //
  121. hRes = ((OPENCLUSTERRESOURCE) g_ClusDLL[CLUS_OPEN_CLUSTER_RESOURCE])( hCluster, lpszResName );
  122. if (hRes == NULL)
  123. {
  124. dwError = GetLastError();
  125. Trace1 ( "OpenClusterResource failed %d", dwError);
  126. goto ExitFunc;
  127. }
  128. //
  129. // Get the resource type.
  130. //
  131. dwError = ((CLUSTERRESOURCECONTROL) g_ClusDLL[CLUS_CLUSTER_RESOURCE_CONTROL])( hRes,
  132. NULL,
  133. CLUSCTL_RESOURCE_GET_RESOURCE_TYPE,
  134. NULL,
  135. 0,
  136. lpszResType,
  137. cchResNameAlloc,
  138. &cchResNameSize);
  139. //
  140. // Reallocation routine if lpszResType is too small
  141. //
  142. if ( dwError == ERROR_MORE_DATA )
  143. {
  144. LocalFree( lpszResType );
  145. cchResNameAlloc = cchResNameSize;
  146. lpszResType = (LPWSTR) LocalAlloc( LPTR, cchResNameAlloc );
  147. dwError = ((CLUSTERRESOURCECONTROL) g_ClusDLL[CLUS_CLUSTER_RESOURCE_CONTROL])( hRes,
  148. NULL,
  149. CLUSCTL_RESOURCE_GET_RESOURCE_TYPE,
  150. NULL,
  151. 0,
  152. lpszResType,
  153. cchResNameAlloc,
  154. &cchResNameSize);
  155. }
  156. if ( dwError != ERROR_SUCCESS )
  157. break;
  158. if ( lstrcmpi( lpszResType, pszResourceType ) == 0 )
  159. {
  160. //
  161. // do the online/offline stuff here
  162. //
  163. if (fStart)
  164. {
  165. dwError = StartResource(pszComputer, hRes, pszServiceDesc);
  166. }
  167. else
  168. {
  169. dwError = StopResource(pszComputer, hRes, pszServiceDesc);
  170. }
  171. bDoLoop = FALSE;
  172. }
  173. ((CLOSECLUSTERRESOURCE) g_ClusDLL[CLUS_CLOSE_CLUSTER_RESOURCE])( hRes );
  174. dwIndex++; // increment the enumeration index
  175. } // end Enumeration Loop
  176. ExitFunc:
  177. if ( hClusEnum != NULL )
  178. ((CLUSTERCLOSEENUM) g_ClusDLL[CLUS_CLUSTER_CLOSE_ENUM])( hClusEnum );
  179. if ( hCluster != NULL )
  180. ((CLOSECLUSTER) g_ClusDLL[CLUS_CLOSE_CLUSTER])( hCluster );
  181. LocalFree( lpszResName );
  182. LocalFree( lpszResType );
  183. return dwError;
  184. }
  185. //////////////////////////////////////////////////////////////////////
  186. //
  187. // FIsComputerInRunningCluster()
  188. //
  189. // Determines if the given machine is in a running cluster
  190. //
  191. // Arguments: Computer Name
  192. //
  193. // Return value: Error code
  194. //
  195. //////////////////////////////////////////////////////////////////////
  196. BOOL
  197. FIsComputerInRunningCluster(LPCTSTR pszComputer)
  198. {
  199. DWORD dwClusterState = 0;
  200. DWORD dwError = ERROR_SUCCESS;
  201. BOOL fInRunningCluster = FALSE;
  202. if ( !g_ClusDLL.LoadFunctionPointers() )
  203. return dwError;
  204. dwError = ((GETNODECLUSTERSTATE) g_ClusDLL[CLUS_GET_NODE_CLUSTER_STATE])( pszComputer, &dwClusterState );
  205. if (dwError == ERROR_SUCCESS)
  206. {
  207. if (dwClusterState == ClusterStateRunning)
  208. fInRunningCluster = TRUE;
  209. }
  210. return fInRunningCluster;
  211. }
  212. DWORD
  213. StartResource(LPCTSTR pszComputer, HRESOURCE hResource, LPCTSTR pszServiceDesc)
  214. {
  215. DWORD dwError = ERROR_SUCCESS;
  216. if ( !g_ClusDLL.LoadFunctionPointers() )
  217. return dwError;
  218. dwError = ((ONLINECLUSTERRESOURCE) g_ClusDLL[CLUS_ONLINE_CLUSTER_RESOURCE])( hResource );
  219. if ( dwError == ERROR_IO_PENDING )
  220. {
  221. //
  222. // Put up the dialog with the funky spinning thing to
  223. // let the user know that something is happening
  224. //
  225. CServiceCtrlDlg dlgServiceCtrl(hResource, pszComputer, pszServiceDesc, TRUE);
  226. dlgServiceCtrl.DoModal();
  227. dwError = dlgServiceCtrl.m_dwErr;
  228. }
  229. return dwError;
  230. }
  231. DWORD
  232. StopResource(LPCTSTR pszComputer, HRESOURCE hResource, LPCTSTR pszServiceDesc)
  233. {
  234. DWORD dwError = ERROR_SUCCESS;
  235. if ( !g_ClusDLL.LoadFunctionPointers() )
  236. return dwError;
  237. dwError = ((OFFLINECLUSTERRESOURCE) g_ClusDLL[CLUS_OFFLINE_CLUSTER_RESOURCE])( hResource );
  238. if ( dwError == ERROR_IO_PENDING )
  239. {
  240. //
  241. // Put up the dialog with the funky spinning thing to
  242. // let the user know that something is happening
  243. //
  244. CServiceCtrlDlg dlgServiceCtrl(hResource, pszComputer, pszServiceDesc, FALSE);
  245. dlgServiceCtrl.DoModal();
  246. dwError = dlgServiceCtrl.m_dwErr;
  247. }
  248. return dwError;
  249. }
  250. //////////////////////////////////////////////////////////////////////
  251. //
  252. // GetClusterResourceIp()
  253. //
  254. // Finds the cluster name using the following procedure:
  255. // 1. Opens a handle to the local cluster (using NULL cluster name).
  256. // 1. Enumerates the resources in the cluster.
  257. // 2. Checks each resource to see if it is the core
  258. // Network Name resource.
  259. // 5. Finds the cluster name by retrieving the private properties
  260. // of the core Network Name resource.
  261. //
  262. // Arguments: ServiceName
  263. //
  264. // Return value: Error code
  265. //
  266. //////////////////////////////////////////////////////////////////////
  267. DWORD
  268. GetClusterResourceIp(LPCTSTR pszComputer, LPCTSTR pszResourceType, CString & strAddress)
  269. {
  270. HCLUSTER hCluster = NULL; // cluster handle
  271. HCLUSENUM hClusEnum = NULL; // enumeration handle
  272. HRESOURCE hRes = NULL; // resource handle
  273. HRESOURCE hResIp = NULL; // resource handle
  274. DWORD dwError = ERROR_SUCCESS; // captures return values
  275. DWORD dwIndex = 0; // enumeration index; incremented to loop through all resources
  276. DWORD dwResFlags = 0; // describes the flags set for a resource
  277. DWORD dwEnumType = CLUSTER_ENUM_RESOURCE; // bitmask describing the cluster object(s) to enumerate
  278. DWORD cchResNameSize = 0; // actual size (count of characters) of lpszResName
  279. DWORD cchResNameAlloc = MAX_NAME_SIZE; // allocated size of lpszResName; MAX_NAME_SIZE = 256 (defined in clushead.h)
  280. LPWSTR lpszResName = (LPWSTR)LocalAlloc(LPTR, MAX_NAME_SIZE); // enumerated resource name
  281. LPWSTR lpszResType = (LPWSTR)LocalAlloc(LPTR, MAX_NAME_SIZE); // the resource type of the current resource name
  282. BOOL bDoLoop = TRUE; // loop exit condition
  283. HKEY hkeyProvider = NULL;
  284. HRESENUM hResEnum = NULL;
  285. int ienum;
  286. LPWSTR pwszName = NULL;
  287. DWORD cchName;
  288. DWORD cchmacName;
  289. DWORD dwRetType;
  290. LPWSTR lpszResIpType = NULL;
  291. strAddress.Empty();
  292. if ( !g_ClusDLL.LoadFunctionPointers() )
  293. return dwError;
  294. //
  295. // Open a cluster handle.
  296. // The NULL cluster name opens a handle to the local cluster.
  297. //
  298. hCluster = ((OPENCLUSTER) g_ClusDLL[CLUS_OPEN_CLUSTER])( pszComputer );
  299. if (hCluster == NULL)
  300. {
  301. dwError = GetLastError();
  302. Trace1("OpenCluster failed %d!", dwError );
  303. goto ExitFunc;
  304. }
  305. //
  306. // Open an enumeration handle
  307. //
  308. hClusEnum = ((CLUSTEROPENENUM) g_ClusDLL[CLUS_CLUSTER_OPEN_ENUM])( hCluster, dwEnumType );
  309. if (hClusEnum == NULL)
  310. {
  311. dwError = GetLastError();
  312. Trace1( "ClusterOpenEnum failed %d", dwError );
  313. goto ExitFunc;
  314. }
  315. //
  316. // Enumeration loop
  317. //
  318. while( bDoLoop == TRUE )
  319. {
  320. //
  321. // Reset the name size for each iteration
  322. //
  323. cchResNameSize = cchResNameAlloc;
  324. //
  325. // Enumerate resource #<dwIndex>
  326. //
  327. dwError = ((CLUSTERENUM) g_ClusDLL[CLUS_CLUSTER_ENUM])( hClusEnum,
  328. dwIndex,
  329. &dwEnumType,
  330. lpszResName,
  331. &cchResNameSize );
  332. //
  333. // If the lpszResName buffer was too small, reallocate
  334. // according to the size returned by cchResNameSize
  335. //
  336. if ( dwError == ERROR_MORE_DATA )
  337. {
  338. LocalFree( lpszResName );
  339. cchResNameAlloc = cchResNameSize;
  340. lpszResName = (LPWSTR) LocalAlloc( LPTR, cchResNameAlloc );
  341. dwError = ((CLUSTERENUM) g_ClusDLL[CLUS_CLUSTER_ENUM])( hClusEnum,
  342. dwIndex,
  343. &dwEnumType,
  344. lpszResName,
  345. &cchResNameSize );
  346. }
  347. //
  348. // Exit loop on any non-success.
  349. // Includes ERROR_NO_MORE_ITEMS (no more objects to enumerate)
  350. //
  351. if ( dwError != ERROR_SUCCESS )
  352. break;
  353. //
  354. // Open resource handle
  355. //
  356. hRes = ((OPENCLUSTERRESOURCE) g_ClusDLL[CLUS_OPEN_CLUSTER_RESOURCE])( hCluster, lpszResName );
  357. if (hRes == NULL)
  358. {
  359. dwError = GetLastError();
  360. Trace1 ( "OpenClusterResource failed %d", dwError);
  361. goto ExitFunc;
  362. }
  363. dwError = GetResourceType(hRes, &lpszResType, cchResNameAlloc, &cchResNameSize);
  364. if ( dwError != ERROR_SUCCESS )
  365. break;
  366. if ( lstrcmpi( lpszResType, pszResourceType ) == 0 )
  367. {
  368. // found the right resource, enum dependencies and find the IP
  369. hResEnum = ((CLUSTERRESOURCEOPENENUM) g_ClusDLL[CLUS_CLUSTER_RESOURCE_OPEN_ENUM])( hRes,
  370. CLUSTER_RESOURCE_ENUM_DEPENDS);
  371. if (hResEnum)
  372. {
  373. // Allocate a name buffer.
  374. cchmacName = 128;
  375. pwszName = new WCHAR[cchmacName];
  376. // Loop through the enumeration and add each dependent resource to the list.
  377. for (ienum = 0 ; ; ienum++)
  378. {
  379. // Get the next item in the enumeration.
  380. cchName = cchmacName;
  381. dwError = ((CLUSTERRESOURCEENUM) g_ClusDLL[CLUS_CLUSTER_RESOURCE_ENUM])( hResEnum,
  382. ienum,
  383. &dwRetType,
  384. pwszName,
  385. &cchName);
  386. if (dwError == ERROR_MORE_DATA)
  387. {
  388. delete [] pwszName;
  389. cchmacName = ++cchName;
  390. pwszName = new WCHAR[cchmacName];
  391. dwError = ((CLUSTERRESOURCEENUM) g_ClusDLL[CLUS_CLUSTER_RESOURCE_ENUM])( hResEnum,
  392. ienum,
  393. &dwRetType,
  394. pwszName,
  395. &cchName);
  396. } // if: name buffer was too small
  397. if (dwError == ERROR_NO_MORE_ITEMS)
  398. {
  399. break;
  400. }
  401. else
  402. if (dwError != ERROR_SUCCESS)
  403. {
  404. break;
  405. }
  406. ASSERT(dwRetType == CLUSTER_RESOURCE_ENUM_DEPENDS);
  407. //
  408. // Open resource handle
  409. //
  410. hResIp = ((OPENCLUSTERRESOURCE) g_ClusDLL[CLUS_OPEN_CLUSTER_RESOURCE])( hCluster, pwszName );
  411. if (hResIp == NULL)
  412. {
  413. dwError = GetLastError();
  414. Trace1 ( "OpenClusterResource failed %d", dwError);
  415. break;
  416. }
  417. lpszResIpType = (LPWSTR)LocalAlloc(LPTR, MAX_NAME_SIZE);
  418. dwError = GetResourceType(hResIp, &lpszResIpType, MAX_NAME_SIZE, NULL);
  419. if ( dwError != ERROR_SUCCESS )
  420. break;
  421. if ( lstrcmpiW( lpszResIpType, _T("IP Address") ) == 0 )
  422. {
  423. GetResourceIpAddress(hResIp, strAddress);
  424. bDoLoop = FALSE;
  425. } // if: IP Address resource found
  426. ((CLOSECLUSTERRESOURCE) g_ClusDLL[CLUS_CLOSE_CLUSTER_RESOURCE])( hResIp );
  427. LocalFree( lpszResIpType );
  428. hResIp = NULL;
  429. lpszResIpType = NULL;
  430. if (!strAddress.IsEmpty())
  431. break; // found it
  432. } // for: each dependency
  433. delete [] pwszName;
  434. dwError = ((CLUSTERRESOURCECLOSEENUM) g_ClusDLL[CLUS_CLUSTER_RESOURCE_CLOSE_ENUM])( hResEnum );
  435. }
  436. }
  437. ((CLOSECLUSTERRESOURCE) g_ClusDLL[CLUS_CLOSE_CLUSTER_RESOURCE])( hRes );
  438. dwIndex++; // increment the enumeration index
  439. } // end Enumeration Loop
  440. ExitFunc:
  441. if ( hClusEnum != NULL )
  442. ((CLUSTERCLOSEENUM) g_ClusDLL[CLUS_CLUSTER_CLOSE_ENUM])( hClusEnum );
  443. if ( hCluster != NULL )
  444. ((CLOSECLUSTER) g_ClusDLL[CLUS_CLOSE_CLUSTER])( hCluster );
  445. LocalFree( lpszResName );
  446. LocalFree( lpszResType );
  447. return dwError;
  448. }
  449. DWORD
  450. GetResourceType(HRESOURCE hRes, LPWSTR * ppszName, DWORD dwBufSizeIn, DWORD * pdwBufSizeOut)
  451. {
  452. DWORD dwError = ERROR_SUCCESS;
  453. DWORD cchResNameSize = dwBufSizeIn;
  454. DWORD cchResNameSizeNeeded = 0;
  455. //
  456. // Figure out how big a buffer we need.
  457. //
  458. dwError = ((CLUSTERRESOURCECONTROL) g_ClusDLL[CLUS_CLUSTER_RESOURCE_CONTROL])( hRes,
  459. NULL,
  460. CLUSCTL_RESOURCE_GET_RESOURCE_TYPE,
  461. NULL,
  462. 0,
  463. *ppszName,
  464. cchResNameSize,
  465. &cchResNameSizeNeeded);
  466. //
  467. // Reallocation routine if lpszResType is too small
  468. //
  469. if ( dwError == ERROR_MORE_DATA )
  470. {
  471. cchResNameSize = cchResNameSizeNeeded;
  472. LocalFree(*ppszName);
  473. *ppszName = (LPWSTR) LocalAlloc( LPTR, cchResNameSize );
  474. dwError = ((CLUSTERRESOURCECONTROL) g_ClusDLL[CLUS_CLUSTER_RESOURCE_CONTROL])( hRes,
  475. NULL,
  476. CLUSCTL_RESOURCE_GET_RESOURCE_TYPE,
  477. NULL,
  478. 0,
  479. *ppszName,
  480. cchResNameSize,
  481. &cchResNameSizeNeeded);
  482. }
  483. if (pdwBufSizeOut)
  484. *pdwBufSizeOut = cchResNameSizeNeeded;
  485. return dwError;
  486. }
  487. DWORD
  488. GetResourceIpAddress(HRESOURCE hRes, CString & strAddress)
  489. {
  490. DWORD dwError = ERROR_SUCCESS;
  491. DWORD cbProps;
  492. PVOID pvProps = NULL;
  493. LPWSTR pszIPAddress = NULL;
  494. // Loop to avoid goto's.
  495. do
  496. {
  497. //
  498. // Get the size of the private properties from the resource.
  499. //
  500. dwError = ((CLUSTERRESOURCECONTROL) g_ClusDLL[CLUS_CLUSTER_RESOURCE_CONTROL])( hRes,
  501. NULL,
  502. CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES,
  503. NULL,
  504. 0,
  505. NULL,
  506. 0,
  507. &cbProps);
  508. if ( (dwError != ERROR_SUCCESS) ||
  509. (cbProps == 0) )
  510. {
  511. if ( dwError == ERROR_SUCCESS )
  512. {
  513. dwError = ERROR_INVALID_DATA;
  514. } // if: no properties available
  515. break;
  516. } // if: error getting size of properties or no properties available
  517. //
  518. // Allocate the property buffer.
  519. //
  520. pvProps = LocalAlloc( LMEM_FIXED, cbProps );
  521. if ( pvProps == NULL )
  522. {
  523. dwError = GetLastError();
  524. break;
  525. } // if: error allocating memory
  526. //
  527. // Get the private properties from the resource.
  528. //
  529. dwError = ((CLUSTERRESOURCECONTROL) g_ClusDLL[CLUS_CLUSTER_RESOURCE_CONTROL])( hRes,
  530. NULL,
  531. CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES,
  532. NULL,
  533. 0,
  534. pvProps,
  535. cbProps,
  536. &cbProps);
  537. if ( dwError != ERROR_SUCCESS )
  538. {
  539. break;
  540. } // if: error getting private properties
  541. //
  542. // Find the Address property.
  543. //
  544. dwError = FindSzProp(pvProps, cbProps, L"Address", &pszIPAddress);
  545. if ( dwError != ERROR_SUCCESS )
  546. {
  547. break;
  548. } // if: error finding the Address property
  549. } while ( 0 );
  550. //
  551. // Cleanup.
  552. //
  553. strAddress = pszIPAddress;
  554. LocalFree( pvProps );
  555. return dwError;
  556. }
  557. DWORD FindSzProp
  558. (
  559. LPVOID pvProps,
  560. DWORD cbProps,
  561. LPCWSTR pszTarget,
  562. LPWSTR * ppszOut
  563. )
  564. {
  565. BOOL DoLoop = TRUE; // loop exit condition
  566. BOOL Found = FALSE; // tests whether property has been found
  567. DWORD dwError = ERROR_SUCCESS; // for return values
  568. DWORD cbOffset = 0; // offset to next entry in the value list
  569. DWORD cbPosition = 0; // tracks the advance through the value list buffer
  570. CLUSPROP_BUFFER_HELPER ListEntry; // to parse the list
  571. //
  572. // Set the pb member to the start of the list
  573. //
  574. ListEntry.pb = (BYTE *) pvProps;
  575. //
  576. // Main loop:
  577. // 1. Check syntax of current list entry
  578. // 2. If it is a property name, check that we have the right property.
  579. // 3. If it is a binary value, check that we found the right name.
  580. // 4. Advance the position counter and test vs. size of list.
  581. //
  582. do
  583. {
  584. switch( *ListEntry.pdw ) // check the syntax of the entry
  585. {
  586. case CLUSPROP_SYNTAX_NAME:
  587. //
  588. // If this is the Security property, flag Found as TRUE.
  589. // The next pass through the loop should yield the Security value.
  590. //
  591. if ( lstrcmpi( ListEntry.pName->sz, pszTarget ) == 0 )
  592. {
  593. Trace0( "Found name.\n" );
  594. Found = TRUE;
  595. }
  596. else
  597. {
  598. Found = FALSE;
  599. }
  600. //
  601. // Calculate offset to next entry. Note the use of ALIGN_CLUSPROP
  602. //
  603. cbOffset = sizeof( *ListEntry.pName ) + ALIGN_CLUSPROP( ListEntry.pName->cbLength );
  604. break;
  605. case CLUSPROP_SYNTAX_LIST_VALUE_DWORD:
  606. cbOffset = sizeof( *ListEntry.pDwordValue ); // ALIGN_CLUSPROP not used; value is already DWORD-aligned
  607. break;
  608. case CLUSPROP_SYNTAX_LIST_VALUE_SZ:
  609. if ( Found == TRUE)
  610. {
  611. if (ppszOut)
  612. {
  613. *ppszOut = ListEntry.pStringValue->sz;
  614. }
  615. DoLoop = FALSE;
  616. }
  617. else
  618. {
  619. Trace0( "Found something else.\n" );
  620. cbOffset = sizeof( *ListEntry.pStringValue ) + ALIGN_CLUSPROP( ListEntry.pStringValue->cbLength );
  621. }
  622. break;
  623. case CLUSPROP_SYNTAX_LIST_VALUE_BINARY: // this is what we're looking for
  624. cbOffset = sizeof( *ListEntry.pBinaryValue ) + ALIGN_CLUSPROP( ListEntry.pBinaryValue->cbLength );
  625. break;
  626. case CLUSPROP_SYNTAX_ENDMARK:
  627. default:
  628. cbOffset = sizeof( DWORD );
  629. break;
  630. }
  631. //
  632. // Verify that the offset to the next entry is
  633. // within the value list buffer, then advance
  634. // the CLUSPROP_BUFFER_HELPER pointer.
  635. //
  636. cbPosition += cbOffset;
  637. if ( cbPosition > cbProps )
  638. break;
  639. ListEntry.pb += cbOffset;
  640. } while ( DoLoop );
  641. if (Found)
  642. return 0;
  643. else
  644. return 1;
  645. }
  646. DWORD GetClusterInfo(
  647. LPCTSTR pszClusIp,
  648. CString &strClusName,
  649. DWORD * pdwClusIp)
  650. {
  651. DWORD dwErr = ERROR_SUCCESS;
  652. HCLUSTER hCluster;
  653. CIpAddress ipClus(pszClusIp);
  654. strClusName.Empty();
  655. *pdwClusIp = (LONG)ipClus;
  656. hCluster = ((OPENCLUSTER) g_ClusDLL[CLUS_OPEN_CLUSTER])(pszClusIp);
  657. if (hCluster == NULL)
  658. {
  659. dwErr = GetLastError();
  660. }
  661. else
  662. {
  663. DWORD dwClusNameLen;
  664. dwClusNameLen = 0;
  665. dwErr = ((GETCLUSTERINFORMATION) g_ClusDLL[CLUS_GET_CLUSTER_INFORMATION])(
  666. hCluster,
  667. NULL,
  668. &dwClusNameLen,
  669. NULL);
  670. if (dwClusNameLen > 0)
  671. {
  672. LPTSTR pClusName;
  673. dwClusNameLen++;
  674. pClusName = strClusName.GetBuffer((dwClusNameLen)*sizeof(WCHAR));
  675. dwErr = ((GETCLUSTERINFORMATION) g_ClusDLL[CLUS_GET_CLUSTER_INFORMATION])(
  676. hCluster,
  677. pClusName,
  678. &dwClusNameLen,
  679. NULL);
  680. strClusName.ReleaseBuffer();
  681. }
  682. ((CLOSECLUSTER) g_ClusDLL[CLUS_CLOSE_CLUSTER])(hCluster);
  683. }
  684. return dwErr;
  685. }