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.

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