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.

411 lines
13 KiB

  1. /*++
  2. Copyright (C) 2001 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. NCclusfunc.cxx
  6. Abstract:
  7. This module provides several utility functions for cluster related operations.
  8. Author:
  9. Felix Maxa (AMaxa) 16 May 2001
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #include <clusapi.h>
  14. #include "ncnamecache.hxx"
  15. #include "ncclusapi.hxx"
  16. using namespace NCoreLibrary;
  17. LPCWSTR g_pszIPAddressResource = L"IP Address";
  18. LPCWSTR g_pszIPAddressProperty = L"Address";
  19. /*++
  20. Name:
  21. ClusResControl
  22. Description:
  23. Helper function. Encapsulates a call to ClusterResourceControl. The function
  24. allocates a buffer. Upon success, the caller nedds to free the buffer using
  25. delete [].
  26. Arguments:
  27. ClusterAPI - reference to object exposing cluster APIs
  28. hResource - handle to cluster resource
  29. ControlCode - control code for ClusterResourceControl
  30. ppBuffer - pointer to address where to store byte array
  31. pcBytesReturned - number of bytes returned by ClusterResourceControl (not
  32. necessarily the number of byes allocated for *ppBuffer)
  33. Return Value:
  34. S_OK - success. ppBuffer can be used and must be freed using delete []
  35. any other HRESULT - failure
  36. --*/
  37. HRESULT
  38. ClusResControl(
  39. IN TClusterAPI& ClusterAPI,
  40. IN HRESOURCE hResource,
  41. IN DWORD ControlCode,
  42. OUT BYTE **ppBuffer,
  43. IN DWORD *pcBytesReturned OPTIONAL
  44. )
  45. {
  46. TStatusH hRetval;
  47. hRetval DBGCHK = ppBuffer ? S_OK : E_INVALIDARG;
  48. if (SUCCEEDED(hRetval))
  49. {
  50. DWORD Error;
  51. DWORD cbBuffer = kBufferAllocHint;
  52. DWORD cbNeeded = 0;
  53. *ppBuffer = new BYTE[cbBuffer];
  54. Error = *ppBuffer ? ERROR_SUCCESS : ERROR_NOT_ENOUGH_MEMORY;
  55. if (Error == ERROR_SUCCESS)
  56. {
  57. Error = ClusterAPI.pfnClusterResourceControl(hResource,
  58. NULL,
  59. ControlCode,
  60. NULL,
  61. 0,
  62. *ppBuffer,
  63. cbBuffer,
  64. &cbNeeded);
  65. if (Error == ERROR_MORE_DATA)
  66. {
  67. cbBuffer = cbNeeded;
  68. delete [] *ppBuffer;
  69. *ppBuffer = new BYTE[cbBuffer];
  70. Error = *ppBuffer ? ERROR_SUCCESS : ERROR_NOT_ENOUGH_MEMORY;
  71. if (Error == ERROR_SUCCESS)
  72. {
  73. Error = ClusterAPI.pfnClusterResourceControl(hResource,
  74. NULL,
  75. ControlCode,
  76. NULL,
  77. 0,
  78. *ppBuffer,
  79. cbBuffer,
  80. &cbNeeded);
  81. }
  82. }
  83. if (Error != ERROR_SUCCESS)
  84. {
  85. delete [] *ppBuffer;
  86. *ppBuffer = NULL;
  87. cbNeeded = 0;
  88. }
  89. if (pcBytesReturned)
  90. {
  91. *pcBytesReturned = cbNeeded;
  92. }
  93. }
  94. hRetval DBGCHK = HRESULT_FROM_WIN32(Error);
  95. }
  96. return hRetval;
  97. }
  98. /*++
  99. Name:
  100. GetResourceIPAddress
  101. Description:
  102. Helper function used in GetClusterIPAddresses. Checks if a cluster resource is an IP address
  103. reosurce, in which case it retrieve the IP associated.
  104. Arguments:
  105. ClusterAPI - reference to object exposing cluster APIs
  106. hCluster - handle retrieved via OpenCluster
  107. pszResource - resource name
  108. ppszAddress - pointer to where to receive string representing IP address
  109. Return Value:
  110. S_OK - success. ppszAddress may still be NULL on success. success means
  111. either the reosurce is not IP resource or it is IP resource and
  112. the ppszAddress is then not NULL. ppszAddress must be freed by caller
  113. using LocalFree.
  114. any other HRESULT - failure
  115. --*/
  116. HRESULT
  117. GetResourceIPAddress(
  118. IN TClusterAPI& ClusterAPI,
  119. IN HCLUSTER hCluster,
  120. IN LPCWSTR pszResource,
  121. OUT LPWSTR *ppszAddress
  122. )
  123. {
  124. HRESOURCE hResource;
  125. TStatusH hRetval;
  126. hRetval DBGCHK = hCluster && pszResource && ppszAddress ? S_OK : E_INVALIDARG;
  127. if (SUCCEEDED(hRetval))
  128. {
  129. *ppszAddress = NULL;
  130. hResource = ClusterAPI.pfnOpenClusterResource(hCluster, pszResource);
  131. hRetval DBGCHK = hResource ? S_OK : GetLastErrorAsHResult();
  132. }
  133. if (SUCCEEDED(hRetval))
  134. {
  135. BYTE *pResType = NULL;
  136. hRetval DBGCHK = ClusResControl(ClusterAPI,
  137. hResource,
  138. CLUSCTL_RESOURCE_GET_RESOURCE_TYPE,
  139. &pResType,
  140. NULL);
  141. if (SUCCEEDED(hRetval))
  142. {
  143. //
  144. // Check resource type. We are interested only in IP Address resources.
  145. //
  146. if (!_wcsicmp(reinterpret_cast<LPWSTR>(pResType), g_pszIPAddressResource))
  147. {
  148. LPWSTR pszIPAddress = NULL;
  149. BYTE *pResProp = NULL;
  150. DWORD cbResProp = 0;
  151. //
  152. // Get all the private properties of the IP Address resource.
  153. //
  154. hRetval DBGCHK = ClusResControl(ClusterAPI,
  155. hResource,
  156. CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES,
  157. &pResProp,
  158. &cbResProp);
  159. if (SUCCEEDED(hRetval))
  160. {
  161. //
  162. // Scan for the property indicating the IP address of the resource
  163. //
  164. DWORD Error = ClusterAPI.pfnResUtilFindSzProperty(pResProp,
  165. cbResProp,
  166. g_pszIPAddressProperty,
  167. ppszAddress);
  168. hRetval DBGCHK = HRESULT_FROM_WIN32(Error);
  169. }
  170. delete [] pResProp;
  171. }
  172. }
  173. delete [] pResType;
  174. ClusterAPI.pfnCloseClusterResource(hResource);
  175. }
  176. return hRetval;
  177. }
  178. /*++
  179. Name:
  180. GetClusterIPAddresses
  181. Description:
  182. Fill in a list with the IP addresses used by the cluster service running on the local machine.
  183. The function returns S_OK if the cluster service is not running. In that case the list will be
  184. empty.
  185. Arguments:
  186. pClusterIPsList - pointer to list of TStringNodes.
  187. Return Value:
  188. S_OK - success. pClusterIPsList will have 0 or more elements represeting each
  189. an IP address used by cluster resources
  190. any other HRESULT - failure
  191. --*/
  192. HRESULT
  193. GetClusterIPAddresses(
  194. IN TList<TStringNode> *pClusterIPsList
  195. )
  196. {
  197. TStatusH hRetval;
  198. HCLUSTER hCluster;
  199. TClusterAPI ClusterAPI;
  200. hRetval DBGCHK = pClusterIPsList ? ClusterAPI.Valid() : E_INVALIDARG;
  201. if (SUCCEEDED(hRetval))
  202. {
  203. hCluster = ClusterAPI.pfnOpenCluster(NULL);
  204. //
  205. // If we cannot open the cluster then we return success to our caller.
  206. //
  207. if (hCluster)
  208. {
  209. HCLUSENUM hClusEnum;
  210. hClusEnum = ClusterAPI.pfnClusterOpenEnum(hCluster, CLUSTER_ENUM_RESOURCE);
  211. hRetval DBGCHK = hClusEnum ? S_OK : GetLastErrorAsHResult();
  212. if (SUCCEEDED(hRetval))
  213. {
  214. BOOL bDone = FALSE;
  215. DWORD Index = 0;
  216. LPWSTR pszName = NULL;
  217. DWORD cchName = 0;
  218. DWORD cchNeeded;
  219. DWORD ResourceType;
  220. cchName = cchNeeded = kBufferAllocHint;
  221. //
  222. // We need to initialize pszName to a valid non NULL memory block, otherwise
  223. // CluserEnum AV's.
  224. //
  225. pszName = new WCHAR[cchName];
  226. hRetval DBGCHK = pszName ? S_OK : E_OUTOFMEMORY;
  227. for (Index = 0; !bDone && SUCCEEDED(hRetval);)
  228. {
  229. DWORD Error;
  230. cchNeeded = cchName;
  231. Error = ClusterAPI.pfnClusterEnum(hClusEnum,
  232. Index,
  233. &ResourceType,
  234. pszName,
  235. &cchNeeded);
  236. switch (Error)
  237. {
  238. case ERROR_SUCCESS:
  239. {
  240. LPWSTR pszAddress = NULL;
  241. hRetval DBGCHK = GetResourceIPAddress(ClusterAPI, hCluster, pszName, &pszAddress);
  242. if (pszAddress)
  243. {
  244. TStringNode *pNode = new TStringNode(pszAddress);
  245. hRetval DBGCHK = pNode ? S_OK : E_OUTOFMEMORY;
  246. if (SUCCEEDED(hRetval))
  247. {
  248. hRetval DBGCHK = pNode->Valid();
  249. }
  250. if (SUCCEEDED(hRetval))
  251. {
  252. hRetval DBGCHK = pClusterIPsList->AddAtHead(pNode);
  253. if (SUCCEEDED(hRetval))
  254. {
  255. //
  256. // List took ownership of pNode.
  257. //
  258. pNode = NULL;
  259. }
  260. }
  261. delete pNode;
  262. LocalFree(pszAddress);
  263. }
  264. Index++;
  265. break;
  266. }
  267. case ERROR_MORE_DATA:
  268. {
  269. delete [] pszName;
  270. //
  271. // cchNeeded returns the number of characters needed, excluding the terminating NULL
  272. //
  273. cchName = cchNeeded + 1;
  274. pszName = new WCHAR[cchName];
  275. if (!pszName)
  276. {
  277. hRetval DBGCHK = E_OUTOFMEMORY;
  278. }
  279. break;
  280. }
  281. case ERROR_NO_MORE_ITEMS:
  282. {
  283. delete [] pszName;
  284. bDone = TRUE;
  285. break;
  286. }
  287. default:
  288. {
  289. delete [] pszName;
  290. hRetval DBGCHK = HRESULT_FROM_WIN32(Error);
  291. }
  292. }
  293. }
  294. ClusterAPI.pfnClusterCloseEnum(hClusEnum);
  295. }
  296. ClusterAPI.pfnCloseCluster(hCluster);
  297. }
  298. else
  299. {
  300. DWORD Error = GetLastError();
  301. DBGMSG(DBG_WARN, ("\n\nGetClusterIPAddresses OpenCluster failed with Win32 error %u !!!\n\n", Error));
  302. }
  303. }
  304. return hRetval;
  305. }