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.

888 lines
21 KiB

  1. /*++
  2. Copyright (c) 1992-1996 Microsoft Corporation
  3. Module Name:
  4. iisutil.c
  5. Abstract:
  6. IIS Resource utility routine DLL
  7. Author:
  8. Pete Benoit (v-pbenoi) 12-SEP-1996
  9. Revision History:
  10. --*/
  11. #include "iisutil.h"
  12. DWORD IISService[] = {
  13. INET_HTTP,
  14. INET_FTP,
  15. INET_GOPHER
  16. };
  17. #define IIS_MNGT_DLLNAME L"infoadmn.dll"
  18. //
  19. // Define some globals used to get iis management routines
  20. //
  21. HINSTANCE iisDLL = NULL;
  22. typedef NET_API_STATUS (NET_API_FUNCTION *INETINFOGETPROC)(LPWSTR,DWORD,LPINET_INFO_CONFIG_INFO *);
  23. typedef NET_API_STATUS (NET_API_FUNCTION *INETINFOSETPROC)(LPWSTR,DWORD,LPINET_INFO_CONFIG_INFO);
  24. typedef NET_API_STATUS (NET_API_FUNCTION *INETINFOFLUSHPROC)(LPWSTR,DWORD);
  25. INETINFOGETPROC InetInfoGet = NULL;
  26. INETINFOSETPROC InetInfoSet = NULL;
  27. INETINFOFLUSHPROC InetInfoFlushMemory = NULL;
  28. DWORD
  29. IsIISMngtDllLoaded(
  30. )
  31. /*++
  32. Routine Description:
  33. Checks to see if the IIS mngt dll loaded
  34. Arguments:
  35. Return Value:
  36. ERROR_SUCCESS - Successfully loaded and found
  37. A Win32 error code on failure.
  38. --*/
  39. {
  40. if (iisDLL != NULL) {
  41. return(ERROR_SUCCESS);
  42. }
  43. return(ERROR_SERVICE_NOT_ACTIVE);
  44. }
  45. DWORD
  46. IISLoadMngtDll(
  47. )
  48. /*++
  49. Routine Description:
  50. This routine tries to load the iis management dll. Then it attempts to
  51. find the procedures required to manage it.
  52. Arguments:
  53. Return Value:
  54. ERROR_SUCCESS - Successfully loaded and found
  55. A Win32 error code on failure.
  56. --*/
  57. {
  58. DWORD status;
  59. //
  60. // Try and load the IIS Mngt dll
  61. //
  62. iisDLL = LoadLibrary( IIS_MNGT_DLLNAME );
  63. if (iisDLL == NULL) {
  64. return(GetLastError());
  65. }
  66. //
  67. // Try to locate the management routines
  68. //
  69. InetInfoGet = (INETINFOGETPROC)GetProcAddress(iisDLL,"InetInfoGetAdminInformation");
  70. if (InetInfoGet == NULL) {
  71. status = GetLastError();
  72. goto error_exit;
  73. }
  74. InetInfoSet = (INETINFOSETPROC)GetProcAddress(iisDLL,"InetInfoSetAdminInformation");
  75. if (InetInfoGet == NULL) {
  76. status = GetLastError();
  77. goto error_exit;
  78. }
  79. InetInfoFlushMemory = (INETINFOFLUSHPROC)GetProcAddress(iisDLL,"InetInfoFlushMemoryCache");
  80. if (InetInfoFlushMemory == NULL) {
  81. status = GetLastError();
  82. goto error_exit;
  83. }
  84. return(ERROR_SUCCESS);
  85. error_exit:
  86. IISUnloadMngtDll();
  87. return(status);
  88. } // END IsIISInstalled
  89. VOID
  90. IISUnloadMngtDll(
  91. )
  92. /*++
  93. Routine Description:
  94. This routine frees the IIS management DLL
  95. Arguments:
  96. Return Value:
  97. --*/
  98. {
  99. if (iisDLL != NULL) {
  100. FreeLibrary( iisDLL);
  101. }
  102. iisDLL = NULL;
  103. InetInfoGet = NULL;
  104. InetInfoSet = NULL;
  105. InetInfoFlushMemory = NULL;
  106. }
  107. DWORD
  108. GetIISInfo(
  109. IN DWORD ServiceType,
  110. OUT LPINET_INFO_CONFIG_INFO *IISInfo
  111. )
  112. /*++
  113. Routine Description:
  114. Get IIS information. This call returns a pointer
  115. to an INET_INFO_CONFIG_INFO structure
  116. Arguments:
  117. ServiceType - The type of service
  118. IISInfo - return a pointer to an INET_INFO_CONFIG_INFO structure. This
  119. structure contains the virtual root information
  120. Return Value:
  121. NET_API_STATUS
  122. --*/
  123. {
  124. DWORD Status;
  125. if (InetInfoGet == NULL) {
  126. return(ERROR_SERVICE_NOT_ACTIVE);
  127. }
  128. Status=InetInfoGet(NULL,IISService[ServiceType],IISInfo);
  129. return(Status);
  130. } // END GetIISInfo
  131. DWORD
  132. SetIISInfo(
  133. IN DWORD ServiceType,
  134. IN LPINET_INFO_CONFIG_INFO IISInfo
  135. )
  136. /*++
  137. Routine Description:
  138. Set IIS information. This call sets inet config infor using the
  139. INET_INFO_CONFIG_INFO structure
  140. Arguments:
  141. ServiceType - The type of service
  142. IISInfo - pointer to an INET_INFO_CONFIG_INFO structure. This structure
  143. contains the virtual root information
  144. Return Value:
  145. ERROR_SUCCESS
  146. NET ERROR Status
  147. --*/
  148. {
  149. DWORD Status;
  150. if ((InetInfoSet == NULL) || (InetInfoFlushMemory == NULL)) {
  151. return(ERROR_SERVICE_NOT_ACTIVE);
  152. }
  153. //
  154. // Only set the VirtualRoots
  155. //
  156. IISInfo->FieldControl = FC_INET_INFO_VIRTUAL_ROOTS;
  157. Status=InetInfoSet(NULL,IISService[ServiceType],IISInfo);
  158. if (Status != ERROR_SUCCESS) {
  159. return(Status);
  160. }
  161. //
  162. // If we sucessfully set the virtual root information
  163. // flush the memory cache
  164. //
  165. Status = InetInfoFlushMemory(NULL,IISService[ServiceType]);
  166. return(Status);
  167. } // END SetIISInfo
  168. DWORD
  169. OffLineVirtualRoot(
  170. IN LPIIS_RESOURCE ResourceEntry,
  171. IN PLOG_EVENT_ROUTINE LogEvent
  172. )
  173. /*++
  174. Routine Description:
  175. Take offline all Virtual Roots for this resource
  176. Arguments:
  177. ResourceEntry - The resource that contains a list of virtual roots
  178. Return Value:
  179. ERROR_SUCCESS
  180. W32 error code
  181. --*/
  182. {
  183. LPINET_INFO_CONFIG_INFO IISInfo = NULL;
  184. LPINET_INFO_VIRTUAL_ROOT_LIST tmpVRL = NULL;
  185. LPINET_INFO_VIRTUAL_ROOT_LIST iisVRL = NULL;
  186. LPINET_INFO_VIRTUAL_ROOT_ENTRY resVR = NULL;
  187. DWORD Status = ERROR_SUCCESS;
  188. DWORD i,c;
  189. BOOLEAN MatchFound;
  190. DWORD MatchingEntries = 0;
  191. //
  192. // Call IIS Management API to GET list of Virtual Roots
  193. //
  194. Status = GetIISInfo(ResourceEntry->ServiceType, &IISInfo);
  195. if (Status != ERROR_SUCCESS) {
  196. goto error_exit;
  197. }
  198. //
  199. // For Robustness check to see if the IIS returned SUCCESS but
  200. // did not return a valid address
  201. //
  202. if (IISInfo == NULL) {
  203. (LogEvent)(
  204. ResourceEntry->ResourceHandle,
  205. LOG_ERROR,
  206. L"Error [OffLineVirtualRoots] Get IIS information returned NULL\n");
  207. Status = ERROR_RESOURCE_NOT_FOUND;
  208. goto error_exit;
  209. }
  210. //
  211. // Save pointer to original VirtualRoot Structure
  212. //
  213. iisVRL = IISInfo->VirtualRoots;
  214. resVR = ResourceEntry->VirtualRoot;
  215. //
  216. // If the caller called terminate after open BUT before online
  217. // the VR field of the resource could be NULL. Return so we don't accvio
  218. //
  219. if (resVR == NULL) {
  220. (LogEvent)(
  221. ResourceEntry->ResourceHandle,
  222. LOG_ERROR,
  223. L"Error [OffLineVirtualRoots] Resource VR information is NULL\n");
  224. Status = ERROR_RESOURCE_NOT_FOUND;
  225. goto error_exit;
  226. }
  227. //
  228. // This is a sanity check
  229. //
  230. if ( (resVR->pszRoot == NULL) ||
  231. (resVR->pszAddress == NULL) ||
  232. (resVR->pszDirectory == NULL) ) {
  233. (LogEvent)(
  234. ResourceEntry->ResourceHandle,
  235. LOG_ERROR,
  236. L"Error [OffLineVirtualRoots] Resource has NULL entries for root , addr or directory\n");
  237. Status = ERROR_RESOURCE_NOT_FOUND;
  238. goto error_exit;
  239. }
  240. //
  241. // Allocate storage to Filter out Virtual Roots managed by the Cluster
  242. //
  243. tmpVRL = LocalAlloc(LPTR,
  244. ( (iisVRL->cEntries + 1) *
  245. sizeof(INET_INFO_VIRTUAL_ROOT_ENTRY) ) +
  246. sizeof(INET_INFO_VIRTUAL_ROOT_LIST));
  247. //
  248. // Check to see we got a valid address
  249. //
  250. if (tmpVRL == NULL) {
  251. (LogEvent)(
  252. ResourceEntry->ResourceHandle,
  253. LOG_ERROR,
  254. L"Error [OffLineVirtualRoots] Allocation of TMP VR failed\n");
  255. Status = ERROR_RESOURCE_NOT_FOUND;
  256. goto error_exit;
  257. }
  258. //
  259. // This is so ugly ...
  260. // 1. Enumerate and compare each IIS VR KEY with the resource VR
  261. // 2. Add ones that don't match to the tmpVR
  262. // 3. Use the tmpVR to update the IIS service and mask resources entries
  263. tmpVRL->cEntries = 0;
  264. for (i=0;i<iisVRL->cEntries ;i++ ) {
  265. MatchFound = FALSE;
  266. if ( (_wcsicmp(iisVRL->aVirtRootEntry[i].pszRoot,resVR->pszRoot) == 0) &&
  267. (_wcsicmp(iisVRL->aVirtRootEntry[i].pszAddress,resVR->pszAddress) == 0)
  268. // (_wcsicmp(iisVRL->aVirtRootEntry[i].pszDirectory,resVR->pszDirectory) == 0)
  269. ){
  270. // if all the VR primary keys match then skip this entry
  271. MatchFound = TRUE;
  272. MatchingEntries +=1;
  273. } // END if
  274. // No matching entry found in the Cluster config data so this VR is ok
  275. if (!MatchFound) {
  276. tmpVRL->aVirtRootEntry[tmpVRL->cEntries++] = iisVRL->aVirtRootEntry[i];
  277. } // END if !MatchFound
  278. } // END for i=0
  279. IISInfo->VirtualRoots = tmpVRL;
  280. //
  281. // Call IIS Management API to SET list of Virtual Roots
  282. // But only call this if we have something to remove
  283. //
  284. if (MatchingEntries > 0) {
  285. Status = SetIISInfo(ResourceEntry->ServiceType, IISInfo);
  286. }
  287. // Destruct any temporary storage
  288. IISInfo->VirtualRoots = iisVRL;
  289. error_exit:
  290. if (IISInfo != NULL) MIDL_user_free((LPVOID)IISInfo);
  291. if (tmpVRL != NULL) LocalFree(tmpVRL);
  292. return(Status);
  293. } //OfflineVirtualRoot
  294. DWORD
  295. OnLineVirtualRoot(
  296. IN LPIIS_RESOURCE ResourceEntry,
  297. IN PLOG_EVENT_ROUTINE LogEvent
  298. )
  299. /*++
  300. Routine Description:
  301. Add this resources Virtual Root to the IIS
  302. Arguments:
  303. ResourceEntry - The resource that contains a list of virtual roots
  304. Return Value:
  305. ERROR_SUCCESS
  306. W32 error code
  307. --*/
  308. {
  309. LPINET_INFO_CONFIG_INFO IISInfo = NULL;
  310. LPINET_INFO_VIRTUAL_ROOT_LIST tmpVRL = NULL;
  311. LPINET_INFO_VIRTUAL_ROOT_LIST iisVRL = NULL;
  312. LPINET_INFO_VIRTUAL_ROOT_ENTRY resVR = NULL;
  313. DWORD Status = ERROR_SUCCESS;
  314. DWORD i,c;
  315. BOOLEAN MatchFound;
  316. // Call IIS Management API to GET list of Virtual Roots
  317. Status = GetIISInfo(ResourceEntry->ServiceType, &IISInfo);
  318. if (Status != ERROR_SUCCESS) {
  319. (LogEvent)(
  320. ResourceEntry->ResourceHandle,
  321. LOG_ERROR,
  322. L"Error [OnLineVirtualRoots] Get IIS information call failed status = %1!u! \n",
  323. Status);
  324. goto error_exit;
  325. }
  326. // Save pointer to original VirtualRoot Structure
  327. iisVRL = IISInfo->VirtualRoots;
  328. resVR = ResourceEntry->VirtualRoot;
  329. // Add Virtual Roots managed by the resource
  330. if (resVR == NULL) {
  331. (LogEvent)(
  332. ResourceEntry->ResourceHandle,
  333. LOG_ERROR,
  334. L"Error [OnLineVirtualRoots] NULL virtual root entry \n");
  335. Status = ERROR_RESOURCE_NOT_FOUND;
  336. goto error_exit;
  337. }
  338. //
  339. // See if the resource is already on line. In which
  340. // case this is a duplicate
  341. //
  342. if ( VerifyIISService( ResourceEntry,FALSE,LogEvent ) ) {
  343. // We found a duplicate or this resource is already online
  344. (LogEvent)(
  345. ResourceEntry->ResourceHandle,
  346. LOG_INFORMATION,
  347. L"Warning [OnLineThread] Resource already online or is a duplicate. Check for Unique Alias property\n");
  348. // Status = ERROR_DUP_NAME;
  349. Status = ERROR_SUCCESS;
  350. goto error_exit;
  351. }
  352. #if DBG
  353. (LogEvent)(
  354. ResourceEntry->ResourceHandle,
  355. LOG_INFORMATION,
  356. L"[OnLineVirtualRoots] about to set info Root = %1!ws! ip = %2!ws! Dir = %3!ws! Mask = %4!u! Name = %5!ws! Pass = %6!ws! \n",
  357. resVR->pszRoot,
  358. resVR->pszAddress,
  359. resVR->pszDirectory,
  360. resVR->dwMask,
  361. resVR->pszAccountName,
  362. resVR->AccountPassword);
  363. #endif
  364. // Allocate temporary storage for cluster and iis vr entries
  365. tmpVRL = LocalAlloc(LPTR,
  366. ((iisVRL->cEntries + 1) *
  367. sizeof(INET_INFO_VIRTUAL_ROOT_ENTRY) ) +
  368. sizeof(INET_INFO_VIRTUAL_ROOT_LIST));
  369. // Make sure we didn't fail on the allocate
  370. if (tmpVRL == NULL){
  371. (LogEvent)(
  372. ResourceEntry->ResourceHandle,
  373. LOG_ERROR,
  374. L"[OnLineVirtualRoots] LocalAlloc for temp VRL failed\n");
  375. Status = ERROR_RESOURCE_NOT_FOUND;
  376. goto error_exit;
  377. }
  378. tmpVRL->aVirtRootEntry[0] = *resVR;
  379. // Add any additional VR not managed by the cluster
  380. for (i=0;i<iisVRL->cEntries ;i++ ) {
  381. tmpVRL->aVirtRootEntry[i+1] = iisVRL->aVirtRootEntry[i];
  382. }
  383. tmpVRL->cEntries = iisVRL->cEntries + 1;
  384. IISInfo->VirtualRoots = tmpVRL;
  385. #if DBG
  386. for (i=0;i < tmpVRL->cEntries ;i++ ) {
  387. (LogEvent)(
  388. ResourceEntry->ResourceHandle,
  389. LOG_INFORMATION,
  390. L"[OnLineVirtualRoots] about to set info Root = %1!ws! Ipaddr = %2!ws! Dir = %3!ws! Mask = %4!u! Name = %5!ws! Pass = %6!ws! \n",
  391. tmpVRL->aVirtRootEntry[i].pszRoot,
  392. tmpVRL->aVirtRootEntry[i].pszAddress,
  393. tmpVRL->aVirtRootEntry[i].pszDirectory,
  394. tmpVRL->aVirtRootEntry[i].dwMask,
  395. tmpVRL->aVirtRootEntry[i].pszAccountName,
  396. tmpVRL->aVirtRootEntry[i].AccountPassword);
  397. }
  398. #endif
  399. // Call IIS Management API to SET list of Virtual Roots
  400. Status = SetIISInfo(ResourceEntry->ServiceType, IISInfo);
  401. if (Status != ERROR_SUCCESS) {
  402. (LogEvent)(
  403. ResourceEntry->ResourceHandle,
  404. LOG_ERROR,
  405. L"[OnLineVirtualRoots] set info status = %1!u!\n",
  406. Status);
  407. } else {
  408. //
  409. // See if root came on line sucessfully
  410. //
  411. if ( !VerifyIISService( ResourceEntry,FALSE,LogEvent ) ) {
  412. //
  413. // The root was sucessfully added to iis but the iis could
  414. // not access the root. Remove it here so the inet manager does
  415. // not contain bad roots
  416. //
  417. OffLineVirtualRoot( ResourceEntry, LogEvent);
  418. (LogEvent)(
  419. ResourceEntry->ResourceHandle,
  420. LOG_ERROR,
  421. L"ERROR [OnLineThread] IIS could not bring resource online. Verify IIS root is accessable. \n");
  422. Status = ERROR_RESOURCE_NOT_AVAILABLE;
  423. } // if !VerifyIISService
  424. } // if status != ERROR_SUCCESS
  425. // Destruct any temporary storage
  426. IISInfo->VirtualRoots = iisVRL;
  427. error_exit:
  428. if (IISInfo != NULL) MIDL_user_free((LPVOID)IISInfo);
  429. if (tmpVRL != NULL) LocalFree(tmpVRL);
  430. return(Status);
  431. } // END OnLineVirtualRoot
  432. VOID
  433. FreeIISResource(
  434. IN LPIIS_RESOURCE ResourceEntry
  435. )
  436. /*++
  437. Routine Description:
  438. Free all the storage for a IIS_RESOURCE
  439. Arguments:
  440. vr - virtual root to free
  441. Return Value:
  442. NONE
  443. --*/
  444. {
  445. if (ResourceEntry != NULL) {
  446. if (ResourceEntry->ParametersKey != NULL ) {
  447. ClusterRegCloseKey( ResourceEntry->ParametersKey );
  448. }
  449. if (ResourceEntry->hResource != NULL ) {
  450. CloseClusterResource( ResourceEntry->hResource );
  451. }
  452. LocalFree( ResourceEntry->Params.ServiceName );
  453. LocalFree( ResourceEntry->Params.Alias );
  454. LocalFree( ResourceEntry->Params.Directory );
  455. if (ResourceEntry->VirtualRoot != NULL) {
  456. DestructVR(ResourceEntry->VirtualRoot);
  457. }
  458. } // ResourceEntry != NULL
  459. } // FreeIISResource
  460. VOID
  461. DestructIISResource(
  462. IN LPIIS_RESOURCE ResourceEntry
  463. )
  464. /*++
  465. Routine Description:
  466. Free all the storage for a ResourceEntry and the ResourceEntry
  467. Arguments:
  468. vr - virtual root to free
  469. Return Value:
  470. NONE
  471. --*/
  472. {
  473. if (ResourceEntry != NULL) {
  474. FreeIISResource(ResourceEntry),
  475. LocalFree(ResourceEntry);
  476. } // ResourceEntry != NULL
  477. } // DestructIISResource
  478. VOID
  479. FreeVR(
  480. IN LPINET_INFO_VIRTUAL_ROOT_ENTRY vr
  481. )
  482. /*++
  483. Routine Description:
  484. Free all the storage for a Virtual Root
  485. Arguments:
  486. vr - virtual root to free
  487. Return Value:
  488. NONE
  489. --*/
  490. {
  491. if (vr == NULL) {
  492. return;
  493. }
  494. if (vr->pszRoot != NULL) {
  495. LocalFree(vr->pszRoot);
  496. }
  497. if (vr->pszAddress != NULL) {
  498. LocalFree(vr->pszAddress);
  499. }
  500. if (vr->pszDirectory != NULL) {
  501. LocalFree(vr->pszDirectory);
  502. }
  503. if (vr->pszAccountName != NULL) {
  504. LocalFree(vr->pszAccountName);
  505. }
  506. }// FreeVR
  507. VOID
  508. DestructVR(
  509. LPINET_INFO_VIRTUAL_ROOT_ENTRY vr
  510. )
  511. /*++
  512. Routine Description:
  513. Free all the storage for a Virtual Root and vr
  514. Arguments:
  515. vr - virtual root to free
  516. Return Value:
  517. NONE
  518. --*/
  519. {
  520. if (vr == NULL) {
  521. return;
  522. }
  523. FreeVR(vr);
  524. LocalFree(vr);
  525. }// DestructVR
  526. BOOL
  527. VerifyIISService(
  528. IN LPIIS_RESOURCE ResourceEntry,
  529. IN BOOL IsAliveFlag,
  530. IN PLOG_EVENT_ROUTINE LogEvent
  531. )
  532. /*++
  533. Routine Description:
  534. Verify that the IIS service is running and that it has virtual roots
  535. contained in the resource
  536. Steps:
  537. 1. Make sure the IIS service is running by calling the mngt API
  538. 2. Verfify that the resources virtual roots are currently in
  539. the running system
  540. 3. Check the dwError field to make sure the VR for the resource is accessable
  541. 4. Sanity check to make sure the resources virtual root was found
  542. Arguments:
  543. Resource - supplies the resource id
  544. IsAliveFlag - says this is an IsAlive call - used only for debug print
  545. Return Value:
  546. TRUE - if service is running and service contains resources virtual roots
  547. FALSE - service is in any other state
  548. --*/
  549. {
  550. DWORD status;
  551. DWORD MatchingEntries = 0;
  552. DWORD VRAccessErrors = 0;
  553. BOOL MatchFound;
  554. LPINET_INFO_CONFIG_INFO IISInfo = NULL;
  555. LPINET_INFO_VIRTUAL_ROOT_ENTRY resVR = NULL;
  556. LPINET_INFO_VIRTUAL_ROOT_LIST iisVRL = NULL;
  557. DWORD c;
  558. BOOL VerifyStatus = TRUE;
  559. //
  560. // Get IIS virtual root information
  561. //
  562. status = GetIISInfo(ResourceEntry->ServiceType, &IISInfo);
  563. //
  564. // Check the error status to see if the service is starting
  565. //
  566. if (status != ERROR_SUCCESS) {
  567. if (status == ERROR_SERVICE_NOT_ACTIVE) {
  568. //
  569. // Service is not active
  570. //
  571. (LogEvent)(
  572. ResourceEntry->ResourceHandle,
  573. LOG_ERROR,
  574. L"IsAlive/LooksAlive ERROR Service NOT active service %1!ws!.\n",
  575. ResourceEntry->Params.ServiceName );
  576. } else {
  577. //
  578. // Some type of error
  579. //
  580. (LogEvent)(
  581. ResourceEntry->ResourceHandle,
  582. LOG_ERROR,
  583. L"IsAlive/LooksAlive ERROR getting information for service %1!ws! status = %2!u!\n",
  584. ResourceEntry->Params.ServiceName,
  585. status);
  586. }
  587. //
  588. // Return false;
  589. //
  590. VerifyStatus = FALSE;
  591. goto error_exit;
  592. }
  593. iisVRL = IISInfo->VirtualRoots;
  594. resVR = ResourceEntry->VirtualRoot;
  595. //
  596. // Now check to see if the Virtual roots for this resource exist in the service
  597. //
  598. MatchFound = FALSE;
  599. for (c=0;c<iisVRL->cEntries ;c++ ) {
  600. if ( (_wcsicmp(resVR->pszRoot,iisVRL->aVirtRootEntry[c].pszRoot) == 0) &&
  601. (_wcsicmp(resVR->pszAddress,iisVRL->aVirtRootEntry[c].pszAddress) == 0)
  602. /// (_wcsicmp(resVR->pszDirectory,iisVRL->aVirtRootEntry[c].pszDirectory) == 0)
  603. ){
  604. //
  605. // if all the VR primary keys match
  606. //
  607. MatchFound = TRUE;
  608. MatchingEntries +=1;
  609. //
  610. // See if the IIS can sucessfully access this virtual root
  611. //
  612. if (iisVRL->aVirtRootEntry[c].dwError != ERROR_SUCCESS) {
  613. VRAccessErrors +=1;
  614. (LogEvent)(
  615. ResourceEntry->ResourceHandle,
  616. LOG_INFORMATION,
  617. L"IsAlive/LooksAlive virtual root %1!ws! IIS Access Error service %2!ws! error = %3!u!\n",
  618. resVR->pszRoot,
  619. ResourceEntry->Params.ServiceName,
  620. iisVRL->aVirtRootEntry[c].dwError);
  621. } // END dwERROR != ERROR_SUCCESS
  622. break;
  623. } // END if
  624. } // END for c=0
  625. // No matching entry found in the Cluster config data so this VR is ok
  626. if (!MatchFound) {
  627. if (IsAliveFlag) {
  628. (LogEvent)(
  629. ResourceEntry->ResourceHandle,
  630. LOG_ERROR,
  631. L"ERROR IsAlive/LooksAlive virtual root %1!ws! not found for service %2!ws!\n",
  632. resVR->pszRoot,
  633. ResourceEntry->Params.ServiceName,
  634. status);
  635. }
  636. VerifyStatus = FALSE;
  637. goto error_exit;
  638. } // END if !MatchFound
  639. //
  640. // Perform sanity check
  641. //
  642. if (MatchingEntries != 1) {
  643. (LogEvent)(
  644. ResourceEntry->ResourceHandle,
  645. LOG_ERROR,
  646. L"ERROR IsAlive/LooksAlive more than one resource is active, service %1!ws!\n",
  647. ResourceEntry->Params.ServiceName);
  648. VerifyStatus = FALSE;
  649. goto error_exit;
  650. }
  651. //
  652. // If the resources virtual root is inaccessable then the resource is offline
  653. //
  654. if (VRAccessErrors != 0) {
  655. VerifyStatus = FALSE;
  656. }
  657. error_exit:
  658. if (IISInfo != NULL) MIDL_user_free((LPVOID)IISInfo);
  659. return(VerifyStatus);
  660. } // VerifyIISService