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.

1012 lines
30 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
  4. /**********************************************************************/
  5. #include "stdafx.h"
  6. #include "addrpool.h"
  7. #include "rraswiz.h"
  8. #include "rtrres.h"
  9. #include "rtrcomn.h"
  10. // This is the build where Static Address pools are enabled.
  11. #define STATIC_ADDRESSPOOL_BUILDNO (2076)
  12. // This function is used to convert numbers in the presence of
  13. // separators.
  14. BOOL ConvertStringToNumber(LPCTSTR pszString, DWORD * pdwRet);
  15. void FilterBadChars (LPCTSTR pszEvilString, CString & stGood);
  16. // This array must match the column indices in the addrpool.h enum.
  17. INT s_rgIPPoolColumnHeadersLong[] =
  18. {
  19. IDS_IPPOOL_COL_START,
  20. IDS_IPPOOL_COL_END,
  21. IDS_IPPOOL_COL_RANGE,
  22. IDS_IPPOOL_COL_IPADDRESS,
  23. IDS_IPPOOL_COL_MASK,
  24. 0 // sentinel
  25. };
  26. INT s_rgIPPoolColumnHeadersShort[] =
  27. {
  28. IDS_IPPOOL_COL_START,
  29. IDS_IPPOOL_COL_END,
  30. IDS_IPPOOL_COL_RANGE,
  31. 0 // sentinel
  32. };
  33. /*!--------------------------------------------------------------------------
  34. InitializeAddressPoolListControl
  35. -
  36. Author: KennT
  37. ---------------------------------------------------------------------------*/
  38. HRESULT InitializeAddressPoolListControl(CListCtrl *pListCtrl,
  39. LPARAM flags,
  40. AddressPoolList *pList)
  41. {
  42. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  43. HRESULT hr = hrOK;
  44. LV_COLUMN lvCol; // list view column struct for radius servers
  45. RECT rect;
  46. CString stColCaption;
  47. int nColWidth;
  48. POSITION pos;
  49. AddressPoolInfo pool;
  50. INT iPos;
  51. LV_ITEM lvItem;
  52. CString st, stStart;
  53. TCHAR szBuffer[64];
  54. INT * prgColumnHeaders = NULL;
  55. int cColumns = 0;
  56. ListView_SetExtendedListViewStyle(pListCtrl->GetSafeHwnd(),
  57. LVS_EX_FULLROWSELECT);
  58. // Show a different set of columns depending on the flag
  59. if (flags & ADDRPOOL_LONG)
  60. {
  61. // Subtract one for the sentinel
  62. cColumns = DimensionOf(s_rgIPPoolColumnHeadersLong) - 1;
  63. prgColumnHeaders = s_rgIPPoolColumnHeadersLong;
  64. }
  65. else
  66. {
  67. // Subtract one for the sentinel
  68. cColumns = DimensionOf(s_rgIPPoolColumnHeadersShort) - 1;
  69. prgColumnHeaders = s_rgIPPoolColumnHeadersShort;
  70. }
  71. // Add the columns to the list control
  72. pListCtrl->GetClientRect(&rect);
  73. nColWidth = rect.right / cColumns;
  74. lvCol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
  75. lvCol.fmt = LVCFMT_LEFT;
  76. lvCol.cx = nColWidth;
  77. // Insert the columns until we hit the sentinel value.
  78. for (INT index=0; *prgColumnHeaders; index++,prgColumnHeaders++)
  79. {
  80. stColCaption.LoadString( *prgColumnHeaders );
  81. lvCol.pszText = (LPTSTR)((LPCTSTR) stColCaption);
  82. pListCtrl->InsertColumn(index, &lvCol);
  83. }
  84. // Now we go in and add the data
  85. if (pList)
  86. {
  87. pos = pList->GetHeadPosition();
  88. lvItem.mask = LVIF_TEXT | LVIF_PARAM;
  89. lvItem.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
  90. lvItem.state = 0;
  91. while (pos)
  92. {
  93. // Break out of the loop if we do not support
  94. // multiple address pools.
  95. if (!pList->FUsesMultipleAddressPools() &&
  96. (pListCtrl->GetItemCount() > 1))
  97. {
  98. break;
  99. }
  100. pool = pList->GetNext(pos);
  101. stStart = INET_NTOA(pool.m_netStart);
  102. lvItem.iItem = pList->GetCount() + 1;
  103. lvItem.iSubItem = 0;
  104. lvItem.pszText = (LPTSTR)(LPCTSTR) stStart;
  105. // We use the pool key as a way of finding the item in the
  106. // list
  107. lvItem.lParam = pool.m_dwKey;
  108. iPos = pListCtrl->InsertItem(&lvItem);
  109. if (iPos != -1)
  110. {
  111. pListCtrl->SetItemText(iPos, IPPOOLCOL_START, stStart);
  112. st = INET_NTOA(pool.m_netEnd);
  113. pListCtrl->SetItemText(iPos, IPPOOLCOL_END, st);
  114. FormatNumber(pool.GetNumberOfAddresses(),
  115. szBuffer,
  116. DimensionOf(szBuffer),
  117. FALSE);
  118. pListCtrl->SetItemText(iPos, IPPOOLCOL_RANGE, szBuffer);
  119. if (flags & ADDRPOOL_LONG)
  120. {
  121. st = INET_NTOA(pool.m_netAddress);
  122. pListCtrl->SetItemText(iPos, IPPOOLCOL_IPADDRESS, st);
  123. st = INET_NTOA(pool.m_netMask);
  124. pListCtrl->SetItemText(iPos, IPPOOLCOL_MASK, st);
  125. }
  126. }
  127. }
  128. }
  129. return hr;
  130. }
  131. /*!--------------------------------------------------------------------------
  132. OnNewAddressPool
  133. -
  134. Author: KennT
  135. ---------------------------------------------------------------------------*/
  136. void OnNewAddressPool(HWND hWnd, CListCtrl *pList, LPARAM flags, AddressPoolList *pPoolList)
  137. {
  138. LV_ITEM lvItem;
  139. CString st, stStart;
  140. INT iPos;
  141. TCHAR szBuffer[64];
  142. AddressPoolInfo poolInfo;
  143. CAddressPoolDialog dlg(&poolInfo,
  144. pPoolList,
  145. TRUE);
  146. if (dlg.DoModal() == IDOK)
  147. {
  148. poolInfo.GetNewKey();
  149. // Add this to the list.
  150. pPoolList->AddTail(poolInfo);
  151. // Add this to the UI
  152. stStart = INET_NTOA(poolInfo.m_netStart);
  153. lvItem.mask = LVIF_TEXT | LVIF_PARAM;
  154. lvItem.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
  155. lvItem.state = 0;
  156. lvItem.iItem = pPoolList->GetCount() + 1;
  157. lvItem.iSubItem = 0;
  158. lvItem.pszText = (LPTSTR)(LPCTSTR) stStart;
  159. // We use the pool key as a way of finding the item in the
  160. // list
  161. lvItem.lParam = poolInfo.m_dwKey;
  162. iPos = pList->InsertItem(&lvItem);
  163. if (iPos != -1)
  164. {
  165. pList->SetItemText(iPos, IPPOOLCOL_START, stStart);
  166. st = INET_NTOA(poolInfo.m_netEnd);
  167. pList->SetItemText(iPos, IPPOOLCOL_END, st);
  168. FormatNumber(poolInfo.GetNumberOfAddresses(),
  169. szBuffer,
  170. DimensionOf(szBuffer),
  171. FALSE);
  172. pList->SetItemText(iPos, IPPOOLCOL_RANGE, szBuffer);
  173. if (flags & ADDRPOOL_LONG)
  174. {
  175. st = INET_NTOA(poolInfo.m_netAddress);
  176. pList->SetItemText(iPos, IPPOOLCOL_IPADDRESS, st);
  177. st = INET_NTOA(poolInfo.m_netMask);
  178. pList->SetItemText(iPos, IPPOOLCOL_MASK, st);
  179. }
  180. }
  181. }
  182. }
  183. void OnEditAddressPool(HWND hWnd, CListCtrl *pList, LPARAM flags, AddressPoolList *pPoolList)
  184. {
  185. INT iPos;
  186. DWORD dwKey = 0;
  187. POSITION pos, posT;
  188. AddressPoolInfo poolInfo;
  189. TCHAR szBuffer[64];
  190. CString st;
  191. // Is there a selected item?
  192. if ((iPos = pList->GetNextItem(-1, LVNI_SELECTED)) == -1)
  193. return;
  194. dwKey = pList->GetItemData(iPos);
  195. // Given the key, find it in our list of items
  196. pos = pPoolList->GetHeadPosition();
  197. while (pos)
  198. {
  199. posT = pos;
  200. poolInfo = pPoolList->GetNext(pos);
  201. if (poolInfo.m_dwKey == dwKey)
  202. break;
  203. }
  204. // Did we find a match?
  205. if (dwKey)
  206. {
  207. Assert(posT);
  208. poolInfo = pPoolList->GetAt(posT);
  209. CAddressPoolDialog dlg(&poolInfo,
  210. pPoolList,
  211. FALSE);
  212. if (dlg.DoModal() == IDOK)
  213. {
  214. // set it back
  215. st = INET_NTOA(poolInfo.m_netStart);
  216. pList->SetItemText(iPos, IPPOOLCOL_START, st);
  217. st = INET_NTOA(poolInfo.m_netEnd);
  218. pList->SetItemText(iPos, IPPOOLCOL_END, st);
  219. FormatNumber(poolInfo.GetNumberOfAddresses(),
  220. szBuffer,
  221. DimensionOf(szBuffer),
  222. FALSE);
  223. pList->SetItemText(iPos, IPPOOLCOL_RANGE, szBuffer);
  224. if (flags & ADDRPOOL_LONG)
  225. {
  226. st = INET_NTOA(poolInfo.m_netAddress);
  227. pList->SetItemText(iPos, IPPOOLCOL_IPADDRESS, st);
  228. st = INET_NTOA(poolInfo.m_netMask);
  229. pList->SetItemText(iPos, IPPOOLCOL_MASK, st);
  230. }
  231. pPoolList->SetAt(posT, poolInfo);
  232. }
  233. }
  234. }
  235. void OnDeleteAddressPool(HWND hWnd, CListCtrl *pList, LPARAM flags, AddressPoolList *pPoolList)
  236. {
  237. INT iPos;
  238. DWORD dwKey = 0;
  239. POSITION pos, posT;
  240. AddressPoolInfo poolInfo;
  241. // Ok, need to remove the selected item from the list and from the UI
  242. // Is there a selected item?
  243. if ((iPos = pList->GetNextItem(-1, LVNI_SELECTED)) == -1)
  244. return;
  245. dwKey = pList->GetItemData(iPos);
  246. // Given the key, find it in our list of items
  247. pos = pPoolList->GetHeadPosition();
  248. while (pos)
  249. {
  250. posT = pos;
  251. poolInfo = pPoolList->GetNext(pos);
  252. if (poolInfo.m_dwKey == dwKey)
  253. break;
  254. }
  255. // Did we find a match?
  256. if (dwKey)
  257. {
  258. INT nCount;
  259. Assert(posT);
  260. pPoolList->RemoveAt(posT);
  261. pList->DeleteItem(iPos);
  262. // Ok, update the selected state to point at the next item
  263. nCount = pList->GetItemCount();
  264. if (nCount > 0)
  265. {
  266. iPos = min(nCount-1, iPos);
  267. pList->SetItemState(iPos, LVIS_SELECTED, LVIS_SELECTED);
  268. }
  269. }
  270. }
  271. /*!--------------------------------------------------------------------------
  272. AddressPoolInfo::GetNewKey
  273. -
  274. Author: KennT
  275. ---------------------------------------------------------------------------*/
  276. DWORD AddressPoolInfo::GetNewKey()
  277. {
  278. static DWORD s_dwAddressPoolKey = 1;
  279. m_dwKey = s_dwAddressPoolKey;
  280. ++s_dwAddressPoolKey;
  281. return m_dwKey;
  282. }
  283. /*!--------------------------------------------------------------------------
  284. AddressPoolInfo::SetAddressAndMask
  285. -
  286. Author: KennT
  287. ---------------------------------------------------------------------------*/
  288. void AddressPoolInfo::SetAddressAndMask(DWORD netAddress, DWORD netMask)
  289. {
  290. // Ok, need to determine the start and end address
  291. DWORD netStart, netEnd;
  292. m_netStart = netAddress & netMask;
  293. m_netEnd = netAddress | ~netMask;
  294. m_netAddress = netAddress;
  295. m_netMask = netMask;
  296. }
  297. /*!--------------------------------------------------------------------------
  298. AddressPoolInfo::SetStartAndEnd
  299. -
  300. Author: KennT
  301. ---------------------------------------------------------------------------*/
  302. void AddressPoolInfo::SetStartAndEnd(DWORD netStart, DWORD netEnd)
  303. {
  304. DWORD dwAddress, dwMask, dwTemp, dwMaskTemp;
  305. DWORD dwStart, dwEnd;
  306. // Given the start and the end, figure out the address and mask
  307. // Save the start/end addresses before they get converted to host form.
  308. m_netStart = netStart;
  309. m_netEnd = netEnd;
  310. dwStart = ntohl(netStart);
  311. dwEnd = ntohl(netEnd);
  312. // This will put 1's where the bits have the same value
  313. dwTemp = ~(dwStart ^ dwEnd);
  314. // Now we look for the first 0 bit (looking from high bit to low bit)
  315. // This will give us our mask
  316. dwMask = 0;
  317. dwMaskTemp = 0;
  318. for (int i=0; i<sizeof(DWORD)*8; i++)
  319. {
  320. dwMaskTemp >>= 1;
  321. dwMaskTemp |= 0x80000000;
  322. // Is there a zero bit?
  323. if ((dwMaskTemp & dwTemp) != dwMaskTemp)
  324. {
  325. // There is a zero, so we break out.
  326. break;
  327. }
  328. // If not, continue
  329. dwMask = dwMaskTemp;
  330. }
  331. m_netMask = htonl(dwMask);
  332. m_netAddress = htonl(dwMask & dwStart);
  333. }
  334. /*!--------------------------------------------------------------------------
  335. AddressPoolList::HrIsValidAddressPool
  336. -
  337. Author: KennT
  338. ---------------------------------------------------------------------------*/
  339. HRESULT AddressPoolList::HrIsValidAddressPool(AddressPoolInfo *pInfo)
  340. {
  341. DWORD dwStart, dwEnd; // in host order
  342. dwStart = ntohl(pInfo->m_netStart);
  343. dwEnd = ntohl(pInfo->m_netEnd);
  344. // Verify that this is a valid address pool entry.
  345. // First, check to see that the end is greater than the start
  346. // We add one to the start address, to include the RAS adapter
  347. // ----------------------------------------------------------------
  348. if (dwStart >= dwEnd)
  349. {
  350. return IDS_ERR_IP_ADDRESS_POOL_RANGE_TOO_SMALL;
  351. }
  352. // Now check to see that the 127 range is not included
  353. // ----------------------------------------------------------------
  354. if ((dwEnd >= MAKEIPADDRESS(127,0,0,0)) &&
  355. (dwStart <= MAKEIPADDRESS(127,255,255,255)))
  356. {
  357. return IDS_ERR_IP_ADDRESS_POOL_RANGE_OVERLAPS_127;
  358. }
  359. // Check to see that the addresses are in the normal range
  360. // 1.0.0.0 <= address < 224.0.0.0
  361. // ----------------------------------------------------------------
  362. if ((dwStart < MAKEIPADDRESS(1,0,0,0)) ||
  363. (dwEnd > MAKEIPADDRESS(223,255,255,255)))
  364. {
  365. return IDS_ERR_IP_ADDRESS_POOL_RANGE_NOT_NORMAL;
  366. }
  367. Assert(pInfo->GetNumberOfAddresses() > 0);
  368. //$ TODO : Need to check that we don't have overlaps
  369. if (GetCount())
  370. {
  371. POSITION pos;
  372. AddressPoolInfo poolInfo;
  373. DWORD dwPoolStart, dwPoolEnd;
  374. pos = GetHeadPosition();
  375. while (pos)
  376. {
  377. poolInfo = GetNext(pos);
  378. if (poolInfo.m_dwKey == pInfo->m_dwKey)
  379. continue;
  380. dwPoolStart = ntohl(poolInfo.m_netStart);
  381. dwPoolEnd = ntohl(poolInfo.m_netEnd);
  382. // do we overlap?
  383. if ((dwEnd >= dwPoolStart) && (dwStart <= dwPoolEnd))
  384. {
  385. return IDS_ERR_IP_ADDRESS_POOL_OVERLAP;
  386. }
  387. }
  388. }
  389. return hrOK;
  390. }
  391. BOOL AddressPoolList::FUsesMultipleAddressPools()
  392. {
  393. return m_fMultipleAddressPools;
  394. }
  395. HRESULT AddressPoolList::LoadFromReg(HKEY hkeyRasIp, DWORD dwBuildNo)
  396. {
  397. HRESULT hr = hrOK;
  398. RegKey regkeyRasIp;
  399. RegKey regkeyPool;
  400. RegKey regkeyRange;
  401. CString stIpAddr, stIpMask;
  402. AddressPoolInfo poolInfo;
  403. DWORD dwIpAddr, dwMask;
  404. DWORD dwFrom, dwTo;
  405. RegKeyIterator regkeyIter;
  406. HRESULT hrIter;
  407. CString stKey;
  408. m_fMultipleAddressPools = FALSE;
  409. regkeyRasIp.Attach(hkeyRasIp);
  410. COM_PROTECT_TRY
  411. {
  412. // Remove all of the old addresses
  413. RemoveAll();
  414. // Support multiple address pools only if we are on newer builds.
  415. // ------------------------------------------------------------
  416. m_fMultipleAddressPools = (dwBuildNo >= STATIC_ADDRESSPOOL_BUILDNO);
  417. // Check to see if the StaticAddressPool key exists, if so
  418. // then we use that, otherwise use the ip addr and mask
  419. // entries
  420. // Check out RemoteAccess\Parameters\Ip\StaticAddressPool
  421. // ------------------------------------------------------------
  422. if ( ERROR_SUCCESS == regkeyPool.Open(regkeyRasIp,
  423. c_szRegValStaticAddressPool))
  424. {
  425. TCHAR szKeyName[32];
  426. INT iCount = 0;
  427. // Instead of enumerating we open up the keys one-by-one
  428. // (to maintain the order of the keys).
  429. // --------------------------------------------------------
  430. while (TRUE)
  431. {
  432. // Cleanup from previous loop
  433. // ----------------------------------------------------
  434. regkeyRange.Close();
  435. // Setup for this loop
  436. // ----------------------------------------------------
  437. wsprintf(szKeyName, _T("%d"), iCount);
  438. // Try to open the key
  439. // If we fail, bail out of the loop.
  440. // ----------------------------------------------------
  441. if (ERROR_SUCCESS != regkeyRange.Open(regkeyPool, szKeyName))
  442. break;
  443. regkeyRange.QueryValue(c_szRegValFrom, dwFrom);
  444. regkeyRange.QueryValue(c_szRegValTo, dwTo);
  445. poolInfo.SetStartAndEnd(htonl(dwFrom), htonl(dwTo));
  446. poolInfo.GetNewKey();
  447. // Ok, add this to the list of address ranges
  448. // ----------------------------------------------------
  449. AddTail(poolInfo);
  450. iCount++;
  451. }
  452. }
  453. else
  454. {
  455. // We can't find the StaticAddressPool key, so use the
  456. // data in the address/mask entries.
  457. // --------------------------------------------------------
  458. regkeyRasIp.QueryValue(c_szRegValIpAddr, stIpAddr);
  459. regkeyRasIp.QueryValue(c_szRegValIpMask, stIpMask);
  460. if (!stIpAddr.IsEmpty() && !stIpMask.IsEmpty())
  461. {
  462. dwIpAddr = INET_ADDR((LPTSTR) (LPCTSTR) stIpAddr);
  463. dwMask = INET_ADDR((LPTSTR) (LPCTSTR) stIpMask);
  464. poolInfo.SetAddressAndMask(dwIpAddr, dwMask);
  465. poolInfo.GetNewKey();
  466. // Add this to the head of the list
  467. AddHead(poolInfo);
  468. }
  469. }
  470. }
  471. COM_PROTECT_CATCH;
  472. regkeyRasIp.Detach();
  473. return hr;
  474. }
  475. /*!--------------------------------------------------------------------------
  476. AddressPoolList::SaveToReg
  477. -
  478. Author: KennT
  479. ---------------------------------------------------------------------------*/
  480. HRESULT AddressPoolList::SaveToReg(HKEY hkeyRasIp, DWORD dwBuildNo)
  481. {
  482. HRESULT hr = hrOK;
  483. AddressPoolInfo poolInfo;
  484. CString stAddress, stMask;
  485. CString stRange;
  486. POSITION pos;
  487. RegKey regkeyRasIp;
  488. RegKey regkeyPool;
  489. RegKey regkeyRange;
  490. DWORD dwCount;
  491. DWORD dwErr, dwData;
  492. regkeyRasIp.Attach(hkeyRasIp);
  493. COM_PROTECT_TRY
  494. {
  495. // Reset the m_fMultipleAddressPools
  496. m_fMultipleAddressPools = (dwBuildNo >= STATIC_ADDRESSPOOL_BUILDNO);
  497. // If this is a newer build, use the StaticAddressPoolKey,
  498. // otherwise use the old keys.
  499. // ------------------------------------------------------------
  500. if (m_fMultipleAddressPools)
  501. {
  502. // Open RemoteAccess\Parameters\Ip\StaticAddressPool
  503. // --------------------------------------------------------
  504. CWRg( regkeyPool.Create(regkeyRasIp,
  505. c_szRegValStaticAddressPool) );
  506. // Delete all of the current keys in the list
  507. // ------------------------------------------------------------
  508. regkeyPool.RecurseDeleteSubKeys();
  509. // Delete any of the older keys
  510. // --------------------------------------------------------
  511. regkeyRasIp.DeleteValue(c_szRegValIpAddr);
  512. regkeyRasIp.DeleteValue(c_szRegValIpMask);
  513. // Now enumerate through the address pool list and
  514. // add all of those keys.
  515. // ------------------------------------------------------------
  516. if (GetCount())
  517. {
  518. pos = GetHeadPosition();
  519. dwCount = 0;
  520. while (pos)
  521. {
  522. poolInfo = GetNext(pos);
  523. regkeyRange.Close();
  524. // This is the title for the key
  525. // ------------------------------------------------
  526. stRange.Format(_T("%d"), dwCount);
  527. CWRg( regkeyRange.Create(regkeyPool, stRange) );
  528. dwData = ntohl(poolInfo.m_netStart);
  529. CWRg( regkeyRange.SetValue(c_szRegValFrom, dwData) );
  530. dwData = ntohl(poolInfo.m_netEnd);
  531. CWRg( regkeyRange.SetValue(c_szRegValTo, dwData) );
  532. dwCount++;
  533. }
  534. }
  535. }
  536. else
  537. {
  538. // Just write out the first address we find, if there are none then
  539. // write out blanks (to erase any previous values).
  540. if (GetCount())
  541. {
  542. // Get the first address info
  543. Assert(GetCount() == 1);
  544. poolInfo = GetHead();
  545. stAddress = INET_NTOA(poolInfo.m_netAddress);
  546. stMask = INET_NTOA(poolInfo.m_netMask);
  547. CWRg( regkeyRasIp.SetValue( c_szRegValIpAddr, (LPCTSTR) stAddress) );
  548. CWRg( regkeyRasIp.SetValue( c_szRegValIpMask, (LPCTSTR) stMask) );
  549. }
  550. else
  551. {
  552. CWRg( regkeyRasIp.SetValue( c_szRegValIpAddr, (LPCTSTR) _T("")) );
  553. CWRg( regkeyRasIp.SetValue( c_szRegValIpMask, (LPCTSTR) _T("")) );
  554. }
  555. }
  556. COM_PROTECT_ERROR_LABEL;
  557. }
  558. COM_PROTECT_CATCH;
  559. regkeyRasIp.Detach();
  560. return hr;
  561. }
  562. /*---------------------------------------------------------------------------
  563. CAddressPoolDialog implementation
  564. ---------------------------------------------------------------------------*/
  565. CAddressPoolDialog::CAddressPoolDialog(
  566. AddressPoolInfo *pPool,
  567. AddressPoolList *pPoolList,
  568. BOOL fCreate)
  569. : CBaseDialog(IDD_IPPOOL),
  570. m_pPool(pPool),
  571. m_fCreate(fCreate),
  572. m_fReady(FALSE),
  573. m_pPoolList(pPoolList)
  574. {
  575. }
  576. void CAddressPoolDialog::DoDataExchange(CDataExchange *pDX)
  577. {
  578. CBaseDialog::DoDataExchange(pDX);
  579. }
  580. BEGIN_MESSAGE_MAP(CAddressPoolDialog, CBaseDialog)
  581. ON_EN_CHANGE(IDC_IPPOOL_IP_START, OnChangeStartAddress)
  582. ON_EN_CHANGE(IDC_IPPOOL_IP_END, OnChangeEndAddress)
  583. ON_EN_CHANGE(IDC_IPPOOL_EDIT_RANGE, OnChangeRange)
  584. ON_EN_KILLFOCUS(IDC_IPPOOL_IP_START, OnKillFocusStartAddress)
  585. ON_EN_KILLFOCUS(IDC_IPPOOL_IP_END, OnKillFocusEndAddress)
  586. END_MESSAGE_MAP()
  587. BOOL CAddressPoolDialog::OnInitDialog()
  588. {
  589. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  590. CString st;
  591. TCHAR szBuffer[64];
  592. CBaseDialog::OnInitDialog();
  593. st.LoadString(m_fCreate ? IDS_ADD_IPPOOL_TITLE : IDS_EDIT_IPPOOL_TITLE);
  594. SetWindowText((LPCTSTR) st);
  595. m_ipStartAddress.Create(GetSafeHwnd(), IDC_IPPOOL_IP_START);
  596. st = INET_NTOA(m_pPool->m_netStart);
  597. m_ipStartAddress.SetAddress((LPCTSTR) st);
  598. m_ipEndAddress.Create(GetSafeHwnd(), IDC_IPPOOL_IP_END);
  599. st = INET_NTOA(m_pPool->m_netEnd);
  600. m_ipEndAddress.SetAddress((LPCTSTR) st);
  601. GenerateRange();
  602. m_fReady = TRUE;
  603. return TRUE;
  604. }
  605. void CAddressPoolDialog::OnOK()
  606. {
  607. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  608. CString st;
  609. DWORD netStart, netEnd;
  610. HRESULT hr = hrOK;
  611. UINT ids = 0;
  612. // Ok, check the validity of the addresses
  613. // Are all of the fields there?
  614. if (m_ipStartAddress.IsBlank())
  615. {
  616. AfxMessageBox(IDS_ERR_ADDRESS_POOL_NO_START_ADDRESS);
  617. return;
  618. }
  619. if (m_ipEndAddress.IsBlank())
  620. {
  621. AfxMessageBox(IDS_ERR_ADDRESS_POOL_NO_END_ADDRESS);
  622. return;
  623. }
  624. m_ipStartAddress.GetAddress(st);
  625. netStart = INET_ADDR((LPTSTR)(LPCTSTR)st);
  626. if ((netStart == 0) || (netStart == 0xFFFFFFFF))
  627. {
  628. AfxMessageBox(IDS_ERR_ADDRESS_POOL_NO_START_ADDRESS);
  629. return;
  630. }
  631. m_ipEndAddress.GetAddress(st);
  632. netEnd = INET_ADDR((LPTSTR)(LPCTSTR)st);
  633. if ((netEnd == 0) || (netEnd == 0xFFFFFFFF))
  634. {
  635. AfxMessageBox(IDS_ERR_ADDRESS_POOL_NO_END_ADDRESS);
  636. return;
  637. }
  638. m_pPool->SetStartAndEnd(netStart, netEnd);
  639. if (!FHrOK(hr = m_pPoolList->HrIsValidAddressPool(m_pPool)))
  640. {
  641. if (FHrSucceeded(hr))
  642. {
  643. // If it is not hrOK and is not an error code,
  644. // the success code can be interpreted as a string id
  645. AfxMessageBox(hr);
  646. }
  647. return;
  648. }
  649. CBaseDialog::OnOK();
  650. }
  651. void CAddressPoolDialog::OnChangeStartAddress()
  652. {
  653. if (m_fReady)
  654. GenerateRange();
  655. }
  656. void CAddressPoolDialog::OnChangeEndAddress()
  657. {
  658. if (m_fReady)
  659. GenerateRange();
  660. }
  661. void CAddressPoolDialog::OnChangeRange()
  662. {
  663. if (m_fReady)
  664. {
  665. CString st;
  666. DWORD dwAddr, dwSize;
  667. DWORD netAddr;
  668. DWORD dwRange;
  669. m_fReady = FALSE;
  670. // Get the start address and update the end address
  671. m_ipStartAddress.GetAddress(st);
  672. dwAddr = ntohl(INET_ADDR(st));
  673. // Have to read in the text, but strip out the
  674. // commas in the range, sigh.
  675. GetDlgItemText(IDC_IPPOOL_EDIT_RANGE, st);
  676. if ( ConvertStringToNumber(st, &dwRange) )
  677. {
  678. dwAddr += dwRange;
  679. // Subtract 1 since this is an inclusive range
  680. // i.e. 0..(n-1) is n addresses.
  681. dwAddr -= 1;
  682. netAddr = htonl(dwAddr);
  683. st = INET_NTOA(netAddr);
  684. m_ipEndAddress.SetAddress(st);
  685. }
  686. else
  687. {
  688. CString stGood;
  689. //Filter the bad chars out of the box
  690. FilterBadChars (st, stGood);
  691. SetDlgItemText (IDC_IPPOOL_EDIT_RANGE, stGood );
  692. AfxMessageBox (IDS_ILLEGAL_CHARACTER, MB_ICONERROR | MB_OK );
  693. }
  694. m_fReady = TRUE;
  695. }
  696. }
  697. void CAddressPoolDialog::OnKillFocusStartAddress()
  698. {
  699. GenerateRange();
  700. if (m_ipEndAddress.IsBlank())
  701. {
  702. CString st;
  703. m_ipStartAddress.GetAddress(st);
  704. m_ipEndAddress.SetAddress(st);
  705. }
  706. }
  707. void CAddressPoolDialog::OnKillFocusEndAddress()
  708. {
  709. GenerateRange();
  710. }
  711. void CAddressPoolDialog::GenerateRange()
  712. {
  713. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  714. DWORD dwStart, dwEnd;
  715. TCHAR szBuffer[64];
  716. CString st;
  717. m_ipStartAddress.GetAddress(st);
  718. dwStart = ntohl(INET_ADDR(st));
  719. m_ipEndAddress.GetAddress(st);
  720. dwEnd = ntohl(INET_ADDR(st));
  721. m_fReady = FALSE;
  722. // Display the range.
  723. if (dwStart >= dwEnd)
  724. {
  725. SetDlgItemInt(IDC_IPPOOL_EDIT_RANGE, 0);
  726. }
  727. else
  728. {
  729. FormatNumber(dwEnd - dwStart + 1,
  730. szBuffer,
  731. DimensionOf(szBuffer),
  732. FALSE);
  733. SetDlgItemText(IDC_IPPOOL_EDIT_RANGE, szBuffer);
  734. }
  735. m_fReady = TRUE;
  736. }
  737. void FilterBadChars (LPCTSTR pszEvilString, CString & stGood)
  738. {
  739. static TCHAR s_szThousandsSeparator[5] = TEXT("");
  740. static int s_cchThousands;
  741. stGood.Empty();
  742. if (s_szThousandsSeparator[0] == TEXT('\0'))
  743. {
  744. ::GetLocaleInfo(
  745. LOCALE_USER_DEFAULT,
  746. LOCALE_STHOUSAND,
  747. s_szThousandsSeparator,
  748. 4
  749. );
  750. s_cchThousands = StrLen(s_szThousandsSeparator);
  751. }
  752. while (*pszEvilString )
  753. {
  754. if (_istdigit(*pszEvilString))
  755. stGood += *pszEvilString++;
  756. else
  757. {
  758. // It's not a digit, we need to check to see if this
  759. // is a separator
  760. if (StrnCmp(pszEvilString, s_szThousandsSeparator, s_cchThousands) == 0)
  761. {
  762. // This is a separtor, skip over the string
  763. pszEvilString += s_cchThousands;
  764. }
  765. else
  766. {
  767. // skip this character, we're at a character we don't understand
  768. pszEvilString ++;
  769. }
  770. }
  771. }
  772. }
  773. /*!--------------------------------------------------------------------------
  774. ConvertStringToNumber
  775. This will convert the string into a number (even in the presence
  776. of thousands separtors).
  777. Author: KennT
  778. ---------------------------------------------------------------------------*/
  779. BOOL ConvertStringToNumber(LPCTSTR pszString, DWORD * pdwRet)
  780. {
  781. static TCHAR s_szThousandsSeparator[5] = TEXT("");
  782. static int s_cchThousands;
  783. if (s_szThousandsSeparator[0] == TEXT('\0'))
  784. {
  785. ::GetLocaleInfo(
  786. LOCALE_USER_DEFAULT,
  787. LOCALE_STHOUSAND,
  788. s_szThousandsSeparator,
  789. 4
  790. );
  791. s_cchThousands = StrLen(s_szThousandsSeparator);
  792. }
  793. // Make a copy of the string
  794. TCHAR * psz = (TCHAR *) _alloca((StrLen(pszString) + 1) * sizeof(WCHAR));
  795. TCHAR * pszCur = psz;
  796. // Now copy over the characters from pszString to psz, skipping
  797. // the numeric separators
  798. int cLen = StrLen(pszString);
  799. while (*pszString)
  800. {
  801. if (_istdigit(*pszString))
  802. *pszCur++ = *pszString++;
  803. else
  804. {
  805. // It's not a digit, we need to check to see if this
  806. // is a separator
  807. if (StrnCmp(pszString, s_szThousandsSeparator, s_cchThousands) == 0)
  808. {
  809. // This is a separtor, skip over the string
  810. pszString += s_cchThousands;
  811. }
  812. // Else we're done, we're at a character we don't understand
  813. else
  814. {
  815. //this is an error case
  816. return FALSE;
  817. break;
  818. }
  819. }
  820. }
  821. *pdwRet = _tcstoul(psz, NULL, 10);
  822. return TRUE;
  823. }