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.

584 lines
22 KiB

  1. /*++
  2. Copyright(c) 1998,99 Microsoft Corporation
  3. Module Name:
  4. host.cpp
  5. Abstract:
  6. Windows Load Balancing Service (WLBS)
  7. Notifier object UI - host config tab
  8. Author:
  9. kyrilf
  10. shouse
  11. --*/
  12. #include "pch.h"
  13. #pragma hdrstop
  14. #include "ncatlui.h"
  15. #include "resource.h"
  16. #include "wlbsparm.h"
  17. #include "wlbscfg.h"
  18. #include "host.h"
  19. #include "utils.h"
  20. #include <winsock2.h>
  21. #include <strsafe.h>
  22. #if DBG
  23. static void TraceMsg(PCTSTR pszFormat, ...);
  24. #else
  25. #define TraceMsg NOP_FUNCTION
  26. #endif
  27. /*
  28. * Method: CDialogHost
  29. * Description: The class constructor.
  30. */
  31. CDialogHost::CDialogHost (NETCFG_WLBS_CONFIG * paramp, const DWORD * adwHelpIDs) {
  32. TraceMsg(L"CDialogHost::CDialogHost\n");
  33. m_paramp = paramp;
  34. m_adwHelpIDs = adwHelpIDs;
  35. ZeroMemory(&m_IPFieldChangeState, sizeof(m_IPFieldChangeState));
  36. }
  37. /*
  38. * Method: ~CDialogHost
  39. * Description: The class destructor.
  40. */
  41. CDialogHost::~CDialogHost () {
  42. TraceMsg(L"CDialogHost::~CDialogHost\n");
  43. }
  44. /*
  45. * Method: OnInitDialog
  46. * Description: Called to initialize the host properties dialog.
  47. */
  48. LRESULT CDialogHost::OnInitDialog (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & fHandled) {
  49. INT iItem;
  50. INT cItems;
  51. TraceMsg(L"CDialogHost::OnInitDialog\n");
  52. /* Always tell NetCfg that the page has changed, so we don't have to keep track of this. */
  53. SetChangedFlag();
  54. /* Limit the field ranges for the address and priority fields. */
  55. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DED_IP, EM_SETLIMITTEXT, CVY_MAX_DED_IP_ADDR, 0);
  56. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DED_MASK, EM_SETLIMITTEXT, CVY_MAX_DED_NET_MASK, 0);
  57. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_PRI, EM_SETLIMITTEXT, 2, 0);
  58. ::SendDlgItemMessage(m_hWnd, IDC_SPIN_PRI, UDM_SETRANGE32, CVY_MIN_MAX_HOSTS, m_paramp->dwMaxHosts);
  59. /* Limit the zeroth field of the dedicated IP address between 1 and 223. */
  60. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DED_IP, IPM_SETRANGE, 0, (LPARAM)MAKEIPRANGE(WLBS_IP_FIELD_ZERO_LOW, WLBS_IP_FIELD_ZERO_HIGH));
  61. /* If the cluster IP address or subnet mask are the default values, set them to NUL strings. */
  62. if (!wcscmp(m_paramp->ded_ip_addr, CVY_DEF_DED_IP_ADDR)) m_paramp->ded_ip_addr[0] = 0;
  63. if (!wcscmp(m_paramp->ded_net_mask, CVY_DEF_DED_NET_MASK)) m_paramp->ded_net_mask[0] = 0;
  64. /* Insert "Started" into the dropdown list for initial host state. Set its data to CVY_HOST_STATE_STARTED (1). */
  65. iItem = (INT)SendDlgItemMessage(IDC_COMBOBOX_DEFAULT_STATE, CB_ADDSTRING, 0, (LPARAM)SzLoadIds(IDS_HOST_STATE_STARTED));
  66. SendDlgItemMessage(IDC_COMBOBOX_DEFAULT_STATE, CB_SETITEMDATA, iItem, (LPARAM)CVY_HOST_STATE_STARTED);
  67. /* Insert "Stopped" into the dropdown list for initial host state. Set its data to CVY_HOST_STATE_STOPPED (0). */
  68. iItem = (INT)SendDlgItemMessage(IDC_COMBOBOX_DEFAULT_STATE, CB_ADDSTRING, 0, (LPARAM)SzLoadIds(IDS_HOST_STATE_STOPPED));
  69. SendDlgItemMessage(IDC_COMBOBOX_DEFAULT_STATE, CB_SETITEMDATA, iItem, (LPARAM)CVY_HOST_STATE_STOPPED);
  70. /* Insert "Suspended" into the dropdown list for initial host state. Set its data to CVY_HOST_STATE_SUSPENDED (2). */
  71. iItem = (INT)SendDlgItemMessage(IDC_COMBOBOX_DEFAULT_STATE, CB_ADDSTRING, 0, (LPARAM)SzLoadIds(IDS_HOST_STATE_SUSPENDED));
  72. SendDlgItemMessage(IDC_COMBOBOX_DEFAULT_STATE, CB_SETITEMDATA, iItem, (LPARAM)CVY_HOST_STATE_SUSPENDED);
  73. /* Get the number of items added to ths dropdown list. */
  74. cItems = (INT)SendDlgItemMessage(IDC_COMBOBOX_DEFAULT_STATE, CB_GETCOUNT);
  75. /* This had better be 3. */
  76. ASSERT(cItems == 3);
  77. return 0;
  78. }
  79. /*
  80. * Method: OnContextMenu
  81. * Description:
  82. */
  83. LRESULT CDialogHost::OnContextMenu (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & fHandled) {
  84. TraceMsg(L"CDialogHost::OnContextMenu\n");
  85. /* Spawn a help window. */
  86. if (m_adwHelpIDs != NULL)
  87. ::WinHelp(m_hWnd, CVY_CTXT_HELP_FILE, HELP_CONTEXTMENU, (ULONG_PTR)m_adwHelpIDs);
  88. return 0;
  89. }
  90. /*
  91. * Method: OnHelp
  92. * Description:
  93. */
  94. LRESULT CDialogHost::OnHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & fHandled) {
  95. TraceMsg(L"CDialogHost::OnHelp\n");
  96. LPHELPINFO lphi = reinterpret_cast<LPHELPINFO>(lParam);
  97. /* Spawn a help window. */
  98. if ((HELPINFO_WINDOW == lphi->iContextType) && (m_adwHelpIDs != NULL))
  99. ::WinHelp(static_cast<HWND>(lphi->hItemHandle), CVY_CTXT_HELP_FILE, HELP_WM_HELP, (ULONG_PTR)m_adwHelpIDs);
  100. return 0;
  101. }
  102. /*
  103. * Method: OnActive
  104. * Description: Called when the host settings tab becomes active (is clicked).
  105. */
  106. LRESULT CDialogHost::OnActive (int idCtrl, LPNMHDR pnmh, BOOL & fHandled) {
  107. TraceMsg(L"CDialogHost::OnActive\n");
  108. /* Populate the UI with the current configuration. */
  109. SetInfo();
  110. ::SetWindowLongPtr(m_hWnd, DWLP_MSGRESULT, PSNRET_NOERROR);
  111. return 0;
  112. }
  113. /*
  114. * Method: OnKillActive
  115. * Description: Called When the focus moves away from the host settings tab.
  116. */
  117. LRESULT CDialogHost::OnKillActive (int idCtrl, LPNMHDR pnmh, BOOL & fHandled) {
  118. TraceMsg(L"CDialogHost::OnKillActive\n");
  119. /* Get the new configuration from the UI. */
  120. UpdateInfo();
  121. ::SetWindowLongPtr(m_hWnd, DWLP_MSGRESULT, PSNRET_NOERROR);
  122. return 0;
  123. }
  124. /*
  125. * Method: OnApply
  126. * Description: Called when the user clicks "OK".
  127. */
  128. LRESULT CDialogHost::OnApply (int idCtrl, LPNMHDR pnmh, BOOL & fHandled) {
  129. LRESULT fError = PSNRET_NOERROR;
  130. TraceMsg(L"CDialogHost::OnApply\n");
  131. /* Validate the UI values entered by the user. */
  132. fError = ValidateInfo();
  133. /* If the user has not specified dedicated IP address information, copy the defaults back. */
  134. if (!fError && !m_paramp->ded_ip_addr[0])
  135. {
  136. (VOID) StringCchCopy(m_paramp->ded_ip_addr, ASIZECCH(m_paramp->ded_ip_addr), CVY_DEF_DED_IP_ADDR);
  137. }
  138. if (!fError && !m_paramp->ded_net_mask[0])
  139. {
  140. (VOID) StringCchCopy(m_paramp->ded_net_mask, ASIZECCH(m_paramp->ded_net_mask), CVY_DEF_DED_NET_MASK);
  141. }
  142. ::SetWindowLongPtr(m_hWnd, DWLP_MSGRESULT, fError);
  143. return fError;
  144. }
  145. /*
  146. * Method: OnCancel
  147. * Description: Called when the user clicks "Cancel".
  148. */
  149. LRESULT CDialogHost::OnCancel (int idCtrl, LPNMHDR pnmh, BOOL & fHandled) {
  150. TraceMsg(L"CDialogHost::OnCancel\n");
  151. return 0;
  152. }
  153. /*
  154. * Method: OnEditDedMask
  155. * Description: Called when the user modifies the host netmask.
  156. */
  157. LRESULT CDialogHost::OnEditDedMask (WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL & fHandled) {
  158. WCHAR ded_ip_addr [CVY_MAX_DED_IP_ADDR + 1];
  159. WCHAR ded_mask_addr [CVY_MAX_DED_NET_MASK + 1];
  160. TraceMsg(L"CDialogHost::OnEditDedMask\n");
  161. switch (wNotifyCode) {
  162. case EN_SETFOCUS:
  163. /* Only generate a netmask if the netmask is currently empty and the IP address is not. */
  164. if (::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_MASK), IPM_ISBLANK, 0, 0) &&
  165. !::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_IP), IPM_ISBLANK, 0, 0)) {
  166. /* Retrieve the cluster IP address. */
  167. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DED_IP, WM_GETTEXT, CVY_MAX_DED_IP_ADDR + 1, (LPARAM)ded_ip_addr);
  168. /* Fill the subnet mask. */
  169. ParamsGenerateSubnetMask(ded_ip_addr, ded_mask_addr, ASIZECCH(ded_mask_addr));
  170. /* Set the cluster subnet mask. */
  171. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DED_MASK, WM_SETTEXT, 0, (LPARAM)ded_mask_addr);
  172. break;
  173. }
  174. }
  175. return 0;
  176. }
  177. /*
  178. * Method: PrintRangeError
  179. * Description: Displays a message box warning the user of an out-of-range entry.
  180. */
  181. void CDialogHost::PrintRangeError (unsigned int ids, int low, int high) {
  182. WCHAR szLow[12]; // size = sign + n,nnn,nnn,nnn + null-terminator
  183. WCHAR szHigh[12];
  184. TraceMsg(L"CDialogHost::PrintRangeError\n");
  185. /* Fill in the range and the offending value. */
  186. StringCchPrintf(szHigh, ASIZECCH(szHigh), L"%d", high);
  187. StringCchPrintf(szLow , ASIZECCH(szLow) , L"%d", low);
  188. /* Pop-up a message box. */
  189. NcMsgBox(m_hWnd, IDS_PARM_ERROR, ids, MB_APPLMODAL | MB_ICONSTOP | MB_OK, szLow, szHigh);
  190. }
  191. /*
  192. * Method: PrintIPRangeError
  193. * Description: Displays a message box warning the user of an out-of-range entry in
  194. * an IP address octet.
  195. */
  196. void CDialogHost::PrintIPRangeError (unsigned int ids, int value, int low, int high) {
  197. WCHAR szCurrent[12]; // size = sign + n,nnn,nnn,nnn + null-terminator
  198. WCHAR szLow[12];
  199. WCHAR szHigh[12];
  200. TraceMsg(L"CDialogHost::PrintIPRangeError\n");
  201. /* Fill in the range and the offending value. */
  202. StringCchPrintf(szHigh , ASIZECCH(szHigh) , L"%d", high);
  203. StringCchPrintf(szCurrent, ASIZECCH(szCurrent), L"%d", value);
  204. StringCchPrintf(szLow , ASIZECCH(szLow) , L"%d", low);
  205. /* Pop-up a message box. */
  206. NcMsgBox(m_hWnd, IDS_PARM_ERROR, ids, MB_APPLMODAL | MB_ICONSTOP | MB_OK, szCurrent, szLow, szHigh);
  207. }
  208. /*
  209. * Method: OnIpFieldChange
  210. * Description: Called wnen a field (byte) of the dedicated IP address changes. We use this
  211. * to make sure the first byte of the IP is not < 1 or > 223.
  212. */
  213. LRESULT CDialogHost::OnIpFieldChange (int idCtrl, LPNMHDR pnmh, BOOL & fHandled) {
  214. LPNMIPADDRESS Ip;
  215. int low = WLBS_FIELD_LOW;
  216. int high = WLBS_FIELD_HIGH;
  217. TraceMsg(L"CDialogHost::OnIpFieldChange\n");
  218. Ip = (LPNMIPADDRESS)pnmh;
  219. switch(idCtrl) {
  220. case IDC_EDIT_DED_IP:
  221. /* Field zero of the cluster IP address has different limits. */
  222. if (!Ip->iField) {
  223. low = WLBS_IP_FIELD_ZERO_LOW;
  224. high = WLBS_IP_FIELD_ZERO_HIGH;
  225. }
  226. case IDC_EDIT_DED_MASK:
  227. /* The notifier may call us twice for the same change, so we have to do the bookkeeping to make
  228. sure we only alert the user once. Use static variables to keep track of our state. This will
  229. allow us to ignore duplicate alerts. */
  230. if ((m_IPFieldChangeState.IpControl != Ip->hdr.idFrom) || (m_IPFieldChangeState.Field != Ip->iField) ||
  231. (m_IPFieldChangeState.Value != Ip->iValue) || (m_IPFieldChangeState.RejectTimes > 0)) {
  232. m_IPFieldChangeState.RejectTimes = 0;
  233. m_IPFieldChangeState.IpControl = (UINT)(Ip->hdr.idFrom);
  234. m_IPFieldChangeState.Field = Ip->iField;
  235. m_IPFieldChangeState.Value = Ip->iValue;
  236. /* Check the field value against its limits. */
  237. if ((Ip->iValue != WLBS_FIELD_EMPTY) && ((Ip->iValue < low) || (Ip->iValue > high))) {
  238. /* Alert the user. */
  239. PrintIPRangeError((idCtrl == IDC_EDIT_DED_IP) ? IDS_PARM_DED_IP_FIELD : IDS_PARM_DED_NM_FIELD, Ip->iValue, low, high);
  240. }
  241. } else m_IPFieldChangeState.RejectTimes++;
  242. break;
  243. default:
  244. break;
  245. }
  246. return 0;
  247. }
  248. /*
  249. * Method: SetInfo
  250. * Description: Called to populate the UI with the current host settings.
  251. */
  252. void CDialogHost::SetInfo () {
  253. DWORD addr[4];
  254. INT cItems;
  255. INT iItem;
  256. TraceMsg(L"CDialogHost::SetInfo\n");
  257. /* Get the number of items in the dropdown list. */
  258. cItems = (INT)SendDlgItemMessage(IDC_COMBOBOX_DEFAULT_STATE, CB_GETCOUNT);
  259. /* This MUST be 3. */
  260. ASSERT(cItems == 3);
  261. /* Loop through the items looking for the one currently selected in the registry. */
  262. for (iItem = 0; iItem < cItems; iItem++) {
  263. /* The "state" is the item data that we inserted during OnInitDialog. */
  264. INT state = (INT)SendDlgItemMessage(IDC_COMBOBOX_DEFAULT_STATE, CB_GETITEMDATA, iItem, 0);
  265. /* If this is the one currently set in the registry, make it the current selection. */
  266. if (m_paramp->dwInitialState == state) {
  267. SendDlgItemMessage(IDC_COMBOBOX_DEFAULT_STATE, CB_SETCURSEL, iItem, 0);
  268. break;
  269. }
  270. }
  271. /* Check (or uncheck) the persist suspended state checkbox. */
  272. ::CheckDlgButton(m_hWnd, IDC_CHECK_PERSIST_SUSPEND, m_paramp->dwPersistedStates & CVY_PERSIST_STATE_SUSPENDED);
  273. /* If the dedicated IP address is empty, then clear the entry box. Otherwise, populate it with the IP address. */
  274. if (!m_paramp->ded_ip_addr[0])
  275. ::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_IP), IPM_CLEARADDRESS, 0, 0);
  276. else {
  277. /* Extract the IP address octects from the IP address string. */
  278. GetIPAddressOctets(m_paramp->ded_ip_addr, addr);
  279. ::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_IP), IPM_SETADDRESS, 0, (LPARAM)MAKEIPADDRESS(addr[0], addr[1], addr[2], addr[3]));
  280. }
  281. /* If the host subnet mask is empty, then clear the entry box. Otherwise, populate it with the netmask. */
  282. if (!m_paramp->ded_net_mask[0])
  283. ::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_MASK), IPM_CLEARADDRESS, 0, 0);
  284. else {
  285. /* Extract the IP address octects from the IP address string. */
  286. GetIPAddressOctets(m_paramp->ded_net_mask, addr);
  287. ::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_MASK), IPM_SETADDRESS, 0, (LPARAM)MAKEIPADDRESS(addr[0], addr[1], addr[2], addr[3]));
  288. }
  289. /* Fill in the host priority entry box. If the entry is blank or out of range, insert an empty string. */
  290. if (m_paramp->dwHostPriority >= CVY_MIN_HOST_PRIORITY && m_paramp->dwHostPriority <= CVY_MAX_HOST_PRIORITY)
  291. ::SetDlgItemInt(m_hWnd, IDC_EDIT_PRI, m_paramp->dwHostPriority, FALSE);
  292. else
  293. ::SetDlgItemText(m_hWnd, IDC_EDIT_PRI, L"");
  294. }
  295. /*
  296. * Method: UpdateInfo
  297. * Description: Called to copy the UI state to the host configuration.
  298. */
  299. void CDialogHost::UpdateInfo () {
  300. BOOL fValid = TRUE;
  301. INT iItem;
  302. TraceMsg(L"CDialogHost::UpdateInfo\n");
  303. /* Get the current selection from the dropdown list. */
  304. iItem = (INT)SendDlgItemMessage(IDC_COMBOBOX_DEFAULT_STATE, CB_GETCURSEL, 0, 0);
  305. /* Get the item data for the current selection and store it. */
  306. m_paramp->dwInitialState = (INT)SendDlgItemMessage(IDC_COMBOBOX_DEFAULT_STATE, CB_GETITEMDATA, iItem, 0);
  307. /* If the persist suspend checkbox is checked, then set the suspend bit
  308. in the persisted states registry setting; otherwise, clear that bit. */
  309. if (::IsDlgButtonChecked(m_hWnd, IDC_CHECK_PERSIST_SUSPEND))
  310. m_paramp->dwPersistedStates |= CVY_PERSIST_STATE_SUSPENDED;
  311. else
  312. m_paramp->dwPersistedStates &= ~CVY_PERSIST_STATE_SUSPENDED;
  313. /* If the dedicated IP entry box is empty, then the dedicated IP address is NUL. Otherwise, grab it from the UI. */
  314. if (::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_IP), IPM_ISBLANK, 0, 0))
  315. m_paramp->ded_ip_addr[0] = 0;
  316. else
  317. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DED_IP, WM_GETTEXT, CVY_MAX_DED_IP_ADDR + 1, (LPARAM)m_paramp->ded_ip_addr);
  318. /* If the host net mask entry box is empty, then the host net mask is NUL. Otherwise, grab it from the UI. */
  319. if (::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_MASK), IPM_ISBLANK, 0, 0))
  320. m_paramp->ded_net_mask[0] = 0;
  321. else
  322. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DED_MASK, WM_GETTEXT, CVY_MAX_DED_NET_MASK + 1, (LPARAM)m_paramp->ded_net_mask);
  323. /* Retrieve the host priority from the entry box. */
  324. m_paramp->dwHostPriority = ::GetDlgItemInt(m_hWnd, IDC_EDIT_PRI, &fValid, FALSE);
  325. /* The error code from GetDlgItemInt() indicates an error converting the alphanumeric
  326. string to an integer. This allows us to check for empty fields, assuming that because
  327. we otherwise limit the user input to digits, there will be no errors of any other type.
  328. In this case, we set the priority to a sentinnel value that will be checked later. */
  329. if (!fValid) m_paramp->dwHostPriority = WLBS_BLANK_HPRI;
  330. }
  331. /*
  332. * Method: ValidateInfo
  333. * Description: Called to validate the entries made by the user.
  334. */
  335. BOOL CDialogHost::ValidateInfo () {
  336. BOOL fError = FALSE;
  337. DWORD IPAddr;
  338. TraceMsg(L"CDialogHost::ValidateInfo\n");
  339. /* Check for an invalid host priority. */
  340. if ((m_paramp->dwHostPriority < CVY_MIN_HOST_PRIORITY) || (m_paramp->dwHostPriority > m_paramp->dwMaxHosts)) {
  341. /* Help the user by setting the priority to the closest viable value. */
  342. if (m_paramp->dwHostPriority != WLBS_BLANK_HPRI) {
  343. /* Alert the user. */
  344. PrintRangeError(IDS_PARM_PRI, CVY_MIN_HOST_PRIORITY, CVY_MAX_HOST_PRIORITY);
  345. CVY_CHECK_MIN(m_paramp->dwHostPriority, CVY_MIN_HOST_PRIORITY);
  346. CVY_CHECK_MAX(m_paramp->dwHostPriority, CVY_MAX_HOST_PRIORITY);
  347. /* Set the handling priority to the now valid entry. */
  348. ::SetDlgItemInt(m_hWnd, IDC_EDIT_PRI, m_paramp->dwHostPriority, FALSE);
  349. } else {
  350. /* Alert the user. */
  351. PrintRangeError(IDS_PARM_PRI_BLANK, CVY_MIN_HOST_PRIORITY, CVY_MAX_HOST_PRIORITY);
  352. }
  353. /* An error occurred. */
  354. return PSNRET_INVALID;
  355. }
  356. /* Check for blank dedicated IP address with a non-empty netmask. */
  357. if (!::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_MASK), IPM_ISBLANK, 0, 0) &&
  358. ::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_IP), IPM_ISBLANK, 0, 0)) {
  359. /* Alert the user. */
  360. NcMsgBox(::GetActiveWindow(), IDS_PARM_ERROR, IDS_PARM_DED_IP_BLANK,
  361. MB_APPLMODAL | MB_ICONSTOP | MB_OK);
  362. /* An error occurred. */
  363. return PSNRET_INVALID;
  364. }
  365. /* Check for blank netmask with a non-empty dedicated IP address and fill in the netmask if necessary. */
  366. if (!::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_IP), IPM_ISBLANK, 0, 0) &&
  367. ::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_MASK), IPM_ISBLANK, 0, 0)) {
  368. /* Fill in the netmask for the user. */
  369. OnEditDedMask(EN_SETFOCUS, 0, 0, fError);
  370. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DED_MASK, WM_GETTEXT, CVY_MAX_DED_NET_MASK + 1, (LPARAM)m_paramp->ded_net_mask);
  371. /* Alert the user. */
  372. NcMsgBox(::GetActiveWindow(), IDS_PARM_ERROR, IDS_PARM_DED_NM_BLANK,
  373. MB_APPLMODAL | MB_ICONSTOP | MB_OK);
  374. /* An error occurred. */
  375. return PSNRET_INVALID;
  376. }
  377. /* Only perform the rest of the IP checking if the user has specified both a dedicated
  378. IP address and a corresponding netmask. */
  379. if (!::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_IP), IPM_ISBLANK, 0, 0) &&
  380. !::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_MASK), IPM_ISBLANK, 0, 0)) {
  381. /* Get the dedicated IP address. */
  382. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DED_IP, IPM_GETADDRESS, 0, (LPARAM)&IPAddr);
  383. /* Make sure that the first octet is not zero. If it is, make it 1 and alter the user. */
  384. if (!FIRST_IPADDRESS(IPAddr)) {
  385. /* Make the first octet 1 instead of the erroneous 0. */
  386. IPAddr = IPAddr | (DWORD)(WLBS_IP_FIELD_ZERO_LOW << 24);
  387. /* Set the IP address and update our dedicated IP address string. */
  388. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DED_IP, IPM_SETADDRESS, 0, (LPARAM)IPAddr);
  389. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DED_IP, WM_GETTEXT, CVY_MAX_DED_IP_ADDR + 1, (LPARAM)m_paramp->ded_ip_addr);
  390. /* Alert the user. */
  391. PrintIPRangeError(IDS_PARM_DED_IP_FIELD, 0, WLBS_IP_FIELD_ZERO_LOW, WLBS_IP_FIELD_ZERO_HIGH);
  392. return PSNRET_INVALID;
  393. }
  394. /* Check for valid dedicated IP address/netmask pairs. */
  395. if (!IsValidIPAddressSubnetMaskPair(m_paramp->ded_ip_addr, m_paramp->ded_net_mask)) {
  396. /* Alert the user. */
  397. NcMsgBox(::GetActiveWindow(), IDS_PARM_ERROR, IDS_PARM_INVAL_DED_IP,
  398. MB_APPLMODAL | MB_ICONSTOP | MB_OK);
  399. /* An error occurred. */
  400. return PSNRET_INVALID;
  401. }
  402. /* Check to make sure that the netmask is contiguous. */
  403. if (!IsContiguousSubnetMask(m_paramp->ded_net_mask)) {
  404. /* Alert the user. */
  405. NcMsgBox(::GetActiveWindow(), IDS_PARM_ERROR, IDS_PARM_INVAL_DED_MASK,
  406. MB_APPLMODAL | MB_ICONSTOP | MB_OK);
  407. /* An error occurred. */
  408. return PSNRET_INVALID;
  409. }
  410. /* Check if the Dedicated IP Address is not the same as one of the VIPs */
  411. DWORD dwNumRules = m_paramp->dwNumRules;
  412. while(dwNumRules--)
  413. {
  414. /* If this port rule has specified a virtual IP address, make sure it
  415. doesn't match the DIP the user has specified here. */
  416. if (lstrcmpi(m_paramp->port_rules[dwNumRules].virtual_ip_addr, CVY_DEF_ALL_VIP)) {
  417. if (IpAddressFromAbcdWsz(m_paramp->ded_ip_addr) == IpAddressFromAbcdWsz(m_paramp->port_rules[dwNumRules].virtual_ip_addr))
  418. {
  419. /* Alert the user. */
  420. NcMsgBox(::GetActiveWindow(), IDS_PARM_ERROR, IDS_PARM_DIP_CONFLICT_VIP,
  421. MB_APPLMODAL | MB_ICONSTOP | MB_OK);
  422. /* An error occurred. */
  423. return PSNRET_INVALID;
  424. }
  425. }
  426. }
  427. }
  428. return PSNRET_NOERROR;
  429. }
  430. #if DBG
  431. /*
  432. * Function: TraceMsg
  433. * Description: Generate a trace or error message.
  434. */
  435. void TraceMsg (PCWSTR pszFormat, ...) {
  436. static WCHAR szTempBufW[4096];
  437. static CHAR szTempBufA[4096];
  438. va_list arglist;
  439. va_start(arglist, pszFormat);
  440. (VOID) StringCchVPrintf(szTempBufW, ASIZECCH(szTempBufW), pszFormat, arglist);
  441. /* Convert the WCHAR to CHAR. This is for backward compatability with TraceMsg
  442. so that it was not necessary to change all pre-existing calls thereof. */
  443. if(WideCharToMultiByte(CP_ACP, 0, szTempBufW, -1, szTempBufA, ASIZECCH(szTempBufA), NULL, NULL) != 0)
  444. {
  445. /* Traced messages are now sent through the netcfg TraceTag routine so that
  446. they can be turned on/off dynamically. */
  447. TraceTag(ttidWlbs, szTempBufA);
  448. }
  449. va_end(arglist);
  450. }
  451. #endif