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.
 
 
 
 
 
 

2247 lines
50 KiB

/**********************************************************************/
/** Microsoft Windows/NT **/
/** Copyright(c) Microsoft Corp., 1995 **/
/**********************************************************************/
/*
winsadmn.cpp
FILE HISTORY:
*/
#include "stdafx.h"
#include "winsadmn.h"
#include "mainfrm.h"
#include "winsadoc.h"
#include "statisti.h"
#include "selectwi.h"
#include "addstati.h"
#include "staticma.h"
#include <winsock.h> // For WSAStartup()
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
#define new DEBUG_NEW
//
// Typedef for the ShellAbout function
//
typedef void (WINAPI *LPFNSHELLABOUT)(HWND, LPTSTR, LPTSTR, HICON);
//
// CWinsadmnApp
//
BEGIN_MESSAGE_MAP(CWinsadmnApp, CWinApp)
//{{AFX_MSG_MAP(CWinsadmnApp)
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
//}}AFX_MSG_MAP
// Standard file based document commands
ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
// Standard print setup command
ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
// 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()
//
// Name of NetBIOS named pipe for WINS servers.
//
const LPCSTR CWinsadmnApp::lpstrPipeName = "\\pipe\\WinsPipe";
//
// CWinsadmnApp construction
//
CWinsadmnApp::CWinsadmnApp()
#ifndef WIN32S
: m_hmutStatistics(NULL),
m_hmutScreenRefresh(NULL)
#endif // WIN32S
{
#ifdef _TIGHTMEMCHECKING
afxMemDF |= checkAlwaysMemDF;
#endif //_TIGHTMEMCHECKING
}
//
// CWinsadmnApp initialization
//
BOOL
CWinsadmnApp::InitApplication()
{
//
// Call base class. Default version does nothing.
//
CWinApp::InitApplication();
WNDCLASS wndcls;
::memset(&wndcls, 0, sizeof(WNDCLASS)); // start with NULL defaults
//
// Get class information for default window class.
//
::GetClassInfo(AfxGetInstanceHandle(),"AfxFrameOrView",&wndcls);
//
// Substitute unique class name for new class
//
wndcls.lpszClassName = WINSADMIN_CLASS_NAME;
//
// Register new class and return the result code
//
return ::RegisterClass(&wndcls);
}
BOOL
CWinsadmnApp::FirstInstance()
{
CWnd *PrevCWnd, *ChildCWnd;
//
// Determine if another window with our class name exists...
//
if ((PrevCWnd = CWnd::FindWindow(WINSADMIN_CLASS_NAME,NULL)) == NULL)
{
//
// First instance, proceed as normal
//
return TRUE;
}
//
// Previous instance exists -- reactivate it.
//
ChildCWnd=PrevCWnd->GetLastActivePopup(); // if so, does it have any popups?
#ifdef _WIN32
// BringWindowToTop() doesn't do it in WIN32 -- MFC bug?
::SetForegroundWindow(PrevCWnd->m_hWnd);
#else
PrevCWnd->BringWindowToTop(); // Bring the main window to the top
#endif // _WIN32
if (PrevCWnd->IsIconic())
{
//
// If iconic, restore the main window
//
PrevCWnd->ShowWindow(SW_RESTORE);
}
if (PrevCWnd != ChildCWnd)
{
//
// Restore popups
//
#ifdef _WIN32
::SetForegroundWindow(ChildCWnd->m_hWnd);
#else
ChildCWnd->BringWindowToTop();
#endif // _WIN32
}
return FALSE;
}
BOOL
CWinsadmnApp::InitInstance()
{
//
// If this isn't the first instance, return FALSE
// immediately. FirstInstance() will have already
// activated the previous instance.
//
if (!FirstInstance())
{
return FALSE;
}
//
// Initialize the CWndIpAddress control window class IPADDRESS
//
CWndIpAddress::CreateWindowClass( m_hInstance ) ;
#ifdef _USE_3D
Enable3dControls(); // Use CTRL3D
#endif // _USE_3D
#ifdef GRAYDLG
SetDialogBkColor(); // set dialog background color to gray
#endif // GRAYDLG
//
// Not connected to anyone at startup.
//
m_hBinding = INVALID_HANDLE_VALUE;
//
// load preferences and cache from the registry
//
LoadStdProfileSettings();
APIERR err;
BeginWaitCursor();
if ((err = m_wpPreferences.Load()) ||
(err = m_wcWinssCache.Load(m_wpPreferences.IsValidateCache(),
theApp.m_wpPreferences.m_nAddressDisplay == CPreferences::ADD_IP_ONLY ||
theApp.m_wpPreferences.m_nAddressDisplay == CPreferences::ADD_IP_NB))
)
{
theApp.MessageBox(err);
}
EndWaitCursor();
WORD wVersionRequested = MAKEWORD(1, 1);
WSADATA wsaData;
err = WSAStartup(wVersionRequested, &wsaData);
if (err)
{
//Tell the user that we couldn't find a useable winsock.dll
TRACEEOLID("WSAStartup returned err=" << err );
return FALSE;
}
//
// 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(CWinsadmnDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CStatistics)));
//
// Set up initial screen
//
OnFileNew();
if (!m_strEllipses.LoadString(IDS_ELLIPSES))
{
m_strEllipses = _T("..."); // Just in case
}
//
// Necessary for explicit import
//
BOOL fIpInit = IPAddrInit(NULL);
TRACEEOLID("IPAddrInit returned " << fIpInit );
return TRUE;
}
int
CWinsadmnApp::ExitInstance()
{
ASSERT(!IsConnected());
BeginWaitCursor();
APIERR err;
if ((err = m_wpPreferences.Store()) ||
(err = m_wcWinssCache.Store()))
{
theApp.MessageBox(err);
}
EndWaitCursor();
#ifndef WIN32S
if (m_hmutStatistics == NULL)
{
::ReleaseMutex(m_hmutStatistics);
::CloseHandle(m_hmutStatistics);
}
#endif // WIN32S
return 0;
}
//
// Clean up the main window before putting on the hourglass and
// freezing the display.
//
void
CWinsadmnApp::DoWaitCursor(
int nCode
)
{
if ( m_pMainWnd != NULL )
{
m_pMainWnd->UpdateWindow();
}
CWinApp::DoWaitCursor(nCode);
}
/***
*
* CWinsadmnApp::GetSystemMessage
*
* Purpose:
*
* Given a message ID, determine where the message resides,
* and load it into the buffer.
*
* Arguments:
*
* UINT nId Message ID number
* char * chBuffer Character buffer to load into.
* int cbBuffSize Size of buffer in characters
*
* Returns:
*
* API error return code, or ERROR_SUCCESS
*
*/
APIERR
CWinsadmnApp::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.
//
if( nId >= NERR_BASE && nId <= MAX_NERR )
{
hdll = ::LoadLibrary( "netmsg.dll" );
}
else if( nId >= 0x40000000L )
{
hdll = ::LoadLibrary( "ntdll.dll" );
}
if( hdll == NULL )
{
flags |= FORMAT_MESSAGE_FROM_SYSTEM;
}
else
{
flags |= FORMAT_MESSAGE_FROM_HMODULE;
}
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 ? ERROR_SUCCESS : ::GetLastError();
}
/***
*
* CWinsadmnApp::MessageBox
*
* Purpose:
*
* Replacement for AfxMessageBox(). This function will call up the
* appropriate message from wherever before displaying it
*
* Arguments:
*
* UINT nIdPrompt Message ID
* UINT nType AfxMessageBox type (YESNO, OKCANCEL, etc)
* UINT nHelpContext Help context ID for AfxMessageBox();
*
* Notes:
*
* If an error occurs, a standard message (hard-coded in english) will
* be shown that gives the error number.
*
*/
int
CWinsadmnApp::MessageBox (
UINT nIdPrompt,
UINT nType,
UINT nHelpContext
)
{
//
// 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_WINS_DOWN;
}
//
// If it's our error, the text is in our resource segment.
// Otherwise, use FormatMessage() and the appropriate DLL>
//
if ((nIdPrompt >= IDS_ERR_BASE) && (nIdPrompt <= IDS_MSG_LAST))
{
return ::AfxMessageBox(nIdPrompt, nType, nHelpContext);
}
char szMesg [1024] ;
int nResult;
if ((nResult = GetSystemMessage(nIdPrompt, szMesg, sizeof(szMesg)))
== ERROR_SUCCESS)
{
return ::AfxMessageBox(szMesg, nType, nHelpContext);
}
TRACEEOLID("Message number " << nIdPrompt << " not found");
ASSERT(0 && "Error Message ID not handled");
//
// Do something for the retail version
//
::wsprintf ( szMesg, _T("Error: %lu"), nIdPrompt);
::AfxMessageBox(szMesg, nType, nHelpContext);
return nResult;
}
//
// Get the control rectangle coordinates relative
// to its parent. This can then be used in
// SetWindowPos()
//
void
CWinsadmnApp::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);
}
/***
*
* CWinsadmnApp::CleanString(CString& str)
*
* Purpose:
*
* Strip leading and trailing spaces from the string.
*
* Returns:
*
* A reference to the string
*
*/
CString&
CWinsadmnApp::CleanString(
CString& str
)
{
if (str.IsEmpty())
{
return str ;
}
int n = 0;
while ((n < str.GetLength()) && (str[n] == ' '))
{
++n;
}
if (n)
{
str = str.Mid(n);
}
n = str.GetLength();
while (n && (str[--n] == ' '))
{
str.ReleaseBuffer(n);
}
return str;
}
//
// Convert the netbios name to a displayable format, with
// beginning slashes, the unprintable characters converted
// to '-' characters, and the 16th character displayed in brackets.
// Convert the string to ANSI/Unicode before displaying it.
//
//
CString&
CWinsadmnApp::CleanNetBIOSName(
LPCSTR lpSrc,
BOOL fExpandChars,
BOOL fTruncate,
BOOL fLanmanCompatible,
BOOL fOemName,
BOOL fWackwack,
int nLength
)
{
static CString strTarget;
static TCHAR szWacks[] = _T("\\\\");
BYTE ch16 = 0;
int nLen, nDisplayLen;
int nMaxDisplayLen = fLanmanCompatible ? 15 : 16;
if (!fWackwack && fLanmanCompatible)
{
//
// Don't want backslahes, but if they do exist,
// remove them.
//
if (!::strncmp(lpSrc, szWacks, ::strlen(szWacks)))
{
lpSrc += ::strlen(szWacks);
if (nLength)
{
nLength -= 2;
}
}
}
if ((nDisplayLen = nLen = nLength ? nLength : ::lstrlen(lpSrc)) > 15)
{
ch16 = (BYTE)lpSrc[15];
nDisplayLen = fTruncate ? nMaxDisplayLen : nLen;
}
char * pTarget = strTarget.GetBuffer(256);
if (fWackwack)
{
::strcpy(pTarget, szWacks);
pTarget += ::strlen(szWacks);
}
if (fOemName)
{
::OemToCharBuff(lpSrc, pTarget, nLen);
}
else
{
::memcpy(pTarget, lpSrc, nLen);
}
int n = 0;
while (n < nDisplayLen)
{
if (fExpandChars)
{
if (!::IsCharAlphaNumeric(*pTarget) && !isprint(*pTarget))
{
*pTarget = BADNAME_CHAR;
}
}
++n;
++pTarget;
}
if (nLen == 16)
{
if (fLanmanCompatible)
{
if (!fTruncate && nDisplayLen == nLen)
{
//
// Back up over the 16th character
//
--pTarget;
}
//
// Back up over the spaces. Then, attach the
// 16th character string.
//
while (*(--pTarget) == ' ') /**/ ;
pTarget += ::wsprintfA (++pTarget, "[%02Xh]", ch16);
++pTarget;
}
}
else if (nLen > 16 && fTruncate)
{
pTarget += ::wsprintfA(pTarget, (LPCSTR)m_strEllipses);
++pTarget;
}
*pTarget = '\0';
strTarget.ReleaseBuffer();
return strTarget;
}
/***
*
* CWinsadmnApp::IsValidNetBIOSName
*
* Purpose:
*
* Determine if the given netbios is valid, and pre-pend
* a double backslash if not already present (and the address
* is otherwise valid).
*
* Arguments:
*
* CString& strAddress Name to verify
*
* Returns:
*
* TRUE for a valid netbios name, FALSE otherwise
*
*/
BOOL
CWinsadmnApp::IsValidNetBIOSName(
CString & strAddress,
BOOL fLanmanCompatible,
BOOL fWackwack // expand slashes if not present
)
{
TCHAR szWacks[] = _T("\\\\");
if (strAddress.IsEmpty())
{
return FALSE;
}
if (strAddress[0] == _T('\\'))
{
if (strAddress.GetLength() < 3)
{
return FALSE;
}
if (strAddress[1] != _T('\\'))
{
//
// One slash only? Not valid
//
return FALSE;
}
if (!fWackwack && fLanmanCompatible)
{
//
// Don't want backslashes, but since they do exist,
// remove them.
//
if (!::strncmp((LPCSTR)strAddress, szWacks, ::strlen(szWacks)))
{
strAddress = CString((LPCSTR)strAddress + ::strlen(szWacks));
}
}
}
else
{
if (fWackwack)
{
//
// Add the backslashes
//
strAddress = szWacks + strAddress;
}
}
int nMaxAllowedLength = fLanmanCompatible
? LM_NAME_MAX_LENGTH
: NB_NAME_MAX_LENGTH;
if (fLanmanCompatible)
{
strAddress.MakeUpper();
}
return strAddress.GetLength() <= nMaxAllowedLength + 2;
}
/***
* CWinsadmnApp::IsValidDomain
*
* Purpose:
*
* Determine if the given domain name address is valid, and clean
* it up, if necessary
*
* Arguments:
*
* CString& strAddress Address to verify
*
* Returns:
*
* TRUE for a valid FQDN address, FALSE otherwise
*
*/
BOOL
CWinsadmnApp::IsValidDomain(
CString & strDomain)
{
int nLen;
if ((nLen = strDomain.GetLength()) != 0)
{
if (nLen < DOMAINNAME_LENGTH) // 255
{
int i;
int istr = 0;
TCHAR ch;
BOOL fLet_Dig = FALSE;
BOOL fDot = FALSE;
int cHostname = 0;
for (i = 0; i < nLen; i++)
{
// check each character
ch = strDomain[i];
BOOL fAlNum = iswalpha(ch) || iswdigit(ch);
if (((i == 0) && !fAlNum) ||
// first letter must be a digit or a letter
(fDot && !fAlNum) ||
// first letter after dot must be a digit or a letter
((i == (nLen - 1)) && !fAlNum) ||
// last letter must be a letter or a digit
(!fAlNum && ( ch != _T('-') && ( ch != _T('.') && ( ch != _T('_'))))) ||
// must be letter, digit, - or "."
(( ch == _T('.')) && ( !fLet_Dig )))
// must be letter or digit before '.'
{
return FALSE;
}
fLet_Dig = fAlNum;
fDot = (ch == _T('.'));
cHostname++;
if ( cHostname > HOSTNAME_LENGTH )
{
return FALSE;
}
if ( fDot )
{
cHostname = 0;
}
}
}
}
return TRUE;
}
/***
* CWinsadmnApp::IsValidIpAddress
*
* Purpose:
*
* Determine if the given IP address is valid, and clean
* it up, if necessary
*
* Arguments:
*
* CString& strAddress Address to verify
*
* Returns:
*
* TRUE for a valid IP address, FALSE otherwise
*
*/
BOOL
CWinsadmnApp::IsValidIpAddress(
CString & strAddress
)
{
if (strAddress.IsEmpty())
{
return FALSE;
}
CIpAddress ia(strAddress);
BOOL fValid = ia.IsValid();
if (fValid)
{
//
// Fill out the IP address string for clarity
//
strAddress = ia;
return TRUE;
}
return FALSE;
}
/***
*
* CWinsadmnApp::IsValidAddress
*
* Purpose:
*
* Determine if the given address is a valid NetBIOS or
* TCP/IP address, judging by the name only. Note that
* validation may clean up the given string
*
* Arguments:
*
* CString& strAddress The address in question
* BOOL * fIpAddress Returns TRUE if the address is an IP
* address, FALSE is it's a NetBIOS name.
*
* Returns:
*
* TRUE for a valid name, FALSE otherwise.
*
* Notes:
*
* NetBIOS names not beginning with "\\" will have those characters
* pre-pended, and otherwise valid IP Addresses are filled out to
* 4 octets.
*
* Leading and trailing spaces are removed from the string.
*
*/
BOOL
CWinsadmnApp::IsValidAddress(
CString& strAddress,
BOOL * fIpAddress,
BOOL fLanmanCompatible,
BOOL fWackwack // expand netbios slashes
)
{
int i;
//
// Remove leading and trailing spaces
//
CleanString(strAddress);
if (strAddress.IsEmpty()) {
*fIpAddress = FALSE;
return FALSE;
}
if (strAddress[0] == _T('\\')) {
*fIpAddress = FALSE;
return IsValidNetBIOSName(strAddress, fLanmanCompatible, fWackwack);
}
if (IsValidIpAddress(strAddress)) {
*fIpAddress = TRUE;
return TRUE;
} else {
*fIpAddress = FALSE;
}
if (IsValidDomain (strAddress)) {
return TRUE;
}
// last chance, maybe its a NetBIOS name w/o wackwack
return IsValidNetBIOSName(strAddress, fLanmanCompatible, fWackwack);
/*-----------------------------------------------------------
old code, being replaced.
for (i=0; i < strAddress.GetLength(); ++i)
{
//
// If a dot is encountered, we immediately assume
// it's an IP address
//
if (strAddress[i] == _T('.'))
{
*fIpAddress = TRUE;
return IsValidIpAddress(strAddress);
}
//
// A non-digit (and non-period) immediately
// makes us realise we have a NB name.
//
if (!isdigit(strAddress[i]))
{
*fIpAddress = FALSE;
return IsValidNetBIOSName(strAddress, fLanmanCompatible, fWackwack);
}
}
//
// Having come this far without encountering a period,
// we know this is a netbios name
//
*fIpAddress = FALSE;
return IsValidNetBIOSName(strAddress, fLanmanCompatible, fWackwack);
---------------------------------------------------------------*/
}
/***
*
* CWinsadmnApp::ValidateNumberEditControl
*
* Purpose:
*
* Verify that the given edit control contains a valid number, otherwise
* balk and set focus to it.
*
* Arguments:
*
* CEdit& edit The edit control to check
* BOOL fEmptyOk If TRUE, allow blank entries
* LONG lMin Minimum value to allow
* LONG lMax Maximum value to allow
*
* Returns:
*
* TRUE or FALSE depending on whether validation succeeded or not.
*
* Notes:
*
* The contents of the edit control will be re-displayed after
* validation, since they may have been cleaned up.
*
*/
BOOL
CWinsadmnApp::ValidateNumberEditControl(
CEdit& edit,
BOOL fEmptyOk,
LONG lMin,
LONG lMax
)
{
CString str;
edit.GetWindowText(str);
//
// Kill Leading and Trailing Spaces.
//
CleanString(str);
//
// If empty is not ok, then it will fail later on.
//
if (str.IsEmpty() && fEmptyOk)
{
return TRUE;
}
CIntlNumber n(str);
if (!n.IsValid() || ((LONG)n < lMin) || ((LONG)n > lMax))
{
theApp.MessageBox(IDS_ERR_BAD_NUMBER);
edit.SetFocus();
edit.SetSel(0,-1);
return FALSE;
}
//
// Re-display the number, which may have been
// cleaned up in validation.
//
edit.SetWindowText((const CString)n);
edit.UpdateWindow();
return TRUE;
}
BOOL
CWinsadmnApp::ValidateTimeEditControl(
CEdit& edit,
BOOL fEmptyOk
)
{
CString str;
edit.GetWindowText(str);
//
// Kill Leading and Trailing Spaces.
//
CleanString(str);
//
// If empty is not ok, then it will fail later on.
//
if (str.IsEmpty() && fEmptyOk)
{
return TRUE;
}
CIntlTime tm(str, CIntlTime::TFRQ_TIME_ONLY, NULL);
if (!tm.IsValid())
{
theApp.MessageBox(IDS_ERR_TIME_INVALID);
edit.SetFocus();
edit.SetSel(0,-1);
return FALSE;
}
//
// Re-display the number, which may have been
// cleaned up in validation.
//
edit.SetWindowText(tm.IntlFormat(CIntlTime::TFRQ_TIME_ONLY));
edit.UpdateWindow();
return TRUE;
}
//
// Return the name of the server we're connected
// to. Return the IP address if connected over ip,
// and the netbios name if connected over netbios.
//
CString
CWinsadmnApp::GetConnectedServerName()
{
if (m_wbdBindData.fTcpIp)
{
return m_iaIpAddress;
}
return m_strNetBIOSName;
}
//
// Change the title on the given window. If the
// window pointer is NULL, use the main application
// window.
//
void
CWinsadmnApp::SetTitle(
CWnd * pWnd
)
{
CString strTitle;
TRY
{
if (pWnd == NULL)
{
//
// Setting the main title bar. Check to
// make sure that there is a main app screen
// visible.
//
ASSERT(theApp.m_pMainWnd != NULL);
pWnd = theApp.m_pMainWnd;
}
pWnd->GetWindowText(strTitle);
//
// Check for existence of current title. If present,
// remove it.
//
CString strDivider;
int nPos;
strDivider.LoadString(IDS_DIVIDER);
if ((nPos = strTitle.Find(strDivider)) != -1)
{
//
// Truncate to new length.
//
strTitle.ReleaseBuffer(nPos);
}
if (IsConnected())
{
strTitle += strDivider;
//
// Append the address of the currently open
// WINS server.
//
if (IsLocalConnection())
{
CString strLocal;
strLocal.LoadString(IDS_LOCAL);
strTitle += strLocal;
}
else
{
strTitle += GetConnectedServerName();
}
}
pWnd->SetWindowText(strTitle);
}
CATCH_ALL(e)
{
theApp.MessageBox(::GetLastError());
}
END_CATCH_ALL
}
void
CWinsadmnApp::SetStatusBarText(
UINT nId
)
{
ASSERT(m_pMainWnd != NULL);
CString str;
TRY
{
BOOL f = str.LoadString(nId) ;
ASSERT(f);
((CMainFrame *)m_pMainWnd)->GetStatusBarHandle().SetWindowText(str);
((CMainFrame *)m_pMainWnd)->GetStatusBarHandle().UpdateWindow();
}
CATCH_ALL(e)
{
theApp.MessageBox(::GetLastError());
}
END_CATCH_ALL
}
void
CWinsadmnApp::MessageBeep(
UINT nType
)
{
::MessageBeep(nType);
}
//
// Get a temporary file on a remote drive
//
CHAR *
CWinsadmnApp::RemoteTmp(
CHAR * szDir,
CHAR * szPrefix
)
{
static TCHAR sz[256];
int n = 0;
while(1)
{
::wsprintf (sz, _T("%s\\%s%d"), szDir, szPrefix, ++n);
if (GetFileAttributes(sz) == -1)
{
return GetLastError() == ERROR_FILE_NOT_FOUND ? sz : NULL;
}
}
}
void
CWinsadmnApp::DoImportStaticMappingsDlg(
CWnd * pParentWindow
)
{
ASSERT(IsServiceRunning());
CString strTitle;
if (!strTitle.LoadString(IDS_SELECT_STATIC_MAPPING_FILE))
{
theApp.MessageBox(::GetLastError());
return;
}
CFileDialog dlgFile(TRUE, NULL, NULL, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, " |*.||");
dlgFile.m_ofn.lpstrTitle = strTitle;
if (dlgFile.DoModal() == IDOK)
{
//
// If this is a local connection, we copy the file to
// temporary name (the source may be on a remote drive
// which is not accessible to the WINS service.
//
// If this is not a local connection, attempt to copy
// the file to a temp name on C$ of the WINS server
//
//
// Put up the informational dialog
//
CImportingDlg * pDlg = NULL;
pDlg = new CImportingDlg(pParentWindow);
APIERR err = 0;
SetStatusBarText(IDS_STATUS_IMPORT);
theApp.BeginWaitCursor();
CString strMappingFile(dlgFile.GetPathName());
do
{
if (IsLocalConnection())
{
CString strTmpFile(_tempnam(NULL, _T("WINS")));
//
// First copy file to a temporary name (since the file
// could be remote), and then import and delete this file
//
if (!CopyFile(strMappingFile, strTmpFile, TRUE))
{
err = ::GetLastError();
break;
}
//
// Now import the temporary file, and delete the file
// afterwards.
//
err = ImportStaticMappingsFile(strTmpFile, TRUE);
}
else
{
//
// Try copying to the remote machine C: drive
//
CHAR szDir[1024];
::wsprintf(szDir, "%s\\C$", (LPCSTR)GetConnectedNetBIOSName());
CHAR * pchTmp = RemoteTmp(szDir, "WINS");
if (pchTmp == NULL)
{
err = IDS_ERR_REMOTE_IMPORT;
break;
}
CString strTmpFile(pchTmp);
//
// First copy file to a temporary name (since the file
// could be remote), and then import and delete this file
//
if (!CopyFile(strMappingFile, strTmpFile, TRUE))
{
err = ::GetLastError();
break;
}
CHAR * pch = strTmpFile.GetBuffer(256);
//
// Now replace the remote path with a local path
// for the remote WINS server
//
while (*pch != '$')
{
++pch;
}
*pch = ':';
--pch;
CString strRemoteFile(pch);
strTmpFile.ReleaseBuffer();
//
// Now import the temporary file, and delete the file
// afterwards.
//
err = ImportStaticMappingsFile(strRemoteFile, TRUE);
}
}
while(FALSE);
theApp.EndWaitCursor();
SetStatusBarText();
if (pDlg != NULL)
{
pDlg->Dismiss();
}
if (err == ERROR_SUCCESS)
{
theApp.MessageBox(IDS_MSG_IMPORT, MB_ICONINFORMATION);
}
else
{
theApp.MessageBox(err);
}
GetFrameWnd()->GetStatistics();
}
}
int
CWinsadmnApp::DoAddStaticMappingsDlg()
{
ASSERT(IsConnected());
ASSERT(IsServiceRunning());
CAddStaticMappingDlg dlgAdd;
dlgAdd.DoModal();
GetFrameWnd()->GetStatistics();
return dlgAdd.QueryMappingsAdded();
}
//
// UI API Wrappers:
//
APIERR
CWinsadmnApp::ConnectToWinsServer(
CString strAddress,
BOOL fIp,
BOOL fAdd // Add to cache
)
{
// First attempt to bind to the new address
m_wbdBindData.fTcpIp = fIp;
m_wbdBindData.pPipeName = fIp
? NULL
: (char *)CWinsadmnApp::lpstrPipeName;
m_wbdBindData.pServerAdd = new char[strAddress.GetLength()+1];
if (m_wbdBindData.pServerAdd == NULL)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
::lstrcpy(m_wbdBindData.pServerAdd, (LPCSTR)strAddress);
if ((m_hBinding = ::WinsBind(&m_wbdBindData)) == NULL)
{
TRACEEOLID("Failed to bind to " << m_wbdBindData.pServerAdd);
delete[] m_wbdBindData.pServerAdd;
return ::GetLastError();
}
//
// Get the UNC name and IP address that we're currently connected to,
// which also serves as a check that there really is a WINS server
// at the other end.
//
m_iaPrimaryIpAddress = m_iaIpAddress = 0L;
m_strNetBIOSName = "\\\\"; // Not provided by the API call.
WINSINTF_ADD_T waWinsAddress;
m_dwLastStatus = ::WinsGetNameAndAdd(&waWinsAddress,
(BYTE *)m_strNetBIOSName.GetBuffer(128)+2);
m_strNetBIOSName.ReleaseBuffer();
if (m_dwLastStatus != ERROR_SUCCESS)
{
TRACEEOLID("Failed to connect to " << m_wbdBindData.pServerAdd);
DisconnectFromWinsServer();
return m_dwLastStatus;
}
//
// If we're connected over TCPIP, regardless
// of what the actual IP address is, we use
// the ip address we used to connect
//
if (fIp)
{
m_iaIpAddress = (LPCTSTR)strAddress;
}
else
{
m_iaIpAddress = waWinsAddress.IPAdd;
}
m_iaPrimaryIpAddress = waWinsAddress.IPAdd;
m_tmConnectedSince = CTime::GetCurrentTime();
#ifndef WIN32S
//
// Create the mutex
//
ASSERT(m_hmutStatistics == NULL);
if ((m_hmutStatistics = ::CreateMutex(NULL, FALSE, STATMUTEXNAME)) == NULL)
{
MessageBox(::GetLastError());
return FALSE;
}
#endif // WIN32S
//
// Optionally add the WINS server to our cache of
// "known" WINS server
//
if (fAdd)
{
m_wcWinssCache.Add(CIpNamePair(
GetConnectedIpAddress(), (LPCSTR)m_strNetBIOSName+2), TRUE);
}
//
// Determine if the connection is on the local machine
// by comparing netbios names.
//
TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH+1];
DWORD dwSize = sizeof(szComputerName);
if (::GetComputerName(szComputerName, &dwSize))
{
//
// Ignore the slashes
//
m_fLocalConnection = (::lstrcmpi((LPCSTR)m_strNetBIOSName+2,
szComputerName)==0);
}
else
{
theApp.MessageBox(IDS_ERR_NO_COMPUTERNAME);
m_fLocalConnection = FALSE;
}
//
// Now try to get to the registry to determine access
// rights.
//
m_cConfig.SetOwner(m_strNetBIOSName);
m_nPrivilege = (m_cConfig.Touch() == ERROR_SUCCESS)
? CWinsadmnApp::PRIV_FULL : CWinsadmnApp::PRIV_READONLY;
m_nServiceStatus = CWinsadmnApp::SRVC_RUNNING;
return ERROR_SUCCESS;
}
//
// Completely purge the database of all references to this WINS server
//
APIERR
CWinsadmnApp::DeleteWinsServer(
CIpNamePair * pipServer
)
{
WINSINTF_ADD_T WinsAdd;
WinsAdd.Len = 4;
WinsAdd.Type = 0;
WinsAdd.IPAdd = (LONG)(pipServer->GetIpAddress());
return :: WinsDeleteWins(&WinsAdd);
}
//
// Disconnect from current wins server
// before calling this API
//
APIERR
CWinsadmnApp::VerifyWinsServer(
CIpNamePair & ipNamePair
)
{
if (IsConnected())
{
return RPC_S_SERVER_UNAVAILABLE;
}
APIERR err = ERROR_SUCCESS;
WINSINTF_BIND_DATA_T wbdBindData;
WINSINTF_ADD_T waWinsAddress;
CString strNetBIOSName;
do
{
handle_t hBinding;
//
// First attempt to bind to the new address
//
wbdBindData.fTcpIp = ipNamePair.GetNetBIOSName().IsEmpty();
CString strAddress;
if (wbdBindData.fTcpIp)
{
strAddress = ((CString)ipNamePair.GetIpAddress());
}
else
{
strAddress = _T("\\\\") + ipNamePair.GetNetBIOSName();
}
wbdBindData.pPipeName = wbdBindData.fTcpIp
? NULL
: (char *)CWinsadmnApp::lpstrPipeName;
wbdBindData.pServerAdd = new char[strAddress.GetLength()+1];
::lstrcpy(wbdBindData.pServerAdd, (LPCSTR)strAddress);
if ((hBinding = ::WinsBind(&wbdBindData)) == NULL)
{
TRACEEOLID("Failed to bind to " << wbdBindData.pServerAdd);
err = ::GetLastError();
break;
}
err = ::WinsGetNameAndAdd(
&waWinsAddress,
(BYTE *)strNetBIOSName.GetBuffer(128));
strNetBIOSName.ReleaseBuffer();
if (err != ERROR_SUCCESS)
{
TRACEEOLID("Failed to connect to " << wbdBindData.pServerAdd);
break;
}
}
while(FALSE);
if (err == ERROR_SUCCESS)
{
//
// Always use the IP address used for connection
// if we went over tcpip (not the address returned
// by the WINS service.
//
if (wbdBindData.fTcpIp)
{
CIpNamePair ip(ipNamePair.GetIpAddress(), (LPCSTR)strNetBIOSName);
ipNamePair = ip;
}
else
{
CIpNamePair ip(waWinsAddress.IPAdd, (LPCSTR)strNetBIOSName);
ipNamePair = ip;
}
}
delete[] wbdBindData.pServerAdd;
return err;
}
APIERR
CWinsadmnApp::DisconnectFromWinsServer()
{
ASSERT((m_hBinding != INVALID_HANDLE_VALUE) && (m_hBinding != NULL));
::WinsUnbind(&m_wbdBindData, m_hBinding);
delete[] m_wbdBindData.pServerAdd;
m_hBinding = INVALID_HANDLE_VALUE;
m_nServiceStatus = CWinsadmnApp::SRVC_NOT_RUNNING;
if (m_hmutStatistics != NULL)
{
::ReleaseMutex(m_hmutStatistics);
::CloseHandle(m_hmutStatistics);
m_hmutStatistics = NULL;
}
return ERROR_SUCCESS;
}
void
CWinsadmnApp::SetServiceStatus()
{
//
// Update the service status appropriately, based on the result
// of the last API call.
//
m_nServiceStatus = (m_dwLastStatus != EPT_S_NOT_REGISTERED
&& m_dwLastStatus != RPC_S_SERVER_UNAVAILABLE)
? CWinsadmnApp::SRVC_RUNNING
: CWinsadmnApp::SRVC_NOT_RUNNING;
}
/***
*
* CWinsadmnApp::GetStatistics
*
* Purpose:
*
* UI Wrapper for WINS Api call
*
*/
APIERR
CWinsadmnApp::GetStatistics(
WINSINTF_RESULTS_T * pwrResults
)
{
#ifndef WIN32S
DWORD dw = ::WaitForSingleObject(m_hmutStatistics, 2000L);
if (dw != WAIT_OBJECT_0)
{
TRACEEOLID( "(app) Failed to get the mutex");
return ERROR_SEM_TIMEOUT;
}
#endif // WIN32S
TRY
{
pwrResults->WinsStat.NoOfPnrs = 0;
pwrResults->WinsStat.pRplPnrs = 0;
pwrResults->NoOfWorkerThds = 1;
m_dwLastStatus = ::WinsStatus(WINSINTF_E_STAT, pwrResults);
if (pwrResults->WinsStat.NoOfPnrs)
{
::WinsFreeMem(pwrResults->WinsStat.pRplPnrs);
}
}
CATCH_ALL(e)
{
m_dwLastStatus = ::GetLastError();
}
END_CATCH_ALL
#ifndef WIN32S
if (!::ReleaseMutex(m_hmutStatistics))
{
m_dwLastStatus = ::GetLastError();
}
#endif // WIN32S
SetServiceStatus();
return m_dwLastStatus;
}
APIERR
CWinsadmnApp::ClearStatistics()
{
m_dwLastStatus = ::WinsResetCounters();
SetServiceStatus();
return m_dwLastStatus;
}
APIERR
CWinsadmnApp::SendTrigger(
CWinsServer & ws,
BOOL fPush,
BOOL fPropagate
)
{
WINSINTF_ADD_T WinsAdd;
WinsAdd.Len = 4;
WinsAdd.Type = 0;
WinsAdd.IPAdd = (LONG)ws.GetIpAddress();
m_dwLastStatus = ::WinsTrigger(&WinsAdd, fPush
? fPropagate
? WINSINTF_E_PUSH_PROP
: WINSINTF_E_PUSH
: WINSINTF_E_PULL);
SetServiceStatus();
return m_dwLastStatus;
}
APIERR
CWinsadmnApp::GetConfig(
WINSINTF_RESULTS_T * pwrResults
)
{
pwrResults->WinsStat.NoOfPnrs = 0;
pwrResults->WinsStat.pRplPnrs = NULL;
pwrResults->NoOfWorkerThds = 1;
m_dwLastStatus = ::WinsStatus(WINSINTF_E_CONFIG, pwrResults);
SetServiceStatus();
return m_dwLastStatus;
}
//
// Same as above, but calling the new API.
//
APIERR
CWinsadmnApp::GetNewConfig(
WINSINTF_RESULTS_NEW_T * pwrResults
)
{
pwrResults->WinsStat.NoOfPnrs = 0;
pwrResults->WinsStat.pRplPnrs = NULL;
pwrResults->NoOfWorkerThds = 1;
pwrResults->pAddVersMaps = NULL;
m_dwLastStatus = ::WinsStatusNew(WINSINTF_E_CONFIG, pwrResults);
SetServiceStatus();
return m_dwLastStatus;
}
APIERR
CWinsadmnApp::ImportStaticMappingsFile(
CString strFile,
BOOL fDelete
)
{
// CODEWORK:: Change this when we're UNICODE ourselves
WCHAR ws[256];
::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (LPCSTR)strFile, -1, ws, 255);
m_dwLastStatus = ::WinsDoStaticInit(ws, fDelete);
// End of UNICODE
SetServiceStatus();
return m_dwLastStatus;
}
APIERR
CWinsadmnApp::DoScavenging()
{
m_dwLastStatus = ::WinsDoScavenging();
SetServiceStatus();
return m_dwLastStatus;
}
APIERR
CWinsadmnApp::BackupDatabase(
CString strPath,
BOOL fIncremental
)
{
m_dwLastStatus = ::WinsBackup((unsigned char *)(LPCSTR)strPath, (short)fIncremental);
SetServiceStatus();
return m_dwLastStatus;
}
//
// Only works on a local WINS, with the service not running.
//
APIERR
CWinsadmnApp::RestoreDatabase(
CString strPath
)
{
APIERR err;
ASSERT(!IsConnected());
ASSERT(HasStoppedWins());
err = ::WinsRestore((unsigned char *)(LPCSTR)strPath);
return err;
}
//
// Register a static mapping
//
APIERR
CWinsadmnApp::AddMapping(
int nType,
int nCount,
CMultipleIpNamePair& mipnp,
BOOL fEdit // Editing existing mapping?
)
{
WINSINTF_RECORD_ACTION_T RecAction;
PWINSINTF_RECORD_ACTION_T pRecAction;
ASSERT(nType >= WINSINTF_E_UNIQUE && nType <= WINSINTF_E_MULTIHOMED);
RecAction.TypOfRec_e = nType;
RecAction.Cmd_e = WINSINTF_E_INSERT;
RecAction.pAdd = NULL;
RecAction.pName = NULL;
pRecAction = &RecAction;
if (nType == WINSINTF_E_UNIQUE ||
nType == WINSINTF_E_NORM_GROUP)
{
RecAction.NoOfAdds = 1;
RecAction.Add.IPAdd = (LONG)mipnp.GetIpAddress();
RecAction.Add.Type = 0;
RecAction.Add.Len = 4;
}
else
{
ASSERT(nCount <= WINSINTF_MAX_MEM);
RecAction.pAdd = (WINSINTF_ADD_T *)::WinsAllocMem(
sizeof(WINSINTF_ADD_T) * nCount);
if (RecAction.pAdd == NULL)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
RecAction.NoOfAdds = nCount;
int i;
for (i = 0; i < nCount; ++i)
{
(RecAction.pAdd+i)->IPAdd = (LONG)mipnp.GetIpAddress(i);
(RecAction.pAdd+i)->Type = 0;
(RecAction.pAdd+i)->Len = 4;
}
RecAction.NodeTyp = WINSINTF_E_PNODE;
}
RecAction.fStatic = TRUE;
//
// Don't copy the beginning slashes when adding.
//
int nLen = mipnp.GetNetBIOSNameLength();
//
// Must have at least enough room for 16 character string
//
RecAction.pName = (LPBYTE)::WinsAllocMem(__max(nLen+1, 17));
if (RecAction.pName == NULL)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
if (fEdit)
{
//
// No need to convert if already existing in the database.
//
::memcpy((char *)RecAction.pName,
(char *)(LPCSTR)mipnp.GetNetBIOSName(),
nLen+1
);
}
else
{
::CharToOemBuff((LPCSTR)mipnp.GetNetBIOSName(),
(char *)RecAction.pName,
nLen+1
);
}
if (nLen < 16)
{
if (nType == WINSINTF_E_SPEC_GROUP)
{
::memset(RecAction.pName+nLen, (int)' ',16-nLen);
RecAction.pName[15] = 0x1C;
RecAction.pName[16] = '\0';
RecAction.NameLen = nLen = 16;
m_dwLastStatus = ::WinsRecordAction(&pRecAction);
}
else
if (nType == WINSINTF_E_NORM_GROUP)
{
::memset(RecAction.pName+nLen, (int)' ',16-nLen);
RecAction.pName[15] = 0x1E;
RecAction.pName[16] = '\0';
RecAction.NameLen = nLen = 16;
m_dwLastStatus = ::WinsRecordAction(&pRecAction);
}
else
{
//
// NOTICE:: When lanman compatible, the name is added
// three times - once each as worksta, server
// and messenger. This will change when we allow
// different 16th bytes to be set.
//
if (m_wpPreferences.IsLanmanCompatible() && !fEdit)
{
BYTE ab[] = { 0x00, 0x03, 0x20 };
::memset(RecAction.pName + nLen, (int)' ', 16-nLen);
int i;
for (i = 0; i < sizeof(ab) / sizeof(ab[0]); ++i)
{
*(RecAction.pName+15) = ab[i];
*(RecAction.pName+16) = '\0';
RecAction.NameLen = nLen = 16;
pRecAction = &RecAction;
m_dwLastStatus = ::WinsRecordAction(&pRecAction);
if (m_dwLastStatus != ERROR_SUCCESS)
{
break;
}
}
}
else
{
::memset(RecAction.pName+nLen, (int)'\0',16-nLen);
*(RecAction.pName+15) = 0x20;
*(RecAction.pName+16) = '\0';
RecAction.NameLen = nLen;
m_dwLastStatus = ::WinsRecordAction(&pRecAction);
}
}
}
else
{
RecAction.NameLen = nLen;
m_dwLastStatus = ::WinsRecordAction(&pRecAction);
}
if (RecAction.pName != NULL);
{
::WinsFreeMem(RecAction.pName);
}
if (RecAction.pAdd != NULL);
{
::WinsFreeMem(RecAction.pAdd);
}
::WinsFreeMem(pRecAction);
SetServiceStatus();
return m_dwLastStatus;
}
APIERR
CWinsadmnApp::DeleteMapping (
CMapping& mapping
)
{
WINSINTF_RECORD_ACTION_T RecAction;
PWINSINTF_RECORD_ACTION_T pRecAction;
ASSERT(mapping.GetMappingType() >= WINSINTF_E_UNIQUE
&& mapping.GetMappingType() <= WINSINTF_E_MULTIHOMED);
RecAction.TypOfRec_e = mapping.GetMappingType();
RecAction.Cmd_e = WINSINTF_E_DELETE;
RecAction.State_e = WINSINTF_E_DELETED;
RecAction.fStatic = TRUE;
RecAction.pName = NULL;
RecAction.pAdd = NULL;
pRecAction = &RecAction;
RecAction.pName = (LPBYTE)::WinsAllocMem(mapping.GetNetBIOSName().GetLength()+1);
if (RecAction.pName == NULL)
{
return(::GetLastError());
}
::lstrcpy((char *)(LPCSTR)RecAction.pName,
(char *)(LPCSTR)mapping.GetNetBIOSName());
RecAction.NameLen = mapping.GetNetBIOSNameLength()
? mapping.GetNetBIOSNameLength()
: ::lstrlen((LPCSTR)RecAction.pName);
m_dwLastStatus = ::WinsRecordAction(&pRecAction);
if (RecAction.pName != NULL);
{
::WinsFreeMem(RecAction.pName);
}
if (RecAction.pAdd != NULL);
{
::WinsFreeMem(RecAction.pAdd);
}
::WinsFreeMem(pRecAction);
SetServiceStatus();
return m_dwLastStatus;
}
BOOL
CWinsadmnApp::MatchIpAddress (
PADDRESS_MASK pMask,
LONG lIpAddress
)
{
ASSERT(pMask != NULL);
LONG l1 = pMask->lIpMask;
int i;
for (i=0; i < 4; ++i)
{
if (!(pMask->bMask & 1<<i) && (HIBYTE(HIWORD(l1))
!= HIBYTE(HIWORD(lIpAddress))))
{
return FALSE;
}
l1 <<= 8;
lIpAddress <<= 8;
}
return TRUE;
}
//
// Determine if the given ip name pair fits the mask
//
BOOL
CWinsadmnApp::FitsMask(
PADDRESS_MASK pMask,
PWINSINTF_RECORD_ACTION_T pRow
)
{
ASSERT(pMask != NULL);
ASSERT(pRow != NULL);
ASSERT(pMask->lpNetBIOSName != NULL);
//
// Match NetBIOSName
//
if(*pMask->lpNetBIOSName)
{
LPSTR lp1 = (LPSTR)pMask->lpNetBIOSName;
LPSTR lp2 = (LPSTR)pRow->pName;
while ((*lp1 != TEXT('\0')) && (*lp2 != TEXT('\0')))
{
if (*lp1 == '*')
{
break;
}
if (*lp1 != '?' && *lp1 != *lp2)
{
return FALSE;
}
++lp1;
++lp2;
}
if ((*lp1 != '*') && (*lp1 != TEXT('\0') || *lp2 != TEXT('\0')))
{
return FALSE;
}
}
//
// Match IP Address(es)
//
if (pMask->bMask != 0xFF)
{
//
// Special case for multiple address
// mappings
//
if (pRow->NoOfAdds==0)
{
return MatchIpAddress(pMask, pRow->Add.IPAdd);
}
else
{
//
// The unit matches if any of the IP addresses
// matches
//
int j;
int k = 1;
for (j=0; j < (int)pRow->NoOfAdds/2; ++j)
{
if (MatchIpAddress(pMask, (pRow->pAdd+k)->IPAdd))
{
return TRUE;
}
++k;
++k;
}
return FALSE;
}
}
return TRUE;
}
BOOL
CWinsadmnApp::IsValidNBMask(
CString & strNetBIOSNameMask
)
{
if (!IsValidNetBIOSName(strNetBIOSNameMask,
theApp.m_wpPreferences.IsLanmanCompatible(), FALSE))
{
return FALSE;
}
//
// Any characters after the * are not allowed.
//
int i = strNetBIOSNameMask.Find('*');
if (i == -1)
strNetBIOSNameMask += "*";
i = strNetBIOSNameMask.Find('*');
if ((i != -1) && (i!=strNetBIOSNameMask.GetLength()-1))
{
return FALSE;
}
return TRUE;
}
BOOL
CWinsadmnApp::IsValidDNMask(
CString & strDomainNameMask
)
{
if (!IsValidDomain(strDomainNameMask))
{
return FALSE;
}
//
// Any characters after the * are not allowed.
//
int i = strDomainNameMask.Find('*');
if (i == -1)
strDomainNameMask += "*";
i = strDomainNameMask.Find('*');
if ((i != -1) && (i!=strDomainNameMask.GetLength()-1))
{
return FALSE;
}
return TRUE;
}
void
CWinsadmnApp::GetFilterString(
PADDRESS_MASK pMask,
CString& str
)
{
if (pMask != NULL)
{
TCHAR sz[256];
//
// Mask's are stored as OEM strings
//
::OemToCharBuff(pMask->lpNetBIOSName, sz,
::lstrlen(pMask->lpNetBIOSName) + 1 );
LONG l = pMask->lIpMask;
str = "[";
str += sz;
str += "]/[";
if (pMask->bMask != 0xFF)
{
int i;
for (i=0; i < 4; ++i)
{
if (pMask->bMask & 1<<i)
{
str+='*';
}
else
{
CHAR sz[5];
_itoa(HIBYTE(HIWORD(l)), sz, 10);
str += sz;
}
if (i!=3)
{
str+='.';
}
l <<= 8;
}
}
str += "]";
}
else
{
str.LoadString(IDS_MASK_NONE);
}
}
//
// Determine if the local machine has the wins
// service installed, and this service is
// not running
//
BOOL
CWinsadmnApp::HasStoppedWins()
{
SC_HANDLE hService;
SC_HANDLE hScManager;
hScManager = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hScManager == NULL)
{
return FALSE ;
}
hService = ::OpenService(hScManager, "WINS", SERVICE_QUERY_STATUS);
if (hService == NULL)
{
return FALSE;
}
SERVICE_STATUS ss;
BOOL fSuccess = ::QueryServiceStatus(hService, &ss);
APIERR err = ::GetLastError();
::CloseServiceHandle(hService);
::CloseServiceHandle(hScManager);
return fSuccess && ss.dwCurrentState == SERVICE_STOPPED;
}
APIERR
CWinsadmnApp::ChangeServiceState(
int nService
)
{
ASSERT(nService >= SRVC_NOT_RUNNING && nService <= SRVC_PAUSED);
SC_HANDLE hService;
SC_HANDLE hScManager;
hScManager = ::OpenSCManager(GetConnectedNetBIOSName(),
NULL, SC_MANAGER_ALL_ACCESS);
if (hScManager == NULL)
{
return ::GetLastError();
}
hService = OpenService(hScManager, "WINS", SERVICE_ALL_ACCESS);
if (hService == NULL)
{
return ::GetLastError();
}
SERVICE_STATUS ss;
DWORD dwControl;
BOOL fSuccess;
switch(nService)
{
case SRVC_NOT_RUNNING:
dwControl = SERVICE_CONTROL_STOP;
fSuccess = ::ControlService(hService, dwControl, &ss);
break;
case SRVC_PAUSED:
dwControl = SERVICE_CONTROL_PAUSE;
fSuccess = ::ControlService(hService, dwControl, &ss);
break;
case SRVC_RUNNING:
if (m_nServiceStatus == SERVICE_PAUSED)
{
dwControl = SERVICE_CONTROL_CONTINUE;
fSuccess = ::ControlService(hService, dwControl, &ss);
}
else
{
fSuccess = ::StartService(hService, 0, NULL);
}
}
::CloseServiceHandle(hService);
::CloseServiceHandle(hScManager);
if (!fSuccess)
{
return ::GetLastError();
}
m_nServiceStatus = nService;
return ERROR_SUCCESS;
}
//
// CWinsadmnApp commands
//
// Display the standard about box
//
void
CWinsadmnApp::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 );
}
}
//
// The one and only CWinsadmnApp object
//
CWinsadmnApp NEAR theApp;