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.

2046 lines
65 KiB

  1. #include "stdafx.h"
  2. #include "wolfpack.h"
  3. #ifndef _CHICAGO_
  4. #include <windows.h>
  5. #include <stdio.h>
  6. #include <clusapi.h>
  7. #include <resapi.h>
  8. #include <helper.h>
  9. #define INITIAL_RESOURCE_NAME_SIZE 256 // In characters not in bytes
  10. #define IIS_RESOURCE_TYPE_NAME L"IIS Server Instance"
  11. #define SMTP_RESOURCE_TYPE_NAME L"SMTP Server Instance"
  12. #define NNTP_RESOURCE_TYPE_NAME L"NNTP Server Instance"
  13. #define MAX_OFFLINE_RETRIES 5 // Number of times to try and take a resources offline before giving up
  14. #define DELAY_BETWEEN_CALLS_TO_OFFLINE 1000*2 // in milliseconds
  15. CONST LPCWSTR scClusterPath = _T("System\\CurrentControlSet\\Services\\ClusSvc");
  16. CONST LPCWSTR scClusterPath2 = _T("System\\CurrentControlSet\\Services\\ClusSvc\\Parameters");
  17. CStringList gcstrListOfClusResources;
  18. int g_ClusterSVCExist = -1; // -1 = not checked, 1 = exist, 0 = not exist
  19. typedef DWORD
  20. (WINAPI *PFN_RESUTILFINDSZPROPERTY)(
  21. IN LPVOID lpTheProperty,
  22. IN OUT LPDWORD nInBufferSize,
  23. IN LPCWSTR lpszResourceTypeName,
  24. OUT LPVOID lpOutBuffer);
  25. typedef DWORD
  26. (WINAPI *PFN_RESUTILFINDDWORDPROPERTY)(
  27. IN LPVOID lpTheProperty,
  28. IN OUT LPDWORD nInBufferSize,
  29. IN LPCWSTR lpszResourceTypeName,
  30. OUT LPDWORD pdwPropertyValue);
  31. typedef DWORD
  32. (WINAPI *PFN_CLUSTERRESOURCECONTROL)(
  33. IN HRESOURCE hResource,
  34. IN HNODE hNode,
  35. IN DWORD dwControlCode,
  36. IN LPVOID lpInBuffer,
  37. IN OUT DWORD nInBufferSize,
  38. OUT LPVOID lpOutBuffer,
  39. IN OUT DWORD nOutBufferSize,
  40. OUT LPDWORD lpBytesReturned
  41. );
  42. typedef HCLUSTER
  43. (WINAPI *PFN_OPENCLUSTER)(
  44. IN LPCWSTR lpszClusterName
  45. );
  46. typedef BOOL
  47. (WINAPI *PFN_CLOSECLUSTER)(
  48. IN HCLUSTER hCluster
  49. );
  50. typedef DWORD
  51. (WINAPI *PFN_CREATECLUSTERRESOURCETYPE)(
  52. IN HCLUSTER hCluster,
  53. IN LPCWSTR lpszResourceTypeName,
  54. IN LPCWSTR lpszDisplayName,
  55. IN LPCWSTR lpszResourceTypeDll,
  56. IN DWORD dwLooksAlivePollInterval,
  57. IN DWORD dwIsAlivePollInterval
  58. );
  59. typedef DWORD
  60. (WINAPI *PFN_DELETECLUSTERRESOURCETYPE)(
  61. IN HCLUSTER hCluster,
  62. IN LPCWSTR lpszResourceTypeName
  63. );
  64. typedef HCLUSENUM
  65. (WINAPI
  66. *PFN_ClusterOpenEnum)(
  67. IN HCLUSTER hCluster,
  68. IN DWORD dwType
  69. );
  70. typedef DWORD
  71. (WINAPI
  72. *PFN_ClusterEnum)(
  73. IN HCLUSENUM hEnum,
  74. IN DWORD dwIndex,
  75. OUT LPDWORD lpdwType,
  76. OUT LPWSTR lpszName,
  77. IN OUT LPDWORD lpcbName
  78. );
  79. typedef DWORD
  80. (WINAPI
  81. *PFN_ClusterCloseEnum)(
  82. IN HCLUSENUM hEnum
  83. );
  84. typedef HRESOURCE
  85. (WINAPI
  86. *PFN_OpenClusterResource)(
  87. IN HCLUSTER hCluster,
  88. IN LPCWSTR lpszResourceName
  89. );
  90. typedef BOOL
  91. (WINAPI
  92. *PFN_CloseClusterResource)(
  93. IN HRESOURCE hResource
  94. );
  95. typedef DWORD
  96. (WINAPI
  97. *PFN_DeleteClusterResource)(
  98. IN HRESOURCE hResource
  99. );
  100. typedef DWORD
  101. (WINAPI
  102. *PFN_OfflineClusterResource)(
  103. IN HRESOURCE hResource
  104. );
  105. typedef HKEY
  106. (WINAPI
  107. *PFN_GetClusterResourceKey)(
  108. IN HRESOURCE hResource,
  109. IN REGSAM samDesired
  110. );
  111. typedef LONG
  112. (WINAPI
  113. *PFN_ClusterRegCloseKey)(
  114. IN HKEY hKey
  115. );
  116. typedef LONG
  117. (WINAPI
  118. *PFN_ClusterRegQueryValue)(
  119. IN HKEY hKey,
  120. IN LPCWSTR lpszValueName,
  121. OUT LPDWORD lpValueType,
  122. OUT LPBYTE lpData,
  123. IN OUT LPDWORD lpcbData
  124. );
  125. typedef CLUSTER_RESOURCE_STATE
  126. (WINAPI
  127. *PFN_GetClusterResourceState)(
  128. IN HRESOURCE hResource,
  129. OUT OPTIONAL LPWSTR lpszNodeName,
  130. IN OUT LPDWORD lpcbNodeName,
  131. OUT OPTIONAL LPWSTR lpszGroupName,
  132. IN OUT LPDWORD lpcbGroupName
  133. );
  134. typedef DWORD
  135. (WINAPI *PFN_DLLREGISTERCLUADMINEXTENSION)(
  136. IN HCLUSTER hCluster
  137. );
  138. typedef DWORD
  139. (WINAPI *PFN_DLLUNREGISTERCLUADMINEXTENSION)(
  140. IN HCLUSTER hCluster
  141. );
  142. void ListOfClusResources_Add(TCHAR * szEntry)
  143. {
  144. //Add entry to the list if not already there
  145. if (_tcsicmp(szEntry, _T("")) != 0)
  146. {
  147. // Add it if it is not already there.
  148. if (TRUE != IsThisStringInThisCStringList(gcstrListOfClusResources, szEntry))
  149. {
  150. gcstrListOfClusResources.AddTail(szEntry);
  151. //iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ListOfClusResources_Add:%s\n"),szEntry));
  152. }
  153. }
  154. return;
  155. }
  156. INT ListOfClusResources_Check(TCHAR * szEntry)
  157. {
  158. int iReturn = FALSE;
  159. //Add entry to the list if not already there
  160. if (_tcsicmp(szEntry, _T("")) != 0)
  161. {
  162. // Return true if it's in there!
  163. iReturn = IsThisStringInThisCStringList(gcstrListOfClusResources, szEntry);
  164. }
  165. return iReturn;
  166. }
  167. BOOL
  168. RegisterIisServerInstanceResourceType(
  169. LPWSTR pszResType,
  170. LPWSTR pszResTypeDisplayName,
  171. LPWSTR pszPath,
  172. LPWSTR pszAdminPath
  173. )
  174. {
  175. HCLUSTER hC;
  176. DWORD dwErr = ERROR_SUCCESS;
  177. HINSTANCE hClusapi;
  178. PFN_OPENCLUSTER pfnOpenCluster;
  179. PFN_CLOSECLUSTER pfnCloseCluster;
  180. PFN_CREATECLUSTERRESOURCETYPE pfnCreateClusterResourceType;
  181. HRESULT hres;
  182. if ( hClusapi = LoadLibrary( L"clusapi.dll" ) )
  183. {
  184. pfnOpenCluster = (PFN_OPENCLUSTER)GetProcAddress( hClusapi, "OpenCluster" );
  185. pfnCloseCluster = (PFN_CLOSECLUSTER)GetProcAddress( hClusapi, "CloseCluster" );
  186. pfnCreateClusterResourceType = (PFN_CREATECLUSTERRESOURCETYPE)GetProcAddress( hClusapi, "CreateClusterResourceType" );
  187. if ( pfnOpenCluster &&
  188. pfnCloseCluster &&
  189. pfnCreateClusterResourceType )
  190. {
  191. if ( hC = pfnOpenCluster( NULL ) )
  192. {
  193. hres = pfnCreateClusterResourceType(
  194. hC,
  195. pszResType,
  196. pszResType,
  197. pszPath,
  198. 5000,
  199. 60000 );
  200. if ( SUCCEEDED( hres ) )
  201. {
  202. HINSTANCE hAdmin;
  203. PFN_DLLREGISTERCLUADMINEXTENSION pfnDllRegisterCluAdminExtension;
  204. if ( hAdmin = LoadLibrary( pszAdminPath ) )
  205. {
  206. pfnDllRegisterCluAdminExtension =
  207. (PFN_DLLREGISTERCLUADMINEXTENSION)GetProcAddress( hAdmin, "DllRegisterCluAdminExtension" );
  208. if ( pfnDllRegisterCluAdminExtension )
  209. {
  210. if ( FAILED(hres = pfnDllRegisterCluAdminExtension( hC )) )
  211. {
  212. dwErr = hres;
  213. }
  214. }
  215. else
  216. {
  217. dwErr = GetLastError();
  218. }
  219. FreeLibrary( hAdmin );
  220. }
  221. else
  222. {
  223. dwErr = GetLastError();
  224. }
  225. }
  226. else
  227. {
  228. dwErr = hres;
  229. }
  230. pfnCloseCluster( hC );
  231. if ( dwErr )
  232. {
  233. SetLastError( dwErr );
  234. }
  235. }
  236. }
  237. else
  238. {
  239. dwErr = GetLastError();
  240. }
  241. FreeLibrary( hClusapi );
  242. }
  243. else
  244. {
  245. dwErr = GetLastError();
  246. }
  247. return dwErr == ERROR_SUCCESS ? TRUE : FALSE;
  248. }
  249. BOOL
  250. UnregisterIisServerInstanceResourceType(
  251. LPWSTR pszResType,
  252. LPWSTR pszAdminPath,
  253. BOOL bGrabVRootFromResourceAndAddToIISVRoot,
  254. BOOL bDeleteAfterMove
  255. )
  256. {
  257. CStringArray cstrArryName, cstrArryPath;
  258. CStringArray cstrArryNameftp, cstrArryPathftp;
  259. HCLUSTER hC;
  260. DWORD dwErr = ERROR_SUCCESS;
  261. HINSTANCE hClusapi;
  262. PFN_OPENCLUSTER pfnOpenCluster;
  263. PFN_CLOSECLUSTER pfnCloseCluster;
  264. PFN_DELETECLUSTERRESOURCETYPE pfnDeleteClusterResourceType;
  265. PFN_ClusterOpenEnum pfnClusterOpenEnum;
  266. PFN_ClusterEnum pfnClusterEnum;
  267. PFN_ClusterCloseEnum pfnClusterCloseEnum;
  268. PFN_OpenClusterResource pfnOpenClusterResource;
  269. PFN_CloseClusterResource pfnCloseClusterResource;
  270. PFN_DeleteClusterResource pfnDeleteClusterResource;
  271. PFN_OfflineClusterResource pfnOfflineClusterResource;
  272. PFN_GetClusterResourceKey pfnGetClusterResourceKey;
  273. PFN_ClusterRegCloseKey pfnClusterRegCloseKey;
  274. PFN_ClusterRegQueryValue pfnClusterRegQueryValue;
  275. PFN_GetClusterResourceState pfnGetClusterResourceState;
  276. HRESULT hres;
  277. HCLUSENUM hClusEnum;
  278. WCHAR * pawchResName = NULL;
  279. WCHAR awchResName[256];
  280. WCHAR awchResType[256];
  281. DWORD dwEnum;
  282. DWORD dwType;
  283. DWORD dwStrLen;
  284. HRESOURCE hRes;
  285. HKEY hKey;
  286. BOOL fDel;
  287. DWORD dwRetry;
  288. hClusapi = NULL;
  289. hClusapi = LoadLibrary(L"clusapi.dll");
  290. if (!hClusapi)
  291. {
  292. hClusapi = NULL;
  293. iisDebugOut((LOG_TYPE_ERROR, _T("UnregisterIisServerInstanceResourceType:LoadLib clusapi.dll failed.\n")));
  294. goto UnregisterIisServerInstanceResourceType_Exit;
  295. }
  296. pfnOpenCluster = (PFN_OPENCLUSTER)GetProcAddress( hClusapi, "OpenCluster" );
  297. pfnCloseCluster = (PFN_CLOSECLUSTER)GetProcAddress( hClusapi, "CloseCluster" );
  298. pfnDeleteClusterResourceType = (PFN_DELETECLUSTERRESOURCETYPE)GetProcAddress( hClusapi, "DeleteClusterResourceType" );
  299. pfnClusterOpenEnum = (PFN_ClusterOpenEnum)GetProcAddress( hClusapi, "ClusterOpenEnum" );
  300. pfnClusterEnum = (PFN_ClusterEnum)GetProcAddress( hClusapi, "ClusterEnum" );
  301. pfnClusterCloseEnum = (PFN_ClusterCloseEnum)GetProcAddress( hClusapi, "ClusterCloseEnum" );
  302. pfnOpenClusterResource = (PFN_OpenClusterResource)GetProcAddress( hClusapi, "OpenClusterResource" );
  303. pfnCloseClusterResource = (PFN_CloseClusterResource)GetProcAddress( hClusapi, "CloseClusterResource" );
  304. pfnDeleteClusterResource = (PFN_DeleteClusterResource)GetProcAddress( hClusapi, "DeleteClusterResource" );
  305. pfnOfflineClusterResource = (PFN_OfflineClusterResource)GetProcAddress( hClusapi, "OfflineClusterResource" );
  306. pfnGetClusterResourceKey = (PFN_GetClusterResourceKey)GetProcAddress( hClusapi, "GetClusterResourceKey" );
  307. pfnClusterRegCloseKey = (PFN_ClusterRegCloseKey)GetProcAddress( hClusapi, "ClusterRegCloseKey" );
  308. pfnClusterRegQueryValue = (PFN_ClusterRegQueryValue)GetProcAddress( hClusapi, "ClusterRegQueryValue" );
  309. pfnGetClusterResourceState = (PFN_GetClusterResourceState)GetProcAddress( hClusapi, "GetClusterResourceState" );
  310. if ( !pfnOpenCluster ||
  311. !pfnCloseCluster ||
  312. !pfnDeleteClusterResourceType ||
  313. !pfnClusterOpenEnum ||
  314. !pfnClusterEnum ||
  315. !pfnClusterCloseEnum ||
  316. !pfnOpenClusterResource ||
  317. !pfnCloseClusterResource ||
  318. !pfnDeleteClusterResource ||
  319. !pfnOfflineClusterResource ||
  320. !pfnGetClusterResourceKey ||
  321. !pfnClusterRegCloseKey ||
  322. !pfnClusterRegQueryValue ||
  323. !pfnGetClusterResourceState )
  324. {
  325. iisDebugOut((LOG_TYPE_ERROR, _T("UnregisterIisServerInstanceResourceType:clusapi.dll missing export function.failure.\n")));
  326. goto UnregisterIisServerInstanceResourceType_Exit;
  327. }
  328. hC = pfnOpenCluster(NULL);
  329. // if we can't open the cluster, then maybe there are none.
  330. if (!hC) {goto UnregisterIisServerInstanceResourceType_Exit;}
  331. // Delete all resources of type pszResType
  332. hClusEnum = pfnClusterOpenEnum(hC, CLUSTER_ENUM_RESOURCE);
  333. if (hClusEnum != NULL)
  334. {
  335. dwEnum = 0;
  336. int iClusterEnumReturn = ERROR_SUCCESS;
  337. // allocate the initial buffer for pawchResName
  338. dwStrLen = 256 * sizeof(WCHAR);
  339. pawchResName = NULL;
  340. pawchResName = (WCHAR *) malloc( dwStrLen );
  341. if (!pawchResName)
  342. {
  343. iisDebugOut((LOG_TYPE_ERROR, _T("UnregisterIisServerInstanceResourceType: malloc FAILED.out of memory.\n")));
  344. goto UnregisterIisServerInstanceResourceType_Exit;
  345. }
  346. do
  347. {
  348. iClusterEnumReturn = ERROR_SUCCESS;
  349. iClusterEnumReturn = pfnClusterEnum( hClusEnum, dwEnum, &dwType, pawchResName, &dwStrLen );
  350. if (iClusterEnumReturn != ERROR_SUCCESS)
  351. {
  352. // Check if failed because it needs more space.
  353. if (iClusterEnumReturn == ERROR_MORE_DATA)
  354. {
  355. // dwStrLen should be set to the required length returned from pfnClusterEnum
  356. dwStrLen = (dwStrLen + 1) * sizeof(WCHAR);
  357. pawchResName = (WCHAR *) realloc(pawchResName, dwStrLen);
  358. if (!pawchResName)
  359. {
  360. iisDebugOut((LOG_TYPE_ERROR, _T("UnregisterIisServerInstanceResourceType: realloc FAILED.out of memory.\n")));
  361. goto UnregisterIisServerInstanceResourceType_Exit;
  362. }
  363. // try it again.
  364. iClusterEnumReturn = ERROR_SUCCESS;
  365. iClusterEnumReturn = pfnClusterEnum( hClusEnum, dwEnum, &dwType, pawchResName, &dwStrLen );
  366. if (iClusterEnumReturn != ERROR_SUCCESS)
  367. {
  368. iisDebugOut((LOG_TYPE_ERROR, _T("UnregisterIisServerInstanceResourceType: FAILED.err=0x%x.\n"), iClusterEnumReturn));
  369. break;
  370. }
  371. }
  372. else
  373. {
  374. if (iClusterEnumReturn != ERROR_NO_MORE_ITEMS)
  375. {
  376. // failed for some other reason than no more data
  377. iisDebugOut((LOG_TYPE_ERROR, _T("UnregisterIisServerInstanceResourceType: FAILED.err=0x%x.\n"), iClusterEnumReturn));
  378. }
  379. break;
  380. }
  381. }
  382. // proceed
  383. if ( hRes = pfnOpenClusterResource( hC, pawchResName ) )
  384. {
  385. if ( hKey = pfnGetClusterResourceKey( hRes, KEY_READ ) )
  386. {
  387. dwStrLen = sizeof(awchResType)/sizeof(WCHAR);
  388. // Check if it's for 'our' type of key (pszResType)
  389. fDel = pfnClusterRegQueryValue( hKey, L"Type", &dwType, (LPBYTE)awchResType, &dwStrLen ) == ERROR_SUCCESS && !wcscmp( awchResType, pszResType );
  390. pfnClusterRegCloseKey( hKey );
  391. if ( fDel )
  392. {
  393. if (bDeleteAfterMove)
  394. {
  395. // Take the resource off line so that we can actually delete it, i guess.
  396. pfnOfflineClusterResource( hRes );
  397. for ( dwRetry = 0 ;dwRetry < 30 && pfnGetClusterResourceState( hRes,NULL,&dwStrLen,NULL,&dwStrLen ) != ClusterResourceOffline; ++dwRetry )
  398. {
  399. Sleep( 1000 );
  400. }
  401. }
  402. // At this point we have successfully got the cluster to go offline
  403. if (bGrabVRootFromResourceAndAddToIISVRoot)
  404. {
  405. // At this point we have successfully got the cluster to go offline
  406. // Get the vroot names and path's here and stick into the arrays....
  407. GetClusterIISVRoot(hRes, L"W3SVC", cstrArryName, cstrArryPath);
  408. // Do it for FTP now.
  409. GetClusterIISVRoot(hRes, L"MSFTPSVC", cstrArryNameftp, cstrArryPathftp);
  410. // No need to do it for gopher since there is none.
  411. //GetClusterIISVRoot(hRes, L"GOPHERSVC", cstrArryName, cstrArryPath);
  412. }
  413. // We have saved all the important data into our Array's
  414. // now it's okay to delete the Resource
  415. if (bDeleteAfterMove)
  416. {
  417. pfnDeleteClusterResource( hRes );
  418. }
  419. }
  420. }
  421. pfnCloseClusterResource( hRes );
  422. }
  423. // Increment to the next one
  424. ++dwEnum;
  425. } while(TRUE);
  426. pfnClusterCloseEnum( hClusEnum );
  427. }
  428. if (bDeleteAfterMove)
  429. {
  430. dwErr = pfnDeleteClusterResourceType(hC,pszResType );
  431. HINSTANCE hAdmin;
  432. if ( hAdmin = LoadLibrary( pszAdminPath ) )
  433. {
  434. PFN_DLLUNREGISTERCLUADMINEXTENSION pfnDllUnregisterCluAdminExtension;
  435. pfnDllUnregisterCluAdminExtension = (PFN_DLLUNREGISTERCLUADMINEXTENSION)GetProcAddress( hAdmin, "DllUnregisterCluAdminExtension" );
  436. if ( pfnDllUnregisterCluAdminExtension )
  437. {
  438. if ( FAILED(hres = pfnDllUnregisterCluAdminExtension( hC )) )
  439. {
  440. dwErr = hres;
  441. }
  442. }
  443. else
  444. {
  445. dwErr = GetLastError();
  446. }
  447. FreeLibrary( hAdmin );
  448. }
  449. else
  450. {
  451. dwErr = GetLastError();
  452. }
  453. }
  454. pfnCloseCluster( hC );
  455. if (dwErr)
  456. {SetLastError( dwErr );}
  457. UnregisterIisServerInstanceResourceType_Exit:
  458. // Copy these to the iis virtual root registry....
  459. MoveVRootToIIS3Registry(REG_W3SVC,cstrArryName,cstrArryPath);
  460. // Copy these to the iis virtual root registry....
  461. MoveVRootToIIS3Registry(REG_MSFTPSVC,cstrArryNameftp,cstrArryPathftp);
  462. if (hClusapi) {FreeLibrary(hClusapi);}
  463. if (pawchResName) {free(pawchResName);}
  464. return dwErr == ERROR_SUCCESS ? TRUE : FALSE;
  465. }
  466. void TestClusterRead(LPWSTR pszClusterName)
  467. {
  468. iisDebugOut_Start(_T("TestClusterRead"));
  469. LPWSTR pszResType = L"IIS Virtual Root";
  470. CStringArray cstrArryName, cstrArryPath;
  471. CStringArray cstrArryNameftp, cstrArryPathftp;
  472. HCLUSTER hC;
  473. DWORD dwErr = ERROR_SUCCESS;
  474. HINSTANCE hClusapi;
  475. PFN_OPENCLUSTER pfnOpenCluster;
  476. PFN_CLOSECLUSTER pfnCloseCluster;
  477. PFN_DELETECLUSTERRESOURCETYPE pfnDeleteClusterResourceType;
  478. PFN_ClusterOpenEnum pfnClusterOpenEnum;
  479. PFN_ClusterEnum pfnClusterEnum;
  480. PFN_ClusterCloseEnum pfnClusterCloseEnum;
  481. PFN_OpenClusterResource pfnOpenClusterResource;
  482. PFN_CloseClusterResource pfnCloseClusterResource;
  483. PFN_DeleteClusterResource pfnDeleteClusterResource;
  484. PFN_OfflineClusterResource pfnOfflineClusterResource;
  485. PFN_GetClusterResourceKey pfnGetClusterResourceKey;
  486. PFN_ClusterRegCloseKey pfnClusterRegCloseKey;
  487. PFN_ClusterRegQueryValue pfnClusterRegQueryValue;
  488. PFN_GetClusterResourceState pfnGetClusterResourceState;
  489. HRESULT hres;
  490. HCLUSENUM hClusEnum;
  491. WCHAR * pawchResName = NULL;
  492. WCHAR awchResName[256];
  493. WCHAR awchResType[256];
  494. DWORD dwEnum;
  495. DWORD dwType;
  496. DWORD dwStrLen;
  497. HRESOURCE hRes;
  498. HKEY hKey;
  499. BOOL fDel;
  500. DWORD dwRetry;
  501. hClusapi = NULL;
  502. hClusapi = LoadLibrary(L"clusapi.dll");
  503. if (!hClusapi)
  504. {
  505. hClusapi = NULL;
  506. iisDebugOut((LOG_TYPE_TRACE, _T("fail 1\n")));
  507. goto TestClusterRead_Exit;
  508. }
  509. pfnOpenCluster = (PFN_OPENCLUSTER)GetProcAddress( hClusapi, "OpenCluster" );
  510. pfnCloseCluster = (PFN_CLOSECLUSTER)GetProcAddress( hClusapi, "CloseCluster" );
  511. pfnDeleteClusterResourceType = (PFN_DELETECLUSTERRESOURCETYPE)GetProcAddress( hClusapi, "DeleteClusterResourceType" );
  512. pfnClusterOpenEnum = (PFN_ClusterOpenEnum)GetProcAddress( hClusapi, "ClusterOpenEnum" );
  513. pfnClusterEnum = (PFN_ClusterEnum)GetProcAddress( hClusapi, "ClusterEnum" );
  514. pfnClusterCloseEnum = (PFN_ClusterCloseEnum)GetProcAddress( hClusapi, "ClusterCloseEnum" );
  515. pfnOpenClusterResource = (PFN_OpenClusterResource)GetProcAddress( hClusapi, "OpenClusterResource" );
  516. pfnCloseClusterResource = (PFN_CloseClusterResource)GetProcAddress( hClusapi, "CloseClusterResource" );
  517. pfnDeleteClusterResource = (PFN_DeleteClusterResource)GetProcAddress( hClusapi, "DeleteClusterResource" );
  518. pfnOfflineClusterResource = (PFN_OfflineClusterResource)GetProcAddress( hClusapi, "OfflineClusterResource" );
  519. pfnGetClusterResourceKey = (PFN_GetClusterResourceKey)GetProcAddress( hClusapi, "GetClusterResourceKey" );
  520. pfnClusterRegCloseKey = (PFN_ClusterRegCloseKey)GetProcAddress( hClusapi, "ClusterRegCloseKey" );
  521. pfnClusterRegQueryValue = (PFN_ClusterRegQueryValue)GetProcAddress( hClusapi, "ClusterRegQueryValue" );
  522. pfnGetClusterResourceState = (PFN_GetClusterResourceState)GetProcAddress( hClusapi, "GetClusterResourceState" );
  523. if ( !pfnOpenCluster ||
  524. !pfnCloseCluster ||
  525. !pfnDeleteClusterResourceType ||
  526. !pfnClusterOpenEnum ||
  527. !pfnClusterEnum ||
  528. !pfnClusterCloseEnum ||
  529. !pfnOpenClusterResource ||
  530. !pfnCloseClusterResource ||
  531. !pfnDeleteClusterResource ||
  532. !pfnOfflineClusterResource ||
  533. !pfnGetClusterResourceKey ||
  534. !pfnClusterRegCloseKey ||
  535. !pfnClusterRegQueryValue ||
  536. !pfnGetClusterResourceState )
  537. {
  538. iisDebugOut((LOG_TYPE_TRACE, _T("fail 2\n")));
  539. goto TestClusterRead_Exit;
  540. }
  541. iisDebugOut((LOG_TYPE_TRACE, _T("try to open cluster=%s\n"),pszClusterName));
  542. // try to open the cluster on the computer
  543. if ( hC = pfnOpenCluster( pszClusterName ) )
  544. {
  545. //
  546. // Delete all resources of type pszResType
  547. //
  548. if ( (hClusEnum = pfnClusterOpenEnum( hC, CLUSTER_ENUM_RESOURCE )) != NULL )
  549. {
  550. dwEnum = 0;
  551. int iClusterEnumReturn = ERROR_SUCCESS;
  552. // allocate the initial buffer for pawchResName
  553. dwStrLen = 256 * sizeof(WCHAR);
  554. pawchResName = NULL;
  555. pawchResName = (LPTSTR) malloc( dwStrLen );
  556. if (!pawchResName)
  557. {
  558. iisDebugOut((LOG_TYPE_ERROR, _T("TestClusterRead: malloc FAILED.out of memory.\n")));
  559. goto TestClusterRead_Exit;
  560. }
  561. do
  562. {
  563. iClusterEnumReturn = pfnClusterEnum( hClusEnum, dwEnum, &dwType, pawchResName, &dwStrLen );
  564. if (iClusterEnumReturn != ERROR_SUCCESS)
  565. {
  566. // Check if failed because it needs more space.
  567. if (iClusterEnumReturn == ERROR_MORE_DATA)
  568. {
  569. // dwStrLen should be set to the required length returned from pfnClusterEnum
  570. dwStrLen = (dwStrLen + 1) * sizeof(WCHAR);
  571. pawchResName = (LPTSTR) realloc(pawchResName, dwStrLen);
  572. if (!pawchResName)
  573. {
  574. iisDebugOut((LOG_TYPE_ERROR, _T("TestClusterRead: realloc FAILED.out of memory.\n")));
  575. goto TestClusterRead_Exit;
  576. }
  577. // try it again.
  578. iClusterEnumReturn = pfnClusterEnum( hClusEnum, dwEnum, &dwType, pawchResName, &dwStrLen );
  579. if (iClusterEnumReturn != ERROR_SUCCESS)
  580. {
  581. iisDebugOut((LOG_TYPE_ERROR, _T("TestClusterRead: FAILED.err=0x%x.\n"), iClusterEnumReturn));
  582. break;
  583. }
  584. }
  585. else
  586. {
  587. if (iClusterEnumReturn != ERROR_NO_MORE_ITEMS)
  588. {
  589. // failed for some other reason.
  590. iisDebugOut((LOG_TYPE_ERROR, _T("TestClusterRead: FAILED.err=0x%x.\n"), iClusterEnumReturn));
  591. }
  592. break;
  593. }
  594. }
  595. // proceed
  596. if ( hRes = pfnOpenClusterResource( hC, pawchResName ) )
  597. {
  598. if ( hKey = pfnGetClusterResourceKey( hRes, KEY_READ ) )
  599. {
  600. dwStrLen = sizeof(awchResType)/sizeof(WCHAR);
  601. fDel = pfnClusterRegQueryValue( hKey, L"Type", &dwType, (LPBYTE)awchResType, &dwStrLen ) == ERROR_SUCCESS && !wcscmp( awchResType, pszResType );
  602. iisDebugOut((LOG_TYPE_TRACE, _T("TestClusterRead():ClusterRegQueryValue:%s."),awchResType));
  603. pfnClusterRegCloseKey( hKey );
  604. if ( fDel )
  605. {
  606. /*
  607. pfnOfflineClusterResource( hRes );
  608. for ( dwRetry = 0 ; dwRetry < 30 && pfnGetClusterResourceState( hRes,NULL,&dwStrLen,NULL,&dwStrLen ) != ClusterResourceOffline; ++dwRetry )
  609. {
  610. Sleep( 1000 );
  611. }
  612. */
  613. // At this point we have successfully got the cluster to go offline
  614. // Get the vroot names and path's here and stick into the arrays....
  615. GetClusterIISVRoot(hRes, L"W3SVC", cstrArryName, cstrArryPath);
  616. // Do it for FTP now.
  617. GetClusterIISVRoot(hRes, L"MSFTPSVC", cstrArryNameftp, cstrArryPathftp);
  618. // No need to do it for gopher since there is none.
  619. //GetClusterIISVRoot(hRes, L"GOPHERSVC", cstrArryName, cstrArryPath);
  620. }
  621. }
  622. pfnCloseClusterResource( hRes );
  623. }
  624. // Increment to the next one
  625. ++dwEnum;
  626. } while(TRUE);
  627. pfnClusterCloseEnum( hClusEnum );
  628. }
  629. //dwErr = pfnDeleteClusterResourceType(hC,pszResType );
  630. pfnCloseCluster( hC );
  631. if (dwErr)
  632. {SetLastError( dwErr );}
  633. }
  634. else
  635. {
  636. iisDebugOut((LOG_TYPE_TRACE, _T("fail 3\n")));
  637. }
  638. TestClusterRead_Exit:
  639. // Copy these to the iis virtual root registry....
  640. MoveVRootToIIS3Registry(REG_W3SVC,cstrArryName,cstrArryPath);
  641. // Copy these to the iis virtual root registry....
  642. MoveVRootToIIS3Registry(REG_MSFTPSVC,cstrArryNameftp,cstrArryPathftp);
  643. if (hClusapi) {FreeLibrary(hClusapi);}
  644. if (pawchResName) {free(pawchResName);}
  645. iisDebugOut_End(_T("TestClusterRead"));
  646. return;
  647. }
  648. /****************************************************************************************
  649. *
  650. * Function: GetClusterIISVRoot
  651. *
  652. * Args: [in] hResource , the resource whos info should be added to the list
  653. *
  654. * Retrurn: GetLastError, on error
  655. *
  656. ****************************************************************************************/
  657. int GetClusterIISVRoot(HRESOURCE hResource, LPWSTR pszTheServiceType, CStringArray &strArryOfVrootNames, CStringArray &strArryOfVrootData)
  658. {
  659. //iisDebugOut((LOG_TYPE_ERROR, _T("GetClusterIISVRoot: start\n")));
  660. int iReturn = FALSE;
  661. HINSTANCE hClusapi;
  662. HINSTANCE hResutils;
  663. PFN_CLUSTERRESOURCECONTROL pfnClusterResourceControl;
  664. PFN_RESUTILFINDSZPROPERTY pfnResUtilFindSzProperty;
  665. PFN_RESUTILFINDDWORDPROPERTY pfnResUtilFindDwordProperty;
  666. //
  667. // Initial size of the buffer
  668. //
  669. DWORD dwBufferSize = 256;
  670. //
  671. // The requested buffer size, and the number of bytes actually in the returned buffer
  672. //
  673. DWORD dwRequestedBufferSize = dwBufferSize;
  674. //
  675. // Result from the call to the cluster resource control function
  676. //
  677. DWORD dwResult;
  678. //
  679. // Buffer that holds the property list for this resource
  680. //
  681. LPVOID lpvPropList = NULL;
  682. //
  683. // The Proivate property that is being read
  684. //
  685. LPWSTR lpwszPrivateProp = NULL;
  686. hClusapi = LoadLibrary( L"clusapi.dll" );
  687. if (!hClusapi)
  688. {
  689. iisDebugOut((LOG_TYPE_ERROR, _T("GetClusterIISVRoot: failed to loadlib clusapi.dll\n")));
  690. goto GetIISVRoot_Exit;
  691. }
  692. pfnClusterResourceControl = (PFN_CLUSTERRESOURCECONTROL)GetProcAddress( hClusapi, "ClusterResourceControl" );
  693. if (!pfnClusterResourceControl)
  694. {
  695. iisDebugOut((LOG_TYPE_ERROR, _T("GetClusterIISVRoot: failed to GetProcAddress clusapi.dll:ClusterResourceControl\n")));
  696. goto GetIISVRoot_Exit;
  697. }
  698. hResutils = LoadLibrary( L"resutils.dll" );
  699. if (!hResutils)
  700. {
  701. iisDebugOut((LOG_TYPE_ERROR, _T("GetClusterIISVRoot: failed to loadlib resutils.dll\n")));
  702. goto GetIISVRoot_Exit;
  703. }
  704. pfnResUtilFindSzProperty = (PFN_RESUTILFINDSZPROPERTY)GetProcAddress( hResutils, "ResUtilFindSzProperty" );
  705. if (!pfnResUtilFindSzProperty)
  706. {
  707. iisDebugOut((LOG_TYPE_ERROR, _T("GetClusterIISVRoot: failed to GetProcAddress resutils.dll:ResUtilFindSzProperty\n")));
  708. goto GetIISVRoot_Exit;
  709. }
  710. pfnResUtilFindDwordProperty = (PFN_RESUTILFINDDWORDPROPERTY)GetProcAddress( hResutils, "ResUtilFindDwordProperty" );
  711. if (!pfnResUtilFindDwordProperty)
  712. {
  713. iisDebugOut((LOG_TYPE_ERROR, _T("GetClusterIISVRoot: failed to GetProcAddress resutils.dll:ResUtilFindDwordProperty\n")));
  714. goto GetIISVRoot_Exit;
  715. }
  716. //
  717. // Allocate memory for the resource type
  718. //
  719. lpvPropList = (LPWSTR) HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufferSize * sizeof(WCHAR) );
  720. if( lpvPropList == NULL)
  721. {
  722. lpvPropList = NULL;
  723. iisDebugOut((LOG_TYPE_ERROR, _T("GetClusterIISVRoot: E_OUTOFMEMORY\n")));
  724. goto GetIISVRoot_Exit;
  725. }
  726. //
  727. // Allocate memory for the Property
  728. //
  729. lpwszPrivateProp = (LPWSTR) HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, (_MAX_PATH+_MAX_PATH+1) * sizeof(WCHAR) );
  730. if( lpwszPrivateProp == NULL)
  731. {
  732. lpvPropList = NULL;
  733. iisDebugOut((LOG_TYPE_ERROR, _T("GetClusterIISVRoot: E_OUTOFMEMORY\n")));
  734. goto GetIISVRoot_Exit;
  735. }
  736. //
  737. // Get the resource's private properties (Service , InstanceId)
  738. //
  739. while( 1 )
  740. {
  741. dwResult = pfnClusterResourceControl(hResource,NULL,CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES,NULL,0,lpvPropList,dwBufferSize,&dwRequestedBufferSize );
  742. if( ERROR_SUCCESS == dwResult )
  743. {
  744. // ---------------------
  745. // what the entries are:
  746. // AccessMask (dword) = 5
  747. // Alias (string) = "virtual dir name"
  748. // Directory (string) = "c:\la\lalalala"
  749. // ServiceName (string) = W3SVC, MSFTPSVC, GOPHERSVC
  750. // ---------------------
  751. //
  752. // Get the "ServiceName" entry
  753. //
  754. dwResult = pfnResUtilFindSzProperty( lpvPropList, &dwRequestedBufferSize, L"ServiceName", &lpwszPrivateProp);
  755. if( dwResult != ERROR_SUCCESS )
  756. {
  757. iisDebugOut((LOG_TYPE_ERROR, _T("Couldn't get 'ServiceName' property.fail\n")));
  758. goto GetIISVRoot_Exit;
  759. }
  760. if (_wcsicmp(lpwszPrivateProp, pszTheServiceType) == 0)
  761. {
  762. // okay, we want to do stuff with this one!!!
  763. DWORD dwAccessMask;
  764. CString csAlias;
  765. CString csDirectory;
  766. TCHAR szMyBigPath[_MAX_PATH + 20];
  767. DWORD dwPrivateProp = 0;
  768. dwRequestedBufferSize = sizeof(DWORD);
  769. // get the Access Mask.
  770. dwResult = pfnResUtilFindDwordProperty( lpvPropList, &dwRequestedBufferSize, L"AccessMask", &dwPrivateProp);
  771. if( dwResult != ERROR_SUCCESS )
  772. {
  773. iisDebugOut((LOG_TYPE_ERROR, _T("Couldn't get 'AccessMask' property.fail\n")));
  774. goto GetIISVRoot_Exit;
  775. }
  776. dwAccessMask = dwPrivateProp;
  777. // get the Alias
  778. dwResult = pfnResUtilFindSzProperty( lpvPropList, &dwRequestedBufferSize, L"Alias", &lpwszPrivateProp);
  779. if( dwResult != ERROR_SUCCESS )
  780. {
  781. iisDebugOut((LOG_TYPE_ERROR, _T("Couldn't get 'Alias' property.fail\n")));
  782. goto GetIISVRoot_Exit;
  783. }
  784. csAlias = lpwszPrivateProp;
  785. // Get the Directory
  786. dwResult = pfnResUtilFindSzProperty( lpvPropList, &dwRequestedBufferSize, L"Directory", &lpwszPrivateProp);
  787. if( dwResult != ERROR_SUCCESS )
  788. {
  789. iisDebugOut((LOG_TYPE_ERROR, _T("Couldn't get 'Directory' property.fail\n")));
  790. goto GetIISVRoot_Exit;
  791. }
  792. TCHAR thepath[_MAX_PATH];
  793. TCHAR * pmypath;
  794. csDirectory = lpwszPrivateProp;
  795. // make sure it's a valid directory name!
  796. if (0 != GetFullPathName(lpwszPrivateProp, _MAX_PATH, thepath, &pmypath))
  797. {csDirectory = thepath;}
  798. // --------------------
  799. // formulate the string
  800. // --------------------
  801. //
  802. // Put the Name into the array.
  803. //
  804. // "/Alias"
  805. strArryOfVrootNames.Add(csAlias);
  806. //
  807. // "C:\inetpub\ASPSamp,,5"
  808. //
  809. _stprintf(szMyBigPath,_T("%s,,%d"),csDirectory, dwAccessMask);
  810. strArryOfVrootData.Add(szMyBigPath);
  811. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("Entry=[%s] '%s=%s'\n"),pszTheServiceType,csAlias,szMyBigPath));
  812. }
  813. goto GetIISVRoot_Exit;
  814. }
  815. if( ERROR_MORE_DATA == dwResult )
  816. {
  817. //
  818. // Set the buffer size to the required size reallocate the buffer
  819. //
  820. dwBufferSize = ++dwRequestedBufferSize;
  821. lpvPropList = (LPWSTR) HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY | HEAP_NO_SERIALIZE, lpvPropList, dwBufferSize * sizeof(WCHAR) );
  822. if ( lpvPropList == NULL)
  823. {
  824. // out of memory!!!!
  825. goto GetIISVRoot_Exit;
  826. }
  827. }
  828. }
  829. GetIISVRoot_Exit:
  830. if (lpwszPrivateProp)
  831. {HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, lpwszPrivateProp);}
  832. if (lpvPropList)
  833. {HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, lpvPropList);}
  834. //iisDebugOut((LOG_TYPE_ERROR, _T("GetClusterIISVRoot: end\n")));
  835. return iReturn;
  836. }
  837. // REG_W3SVC, REG_MSFTPSVC
  838. void MoveVRootToIIS3Registry(CString strRegPath, CStringArray &strArryOfVrootNames, CStringArray &strArryOfVrootData)
  839. {
  840. int nArrayItems = 0;
  841. int i = 0;
  842. strRegPath +=_T("\\Parameters\\Virtual Roots");
  843. CRegKey regVR( HKEY_LOCAL_MACHINE, strRegPath);
  844. if ((HKEY) regVR)
  845. {
  846. nArrayItems = (int)strArryOfVrootNames.GetSize();
  847. // if the CString arrays are empty then we won't ever process anything (nArrayItems is 1 based)
  848. for (i = 0; i < nArrayItems; i++ )
  849. {
  850. regVR.SetValue(strArryOfVrootNames[i], strArryOfVrootData[i]);
  851. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("Array[%d]:%s=%s\n"),i,strArryOfVrootNames[i], strArryOfVrootData[i]));
  852. }
  853. }
  854. return;
  855. }
  856. void Upgrade_WolfPack()
  857. {
  858. iisDebugOut_Start(_T("Upgrade_WolfPack"),LOG_TYPE_TRACE);
  859. CRegKey regClusSvc(HKEY_LOCAL_MACHINE, scClusterPath, KEY_READ);
  860. if ( (HKEY)regClusSvc )
  861. {
  862. CString csPath;
  863. TCHAR szPath[MAX_PATH];
  864. if (regClusSvc.QueryValue(_T("ImagePath"), csPath) == NERR_Success)
  865. {
  866. // string is formatted like this
  867. // %SystemRoot%\cluster\clusprxy.exe
  868. // Find the last \ and trim and paste the new file name on
  869. csPath = csPath.Left(csPath.ReverseFind('\\'));
  870. if ( csPath.IsEmpty() )
  871. {
  872. ASSERT(TRUE);
  873. return;
  874. }
  875. csPath += _T("\\iisclex3.dll");
  876. if ( ExpandEnvironmentStrings( (LPCTSTR)csPath,szPath,sizeof(szPath)/sizeof(TCHAR)))
  877. {
  878. // in iis3.0 the resources were called 'IIS Virtual Root'
  879. // in iis4.0 it is something else (iis50 is the same as iis4)
  880. UnregisterIisServerInstanceResourceType(L"IIS Virtual Root",(LPTSTR)szPath,TRUE,TRUE);
  881. }
  882. else
  883. {
  884. ASSERT(TRUE);
  885. }
  886. }
  887. ProcessSection(g_pTheApp->m_hInfHandle, _T("Wolfpack_Upgrade"));
  888. }
  889. iisDebugOut_End(_T("Upgrade_WolfPack"),LOG_TYPE_TRACE);
  890. }
  891. /****************************************************
  892. *
  893. * Known "problem": If a resource doesn't come offline after the five
  894. * retries than the function continues to try to take the other iis resources
  895. * offline but there is no error reported. You could change this pretty simply I think.
  896. *
  897. *****************************************************/
  898. DWORD BringALLIISClusterResourcesOffline()
  899. {
  900. //
  901. // The return code
  902. //
  903. DWORD dwError = ERROR_SUCCESS;
  904. //
  905. // Handle for the cluster
  906. //
  907. HCLUSTER hCluster = NULL;
  908. //
  909. // Handle for the cluster enumerator
  910. //
  911. HCLUSENUM hClusResEnum = NULL;
  912. //
  913. // Handle to a resource
  914. //
  915. HRESOURCE hResource = NULL;
  916. //
  917. // The index of the resources we're taking offline
  918. //
  919. DWORD dwResourceIndex = 0;
  920. //
  921. // The type cluster object being enumerated returned by the ClusterEnum function
  922. //
  923. DWORD dwObjectType = 0;
  924. //
  925. // The name of the cluster resource returned by the ClusterEnum function
  926. //
  927. LPWSTR lpwszResourceName = NULL;
  928. //
  929. // The return code from the call to ClusterEnum
  930. //
  931. DWORD dwResultClusterEnum = ERROR_SUCCESS;
  932. //
  933. // The size of the buffer (in characters) that is used to hold the resource name's length
  934. //
  935. DWORD dwResourceNameBufferLength = INITIAL_RESOURCE_NAME_SIZE;
  936. //
  937. // Size of the resource name passed to and returned by the ClusterEnum function
  938. //
  939. DWORD dwClusterEnumResourceNameLength = dwResourceNameBufferLength;
  940. BOOL iClusDependsOnIISServices = FALSE;
  941. //
  942. // Open the cluster
  943. //
  944. if ( !(hCluster = OpenCluster(NULL)) )
  945. {
  946. dwError = GetLastError();
  947. // This will fail with RPC_S_SERVER_UNAVAILABLE "The RPC server is unavailable" if there is no cluster on this system
  948. if (hCluster == NULL)
  949. {
  950. if ( (dwError != RPC_S_SERVER_UNAVAILABLE) &&
  951. (dwError != EPT_S_NOT_REGISTERED ) )
  952. {
  953. iisDebugOut((LOG_TYPE_ERROR, _T("BringALLIISClusterResourcesOffline:OpenCluster failed err=0x%x.\n"),dwError));
  954. }
  955. }
  956. else
  957. {
  958. iisDebugOut((LOG_TYPE_ERROR, _T("BringALLIISClusterResourcesOffline:OpenCluster failed err=0x%x.\n"),dwError));
  959. }
  960. goto clean_up;
  961. }
  962. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("BringALLIISClusterResourcesOffline:start.\n")));
  963. //
  964. // Get Enumerator for the cluster resouces
  965. //
  966. if ( !(hClusResEnum = ClusterOpenEnum( hCluster, CLUSTER_ENUM_RESOURCE )) )
  967. {
  968. dwError = GetLastError();
  969. iisDebugOut((LOG_TYPE_ERROR, _T("BringALLIISClusterResourcesOffline:ClusterOpenEnum failed err=0x%x.\n"),dwError));
  970. goto clean_up;
  971. }
  972. //
  973. // Enumerate the Resources in the cluster
  974. //
  975. //
  976. // Allocate memory to hold the cluster resource name as we enumerate the resources
  977. //
  978. if ( !(lpwszResourceName = (LPWSTR) LocalAlloc(LPTR, dwResourceNameBufferLength * sizeof(WCHAR))) )
  979. {
  980. dwError = GetLastError();
  981. iisDebugOut((LOG_TYPE_ERROR, _T("BringALLIISClusterResourcesOffline:LocalAlloc failed err=0x%x.\n"),dwError));
  982. goto clean_up;
  983. }
  984. //
  985. // Enumerate all of the resources in the cluster and take the IIS Server Instance's offline
  986. //
  987. while( ERROR_NO_MORE_ITEMS !=
  988. (dwResultClusterEnum = ClusterEnum(hClusResEnum,
  989. dwResourceIndex,
  990. &dwObjectType,
  991. lpwszResourceName,
  992. &dwClusterEnumResourceNameLength )) )
  993. {
  994. //
  995. // If we have a resource's name
  996. //
  997. if( ERROR_SUCCESS == dwResultClusterEnum )
  998. {
  999. if ( !(hResource = OpenClusterResource( hCluster, lpwszResourceName )) )
  1000. {
  1001. dwError = GetLastError();
  1002. break;
  1003. }
  1004. // If the resource type is "IIS Server Instance", or some other one that is
  1005. // dependent upon the iis services, then we need to stop it.
  1006. iClusDependsOnIISServices = CheckForIISDependentClusters(hResource);
  1007. if (iClusDependsOnIISServices)
  1008. {
  1009. CLUSTER_RESOURCE_STATE TheState = GetClusterResourceState(hResource,NULL,0,NULL,0);
  1010. if (TheState == ClusterResourceOnline || TheState == ClusterResourceOnlinePending)
  1011. {
  1012. HKEY hKey;
  1013. if ( hKey = GetClusterResourceKey( hResource, KEY_READ ) )
  1014. {
  1015. //
  1016. // Get the resource name.
  1017. //
  1018. LPWSTR lpwsResourceName = NULL;
  1019. lpwsResourceName = GetParameter( hKey, L"Name" );
  1020. if ( lpwsResourceName != NULL )
  1021. {
  1022. // this is a resource which we will try to stop
  1023. // so we should save the name somewhere in like a global list
  1024. iisDebugOut((LOG_TYPE_TRACE, _T("OfflineClusterResource:'%s'\n"),lpwsResourceName));
  1025. ListOfClusResources_Add(lpwsResourceName);
  1026. }
  1027. if (lpwsResourceName){LocalFree((LPWSTR) lpwsResourceName);}
  1028. ClusterRegCloseKey(hKey);
  1029. }
  1030. //
  1031. // If the resource doesn't come offline quickly then wait
  1032. //
  1033. if ( ERROR_IO_PENDING == OfflineClusterResource( hResource ) )
  1034. {
  1035. for(int iRetry=0; iRetry < MAX_OFFLINE_RETRIES; iRetry++)
  1036. {
  1037. Sleep( DELAY_BETWEEN_CALLS_TO_OFFLINE );
  1038. if ( ERROR_SUCCESS == OfflineClusterResource( hResource ) )
  1039. {
  1040. break;
  1041. }
  1042. }
  1043. }
  1044. }
  1045. CloseClusterResource( hResource );
  1046. }
  1047. dwResourceIndex++;
  1048. }
  1049. //
  1050. // If the buffer wasn't large enough then retry with a larger buffer
  1051. //
  1052. if( ERROR_MORE_DATA == dwResultClusterEnum )
  1053. {
  1054. //
  1055. // Set the buffer size to the required size reallocate the buffer
  1056. //
  1057. LPWSTR lpwszResourceNameTmp = lpwszResourceName;
  1058. //
  1059. // After returning from ClusterEnum dwClusterEnumResourceNameLength
  1060. // doesn't include the null terminator character
  1061. //
  1062. dwResourceNameBufferLength = dwClusterEnumResourceNameLength + 1;
  1063. if ( !(lpwszResourceName =
  1064. (LPWSTR) LocalReAlloc (lpwszResourceName, dwResourceNameBufferLength * sizeof(WCHAR), 0)) )
  1065. {
  1066. dwError = GetLastError();
  1067. LocalFree( lpwszResourceNameTmp );
  1068. lpwszResourceNameTmp = NULL;
  1069. break;
  1070. }
  1071. }
  1072. //
  1073. // Reset dwResourceNameLength with the size of the number of characters in the buffer
  1074. // You have to do this because everytime you call ClusterEnum is sets your buffer length
  1075. // argument to the number of characters in the string it's returning.
  1076. //
  1077. dwClusterEnumResourceNameLength = dwResourceNameBufferLength;
  1078. }
  1079. clean_up:
  1080. if ( lpwszResourceName )
  1081. {
  1082. LocalFree( lpwszResourceName );
  1083. lpwszResourceName = NULL;
  1084. }
  1085. if ( hClusResEnum )
  1086. {
  1087. ClusterCloseEnum( hClusResEnum );
  1088. hClusResEnum = NULL;
  1089. }
  1090. if ( hCluster )
  1091. {
  1092. CloseCluster( hCluster );
  1093. hCluster = NULL;
  1094. }
  1095. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("BringALLIISClusterResourcesOffline:end.ret=0x%x\n"),dwError));
  1096. return dwError;
  1097. }
  1098. DWORD BringALLIISClusterResourcesOnline()
  1099. {
  1100. //
  1101. // The return code
  1102. //
  1103. DWORD dwError = ERROR_SUCCESS;
  1104. //
  1105. // Handle for the cluster
  1106. //
  1107. HCLUSTER hCluster = NULL;
  1108. //
  1109. // Handle for the cluster enumerator
  1110. //
  1111. HCLUSENUM hClusResEnum = NULL;
  1112. //
  1113. // Handle to a resource
  1114. //
  1115. HRESOURCE hResource = NULL;
  1116. //
  1117. // The index of the resources we're taking offline
  1118. //
  1119. DWORD dwResourceIndex = 0;
  1120. //
  1121. // The type cluster object being enumerated returned by the ClusterEnum function
  1122. //
  1123. DWORD dwObjectType = 0;
  1124. //
  1125. // The name of the cluster resource returned by the ClusterEnum function
  1126. //
  1127. LPWSTR lpwszResourceName = NULL;
  1128. //
  1129. // The return code from the call to ClusterEnum
  1130. //
  1131. DWORD dwResultClusterEnum = ERROR_SUCCESS;
  1132. //
  1133. // The size of the buffer (in characters) that is used to hold the resource name's length
  1134. //
  1135. DWORD dwResourceNameBufferLength = INITIAL_RESOURCE_NAME_SIZE;
  1136. //
  1137. // Size of the resource name passed to and returned by the ClusterEnum function
  1138. //
  1139. DWORD dwClusterEnumResourceNameLength = dwResourceNameBufferLength;
  1140. BOOL iClusDependsOnIISServices = FALSE;
  1141. //
  1142. // Open the cluster
  1143. //
  1144. if ( !(hCluster = OpenCluster(NULL)) )
  1145. {
  1146. dwError = GetLastError();
  1147. // This will fail with RPC_S_SERVER_UNAVAILABLE "The RPC server is unavailable" if there is no cluster on this system
  1148. if (hCluster == NULL)
  1149. {
  1150. if ( (dwError != RPC_S_SERVER_UNAVAILABLE) &&
  1151. (dwError != EPT_S_NOT_REGISTERED ) )
  1152. {
  1153. iisDebugOut((LOG_TYPE_ERROR, _T("BringALLIISClusterResourcesOnline:OpenCluster failed err=0x%x.\n"),dwError));
  1154. }
  1155. }
  1156. else
  1157. {
  1158. iisDebugOut((LOG_TYPE_ERROR, _T("BringALLIISClusterResourcesOnline:OpenCluster failed err=0x%x.\n"),dwError));
  1159. }
  1160. goto clean_up;
  1161. }
  1162. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("BringALLIISClusterResourcesOnline:end.ret=0x%x\n"),dwError));
  1163. //
  1164. // Get Enumerator for the cluster resouces
  1165. //
  1166. if ( !(hClusResEnum = ClusterOpenEnum( hCluster, CLUSTER_ENUM_RESOURCE )) )
  1167. {
  1168. dwError = GetLastError();
  1169. iisDebugOut((LOG_TYPE_ERROR, _T("BringALLIISClusterResourcesOnline:ClusterOpenEnum failed err=0x%x.\n"),dwError));
  1170. goto clean_up;
  1171. }
  1172. //
  1173. // Enumerate the Resources in the cluster
  1174. //
  1175. //
  1176. // Allocate memory to hold the cluster resource name as we enumerate the resources
  1177. //
  1178. if ( !(lpwszResourceName = (LPWSTR) LocalAlloc(LPTR, dwResourceNameBufferLength * sizeof(WCHAR))) )
  1179. {
  1180. dwError = GetLastError();
  1181. iisDebugOut((LOG_TYPE_ERROR, _T("BringALLIISClusterResourcesOnline:LocalAlloc failed err=0x%x.\n"),dwError));
  1182. goto clean_up;
  1183. }
  1184. //
  1185. // Enumerate all of the resources in the cluster and take the IIS Server Instance's offline
  1186. //
  1187. while( ERROR_NO_MORE_ITEMS !=
  1188. (dwResultClusterEnum = ClusterEnum(hClusResEnum,
  1189. dwResourceIndex,
  1190. &dwObjectType,
  1191. lpwszResourceName,
  1192. &dwClusterEnumResourceNameLength )) )
  1193. {
  1194. //
  1195. // If we have a resource's name
  1196. //
  1197. if( ERROR_SUCCESS == dwResultClusterEnum )
  1198. {
  1199. if ( !(hResource = OpenClusterResource( hCluster, lpwszResourceName )) )
  1200. {
  1201. dwError = GetLastError();
  1202. break;
  1203. }
  1204. // If the resource type is "IIS Server Instance", or some other one that is
  1205. // dependent upon the iis services, then we probably stopped, it.
  1206. iClusDependsOnIISServices = CheckForIISDependentClusters(hResource);
  1207. if (iClusDependsOnIISServices)
  1208. {
  1209. CLUSTER_RESOURCE_STATE TheState = GetClusterResourceState(hResource,NULL,0,NULL,0);
  1210. if (TheState == ClusterResourceOffline || TheState == ClusterResourceOfflinePending)
  1211. {
  1212. int iRestart = FALSE;
  1213. LPWSTR lpwsResourceName = NULL;
  1214. HKEY hKey;
  1215. if ( hKey = GetClusterResourceKey( hResource, KEY_READ ) )
  1216. {
  1217. //
  1218. // Get the resource name.
  1219. //
  1220. lpwsResourceName = GetParameter( hKey, L"Name" );
  1221. if ( lpwsResourceName != NULL )
  1222. {
  1223. iRestart = ListOfClusResources_Check(lpwsResourceName);
  1224. }
  1225. ClusterRegCloseKey(hKey);
  1226. }
  1227. if (TRUE == iRestart)
  1228. {
  1229. iisDebugOut((LOG_TYPE_TRACE, _T("OnlineClusterResource:'%s'.\n"),lpwsResourceName));
  1230. OnlineClusterResource(hResource);
  1231. if (lpwsResourceName){LocalFree((LPWSTR) lpwsResourceName);}
  1232. }
  1233. }
  1234. }
  1235. CloseClusterResource( hResource );
  1236. dwResourceIndex++;
  1237. }
  1238. //
  1239. // If the buffer wasn't large enough then retry with a larger buffer
  1240. //
  1241. if( ERROR_MORE_DATA == dwResultClusterEnum )
  1242. {
  1243. //
  1244. // Set the buffer size to the required size reallocate the buffer
  1245. //
  1246. LPWSTR lpwszResourceNameTmp = lpwszResourceName;
  1247. //
  1248. // After returning from ClusterEnum dwClusterEnumResourceNameLength
  1249. // doesn't include the null terminator character
  1250. //
  1251. dwResourceNameBufferLength = dwClusterEnumResourceNameLength + 1;
  1252. if ( !(lpwszResourceName =
  1253. (LPWSTR) LocalReAlloc (lpwszResourceName, dwResourceNameBufferLength * sizeof(WCHAR), 0)) )
  1254. {
  1255. dwError = GetLastError();
  1256. LocalFree( lpwszResourceNameTmp );
  1257. lpwszResourceNameTmp = NULL;
  1258. break;
  1259. }
  1260. }
  1261. //
  1262. // Reset dwResourceNameLength with the size of the number of characters in the buffer
  1263. // You have to do this because everytime you call ClusterEnum is sets your buffer length
  1264. // argument to the number of characters in the string it's returning.
  1265. //
  1266. dwClusterEnumResourceNameLength = dwResourceNameBufferLength;
  1267. }
  1268. clean_up:
  1269. if ( lpwszResourceName )
  1270. {
  1271. LocalFree( lpwszResourceName );
  1272. lpwszResourceName = NULL;
  1273. }
  1274. if ( hClusResEnum )
  1275. {
  1276. ClusterCloseEnum( hClusResEnum );
  1277. hClusResEnum = NULL;
  1278. }
  1279. if ( hCluster )
  1280. {
  1281. CloseCluster( hCluster );
  1282. hCluster = NULL;
  1283. }
  1284. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("BringALLIISClusterResourcesOnline:end.ret=0x%x\n"),dwError));
  1285. return dwError;
  1286. }
  1287. LPWSTR GetParameter(
  1288. IN HKEY ClusterKey,
  1289. IN LPCWSTR ValueName
  1290. )
  1291. /*++
  1292. Routine Description:
  1293. Reads a REG_SZ parameter from the cluster regitry, and allocates the
  1294. necessary storage for it.
  1295. Arguments:
  1296. ClusterKey - supplies the cluster key where the parameter is stored.
  1297. ValueName - supplies the name of the value.
  1298. Return Value:
  1299. A pointer to a buffer containing the parameter value on success.
  1300. NULL on failure.
  1301. --*/
  1302. {
  1303. LPWSTR value = NULL;
  1304. DWORD valueLength;
  1305. DWORD valueType;
  1306. DWORD status;
  1307. valueLength = 0;
  1308. status = ClusterRegQueryValue( ClusterKey,ValueName,&valueType,NULL,&valueLength );
  1309. if ( (status != ERROR_SUCCESS) && (status != ERROR_MORE_DATA) )
  1310. {
  1311. SetLastError(status);
  1312. return(NULL);
  1313. }
  1314. if ( valueType == REG_SZ )
  1315. {
  1316. valueLength += sizeof(UNICODE_NULL);
  1317. }
  1318. value = (LPWSTR) LocalAlloc(LMEM_FIXED, valueLength);
  1319. if ( value == NULL )
  1320. {return(NULL);}
  1321. status = ClusterRegQueryValue(ClusterKey,ValueName,&valueType,(LPBYTE)value,&valueLength);
  1322. if ( status != ERROR_SUCCESS)
  1323. {
  1324. LocalFree(value);
  1325. SetLastError(status);
  1326. value = NULL;
  1327. }
  1328. return(value);
  1329. }
  1330. INT CheckForIISDependentClusters(HRESOURCE hResource)
  1331. {
  1332. INT iReturn = FALSE;
  1333. // If the resource type is "IIS Server Instance",
  1334. // "SMTP Server Instance" or "NNTP Server Instance" then take it offline
  1335. iReturn = ResUtilResourceTypesEqual(IIS_RESOURCE_TYPE_NAME, hResource);
  1336. if (!iReturn){iReturn = ResUtilResourceTypesEqual(SMTP_RESOURCE_TYPE_NAME, hResource);}
  1337. if (!iReturn){iReturn = ResUtilResourceTypesEqual(NNTP_RESOURCE_TYPE_NAME, hResource);}
  1338. // check for other ones which might be listed in the inf file!
  1339. if (!iReturn && g_pTheApp->m_hInfHandle)
  1340. {
  1341. CStringList strList;
  1342. CString csTheSection = _T("ClusterResType_DependsonIIS");
  1343. if (GetSectionNameToDo(g_pTheApp->m_hInfHandle, csTheSection))
  1344. {
  1345. if (ERROR_SUCCESS == FillStrListWithListOfSections(g_pTheApp->m_hInfHandle, strList, csTheSection))
  1346. {
  1347. // loop thru the list returned back
  1348. if (strList.IsEmpty() == FALSE)
  1349. {
  1350. POSITION pos;
  1351. CString csEntry;
  1352. pos = strList.GetHeadPosition();
  1353. while (pos)
  1354. {
  1355. csEntry = strList.GetAt(pos);
  1356. int iTempReturn = FALSE;
  1357. iTempReturn = ResUtilResourceTypesEqual(csEntry, hResource);
  1358. if (iTempReturn)
  1359. {
  1360. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("CheckForIISDependentClusters:yes='%s'\n"),csEntry));
  1361. iReturn = TRUE;
  1362. break;
  1363. }
  1364. strList.GetNext(pos);
  1365. }
  1366. }
  1367. }
  1368. }
  1369. }
  1370. return iReturn;
  1371. }
  1372. DWORD WINAPI DoesThisServiceTypeExistInCluster(PVOID pInfo)
  1373. {
  1374. INT iTemp = FALSE;
  1375. CLUSTER_SVC_INFO_FILL_STRUCT * pMyStructOfInfo;
  1376. pMyStructOfInfo = (CLUSTER_SVC_INFO_FILL_STRUCT *) pInfo;
  1377. //pMyStructOfInfo->szTheClusterName
  1378. //pMyStructOfInfo->pszTheServiceType
  1379. //pMyStructOfInfo->csTheReturnServiceResName
  1380. //pMyStructOfInfo->dwReturnStatus
  1381. //
  1382. // The return code
  1383. //
  1384. DWORD dwReturn = ERROR_NOT_FOUND;
  1385. pMyStructOfInfo->dwReturnStatus = dwReturn;
  1386. //
  1387. // Handle for the cluster
  1388. //
  1389. HCLUSTER hCluster = NULL;
  1390. //
  1391. // Handle for the cluster enumerator
  1392. //
  1393. HCLUSENUM hClusResEnum = NULL;
  1394. //
  1395. // Handle to a resource
  1396. //
  1397. HRESOURCE hResource = NULL;
  1398. //
  1399. // The index of the resources we're taking offline
  1400. //
  1401. DWORD dwResourceIndex = 0;
  1402. //
  1403. // The type cluster object being enumerated returned by the ClusterEnum function
  1404. //
  1405. DWORD dwObjectType = 0;
  1406. //
  1407. // The name of the cluster resource returned by the ClusterEnum function
  1408. //
  1409. LPWSTR lpwszResourceName = NULL;
  1410. //
  1411. // The return code from the call to ClusterEnum
  1412. //
  1413. DWORD dwResultClusterEnum = ERROR_SUCCESS;
  1414. //
  1415. // The size of the buffer (in characters) that is used to hold the resource name's length
  1416. //
  1417. DWORD dwResourceNameBufferLength = INITIAL_RESOURCE_NAME_SIZE;
  1418. //
  1419. // Size of the resource name passed to and returned by the ClusterEnum function
  1420. //
  1421. DWORD dwClusterEnumResourceNameLength = dwResourceNameBufferLength;
  1422. //
  1423. // Open the cluster
  1424. //
  1425. hCluster = OpenCluster(pMyStructOfInfo->szTheClusterName);
  1426. if( !hCluster )
  1427. {
  1428. dwReturn = GetLastError();
  1429. goto DoesThisServiceTypeExistInCluster_Exit;
  1430. }
  1431. //
  1432. // Get Enumerator for the cluster resouces
  1433. //
  1434. if ( !(hClusResEnum = ClusterOpenEnum( hCluster, CLUSTER_ENUM_RESOURCE )) )
  1435. {
  1436. dwReturn = GetLastError();
  1437. goto DoesThisServiceTypeExistInCluster_Exit;
  1438. }
  1439. //
  1440. // Enumerate the Resources in the cluster
  1441. //
  1442. //
  1443. // Allocate memory to hold the cluster resource name as we enumerate the resources
  1444. //
  1445. if ( !(lpwszResourceName = (LPWSTR) LocalAlloc(LPTR, dwResourceNameBufferLength * sizeof(WCHAR))) )
  1446. {
  1447. dwReturn = GetLastError();
  1448. goto DoesThisServiceTypeExistInCluster_Exit;
  1449. }
  1450. //
  1451. // Enumerate all of the resources in the cluster
  1452. //
  1453. while( ERROR_NO_MORE_ITEMS != (dwResultClusterEnum = ClusterEnum(hClusResEnum,dwResourceIndex,&dwObjectType,lpwszResourceName,&dwClusterEnumResourceNameLength)) )
  1454. {
  1455. //
  1456. // If we have a resource's name
  1457. //
  1458. if( ERROR_SUCCESS == dwResultClusterEnum )
  1459. {
  1460. if ( !(hResource = OpenClusterResource( hCluster, lpwszResourceName )) )
  1461. {
  1462. dwReturn = GetLastError();
  1463. break;
  1464. }
  1465. // If the resource type is "IIS Server Instance", or one that depends upon iis like smtp or nntp then
  1466. // check further to see if they have our services (W3SVC or MSFTPSVC)
  1467. iTemp = ResUtilResourceTypesEqual(IIS_RESOURCE_TYPE_NAME, hResource);
  1468. if (!iTemp){iTemp = ResUtilResourceTypesEqual(SMTP_RESOURCE_TYPE_NAME, hResource);}
  1469. if (!iTemp){iTemp = ResUtilResourceTypesEqual(NNTP_RESOURCE_TYPE_NAME, hResource);}
  1470. if (TRUE == iTemp)
  1471. {
  1472. // if the resource hangs it will hang on this call
  1473. pMyStructOfInfo->dwReturnStatus = ERROR_INVALID_BLOCK;
  1474. if (ERROR_SUCCESS == IsResourceThisTypeOfService(hResource, pMyStructOfInfo->pszTheServiceType))
  1475. {
  1476. CString csResName;
  1477. //
  1478. // Yes! we found it
  1479. //
  1480. dwReturn = ERROR_SUCCESS;
  1481. // Display the resource name for fun
  1482. if (TRUE == GetClusterResName(hResource, &csResName))
  1483. {
  1484. // copy it to the return string
  1485. *pMyStructOfInfo->csTheReturnServiceResName = csResName;
  1486. }
  1487. CloseClusterResource( hResource );
  1488. goto DoesThisServiceTypeExistInCluster_Exit;
  1489. }
  1490. dwReturn = ERROR_NOT_FOUND;
  1491. CloseClusterResource( hResource );
  1492. }
  1493. dwResourceIndex++;
  1494. }
  1495. //
  1496. // If the buffer wasn't large enough then retry with a larger buffer
  1497. //
  1498. if( ERROR_MORE_DATA == dwResultClusterEnum )
  1499. {
  1500. //
  1501. // Set the buffer size to the required size reallocate the buffer
  1502. //
  1503. LPWSTR lpwszResourceNameTmp = lpwszResourceName;
  1504. //
  1505. // After returning from ClusterEnum dwClusterEnumResourceNameLength
  1506. // doesn't include the null terminator character
  1507. //
  1508. dwResourceNameBufferLength = dwClusterEnumResourceNameLength + 1;
  1509. if ( !(lpwszResourceName =
  1510. (LPWSTR) LocalReAlloc (lpwszResourceName, dwResourceNameBufferLength * sizeof(WCHAR), 0)) )
  1511. {
  1512. dwReturn = GetLastError();
  1513. LocalFree( lpwszResourceNameTmp );
  1514. lpwszResourceNameTmp = NULL;
  1515. break;
  1516. }
  1517. }
  1518. //
  1519. // Reset dwResourceNameLength with the size of the number of characters in the buffer
  1520. // You have to do this because everytime you call ClusterEnum is sets your buffer length
  1521. // argument to the number of characters in the string it's returning.
  1522. //
  1523. dwClusterEnumResourceNameLength = dwResourceNameBufferLength;
  1524. }
  1525. DoesThisServiceTypeExistInCluster_Exit:
  1526. if ( lpwszResourceName )
  1527. {
  1528. LocalFree( lpwszResourceName );
  1529. lpwszResourceName = NULL;
  1530. }
  1531. if ( hClusResEnum )
  1532. {
  1533. ClusterCloseEnum( hClusResEnum );
  1534. hClusResEnum = NULL;
  1535. }
  1536. if ( hCluster )
  1537. {
  1538. CloseCluster( hCluster );
  1539. hCluster = NULL;
  1540. }
  1541. pMyStructOfInfo->dwReturnStatus = dwReturn;
  1542. return dwReturn;
  1543. }
  1544. DWORD IsResourceThisTypeOfService(HRESOURCE hResource, LPWSTR pszTheServiceType)
  1545. {
  1546. DWORD dwReturn = ERROR_NOT_FOUND;
  1547. HINSTANCE hClusapi = NULL;
  1548. HINSTANCE hResutils = NULL;
  1549. PFN_CLUSTERRESOURCECONTROL pfnClusterResourceControl;
  1550. PFN_RESUTILFINDSZPROPERTY pfnResUtilFindSzProperty;
  1551. //
  1552. // Initial size of the buffer
  1553. //
  1554. DWORD dwBufferSize = 256;
  1555. //
  1556. // The requested buffer size, and the number of bytes actually in the returned buffer
  1557. //
  1558. DWORD dwRequestedBufferSize = dwBufferSize;
  1559. //
  1560. // Result from the call to the cluster resource control function
  1561. //
  1562. DWORD dwResult;
  1563. //
  1564. // Buffer that holds the property list for this resource
  1565. //
  1566. LPVOID lpvPropList = NULL;
  1567. //
  1568. // The Proivate property that is being read
  1569. //
  1570. LPWSTR lpwszPrivateProp = NULL;
  1571. //
  1572. // Load cluster dll's
  1573. //
  1574. hClusapi = LoadLibrary( L"clusapi.dll" );
  1575. if (!hClusapi)
  1576. {
  1577. dwReturn = TYPE_E_CANTLOADLIBRARY;
  1578. goto IsResourceThisTypeOfService_Exit;
  1579. }
  1580. pfnClusterResourceControl = (PFN_CLUSTERRESOURCECONTROL)GetProcAddress( hClusapi, "ClusterResourceControl" );
  1581. if (!pfnClusterResourceControl)
  1582. {
  1583. dwReturn = ERROR_PROC_NOT_FOUND;
  1584. goto IsResourceThisTypeOfService_Exit;
  1585. }
  1586. hResutils = LoadLibrary( L"resutils.dll" );
  1587. if (!hResutils)
  1588. {
  1589. dwReturn = TYPE_E_CANTLOADLIBRARY;
  1590. goto IsResourceThisTypeOfService_Exit;
  1591. }
  1592. pfnResUtilFindSzProperty = (PFN_RESUTILFINDSZPROPERTY)GetProcAddress( hResutils, "ResUtilFindSzProperty" );
  1593. if (!pfnResUtilFindSzProperty)
  1594. {
  1595. dwReturn = ERROR_PROC_NOT_FOUND;
  1596. goto IsResourceThisTypeOfService_Exit;
  1597. }
  1598. //
  1599. // Allocate memory for the resource type
  1600. //
  1601. lpvPropList = (LPWSTR) HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufferSize * sizeof(WCHAR) );
  1602. if( lpvPropList == NULL)
  1603. {
  1604. lpvPropList = NULL;
  1605. dwReturn = E_OUTOFMEMORY;
  1606. goto IsResourceThisTypeOfService_Exit;
  1607. }
  1608. //
  1609. // Allocate memory for the Property
  1610. //
  1611. lpwszPrivateProp = (LPWSTR) HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, (_MAX_PATH+_MAX_PATH+1) * sizeof(WCHAR) );
  1612. if( lpwszPrivateProp == NULL)
  1613. {
  1614. lpvPropList = NULL;
  1615. dwReturn = E_OUTOFMEMORY;
  1616. goto IsResourceThisTypeOfService_Exit;
  1617. }
  1618. //
  1619. // Get the resource's private properties (Service , InstanceId)
  1620. //
  1621. while( 1 )
  1622. {
  1623. dwResult = pfnClusterResourceControl(hResource,NULL,CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES,NULL,0,lpvPropList,dwBufferSize,&dwRequestedBufferSize );
  1624. if( ERROR_SUCCESS == dwResult )
  1625. {
  1626. // ---------------------
  1627. // what the entries are:
  1628. // AccessMask (dword) = 5
  1629. // Alias (string) = "virtual dir name"
  1630. // Directory (string) = "c:\la\lalalala"
  1631. // ServiceName (string) = W3SVC, MSFTPSVC, GOPHERSVC
  1632. // ---------------------
  1633. //
  1634. // Get the "ServiceName" entry
  1635. //
  1636. dwResult = pfnResUtilFindSzProperty( lpvPropList, &dwRequestedBufferSize, L"ServiceName", &lpwszPrivateProp);
  1637. if( dwResult != ERROR_SUCCESS )
  1638. {
  1639. dwReturn = dwResult;
  1640. goto IsResourceThisTypeOfService_Exit;
  1641. }
  1642. if (_wcsicmp(lpwszPrivateProp, pszTheServiceType) == 0)
  1643. {
  1644. // Okay, we found at least 1 service name that matches
  1645. // the one that was passed -- which we're supposed to look for
  1646. // return success
  1647. dwReturn = ERROR_SUCCESS;
  1648. }
  1649. goto IsResourceThisTypeOfService_Exit;
  1650. }
  1651. if( ERROR_MORE_DATA == dwResult )
  1652. {
  1653. //
  1654. // Set the buffer size to the required size reallocate the buffer
  1655. //
  1656. dwBufferSize = ++dwRequestedBufferSize;
  1657. lpvPropList = (LPWSTR) HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY | HEAP_NO_SERIALIZE, lpvPropList, dwBufferSize * sizeof(WCHAR) );
  1658. if ( lpvPropList == NULL)
  1659. {
  1660. dwReturn = E_OUTOFMEMORY;
  1661. goto IsResourceThisTypeOfService_Exit;
  1662. }
  1663. }
  1664. }
  1665. IsResourceThisTypeOfService_Exit:
  1666. if (lpwszPrivateProp)
  1667. {HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, lpwszPrivateProp);}
  1668. if (lpvPropList)
  1669. {HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, lpvPropList);}
  1670. if (hClusapi)
  1671. {FreeLibrary(hClusapi);}
  1672. if (hResutils)
  1673. {FreeLibrary(hClusapi);}
  1674. return dwReturn;
  1675. }
  1676. INT GetClusterResName(HRESOURCE hResource, CString * csReturnedName)
  1677. {
  1678. int iReturn = FALSE;
  1679. HKEY hKey;
  1680. if ( hKey = GetClusterResourceKey( hResource, KEY_READ ) )
  1681. {
  1682. //
  1683. // Get the resource name.
  1684. //
  1685. LPWSTR lpwsResourceName = NULL;
  1686. lpwsResourceName = GetParameter( hKey, L"Name" );
  1687. if ( lpwsResourceName != NULL )
  1688. {
  1689. //wcscpy(csReturnedName,lpwsResourceName);
  1690. *csReturnedName = lpwsResourceName;
  1691. iReturn = TRUE;
  1692. }
  1693. if (lpwsResourceName){LocalFree((LPWSTR) lpwsResourceName);}
  1694. ClusterRegCloseKey(hKey);
  1695. }
  1696. return iReturn;
  1697. }
  1698. INT DoClusterServiceCheck(CLUSTER_SVC_INFO_FILL_STRUCT * pMyStructOfInfo)
  1699. {
  1700. int iReturn = FALSE;
  1701. DWORD ThreadID = 0;
  1702. DWORD status = 0;
  1703. HANDLE hMyThread = CreateThread(NULL,0,DoesThisServiceTypeExistInCluster,pMyStructOfInfo,0,&ThreadID);
  1704. if (hMyThread)
  1705. {
  1706. // wait for 30 secs only
  1707. DWORD res = WaitForSingleObject(hMyThread,30*1000);
  1708. if (res == WAIT_TIMEOUT)
  1709. {
  1710. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ERROR DoClusterServiceCheck thread never finished...\n")));
  1711. GetExitCodeThread(hMyThread, &status);
  1712. if (status == STILL_ACTIVE)
  1713. {
  1714. if (hMyThread != NULL)
  1715. {TerminateThread(hMyThread, 0);}
  1716. }
  1717. }
  1718. else
  1719. {
  1720. GetExitCodeThread(hMyThread, &status);
  1721. if (status == STILL_ACTIVE)
  1722. {
  1723. if (hMyThread != NULL)
  1724. {TerminateThread(hMyThread, 0);}
  1725. }
  1726. else
  1727. {
  1728. if (ERROR_SUCCESS == status)
  1729. {iReturn = TRUE;}
  1730. }
  1731. if (hMyThread != NULL)
  1732. {CloseHandle(hMyThread);}
  1733. }
  1734. }
  1735. return iReturn;
  1736. }
  1737. INT DoesClusterServiceExist(void)
  1738. {
  1739. if (-1 == g_ClusterSVCExist)
  1740. {
  1741. CRegKey regClusSvc(HKEY_LOCAL_MACHINE, scClusterPath2, KEY_READ);
  1742. if ( (HKEY) regClusSvc )
  1743. {
  1744. g_ClusterSVCExist = 1;
  1745. }
  1746. else
  1747. {
  1748. g_ClusterSVCExist = 0;
  1749. }
  1750. }
  1751. return g_ClusterSVCExist;
  1752. }
  1753. #endif //_CHICAGO_