|
|
/**********************************************************************/ /** Microsoft Windows/NT **/ /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/ /**********************************************************************/
/*
winsup.cpp Global functions
FILE HISTORY:
*/
#include "stdafx.h"
#include "winssup.h"
#include "tregkey.h"
#include "resource.h"
#include "wins.h"
#include <clusapi.h>
#include "..\tfscore\cluster.h"
const TCHAR g_szPipeName[] = _T("\\pipe\\WinsPipe"); const TCHAR g_szDefaultHelpTopic[] = _T("\\help\\winsconcepts.chm::/sag_WINStopnode.htm");
/*---------------------------------------------------------------------------
SendTrigger() Sends a pull or push replication trigger to a given wins server ---------------------------------------------------------------------------*/ DWORD SendTrigger ( handle_t hWins, LONG ipTarget, BOOL fPush, BOOL fPropagate ) { DWORD dwStatus; WINSINTF_ADD_T WinsAdd; WinsAdd.Len = 4; WinsAdd.Type = 0; WinsAdd.IPAdd = ipTarget;
WINSINTF_TRIG_TYPE_E TrigType;
TrigType = fPush ? (fPropagate ? WINSINTF_E_PUSH_PROP : WINSINTF_E_PUSH) : WINSINTF_E_PULL;
#ifdef WINS_CLIENT_APIS
dwStatus = ::WinsTrigger(hWins, &WinsAdd, TrigType); #else
dwStatus = ::WinsTrigger(&WinsAdd, TrigType); #endif WINS_CLIENT_APIS
return dwStatus; }
/*---------------------------------------------------------------------------
ControlWINSService(LPCTSTR pszName, BOOL bStop) Stops ot starts the WINS service on the local machine ---------------------------------------------------------------------------*/ DWORD ControlWINSService(LPCTSTR pszName, BOOL bStop) { DWORD dwState = bStop ? SERVICE_STOPPED : SERVICE_RUNNING; DWORD dwPending = bStop ? SERVICE_STOP_PENDING : SERVICE_START_PENDING; DWORD err = ERROR_SUCCESS; int i; SERVICE_STATUS ss; DWORD dwControl; BOOL fSuccess; SC_HANDLE hService = NULL; SC_HANDLE hScManager = NULL;
// oepmnt he service control manager
hScManager = ::OpenSCManager(pszName, NULL, SC_MANAGER_ALL_ACCESS); if (hScManager == NULL) { err = ::GetLastError(); Trace1("ControlWINSService - OpenScManager failed! %d\n", err); goto Error; }
// get the handle to the WINS service
hService = OpenService(hScManager, _T("WINS"), SERVICE_ALL_ACCESS); if (hService == NULL) { err = ::GetLastError(); Trace1("ControlWINSService - OpenService failed! %d\n", err); goto Error; }
// if stop requested
if (bStop) { dwControl = SERVICE_CONTROL_STOP; fSuccess = ::ControlService(hService, dwControl, &ss); if (!fSuccess) { err = ::GetLastError(); Trace1("ControlWINSService - ControlService failed! %d\n", err); goto Error; } } // otherwise start the service
else { fSuccess = ::StartService(hService, 0, NULL); if (!fSuccess) { err = ::GetLastError(); Trace1("ControlWINSService - StartService failed! %d\n", err); goto Error; } }
#define LOOP_TIME 5000
#define NUM_LOOPS 600
// wait for the service to start/stop.
for (i = 0; i < NUM_LOOPS; i++) { ::QueryServiceStatus(hService, &ss);
// check to see if we are done
if (ss.dwCurrentState == dwState) { int time = LOOP_TIME * i; Trace1("ControlWINSService - service stopped/started in approx %d ms!\n", time); break; } // now see if something bad happened
if (ss.dwCurrentState != dwPending) { int time = LOOP_TIME * i; Trace1("ControlWINSService - service stop/start failed in approx %d ms!\n", time); break; }
Sleep(LOOP_TIME); }
if (i == NUM_LOOPS) Trace0("ControlWINSService - service did NOT stop/start in wait period!\n");
if (ss.dwCurrentState != dwState) err = ERROR_SERVICE_REQUEST_TIMEOUT;
Error: // close the respective handles
if (hService) ::CloseServiceHandle(hService);
if (hScManager) ::CloseServiceHandle(hScManager);
return err; }
/*---------------------------------------------------------------------------
GetNameIP( const CString &strDisplay, CString &strName, CString &strIP) Returns the Server name and the IP Address string with the group name ---------------------------------------------------------------------------*/ void GetNameIP ( const CString &strDisplay, CString &strName, CString &strIP ) { CString strTemp = strDisplay;
// find '['
int nPos = strDisplay.Find(_T("["));
// left of the positioncontains the name and right of it has the IP address
// 1 to take care of the space before '['
strName = strDisplay.Left(nPos-1);
strIP = strDisplay.Right(strDisplay.GetLength() - nPos);
// take out '[' and ']' in strIP
int npos1 = strIP.Find(_T("[")); int npos2 = strIP.Find(_T("]"));
strIP = strIP.Mid(npos1+1, npos2-npos1-1);
return; }
/*---------------------------------------------------------------------------
WideToMBCS() converts WCS to MBCS string
NOTE: the caller of this function must make sure that szOut is big enough to hold any possible string in strIn. ---------------------------------------------------------------------------*/ DWORD WideToMBCS(CString & strIn, LPSTR szOut, UINT uCodePage, DWORD dwFlags, BOOL * pfDefaultUsed) { DWORD dwErr = ERROR_SUCCESS; BOOL fDefaultCharUsed = FALSE;
int nNumBytes = ::WideCharToMultiByte(uCodePage, dwFlags, strIn, -1, szOut, 0, NULL, &fDefaultCharUsed); dwErr = ::WideCharToMultiByte(uCodePage, dwFlags, strIn, -1, szOut, nNumBytes, NULL, &fDefaultCharUsed);
szOut[nNumBytes] = '\0';
if (pfDefaultUsed) *pfDefaultUsed = fDefaultCharUsed;
return dwErr; }
/*---------------------------------------------------------------------------
MBCSToWide () converts MBCS to Wide string ---------------------------------------------------------------------------*/ DWORD MBCSToWide(LPSTR szIn, CString & strOut, UINT uCodePage, DWORD dwFlags) { DWORD dwErr = ERROR_SUCCESS;
LPTSTR pBuf = strOut.GetBuffer(MAX_PATH * 2); ZeroMemory(pBuf, MAX_PATH * 2);
dwErr = ::MultiByteToWideChar(uCodePage, dwFlags, szIn, -1, pBuf, MAX_PATH * 2);
strOut.ReleaseBuffer();
return dwErr; }
LONG GetSystemMessageA ( 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
// WINS server error messages.
//
if( nId >= NERR_BASE && nId <= MAX_NERR ) { hdll = LoadLibrary( _T("netmsg.dll") ); } else if( nId >= 0x40000000L ) { hdll = LoadLibrary( _T("ntdll.dll") ); }
if( hdll == NULL ) { flags |= FORMAT_MESSAGE_FROM_SYSTEM; } else { flags |= FORMAT_MESSAGE_FROM_HMODULE; }
//
// Let FormatMessage do the dirty work.
//
DWORD dwResult = ::FormatMessageA( 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() ; }
LONG GetSystemMessage ( UINT nId, TCHAR * chBuffer, int cbBuffSize ) { TCHAR * 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
// WINS server error messages.
//
if( nId >= NERR_BASE && nId <= MAX_NERR ) { hdll = LoadLibrary( _T("netmsg.dll") ); } else if( nId >= 0x40000000L ) { hdll = LoadLibrary( _T("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 ? ERROR_SUCCESS : ::GetLastError() ; }
/*!--------------------------------------------------------------------------
LoadMessage Loads the error message from the correct DLL. Author: EricDav ---------------------------------------------------------------------------*/ BOOL LoadMessage ( UINT nIdPrompt, TCHAR * 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_WINS_DOWN; }
//
// 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_MSG_LAST) ) { //
// It's in our resource fork
//
bOk = ::LoadString( AfxGetInstanceHandle(), nIdPrompt, chMsg, nMsgSize / sizeof(TCHAR) ) != 0 ; } else { //
// It's in the system somewhere.
//
bOk = GetSystemMessage( nIdPrompt, chMsg, nMsgSize ) == 0 ; }
if (bOk && nIdPrompt == ERROR_ACCESS_DENIED) { // tack on our extra help to explain different acess levels
CString strAccessDeniedHelp;
strAccessDeniedHelp.LoadString(IDS_ACCESS_DENIED_HELP);
lstrcat(chMsg, _T("\n\n")); lstrcat(chMsg, strAccessDeniedHelp); }
//
// If the error message did not compute, replace it.
//
if ( ! bOk ) { TCHAR chBuff [STRING_LENGTH_MAX] ; static const TCHAR * pszReplacement = _T("System Error: %ld"); const TCHAR * pszMsg = pszReplacement ;
//
// Try to load the generic (translatable) error message text
//
if ( ::LoadString( AfxGetInstanceHandle(), IDS_ERR_MESSAGE_GENERIC, chBuff, STRING_LENGTH_MAX ) != 0 ) { pszMsg = chBuff ; } ::wsprintf( chMsg, pszMsg, nIdPrompt ) ; }
return bOk; }
/*!--------------------------------------------------------------------------
WinsMessageBox Puts up a message box with the corresponding error text. Author: EricDav ---------------------------------------------------------------------------*/ int WinsMessageBox(UINT nIdPrompt, UINT nType , const TCHAR * pszSuffixString, UINT nHelpContext) { TCHAR chMesg [4000] ; BOOL bOk ; CThemeContextActivator themeActivator;
bOk = LoadMessage(nIdPrompt, chMesg, sizeof(chMesg)/sizeof(TCHAR)); if ( pszSuffixString ) { ::lstrcat( chMesg, _T(" ") ) ; ::lstrcat( chMesg, pszSuffixString ) ; }
return ::AfxMessageBox( chMesg, nType, nHelpContext ) ; }
/*!--------------------------------------------------------------------------
WinsMessageBoxEx Puts up a message box with the corresponding error text. Author: EricDav ---------------------------------------------------------------------------*/ int WinsMessageBoxEx ( UINT nIdPrompt, LPCTSTR pszPrefixMessage, UINT nType, UINT nHelpContext ) { AFX_MANAGE_STATE(AfxGetStaticModuleState());
TCHAR chMesg[4000]; CString strMessage; BOOL bOk; CThemeContextActivator themeActivator;
bOk = LoadMessage(nIdPrompt, chMesg, sizeof(chMesg)/sizeof(TCHAR)); if ( pszPrefixMessage ) { strMessage = pszPrefixMessage; strMessage += _T("\n"); strMessage += _T("\n"); strMessage += chMesg; } else { strMessage = chMesg; }
return AfxMessageBox(strMessage, nType, nHelpContext); }
// class NameTypeMapping handlers
/*!--------------------------------------------------------------------------
MapDWORDToCString Generic mapping of a DWORD to a CString. dwNameType is the 16th byte of the name. dwWinsType is Unique, multihomed, group, etc... Author: KennT ---------------------------------------------------------------------------*/ void MapDWORDToCString(DWORD dwNameType, DWORD dwWinsType, const CStringMapArray * pMap, CString & strName) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CStringMapEntry mapEntry;
for (int i = 0; i < pMap->GetSize(); i++) { mapEntry = pMap->GetAt(i);
// break out if this is the correct type and the wins type
// matches or is a don't care
if ( (mapEntry.dwNameType == dwNameType) && ( (mapEntry.dwWinsType == -1) || (mapEntry.dwWinsType == dwWinsType) ) ) { break; }
mapEntry.dwNameType = 0xFFFFFFFF; } if (mapEntry.dwNameType == 0xFFFFFFFF) { MapDWORDToCString(NAME_TYPE_OTHER, dwWinsType, pMap, strName); } else { if (mapEntry.st.IsEmpty()) Verify(pMap->GetAt(i).st.LoadString(mapEntry.ulStringId));
strName = pMap->GetAt(i).st; } }
// this structure allows us to map name types to strings. The secondary
// check is based on the wins defined record type. In order for this to work
// correctly, place any names that need to be defined with the wins type before
// the entry with the wins type set to -1.
static const UINT s_NameTypeMappingDefault[NUM_DEFAULT_NAME_TYPES][3] = { { NAME_TYPE_WORKSTATION, WINSINTF_E_NORM_GROUP, IDS_NAMETYPE_MAP_WORKGROUP }, { NAME_TYPE_WORKSTATION, -1, IDS_NAMETYPE_MAP_WORKSTATION }, { NAME_TYPE_DC, -1, IDS_NAMETYPE_MAP_DC }, { NAME_TYPE_FILE_SERVER, WINSINTF_E_SPEC_GROUP, IDS_NAMETYPE_MAP_SPECIAL_INTERNET_GROUP }, { NAME_TYPE_FILE_SERVER, -1, IDS_NAMETYPE_MAP_FILE_SERVER }, { NAME_TYPE_DMB , -1, IDS_NAMETYPE_MAP_DMB }, { NAME_TYPE_OTHER, -1, IDS_NAMETYPE_MAP_OTHER }, { NAME_TYPE_NETDDE, -1, IDS_NAMETYPE_MAP_NETDDE }, { NAME_TYPE_MESSENGER, -1, IDS_NAMETYPE_MAP_MESSENGER }, { NAME_TYPE_RAS_SERVER, -1, IDS_NAMETYPE_MAP_RAS_SERVER }, { NAME_TYPE_NORM_GRP_NAME, -1, IDS_NAMETYPE_MAP_NORMAL_GROUP_NAME }, { NAME_TYPE_WORK_NW_MON_AGENT, -1, IDS_NAMETYPE_MAP_NW_MON_AGENT }, { NAME_TYPE_WORK_NW_MON_NAME, -1, IDS_NAMETYPE_MAP_NMN}, };
const NameTypeMapping::REGKEYNAME NameTypeMapping::c_szNameTypeMapKey = _T("SYSTEM\\CurrentControlSet\\Services\\wins\\NameTypeMap"); const NameTypeMapping::REGKEYNAME NameTypeMapping::c_szDefault= _T("(Default)");
NameTypeMapping ::NameTypeMapping() { }
NameTypeMapping ::~NameTypeMapping() { Unload(); }
void NameTypeMapping ::SetMachineName(LPCTSTR pszMachineName) { m_strMachineName = pszMachineName; }
HRESULT NameTypeMapping::Load() { HRESULT hr = hrOK; RegKey regkey; RegKey regkeyMachine; HKEY hkeyMachine = HKEY_LOCAL_MACHINE; RegKey::CREGKEY_KEY_INFO regkeyInfo; RegKeyIterator regkeyIter; UINT i; WORD langID; RegKey regkeyProto; DWORD dwErr; CStringMapEntry mapEntry;
::ZeroMemory(®keyInfo, sizeof(regkeyInfo)); // Look for the registry key
if (FHrSucceeded(hr)) { DWORD dwErr = regkey.Open(hkeyMachine, c_szNameTypeMapKey, KEY_READ, m_strMachineName) ; hr = HRESULT_FROM_WIN32( dwErr ); }
// Get the count of items
if (FHrSucceeded(hr)) { DWORD dwErr = regkey.QueryKeyInfo(®keyInfo) ; hr = HRESULT_FROM_WIN32( dwErr ); } // Alloc the array for the count of items + default items
Unload();
// Read in the registry data and add it to the internal array
//
// enumerate the keys
//
if (FHrSucceeded(hr)) hr = regkeyIter.Init(®key); if (FHrSucceeded(hr)) { HRESULT hrIter; DWORD dwProtoId; CString stKey; CString stLang; // Now that we have this key, look for the language id
langID = GetUserDefaultLangID(); stLang.Format(_T("%04x"), (DWORD)langID); for (hrIter = regkeyIter.Next(&stKey, NULL); hrIter == hrOK; hrIter = regkeyIter.Next(&stKey, NULL)) { CString st; // Given the name of the key, that is a hex value (the protocol id)
// Convert that into a DWORD
dwProtoId = _tcstoul((LPCTSTR) stKey, NULL, 16);
// Open this key
regkeyProto.Close(); dwErr = regkeyProto.Open(regkey, stKey); if (!FHrSucceeded(HRESULT_FROM_WIN32(dwErr))) continue;
// Ok, get the name value
dwErr = regkeyProto.QueryValue(stLang, st); if (!FHrSucceeded(HRESULT_FROM_WIN32(dwErr))) { // Look for the key with the name of default
dwErr = regkeyProto.QueryValue(c_szDefault, st); }
if (FHrSucceeded(HRESULT_FROM_WIN32(dwErr))) { // Ok, add this value to the list
mapEntry.dwNameType = dwProtoId; mapEntry.st = st; mapEntry.ulStringId = 0;
Add(mapEntry); } } }
// Read in the default item data and add it to the array
for (i = 0; i < DimensionOf(s_NameTypeMappingDefault); i++) { mapEntry.dwNameType = s_NameTypeMappingDefault[i][0]; mapEntry.dwWinsType = s_NameTypeMappingDefault[i][1]; mapEntry.st.LoadString(s_NameTypeMappingDefault[i][2]); mapEntry.ulStringId = 0;
Add(mapEntry); } return hrOK; }
void NameTypeMapping::Unload() { RemoveAll(); }
void NameTypeMapping::TypeToCString(DWORD dwProtocolId, DWORD dwRecordType, CString & strName) { MapDWORDToCString(dwProtocolId, dwRecordType, this, strName); }
// add in the new id/name
HRESULT NameTypeMapping::AddEntry(DWORD dwProtocolId, LPCTSTR pstrName) { HRESULT hr = hrOK; RegKey regkey; RegKey regkeyID; HKEY hkeyMachine = HKEY_LOCAL_MACHINE; WORD langID; CStringMapEntry mapEntry; CString stID, stLang, stNew;
// Look for the registry key
if (FHrSucceeded(hr)) { DWORD dwErr = regkey.Create(hkeyMachine, c_szNameTypeMapKey, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,NULL, m_strMachineName) ; hr = HRESULT_FROM_WIN32( dwErr ); }
// build our new ID string
stID.Format(_T("%04x"), (DWORD) dwProtocolId);
// Now that we have this key, look for the language id
langID = GetUserDefaultLangID(); stLang.Format(_T("%04x"), (DWORD)langID);
stNew = c_szNameTypeMapKey + _T("\\") + stID;
// create the ID key
if (FHrSucceeded(hr)) { DWORD dwErr = regkeyID.Create(hkeyMachine, stNew, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,NULL, m_strMachineName) ; hr = HRESULT_FROM_WIN32( dwErr ); }
// set the name value
if (FHrSucceeded(hr)) { DWORD dwErr = regkeyID.SetValue(stLang, pstrName) ; hr = HRESULT_FROM_WIN32( dwErr ); }
if (FHrSucceeded(hr)) { // add to internal list
mapEntry.dwNameType = dwProtocolId; mapEntry.st = pstrName; mapEntry.ulStringId = 0;
Add(mapEntry); }
return hr; }
// modify the given ID's string name
HRESULT NameTypeMapping::ModifyEntry(DWORD dwProtocolId, LPCTSTR pstrName) { HRESULT hr = hrOK; RegKey regkey; RegKey regkeyID; HKEY hkeyMachine = HKEY_LOCAL_MACHINE; int i; WORD langID; CString stID, stLang, stNew;
// Look for the registry key
if (FHrSucceeded(hr)) { DWORD dwErr = regkey.Open(hkeyMachine, c_szNameTypeMapKey, KEY_READ, m_strMachineName) ; hr = HRESULT_FROM_WIN32( dwErr ); }
// build our new ID string
stID.Format(_T("%04x"), (DWORD) dwProtocolId);
stNew = c_szNameTypeMapKey + _T("\\") + stID;
// open the correct ID key
if (FHrSucceeded(hr)) { DWORD dwErr = regkeyID.Open(hkeyMachine, stNew, KEY_ALL_ACCESS, m_strMachineName) ; hr = HRESULT_FROM_WIN32( dwErr ); }
// Now that we have this key, look for the language id
langID = GetUserDefaultLangID(); stLang.Format(_T("%04x"), (DWORD)langID);
// set the new value
if (FHrSucceeded(hr)) { DWORD dwErr = regkeyID.SetValue(stLang, pstrName) ; hr = HRESULT_FROM_WIN32( dwErr ); }
if (FHrSucceeded(hr)) { // modify the internal list
for (i = 0; i < GetSize(); i++) { if (GetAt(i).dwNameType == dwProtocolId) { m_pData[i].st = pstrName; break; } } }
return hr; }
// remove the given ID's string name
HRESULT NameTypeMapping::RemoveEntry(DWORD dwProtocolId) { HRESULT hr = hrOK; RegKey regkey; HKEY hkeyMachine = HKEY_LOCAL_MACHINE; int i; CString stID;
// Look for the registry key
if (FHrSucceeded(hr)) { DWORD dwErr = regkey.Open(hkeyMachine, c_szNameTypeMapKey, KEY_READ, m_strMachineName) ; hr = HRESULT_FROM_WIN32( dwErr ); }
// build our new ID string
stID.Format(_T("%04x"), (DWORD) dwProtocolId);
// set the new value
if (FHrSucceeded(hr)) { DWORD dwErr = regkey.RecurseDeleteKey(stID) ; hr = HRESULT_FROM_WIN32( dwErr ); }
if (FHrSucceeded(hr)) { // modify the internal list
for (i = 0; i < GetSize(); i++) { if (GetAt(i).dwNameType == dwProtocolId) { RemoveAt(i); break; } } }
return hr; }
BOOL NameTypeMapping::EntryExists(DWORD dwProtocolId) { BOOL fExists = FALSE;
for (int i = 0; i < GetSize(); i++) { if (GetAt(i).dwNameType == dwProtocolId) { fExists = TRUE; break; } }
return fExists; }
/*---------------------------------------------------------------------------
CleanString(CString& str) Strip leading and trailing spaces from the string. ---------------------------------------------------------------------------*/ CString& 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; }
/*---------------------------------------------------------------------------
IsValidNetBIOSName Determine if the given netbios is valid, and pre-pend a double backslash if not already present (and the address is otherwise valid). ---------------------------------------------------------------------------*/ BOOL 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; } } 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; }
/*---------------------------------------------------------------------------
IsValidDomain Determine if the given domain name address is valid, and clean it up, if necessary ---------------------------------------------------------------------------*/ BOOL 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; }
/*---------------------------------------------------------------------------
IsValidIpAddress Determine if the given IP address is valid, and clean it up, if necessary ---------------------------------------------------------------------------*/ BOOL 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; }
/*---------------------------------------------------------------------------
IsValidAddress 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 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 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); }
/*---------------------------------------------------------------------------
VerifyWinsServer(CString& strServer,CString& strIP) Called if the server is not coonected yet, gets the name and IP address od the server Author:v-shubk ---------------------------------------------------------------------------*/ /*
DWORD VerifyWinsServer(CString &strAddress, CString &strServerName, DWORD & dwIP) { CString strNameIP = strAddress; BOOL fIp; DWORD err = ERROR_SUCCESS;
if (IsValidAddress(strNameIP, &fIp, TRUE, TRUE)) { CWinsServerObj ws(NULL,"", TRUE, TRUE);
if (fIp) { // IP address specified
ws = CWinsServerObj(CIpAddress(strNameIP), "", TRUE, TRUE); } else { // machine name specified
ws = CWinsServerObj(CIpAddress(), strNameIP, TRUE, TRUE); }
WINSINTF_BIND_DATA_T wbdBindData; handle_t hBinding = NULL; WINSINTF_ADD_T waWinsAddress; char szNetBIOSName[256] = {0};
do { // First attempt to bind to the new address
wbdBindData.fTcpIp = ws.GetNetBIOSName().IsEmpty(); CString strTempAddress;
if (wbdBindData.fTcpIp) { strTempAddress = ((CString)ws.GetIpAddress()); } else { //strTempAddress = _T("\\\\") + ws.GetNetBIOSName();
CString tmp;
tmp = ws.GetNetBIOSName();
if ( (tmp[0] == _T('\\')) && (tmp[1] == _T('\\')) ) strTempAddress = ws.GetNetBIOSName(); else strTempAddress = _T("\\\\") + ws.GetNetBIOSName(); }
wbdBindData.pPipeName = wbdBindData.fTcpIp ? NULL : (LPSTR) g_szPipeName; wbdBindData.pServerAdd = (LPSTR) (LPCTSTR) strTempAddress;
if ((hBinding = ::WinsBind(&wbdBindData)) == NULL) { err = ::GetLastError(); break; }
#ifdef WINS_CLIENT_APIS
err = ::WinsGetNameAndAdd(hBinding, &waWinsAddress, (LPBYTE) szNetBIOSName); #else
err = ::WinsGetNameAndAdd(&waWinsAddress, (LPBYTE) szNetBIOSName); #endif WINS_CLIENT_APIS
} 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(ws.GetIpAddress(), szNetBIOSName); ws = ip; } else { CIpNamePair ip(waWinsAddress.IPAdd, szNetBIOSName); ws = ip; }
// convert the dbcs netbios name to wide char
WCHAR szTempIP[20] = {0};
int nNumBytes = MultiByteToWideChar(CP_ACP, 0, szNetBIOSName, -1, szTempIP, 20); // now fill in the name for return
strServerName = szTempIP;
// fill in the IP
dwIP = (LONG) ws.QueryIpAddress(); }
if (hBinding) { // call winsunbind here, No more WINS apis called atfer this
WinsUnbind(&wbdBindData, hBinding); hBinding = NULL; } } return err; } */
/*---------------------------------------------------------------------------
VerifyWinsServer(CString& strServer,CString& strIP) Called if the server is not coonected yet, gets the name and IP address od the server Author: ericdav ---------------------------------------------------------------------------*/ DWORD VerifyWinsServer(CString &strAddress, CString &strServerName, DWORD & dwIP) { CString strNameIP = strAddress; BOOL fIp; DWORD err = ERROR_SUCCESS;
if (IsValidAddress(strNameIP, &fIp, TRUE, TRUE)) { CWinsServerObj ws(NULL, "", TRUE, TRUE);
if (fIp) { BOOL bIsCluster = ::FIsComputerInRunningCluster(strNameIP);
// IP address specified
ws = CWinsServerObj(CIpAddress(strNameIP), "", TRUE, TRUE);
// if the ip address given to us is a cluster address..
if (bIsCluster) { err = GetClusterInfo( strNameIP, strServerName, &dwIP); if (err == ERROR_SUCCESS) { DWORD dwCheckIP;
err = GetHostAddress(strServerName, &dwCheckIP); if (dwCheckIP != dwIP) { bIsCluster = FALSE; } } }
// this is not a cluster address
if (!bIsCluster) { err = GetHostName((LONG) ws.GetIpAddress(), strServerName); if (err == ERROR_SUCCESS) { if (strServerName.IsEmpty()) { err = DNS_ERROR_NAME_DOES_NOT_EXIST; } else { // just want the host name
int nDot = strServerName.Find('.'); if (nDot != -1) { strServerName = strServerName.Left(nDot); } }
dwIP = (LONG) ws.GetIpAddress(); } } } else { // machine name specified
ws = CWinsServerObj(CIpAddress(), strNameIP, TRUE, TRUE);
err = GetHostAddress(strNameIP, &dwIP); if (err == ERROR_SUCCESS) { // just want the host name
int nDot = strNameIP.Find('.'); if (nDot != -1) { strServerName = strNameIP.Left(nDot); } else { strServerName = strNameIP; } } } }
return err; }
void MakeIPAddress(DWORD dwIP, CString & strIP) { CString strTemp; DWORD dwFirst = GETIP_FIRST(dwIP); DWORD dwSecond = GETIP_SECOND(dwIP); DWORD dwThird = GETIP_THIRD(dwIP); DWORD dwLast = GETIP_FOURTH(dwIP);
strIP.Empty();
// wrap it into CString object
TCHAR szStr[20] = {0};
_itot(dwFirst, szStr, 10); strTemp = szStr; strTemp += _T(".");
_itot(dwSecond, szStr, 10); strTemp += szStr; strTemp += _T(".");
_itot(dwThird, szStr, 10); strTemp += szStr; strTemp += _T(".");
_itot(dwLast, szStr, 10); strTemp += szStr; strIP = strTemp; }
DWORD GetHostName ( DWORD dwIpAddr, CString & strHostName ) { CString strName;
//
// Call the Winsock API to get host name information.
//
strHostName.Empty();
u_long ulAddrInNetOrder = ::htonl( (u_long) dwIpAddr ) ;
HOSTENT * pHostInfo = ::gethostbyaddr( (CHAR *) & ulAddrInNetOrder, sizeof ulAddrInNetOrder, PF_INET ) ; if ( pHostInfo == NULL ) { return ::WSAGetLastError(); }
// copy the name
MBCSToWide(pHostInfo->h_name, strName);
strName.MakeUpper();
int nDot = strName.Find(_T("."));
if (nDot != -1) strHostName = strName.Left(nDot); else strHostName = strName;
return NOERROR; }
/*---------------------------------------------------------------------------
GetHostAddress Description Author: EricDav ---------------------------------------------------------------------------*/ DWORD GetHostAddress ( LPCTSTR pszHostName, DWORD * pdwIp ) { DWORD err = ERROR_SUCCESS; CHAR szString [ 2 * (MAX_PATH + 1)] = {0}; // large enough for a MAX_PATH MBCS encoding
CString strTemp(pszHostName); WideToMBCS(strTemp, szString);
HOSTENT * pHostent = ::gethostbyname( szString ) ;
if ( pHostent ) { *pdwIp = ::ntohl( *((u_long *) pHostent->h_addr_list[0]) ) ; } else { err = ::WSAGetLastError() ; }
return err ; }
//
// This function makes the appropriate call to either WinsStatus or WinsStatusNew
//
CWinsResults::CWinsResults() { NoOfOwners = 0; AddVersMaps.RemoveAll(); MyMaxVersNo.QuadPart = 0; RefreshInterval = 0; TombstoneInterval = 0; TombstoneTimeout = 0; VerifyInterval = 0; WinsPriorityClass = 0; NoOfWorkerThds = 0; memset(&WinsStat, 0, sizeof(WinsStat)); }
CWinsResults::CWinsResults(WINSINTF_RESULTS_T * pwrResults) { Set(pwrResults); }
CWinsResults::CWinsResults(WINSINTF_RESULTS_NEW_T * pwrResults) { Set(pwrResults); }
DWORD CWinsResults::Update(handle_t hBinding) { DWORD err;
//
// First try the new API which does not
// not have the 25 partner limitation. If
// this fails with RPC_S_PROCNUM_OUT_OF_RANGE,
// we know the server is a down-level server,
// and we need to call the old method.
//
err = GetNewConfig(hBinding);
if (err == RPC_S_PROCNUM_OUT_OF_RANGE) { //
// Try old API
//
err = GetConfig(hBinding); }
return err; } DWORD CWinsResults::GetNewConfig(handle_t hBinding) { WINSINTF_RESULTS_NEW_T wrResults;
wrResults.WinsStat.NoOfPnrs = 0; wrResults.WinsStat.pRplPnrs = NULL; wrResults.NoOfWorkerThds = 1; wrResults.pAddVersMaps = NULL;
#ifdef WINS_CLIENT_APIS
DWORD dwStatus = ::WinsStatusNew(hBinding, WINSINTF_E_CONFIG_ALL_MAPS, &wrResults); #else
DWORD dwStatus = ::WinsStatusNew(WINSINTF_E_CONFIG_ALL_MAPS, &wrResults); #endif WINS_CLIENT_APIS
if (dwStatus == ERROR_SUCCESS) { Set(&wrResults); } else { Clear(); }
return dwStatus; }
DWORD CWinsResults::GetConfig(handle_t hBinding) { WINSINTF_RESULTS_T wrResults;
wrResults.WinsStat.NoOfPnrs = 0; wrResults.WinsStat.pRplPnrs = NULL; wrResults.NoOfWorkerThds = 1;
#ifdef WINS_CLIENT_APIS
DWORD dwStatus = ::WinsStatus(hBinding, WINSINTF_E_CONFIG_ALL_MAPS, &wrResults); #else
DWORD dwStatus = ::WinsStatus(WINSINTF_E_CONFIG_ALL_MAPS, &wrResults); #endif WINS_CLIENT_APIS
if (dwStatus == ERROR_SUCCESS) { Set(&wrResults); } else { Clear(); }
return dwStatus; }
void CWinsResults::Clear() { AddVersMaps.RemoveAll();
NoOfOwners = 0; MyMaxVersNo.QuadPart = 0; RefreshInterval = 0; TombstoneInterval = 0; TombstoneTimeout = 0; VerifyInterval = 0; WinsPriorityClass = 0; NoOfWorkerThds = 0; memset(&WinsStat, 0, sizeof(WinsStat)); }
void CWinsResults::Set(WINSINTF_RESULTS_NEW_T * pwrResults) { if (pwrResults) { NoOfOwners = pwrResults->NoOfOwners; AddVersMaps.RemoveAll(); for (UINT i = 0; i < NoOfOwners; i++) { AddVersMaps.Add(pwrResults->pAddVersMaps[i]); }
MyMaxVersNo.QuadPart = pwrResults->MyMaxVersNo.QuadPart; RefreshInterval = pwrResults->RefreshInterval; TombstoneInterval = pwrResults->TombstoneInterval; TombstoneTimeout = pwrResults->TombstoneTimeout; VerifyInterval = pwrResults->VerifyInterval; WinsPriorityClass = pwrResults->WinsPriorityClass; NoOfWorkerThds = pwrResults->NoOfWorkerThds; WinsStat = pwrResults->WinsStat; } }
void CWinsResults::Set(WINSINTF_RESULTS_T * pwrResults) { if (pwrResults == NULL) { Clear(); } else { NoOfOwners = pwrResults->NoOfOwners; AddVersMaps.RemoveAll();
for (UINT i = 0; i < NoOfOwners; i++) { AddVersMaps.Add(pwrResults->AddVersMaps[i]); }
MyMaxVersNo.QuadPart = pwrResults->MyMaxVersNo.QuadPart; RefreshInterval = pwrResults->RefreshInterval; TombstoneInterval = pwrResults->TombstoneInterval; TombstoneTimeout = pwrResults->TombstoneTimeout; VerifyInterval = pwrResults->VerifyInterval; WinsPriorityClass = pwrResults->WinsPriorityClass; NoOfWorkerThds = pwrResults->NoOfWorkerThds; WinsStat = pwrResults->WinsStat; } }
|