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.

350 lines
12 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. #include <stdio.h>
  4. #include <process.h>
  5. #include "IpSubnetMaskControl.h"
  6. #include "wlbsconfig.h"
  7. #include "wlbsutil.h"
  8. /* Limitations for IP address fields. */
  9. #define WLBS_FIELD_EMPTY -1
  10. #define WLBS_FIELD_LOW 0
  11. #define WLBS_FIELD_HIGH 255
  12. #define WLBS_BLANK_HPRI -1
  13. void PrintIPRangeError(HINSTANCE hInstance, HWND hWnd, unsigned int ids, int value, int low, int high);
  14. CIpSubnetMaskControl::CIpSubnetMaskControl(DWORD dwIpAddressId, DWORD dwSubnetMaskId)
  15. {
  16. m_dwIpAddressId = dwIpAddressId;
  17. m_dwSubnetMaskId = dwSubnetMaskId;
  18. m_hWndDialog = NULL;
  19. m_hInstance = NULL;
  20. ZeroMemory(&m_IPFieldChangeState, sizeof(m_IPFieldChangeState));
  21. }
  22. //+----------------------------------------------------------------------------
  23. //
  24. // Function: CIpSubnetMaskControl::OnInitDialog
  25. //
  26. // Description: Called upon WM_INITDIALOG message.
  27. //
  28. // Arguments: HWND hWnd - the parent dialog window
  29. // HINSTANCE hInstance - instance handle for resources
  30. //
  31. // Returns: Nothing
  32. //
  33. // History: fengsun Created Header 1/10/01
  34. //
  35. //+----------------------------------------------------------------------------
  36. void CIpSubnetMaskControl::OnInitDialog(HWND hWnd, HINSTANCE hInstance)
  37. {
  38. m_hWndDialog = hWnd;
  39. m_hInstance = hInstance;
  40. /* Limit the field ranges for the address fields. */
  41. ::SendDlgItemMessage(hWnd, m_dwIpAddressId, EM_SETLIMITTEXT, CVY_MAX_CL_IP_ADDR, 0);
  42. ::SendDlgItemMessage(hWnd, m_dwSubnetMaskId, EM_SETLIMITTEXT, CVY_MAX_CL_NET_MASK, 0);
  43. /* Limit the zeroth field of the dedicated IP address between 1 and 223. */
  44. ::SendDlgItemMessage(m_hWndDialog, m_dwIpAddressId, IPM_SETRANGE, 0, (LPARAM)MAKEIPRANGE(WLBS_IP_FIELD_ZERO_LOW, WLBS_IP_FIELD_ZERO_HIGH));
  45. }
  46. /*
  47. * Method: OnSubnetMask
  48. * Description: Called when the user modifies the host netmask.
  49. */
  50. LRESULT CIpSubnetMaskControl::OnSubnetMask(WORD wNotifyCode)
  51. {
  52. WCHAR wszIpAddress [CVY_MAX_CL_IP_ADDR + 1];
  53. WCHAR wszSubnetMask [CVY_MAX_CL_NET_MASK + 1];
  54. switch (wNotifyCode)
  55. {
  56. case EN_SETFOCUS:
  57. /* Only generate a netmask if the netmask is currently empty and the IP address is not. */
  58. if (::SendMessage(::GetDlgItem(m_hWndDialog, m_dwSubnetMaskId), IPM_ISBLANK, 0, 0) &&
  59. !::SendMessage(::GetDlgItem(m_hWndDialog, m_dwIpAddressId), IPM_ISBLANK, 0, 0))
  60. {
  61. /* Retrieve the cluster IP address. */
  62. ::SendDlgItemMessage(m_hWndDialog, m_dwIpAddressId, WM_GETTEXT, CVY_MAX_CL_IP_ADDR + 1, (LPARAM)wszIpAddress);
  63. /* Fill the subnet mask. */
  64. ParamsGenerateSubnetMask(wszIpAddress, wszSubnetMask, ASIZECCH(wszSubnetMask));
  65. /* Set the cluster subnet mask. */
  66. ::SendDlgItemMessage(m_hWndDialog, m_dwSubnetMaskId, WM_SETTEXT, 0, (LPARAM)wszSubnetMask);
  67. break;
  68. }
  69. }
  70. return 0;
  71. }
  72. /*
  73. * Method: OnIpFieldChange
  74. * Description: Called wnen a field (byte) of the IP address/subnetmask changes. We use this
  75. * to make sure the first byte of the IP is not < 1 or > 223.
  76. */
  77. LRESULT CIpSubnetMaskControl::OnIpFieldChange(int idCtrl, LPNMHDR pnmh)
  78. {
  79. LPNMIPADDRESS Ip;
  80. int low = WLBS_FIELD_LOW;
  81. int high = WLBS_FIELD_HIGH;
  82. Ip = (LPNMIPADDRESS)pnmh;
  83. if (idCtrl == m_dwIpAddressId)
  84. {
  85. /* Field zero of the cluster IP address has different limits. */
  86. if (!Ip->iField)
  87. {
  88. low = WLBS_IP_FIELD_ZERO_LOW;
  89. high = WLBS_IP_FIELD_ZERO_HIGH;
  90. }
  91. }
  92. /* The notifier may call us twice for the same change, so we have to do the bookkeeping to make
  93. sure we only alert the user once. Use static variables to keep track of our state. This will
  94. allow us to ignore duplicate alerts. */
  95. if ((m_IPFieldChangeState.IpControl != Ip->hdr.idFrom) || (m_IPFieldChangeState.Field != Ip->iField) ||
  96. (m_IPFieldChangeState.Value != Ip->iValue) || (m_IPFieldChangeState.RejectTimes > 0)) {
  97. m_IPFieldChangeState.RejectTimes = 0;
  98. m_IPFieldChangeState.IpControl = Ip->hdr.idFrom;
  99. m_IPFieldChangeState.Field = Ip->iField;
  100. m_IPFieldChangeState.Value = Ip->iValue;
  101. /* Check the field value against its limits. */
  102. if ((Ip->iValue != WLBS_FIELD_EMPTY) && ((Ip->iValue < low) || (Ip->iValue > high)))
  103. {
  104. /* Alert the user. */
  105. PrintIPRangeError(m_hInstance, m_hWndDialog,
  106. (idCtrl == m_dwIpAddressId) ? IDS_PARM_CL_IP_FIELD : IDS_PARM_CL_NM_FIELD,
  107. Ip->iValue, low, high);
  108. }
  109. } else m_IPFieldChangeState.RejectTimes++;
  110. return 0;
  111. }
  112. //+----------------------------------------------------------------------------
  113. //
  114. // Function: CIpSubnetMaskControl::SetInfo
  115. //
  116. // Description: Set the value to the control
  117. //
  118. // Arguments: const WCHAR* pszIpAddress -
  119. // const WCHAR* pszSubnetMask -
  120. //
  121. // Returns: Nothing
  122. //
  123. // History: shouse initial code
  124. // fengsun Created Header 1/10/01
  125. //
  126. //+----------------------------------------------------------------------------
  127. void CIpSubnetMaskControl::SetInfo(const WCHAR* pszIpAddress, const WCHAR* pszSubnetMask)
  128. {
  129. /* If the cluster IP address or subnet mask are the default values, set them to NUL strings. */
  130. /* If the dedicated IP address is empty, then clear the entry box. Otherwise, populate it with the IP address. */
  131. if (!pszIpAddress[0] || !wcscmp(pszIpAddress, CVY_DEF_CL_IP_ADDR))
  132. ::SendMessage(::GetDlgItem(m_hWndDialog, m_dwIpAddressId), IPM_CLEARADDRESS, 0, 0);
  133. else
  134. ::SendDlgItemMessage(m_hWndDialog, m_dwIpAddressId, WM_SETTEXT, 0, (LPARAM)pszIpAddress);
  135. /* If the host subnet mask is empty, then clear the entry box. Otherwise, populate it with the netmask. */
  136. if (!pszSubnetMask[0] || !wcscmp(pszSubnetMask, CVY_DEF_CL_NET_MASK))
  137. ::SendMessage(::GetDlgItem(m_hWndDialog, m_dwSubnetMaskId), IPM_CLEARADDRESS, 0, 0);
  138. else
  139. ::SendDlgItemMessage(m_hWndDialog, m_dwSubnetMaskId, WM_SETTEXT, 0, (LPARAM)pszSubnetMask);
  140. }
  141. //+----------------------------------------------------------------------------
  142. //
  143. // Function: CIpSubnetMaskControl::UpdateInfo
  144. //
  145. // Description: Retrieve value from control
  146. //
  147. // Arguments: OUT WCHAR* pszIpAddress -
  148. // OUT WCHAR* pszSubnetMask -
  149. //
  150. // Returns: Nothing
  151. //
  152. // History: shouse initial code
  153. // fengsun Created Header 1/10/01
  154. //
  155. //+----------------------------------------------------------------------------
  156. void CIpSubnetMaskControl::UpdateInfo(OUT WCHAR* pszIpAddress, OUT WCHAR* pszSubnetMask)
  157. /*
  158. We expect that outparams are of
  159. (CVY_MAX_CL_IP_ADDR + 1) and (CVY_MAX_CL_NET_MASK + 1)
  160. characters each, respectively.
  161. */
  162. {
  163. /* If the dedicated IP entry box is empty, then the dedicated IP address is NUL. Otherwise, grab it from the UI. */
  164. if (::SendMessage(::GetDlgItem(m_hWndDialog, m_dwIpAddressId), IPM_ISBLANK, 0, 0))
  165. {
  166. StringCchCopy(pszIpAddress, CVY_MAX_CL_IP_ADDR+1, CVY_DEF_CL_IP_ADDR);
  167. }
  168. else
  169. {
  170. ::SendDlgItemMessage(m_hWndDialog, m_dwIpAddressId, WM_GETTEXT, CVY_MAX_CL_IP_ADDR, (LPARAM)pszIpAddress);
  171. }
  172. /* If the host net mask entry box is empty, then the host net mask is NUL. Otherwise, grab it from the UI. */
  173. if (::SendMessage(::GetDlgItem(m_hWndDialog, m_dwSubnetMaskId), IPM_ISBLANK, 0, 0))
  174. {
  175. StringCchCopy(pszSubnetMask, CVY_MAX_CL_NET_MASK+1, CVY_DEF_CL_NET_MASK);
  176. }
  177. else
  178. {
  179. ::SendDlgItemMessage(m_hWndDialog, m_dwSubnetMaskId, WM_GETTEXT, CVY_MAX_CL_NET_MASK, (LPARAM)pszSubnetMask);
  180. }
  181. }
  182. //+----------------------------------------------------------------------------
  183. //
  184. // Function: CIpSubnetMaskControl::ValidateInfo
  185. //
  186. // Description: Validate whether user input is valid
  187. //
  188. // Arguments: None
  189. //
  190. // Returns: bool - TRUE if valid
  191. //
  192. // History: shouse initial code
  193. // fengsun Created Header 1/10/01
  194. //
  195. //+----------------------------------------------------------------------------
  196. bool CIpSubnetMaskControl::ValidateInfo()
  197. {
  198. DWORD IPAddr;
  199. /* Check for blank IP address */
  200. if (::SendMessage(::GetDlgItem(m_hWndDialog, m_dwIpAddressId), IPM_ISBLANK, 0, 0))
  201. {
  202. /* Alert the user. */
  203. NcMsgBox(m_hInstance, ::GetActiveWindow(), IDS_PARM_ERROR, IDS_PARM_CL_IP_BLANK,
  204. MB_APPLMODAL | MB_ICONSTOP | MB_OK);
  205. SetFocus(::GetDlgItem(m_hWndDialog, m_dwIpAddressId));
  206. /* An error occurred. */
  207. return false;
  208. }
  209. /* Check for blank netmask */
  210. if (::SendMessage(::GetDlgItem(m_hWndDialog, m_dwSubnetMaskId), IPM_ISBLANK, 0, 0))
  211. {
  212. /* Fill in the netmask for the user. */
  213. OnSubnetMask(EN_SETFOCUS);
  214. /* Alert the user. */
  215. NcMsgBox(m_hInstance, ::GetActiveWindow(), IDS_PARM_ERROR, IDS_PARM_CL_NM_BLANK,
  216. MB_APPLMODAL | MB_ICONSTOP | MB_OK);
  217. /* An error occurred. */
  218. return false;
  219. }
  220. /* Only perform the rest of the IP checking if the user has specified both a dedicated
  221. IP address and a corresponding netmask. */
  222. if (!::SendMessage(::GetDlgItem(m_hWndDialog, m_dwIpAddressId), IPM_ISBLANK, 0, 0) &&
  223. !::SendMessage(::GetDlgItem(m_hWndDialog, m_dwSubnetMaskId), IPM_ISBLANK, 0, 0)) {
  224. /* Get the dedicated IP address. */
  225. ::SendDlgItemMessage(m_hWndDialog, m_dwIpAddressId, IPM_GETADDRESS, 0, (LPARAM)&IPAddr);
  226. /* Make sure that the first octet is not zero. If it is, make it 1 and alter the user. */
  227. if (!FIRST_IPADDRESS(IPAddr)) {
  228. /* Make the first octet 1 instead of the erroneous 0. */
  229. IPAddr = IPAddr | (DWORD)(WLBS_IP_FIELD_ZERO_LOW << 24);
  230. /* Set the IP address and update our dedicated IP address string. */
  231. ::SendDlgItemMessage(m_hWndDialog, m_dwIpAddressId, IPM_SETADDRESS, 0, (LPARAM)IPAddr);
  232. /* Alert the user. */
  233. PrintIPRangeError(m_hInstance, m_hWndDialog, IDS_PARM_CL_IP_FIELD, 0,
  234. WLBS_IP_FIELD_ZERO_LOW, WLBS_IP_FIELD_ZERO_HIGH);
  235. SetFocus(::GetDlgItem(m_hWndDialog, m_dwIpAddressId));
  236. return false;
  237. }
  238. WCHAR szIpAddress [CVY_MAX_CL_IP_ADDR + 1];
  239. WCHAR szSubnetMask [CVY_MAX_CL_IP_ADDR + 1];
  240. ::SendDlgItemMessage(m_hWndDialog, m_dwIpAddressId, WM_GETTEXT, CVY_MAX_CL_IP_ADDR, (LPARAM)szIpAddress);
  241. ::SendDlgItemMessage(m_hWndDialog, m_dwSubnetMaskId, WM_GETTEXT, CVY_MAX_CL_NET_MASK, (LPARAM)szSubnetMask);
  242. /* Check for valid dedicated IP address/netmask pairs. */
  243. if (!IsValidIPAddressSubnetMaskPair(szIpAddress, szSubnetMask)) {
  244. /* Alert the user. */
  245. NcMsgBox(m_hInstance, ::GetActiveWindow(), IDS_PARM_ERROR, IDS_PARM_INVAL_CL_IP,
  246. MB_APPLMODAL | MB_ICONSTOP | MB_OK);
  247. SetFocus(::GetDlgItem(m_hWndDialog, m_dwIpAddressId));
  248. /* An error occurred. */
  249. return false;
  250. }
  251. /* Check to make sure that the netmask is contiguous. */
  252. if (!IsContiguousSubnetMask(szSubnetMask)) {
  253. /* Alert the user. */
  254. NcMsgBox(m_hInstance, ::GetActiveWindow(), IDS_PARM_ERROR, IDS_PARM_INVAL_CL_MASK,
  255. MB_APPLMODAL | MB_ICONSTOP | MB_OK);
  256. SetFocus(::GetDlgItem(m_hWndDialog, m_dwIpAddressId));
  257. /* An error occurred. */
  258. return false;
  259. }
  260. }
  261. return true; // no error
  262. }
  263. /*
  264. * Method: PrintIPRangeError
  265. * Description: Displays a message box warning the user of an out-of-range entry in
  266. * an IP address octet.
  267. */
  268. void PrintIPRangeError (HINSTANCE hInstance, HWND hWnd, unsigned int ids, int value, int low, int high)
  269. {
  270. WCHAR szCurrent[12];
  271. WCHAR szLow[12];
  272. WCHAR szHigh[12];
  273. /* Fill in the range and the offending value. */
  274. StringCbPrintf(szHigh, sizeof(szHigh), L"%d", high);
  275. StringCbPrintf(szCurrent, sizeof(szCurrent), L"%d", value);
  276. StringCbPrintf(szLow, sizeof(szLow), L"%d", low);
  277. /* Pop-up a message box. */
  278. NcMsgBox(hInstance, hWnd, IDS_PARM_ERROR, ids, MB_APPLMODAL | MB_ICONSTOP | MB_OK, szCurrent, szLow, szHigh);
  279. }