1013 lines
29 KiB
C++
1013 lines
29 KiB
C++
/**********************************************************************/
|
|
/** Microsoft Windows/NT **/
|
|
/** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
|
|
/**********************************************************************/
|
|
|
|
#include "stdafx.h"
|
|
#include "addrpool.h"
|
|
#include "rraswiz.h"
|
|
#include "rtrres.h"
|
|
#include "rtrcomn.h"
|
|
|
|
|
|
// This is the build where Static Address pools are enabled.
|
|
#define STATIC_ADDRESSPOOL_BUILDNO (2076)
|
|
|
|
|
|
// This function is used to convert numbers in the presence of
|
|
// separators.
|
|
BOOL ConvertStringToNumber(LPCTSTR pszString, DWORD * pdwRet);
|
|
void FilterBadChars (LPCTSTR pszEvilString, CString & stGood);
|
|
// This array must match the column indices in the addrpool.h enum.
|
|
INT s_rgIPPoolColumnHeadersLong[] =
|
|
{
|
|
IDS_IPPOOL_COL_START,
|
|
IDS_IPPOOL_COL_END,
|
|
IDS_IPPOOL_COL_RANGE,
|
|
IDS_IPPOOL_COL_IPADDRESS,
|
|
IDS_IPPOOL_COL_MASK,
|
|
0 // sentinel
|
|
};
|
|
|
|
INT s_rgIPPoolColumnHeadersShort[] =
|
|
{
|
|
IDS_IPPOOL_COL_START,
|
|
IDS_IPPOOL_COL_END,
|
|
IDS_IPPOOL_COL_RANGE,
|
|
0 // sentinel
|
|
};
|
|
|
|
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
InitializeAddressPoolListControl
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT InitializeAddressPoolListControl(CListCtrl *pListCtrl,
|
|
LPARAM flags,
|
|
AddressPoolList *pList)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
|
|
HRESULT hr = hrOK;
|
|
LV_COLUMN lvCol; // list view column struct for radius servers
|
|
RECT rect;
|
|
CString stColCaption;
|
|
int nColWidth;
|
|
POSITION pos;
|
|
AddressPoolInfo pool;
|
|
INT iPos;
|
|
LV_ITEM lvItem;
|
|
CString st, stStart;
|
|
TCHAR szBuffer[64];
|
|
INT * prgColumnHeaders = NULL;
|
|
int cColumns = 0;
|
|
|
|
ListView_SetExtendedListViewStyle(pListCtrl->GetSafeHwnd(),
|
|
LVS_EX_FULLROWSELECT);
|
|
|
|
// Show a different set of columns depending on the flag
|
|
if (flags & ADDRPOOL_LONG)
|
|
{
|
|
// Subtract one for the sentinel
|
|
cColumns = DimensionOf(s_rgIPPoolColumnHeadersLong) - 1;
|
|
prgColumnHeaders = s_rgIPPoolColumnHeadersLong;
|
|
}
|
|
else
|
|
{
|
|
// Subtract one for the sentinel
|
|
cColumns = DimensionOf(s_rgIPPoolColumnHeadersShort) - 1;
|
|
prgColumnHeaders = s_rgIPPoolColumnHeadersShort;
|
|
}
|
|
|
|
// Add the columns to the list control
|
|
|
|
pListCtrl->GetClientRect(&rect);
|
|
|
|
nColWidth = rect.right / cColumns;
|
|
|
|
lvCol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
|
|
lvCol.fmt = LVCFMT_LEFT;
|
|
lvCol.cx = nColWidth;
|
|
|
|
// Insert the columns until we hit the sentinel value.
|
|
for (INT index=0; *prgColumnHeaders; index++,prgColumnHeaders++)
|
|
{
|
|
stColCaption.LoadString( *prgColumnHeaders );
|
|
lvCol.pszText = (LPTSTR)((LPCTSTR) stColCaption);
|
|
pListCtrl->InsertColumn(index, &lvCol);
|
|
}
|
|
|
|
// Now we go in and add the data
|
|
if (pList)
|
|
{
|
|
pos = pList->GetHeadPosition();
|
|
|
|
lvItem.mask = LVIF_TEXT | LVIF_PARAM;
|
|
lvItem.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
|
|
lvItem.state = 0;
|
|
|
|
while (pos)
|
|
{
|
|
// Break out of the loop if we do not support
|
|
// multiple address pools.
|
|
if (!pList->FUsesMultipleAddressPools() &&
|
|
(pListCtrl->GetItemCount() > 1))
|
|
{
|
|
break;
|
|
}
|
|
|
|
pool = pList->GetNext(pos);
|
|
|
|
stStart = INET_NTOA(pool.m_netStart);
|
|
|
|
lvItem.iItem = pList->GetCount() + 1;
|
|
lvItem.iSubItem = 0;
|
|
lvItem.pszText = (LPTSTR)(LPCTSTR) stStart;
|
|
|
|
// We use the pool key as a way of finding the item in the
|
|
// list
|
|
lvItem.lParam = pool.m_dwKey;
|
|
|
|
iPos = pListCtrl->InsertItem(&lvItem);
|
|
if (iPos != -1)
|
|
{
|
|
pListCtrl->SetItemText(iPos, IPPOOLCOL_START, stStart);
|
|
|
|
st = INET_NTOA(pool.m_netEnd);
|
|
pListCtrl->SetItemText(iPos, IPPOOLCOL_END, st);
|
|
|
|
FormatNumber(pool.GetNumberOfAddresses(),
|
|
szBuffer,
|
|
DimensionOf(szBuffer),
|
|
FALSE);
|
|
pListCtrl->SetItemText(iPos, IPPOOLCOL_RANGE, szBuffer);
|
|
|
|
if (flags & ADDRPOOL_LONG)
|
|
{
|
|
st = INET_NTOA(pool.m_netAddress);
|
|
pListCtrl->SetItemText(iPos, IPPOOLCOL_IPADDRESS, st);
|
|
|
|
st = INET_NTOA(pool.m_netMask);
|
|
pListCtrl->SetItemText(iPos, IPPOOLCOL_MASK, st);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
OnNewAddressPool
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
void OnNewAddressPool(HWND hWnd, CListCtrl *pList, LPARAM flags, AddressPoolList *pPoolList)
|
|
{
|
|
LV_ITEM lvItem;
|
|
CString st, stStart;
|
|
INT iPos;
|
|
TCHAR szBuffer[64];
|
|
AddressPoolInfo poolInfo;
|
|
|
|
CAddressPoolDialog dlg(&poolInfo,
|
|
pPoolList,
|
|
TRUE);
|
|
|
|
if (dlg.DoModal() == IDOK)
|
|
{
|
|
poolInfo.GetNewKey();
|
|
|
|
// Add this to the list.
|
|
pPoolList->AddTail(poolInfo);
|
|
|
|
|
|
// Add this to the UI
|
|
stStart = INET_NTOA(poolInfo.m_netStart);
|
|
|
|
lvItem.mask = LVIF_TEXT | LVIF_PARAM;
|
|
lvItem.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
|
|
lvItem.state = 0;
|
|
|
|
lvItem.iItem = pPoolList->GetCount() + 1;
|
|
lvItem.iSubItem = 0;
|
|
lvItem.pszText = (LPTSTR)(LPCTSTR) stStart;
|
|
|
|
// We use the pool key as a way of finding the item in the
|
|
// list
|
|
lvItem.lParam = poolInfo.m_dwKey;
|
|
|
|
iPos = pList->InsertItem(&lvItem);
|
|
if (iPos != -1)
|
|
{
|
|
pList->SetItemText(iPos, IPPOOLCOL_START, stStart);
|
|
|
|
st = INET_NTOA(poolInfo.m_netEnd);
|
|
pList->SetItemText(iPos, IPPOOLCOL_END, st);
|
|
|
|
FormatNumber(poolInfo.GetNumberOfAddresses(),
|
|
szBuffer,
|
|
DimensionOf(szBuffer),
|
|
FALSE);
|
|
pList->SetItemText(iPos, IPPOOLCOL_RANGE, szBuffer);
|
|
|
|
if (flags & ADDRPOOL_LONG)
|
|
{
|
|
st = INET_NTOA(poolInfo.m_netAddress);
|
|
pList->SetItemText(iPos, IPPOOLCOL_IPADDRESS, st);
|
|
|
|
st = INET_NTOA(poolInfo.m_netMask);
|
|
pList->SetItemText(iPos, IPPOOLCOL_MASK, st);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void OnEditAddressPool(HWND hWnd, CListCtrl *pList, LPARAM flags, AddressPoolList *pPoolList)
|
|
{
|
|
INT iPos;
|
|
DWORD dwKey = 0;
|
|
POSITION pos, posT;
|
|
AddressPoolInfo poolInfo;
|
|
TCHAR szBuffer[64];
|
|
CString st;
|
|
|
|
// Is there a selected item?
|
|
if ((iPos = pList->GetNextItem(-1, LVNI_SELECTED)) == -1)
|
|
return;
|
|
|
|
dwKey = pList->GetItemData(iPos);
|
|
|
|
// Given the key, find it in our list of items
|
|
pos = pPoolList->GetHeadPosition();
|
|
while (pos)
|
|
{
|
|
posT = pos;
|
|
|
|
poolInfo = pPoolList->GetNext(pos);
|
|
|
|
if (poolInfo.m_dwKey == dwKey)
|
|
break;
|
|
}
|
|
|
|
// Did we find a match?
|
|
if (dwKey)
|
|
{
|
|
Assert(posT);
|
|
poolInfo = pPoolList->GetAt(posT);
|
|
|
|
CAddressPoolDialog dlg(&poolInfo,
|
|
pPoolList,
|
|
FALSE);
|
|
|
|
if (dlg.DoModal() == IDOK)
|
|
{
|
|
// set it back
|
|
st = INET_NTOA(poolInfo.m_netStart);
|
|
pList->SetItemText(iPos, IPPOOLCOL_START, st);
|
|
|
|
st = INET_NTOA(poolInfo.m_netEnd);
|
|
pList->SetItemText(iPos, IPPOOLCOL_END, st);
|
|
|
|
FormatNumber(poolInfo.GetNumberOfAddresses(),
|
|
szBuffer,
|
|
DimensionOf(szBuffer),
|
|
FALSE);
|
|
pList->SetItemText(iPos, IPPOOLCOL_RANGE, szBuffer);
|
|
|
|
if (flags & ADDRPOOL_LONG)
|
|
{
|
|
st = INET_NTOA(poolInfo.m_netAddress);
|
|
pList->SetItemText(iPos, IPPOOLCOL_IPADDRESS, st);
|
|
|
|
st = INET_NTOA(poolInfo.m_netMask);
|
|
pList->SetItemText(iPos, IPPOOLCOL_MASK, st);
|
|
}
|
|
|
|
pPoolList->SetAt(posT, poolInfo);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void OnDeleteAddressPool(HWND hWnd, CListCtrl *pList, LPARAM flags, AddressPoolList *pPoolList)
|
|
{
|
|
INT iPos;
|
|
DWORD dwKey = 0;
|
|
POSITION pos, posT;
|
|
AddressPoolInfo poolInfo;
|
|
|
|
// Ok, need to remove the selected item from the list and from the UI
|
|
|
|
// Is there a selected item?
|
|
if ((iPos = pList->GetNextItem(-1, LVNI_SELECTED)) == -1)
|
|
return;
|
|
|
|
dwKey = pList->GetItemData(iPos);
|
|
|
|
// Given the key, find it in our list of items
|
|
pos = pPoolList->GetHeadPosition();
|
|
while (pos)
|
|
{
|
|
posT = pos;
|
|
|
|
poolInfo = pPoolList->GetNext(pos);
|
|
|
|
if (poolInfo.m_dwKey == dwKey)
|
|
break;
|
|
}
|
|
|
|
// Did we find a match?
|
|
if (dwKey)
|
|
{
|
|
INT nCount;
|
|
|
|
Assert(posT);
|
|
pPoolList->RemoveAt(posT);
|
|
pList->DeleteItem(iPos);
|
|
|
|
// Ok, update the selected state to point at the next item
|
|
nCount = pList->GetItemCount();
|
|
if (nCount > 0)
|
|
{
|
|
iPos = min(nCount-1, iPos);
|
|
pList->SetItemState(iPos, LVIS_SELECTED, LVIS_SELECTED);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
AddressPoolInfo::GetNewKey
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
DWORD AddressPoolInfo::GetNewKey()
|
|
{
|
|
static DWORD s_dwAddressPoolKey = 1;
|
|
|
|
m_dwKey = s_dwAddressPoolKey;
|
|
++s_dwAddressPoolKey;
|
|
return m_dwKey;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
AddressPoolInfo::SetAddressAndMask
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
void AddressPoolInfo::SetAddressAndMask(DWORD netAddress, DWORD netMask)
|
|
{
|
|
// Ok, need to determine the start and end address
|
|
DWORD netStart, netEnd;
|
|
|
|
m_netStart = netAddress & netMask;
|
|
m_netEnd = netAddress | ~netMask;
|
|
m_netAddress = netAddress;
|
|
m_netMask = netMask;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
AddressPoolInfo::SetStartAndEnd
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
void AddressPoolInfo::SetStartAndEnd(DWORD netStart, DWORD netEnd)
|
|
{
|
|
DWORD dwAddress, dwMask, dwTemp, dwMaskTemp;
|
|
DWORD dwStart, dwEnd;
|
|
// Given the start and the end, figure out the address and mask
|
|
|
|
// Save the start/end addresses before they get converted to host form.
|
|
m_netStart = netStart;
|
|
m_netEnd = netEnd;
|
|
|
|
dwStart = ntohl(netStart);
|
|
dwEnd = ntohl(netEnd);
|
|
|
|
// This will put 1's where the bits have the same value
|
|
dwTemp = ~(dwStart ^ dwEnd);
|
|
|
|
// Now we look for the first 0 bit (looking from high bit to low bit)
|
|
// This will give us our mask
|
|
dwMask = 0;
|
|
dwMaskTemp = 0;
|
|
for (int i=0; i<sizeof(DWORD)*8; i++)
|
|
{
|
|
dwMaskTemp >>= 1;
|
|
dwMaskTemp |= 0x80000000;
|
|
|
|
// Is there a zero bit?
|
|
if ((dwMaskTemp & dwTemp) != dwMaskTemp)
|
|
{
|
|
// There is a zero, so we break out.
|
|
break;
|
|
}
|
|
|
|
// If not, continue
|
|
dwMask = dwMaskTemp;
|
|
}
|
|
|
|
m_netMask = htonl(dwMask);
|
|
m_netAddress = htonl(dwMask & dwStart);
|
|
}
|
|
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
AddressPoolList::HrIsValidAddressPool
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT AddressPoolList::HrIsValidAddressPool(AddressPoolInfo *pInfo)
|
|
{
|
|
DWORD dwStart, dwEnd; // in host order
|
|
|
|
dwStart = ntohl(pInfo->m_netStart);
|
|
dwEnd = ntohl(pInfo->m_netEnd);
|
|
|
|
// Verify that this is a valid address pool entry.
|
|
|
|
// First, check to see that the end is greater than the start
|
|
// We add one to the start address, to include the RAS adapter
|
|
// ----------------------------------------------------------------
|
|
if (dwStart >= dwEnd)
|
|
{
|
|
return IDS_ERR_IP_ADDRESS_POOL_RANGE_TOO_SMALL;
|
|
}
|
|
|
|
// Now check to see that the 127 range is not included
|
|
// ----------------------------------------------------------------
|
|
if ((dwEnd >= MAKEIPADDRESS(127,0,0,0)) &&
|
|
(dwStart <= MAKEIPADDRESS(127,255,255,255)))
|
|
{
|
|
return IDS_ERR_IP_ADDRESS_POOL_RANGE_OVERLAPS_127;
|
|
}
|
|
|
|
// Check to see that the addresses are in the normal range
|
|
// 1.0.0.0 <= address < 224.0.0.0
|
|
// ----------------------------------------------------------------
|
|
if ((dwStart < MAKEIPADDRESS(1,0,0,0)) ||
|
|
(dwEnd > MAKEIPADDRESS(223,255,255,255)))
|
|
{
|
|
return IDS_ERR_IP_ADDRESS_POOL_RANGE_NOT_NORMAL;
|
|
}
|
|
|
|
Assert(pInfo->GetNumberOfAddresses() > 0);
|
|
|
|
//$ TODO : Need to check that we don't have overlaps
|
|
if (GetCount())
|
|
{
|
|
POSITION pos;
|
|
AddressPoolInfo poolInfo;
|
|
DWORD dwPoolStart, dwPoolEnd;
|
|
|
|
pos = GetHeadPosition();
|
|
|
|
while (pos)
|
|
{
|
|
poolInfo = GetNext(pos);
|
|
|
|
if (poolInfo.m_dwKey == pInfo->m_dwKey)
|
|
continue;
|
|
|
|
dwPoolStart = ntohl(poolInfo.m_netStart);
|
|
dwPoolEnd = ntohl(poolInfo.m_netEnd);
|
|
|
|
// do we overlap?
|
|
if ((dwEnd >= dwPoolStart) && (dwStart <= dwPoolEnd))
|
|
{
|
|
return IDS_ERR_IP_ADDRESS_POOL_OVERLAP;
|
|
}
|
|
}
|
|
}
|
|
|
|
return hrOK;
|
|
}
|
|
|
|
BOOL AddressPoolList::FUsesMultipleAddressPools()
|
|
{
|
|
return m_fMultipleAddressPools;
|
|
}
|
|
|
|
|
|
HRESULT AddressPoolList::LoadFromReg(HKEY hkeyRasIp, DWORD dwBuildNo)
|
|
{
|
|
HRESULT hr = hrOK;
|
|
RegKey regkeyRasIp;
|
|
RegKey regkeyPool;
|
|
RegKey regkeyRange;
|
|
CString stIpAddr, stIpMask;
|
|
AddressPoolInfo poolInfo;
|
|
DWORD dwIpAddr, dwMask;
|
|
DWORD dwFrom, dwTo;
|
|
RegKeyIterator regkeyIter;
|
|
HRESULT hrIter;
|
|
CString stKey;
|
|
|
|
m_fMultipleAddressPools = FALSE;
|
|
|
|
regkeyRasIp.Attach(hkeyRasIp);
|
|
|
|
COM_PROTECT_TRY
|
|
{
|
|
// Remove all of the old addresses
|
|
RemoveAll();
|
|
|
|
// Support multiple address pools only if we are on newer builds.
|
|
// ------------------------------------------------------------
|
|
m_fMultipleAddressPools = (dwBuildNo >= STATIC_ADDRESSPOOL_BUILDNO);
|
|
|
|
|
|
// Check to see if the StaticAddressPool key exists, if so
|
|
// then we use that, otherwise use the ip addr and mask
|
|
// entries
|
|
// Check out RemoteAccess\Parameters\Ip\StaticAddressPool
|
|
// ------------------------------------------------------------
|
|
if ( ERROR_SUCCESS == regkeyPool.Open(regkeyRasIp,
|
|
c_szRegValStaticAddressPool))
|
|
{
|
|
TCHAR szKeyName[32];
|
|
INT iCount = 0;
|
|
|
|
// Instead of enumerating we open up the keys one-by-one
|
|
// (to maintain the order of the keys).
|
|
// --------------------------------------------------------
|
|
while (TRUE)
|
|
{
|
|
// Cleanup from previous loop
|
|
// ----------------------------------------------------
|
|
regkeyRange.Close();
|
|
|
|
// Setup for this loop
|
|
// ----------------------------------------------------
|
|
wsprintf(szKeyName, _T("%d"), iCount);
|
|
|
|
// Try to open the key
|
|
// If we fail, bail out of the loop.
|
|
// ----------------------------------------------------
|
|
if (ERROR_SUCCESS != regkeyRange.Open(regkeyPool, szKeyName))
|
|
break;
|
|
|
|
regkeyRange.QueryValue(c_szRegValFrom, dwFrom);
|
|
regkeyRange.QueryValue(c_szRegValTo, dwTo);
|
|
|
|
poolInfo.SetStartAndEnd(htonl(dwFrom), htonl(dwTo));
|
|
poolInfo.GetNewKey();
|
|
|
|
// Ok, add this to the list of address ranges
|
|
// ----------------------------------------------------
|
|
AddTail(poolInfo);
|
|
iCount++;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// We can't find the StaticAddressPool key, so use the
|
|
// data in the address/mask entries.
|
|
// --------------------------------------------------------
|
|
regkeyRasIp.QueryValue(c_szRegValIpAddr, stIpAddr);
|
|
regkeyRasIp.QueryValue(c_szRegValIpMask, stIpMask);
|
|
|
|
if (!stIpAddr.IsEmpty() && !stIpMask.IsEmpty())
|
|
{
|
|
dwIpAddr = INET_ADDR((LPTSTR) (LPCTSTR) stIpAddr);
|
|
dwMask = INET_ADDR((LPTSTR) (LPCTSTR) stIpMask);
|
|
|
|
poolInfo.SetAddressAndMask(dwIpAddr, dwMask);
|
|
poolInfo.GetNewKey();
|
|
|
|
// Add this to the head of the list
|
|
AddHead(poolInfo);
|
|
}
|
|
}
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
|
|
regkeyRasIp.Detach();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
AddressPoolList::SaveToReg
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT AddressPoolList::SaveToReg(HKEY hkeyRasIp, DWORD dwBuildNo)
|
|
{
|
|
HRESULT hr = hrOK;
|
|
AddressPoolInfo poolInfo;
|
|
CString stAddress, stMask;
|
|
CString stRange;
|
|
POSITION pos;
|
|
RegKey regkeyRasIp;
|
|
RegKey regkeyPool;
|
|
RegKey regkeyRange;
|
|
DWORD dwCount;
|
|
DWORD dwErr, dwData;
|
|
|
|
regkeyRasIp.Attach(hkeyRasIp);
|
|
|
|
COM_PROTECT_TRY
|
|
{
|
|
// Reset the m_fMultipleAddressPools
|
|
m_fMultipleAddressPools = (dwBuildNo >= STATIC_ADDRESSPOOL_BUILDNO);
|
|
|
|
// If this is a newer build, use the StaticAddressPoolKey,
|
|
// otherwise use the old keys.
|
|
// ------------------------------------------------------------
|
|
if (m_fMultipleAddressPools)
|
|
{
|
|
// Open RemoteAccess\Parameters\Ip\StaticAddressPool
|
|
// --------------------------------------------------------
|
|
CWRg( regkeyPool.Create(regkeyRasIp,
|
|
c_szRegValStaticAddressPool) );
|
|
|
|
// Delete all of the current keys in the list
|
|
// ------------------------------------------------------------
|
|
regkeyPool.RecurseDeleteSubKeys();
|
|
|
|
// Delete any of the older keys
|
|
// --------------------------------------------------------
|
|
regkeyRasIp.DeleteValue(c_szRegValIpAddr);
|
|
regkeyRasIp.DeleteValue(c_szRegValIpMask);
|
|
|
|
// Now enumerate through the address pool list and
|
|
// add all of those keys.
|
|
// ------------------------------------------------------------
|
|
if (GetCount())
|
|
{
|
|
pos = GetHeadPosition();
|
|
dwCount = 0;
|
|
|
|
while (pos)
|
|
{
|
|
poolInfo = GetNext(pos);
|
|
|
|
regkeyRange.Close();
|
|
|
|
// This is the title for the key
|
|
// ------------------------------------------------
|
|
stRange.Format(_T("%d"), dwCount);
|
|
|
|
CWRg( regkeyRange.Create(regkeyPool, stRange) );
|
|
|
|
dwData = ntohl(poolInfo.m_netStart);
|
|
CWRg( regkeyRange.SetValue(c_szRegValFrom, dwData) );
|
|
|
|
dwData = ntohl(poolInfo.m_netEnd);
|
|
CWRg( regkeyRange.SetValue(c_szRegValTo, dwData) );
|
|
|
|
dwCount++;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Just write out the first address we find, if there are none then
|
|
// write out blanks (to erase any previous values).
|
|
if (GetCount())
|
|
{
|
|
// Get the first address info
|
|
Assert(GetCount() == 1);
|
|
|
|
poolInfo = GetHead();
|
|
|
|
stAddress = INET_NTOA(poolInfo.m_netAddress);
|
|
stMask = INET_NTOA(poolInfo.m_netMask);
|
|
|
|
CWRg( regkeyRasIp.SetValue( c_szRegValIpAddr, (LPCTSTR) stAddress) );
|
|
CWRg( regkeyRasIp.SetValue( c_szRegValIpMask, (LPCTSTR) stMask) );
|
|
}
|
|
else
|
|
{
|
|
CWRg( regkeyRasIp.SetValue( c_szRegValIpAddr, (LPCTSTR) _T("")) );
|
|
CWRg( regkeyRasIp.SetValue( c_szRegValIpMask, (LPCTSTR) _T("")) );
|
|
}
|
|
}
|
|
COM_PROTECT_ERROR_LABEL;
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
|
|
regkeyRasIp.Detach();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
CAddressPoolDialog implementation
|
|
---------------------------------------------------------------------------*/
|
|
CAddressPoolDialog::CAddressPoolDialog(
|
|
AddressPoolInfo *pPool,
|
|
AddressPoolList *pPoolList,
|
|
BOOL fCreate)
|
|
: CBaseDialog(IDD_IPPOOL),
|
|
m_pPool(pPool),
|
|
m_fCreate(fCreate),
|
|
m_fReady(FALSE),
|
|
m_pPoolList(pPoolList)
|
|
{
|
|
}
|
|
|
|
void CAddressPoolDialog::DoDataExchange(CDataExchange *pDX)
|
|
{
|
|
CBaseDialog::DoDataExchange(pDX);
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CAddressPoolDialog, CBaseDialog)
|
|
ON_EN_CHANGE(IDC_IPPOOL_IP_START, OnChangeStartAddress)
|
|
ON_EN_CHANGE(IDC_IPPOOL_IP_END, OnChangeEndAddress)
|
|
ON_EN_CHANGE(IDC_IPPOOL_EDIT_RANGE, OnChangeRange)
|
|
ON_EN_KILLFOCUS(IDC_IPPOOL_IP_START, OnKillFocusStartAddress)
|
|
ON_EN_KILLFOCUS(IDC_IPPOOL_IP_END, OnKillFocusEndAddress)
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
BOOL CAddressPoolDialog::OnInitDialog()
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
|
|
CString st;
|
|
TCHAR szBuffer[64];
|
|
|
|
CBaseDialog::OnInitDialog();
|
|
|
|
st.LoadString(m_fCreate ? IDS_ADD_IPPOOL_TITLE : IDS_EDIT_IPPOOL_TITLE);
|
|
SetWindowText((LPCTSTR) st);
|
|
|
|
m_ipStartAddress.Create(GetSafeHwnd(), IDC_IPPOOL_IP_START);
|
|
st = INET_NTOA(m_pPool->m_netStart);
|
|
m_ipStartAddress.SetAddress((LPCTSTR) st);
|
|
|
|
m_ipEndAddress.Create(GetSafeHwnd(), IDC_IPPOOL_IP_END);
|
|
st = INET_NTOA(m_pPool->m_netEnd);
|
|
m_ipEndAddress.SetAddress((LPCTSTR) st);
|
|
|
|
GenerateRange();
|
|
|
|
m_fReady = TRUE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CAddressPoolDialog::OnOK()
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
|
|
CString st;
|
|
DWORD netStart, netEnd;
|
|
HRESULT hr = hrOK;
|
|
UINT ids = 0;
|
|
|
|
// Ok, check the validity of the addresses
|
|
// Are all of the fields there?
|
|
if (m_ipStartAddress.IsBlank())
|
|
{
|
|
AfxMessageBox(IDS_ERR_ADDRESS_POOL_NO_START_ADDRESS);
|
|
return;
|
|
}
|
|
if (m_ipEndAddress.IsBlank())
|
|
{
|
|
AfxMessageBox(IDS_ERR_ADDRESS_POOL_NO_END_ADDRESS);
|
|
return;
|
|
}
|
|
|
|
m_ipStartAddress.GetAddress(st);
|
|
netStart = INET_ADDR((LPTSTR)(LPCTSTR)st);
|
|
if ((netStart == 0) || (netStart == 0xFFFFFFFF))
|
|
{
|
|
AfxMessageBox(IDS_ERR_ADDRESS_POOL_NO_START_ADDRESS);
|
|
return;
|
|
}
|
|
|
|
m_ipEndAddress.GetAddress(st);
|
|
netEnd = INET_ADDR((LPTSTR)(LPCTSTR)st);
|
|
if ((netEnd == 0) || (netEnd == 0xFFFFFFFF))
|
|
{
|
|
AfxMessageBox(IDS_ERR_ADDRESS_POOL_NO_END_ADDRESS);
|
|
return;
|
|
}
|
|
|
|
m_pPool->SetStartAndEnd(netStart, netEnd);
|
|
|
|
if (!FHrOK(hr = m_pPoolList->HrIsValidAddressPool(m_pPool)))
|
|
{
|
|
if (FHrSucceeded(hr))
|
|
{
|
|
// If it is not hrOK and is not an error code,
|
|
// the success code can be interpreted as a string id
|
|
AfxMessageBox(hr);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
CBaseDialog::OnOK();
|
|
}
|
|
|
|
void CAddressPoolDialog::OnChangeStartAddress()
|
|
{
|
|
if (m_fReady)
|
|
GenerateRange();
|
|
}
|
|
|
|
void CAddressPoolDialog::OnChangeEndAddress()
|
|
{
|
|
if (m_fReady)
|
|
GenerateRange();
|
|
}
|
|
|
|
void CAddressPoolDialog::OnChangeRange()
|
|
{
|
|
if (m_fReady)
|
|
{
|
|
CString st;
|
|
DWORD dwAddr, dwSize;
|
|
DWORD netAddr;
|
|
DWORD dwRange;
|
|
|
|
m_fReady = FALSE;
|
|
|
|
// Get the start address and update the end address
|
|
m_ipStartAddress.GetAddress(st);
|
|
dwAddr = ntohl(INET_ADDR(st));
|
|
|
|
// Have to read in the text, but strip out the
|
|
// commas in the range, sigh.
|
|
GetDlgItemText(IDC_IPPOOL_EDIT_RANGE, st);
|
|
|
|
if ( ConvertStringToNumber(st, &dwRange) )
|
|
{
|
|
dwAddr += dwRange;
|
|
// Subtract 1 since this is an inclusive range
|
|
// i.e. 0..(n-1) is n addresses.
|
|
dwAddr -= 1;
|
|
netAddr = htonl(dwAddr);
|
|
st = INET_NTOA(netAddr);
|
|
m_ipEndAddress.SetAddress(st);
|
|
|
|
}
|
|
else
|
|
{
|
|
CString stGood;
|
|
//Filter the bad chars out of the box
|
|
FilterBadChars (st, stGood);
|
|
SetDlgItemText (IDC_IPPOOL_EDIT_RANGE, stGood );
|
|
AfxMessageBox (IDS_ILLEGAL_CHARACTER, MB_ICONERROR | MB_OK );
|
|
}
|
|
|
|
|
|
m_fReady = TRUE;
|
|
}
|
|
}
|
|
|
|
void CAddressPoolDialog::OnKillFocusStartAddress()
|
|
{
|
|
GenerateRange();
|
|
|
|
if (m_ipEndAddress.IsBlank())
|
|
{
|
|
CString st;
|
|
m_ipStartAddress.GetAddress(st);
|
|
m_ipEndAddress.SetAddress(st);
|
|
}
|
|
}
|
|
|
|
void CAddressPoolDialog::OnKillFocusEndAddress()
|
|
{
|
|
GenerateRange();
|
|
}
|
|
|
|
|
|
void CAddressPoolDialog::GenerateRange()
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
DWORD dwStart, dwEnd;
|
|
TCHAR szBuffer[64];
|
|
CString st;
|
|
|
|
m_ipStartAddress.GetAddress(st);
|
|
dwStart = ntohl(INET_ADDR(st));
|
|
|
|
m_ipEndAddress.GetAddress(st);
|
|
dwEnd = ntohl(INET_ADDR(st));
|
|
|
|
m_fReady = FALSE;
|
|
|
|
// Display the range.
|
|
if (dwStart >= dwEnd)
|
|
{
|
|
SetDlgItemInt(IDC_IPPOOL_EDIT_RANGE, 0);
|
|
}
|
|
else
|
|
{
|
|
FormatNumber(dwEnd - dwStart + 1,
|
|
szBuffer,
|
|
DimensionOf(szBuffer),
|
|
FALSE);
|
|
SetDlgItemText(IDC_IPPOOL_EDIT_RANGE, szBuffer);
|
|
}
|
|
m_fReady = TRUE;
|
|
}
|
|
|
|
void FilterBadChars (LPCTSTR pszEvilString, CString & stGood)
|
|
{
|
|
static TCHAR s_szThousandsSeparator[5] = TEXT("");
|
|
static int s_cchThousands;
|
|
stGood.Empty();
|
|
|
|
if (s_szThousandsSeparator[0] == TEXT('\0'))
|
|
{
|
|
::GetLocaleInfo(
|
|
LOCALE_USER_DEFAULT,
|
|
LOCALE_STHOUSAND,
|
|
s_szThousandsSeparator,
|
|
4
|
|
);
|
|
s_cchThousands = StrLen(s_szThousandsSeparator);
|
|
}
|
|
while (*pszEvilString )
|
|
{
|
|
if (_istdigit(*pszEvilString))
|
|
stGood += *pszEvilString++;
|
|
else
|
|
{
|
|
// It's not a digit, we need to check to see if this
|
|
// is a separator
|
|
if (StrnCmp(pszEvilString, s_szThousandsSeparator, s_cchThousands) == 0)
|
|
{
|
|
// This is a separtor, skip over the string
|
|
pszEvilString += s_cchThousands;
|
|
}
|
|
else
|
|
{
|
|
// skip this character, we're at a character we don't understand
|
|
pszEvilString ++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
ConvertStringToNumber
|
|
This will convert the string into a number (even in the presence
|
|
of thousands separtors).
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
BOOL ConvertStringToNumber(LPCTSTR pszString, DWORD * pdwRet)
|
|
{
|
|
static TCHAR s_szThousandsSeparator[5] = TEXT("");
|
|
static int s_cchThousands;
|
|
|
|
if (s_szThousandsSeparator[0] == TEXT('\0'))
|
|
{
|
|
::GetLocaleInfo(
|
|
LOCALE_USER_DEFAULT,
|
|
LOCALE_STHOUSAND,
|
|
s_szThousandsSeparator,
|
|
4
|
|
);
|
|
s_cchThousands = StrLen(s_szThousandsSeparator);
|
|
}
|
|
|
|
|
|
|
|
// Make a copy of the string
|
|
TCHAR * psz = (TCHAR *) _alloca((StrLen(pszString) + 1) * sizeof(WCHAR));
|
|
TCHAR * pszCur = psz;
|
|
|
|
// Now copy over the characters from pszString to psz, skipping
|
|
// the numeric separators
|
|
int cLen = StrLen(pszString);
|
|
while (*pszString)
|
|
{
|
|
if (_istdigit(*pszString))
|
|
*pszCur++ = *pszString++;
|
|
else
|
|
{
|
|
// It's not a digit, we need to check to see if this
|
|
// is a separator
|
|
if (StrnCmp(pszString, s_szThousandsSeparator, s_cchThousands) == 0)
|
|
{
|
|
// This is a separtor, skip over the string
|
|
pszString += s_cchThousands;
|
|
}
|
|
// Else we're done, we're at a character we don't understand
|
|
else
|
|
{
|
|
//this is an error case
|
|
return FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
*pdwRet = _tcstoul(psz, NULL, 10);
|
|
return TRUE;
|
|
}
|