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.

764 lines
20 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1996-1997 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // Iis.cpp
  7. //
  8. // Abstract:
  9. // Implementation of the CIISVirtualRootParamsPage class.
  10. //
  11. // Author:
  12. // Pete Benoit (v-pbenoi) October 16, 1996
  13. // David Potter (davidp) October 17, 1996
  14. //
  15. // Revision History:
  16. //
  17. // Notes:
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include <inetinfo.h>
  22. #include "IISClEx4.h"
  23. #include "Iis.h"
  24. #include "ExtObj.h"
  25. #include "DDxDDv.h"
  26. #include "HelpData.h" // for g_rghelpmap*
  27. #undef DEFINE_GUID
  28. #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
  29. EXTERN_C const GUID name \
  30. = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
  31. #include <iadm.h>
  32. #include <iiscnfgp.h>
  33. #ifdef _DEBUG
  34. #define new DEBUG_NEW
  35. #undef THIS_FILE
  36. static char THIS_FILE[] = __FILE__;
  37. #endif
  38. /////////////////////////////////////////////////////////////////////////////
  39. // CIISVirtualRootParamsPage property page
  40. /////////////////////////////////////////////////////////////////////////////
  41. IMPLEMENT_DYNCREATE(CIISVirtualRootParamsPage, CBasePropertyPage)
  42. /////////////////////////////////////////////////////////////////////////////
  43. // Message Maps
  44. BEGIN_MESSAGE_MAP(CIISVirtualRootParamsPage, CBasePropertyPage)
  45. //{{AFX_MSG_MAP(CIISVirtualRootParamsPage)
  46. ON_CBN_SELCHANGE(IDC_PP_IIS_INSTANCEID, OnChangeRequiredField)
  47. ON_BN_CLICKED(IDC_PP_IIS_FTP, OnChangeServiceType)
  48. ON_BN_CLICKED(IDC_PP_IIS_WWW, OnChangeServiceType)
  49. ON_BN_CLICKED(IDC_PP_REFRESH, OnRefresh)
  50. //}}AFX_MSG_MAP
  51. // TODO: Modify the following lines to represent the data displayed on this page.
  52. END_MESSAGE_MAP()
  53. /////////////////////////////////////////////////////////////////////////////
  54. //++
  55. //
  56. // CIISVirtualRootParamsPage::CIISVirtualRootParamsPage
  57. //
  58. // Routine Description:
  59. // Default constructor.
  60. //
  61. // Arguments:
  62. // None.
  63. //
  64. // Return Value:
  65. // None.
  66. //
  67. //--
  68. /////////////////////////////////////////////////////////////////////////////
  69. CIISVirtualRootParamsPage::CIISVirtualRootParamsPage(void)
  70. : CBasePropertyPage(g_rghelpmapIISParameters)
  71. {
  72. // TODO: Modify the following lines to represent the data displayed on this page.
  73. //{{AFX_DATA_INIT(CIISVirtualRootParamsPage)
  74. m_strInstanceId = _T("");
  75. m_nServerType = SERVER_TYPE_WWW;
  76. //}}AFX_DATA_INIT
  77. m_fReadList = FALSE;
  78. try
  79. {
  80. m_strServiceName = IIS_SVC_NAME_WWW;
  81. } // try
  82. catch (CMemoryException * pme)
  83. {
  84. pme->ReportError();
  85. pme->Delete();
  86. } // catch: CMemoryException
  87. // Setup the property array.
  88. {
  89. m_rgProps[epropServiceName].Set(REGPARAM_IIS_SERVICE_NAME, m_strServiceName, m_strPrevServiceName);
  90. m_rgProps[epropInstanceId].Set(REGPARAM_IIS_INSTANCEID, m_strInstanceId, m_strPrevInstanceId);
  91. } // Setup the property array
  92. m_iddPropertyPage = IDD_PP_IIS_PARAMETERS;
  93. m_iddWizardPage = IDD_WIZ_IIS_PARAMETERS;
  94. m_idcPPTitle = IDC_PP_TITLE;
  95. } //*** CIISVirtualRootParamsPage::CIISVirtualRootParamsPage()
  96. /////////////////////////////////////////////////////////////////////////////
  97. //++
  98. //
  99. // CIISVirtualRootParamsPage::DoDataExchange
  100. //
  101. // Routine Description:
  102. // Do data exchange between the dialog and the class.
  103. //
  104. // Arguments:
  105. // pDX [IN OUT] Data exchange object
  106. //
  107. // Return Value:
  108. // None.
  109. //
  110. //--
  111. /////////////////////////////////////////////////////////////////////////////
  112. void CIISVirtualRootParamsPage::DoDataExchange(CDataExchange * pDX)
  113. {
  114. CString strInstanceId;
  115. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  116. if (!pDX->m_bSaveAndValidate)
  117. {
  118. // Set the service type.
  119. if (m_strServiceName.CompareNoCase(IIS_SVC_NAME_FTP) == 0)
  120. m_nServerType = SERVER_TYPE_FTP;
  121. else if (m_strServiceName.CompareNoCase(IIS_SVC_NAME_WWW) == 0)
  122. m_nServerType = SERVER_TYPE_WWW;
  123. else
  124. m_nServerType = SERVER_TYPE_WWW;
  125. } // if: setting data to dialog
  126. CBasePropertyPage::DoDataExchange(pDX);
  127. // TODO: Modify the following lines to represent the data displayed on this page.
  128. //{{AFX_DATA_MAP(CIISVirtualRootParamsPage)
  129. DDX_Control(pDX, IDC_PP_IIS_INSTANCEID, m_cInstanceId);
  130. DDX_Text(pDX, IDC_PP_IIS_INSTANCEID, m_strInstanceName);
  131. DDX_Control(pDX, IDC_PP_IIS_WWW, m_rbWWW);
  132. DDX_Control(pDX, IDC_PP_IIS_FTP, m_rbFTP);
  133. DDX_Radio(pDX, IDC_PP_IIS_FTP, m_nServerType);
  134. //}}AFX_DATA_MAP
  135. if (pDX->m_bSaveAndValidate)
  136. {
  137. if (!BBackPressed())
  138. {
  139. DDV_RequiredText(pDX, IDC_PP_IIS_INSTANCEID, IDC_PP_IIS_INSTANCEID_LABEL, m_strInstanceName);
  140. } // if: Back button not pressed
  141. m_strInstanceId = NameToMetabaseId( m_nServerType == SERVER_TYPE_WWW, m_strInstanceName );
  142. // Save the type.
  143. if (m_nServerType == SERVER_TYPE_FTP)
  144. m_strServiceName = IIS_SVC_NAME_FTP;
  145. else if (m_nServerType == SERVER_TYPE_WWW)
  146. m_strServiceName = IIS_SVC_NAME_WWW;
  147. else
  148. {
  149. CString strMsg;
  150. strMsg.LoadString(IDS_INVALID_IIS_SERVICE_TYPE);
  151. AfxMessageBox(strMsg, MB_OK | MB_ICONSTOP);
  152. strMsg.Empty();
  153. pDX->PrepareCtrl(IDC_PP_IIS_FTP); // do this just to set the control for Fail().
  154. pDX->Fail();
  155. } // else: no service type set
  156. } // if: saving data from dialog
  157. } //*** CIISVirtualRootParamsPage::DoDataExchange()
  158. /////////////////////////////////////////////////////////////////////////////
  159. //++
  160. //
  161. // CIISVirtualRootParamsPage::OnInitDialog
  162. //
  163. // Routine Description:
  164. // Handler for the WM_INITDIALOG message.
  165. //
  166. // Arguments:
  167. // None.
  168. //
  169. // Return Value:
  170. // TRUE We need the focus to be set for us.
  171. // FALSE We already set the focus to the proper control.
  172. //
  173. //--
  174. /////////////////////////////////////////////////////////////////////////////
  175. BOOL CIISVirtualRootParamsPage::OnInitDialog(void)
  176. {
  177. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  178. CBasePropertyPage::OnInitDialog();
  179. m_cInstanceId.EnableWindow( TRUE );
  180. //
  181. // Save the inital server type so it will be possible to determine if it changes (# 265510)
  182. //
  183. m_nInitialServerType = m_rbWWW.GetCheck() == BST_CHECKED ? SERVER_TYPE_WWW : SERVER_TYPE_FTP;
  184. OnChangeServiceType();
  185. return TRUE; // return TRUE unless you set the focus to a control
  186. // EXCEPTION: OCX Property Pages should return FALSE
  187. } //*** CIISVirtualRootParamsPage::OnInitDialog()
  188. /////////////////////////////////////////////////////////////////////////////
  189. //++
  190. //
  191. // CIISVirtualRootParamsPage::OnSetActive
  192. //
  193. // Routine Description:
  194. // Handler for the PSN_SETACTIVE message.
  195. //
  196. // Arguments:
  197. // None.
  198. //
  199. // Return Value:
  200. // TRUE Page successfully initialized.
  201. // FALSE Page not initialized.
  202. //
  203. //--
  204. /////////////////////////////////////////////////////////////////////////////
  205. BOOL CIISVirtualRootParamsPage::OnSetActive(void)
  206. {
  207. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  208. // Enable/disable the Next/Finish button.
  209. if (BWizard())
  210. {
  211. SetEnableNext();
  212. } // if: in the wizard
  213. return CBasePropertyPage::OnSetActive();
  214. } //*** CIISVirtualRootParamsPage::OnSetActive()
  215. /////////////////////////////////////////////////////////////////////////////
  216. //++
  217. //
  218. // CIISVirtualRootParamsPage::OnChangeServiceType
  219. //
  220. // Routine Description:
  221. // Handler for the BN_CLICKED message on one of the service type radio
  222. // buttons.
  223. //
  224. // Arguments:
  225. // None.
  226. //
  227. // Return Value:
  228. // None.
  229. //
  230. //--
  231. /////////////////////////////////////////////////////////////////////////////
  232. void CIISVirtualRootParamsPage::OnChangeServiceType(void)
  233. {
  234. #if 0
  235. int nCmdShowAccess;
  236. IDS idsWriteLabel = 0;
  237. OnChangeCtrl();
  238. if (m_rbFTP.GetCheck() == BST_CHECKED)
  239. {
  240. nCmdShowAccess = SW_SHOW;
  241. idsWriteLabel = IDS_WRITE;
  242. } // if: FTP service
  243. else if (m_rbWWW.GetCheck() == BST_CHECKED)
  244. {
  245. nCmdShowAccess = SW_SHOW;
  246. idsWriteLabel = IDS_EXECUTE;
  247. } // else if: WWW service
  248. else
  249. {
  250. nCmdShowAccess = SW_HIDE;
  251. } // else: unknown service
  252. // Set the access checkbox labels.
  253. if (idsWriteLabel != 0)
  254. {
  255. CString strWriteLabel;
  256. // AFX_MANAGE_STATE(AfxGetStaticModuleState());
  257. // strWriteLabel.LoadString(idsWriteLabel);
  258. // m_ckbWrite.SetWindowText(strWriteLabel);
  259. } // if: write label needs to be set
  260. #endif
  261. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  262. OnChangeCtrl();
  263. m_nServerType = m_rbWWW.GetCheck() == BST_CHECKED ? SERVER_TYPE_WWW : SERVER_TYPE_FTP;
  264. FillServerList();
  265. } //*** CIISVirtualRootParamsPage::OnChangeServiceType()
  266. /////////////////////////////////////////////////////////////////////////////
  267. //++
  268. //
  269. // CIISVirtualRootParamsPage::OnChangeRequiredField
  270. //
  271. // Routine Description:
  272. // Handler for the EN_CHANGE message on the Share name or Path edit
  273. // controls.
  274. //
  275. // Arguments:
  276. // None.
  277. //
  278. // Return Value:
  279. // None.
  280. //
  281. //--
  282. /////////////////////////////////////////////////////////////////////////////
  283. void CIISVirtualRootParamsPage::OnChangeRequiredField(void)
  284. {
  285. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  286. OnChangeCtrl();
  287. if (BWizard())
  288. {
  289. SetEnableNext();
  290. } // if: in a wizard
  291. } //*** CIISVirtualRootParamsPage::OnChangeRequiredField()
  292. ////
  293. void
  294. CIISVirtualRootParamsPage::FillServerList(
  295. )
  296. /*++
  297. Routine Description:
  298. Populate server combo box with server list relevant to current service type,
  299. set current selection based on server instance ID
  300. enable Finish button if list non empty
  301. Arguments:
  302. None
  303. Returns:
  304. Nothing
  305. --*/
  306. {
  307. int nIndex;
  308. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  309. //
  310. // build array if not already done
  311. //
  312. if ( !m_fReadList )
  313. {
  314. HRESULT hr1, hr2, hr;
  315. hr1 = ReadList( &m_W3Array, MD_SERVICE_ROOT_WWW, LPCTSTR(Peo()->StrNodeName()), SERVER_TYPE_WWW );
  316. hr2 = ReadList( &m_FTPArray, MD_SERVICE_ROOT_FTP, LPCTSTR(Peo()->StrNodeName()), SERVER_TYPE_FTP );
  317. if (FAILED(hr1) || FAILED(hr2))
  318. {
  319. CString err;
  320. hr = FAILED(hr1) ? hr1 : hr2;
  321. //
  322. // (# 309917) Path not found is not a "reportable" error since it only implies there no servers of the given server type, which is a case that is dealt with below
  323. //
  324. if( (HRESULT_FACILITY(hr) == FACILITY_WIN32) &&
  325. (HRESULT_CODE(hr) == ERROR_PATH_NOT_FOUND) )
  326. {
  327. OutputDebugStringW( L"[FillServerList] ReadList() returned : ERROR_PATH_NOT_FOUND\n" );
  328. }
  329. else if ( REGDB_E_IIDNOTREG == hr)
  330. {
  331. err.Format(IDS_IIS_PROXY_MISCONFIGURED, Peo()->StrNodeName());
  332. AfxMessageBox(err);
  333. }
  334. else
  335. {
  336. CString fmtError;
  337. DWORD dwError;
  338. if ( (HRESULT_FACILITY(hr) == FACILITY_WIN32) ||
  339. (HRESULT_FACILITY(hr) == FACILITY_NT_BIT))
  340. {
  341. dwError = (DWORD) HRESULT_CODE(hr);
  342. }
  343. else
  344. {
  345. dwError = (DWORD) hr;
  346. }
  347. FormatError(fmtError, dwError);
  348. err.Format(IDS_ENUMERATE_FAILED, Peo()->StrNodeName(), fmtError);
  349. AfxMessageBox(err);
  350. }
  351. m_cInstanceId.EnableWindow(FALSE);
  352. }
  353. else
  354. {
  355. m_cInstanceId.EnableWindow(TRUE);
  356. }
  357. m_fReadList = TRUE;
  358. }
  359. m_strInstanceName = MetabaseIdToName( m_nServerType == SERVER_TYPE_WWW, m_strInstanceId );
  360. // add to combo from array
  361. CArray <IISMapper, IISMapper>* pArray = m_nServerType == SERVER_TYPE_WWW ? &m_W3Array : &m_FTPArray;
  362. DWORD nAddCount = 0;
  363. m_cInstanceId.ResetContent();
  364. for ( nIndex = 0 ; nIndex < pArray->GetSize() ; ++nIndex )
  365. {
  366. //
  367. // Only add sites that are not cluster enabled or have the same ID and service type as the resource opened
  368. //
  369. if ( (!pArray->ElementAt(nIndex).IsClusterEnabled()) ||
  370. ((!lstrcmp( pArray->ElementAt( nIndex ).GetId(), m_strInstanceId)) &&
  371. (pArray->ElementAt( nIndex ).GetServerType() == m_nInitialServerType))
  372. )
  373. {
  374. if ( m_cInstanceId.AddString( pArray->ElementAt( nIndex ).GetName() ) < 0 )
  375. {
  376. OutputDebugStringW( L"Error add\n" );
  377. }
  378. else
  379. {
  380. nAddCount++;
  381. }
  382. }
  383. }
  384. if (0 == nAddCount)
  385. {
  386. m_cInstanceId.EnableWindow(FALSE);
  387. if (BWizard())
  388. {
  389. //
  390. // If we're here than there are no more un-clustered sites of server type (m_nServerType)
  391. //
  392. BOOL fAllClusterEnabled = TRUE;
  393. //
  394. // (# 265689) Before reporting that ALL instances are cluster enabled we have to check the other server type for un-clustered sites
  395. //
  396. CArray <IISMapper, IISMapper>* pOhterArray = m_nServerType == SERVER_TYPE_WWW ? &m_FTPArray : &m_W3Array ;
  397. for ( nIndex = 0 ; nIndex < pOhterArray->GetSize() ; ++nIndex )
  398. {
  399. if( !pOhterArray->ElementAt(nIndex).IsClusterEnabled() )
  400. {
  401. fAllClusterEnabled = FALSE;
  402. break;
  403. }
  404. }
  405. if( fAllClusterEnabled )
  406. {
  407. CString err;
  408. err.Format(IDS_ALL_INSTANCES_CLUSTER_ENABLED, Peo()->StrNodeName());
  409. AfxMessageBox(err);
  410. }
  411. EnableNext(FALSE);
  412. }
  413. }
  414. else
  415. {
  416. m_cInstanceId.EnableWindow(TRUE); // # 237376
  417. if (BWizard())
  418. {
  419. SetEnableNext();
  420. m_cInstanceId.SetCurSel(0);
  421. }
  422. else
  423. {
  424. nIndex = m_cInstanceId.FindStringExact(-1, m_strInstanceName);
  425. if ( nIndex != CB_ERR )
  426. {
  427. m_cInstanceId.SetCurSel(nIndex);
  428. }
  429. }
  430. }
  431. }
  432. HRESULT
  433. CIISVirtualRootParamsPage::ReadList(
  434. CArray <IISMapper, IISMapper>* pMapperArray,
  435. LPWSTR pszPath,
  436. LPCWSTR wcsMachineName,
  437. int nServerType
  438. )
  439. /*++
  440. Routine Description:
  441. Read a server list from metabase based on metabase path
  442. Arguments:
  443. pMapperArray - array where to add list of ( ServerComment, InstanceId ) pairs
  444. pszPath - metabase path, e.g. LM/W3SVC
  445. Returns:
  446. Error code, S_OK if success
  447. --*/
  448. {
  449. IMSAdminBaseW * pcAdmCom = NULL;
  450. METADATA_HANDLE hmd;
  451. DWORD i;
  452. WCHAR aId[METADATA_MAX_NAME_LEN+1] = L"";
  453. WCHAR aName[METADATA_MAX_NAME_LEN+1] = L"";
  454. INT cName = METADATA_MAX_NAME_LEN+1;
  455. HRESULT hRes = S_OK;
  456. COSERVERINFO csiMachine;
  457. MULTI_QI QI = {&IID_IMSAdminBase, NULL, 0};
  458. ZeroMemory( &csiMachine, sizeof(COSERVERINFO) );
  459. csiMachine.pwszName = (LPWSTR)wcsMachineName;
  460. hRes = CoCreateInstanceEx( GETAdminBaseCLSID(TRUE),
  461. NULL,
  462. CLSCTX_SERVER,
  463. &csiMachine,
  464. 1,
  465. &QI
  466. );
  467. if ( SUCCEEDED(hRes) && SUCCEEDED(QI.hr))
  468. {
  469. pcAdmCom = (IMSAdminBaseW *)QI.pItf;
  470. if( SUCCEEDED( hRes = pcAdmCom->OpenKey( METADATA_MASTER_ROOT_HANDLE,
  471. pszPath,
  472. METADATA_PERMISSION_READ,
  473. 5000,
  474. &hmd)) )
  475. {
  476. for ( i = 0 ;
  477. SUCCEEDED(pcAdmCom->EnumKeys( hmd, L"", aId, i )) ;
  478. ++i )
  479. {
  480. METADATA_RECORD md;
  481. DWORD dwReq = sizeof(aName);
  482. memset( &md, 0, sizeof(md) );
  483. md.dwMDDataType = STRING_METADATA;
  484. md.dwMDUserType = IIS_MD_UT_SERVER;
  485. md.dwMDIdentifier = MD_SERVER_COMMENT;
  486. md.dwMDDataLen = sizeof(aName);
  487. md.pbMDData = (LPBYTE)aName;
  488. if ( SUCCEEDED( pcAdmCom->GetData( hmd, aId, &md, &dwReq) ) )
  489. {
  490. DWORD dwClusterEnabled = 0;
  491. memset( &md, 0, sizeof(md) );
  492. md.dwMDDataType = DWORD_METADATA;
  493. md.dwMDUserType = IIS_MD_UT_SERVER;
  494. md.dwMDIdentifier = MD_CLUSTER_ENABLED;
  495. md.dwMDDataLen = sizeof(dwClusterEnabled);
  496. md.pbMDData = (LPBYTE)&dwClusterEnabled;
  497. pcAdmCom->GetData( hmd, aId, &md, &dwReq);
  498. //
  499. // (# 296798) Use a default name if there is no server comment
  500. //
  501. if( aId && aName && (0 == lstrlen(aName)) )
  502. {
  503. if( !LoadString(AfxGetResourceHandle( ), IDS_DEFAULT_SITE_NAME, aName, cName) )
  504. {
  505. OutputDebugStringW( L"Error Loading IDS_DEFAULT_SITE_NAME\n" );
  506. }
  507. lstrcat(aName, aId);
  508. }
  509. IISMapper* pMap = new IISMapper( aName, aId, dwClusterEnabled, nServerType );
  510. if ( pMap )
  511. {
  512. pMapperArray->Add( *pMap );
  513. }
  514. else
  515. {
  516. hRes = E_OUTOFMEMORY;
  517. break;
  518. }
  519. }
  520. }
  521. pcAdmCom->CloseKey( hmd );
  522. }
  523. pcAdmCom->Release();
  524. }
  525. return hRes;
  526. }
  527. LPWSTR
  528. CIISVirtualRootParamsPage::NameToMetabaseId(
  529. BOOL fIsW3,
  530. CString& strName
  531. )
  532. /*++
  533. Routine Description:
  534. Convert ServerComment to InstanceId
  535. Arguments:
  536. fIsW3 - TRUE for WWW, FALSE for FTP
  537. strName - ServerComment
  538. Returns:
  539. InstanceId if strName found in array, otherwise NULL
  540. --*/
  541. {
  542. CArray <IISMapper, IISMapper>* pArray = fIsW3 ? &m_W3Array : &m_FTPArray;
  543. DWORD i;
  544. for ( i = 0 ; i < (DWORD)pArray->GetSize() ; ++i )
  545. {
  546. if ( !pArray->ElementAt( i ).GetName().Compare( strName ) )
  547. {
  548. return (LPWSTR)(LPCTSTR)(pArray->ElementAt( i ).GetId());
  549. }
  550. }
  551. return NULL;
  552. }
  553. LPWSTR
  554. CIISVirtualRootParamsPage::MetabaseIdToName(
  555. BOOL fIsW3,
  556. CString& strId
  557. )
  558. /*++
  559. Routine Description:
  560. Convert InstanceId to ServerComment
  561. Arguments:
  562. fIsW3 - TRUE for WWW, FALSE for FTP
  563. strId - InstanceID
  564. Returns:
  565. InstanceId if strName found in array.
  566. If not found return 1st array element if array not empty, otherwise NULL
  567. --*/
  568. {
  569. CArray <IISMapper, IISMapper>* pArray = fIsW3 ? &m_W3Array : &m_FTPArray;
  570. DWORD i;
  571. for ( i = 0 ; i < (DWORD)pArray->GetSize() ; ++i )
  572. {
  573. if ( !pArray->ElementAt( i ).GetId().Compare( strId ) )
  574. {
  575. return (LPWSTR)(LPCTSTR)(pArray->ElementAt( i ).GetName());
  576. }
  577. }
  578. return pArray->GetSize() == 0 ? NULL : (LPWSTR)(LPCTSTR)(pArray->ElementAt( 0 ).GetName());
  579. }
  580. VOID
  581. CIISVirtualRootParamsPage::SetEnableNext(
  582. VOID
  583. )
  584. /*++
  585. Routine Description:
  586. Set enable state of Finish button
  587. Arguments:
  588. None
  589. Returns:
  590. Nothing
  591. --*/
  592. {
  593. BOOL fAllClusterEnabled = TRUE;
  594. CArray <IISMapper, IISMapper>* pArray = m_nServerType == SERVER_TYPE_WWW ? &m_W3Array : &m_FTPArray;
  595. for (int nIndex = 0 ; nIndex < pArray->GetSize() ; ++nIndex )
  596. {
  597. if( !pArray->ElementAt(nIndex).IsClusterEnabled() )
  598. {
  599. fAllClusterEnabled = FALSE;
  600. break;
  601. }
  602. }
  603. fAllClusterEnabled = !fAllClusterEnabled;
  604. EnableNext( fAllClusterEnabled );
  605. }
  606. void CIISVirtualRootParamsPage::OnRefresh()
  607. {
  608. m_fReadList = FALSE;
  609. m_W3Array.RemoveAll();
  610. m_FTPArray.RemoveAll();
  611. FillServerList();
  612. }