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.

680 lines
18 KiB

  1. //***************************************************************************
  2. //
  3. // HOSTPAGE.CPP
  4. //
  5. // Module: NLB Manager
  6. //
  7. // Purpose: Implements HostPage, which is a dialog for host-specific
  8. // properties
  9. //
  10. // Copyright (c)2001-2002 Microsoft Corporation, All Rights Reserved
  11. //
  12. // History:
  13. //
  14. // 07/30/01 JosephJ Created
  15. //
  16. //***************************************************************************
  17. #include "precomp.h"
  18. #pragma hdrstop
  19. #include "private.h"
  20. #include "HostPage.h"
  21. #include "HostPage.tmh"
  22. using namespace std;
  23. BEGIN_MESSAGE_MAP( HostPage, CPropertyPage )
  24. ON_EN_SETFOCUS( IDC_EDIT_DED_IP, OnGainFocusDedicatedIP )
  25. ON_EN_SETFOCUS( IDC_EDIT_DED_MASK, OnGainFocusDedicatedMask )
  26. ON_WM_HELPINFO()
  27. ON_WM_CONTEXTMENU()
  28. END_MESSAGE_MAP()
  29. HostPage::HostPage(
  30. CPropertySheet *psh,
  31. NLB_EXTENDED_CLUSTER_CONFIGURATION *pNlbCfg,
  32. ENGINEHANDLE ehCluster OPTIONAL,
  33. const ENGINEHANDLE *pehInterface OPTIONAL
  34. )
  35. :
  36. m_pshOwner( psh),
  37. m_pNlbCfg( pNlbCfg ),
  38. CPropertyPage( HostPage::IDD ),
  39. m_clusterData(NULL),
  40. m_ehCluster(ehCluster),
  41. m_pehInterface(pehInterface),
  42. m_fSaved(FALSE)
  43. {
  44. TRACE_INFO("%!FUNC! ->");
  45. //
  46. // Note: the following gEngine.GetAvailableXXX APIs can deal with
  47. // the fact that ehCluster may be NULL -- in which case they
  48. // setup the out params to be all-available.
  49. //
  50. m_AvailableHostPriorities = gEngine.GetAvailableHostPriorities(
  51. ehCluster);
  52. mfn_LoadFromNlbCfg();
  53. TRACE_INFO("%!FUNC! <-");
  54. }
  55. void
  56. HostPage::mfn_LoadFromNlbCfg(void)
  57. {
  58. TRACE_INFO("%!FUNC! ->");
  59. DWORD HostId = 0;
  60. _bstr_t bstrDedIp = (LPCWSTR) m_pNlbCfg->NlbParams.ded_ip_addr;
  61. _bstr_t bstrDedMask = (LPCWSTR) m_pNlbCfg->NlbParams.ded_net_mask;
  62. BOOL fPersistSuspendedState = m_pNlbCfg->NlbParams.persisted_states
  63. & CVY_PERSIST_STATE_SUSPENDED;
  64. DWORD preferredInitialHostState = m_pNlbCfg->NlbParams.cluster_mode;
  65. // fill in priority.
  66. wchar_t buf[Common::BUF_SIZE];
  67. ULONG availHostIds = m_AvailableHostPriorities;
  68. ENGINEHANDLE ehInterface = NULL;
  69. HostId = m_pNlbCfg->NlbParams.host_priority;
  70. TRACE_CRIT("%!FUNC! HostId=%lu", HostId);
  71. if (HostId>0 && HostId<=32)
  72. {
  73. availHostIds |= (((ULONG)1)<<(HostId-1));
  74. }
  75. // Delete any current entries in the priorities combobox
  76. {
  77. int iLeft;
  78. do
  79. {
  80. iLeft = priority.DeleteString(0);
  81. } while(iLeft != 0 && iLeft != CB_ERR);
  82. }
  83. for(ULONG u=0; u<32; u++)
  84. {
  85. if (availHostIds & (((ULONG)1)<<u))
  86. {
  87. StringCbPrintf(buf, sizeof(buf), L"%d", (u+1));
  88. priority.AddString( buf );
  89. if (HostId == 0)
  90. {
  91. HostId = u+1; // let's pick the first available one.
  92. }
  93. }
  94. }
  95. // set selection to present hostid
  96. StringCbPrintf( buf, sizeof(buf), L"%d", HostId );
  97. priority.SelectString( -1, buf );
  98. // set persist suspend
  99. persistSuspend.SetCheck(fPersistSuspendedState);
  100. // set initial host state
  101. {
  102. int itemNum = 0;
  103. /* Delete all items currently in the combobox first. */
  104. do {
  105. itemNum = initialState.DeleteString(0);
  106. } while (itemNum != 0 && itemNum != CB_ERR);
  107. itemNum = initialState.AddString(GETRESOURCEIDSTRING(IDS_HOST_STATE_STARTED));
  108. initialState.SetItemData(itemNum, (DWORD)CVY_HOST_STATE_STARTED);
  109. if (preferredInitialHostState == CVY_HOST_STATE_STARTED)
  110. initialState.SetCurSel(itemNum);
  111. itemNum = initialState.AddString(GETRESOURCEIDSTRING(IDS_HOST_STATE_STOPPED));
  112. initialState.SetItemData(itemNum, (DWORD)CVY_HOST_STATE_STOPPED);
  113. if (preferredInitialHostState == CVY_HOST_STATE_STOPPED)
  114. initialState.SetCurSel(itemNum);
  115. itemNum = initialState.AddString(GETRESOURCEIDSTRING(IDS_HOST_STATE_SUSPENDED));
  116. initialState.SetItemData(itemNum, (DWORD)CVY_HOST_STATE_SUSPENDED);
  117. if (preferredInitialHostState == CVY_HOST_STATE_SUSPENDED)
  118. initialState.SetCurSel(itemNum);
  119. }
  120. // fill in host ip
  121. CommonUtils::fillCIPAddressCtrlString(
  122. ipAddress,
  123. bstrDedIp );
  124. // set host mask.
  125. CommonUtils::fillCIPAddressCtrlString(
  126. subnetMask,
  127. bstrDedMask );
  128. //
  129. // Initialize the caption and discription based on the type of
  130. // dialog.
  131. //
  132. {
  133. CWnd *pItem = GetDlgItem(IDC_NIC_FRIENDLY);
  134. LPWSTR szFriendlyName = NULL;
  135. m_pNlbCfg->GetFriendlyName(&szFriendlyName);
  136. if (pItem != NULL && szFriendlyName != NULL)
  137. {
  138. pItem->SetWindowText(szFriendlyName);
  139. }
  140. delete szFriendlyName;
  141. }
  142. TRACE_INFO("%!FUNC! <-");
  143. }
  144. void
  145. HostPage::DoDataExchange( CDataExchange* pDX )
  146. {
  147. DDX_Control( pDX, IDC_EDIT_PRI, priority );
  148. DDX_Control( pDX, IDC_CHECK_PERSIST_SUSPEND, persistSuspend );
  149. DDX_Control( pDX, IDC_COMBOBOX_DEFAULT_STATE, initialState );
  150. DDX_Control( pDX, IDC_EDIT_DED_IP, ipAddress );
  151. DDX_Control( pDX, IDC_EDIT_DED_MASK, subnetMask );
  152. }
  153. BOOL
  154. HostPage::OnInitDialog()
  155. {
  156. TRACE_INFO("%!FUNC! ->");
  157. CPropertyPage::OnInitDialog();
  158. mfn_LoadFromNlbCfg();
  159. TRACE_INFO("%!FUNC! <-");
  160. return TRUE;
  161. }
  162. void
  163. HostPage::OnOK()
  164. {
  165. CPropertyPage::OnOK();
  166. TRACE_INFO("%!FUNC! ->");
  167. //
  168. // Save the configuration to the NLB configuration structure
  169. // that was passed in the constructor of this dialog.
  170. //
  171. mfn_SaveToNlbCfg();
  172. TRACE_INFO("%!FUNC! <-");
  173. }
  174. BOOL
  175. HostPage::mfn_ValidateDip(LPCWSTR szDip)
  176. //
  177. // If connection-IP is on this NIC:
  178. // MUST be the DIP (DIP can't be blank).
  179. // Else if dip is blank:
  180. // return TRUE;
  181. // Else // dip not blank
  182. // It must not be used anywhere else -- i.e., be part of a
  183. // cluster IP, or bound to any other interface known to NLB Manager.
  184. //
  185. //
  186. // On errr, bring up appropriate MsgBox and return FALSE.
  187. // Else return TRUE.
  188. //
  189. {
  190. ENGINEHANDLE ehIF = NULL;
  191. BOOL fRet = FALSE;
  192. NLBERROR nerr;
  193. if (m_pehInterface != NULL)
  194. {
  195. ehIF = *m_pehInterface;
  196. }
  197. if (ehIF == NULL)
  198. {
  199. ASSERT(FALSE);
  200. goto end;
  201. }
  202. //
  203. // Check if this interface is the connection-interface and if so
  204. // what is the connection IP.
  205. //
  206. {
  207. UINT uConnectionIp = 0;
  208. ENGINEHANDLE ehHost = NULL;
  209. ENGINEHANDLE ehCluster = NULL;
  210. ENGINEHANDLE ehConnectionIF = NULL;
  211. _bstr_t bstrFriendlyName;
  212. _bstr_t bstrDisplayName;
  213. _bstr_t bstrHostName;
  214. _bstr_t bstrConnectionString;
  215. nerr = gEngine.GetInterfaceIdentification(
  216. ehIF,
  217. REF ehHost,
  218. REF ehCluster,
  219. REF bstrFriendlyName,
  220. REF bstrDisplayName,
  221. REF bstrHostName
  222. );
  223. if (NLBFAILED(nerr))
  224. {
  225. fRet = TRUE;
  226. goto end;
  227. }
  228. nerr = gEngine.GetHostConnectionInformation(
  229. ehHost,
  230. REF ehConnectionIF,
  231. REF bstrConnectionString,
  232. REF uConnectionIp
  233. );
  234. if (NLBFAILED(nerr))
  235. {
  236. TRACE_CRIT(L"%!FUNC! gEngine.GetHostConnectionInformation fails!");
  237. //
  238. // We'll plow on...
  239. //
  240. ehConnectionIF = NULL;
  241. uConnectionIp = 0;
  242. }
  243. if (ehConnectionIF == ehIF && uConnectionIp != 0)
  244. {
  245. //
  246. // The connection interface IS the current interface --
  247. // so dedicated IP MUST match the connection IP!
  248. //
  249. WBEMSTATUS wStat;
  250. UINT uDipIp = 0;
  251. wStat = CfgUtilsValidateNetworkAddress(
  252. szDip,
  253. &uDipIp,
  254. NULL, // puSubnetMask
  255. NULL // puDefaultSubnetMask
  256. );
  257. if (!FAILED(wStat))
  258. {
  259. if (uDipIp != uConnectionIp)
  260. {
  261. MessageBox( GETRESOURCEIDSTRING( IDS_CANT_CHANGE_DIP_MSG ),
  262. GETRESOURCEIDSTRING( IDS_PARM_ERROR ),
  263. MB_ICONSTOP | MB_OK );
  264. fRet = FALSE;
  265. goto end;
  266. }
  267. }
  268. fRet = TRUE;
  269. goto end;
  270. }
  271. }
  272. //
  273. // If Dip is blank, we're done
  274. //
  275. if (*szDip == 0 || !_wcsicmp(szDip, L"0.0.0.0"))
  276. {
  277. fRet = TRUE;
  278. goto end;
  279. }
  280. //
  281. // Check that DIP is not used elsewhere
  282. //
  283. {
  284. ENGINEHANDLE ehTmp = NULL;
  285. BOOL fIsNew = FALSE;
  286. CLocalLogger logConflict;
  287. nerr = gEngine.ValidateNewDedicatedIp(
  288. ehIF,
  289. szDip,
  290. REF logConflict
  291. );
  292. if (nerr == NLBERR_INVALID_IP_ADDRESS_SPECIFICATION)
  293. {
  294. CLocalLogger logMsg;
  295. logMsg.Log(
  296. IDS_NEW_DIP_CONFLICTS_WITH_XXX,
  297. logConflict.GetStringSafe()
  298. );
  299. MessageBox(
  300. logMsg.GetStringSafe(),
  301. GETRESOURCEIDSTRING( IDS_PARM_ERROR ),
  302. MB_ICONSTOP | MB_OK
  303. );
  304. fRet = FALSE;
  305. goto end;
  306. }
  307. }
  308. fRet = TRUE;
  309. end:
  310. return fRet;
  311. }
  312. BOOL
  313. HostPage::OnSetActive()
  314. {
  315. BOOL fRet;
  316. TRACE_INFO("%!FUNC! ->");
  317. fRet = CPropertyPage::OnSetActive();
  318. if (fRet)
  319. {
  320. mfn_LoadFromNlbCfg();
  321. m_pshOwner->SetWizardButtons(
  322. PSWIZB_BACK|
  323. // PSWIZB_NEXT|
  324. PSWIZB_FINISH|
  325. // PSWIZB_DISABLEDFINISH|
  326. 0
  327. );
  328. }
  329. TRACE_INFO("%!FUNC! <- returns %lu", fRet);
  330. return fRet;
  331. }
  332. BOOL
  333. HostPage::OnKillActive()
  334. {
  335. BOOL fRet;
  336. TRACE_INFO("%!FUNC! ->");
  337. fRet = mfn_ValidateData();
  338. if (!fRet)
  339. {
  340. CPropertyPage::OnCancel();
  341. }
  342. else
  343. {
  344. mfn_SaveToNlbCfg();
  345. fRet = CPropertyPage::OnKillActive();
  346. }
  347. TRACE_INFO("%!FUNC! <- returns %lu", fRet);
  348. return fRet;
  349. }
  350. BOOL HostPage::OnWizardFinish( )
  351. /*
  352. Overwridden virtual function. OnWizardFinish is ONLY called if
  353. this is the last page in the wizard. So if you need to save stuff
  354. on OnKillActive.
  355. */
  356. {
  357. BOOL fRet;
  358. TRACE_INFO("%!FUNC! ->");
  359. fRet = CPropertyPage::OnWizardFinish();
  360. if (fRet)
  361. {
  362. fRet = mfn_ValidateData();
  363. if (fRet)
  364. {
  365. //
  366. // Save the configuration to the NLB configuration structure
  367. // that was passed in the constructor of this dialog.
  368. //
  369. mfn_SaveToNlbCfg();
  370. }
  371. }
  372. TRACE_INFO("%!FUNC! <- returns %lu", fRet);
  373. return fRet;
  374. }
  375. BOOL
  376. HostPage::mfn_ValidateData()
  377. {
  378. DWORD HostId = 0;
  379. _bstr_t bstrDedIp;
  380. _bstr_t bstrDedMask;
  381. BOOL fPersistSuspendedState = false;
  382. BOOL fRet = false;
  383. wchar_t buf[Common::BUF_SIZE];
  384. TRACE_INFO("%!FUNC! ->");
  385. // fill in priority.
  386. {
  387. int selectedPriorityIndex = priority.GetCurSel();
  388. priority.GetLBText( selectedPriorityIndex, buf );
  389. HostId = _wtoi( buf );
  390. }
  391. bstrDedIp =
  392. CommonUtils::getCIPAddressCtrlString( ipAddress );
  393. bstrDedMask =
  394. CommonUtils::getCIPAddressCtrlString( subnetMask );
  395. fPersistSuspendedState = persistSuspend.GetCheck() ? true : false;
  396. // ip is blank
  397. // subnet is blank
  398. // valid
  399. if( ( !_wcsicmp((LPCWSTR)bstrDedIp, L"0.0.0.0") )
  400. &&
  401. ( !_wcsicmp((LPCWSTR)bstrDedMask, L"0.0.0.0") )
  402. )
  403. {
  404. // both ip and subnet can be blank or 0.0.0.0 in host page. both but not
  405. // either.
  406. //
  407. // this is empty, we just need to catch this case.
  408. }
  409. else if (!_wcsicmp((LPCWSTR)bstrDedIp, L"0.0.0.0"))
  410. {
  411. // if only ip is blank or 0.0.0.0 then this is not allowed
  412. MessageBox( GETRESOURCEIDSTRING( IDS_PARM_DED_IP_BLANK ),
  413. GETRESOURCEIDSTRING( IDS_PARM_ERROR ),
  414. MB_ICONSTOP | MB_OK );
  415. goto end;
  416. }
  417. else
  418. {
  419. // check if ip is valid.
  420. bool isIPValid = MIPAddress::checkIfValid(bstrDedIp );
  421. if( isIPValid != true )
  422. {
  423. MessageBox( GETRESOURCEIDSTRING( IDS_PARM_INVAL_DED_IP ),
  424. GETRESOURCEIDSTRING( IDS_PARM_ERROR ),
  425. MB_ICONSTOP | MB_OK );
  426. goto end;
  427. }
  428. // check if subnet is 0.0.0.0
  429. // if so ask user if he wants us to fill it or not.
  430. if (!_wcsicmp((LPCWSTR)bstrDedMask, L"0.0.0.0") )
  431. {
  432. MessageBox( GETRESOURCEIDSTRING( IDS_PARM_DED_NM_BLANK ),
  433. GETRESOURCEIDSTRING( IDS_PARM_ERROR ),
  434. MB_ICONSTOP | MB_OK );
  435. MIPAddress::getDefaultSubnetMask( bstrDedIp,
  436. bstrDedMask
  437. );
  438. CommonUtils::fillCIPAddressCtrlString( subnetMask,
  439. bstrDedMask );
  440. goto end;
  441. }
  442. // check if subnet is contiguous
  443. bool isSubnetContiguous = MIPAddress::isContiguousSubnetMask( bstrDedMask );
  444. if( isSubnetContiguous == false )
  445. {
  446. MessageBox( GETRESOURCEIDSTRING( IDS_PARM_INVAL_DED_MASK ),
  447. GETRESOURCEIDSTRING( IDS_PARM_ERROR ),
  448. MB_ICONSTOP | MB_OK );
  449. goto end;
  450. }
  451. // check if ip address and subnet mask are valid as a pair
  452. bool isIPSubnetPairValid = MIPAddress::isValidIPAddressSubnetMaskPair( bstrDedIp,
  453. bstrDedMask );
  454. if( isIPSubnetPairValid == false )
  455. {
  456. MessageBox( GETRESOURCEIDSTRING( IDS_PARM_INVAL_DED_IP ),
  457. GETRESOURCEIDSTRING( IDS_PARM_ERROR ),
  458. MB_ICONSTOP | MB_OK );
  459. goto end;
  460. }
  461. }
  462. fRet = mfn_ValidateDip((LPCWSTR)bstrDedIp);
  463. if (!fRet)
  464. {
  465. //
  466. // We'll push the original dip and subnet values back to the UI
  467. //
  468. CommonUtils::fillCIPAddressCtrlString(
  469. ipAddress,
  470. m_pNlbCfg->NlbParams.ded_ip_addr
  471. );
  472. CommonUtils::fillCIPAddressCtrlString(
  473. subnetMask,
  474. m_pNlbCfg->NlbParams.ded_net_mask
  475. );
  476. }
  477. end:
  478. TRACE_INFO("%!FUNC! <- returns %lu", fRet);
  479. return fRet;
  480. }
  481. VOID
  482. HostPage::mfn_SaveToNlbCfg(void)
  483. //
  484. // Actually save stuff to nlbcfg.
  485. //
  486. {
  487. DWORD HostId = 0;
  488. _bstr_t bstrDedIp;
  489. _bstr_t bstrDedMask;
  490. BOOL fPersistSuspendedState = false;
  491. BOOL fRet = FALSE;
  492. DWORD preferredInitialHostState = 0;
  493. wchar_t buf[Common::BUF_SIZE];
  494. int itemNum = 0;
  495. TRACE_INFO("%!FUNC! ->");
  496. // fill in priority.
  497. int selectedPriorityIndex = priority.GetCurSel();
  498. priority.GetLBText( selectedPriorityIndex, buf );
  499. HostId = _wtoi( buf );
  500. bstrDedIp =
  501. CommonUtils::getCIPAddressCtrlString( ipAddress );
  502. bstrDedMask =
  503. CommonUtils::getCIPAddressCtrlString( subnetMask );
  504. fPersistSuspendedState = persistSuspend.GetCheck() ? true : false;
  505. itemNum = initialState.GetCurSel();
  506. preferredInitialHostState = initialState.GetItemData(itemNum);
  507. m_pNlbCfg->NlbParams.host_priority = HostId;
  508. ARRAYSTRCPY(m_pNlbCfg->NlbParams.ded_ip_addr, (LPCWSTR) bstrDedIp);
  509. ARRAYSTRCPY(m_pNlbCfg->NlbParams.ded_net_mask, (LPCWSTR) bstrDedMask);
  510. if (fPersistSuspendedState)
  511. m_pNlbCfg->NlbParams.persisted_states |= CVY_PERSIST_STATE_SUSPENDED;
  512. else
  513. m_pNlbCfg->NlbParams.persisted_states &= ~CVY_PERSIST_STATE_SUSPENDED;
  514. m_pNlbCfg->NlbParams.cluster_mode = preferredInitialHostState;
  515. m_fSaved = TRUE;
  516. TRACE_INFO("%!FUNC! <-");
  517. return;
  518. }
  519. void
  520. HostPage::OnSelectedNicChanged()
  521. {
  522. }
  523. BOOL
  524. HostPage::OnHelpInfo (HELPINFO* helpInfo )
  525. {
  526. if( helpInfo->iContextType == HELPINFO_WINDOW )
  527. {
  528. ::WinHelp( static_cast<HWND> ( helpInfo->hItemHandle ), CVY_CTXT_HELP_FILE, HELP_WM_HELP, (ULONG_PTR ) g_aHelpIDs_IDD_HOST_PAGE);
  529. }
  530. return TRUE;
  531. }
  532. void
  533. HostPage::OnContextMenu( CWnd* pWnd, CPoint point )
  534. {
  535. ::WinHelp( m_hWnd, CVY_CTXT_HELP_FILE, HELP_CONTEXTMENU, (ULONG_PTR ) g_aHelpIDs_IDD_HOST_PAGE);
  536. }
  537. void
  538. HostPage::OnGainFocusDedicatedIP()
  539. {
  540. }
  541. void
  542. HostPage::OnGainFocusDedicatedMask()
  543. {
  544. // if dedicated ip is valid
  545. // and subnet mask is blank, then generate
  546. // the default subnet mask.
  547. _bstr_t ipAddressString = CommonUtils::getCIPAddressCtrlString( ipAddress );
  548. if( ( MIPAddress::checkIfValid( ipAddressString ) == true )
  549. &&
  550. ( subnetMask.IsBlank() == TRUE )
  551. )
  552. {
  553. _bstr_t subnetMaskString;
  554. MIPAddress::getDefaultSubnetMask( ipAddressString,
  555. subnetMaskString );
  556. CommonUtils::fillCIPAddressCtrlString( subnetMask,
  557. subnetMaskString );
  558. }
  559. }