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.

777 lines
25 KiB

  1. /*++
  2. Copyright(c) 1998,99 Microsoft Corporation
  3. Module Name:
  4. CommonClusterPage.cpp
  5. Abstract:
  6. Windows Load Balancing Service (WLBS)
  7. Cluster page UI. Shared by Notifier object and NLB Manager
  8. Author:
  9. kyrilf
  10. shouse
  11. // History:
  12. // --------
  13. //
  14. // Revised by : mhakim
  15. // Date : 02-09-01
  16. // Reason : Igmp box was enabled when it needed to be grayed out.
  17. //
  18. // Revised by : mhakim
  19. // Date : 02-12-01
  20. // Reason : Mac address was not being retrieved fully.
  21. --*/
  22. //
  23. // To share the code with notifier object
  24. // share string resurce
  25. // share the common structure
  26. // call SetChangedFlag() in OnInitDialog
  27. // add trace, assert
  28. // Share help file and add help handler
  29. //
  30. //
  31. #include "precomp.h"
  32. #pragma hdrstop
  33. #include "private.h"
  34. #include <process.h>
  35. #include "wlbsutil.h"
  36. #include "CommonClusterPage.h"
  37. #define DUMMY_PASSWORD L"somepassword"
  38. #define EMPTY_PASSWORD L""
  39. //
  40. // No trace/assert for now
  41. //
  42. #define TraceMsg(x)
  43. #define Assert(x)
  44. //+---------------------------------------------------------------------------
  45. //
  46. // Function: SzLoadStringPcch
  47. //
  48. // Purpose: Load a resource string. (This function will never return NULL.)
  49. //
  50. // Arguments:
  51. // hinst [in] Instance handle of module with the string resource.
  52. // unId [in] Resource ID of the string to load.
  53. // pcch [out] Pointer to returned character length.
  54. //
  55. // Returns: Pointer to the constant string.
  56. //
  57. // Author: shaunco 24 Mar 1997
  58. // fengsun copied from net\config\common\ncbase\ncstring.cpp
  59. //
  60. // Notes: The loaded string is pointer directly into the read-only
  61. // resource section. Any attempt to write through this pointer
  62. // will generate an access violation.
  63. //
  64. // The implementations is referenced from "Win32 Binary Resource
  65. // Formats" (MSDN) 4.8 String Table Resources
  66. //
  67. // User must have RCOPTIONS = -N turned on in your sources file.
  68. //
  69. PCWSTR
  70. SzLoadStringPcch (
  71. IN HINSTANCE hinst,
  72. IN UINT unId,
  73. OUT int* pcch)
  74. {
  75. Assert(hinst);
  76. Assert(unId);
  77. Assert(pcch);
  78. static const WCHAR c_szSpace[] = L" ";
  79. PCWSTR psz = c_szSpace;
  80. int cch = 1;
  81. // String Tables are broken up into 16 string segments. Find the segment
  82. // containing the string we are interested in.
  83. HRSRC hrsrcInfo = FindResource (hinst,
  84. (PWSTR)ULongToPtr( ((LONG)(((USHORT)unId >> 4) + 1)) ),
  85. RT_STRING);
  86. if (hrsrcInfo)
  87. {
  88. // Page the resource segment into memory.
  89. HGLOBAL hglbSeg = LoadResource (hinst, hrsrcInfo);
  90. if (hglbSeg)
  91. {
  92. // Lock the resource.
  93. psz = (PCWSTR)LockResource(hglbSeg);
  94. if (psz)
  95. {
  96. // Move past the other strings in this segment.
  97. // (16 strings in a segment -> & 0x0F)
  98. unId &= 0x0F;
  99. cch = 0;
  100. do
  101. {
  102. psz += cch; // Step to start of next string
  103. cch = *((WCHAR*)psz++); // PASCAL like string count
  104. }
  105. while (unId--);
  106. // If we have a non-zero count, it includes the
  107. // null-terminiator. Subtract this off for the return value.
  108. //
  109. if (cch)
  110. {
  111. cch--;
  112. }
  113. else
  114. {
  115. // AssertSz(0, "String resource not found");
  116. psz = c_szSpace;
  117. cch = 1;
  118. }
  119. }
  120. else
  121. {
  122. psz = c_szSpace;
  123. cch = 1;
  124. // TraceLastWin32Error("SzLoadStringPcch: LockResource failed.");
  125. }
  126. }
  127. // else
  128. // TraceLastWin32Error("SzLoadStringPcch: LoadResource failed.");
  129. }
  130. // else
  131. // TraceLastWin32Error("SzLoadStringPcch: FindResource failed.");
  132. *pcch = cch;
  133. Assert(*pcch);
  134. Assert(psz);
  135. return psz;
  136. }
  137. //+---------------------------------------------------------------------------
  138. //
  139. // Function: SzLoadString
  140. //
  141. // Purpose: Load a resource string. (This function will never return NULL.)
  142. //
  143. // Arguments:
  144. // hinst [in] Instance handle of module with the string resource.
  145. // unId [in] Resource ID of the string to load.
  146. //
  147. // Returns: Pointer to the constant string.
  148. //
  149. // Author: shaunco 24 Mar 1997
  150. // fengsun copied from net\config\common\ncbase\ncstring.cpp
  151. //
  152. // Notes: See SzLoadStringPcch()
  153. //
  154. PCWSTR
  155. SzLoadString (
  156. HINSTANCE hinst,
  157. UINT unId)
  158. {
  159. int cch;
  160. return SzLoadStringPcch(hinst, unId, &cch);
  161. }
  162. //+---------------------------------------------------------------------------
  163. //
  164. // Function: NcMsgBox
  165. //
  166. // Purpose: Displays a message box using resource strings and replaceable
  167. // parameters.
  168. //
  169. // Arguments:
  170. // hinst [in] hinstance for resource strings
  171. // hwnd [in] parent window handle
  172. // unIdCaption [in] resource id of caption string
  173. // unIdFormat [in] resource id of text string (with %1, %2, etc.)
  174. // unStyle [in] standard message box styles
  175. // ... [in] replaceable parameters (optional)
  176. // (these must be PCWSTRs as that is all
  177. // FormatMessage handles.)
  178. //
  179. // Returns: the return value of MessageBox()
  180. //
  181. // Author: shaunco 24 Mar 1997
  182. // fengsun copied from net\config\common\ncbase\ncui.cpp
  183. //
  184. // Notes: FormatMessage is used to do the parameter substitution.
  185. //
  186. INT
  187. WINAPIV
  188. NcMsgBox (
  189. IN HINSTANCE hinst,
  190. IN HWND hwnd,
  191. IN UINT unIdCaption,
  192. IN UINT unIdFormat,
  193. IN UINT unStyle,
  194. IN ...)
  195. {
  196. PCWSTR pszCaption = SzLoadString (hinst, unIdCaption);
  197. PCWSTR pszFormat = SzLoadString (hinst, unIdFormat);
  198. PWSTR pszText = NULL;
  199. va_list val;
  200. va_start (val, unStyle);
  201. FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
  202. pszFormat, 0, 0, (PWSTR)&pszText, 0, &val);
  203. va_end (val);
  204. INT nRet = MessageBox (hwnd, pszText, pszCaption, unStyle);
  205. LocalFree (pszText);
  206. return nRet;
  207. }
  208. //+----------------------------------------------------------------------------
  209. //
  210. // Function: CCommonClusterPage::CCommonClusterPage
  211. //
  212. // Description:
  213. //
  214. // Arguments: HINSTANCE hInstance - instance handle for string resources
  215. // NETCFG_WLBS_CONFIG * paramp - IN/OUT NLB properties
  216. // bool fDisablePassword - whether do disable password editing
  217. // const DWORD * adwHelpIDs - a list of help ID pairs, or NULL.
  218. // The pointer has to be valid through the lifetime of this dialog.
  219. //
  220. // Returns: Nothing
  221. //
  222. // History: fengsun Created Header 1/4/01
  223. //
  224. //+----------------------------------------------------------------------------
  225. CCommonClusterPage::CCommonClusterPage(HINSTANCE hInstance,
  226. NETCFG_WLBS_CONFIG * paramp,
  227. bool fDisablePassword, const DWORD * adwHelpIDs) :
  228. m_IpSubnetControl(IDC_EDIT_CL_IP, IDC_EDIT_CL_MASK)
  229. {
  230. TraceMsg(L"CCommonClusterPage::CCommonClusterPage\n");
  231. m_paramp = paramp;
  232. m_adwHelpIDs = adwHelpIDs;
  233. m_rct_warned = FALSE;
  234. m_igmp_warned = FALSE;
  235. m_igmp_mcast_warned = FALSE;
  236. m_hInstance = hInstance;
  237. m_fDisablePassword = fDisablePassword;
  238. }
  239. /*
  240. * Method: CCommonClusterPage
  241. * Description: The class destructor.
  242. */
  243. CCommonClusterPage::~CCommonClusterPage () {
  244. TraceMsg(L"CCommonClusterPage::~CCommonClusterPage\n");
  245. }
  246. /*
  247. * Method: OnInitDialog
  248. * Description: Called to initialize the cluster properties dialog.
  249. */
  250. LRESULT CCommonClusterPage::OnInitDialog (HWND hWnd)
  251. {
  252. TraceMsg(L"CCommonClusterPage::OnInitDialog\n");
  253. m_hWnd = hWnd;
  254. /* Limit the field ranges for the address and password fields. */
  255. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DOMAIN, EM_SETLIMITTEXT, CVY_MAX_DOMAIN_NAME, 0);
  256. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_ETH, EM_SETLIMITTEXT, CVY_MAX_NETWORK_ADDR, 0);
  257. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_PASSW, EM_SETLIMITTEXT, CVY_MAX_RCT_CODE, 0);
  258. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_PASSW2, EM_SETLIMITTEXT, CVY_MAX_RCT_CODE, 0);
  259. /* Disable the MAC address field. It should be read-only. */
  260. if (m_paramp->fConvertMac) ::EnableWindow(::GetDlgItem (m_hWnd, IDC_EDIT_ETH), FALSE);
  261. /* Copy a dummy password into the parameter set. */
  262. wcsncpy(m_passw, DUMMY_PASSWORD, CVY_MAX_RCT_CODE);
  263. wcsncpy(m_passw2, DUMMY_PASSWORD, CVY_MAX_RCT_CODE);
  264. m_IpSubnetControl.OnInitDialog(m_hWnd, AfxGetInstanceHandle());
  265. return 0;
  266. }
  267. /*
  268. * Method: OnContextMenu
  269. * Description:
  270. */
  271. LRESULT CCommonClusterPage::OnContextMenu ()
  272. {
  273. TraceMsg(L"CCommonClusterPage::OnContextMenu\n");
  274. /* Spawn a help window. */
  275. if (m_adwHelpIDs != NULL)
  276. ::WinHelp(m_hWnd, CVY_CTXT_HELP_FILE, HELP_CONTEXTMENU, (ULONG_PTR)m_adwHelpIDs);
  277. return 0;
  278. }
  279. /*
  280. * Method: OnHelp
  281. * Description:
  282. */
  283. LRESULT CCommonClusterPage::OnHelp (UINT uMsg, WPARAM wParam, LPARAM lParam) {
  284. TraceMsg(L"CCommonClusterPage::OnHelp\n");
  285. LPHELPINFO lphi = reinterpret_cast<LPHELPINFO>(lParam);
  286. /* Spawn a help window. */
  287. if ((HELPINFO_WINDOW == lphi->iContextType) && (m_adwHelpIDs != NULL))
  288. ::WinHelp(static_cast<HWND>(lphi->hItemHandle), CVY_CTXT_HELP_FILE, HELP_WM_HELP, (ULONG_PTR)m_adwHelpIDs);
  289. return 0;
  290. }
  291. /*
  292. * Method: Load
  293. * Description: Called when the cluster settings tab becomes active (is clicked).
  294. */
  295. BOOL CCommonClusterPage::Load (void)
  296. {
  297. TraceMsg(L"CCommonClusterPage::Load\n");
  298. /* Populate the UI with the current configuration. */
  299. SetInfo();
  300. //
  301. // NLB mamager always has password editing disabled
  302. //
  303. /* Enable/disable the password entry boxes based on the state of the remote control checkbox.
  304. Edited( mhakim 02-09-01)
  305. but only when remote control is enabled.
  306. */
  307. ::EnableWindow(::GetDlgItem(m_hWnd, IDC_EDIT_PASSW),
  308. ::IsDlgButtonChecked(m_hWnd, IDC_CHECK_RCT)
  309. &&
  310. ::IsWindowEnabled( ::GetDlgItem( m_hWnd, IDC_CHECK_RCT ) ) );
  311. ::EnableWindow(::GetDlgItem(m_hWnd, IDC_EDIT_PASSW2),
  312. ::IsDlgButtonChecked(m_hWnd, IDC_CHECK_RCT)
  313. &&
  314. ::IsWindowEnabled( ::GetDlgItem( m_hWnd, IDC_CHECK_RCT ) ) );
  315. /* Enable/disable the IGMP checkbox based on the state of the multicast checkbox.
  316. Edited( mhakim 02-09-01)
  317. but only when multicast button is enabled.
  318. */
  319. ::EnableWindow(::GetDlgItem(m_hWnd, IDC_CHECK_IGMP),
  320. ::IsDlgButtonChecked (m_hWnd, IDC_RADIO_MULTICAST)
  321. &&
  322. ::IsWindowEnabled( ::GetDlgItem( m_hWnd, IDC_RADIO_MULTICAST) ) );
  323. /* Fill in the cluster MAC address, based on the values of multicast, IGMP, and the cluster IP. */
  324. SetClusterMACAddress();
  325. ::SetWindowLongPtr(m_hWnd, DWLP_MSGRESULT, PSNRET_NOERROR);
  326. return TRUE;
  327. }
  328. /*
  329. * Method: Save
  330. * Description: Called When the focus moves away from the cluster settings tab.
  331. */
  332. BOOL CCommonClusterPage::Save (void)
  333. {
  334. LRESULT lRet;
  335. TraceMsg(L"CCommonClusterPage::OnKillActive\n");
  336. /* Get the new configuration from the UI. */
  337. UpdateInfo();
  338. lRet = ValidateInfo();
  339. ::SetWindowLongPtr(m_hWnd, DWLP_MSGRESULT, lRet);
  340. return lRet==PSNRET_NOERROR;
  341. }
  342. /*
  343. * Method: OnButtonHelp
  344. * Description: Called when the user clicks the NLB "Help" button.
  345. */
  346. LRESULT CCommonClusterPage::OnButtonHelp (WORD wNotifyCode, WORD wID, HWND hWndCtl) {
  347. WCHAR wbuf[CVY_STR_SIZE];
  348. TraceMsg(L"CCommonClusterPage::OnButtonHelp\n");
  349. switch (wNotifyCode) {
  350. case BN_CLICKED:
  351. /* Spawn the windows help process. */
  352. StringCbPrintf(wbuf, sizeof(wbuf), L"%%WINDIR%%\\help\\%ls::/installation.htm", CVY_HELP_FILE);
  353. _wspawnlp(P_NOWAIT, L"hh.exe", L"hh.exe", wbuf, NULL);
  354. break;
  355. }
  356. return 0;
  357. }
  358. /*
  359. * Method: OnEditClIp
  360. * Description: Called when the user edits the cluster IP address.
  361. */
  362. LRESULT CCommonClusterPage::OnEditClIp (WORD wNotifyCode, WORD wID, HWND hWndCtl) {
  363. TraceMsg(L"CCommonClusterPage::OnEditClIp\n");
  364. switch (wNotifyCode) {
  365. case EN_CHANGE:
  366. /* Update the cluster MAC address. */
  367. SetClusterMACAddress();
  368. break;
  369. }
  370. return 0;
  371. }
  372. /*
  373. * Method: OnIpFieldChange
  374. * Description: Called wnen a field (byte) of the cluster IP address changes. We use this
  375. * to make sure the first byte of the IP is not < 1 or > 223.
  376. */
  377. LRESULT CCommonClusterPage::OnIpFieldChange (int idCtrl, LPNMHDR pnmh, BOOL & fHandled)
  378. {
  379. return m_IpSubnetControl.OnIpFieldChange(idCtrl, pnmh);
  380. }
  381. /*
  382. * Method: OnEditClMask
  383. * Description: Called when the user modifies the cluster netmask.
  384. */
  385. LRESULT CCommonClusterPage::OnEditClMask (WORD wNotifyCode, WORD wID, HWND hWndCtl)
  386. {
  387. return m_IpSubnetControl.OnSubnetMask(wNotifyCode);
  388. }
  389. /*
  390. * Method: OnCheckRct
  391. * Description: Called when the user checks/unchecks the remote control enabled checkbox.
  392. */
  393. LRESULT CCommonClusterPage::OnCheckRct (WORD wNotifyCode, WORD wID, HWND hWndCtl) {
  394. TraceMsg(L"CCommonClusterPage::OnCheckRct\n");
  395. switch (wNotifyCode) {
  396. case BN_CLICKED:
  397. /* Decide whether to enable or diable the password entry boxes based on the value of the remote checkbox. */
  398. ::EnableWindow(::GetDlgItem(m_hWnd, IDC_EDIT_PASSW), ::IsDlgButtonChecked(m_hWnd, IDC_CHECK_RCT));
  399. ::EnableWindow(::GetDlgItem(m_hWnd, IDC_EDIT_PASSW2), ::IsDlgButtonChecked(m_hWnd, IDC_CHECK_RCT));
  400. /* Warn the user about the implications of enabling remote control. */
  401. if (::IsDlgButtonChecked(m_hWnd, IDC_CHECK_RCT) && !m_rct_warned) {
  402. /* Alert the user. */
  403. int iResponse = NcMsgBox(m_hInstance, m_hWnd, IDS_PARM_WARN, IDS_PARM_RCT_WARN,
  404. MB_APPLMODAL | MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2);
  405. if (iResponse == IDYES)
  406. {
  407. //
  408. // Dialog button is already checked, so don't do anything in this case.
  409. //
  410. /* Only warn the user once. */
  411. m_rct_warned = TRUE;
  412. }
  413. else
  414. {
  415. //
  416. // Any response other than Yes means No
  417. //
  418. if (::CheckDlgButton(m_hWnd, IDC_CHECK_RCT, BST_UNCHECKED))
  419. {
  420. TraceMsg(L"CDialogCluster::OnCheckRct unchecking remote control option failed\n");
  421. }
  422. }
  423. }
  424. break;
  425. }
  426. return 0;
  427. }
  428. /*
  429. * Method: OnCheckMode
  430. * Description: Called when the user changes cluster mode.
  431. */
  432. LRESULT CCommonClusterPage::OnCheckMode (WORD wNotifyCode, WORD wID, HWND hWndCtl) {
  433. TraceMsg(L"CCommonClusterPage::OnCheckMode\n");
  434. switch (wNotifyCode) {
  435. case BN_CLICKED:
  436. /* If the user has IGMP checked, but is turning off multicast support, warn them. */
  437. if (::IsDlgButtonChecked(m_hWnd, IDC_CHECK_IGMP) && !::IsDlgButtonChecked(m_hWnd, IDC_RADIO_MULTICAST)) {
  438. if (!m_igmp_mcast_warned) {
  439. /* Alert the user. */
  440. NcMsgBox(m_hInstance, ::GetActiveWindow(), IDS_PARM_WARN, IDS_PARM_IGMP_MCAST,
  441. MB_APPLMODAL | MB_ICONEXCLAMATION | MB_OK);
  442. /* Only warn the user once. */
  443. m_igmp_mcast_warned = TRUE;
  444. }
  445. /* Uncheck and disable the IGMP checkbox and set the IGMP support flag to FALSE. */
  446. ::CheckDlgButton(m_hWnd, IDC_CHECK_IGMP, FALSE);
  447. ::EnableWindow(::GetDlgItem(m_hWnd, IDC_CHECK_IGMP), FALSE);
  448. m_paramp->fIGMPSupport = FALSE;
  449. } else {
  450. /* Enable/disable and check/uncheck the IGMP checkbox based on the value of the cluster mode radio buttons. */
  451. ::EnableWindow(::GetDlgItem(m_hWnd, IDC_CHECK_IGMP), ::IsDlgButtonChecked(m_hWnd, IDC_RADIO_MULTICAST));
  452. }
  453. /* Update the cluster MAC address. */
  454. SetClusterMACAddress();
  455. break;
  456. }
  457. return 0;
  458. }
  459. /*
  460. * Method: OnCheckIGMP
  461. * Description: Called when the user checks/unchecks the IGMP support checkbox.
  462. */
  463. LRESULT CCommonClusterPage::OnCheckIGMP (WORD wNotifyCode, WORD wID, HWND hWndCtl) {
  464. TraceMsg(L"CCommonClusterPage::OnCheckIGMP\n");
  465. switch (wNotifyCode) {
  466. case BN_CLICKED:
  467. /* Update the cluster MAC address. */
  468. SetClusterMACAddress();
  469. /* Warn the user about the implications of enabling remote control. */
  470. if (::IsDlgButtonChecked(m_hWnd, IDC_CHECK_IGMP) && !m_igmp_warned) {
  471. /* Alert the user. */
  472. NcMsgBox(m_hInstance, ::GetActiveWindow(), IDS_PARM_WARN, IDS_PARM_IGMP_WARN,
  473. MB_APPLMODAL | MB_ICONEXCLAMATION | MB_OK);
  474. /* Only warn the user once. */
  475. m_igmp_warned = TRUE;
  476. }
  477. break;
  478. }
  479. return 0;
  480. }
  481. /*
  482. * Method: SetClusterMACAddress
  483. * Description: Used to determine the cluster MAC address based on the cluster IP, and the
  484. * state of multicast and IGMP support.
  485. */
  486. void CCommonClusterPage::SetClusterMACAddress () {
  487. WCHAR cl_ip_addr[CVY_MAX_CL_IP_ADDR + 1];
  488. WCHAR cl_mac_addr[CVY_MAX_NETWORK_ADDR + 1];
  489. TraceMsg(L"CCommonClusterPage::SetClusterMACAddress\n");
  490. /* If the convert MAC flag isn't set, the bail out. */
  491. if (!m_paramp->fConvertMac) return;
  492. /* Retrieve the cluster IP address from the UI. */
  493. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_CL_IP, WM_GETTEXT, CVY_MAX_CL_IP_ADDR + 1, (LPARAM)cl_ip_addr);
  494. /* Generate the cluster MAC address. */
  495. ParamsGenerateMAC(cl_ip_addr, cl_mac_addr, ASIZECCH(cl_mac_addr), m_paramp->szMCastIpAddress, ASIZECCH(m_paramp->szMCastIpAddress), m_paramp->fConvertMac, ::IsDlgButtonChecked(m_hWnd, IDC_RADIO_MULTICAST),
  496. ::IsDlgButtonChecked(m_hWnd, IDC_CHECK_IGMP), m_paramp->fIpToMCastIp);
  497. /* Set the cluster MAC address. */
  498. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_ETH, WM_SETTEXT, 0, (LPARAM)cl_mac_addr);
  499. }
  500. /*
  501. * Method: CheckClusterMACAddress
  502. * Description: Used to check the cluster MAC address in the case where we aren't generating it ourselves.
  503. */
  504. BOOL CCommonClusterPage::CheckClusterMACAddress () {
  505. PWCHAR p1, p2;
  506. WCHAR mac_addr[WLBS_MAX_NETWORK_ADDR + 1];
  507. DWORD i, j;
  508. BOOL flag = TRUE;
  509. /* Valid formats include:
  510. 02:bf:0b:0b:01:01
  511. 02-bf-0b-0b-01-01
  512. 02:bf:0b:b:01:1 */
  513. /* Make a copy of the MAC address. */
  514. ARRAYSTRCPY(mac_addr, m_paramp->cl_mac_addr);
  515. /* Point to the beginning of the MAC. */
  516. p2 = p1 = mac_addr;
  517. /* Loop through all six bytes. */
  518. for (i = 0 ; i < 6 ; i++) {
  519. /* If we are pointing at the end of the string, its invalid. */
  520. if (*p2 == _TEXT('\0')) return FALSE;
  521. /* Convert the hex characters into decimal. */
  522. j = _tcstoul(p1, &p2, 16);
  523. /* If the number is greater than 255, then the format is bad. */
  524. if (j > 255) return FALSE;
  525. /* If the NEXT character is neither a -, :, nor the NUL character, then the format is bad. */
  526. if (!((*p2 == _TEXT('-')) || (*p2 == _TEXT(':')) || (*p2 == _TEXT('\0')))) return FALSE;
  527. /* If the NEXT character is the end of the string, but we don't have enough bytes yet, bail out. */
  528. if (*p2 == _TEXT('\0') && i < 5) return FALSE;
  529. /* Repoint to the NEXT character. */
  530. p1 = p2 + 1;
  531. p2 = p1;
  532. }
  533. return TRUE;
  534. }
  535. /*
  536. * Method: SetInfo
  537. * Description: Called to populate the UI with the current cluster settings.
  538. */
  539. void CCommonClusterPage::SetInfo () {
  540. /* Check (or uncheck) the checkboxes. */
  541. ::CheckDlgButton(m_hWnd, IDC_CHECK_RCT, m_paramp->fRctEnabled);
  542. /* Check the appropriate radio button for cluster mode. */
  543. if (m_paramp->fMcastSupport) {
  544. ::CheckDlgButton(m_hWnd, IDC_RADIO_MULTICAST, TRUE);
  545. if (m_paramp->fIGMPSupport) ::CheckDlgButton(m_hWnd, IDC_CHECK_IGMP, TRUE);
  546. } else
  547. ::CheckDlgButton(m_hWnd, IDC_RADIO_UNICAST, TRUE);
  548. m_IpSubnetControl.SetInfo(m_paramp->cl_ip_addr, m_paramp->cl_net_mask);
  549. /* Fill in the edit boxes. */
  550. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DOMAIN, WM_SETTEXT, 0, (LPARAM)m_paramp->domain_name);
  551. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_ETH, WM_SETTEXT, 0, (LPARAM)m_paramp->cl_mac_addr);
  552. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_PASSW, WM_SETTEXT, 0, (LPARAM)m_passw);
  553. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_PASSW2, WM_SETTEXT, 0, (LPARAM)m_passw2);
  554. }
  555. /*
  556. * Method: UpdateInfo
  557. * Description: Called to copy the UI state to the cluster configuration.
  558. */
  559. void CCommonClusterPage::UpdateInfo () {
  560. TraceMsg(L"CCommonClusterPage::UpdateInfo\n");
  561. /* Retrieve the checkbox values. */
  562. m_paramp->fRctEnabled = ::IsDlgButtonChecked(m_hWnd, IDC_CHECK_RCT) == 1;
  563. /* Retrieve the cluster mode radio button value. */
  564. m_paramp->fIGMPSupport = ::IsDlgButtonChecked(m_hWnd, IDC_CHECK_IGMP) == 1;
  565. m_paramp->fMcastSupport = ::IsDlgButtonChecked(m_hWnd, IDC_RADIO_MULTICAST) == 1;
  566. m_IpSubnetControl.UpdateInfo(m_paramp->cl_ip_addr, m_paramp->cl_net_mask);
  567. /* Retrieve the entry box values. */
  568. // Edited ( mhakim 02-12-01 )
  569. // We need to retrieve one more byte for the domain name and network address.
  570. // ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DOMAIN, WM_GETTEXT, CVY_MAX_DOMAIN_NAME, (LPARAM)m_paramp->domain_name);
  571. // ::SendDlgItemMessage(m_hWnd, IDC_EDIT_ETH, WM_GETTEXT, CVY_MAX_NETWORK_ADDR, (LPARAM)m_paramp->cl_mac_addr);
  572. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DOMAIN, WM_GETTEXT, CVY_MAX_DOMAIN_NAME + 1, (LPARAM)m_paramp->domain_name);
  573. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_ETH, WM_GETTEXT, CVY_MAX_NETWORK_ADDR + 1, (LPARAM)m_paramp->cl_mac_addr);
  574. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_PASSW, WM_GETTEXT, CVY_MAX_RCT_CODE + 1, (LPARAM)m_passw);
  575. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_PASSW2, WM_GETTEXT, CVY_MAX_RCT_CODE + 1, (LPARAM)m_passw2);
  576. }
  577. /*
  578. * Method: ValidateInfo
  579. * Description: Called to validate the entries made by the user.
  580. */
  581. LRESULT CCommonClusterPage::ValidateInfo () {
  582. DWORD IPAddr;
  583. TraceMsg(L"CCommonClusterPage::ValidateInfo\n");
  584. if (!m_IpSubnetControl.ValidateInfo())
  585. {
  586. //
  587. // Check whether IP address and subnet mask pair is valid
  588. //
  589. return PSNRET_INVALID;
  590. }
  591. //
  592. // Get the user input
  593. //
  594. m_IpSubnetControl.UpdateInfo(m_paramp->cl_ip_addr, m_paramp->cl_net_mask);
  595. /* Check to make sure that the dedicated IP and cluster IP are not the same. */
  596. if (!wcscmp(m_paramp->ded_ip_addr, m_paramp->cl_ip_addr)) {
  597. /* Alert the user. */
  598. NcMsgBox(m_hInstance, ::GetActiveWindow(), IDS_PARM_ERROR, IDS_PARM_IP_CONFLICT,
  599. MB_APPLMODAL | MB_ICONSTOP | MB_OK);
  600. /* An error occurred. */
  601. return PSNRET_INVALID;
  602. }
  603. if (!m_paramp->fConvertMac && !CheckClusterMACAddress()) {
  604. /* Alert the user. */
  605. NcMsgBox(m_hInstance, ::GetActiveWindow(), IDS_PARM_ERROR, IDS_PARM_INVAL_MAC,
  606. MB_APPLMODAL | MB_ICONSTOP | MB_OK);
  607. /* An error occurred. */
  608. return PSNRET_INVALID;
  609. }
  610. /* Only check for invalid passwords and update if remote control is enabled. */
  611. if (::IsDlgButtonChecked(m_hWnd, IDC_CHECK_RCT)) {
  612. /* Make sure the passwords match. */
  613. if (wcscmp(m_passw, m_passw2) != 0) {
  614. /* Alert the user. */
  615. NcMsgBox(m_hInstance, ::GetActiveWindow(), IDS_PARM_ERROR, IDS_PARM_PASSWORD,
  616. MB_APPLMODAL | MB_ICONSTOP | MB_OK);
  617. /* Empty the passwords. */
  618. m_passw [0] = m_passw2 [0] = 0;
  619. /* An error occurred. */
  620. return PSNRET_INVALID;
  621. } else {
  622. /* If the new password is not the dummy password, update the password. */
  623. if (wcscmp (m_passw, DUMMY_PASSWORD) != 0) {
  624. ARRAYSTRCPY(m_paramp->szPassword, m_passw);
  625. m_paramp->fChangePassword = true;
  626. }
  627. }
  628. }
  629. return PSNRET_NOERROR;
  630. }