Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

693 lines
17 KiB

#include "pch.h"
#pragma hdrstop
#include "button.h"
#include "odb.h"
#include "const.h"
#include "resource.h"
#include "ipctrl.h"
#include "tcpsht.h"
#include "tcphelp.h"
WNDPROC CBootpPage::lpfnOldWndProc=NULL;
CBootpIO::CBootpIO()
{
m_edit = FALSE;
m_newAddr = _T("");
}
CBootpIO::~CBootpIO()
{
}
BOOL CBootpIO::OnInitDialog()
{
HWND hDlg = *this;
CBootpPage* pPage = GetParentObject(CBootpPage, m_io);
// initialize ip controls
// reused the one from the the DNS page
VERIFY(m_ipAddr.Create(hDlg, IDC_DNS_CHANGE_SERVER));
m_ipAddr.SetFieldRange(0, 1, 223);
String caption;
caption.LoadString(hTcpCfgInstance, IDS_BOOTP_IOBOX);
SetWindowText(hDlg, caption);
m_hButton = GetDlgItem(hDlg, IDOK);
if (m_edit == FALSE)
{
caption.LoadString(hTcpCfgInstance, IDS_ADD);
SetWindowText(m_hButton, caption);
}
caption.LoadString(hTcpCfgInstance, IDS_DHCP_ADD_TEXT);
SetDlgItemText(hDlg, IDC_DNS_CHANGE_SERVER_TEXT, caption);
// repos the windows relative to the static text at top
HWND hListBox = GetDlgItem(*pPage, IDC_BOOTP_DHCP_LIST);
RECT rect;
if (hListBox)
{
GetWindowRect(hListBox, &rect);
SetWindowPos(hDlg, NULL, rect.left, rect.top, 0,0,
SWP_NOZORDER|SWP_NOSIZE|SWP_NOACTIVATE);
}
// initialize with a previosu saved address
if (m_newAddr.QueryTextLength())
m_ipAddr.SetAddress(m_newAddr);
return TRUE;
}
BOOL CBootpIO::OnCommand(WPARAM wParam, LPARAM lParam)
{
return CDialog::OnCommand(wParam, lParam);
}
void CBootpIO::OnOk()
{
m_ipAddr.GetAddress(&m_newAddr);
CDialog::OnOk();
}
////////////////////////////////////////////////////////////////////////////////////////////////
///////////
CBootpPage::CBootpPage(CTcpSheet* pSheet) : PropertyPage(pSheet)
{
m_change = FALSE;
}
CBootpPage::~CBootpPage()
{
}
BOOL CBootpPage::OnInitDialog()
{
HWND hDlg = *this;
SubclassEditCtrls();
m_io.Create(hDlg, hTcpCfgInstance, IDD_DNS_SERVER, lpszHelpFile, &a133HelpIDs[0]);
// set control limits
SendDlgItemMessage(hDlg, IDC_BOOTP_SEC_CTRL, UDM_SETRANGE, 0,
(LPARAM)MAKELONG(MAX_SECSTHRESHOLD, MIN_SECSTHRESHOLD));
SendDlgItemMessage(hDlg, IDC_BOOTP_SECONDS, EM_LIMITTEXT, 4, 0);
SendDlgItemMessage(hDlg, IDC_BOOTP_MAX_CTRL, UDM_SETRANGE, 0,
(LPARAM)MAKELONG(MAX_HOPSTHRESHOLD, MIN_HOPSTHRESHOLD));
SendDlgItemMessage(hDlg, IDC_BOOTP_MAXHOPS, EM_LIMITTEXT, 2, 0);
LoadRegistry();
OnSelChanged(); // update button to edit/remove DHCP servers
#ifdef SERVICE_MANAGER
CheckDlgButton(hDlg, IDC_BOOTP_ENABLE, IsServiceStarted());
#endif
return TRUE;
}
int CBootpPage::OnActive()
{
return TRUE;
}
BOOL CBootpPage::OnNotify(HWND hwndParent, UINT idFrom, UINT code, LPARAM lParam)
{
if (idFrom == IDC_BOOTP_SEC_CTRL || idFrom == IDC_BOOTP_MAX_CTRL)
{
PageModified();
return TRUE;
}
return PropertyPage::OnNotify(hwndParent, idFrom, code, lParam);
}
BOOL CBootpPage::OnCommand(WPARAM wParam, LPARAM lParam)
{
WORD nNotify = HIWORD(wParam);
switch(LOWORD(wParam))
{
#ifdef SERVICE_MANAGER
case IDC_BOOTP_ENABLE:
if (IsDlgButtonChecked(*this, IDC_BOOTP_ENABLE))
StartService();
else
StopService();
break;
#endif
case IDC_BOOTP_ADD:
OnAdd();
break;
case IDC_BOOTP_EDIT:
OnEdit();
break;
case IDC_BOOTP_REMOVE:
OnRemove();
break;
case IDC_BOOTP_SECONDS:
case IDC_BOOTP_MAXHOPS:
if (nNotify == EN_UPDATE)
PageModified();
break;
case IDC_BOOTP_DHCP_LIST:
switch(nNotify)
{
case LBN_SELCHANGE:
OnSelChanged();
break;
default:
break;
}
break;
default:
break;
}
return TRUE;
}
BOOL CBootpPage::LoadRegistry()
{
HKEY hkeyParams;
DWORD dwHopsThreshold;
DWORD dwSecsThreshold;
LPTSTR lpszServers, lpsrv;
DWORD dwErr, dwSize, dwType;
HWND hDlg = *this;
dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
REGKEY_SERVICES REG_CONNECT_STR REGKEY_RELAYPARAMS,
0, KEY_READ, &hkeyParams);
if (dwErr != ERROR_SUCCESS)
{
// bootp is not installed set to default values
// set the values in the dialog box
SetDlgItemInt(hDlg, IDC_BOOTP_MAXHOPS, DEF_HOPSTHRESHOLD, FALSE);
SetDlgItemInt(hDlg, IDC_BOOTP_SECONDS, DEF_SECSTHRESHOLD, FALSE);
return FALSE;
}
// read the hops threshold
dwSize = sizeof(dwHopsThreshold);
dwErr = RegQueryValueEx(hkeyParams, REGVAL_HOPSTHRESHOLD,
NULL, &dwType, (LPBYTE)&dwHopsThreshold,
&dwSize);
if (dwErr != ERROR_SUCCESS || dwType != REG_DWORD)
dwHopsThreshold = DEF_HOPSTHRESHOLD;
// read the secs threshold
dwSize = sizeof(dwSecsThreshold);
dwErr = RegQueryValueEx(hkeyParams, REGVAL_SECSTHRESHOLD,
NULL, &dwType, (LPBYTE)&dwSecsThreshold,
&dwSize);
if (dwErr != ERROR_SUCCESS || dwType != REG_DWORD)
dwSecsThreshold = DEF_SECSTHRESHOLD;
// set the values in the dialog box
SetDlgItemInt(hDlg, IDC_BOOTP_MAXHOPS, dwHopsThreshold, FALSE);
SetDlgItemInt(hDlg, IDC_BOOTP_SECONDS, dwSecsThreshold, FALSE);
// find the size of the string needed to hold the server list
dwErr = RegQueryValueEx(hkeyParams, REGVAL_DHCPSERVERS,NULL, &dwType, NULL, &dwSize);
if (dwErr != ERROR_SUCCESS || dwType != REG_MULTI_SZ)
{
RegCloseKey(hkeyParams);
return FALSE;
}
// RegQueryValueEx sometimes sets the size to zero, but minimum
// string length is one character.
if (dwSize == 0)
dwSize += sizeof(TCHAR);
// allocate the memory for the string
lpszServers = (LPTSTR)calloc(dwSize, 1);
if (lpszServers == NULL)
{
RegCloseKey(hkeyParams);
return FALSE;
}
*lpszServers = _T('\0');
// read the string list
dwErr = RegQueryValueEx(hkeyParams, REGVAL_DHCPSERVERS, NULL, &dwType, (LPBYTE)lpszServers, &dwSize);
if (dwErr != ERROR_SUCCESS || dwType != REG_MULTI_SZ)
{
free(lpszServers);
RegCloseKey(hkeyParams);
return dwErr;
}
HWND hList = GetDlgItem(hDlg, IDC_BOOTP_DHCP_LIST);
// fill the listbox with the strings read
for (lpsrv = lpszServers; *lpsrv != _T('\0'); ++lpsrv)
{
ListBox_AddString(hList, lpsrv);
// fast-forward to the end of this string;
// the for clause steps over the '\0' into the next string, if any
while (*lpsrv != _T('\0'))
++lpsrv;
}
if (ListBox_GetCount(hList))
ListBox_SetCurSel(hList,0);
free(lpszServers);
RegCloseKey(hkeyParams);
return TRUE;
}
BOOL CBootpPage::IsBootpInstalled()
{
HKEY hkeyParams;
DWORD dwErr;
// open the RelayAgent\Parameters key
dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_SERVICES
REG_CONNECT_STR
REGKEY_RELAYPARAMS,
0, KEY_WRITE, &hkeyParams);
// the key doesn't exist
if (dwErr != ERROR_SUCCESS)
return FALSE;
RegCloseKey(hkeyParams);
return TRUE;
}
BOOL CBootpPage::SaveRegistry()
{
HWND hDlg = *this;
int err;
int i, count, len;
HKEY hkeyParams;
DWORD dwErr, dwLength, dwArrLength;
DWORD dwHopsThreshold;
DWORD dwSecsThreshold;
LPTSTR lpszServers, lpsrv;
CTcpSheet* pSheet = GetParentObject(CTcpSheet, m_bootp);
// open the RelayAgent\Parameters key
dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_SERVICES
REG_CONNECT_STR
REGKEY_RELAYPARAMS,
0, KEY_WRITE, &hkeyParams);
// the key doesn't exist
if (dwErr != ERROR_SUCCESS)
return FALSE;
HWND hList = GetDlgItem(hDlg, IDC_BOOTP_DHCP_LIST);
dwHopsThreshold = GetDlgItemInt(hDlg, IDC_BOOTP_MAXHOPS, NULL, FALSE);
dwHopsThreshold = __min(dwHopsThreshold, MAX_HOPSTHRESHOLD);
dwLength = sizeof(dwHopsThreshold);
dwErr = RegSetValueEx(hkeyParams, REGVAL_HOPSTHRESHOLD, 0,
REG_DWORD, (LPBYTE)&dwHopsThreshold,
dwLength);
// store the secs threshold value
dwSecsThreshold = GetDlgItemInt(hDlg, IDC_BOOTP_SECONDS, NULL, FALSE);
dwLength = sizeof(dwSecsThreshold);
dwErr = RegSetValueEx(hkeyParams, REGVAL_SECSTHRESHOLD, 0,
REG_DWORD, (LPBYTE)&dwSecsThreshold,
dwLength);
// find size required for listbox contents
dwArrLength = sizeof(TCHAR); // for the terminating NUL character
count = ListBox_GetCount(hList);
// bootp needs at least 1 DHCP server
if (count == 0)
{
int res;
RegCloseKey(hkeyParams);
res = pSheet->MessageBox(IDS_BOOTP_NEED_DHCP_SERVER, MB_APPLMODAL|MB_ICONEXCLAMATION|MB_YESNO);
return ((res == IDYES) ? FALSE : TRUE);
}
for (i = 0; i < count; i++)
{
dwLength = ListBox_GetTextLen(hList, i) + 1;
if (dwLength != -1)
dwArrLength += (dwLength*sizeof(TCHAR)); // make room for embedded null
}
// allocate memory for the listbox strings
lpszServers = (LPTSTR)calloc(dwArrLength, 1);
if (lpszServers == NULL)
{
dwErr = GetLastError();
RegCloseKey(hkeyParams);
return FALSE;
}
// build the list of strings to store in the registry
for (i = 0, lpsrv = lpszServers; i < count; i++)
{
len = ListBox_GetText(hList, i, lpsrv);
if (len != LB_ERR)
lpsrv += (len + 1); // skip embedded NULL
}
*lpsrv = _T('\0');
// store the string
dwErr = RegSetValueEx(hkeyParams, REGVAL_DHCPSERVERS, 0,
REG_MULTI_SZ, (LPBYTE)lpszServers,
dwArrLength);
free(lpszServers);
RegCloseKey(hkeyParams);
return TRUE;
}
void CBootpPage::OnAdd()
{
m_io.m_edit = FALSE;
if (m_io.DoModal() == IDOK)
{
HWND hList = GetDlgItem(*this, IDC_BOOTP_DHCP_LIST);
int idx = ListBox_AddString(hList, m_io.m_newAddr);
PageModified();
m_io.m_newAddr = _T("");
OnSelChanged();
if (idx != LB_ERR)
ListBox_SetCurSel(hList, idx);
}
}
void CBootpPage::OnEdit()
{
m_io.m_edit = TRUE;
HWND hList = GetDlgItem(*this, IDC_BOOTP_DHCP_LIST);
CTcpSheet* pSheet = GetParentObject(CTcpSheet, m_bootp);
int idx = ListBox_GetCurSel(hList);
if (idx == LB_ERR)
{
pSheet->MessageBox(IDS_BOOTP_ITEM_NOT_SEL);
return;
}
TCHAR buf[HOSTNAME_LENGTH] = {0};
ListBox_GetText(hList, idx, buf);
m_io.m_newAddr = buf;
if (m_io.DoModal() == IDOK)
{
if (ListBox_DeleteString(hList, idx) != LB_ERR)
{
int idx = ListBox_AddString(hList, m_io.m_newAddr);
if (idx != LB_ERR)
ListBox_SetCurSel(hList, idx);
PageModified();
OnSelChanged();
}
m_io.m_newAddr = buf; // save remove address
}
}
void CBootpPage::OnRemove()
{
HWND hList = GetDlgItem(*this, IDC_BOOTP_DHCP_LIST);
CTcpSheet* pSheet = GetParentObject(CTcpSheet, m_bootp);
int idx = ListBox_GetCurSel(hList);
if (idx == LB_ERR)
{
pSheet->MessageBox(IDS_BOOTP_ITEM_NOT_SEL);
return;
}
TCHAR buf[HOSTNAME_LENGTH] = {0};
if (ListBox_GetText(hList, idx, buf) != LB_ERR)
{
m_io.m_newAddr = buf;
ListBox_DeleteString(hList, idx);
PageModified();
OnSelChanged();
if (idx)
ListBox_SetCurSel(hList, (idx-1));
else
ListBox_SetCurSel(hList, idx);
}
}
void CBootpPage::OnSelChanged()
{
HWND hDlg = *this;
HWND hList = GetDlgItem(*this, IDC_BOOTP_DHCP_LIST);
int nCount = ListBox_GetCount(hList);
if (nCount != LB_ERR)
{
EnableWindow(GetDlgItem(hDlg, IDC_BOOTP_EDIT), nCount);
EnableWindow(GetDlgItem(hDlg, IDC_BOOTP_REMOVE), nCount);
}
}
int CBootpPage::OnApply()
{
BOOL nResult = PSNRET_NOERROR;
CTcpSheet* pSheet = GetParentObject(CTcpSheet, m_bootp);
HWND hDlg = (HWND)*this;
BOOL bResult;
// only ask to install bootp if it's not installed and the page has been modified
if ((bResult = IsBootpInstalled()) == FALSE && IsModified())
{
// ask the user if they want to install bootp
if (pSheet->MessageBox(IDS_ASK_USER_TO_INSTALL, MB_YESNO|MB_ICONEXCLAMATION|MB_APPLMODAL) == IDYES)
bResult = InstallBootP();
}
if (bResult == TRUE)
{
if (SaveRegistry() == FALSE)
{
SetFocus(GetDlgItem(*this, IDC_BOOTP_ADD));
return PSNRET_INVALID_NOCHANGEPAGE;
}
}
SetModifiedTo(FALSE); // this page is no longer modified
pSheet->SetSheetModifiedTo(TRUE);
return nResult;
}
void CBootpPage::OnHelp()
{
CTcpSheet* pSheet = GetParentObject(CTcpSheet, m_bootp);
// pSheet->DisplayHelp(GetParent((HWND)*this), HC_IPX_HELP);
}
BOOL CBootpPage::InstallBootP()
{
String cmdLine;
String fmt;
fmt.LoadString(hTcpCfgInstance, IDS_INSTALL_CMDLINE);
// set hwnd
cmdLine.Format(fmt, 0);
STARTUPINFO startInfo;
PROCESS_INFORMATION pInfo;
memset(&startInfo, 0, sizeof(startInfo));
startInfo.cb = sizeof(startInfo);
startInfo.dwFlags = STARTF_USESHOWWINDOW;
startInfo.wShowWindow = SW_SHOWDEFAULT;
if (CreateProcess(NULL, cmdLine.GetBuffer(cmdLine.GetLength()), NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &startInfo, &pInfo))
{
WaitForSingleObject(pInfo.hProcess, INFINITE);
}
else
{
String fmt;
fmt.LoadString(hTcpCfgInstance, IDS_CREATE_PROCESS_ERROR);
String mess;
mess.Format(fmt, GetLastError());
CTcpSheet* pSheet = GetParentObject(CTcpSheet, m_bootp);
pSheet->MessageBox(fmt);
return FALSE;
}
return TRUE;
}
LRESULT CALLBACK CBootpPage::EditProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
ASSERT(CBootpPage::lpfnOldWndProc != NULL);
if (nMsg == WM_CHAR)
{
switch (wParam)
{
case VK_BACK:
case VK_DELETE:
case VK_TAB:
case VK_ESCAPE:
break;
default:
if (!iswdigit(wParam))
{
MessageBeep(0);
return 0;
}
break;
}
}
return CallWindowProc(CBootpPage::lpfnOldWndProc, hWnd, nMsg, wParam, lParam);
}
void CBootpPage::SubclassEditCtrls()
{
HWND hDlg = (HWND)*this;
HWND hConnections = GetDlgItem(hDlg, IDC_BOOTP_MAXHOPS);
HWND hIdle = GetDlgItem(hDlg, IDC_BOOTP_SECONDS);
ASSERT(IsWindow(hConnections));
ASSERT(IsWindow(hIdle));
if (hConnections)
{
CBootpPage::lpfnOldWndProc = (WNDPROC)SetWindowLong(hConnections,
GWL_WNDPROC, (DWORD) CBootpPage::EditProc);
}
if (hIdle)
{
SetWindowLong(hIdle, GWL_WNDPROC, (DWORD) CBootpPage::EditProc);
}
}
BOOL CBootpPage::IsServiceStarted()
{
SC_MANAGER scMgr(NULL, GENERIC_READ | GENERIC_EXECUTE);
if (scMgr.QueryError() != NERR_Success)
return FALSE;
SC_SERVICE svBootp(scMgr, RELAY_AGENT_NAME);
if (svBootp.QueryError() != NERR_Success)
return FALSE;
SERVICE_STATUS sStatus;
if (svBootp.QueryStatus(&sStatus) != NERR_Success)
return FALSE;
return sStatus.dwCurrentState == SERVICE_RUNNING;
}
BOOL CBootpPage::StartService()
{
SC_MANAGER scMgr(NULL, GENERIC_READ | GENERIC_EXECUTE);
if (scMgr.QueryError() != NERR_Success)
return FALSE;
SC_SERVICE svBootp(scMgr, RELAY_AGENT_NAME, SERVICE_INTERROGATE | SERVICE_START | GENERIC_READ | GENERIC_EXECUTE);
if (svBootp.QueryError() != NERR_Success)
return FALSE;
APIERR err = svBootp.Start(0, NULL);
if (err != NERR_Success)
{
CTcpSheet* pSheet = GetParentObject(CTcpSheet, m_bootp);
String fmt;
fmt.LoadString(hTcpCfgInstance, IDS_BOOTP_SERVICE_ERROR_START);
String mess;
mess.Format(fmt, err);
pSheet->MessageBox(mess);
}
return err == NERR_Success;
}
BOOL CBootpPage::StopService()
{
SC_MANAGER scMgr(NULL, GENERIC_READ | GENERIC_EXECUTE);
if (scMgr.QueryError() != NERR_Success)
return FALSE;
SC_SERVICE svBootp(scMgr, RELAY_AGENT_NAME, SERVICE_INTERROGATE | SERVICE_STOP | GENERIC_READ | GENERIC_EXECUTE);
if (svBootp.QueryError() != NERR_Success)
return FALSE;
SERVICE_STATUS sStatus;
if (svBootp.QueryStatus(&sStatus) != NERR_Success)
return FALSE;
svBootp.Control(SERVICE_CONTROL_STOP, &sStatus);
if (sStatus.dwCurrentState != SERVICE_STOPPED && sStatus.dwCurrentState != SERVICE_STOP_PENDING)
{
CTcpSheet* pSheet = GetParentObject(CTcpSheet, m_bootp);
String fmt;
fmt.LoadString(hTcpCfgInstance, IDS_BOOTP_SERVICE_ERROR_STOP);
String mess;
mess.Format(fmt, sStatus.dwCurrentState);
pSheet->MessageBox(mess);
}
return sStatus.dwCurrentState == SERVICE_STOP_PENDING || sStatus.dwCurrentState == SERVICE_STOPPED;
}