mirror of https://github.com/lianthony/NT4.0
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.
1198 lines
25 KiB
1198 lines
25 KiB
/**********************************************************************/
|
|
/** Microsoft Windows/NT **/
|
|
/** Copyright(c) Microsoft Corp., 1995 **/
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
dhcpadmn.cpp
|
|
Main entry point for dhcp admin tool
|
|
|
|
FILE HISTORY:
|
|
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char BASED_CODE THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
//
|
|
// Registry constants-- key and value names
|
|
//
|
|
#define DHCP_REG_USER_KEY_NAME "Software\\Microsoft\\DHCP Admin Tool"
|
|
#define DHCP_REG_VALUE_HOSTS "KnownHosts"
|
|
|
|
//
|
|
// Typedef for the ShellAbout function
|
|
//
|
|
typedef void (WINAPI *LPFNSHELLABOUT)(HWND, LPTSTR, LPTSTR, HICON);
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CDhcpApp
|
|
|
|
BEGIN_MESSAGE_MAP(CDhcpApp, CWinApp)
|
|
//{{AFX_MSG_MAP(CDhcpApp)
|
|
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
|
|
ON_COMMAND(ID_APP_EXIT, OnAppExit)
|
|
ON_UPDATE_COMMAND_UI(ID_APP_EXIT, OnUpdateAppExit)
|
|
//}}AFX_MSG_MAP
|
|
// Standard file based document commands
|
|
ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
|
|
ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
|
|
//
|
|
// Global help commands
|
|
//
|
|
ON_COMMAND(ID_HELP_INDEX, CWinApp::OnHelpFinder)
|
|
ON_COMMAND(ID_HELP_USING, CWinApp::OnHelpUsing)
|
|
ON_COMMAND(ID_HELP, CWinApp::OnHelp)
|
|
ON_COMMAND(ID_CONTEXT_HELP, CWinApp::OnContextHelp)
|
|
ON_COMMAND(ID_DEFAULT_HELP, CWinApp::OnHelpIndex)
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CDhcpApp construction
|
|
|
|
CDhcpApp::CDhcpApp()
|
|
: m_b_winsock_inited( FALSE )
|
|
{
|
|
#ifdef _TIGHTMEMCHECKING
|
|
afxMemDF |= checkAlwaysMemDF;
|
|
#endif //_TIGHTMEMCHECKING
|
|
}
|
|
|
|
|
|
CDhcpApp :: ~ CDhcpApp()
|
|
{
|
|
}
|
|
|
|
//
|
|
// Change the wait cursor state, but
|
|
// make sure the main window is up to date first
|
|
//
|
|
void
|
|
CDhcpApp :: DoWaitCursor(
|
|
int nCode
|
|
)
|
|
{
|
|
if ( m_pMainWnd != NULL )
|
|
{
|
|
m_pMainWnd->UpdateWindow();
|
|
}
|
|
|
|
CWinApp::DoWaitCursor(nCode);
|
|
}
|
|
|
|
//
|
|
// Change the text in the status bar
|
|
//
|
|
void
|
|
CDhcpApp :: UpdateStatusBar (
|
|
UINT nMsgId
|
|
)
|
|
{
|
|
if ( m_pMainWnd == NULL )
|
|
{
|
|
return ;
|
|
}
|
|
|
|
CString cStr ;
|
|
LONG err = 0 ;
|
|
|
|
CATCH_MEM_EXCEPTION
|
|
{
|
|
cStr.LoadString( nMsgId ) ;
|
|
|
|
((CMainFrame *)m_pMainWnd)->QueryStatusBar().SetPaneText( 0, cStr ) ;
|
|
((CMainFrame *)m_pMainWnd)->QueryStatusBar().UpdateWindow() ;
|
|
}
|
|
END_MEM_EXCEPTION(err)
|
|
}
|
|
|
|
//
|
|
// Set the second pane in the status bar to either "paused" or blank"
|
|
//
|
|
void
|
|
CDhcpApp :: UpdateStatusBarScope (
|
|
BOOL fPaused
|
|
)
|
|
{
|
|
if ( m_pMainWnd == NULL )
|
|
{
|
|
return ;
|
|
}
|
|
|
|
((CMainFrame *)m_pMainWnd)->QueryStatusBar().SetPaneText( 1, fPaused ? m_str_paused : "") ;
|
|
((CMainFrame *)m_pMainWnd)->QueryStatusBar().UpdateWindow() ;
|
|
}
|
|
|
|
|
|
//
|
|
// The name is misleading -- it will actually put the current
|
|
// address in the title bar.
|
|
//
|
|
void
|
|
CDhcpApp :: UpdateStatusBarHost (
|
|
const CHostName * pobHost,
|
|
CWnd * pWnd /* NULL */
|
|
)
|
|
{
|
|
LONG err = 0 ;
|
|
|
|
if ( pWnd == NULL )
|
|
{
|
|
pWnd = m_pMainWnd;
|
|
}
|
|
|
|
char szBuff [128] = "";
|
|
|
|
if ( pobHost )
|
|
{
|
|
DHCP_IP_ADDRESS dhipa = pobHost->QueryIpAddress() ;
|
|
|
|
//
|
|
// If the current address is the loopback address,
|
|
// then display "(LOCAL)" instead in the title bar
|
|
//
|
|
if ( dhipa == 0x7f000001 )
|
|
{
|
|
::lstrcpy(szBuff, (LPCSTR)m_str_Local);
|
|
}
|
|
else
|
|
{
|
|
::UtilCvtIpAddrToString( dhipa, szBuff, sizeof szBuff );
|
|
}
|
|
|
|
}
|
|
|
|
CATCH_MEM_EXCEPTION
|
|
{
|
|
CString strTitle;
|
|
pWnd->GetWindowText(strTitle);
|
|
|
|
//
|
|
// Check for existence of current title. If present,
|
|
// remove it.
|
|
//
|
|
int nPos;
|
|
|
|
if ((nPos = strTitle.Find(m_str_divider)) != -1)
|
|
{
|
|
//
|
|
// Truncate to new length.
|
|
//
|
|
strTitle.ReleaseBuffer(nPos);
|
|
}
|
|
|
|
//
|
|
// Add address if there's one.
|
|
//
|
|
if (*szBuff)
|
|
{
|
|
strTitle += m_str_divider;
|
|
strTitle += szBuff;
|
|
}
|
|
|
|
pWnd->SetWindowText(strTitle);
|
|
}
|
|
END_MEM_EXCEPTION(err)
|
|
}
|
|
|
|
int
|
|
CDhcpApp :: ExitInstance ()
|
|
{
|
|
//
|
|
// Store the persistent information into the Registry.
|
|
//
|
|
StoreHostsList() ;
|
|
|
|
//
|
|
// Terminate use of the WinSock routines.
|
|
//
|
|
if ( m_b_winsock_inited )
|
|
{
|
|
WSACleanup() ;
|
|
}
|
|
|
|
TRACEEOLID( "DHCP app terminated" ) ;
|
|
|
|
return 0 ;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// The one and only CDhcpApp object
|
|
|
|
CDhcpApp NEAR theApp;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CDhcpApp initialization
|
|
|
|
BOOL
|
|
CDhcpApp::InitInstance()
|
|
{
|
|
//
|
|
// Activate any debugging stuff
|
|
//
|
|
DebugInstance() ;
|
|
|
|
//
|
|
// Initialize the CWndIpAddress control window class IPADDRESS
|
|
//
|
|
CWndIpAddress::CreateWindowClass( m_hInstance ) ;
|
|
|
|
#ifdef _USE_3D
|
|
|
|
Enable3dControls(); // Use CTRL3D
|
|
|
|
#endif // _USE_3D
|
|
|
|
LoadStdProfileSettings(); // Load standard INI file options (including MRU)
|
|
|
|
//
|
|
// Load the strings from the resources, or set defaults;
|
|
//
|
|
if ( ! m_str_ip_inv.LoadString( IDS_INFO_FORMAT_IP_INVALID ) )
|
|
{
|
|
m_str_ip_inv = "<INV>" ; // Just in case.
|
|
}
|
|
|
|
if ( ! m_str_paused.LoadString(IDS_INFO_SERVER_INDICATOR) )
|
|
{
|
|
m_str_paused = "Paused";
|
|
}
|
|
|
|
if ( ! m_str_divider.LoadString(IDS_DIVIDER) )
|
|
{
|
|
m_str_divider = " - ";
|
|
}
|
|
|
|
if ( ! m_str_Local.LoadString(IDS_INFO_LOCAL) )
|
|
{
|
|
m_str_Local = "(Local)";
|
|
}
|
|
|
|
if ( ! m_str_LocalListBox.LoadString(IDS_INFO_LOCAL2) )
|
|
{
|
|
m_str_LocalListBox = "* Local Machine *";
|
|
}
|
|
|
|
//
|
|
// Initialize use of the WinSock routines
|
|
//
|
|
WSADATA wsaData ;
|
|
|
|
if ( ::WSAStartup( MAKEWORD( 1, 1 ), & wsaData ) != 0 )
|
|
{
|
|
m_b_winsock_inited = TRUE ;
|
|
}
|
|
|
|
//
|
|
// Register the application's document templates. Document templates
|
|
// serve as the connection between documents, frame windows and views.
|
|
//
|
|
AddDocTemplate(new CSingleDocTemplate(IDR_MAINFRAME,
|
|
RUNTIME_CLASS(CDhcpDoc),
|
|
RUNTIME_CLASS(CMainFrame), // main SDI frame window
|
|
RUNTIME_CLASS(CScopesDlg)));
|
|
|
|
//
|
|
// create a new (empty) document
|
|
//
|
|
OnFileNew();
|
|
|
|
TRACEEOLID( "DHCP app initialized" ) ;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Display the standard shell "about" dialog
|
|
//
|
|
void
|
|
CDhcpApp::OnAppAbout()
|
|
{
|
|
HMODULE hMod;
|
|
LPFNSHELLABOUT lpfn;
|
|
|
|
if (hMod = ::LoadLibrary("SHELL32"))
|
|
{
|
|
if (lpfn = (LPFNSHELLABOUT)::GetProcAddress(hMod, "ShellAboutA"))
|
|
{
|
|
(*lpfn)(m_pMainWnd->m_hWnd, (LPSTR)m_pszAppName,
|
|
(LPSTR)m_pszAppName, LoadIcon(IDR_MAINFRAME));
|
|
}
|
|
::FreeLibrary(hMod);
|
|
}
|
|
else
|
|
{
|
|
::MessageBeep( MB_ICONEXCLAMATION );
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CDhcpApp commands
|
|
//
|
|
LONG
|
|
CDhcpApp :: RemoveHost (
|
|
CHostName * pobHost
|
|
)
|
|
{
|
|
CObListIter obliHost( m_oblHosts ) ;
|
|
CHostName * pobHostNext ;
|
|
//CDhcpScope * pobScope ;
|
|
POSITION pos ;
|
|
|
|
ASSERT(pobHost != NULL);
|
|
|
|
//
|
|
// Remove the host from the master hosts list
|
|
//
|
|
for ( pos = obliHost.QueryPosition() ;
|
|
pobHostNext = (CHostName *) obliHost.Next() ;
|
|
pos = obliHost.QueryPosition() )
|
|
{
|
|
if ( *pobHostNext == *pobHost )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( pobHostNext == NULL )
|
|
{
|
|
return ERROR_FILE_NOT_FOUND ;
|
|
}
|
|
|
|
m_oblHosts.RemoveAt( pos ) ;
|
|
|
|
// Remove all scopes associated with this host.
|
|
//CObListIter obliScope( m_oblScopes ) ;
|
|
//for ( pos = obliScope.QueryPosition() ;
|
|
// pobScope = (CDhcpScope *) obliScope.Next() ;
|
|
// pos = obliScope.QueryPosition() )
|
|
//{
|
|
// const CHostName & obHn = pobScope->QueryScopeId() ;
|
|
// if ( obHn == *pobHost )
|
|
// {
|
|
// //m_oblScopes.RemoveAt( pos ) ;
|
|
// delete pobScope ;
|
|
// }
|
|
//}
|
|
|
|
delete pobHostNext ;
|
|
|
|
return 0 ;
|
|
}
|
|
|
|
LONG
|
|
CDhcpApp :: RefreshHost (
|
|
CHostName * pobHost
|
|
)
|
|
{
|
|
LONG err = RemoveHost( pobHost ) ;
|
|
if ( err == 0 || err == ERROR_FILE_NOT_FOUND )
|
|
{
|
|
err = AddHost( pobHost ) ;
|
|
}
|
|
|
|
return err ;
|
|
}
|
|
|
|
//
|
|
// Get the control rectangle coordinates relative
|
|
// to its parent. This can then be used in
|
|
// SetWindowPos()
|
|
//
|
|
void
|
|
CDhcpApp::GetDlgCtlRect(
|
|
HWND hWndParent,
|
|
HWND hWndControl,
|
|
LPRECT lprcControl
|
|
)
|
|
{
|
|
|
|
#define MapWindowRect(hwndFrom, hwndTo, lprc)\
|
|
MapWindowPoints((hwndFrom), (hwndTo), (POINT *)(lprc), 2)
|
|
|
|
::GetWindowRect(hWndControl, lprcControl);
|
|
::MapWindowRect(NULL, hWndParent, lprcControl);
|
|
}
|
|
|
|
//
|
|
// Add the named host to the hosts list.
|
|
//
|
|
LONG
|
|
CDhcpApp :: AddHost (
|
|
CHostName * pobHost
|
|
)
|
|
{
|
|
LONG err = 0 ;
|
|
CObListIter obli( m_oblHosts ) ;
|
|
CHostName * pobHostKnown ;
|
|
|
|
//
|
|
// First, check that this host isn't already known
|
|
//
|
|
for ( ; pobHostKnown = (CHostName *) obli.Next() ; )
|
|
{
|
|
if ( *pobHostKnown == *pobHost )
|
|
{
|
|
break ;
|
|
}
|
|
}
|
|
|
|
if ( pobHostKnown )
|
|
{
|
|
return IDS_ERR_HOST_ALREADY_CONNECTED ;
|
|
}
|
|
|
|
CDhcpScope * pobScope = NULL ;
|
|
CDhcpEnumScopeElements * pEnumElem = NULL ;
|
|
//const DHCP_SUBNET_INFO * pdhcSubnetInfo ;
|
|
BOOL bScopeFound = FALSE ;
|
|
|
|
CATCH_MEM_EXCEPTION
|
|
{
|
|
//
|
|
// Add the new host to the list.
|
|
//
|
|
m_oblHosts.AddTail( pobHost ) ;
|
|
|
|
TRACEEOLID( "Host added: " << *pobHost ) ;
|
|
|
|
//
|
|
// Mark the hosts list as "dirty" for persistent Registry update.
|
|
//
|
|
m_oblHosts.SetDirty() ;
|
|
}
|
|
END_MEM_EXCEPTION(err)
|
|
|
|
//
|
|
// If the new scope failed to add, we have to delete it here.
|
|
// delete pobScope ;
|
|
//
|
|
return err ;
|
|
}
|
|
|
|
//
|
|
// Add a new Scope to the Scopes list. First, iterate the scopes
|
|
// list to check for duplicates. Then add the scope.
|
|
//
|
|
LONG
|
|
CDhcpApp :: AddScope (
|
|
CDhcpScope * pobScope,
|
|
CObOwnedList& oblScopes
|
|
)
|
|
{
|
|
LONG err = 0 ;
|
|
CObListIter obli( oblScopes ) ;
|
|
CDhcpScope * pobScopeKnown ;
|
|
|
|
//
|
|
// First, check that this host isn't already known
|
|
//
|
|
for ( ; pobScopeKnown = (CDhcpScope *) obli.Next() ; )
|
|
{
|
|
if ( *pobScopeKnown == *pobScope )
|
|
{
|
|
break ;
|
|
}
|
|
}
|
|
|
|
if ( pobScopeKnown )
|
|
{
|
|
return IDS_ERR_SCOPE_ALREADY_KNOWN ;
|
|
}
|
|
|
|
//
|
|
// Add the new Scope to the list.
|
|
//
|
|
CATCH_MEM_EXCEPTION
|
|
{
|
|
oblScopes.AddTail( pobScope ) ;
|
|
DHCP_IP_ADDRESS dhipa = pobScope->QueryId() ;
|
|
|
|
TRACEEOLID( "Scope added: " << pobScope->QueryScopeId() ) ;
|
|
}
|
|
END_MEM_EXCEPTION(err)
|
|
|
|
return err ;
|
|
}
|
|
|
|
//
|
|
// Remove a Scope from the Scopes list.
|
|
//
|
|
LONG
|
|
CDhcpApp :: RemoveScope (
|
|
CDhcpScope * pobScope,
|
|
CObOwnedList& oblScopes
|
|
)
|
|
{
|
|
LONG err = 0 ;
|
|
CObListIter obli( oblScopes ) ;
|
|
CDhcpScope * pobScopeNext ;
|
|
POSITION pos;
|
|
|
|
ASSERT(pobScope != NULL);
|
|
|
|
//
|
|
// First, assure that this host is known
|
|
//
|
|
for ( pos = obli.QueryPosition() ;
|
|
pobScopeNext = (CDhcpScope *) obli.Next() ;
|
|
pos = obli.QueryPosition() )
|
|
{
|
|
if ( *pobScopeNext == *pobScope )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( pobScopeNext == NULL )
|
|
{
|
|
return ERROR_FILE_NOT_FOUND ;
|
|
}
|
|
oblScopes.RemoveAt( pos ) ;
|
|
|
|
return err ;
|
|
}
|
|
|
|
//
|
|
// Find a connected host based upon its IP address
|
|
//
|
|
CHostName *
|
|
CDhcpApp :: FindHost (
|
|
DHCP_IP_ADDRESS dhipa,
|
|
POSITION * pPos )
|
|
{
|
|
CObListIter obliHosts( m_oblHosts ) ;
|
|
CHostName * pobHost ;
|
|
|
|
for ( ; pobHost = (CHostName *) obliHosts.Next () ; )
|
|
{
|
|
//
|
|
// Store the position if they want it
|
|
//
|
|
if ( pPos )
|
|
{
|
|
*pPos = obliHosts.QueryPosition() ;
|
|
}
|
|
|
|
//
|
|
// If this is the target, break
|
|
//
|
|
if ( pobHost->QueryIpAddress() == dhipa )
|
|
{
|
|
break ;
|
|
}
|
|
}
|
|
|
|
return pobHost ;
|
|
}
|
|
|
|
//
|
|
// Use FormatMessage() to get a system error message
|
|
//
|
|
LONG
|
|
CDhcpApp :: GetSystemMessage (
|
|
UINT nId,
|
|
char * chBuffer,
|
|
int cbBuffSize
|
|
)
|
|
{
|
|
char * pszText = NULL ;
|
|
HINSTANCE hdll = NULL ;
|
|
|
|
DWORD flags = FORMAT_MESSAGE_IGNORE_INSERTS
|
|
| FORMAT_MESSAGE_MAX_WIDTH_MASK;
|
|
|
|
//
|
|
// Interpret the error. Need to special case
|
|
// the lmerr & ntstatus ranges, as well as
|
|
// dhcp server error messages.
|
|
//
|
|
|
|
if( nId >= NERR_BASE && nId <= MAX_NERR )
|
|
{
|
|
hdll = LoadLibrary( "netmsg.dll" );
|
|
}
|
|
else if ( nId >= ERROR_DHCP_REGISTRY_INIT_FAILED
|
|
&& nId <= ERROR_DHCP_REGISTRY_INIT_FAILED + 2000
|
|
)
|
|
{
|
|
hdll = LoadLibrary( "dhcpssvc.dll" );
|
|
}
|
|
else if( nId >= 0x40000000L )
|
|
{
|
|
hdll = LoadLibrary( "ntdll.dll" );
|
|
}
|
|
|
|
if( hdll == NULL )
|
|
{
|
|
flags |= FORMAT_MESSAGE_FROM_SYSTEM;
|
|
}
|
|
else
|
|
{
|
|
flags |= FORMAT_MESSAGE_FROM_HMODULE;
|
|
}
|
|
|
|
//
|
|
// Let FormatMessage do the dirty work.
|
|
//
|
|
DWORD dwResult = ::FormatMessage( flags,
|
|
(LPVOID) hdll,
|
|
nId,
|
|
0,
|
|
chBuffer,
|
|
cbBuffSize,
|
|
NULL ) ;
|
|
|
|
if( hdll != NULL )
|
|
{
|
|
LONG err = GetLastError();
|
|
FreeLibrary( hdll );
|
|
if ( dwResult == 0 )
|
|
{
|
|
::SetLastError( err );
|
|
}
|
|
}
|
|
|
|
return dwResult ? 0 : ::GetLastError() ;
|
|
}
|
|
|
|
//
|
|
// Return a pointer to the a cached version of the host's default types list
|
|
// New entry is created and cached if no such list exists yet.
|
|
// Cache is refreshed if entry exists but is out of date.
|
|
//
|
|
CObListOfTypesOnHost *
|
|
CDhcpApp :: QueryHostTypeList (
|
|
const CDhcpScope & cScope
|
|
)
|
|
{
|
|
CObListIter obli( m_oblTypeList ) ;
|
|
CObListOfTypesOnHost * poblTypes ;
|
|
DWORD dwStale = 1000L * 5 * 60 ; // Five minutes
|
|
APIERR err = 0 ;
|
|
|
|
//
|
|
// Try to find an existing list.
|
|
//
|
|
while ( poblTypes = (CObListOfTypesOnHost *) obli.Next() )
|
|
{
|
|
if ( poblTypes->QueryHostName() == (CHostName &) cScope.QueryScopeId() )
|
|
{
|
|
break ;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we found one, check that it's not expired.
|
|
//
|
|
if ( poblTypes )
|
|
{
|
|
TRACEEOLID( "QueryHostTypeList: found cached entry for " << cScope.QueryScopeId() ) ;
|
|
if ( poblTypes->QueryAge() > dwStale )
|
|
{
|
|
TRACEEOLID( "QueryHostTypeList: cached entry was stale!" ) ;
|
|
err = poblTypes->UpdateList( cScope ) ;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If there isn't one, create it.
|
|
// EXCEPTION CAN BE THROWN HERE.
|
|
//
|
|
if ( poblTypes == NULL )
|
|
{
|
|
TRACEEOLID( "QueryHostTypeList: create new cache entry for " << cScope.QueryScopeId() ) ;
|
|
|
|
poblTypes = new CObListOfTypesOnHost( cScope ) ;
|
|
m_oblTypeList.AddTail( poblTypes, TRUE ) ;
|
|
}
|
|
|
|
//
|
|
// Return the result.
|
|
//
|
|
return poblTypes ;
|
|
}
|
|
|
|
//
|
|
// Remove a host types list from the cached queue.
|
|
//
|
|
BOOL
|
|
CDhcpApp :: RemoveHostTypeList (
|
|
const CHostName & cHostName
|
|
)
|
|
{
|
|
CObListIter obli( m_oblTypeList ) ;
|
|
CObListOfTypesOnHost * poblTypes ;
|
|
|
|
DWORD dwStale = 1000L * 5 * 60 ; // Five minutes
|
|
|
|
//
|
|
// Try to find an existing list.
|
|
//
|
|
while ( poblTypes = (CObListOfTypesOnHost *) obli.Next() )
|
|
{
|
|
if ( poblTypes->QueryHostName() == cHostName )
|
|
{
|
|
break ;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we found one, delete it.
|
|
//
|
|
if ( poblTypes )
|
|
{
|
|
TRACEEOLID( "RemoveHostTypeList: remove cached entry for " << cHostName ) ;
|
|
m_oblTypeList.Remove( poblTypes ) ;
|
|
delete poblTypes ;
|
|
}
|
|
|
|
return poblTypes != NULL ;
|
|
}
|
|
|
|
BOOL
|
|
CDhcpApp :: LoadMessage (
|
|
UINT nIdPrompt,
|
|
CHAR * chMsg,
|
|
int nMsgSize
|
|
)
|
|
{
|
|
BOOL bOk;
|
|
|
|
//
|
|
// Substitute a friendly message for "RPC server not
|
|
// available" and "No more endpoints available from
|
|
// the endpoint mapper".
|
|
//
|
|
if (nIdPrompt == EPT_S_NOT_REGISTERED ||
|
|
nIdPrompt == RPC_S_SERVER_UNAVAILABLE)
|
|
{
|
|
nIdPrompt = IDS_ERR_DHCP_DOWN;
|
|
}
|
|
else if (nIdPrompt == RPC_S_PROCNUM_OUT_OF_RANGE)
|
|
{
|
|
nIdPrompt = IDS_ERR_RPC_NO_ENTRY;
|
|
}
|
|
|
|
//
|
|
// If it's a socket error or our error, the text is in our resource fork.
|
|
// Otherwise, use FormatMessage() and the appropriate DLL.
|
|
//
|
|
if ( (nIdPrompt >= IDS_ERR_BASE && nIdPrompt < IDS_MESG_MAX)
|
|
|| (nIdPrompt >= WSABASEERR && nIdPrompt < WSABASEERR + 2000)
|
|
)
|
|
{
|
|
//
|
|
// It's in our resource fork
|
|
//
|
|
bOk = ::LoadString( AfxGetInstanceHandle(), nIdPrompt, chMsg, nMsgSize ) != 0 ;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// It's in the system somewhere.
|
|
//
|
|
bOk = GetSystemMessage( nIdPrompt, chMsg, nMsgSize ) == 0 ;
|
|
}
|
|
|
|
//
|
|
// If the error message did not compute, replace it.
|
|
//
|
|
if ( ! bOk )
|
|
{
|
|
char chBuff [DHC_STRING_MAX] ;
|
|
static const char * pszReplacement = "System Error: %ld" ;
|
|
const char * pszMsg = pszReplacement ;
|
|
|
|
//
|
|
// Try to load the generic (translatable) error message text
|
|
//
|
|
if ( ::LoadString( AfxGetInstanceHandle(), IDS_ERR_MESSAGE_GENERIC,
|
|
chBuff, sizeof chBuff ) != 0 )
|
|
{
|
|
pszMsg = chBuff ;
|
|
}
|
|
::wsprintf( chMsg, pszMsg, nIdPrompt ) ;
|
|
}
|
|
|
|
return bOk;
|
|
}
|
|
|
|
int
|
|
CDhcpApp :: MessageBox (
|
|
UINT nIdPrompt,
|
|
UINT nType,
|
|
const char * pszSuffixString,
|
|
UINT nHelpContext )
|
|
{
|
|
char chMesg [4000] ;
|
|
BOOL bOk ;
|
|
|
|
bOk = LoadMessage(nIdPrompt, chMesg, sizeof(chMesg));
|
|
if ( pszSuffixString )
|
|
{
|
|
::strcat( chMesg, " " ) ;
|
|
::strcat( chMesg, pszSuffixString ) ;
|
|
}
|
|
|
|
return ::AfxMessageBox( chMesg, nType, nHelpContext ) ;
|
|
}
|
|
|
|
//
|
|
// Safely convert an IP address to a string. If it's invalid, use the
|
|
// "I'm a bogus IP address" string from the resource fork.
|
|
//
|
|
BOOL CDhcpApp :: ConvertIpAddress ( DHCP_IP_ADDRESS dhipa, CString & str ) const
|
|
{
|
|
char chIp [DHC_STRING_MAX] ;
|
|
|
|
|
|
::UtilCvtIpAddrToString( dhipa, chIp, sizeof chIp ) ;
|
|
str = chIp ;
|
|
return TRUE ;
|
|
}
|
|
|
|
//
|
|
// Connect to a new host
|
|
//
|
|
LONG
|
|
CDhcpApp :: CreateHostObject (
|
|
const char * pszServer,
|
|
CHostName * * ppobHost )
|
|
{
|
|
const CObOwnedList & oblHosts = QueryHostsList() ;
|
|
LONG err = 0 ;
|
|
POSITION pos ;
|
|
CHostName * pobHost ;
|
|
DHCP_IP_ADDRESS dhipa ;
|
|
|
|
do
|
|
{
|
|
*ppobHost = NULL ;
|
|
|
|
if ( ::strlen( pszServer ) == 0 )
|
|
{
|
|
err = IDS_ERR_BAD_HOST_NAME ;
|
|
break ;
|
|
}
|
|
|
|
//
|
|
// See what type of name it is.
|
|
//
|
|
switch (CHostName::CategorizeName( pszServer ) )
|
|
{
|
|
case HNM_TYPE_IP:
|
|
dhipa = ::UtilCvtStringToIpAddr( pszServer ) ;
|
|
break ;
|
|
|
|
case HNM_TYPE_DNS:
|
|
err = ::UtilGetHostAddress( pszServer, & dhipa ) ;
|
|
break ;
|
|
|
|
//
|
|
// Treat NetBIOS names as invalid for now.
|
|
//
|
|
case HNM_TYPE_NB:
|
|
err = IDS_ERR_CANTUSENETBIOS;
|
|
break;
|
|
|
|
default:
|
|
err = IDS_ERR_BAD_HOST_NAME ;
|
|
break ;
|
|
}
|
|
|
|
if ( err )
|
|
{
|
|
break ;
|
|
}
|
|
|
|
//
|
|
// Check to see if we're already connected to this server/host
|
|
//
|
|
for ( pos = oblHosts.GetHeadPosition() ; pos ; )
|
|
{
|
|
pobHost = (CHostName *) oblHosts.GetNext( pos ) ;
|
|
if ( pobHost->QueryIpAddress() == dhipa )
|
|
{
|
|
//
|
|
// Duplicate name
|
|
//
|
|
err = IDS_ERR_HOST_ALREADY_CONNECTED ;
|
|
break ;
|
|
}
|
|
}
|
|
|
|
if ( err )
|
|
{
|
|
break ;
|
|
}
|
|
|
|
CATCH_MEM_EXCEPTION
|
|
{
|
|
//
|
|
// Create the return object: a new CHostName.
|
|
//
|
|
*ppobHost = new CHostName( dhipa ) ;
|
|
}
|
|
END_MEM_EXCEPTION(err)
|
|
|
|
if ( err )
|
|
{
|
|
break ;
|
|
}
|
|
}
|
|
while ( FALSE ) ;
|
|
|
|
return err ;
|
|
}
|
|
|
|
//
|
|
// Store the list of hosts into the Registry, including the persistent
|
|
// connections that the user wanted to hang around.
|
|
//
|
|
LONG
|
|
CDhcpApp :: StoreHostsList ()
|
|
{
|
|
CRegKey rk( DHCP_REG_USER_KEY_NAME, HKEY_CURRENT_USER ) ;
|
|
CStringList strList ;
|
|
CHostName * pobHost ;
|
|
|
|
LONG err ;
|
|
|
|
do
|
|
{
|
|
if ( err = rk.QueryError() )
|
|
{
|
|
break ;
|
|
}
|
|
|
|
CObListIter obli( QueryHostsList() ) ;
|
|
|
|
TRY
|
|
{
|
|
while ( pobHost = (CHostName *) obli.Next() )
|
|
{
|
|
strList.AddTail( pobHost->QueryString() ) ;
|
|
}
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
err = ERROR_NOT_ENOUGH_MEMORY ;
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
if ( err )
|
|
{
|
|
break ;
|
|
}
|
|
|
|
err = rk.SetValue( DHCP_REG_VALUE_HOSTS, strList ) ;
|
|
}
|
|
while ( FALSE ) ;
|
|
|
|
return err ;
|
|
}
|
|
|
|
//
|
|
// If the dhcp services is installed on the local machine,
|
|
// add the loopback address to the cache
|
|
//
|
|
void
|
|
CDhcpApp::AddLocalHost()
|
|
{
|
|
//
|
|
// Determine if we're running the DHCP server service locally -- if so,
|
|
// add 127.0.0.1 (the loopback address) to the cache.
|
|
//
|
|
SC_HANDLE hService;
|
|
SC_HANDLE hScManager;
|
|
hScManager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
|
|
if (hScManager != NULL)
|
|
{
|
|
hService = OpenService(hScManager, "DHCPSERVER", SERVICE_INTERROGATE);
|
|
if (hService != NULL)
|
|
{
|
|
//
|
|
// Service exists (running or not) -- Add loopback address
|
|
//
|
|
CHostName * pobHost = NULL ;
|
|
if (!CreateHostObject("127.0.0.1", &pobHost))
|
|
{
|
|
ASSERT( pobHost != NULL );
|
|
AddHost( pobHost );
|
|
}
|
|
else if (pobHost != NULL)
|
|
{
|
|
delete pobHost;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Load the list of hosts from the Registry
|
|
//
|
|
LONG
|
|
CDhcpApp :: LoadHostsList ()
|
|
{
|
|
CRegKey rk( DHCP_REG_USER_KEY_NAME, HKEY_CURRENT_USER ) ;
|
|
CStringList strList ;
|
|
CString * pstr ;
|
|
POSITION pos ;
|
|
LONG err;
|
|
|
|
do
|
|
{
|
|
if ( err = rk.QueryError() )
|
|
{
|
|
break ;
|
|
}
|
|
|
|
if ( err = rk.QueryValue( DHCP_REG_VALUE_HOSTS, strList ) )
|
|
{
|
|
break ;
|
|
}
|
|
|
|
for ( pos = strList.GetHeadPosition() ;
|
|
pos != NULL && (pstr = & strList.GetNext( pos )) ; /**/ )
|
|
{
|
|
CHostName * pobHost = NULL ;
|
|
if ((err = CreateHostObject( *pstr, &pobHost)) == ERROR_SUCCESS)
|
|
{
|
|
ASSERT( pobHost != NULL );
|
|
err = AddHost( pobHost );
|
|
}
|
|
if (err)
|
|
{
|
|
if (pobHost != NULL)
|
|
{
|
|
delete pobHost;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
while ( FALSE ) ;
|
|
|
|
AddLocalHost();
|
|
|
|
//
|
|
// Clear the "dirty" flag so we don't needlessly rewrite the data to
|
|
// the Registry on shutdown.
|
|
//
|
|
m_oblHosts.SetDirty( FALSE ) ;
|
|
|
|
//
|
|
// This isn't really an error -- it just means that we didn't
|
|
// find the key name in the list
|
|
//
|
|
if (err == ERROR_FILE_NOT_FOUND)
|
|
{
|
|
TRACEEOLID("Didn't find old addresses registry key -- starting from scratch");
|
|
err = ERROR_SUCCESS;
|
|
}
|
|
|
|
if ( err )
|
|
{
|
|
theApp.MessageBox( err ) ;
|
|
}
|
|
|
|
return err ;
|
|
}
|
|
|
|
//
|
|
// Sort the list of scopes
|
|
//
|
|
LONG CDhcpApp :: SortScopesList (
|
|
CObOwnedList& oblScopes
|
|
)
|
|
{
|
|
return oblScopes.Sort( (CObjectPlus::PCOBJPLUS_ORDER_FUNC) & CDhcpScope::OrderById ) ;
|
|
}
|
|
|
|
//
|
|
// Sort the list of hosts.
|
|
//
|
|
LONG CDhcpApp :: SortHostsList ()
|
|
{
|
|
return m_oblHosts.Sort( (CObjectPlus::PCOBJPLUS_ORDER_FUNC) & CHostName::OrderByName ) ;
|
|
}
|
|
|
|
//
|
|
// Return TRUE if this is an option we do not want
|
|
// to show up in the listboxes anywhere
|
|
//
|
|
BOOL
|
|
CDhcpApp :: FilterOption(
|
|
DHCP_OPTION_ID id
|
|
)
|
|
{
|
|
//
|
|
// Filter out subnet mask, lease duration,
|
|
// T1, and T2
|
|
//
|
|
return ( id == 1
|
|
|| id == 51
|
|
|| id == 58
|
|
|| id == 59
|
|
);
|
|
}
|
|
|
|
//
|
|
// DEBUGGING routines
|
|
//
|
|
static LONG cAllocRequestToDeny = -1 ;
|
|
static LONG cAllocRequestToBreakOn = -1 ;
|
|
|
|
#if defined(_DEBUG)
|
|
|
|
static BOOL AFXAPI
|
|
DhcpAllocHook (
|
|
size_t cbRequired,
|
|
BOOL bIsCObject,
|
|
LONG cRequestNumber )
|
|
{
|
|
BOOL bPokeWithDebugger = FALSE ;
|
|
|
|
if ( cRequestNumber == cAllocRequestToDeny || bPokeWithDebugger )
|
|
{
|
|
return FALSE ;
|
|
}
|
|
|
|
if ( cRequestNumber == cAllocRequestToBreakOn )
|
|
{
|
|
::DebugBreak() ;
|
|
}
|
|
|
|
return TRUE ;
|
|
}
|
|
|
|
#endif
|
|
|
|
//
|
|
// Prepare any debugging stuff.
|
|
//
|
|
void
|
|
CDhcpApp :: DebugInstance ()
|
|
{
|
|
#if defined(_DEBUG)
|
|
::AfxSetAllocHook( & DhcpAllocHook ) ;
|
|
#endif
|
|
}
|
|
|
|
|
|
void
|
|
CDhcpApp::OnAppExit()
|
|
{
|
|
CWinApp::OnAppExit();
|
|
}
|
|
|
|
void
|
|
CDhcpApp::OnUpdateAppExit(CCmdUI* pCmdUI)
|
|
{
|
|
}
|