|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995.
//
// File: cpdccach.cxx
//
// Contents: PDC Names Cache functionality for the WinNT Provider
//
// Functions:
// CObjNameCache::addentry
// CObjNameCache::findentry
// CObjNameCache::getentry
// CProperyCache::CObjNameCache
// CObjNameCache::~CObjNameCache
// CObjNameCache::CreateClassCache
//
// History: 25-Apr-96 KrishnaG Created.
// 30-Aug-96 RamV Permit cache to store values
// other than PDC names
//
//----------------------------------------------------------------------------
#include "winnt.hxx"
//
// Definition for DsGetDcName on 4.0
//
typedef DWORD (*PF_DsGetDcName) ( IN LPCWSTR ComputerName OPTIONAL, IN LPCWSTR DomainName OPTIONAL, IN GUID *DomainGuid OPTIONAL, IN LPCWSTR SiteName OPTIONAL, IN ULONG Flags, OUT PDOMAIN_CONTROLLER_INFO *DomainControllerInfo );
#ifdef UNICODE
#define GETDCNAME_API "DsGetDcNameW"
#else
#define GETDCNAME_API "DsGetDcNameA"
#endif
//
// DsGetDc will be called if applicabel if not we will look
// at the flags and decide if we should call NetGetAnyDCName or
// NetGetDCName - AjayR 11-04-98.
// Note the code below is not exactly "elegant" but I cannot think
// of any other way to build on 4.0, 95 and NT. Please play close
// attention to the #ifdefs when reading.
//
HRESULT DsGetDcNameNTWrapper( IN LPCWSTR DomainName, OUT LPWSTR *ppszServerName, IN ULONG Flags ) { LPCWSTR ComputerName = NULL; GUID *DomainGuid = NULL; LPCWSTR SiteName = NULL; PDOMAIN_CONTROLLER_INFO pDomainControllerInfo = NULL; DWORD dwStatus = NULL; LPWSTR pszNetServerName = NULL; HRESULT hr = S_OK; ULONG ulDsGetDCFlags = DS_RETURN_FLAT_NAME | DS_WRITABLE_REQUIRED;
if (Flags & ADS_READONLY_SERVER) { ulDsGetDCFlags &= ~DS_WRITABLE_REQUIRED; }
*ppszServerName = NULL;
static PF_DsGetDcName pfDsGetDcName = NULL ;
//
// Load the function if necessary
//
if (pfDsGetDcName == NULL) { pfDsGetDcName = (PF_DsGetDcName) LoadNetApi32Function(GETDCNAME_API) ; }
if (pfDsGetDcName != NULL) {
dwStatus = ((*pfDsGetDcName)( ComputerName, DomainName, DomainGuid, SiteName, ulDsGetDCFlags, &pDomainControllerInfo ) );
if (dwStatus == NO_ERROR) { *ppszServerName = AllocADsStr( pDomainControllerInfo->DomainControllerName );
if (!*ppszServerName) hr = E_OUTOFMEMORY;
} else { hr = HRESULT_FROM_WIN32(dwStatus); }
} else { //
// Could not load library
//
if (Flags & ADS_READONLY_SERVER) {
#ifdef WIN95
dwStatus = NetGetDCName( NULL, DomainName, (LPBYTE *)&pszNetServerName ); #else
dwStatus = NetGetAnyDCName( NULL, DomainName, (LPBYTE *)&pszNetServerName ); #endif
} else {
dwStatus = NetGetDCName( NULL, DomainName, (LPBYTE *)&pszNetServerName ); }
if (dwStatus == NO_ERROR) { *ppszServerName = AllocADsStr( pszNetServerName );
if (!*ppszServerName) hr = E_OUTOFMEMORY;
} else {
hr = HRESULT_FROM_WIN32(dwStatus);
}
}
if (pszNetServerName) { (void) NetApiBufferFree( (void*) pszNetServerName); }
if (pDomainControllerInfo) { (void) NetApiBufferFree(pDomainControllerInfo); }
RRETURN(hr); }
//+------------------------------------------------------------------------
//
// Function: CObjNameCache::addentry
//
// Synopsis:
//
//
//
// Arguments: [pszDomainName] --
// [pszPDCName] --
// [pClassEntry] --
//
//
//-------------------------------------------------------------------------
HRESULT CObjNameCache:: addentry( LPWSTR pszElementName, BOOL fCacheHit, DWORD dwElementType, LPWSTR pszName ) {
//
// The parameter pszName is either the Domain/Wkgrp Name (if dwElementType
// = COMPUTER_ENTRY_TYPE) and PDC Name (if dwElementType is
// DOMAIN_ENTRY_TYPE). it will be a blank string if dwElementType is
// WORKGROUP_ENTRY_TYPE
//
// we will support adding cache hits/misses.
//
HRESULT hr = S_OK; DWORD i = 0; DWORD dwLRUEntry = 0; DWORD dwIndex = 0;
EnterCriticalSection(&_cs);
//
// before adding entries, let us clean out all existing old entries
//
if (_dwMaxCacheSize == 0){ hr = E_FAIL; goto error; }
hr = InvalidateStaleEntries(); BAIL_ON_FAILURE(hr);
hr = findentry( pszElementName, &dwIndex );
//
// if you find an entry then you cannot add it to the cache
//
if(SUCCEEDED(hr)){ goto error; }
hr = S_OK;
for (i = 0; i < _dwMaxCacheSize; i++ ) {
if (!_ClassEntries[i].bInUse) {
//
// Found an available entry; use it
// fill in the name of the entry and related information
// for this class entry
//
break;
} else {
if ((dwLRUEntry == -1) || (i == IsOlderThan(i, dwLRUEntry))){ dwLRUEntry = i; } }
}
if (i == _dwMaxCacheSize){
//
// We have no available entries so we need to use
// the LRUEntry which is busy
//
//
// Free this entry
//
_ClassEntries[dwLRUEntry].bInUse = FALSE;
i = dwLRUEntry; }
//
// Insert the new entry into the Cache
//
_ClassEntries[i].pszElementName = AllocADsStr(pszElementName);
if(_ClassEntries[i].pszElementName == NULL){ hr = E_OUTOFMEMORY; goto error; }
_ClassEntries[i].dwElementType = dwElementType;
if ( fCacheHit){
_ClassEntries[i].fCacheHit = TRUE;
switch(dwElementType) {
case DOMAIN_ENTRY_TYPE:
_ClassEntries[i].u.pszPDCName = AllocADsStr(pszName); if(_ClassEntries[i].u.pszPDCName == NULL){ hr = E_OUTOFMEMORY; goto error; }
break;
case DOMAIN_ENTRY_TYPE_RO: _ClassEntries[i].u.pszDCName = AllocADsStr(pszName); if (_ClassEntries[i].u.pszDCName == NULL) { hr = E_OUTOFMEMORY; goto error; }
break;
case COMPUTER_ENTRY_TYPE:
_ClassEntries[i].u.pszDomainName = AllocADsStr(pszName); if(_ClassEntries[i].u.pszDomainName == NULL){ hr = E_OUTOFMEMORY; goto error; }
break;
default: break;
} } else {
_ClassEntries[i].fCacheHit = FALSE; }
_ClassEntries[i].bInUse = TRUE;
//
// update the time stamp so that we know when this entry was made
//
GetSystemTime(&_ClassEntries[i].st);
error:
LeaveCriticalSection(&_cs);
RRETURN(hr); }
//+------------------------------------------------------------------------
//
// Function: CObjNameCache::findentry
//
// Synopsis:
//
//
//
// Arguments: [szPropertyName] --
// [pdwIndex] --
//
//-------------------------------------------------------------------------
HRESULT CObjNameCache:: findentry( LPWSTR pszElementName, PDWORD pdwIndex ) { DWORD i = 0;
EnterCriticalSection(&_cs);
if (_dwMaxCacheSize == 0 ) {
LeaveCriticalSection(&_cs); RRETURN(E_FAIL); }
for (i = 0; i < _dwMaxCacheSize; i++ ) {
if (_ClassEntries[i].bInUse) {
if(!_ClassEntries[i].pszElementName ){ continue; }
#ifdef WIN95
if (!_wcsicmp(_ClassEntries[i].pszElementName, pszElementName)){ #else
if (CompareStringW( LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, _ClassEntries[i].pszElementName, -1, pszElementName, -1 ) == CSTR_EQUAL ) { #endif
*pdwIndex = i;
LeaveCriticalSection(&_cs);
RRETURN(S_OK);
} } }
LeaveCriticalSection(&_cs);
RRETURN(E_FAIL); }
//+------------------------------------------------------------------------
//
// Function: CObjNameCache::getentry
//
// Synopsis:
//
//
//
// Arguments: [szPropertyName] --
// [pdwIndex] --
//
//-------------------------------------------------------------------------
HRESULT CObjNameCache:: getentry( LPWSTR pszElementName, PBOOL pfHit, PDWORD pdwEntryType, LPWSTR pszName ) { DWORD dwIndex = 0; HRESULT hr = S_OK; DWORD i;
EnterCriticalSection(&_cs);
//
// blow away all the entries that have expired
//
hr = InvalidateStaleEntries(); BAIL_ON_FAILURE(hr);
hr = findentry( pszElementName, &dwIndex ); BAIL_ON_FAILURE(hr);
*pfHit = _ClassEntries[dwIndex].fCacheHit; *pdwEntryType = _ClassEntries[dwIndex].dwElementType;
switch(_ClassEntries[dwIndex].dwElementType) {
case DOMAIN_ENTRY_TYPE: wcscpy(pszName, _ClassEntries[dwIndex].u.pszPDCName); break;
case COMPUTER_ENTRY_TYPE: wcscpy(pszName, _ClassEntries[dwIndex].u.pszDomainName); break;
case DOMAIN_ENTRY_TYPE_RO: wcscpy(pszName, _ClassEntries[dwIndex].u.pszDCName); break;
default: wcscpy(pszName, TEXT("")); break;
}
error:
LeaveCriticalSection(&_cs);
RRETURN(hr);
}
HRESULT CObjNameCache:: InvalidateStaleEntries() {
DWORD i=0; SYSTEMTIME stCurrentTime; BOOL fCacheHit;
GetSystemTime(&stCurrentTime);
for ( i=0; i< _dwMaxCacheSize; i++){
fCacheHit = _ClassEntries[i].fCacheHit;
if(_ClassEntries[i].bInUse && TimeDifference(stCurrentTime, _ClassEntries[i].st) > AGE_LIMIT_VALID_ENTRIES && fCacheHit == CACHE_HIT) {
_ClassEntries[i].bInUse = FALSE; FreeADsStr(_ClassEntries[i].pszElementName); _ClassEntries[i].pszElementName = NULL;
if(_ClassEntries[i].dwElementType == DOMAIN_ENTRY_TYPE){ FreeADsStr(_ClassEntries[i].u.pszPDCName); _ClassEntries[i].u.pszPDCName = NULL;
} else if (_ClassEntries[i].dwElementType == COMPUTER_ENTRY_TYPE){ FreeADsStr(_ClassEntries[i].u.pszDomainName); _ClassEntries[i].u.pszPDCName = NULL;
} }else if(_ClassEntries[i].bInUse && TimeDifference(stCurrentTime, _ClassEntries[i].st) > AGE_LIMIT_INVALID_ENTRIES && fCacheHit == CACHE_MISS) {
_ClassEntries[i].bInUse = FALSE; }
}
RRETURN(S_OK); }
//+------------------------------------------------------------------------
//
// Function: CObjNameCache
//
// Synopsis:
//
//
//
// Arguments:
//
//
//-------------------------------------------------------------------------
CObjNameCache::CObjNameCache() { _dwMaxCacheSize = 10; memset(_ClassEntries, 0, sizeof(CLASSENTRY)* MAX_ENTRIES); }
//+------------------------------------------------------------------------
//
// Function: ~CObjNameCache
//
// Synopsis:
//
//
//
// Arguments:
//
//
//-------------------------------------------------------------------------
CObjNameCache:: ~CObjNameCache() { DWORD i= 0; for (i=0; i< MAX_ENTRIES; i++){ if(_ClassEntries[i].pszElementName){ FreeADsStr(_ClassEntries[i].pszElementName); }
//
// All members of the union are strings so it is not
// necessary to check for each of the members.
//
if(_ClassEntries[i].u.pszPDCName){ FreeADsStr(_ClassEntries[i].u.pszPDCName); } }
DeleteCriticalSection(&_cs);
}
//+------------------------------------------------------------------------
//
// Function:
//
// Synopsis:
//
//
//
// Arguments:
//
//
//-------------------------------------------------------------------------
HRESULT CObjNameCache:: CreateClassCache( CObjNameCache FAR *FAR * ppClassCache ) { CObjNameCache FAR * pClassCache = NULL;
pClassCache = new CObjNameCache();
if (!pClassCache) { RRETURN(E_FAIL); }
InitializeCriticalSection(&(pClassCache->_cs));
*ppClassCache = pClassCache;
RRETURN(S_OK); }
DWORD CObjNameCache:: IsOlderThan( DWORD i, DWORD j ) { SYSTEMTIME *pi, *pj; DWORD iMs, jMs; // DBGMSG(DBG_TRACE, ("IsOlderThan entering with i %d j %d\n", i, j));
pi = &(_ClassEntries[i].st); pj = &(_ClassEntries[j].st);
if (pi->wYear < pj->wYear) { // DBGMSG(DBG_TRACE, ("IsOlderThan returns %d\n", i));
return(i); } else if (pi->wYear > pj->wYear) { // DBGMSG(DBG_TRACE, ("IsOlderThan returns %d\n", j));
return(j); } else if (pi->wMonth < pj->wMonth) { // DBGMSG(DBG_TRACE, ("IsOlderThan returns %d\n", i));
return(i); } else if (pi->wMonth > pj->wMonth) { // DBGMSG(DBG_TRACE, ("IsOlderThan returns %d\n", j));
return(j); } else if (pi->wDay < pj->wDay) { // DBGMSG(DBG_TRACE, ("IsOlderThan returns %d\n", i));
return(i); } else if (pi->wDay > pj->wDay) { // DBGMSG(DBG_TRACE, ("IsOlderThan returns %d\n", j));
return(j); } else { iMs = ((((pi->wHour * 60) + pi->wMinute)*60) + pi->wSecond)* 1000 + pi->wMilliseconds; jMs = ((((pj->wHour * 60) + pj->wMinute)*60) + pj->wSecond)* 1000 + pj->wMilliseconds;
if (iMs <= jMs) { // DBGMSG(DBG_TRACE, ("IsOlderThan returns %d\n", i));
return(i); } else { // DBGMSG(DBG_TRACE, ("IsOlderThan returns %d\n", j));
return(j); } } }
HRESULT WinNTGetCachedDCName( LPWSTR pszDomainName, LPWSTR pszPDCName, DWORD dwFlags ) { WCHAR szSAMName[MAX_PATH];
// In this case credentials do not help because we do not have
// any server/domain to connect to. This is because the param
// pszDomainName is not a domain name for certain.
CWinNTCredentials nullCredentials;
// We do want to copy the flags parameter as that will tell
// us if we need to connect to PDC or not
nullCredentials.SetFlags(dwFlags);
RRETURN(WinNTGetCachedObject(pszDomainName, DOMAIN_ENTRY_TYPE, pszPDCName, szSAMName, dwFlags, nullCredentials )); }
HRESULT WinNTGetCachedComputerName( LPWSTR pszComputerName, LPWSTR pszName, LPWSTR pszSAMName, CWinNTCredentials& Credentials ) {
RRETURN(WinNTGetCachedObject(pszComputerName, COMPUTER_ENTRY_TYPE, pszName, pszSAMName, Credentials.GetFlags(), // doesnt matter
Credentials ));
}
HRESULT WinNTGetCachedObject( LPWSTR pszElementName, DWORD dwElementType, LPWSTR pszName, LPWSTR pszSAMName, DWORD dwFlags, CWinNTCredentials& Credentials ) { HRESULT hr = S_OK; NET_API_STATUS nasStatus = 0; BOOL fCacheHit; DWORD dwEntryType; LPWKSTA_INFO_100 lpWI = NULL; DWORD dwObjectsReturned; DWORD dwObjectsTotal; DWORD dwResumeHandle; // Freed using NetAPI
LPWSTR pszServerName = NULL; // Freed using FreeADsStr
LPWSTR pszADsStrServerName = NULL; BOOL fRefAdded = FALSE; DWORD dwDomainEntryType = DOMAIN_ENTRY_TYPE; // This will be the case most often
DWORD dwUserFlags = Credentials.GetFlags(); DSROLE_PRIMARY_DOMAIN_INFO_BASIC* pdomainInfo = NULL;
hr = pgPDCNameCache->getentry( pszElementName, &fCacheHit, &dwEntryType, pszName );
if (SUCCEEDED(hr)) { //
// we found the entry. Now need to verify that it indeed
// is an object of type desired
//
// Note that dwElement type will never be DOMAIN_ENTRY_TYPE_RO
if(fCacheHit) { if (dwEntryType == dwElementType || ((dwElementType == DOMAIN_ENTRY_TYPE) && (dwEntryType == DOMAIN_ENTRY_TYPE_RO) && (dwUserFlags & ADS_READONLY_SERVER)) ) {
//
// If the user now needs a writeable connection
// should we fail or should we actually pretend
// that the object is not there in the cache.
//
hr = S_OK; goto error;
}
} else if (!fCacheHit && (dwElementType == WORKGROUP_ENTRY_TYPE)) { //
// looks like we either found a cache miss
// Return ok
//
hr = S_OK; goto error;
} else {
hr = E_FAIL; goto error;
}
} switch(dwElementType){
case DOMAIN_ENTRY_TYPE:
//
// A read only server is ok, need to also set the
// domain entry type accordingly
//
if (dwFlags & ADS_READONLY_SERVER) { dwDomainEntryType = DOMAIN_ENTRY_TYPE_RO; }
//
// Call the all encompassing Wrapper.
//
hr = DsGetDcNameNTWrapper( pszElementName, &pszADsStrServerName, dwFlags );
BAIL_ON_FAILURE(hr);
hr = pgPDCNameCache->addentry( pszElementName, TRUE, dwDomainEntryType, pszADsStrServerName );
BAIL_ON_FAILURE(hr); //
// in addition we can also add a computer entry for the PDC
//
hr = pgPDCNameCache->addentry( pszADsStrServerName+2, // to get rid of the leading backslashes
TRUE, COMPUTER_ENTRY_TYPE, pszElementName );
BAIL_ON_FAILURE(hr);
wcscpy(pszName, pszADsStrServerName);
break;
case COMPUTER_ENTRY_TYPE:
// Ref the computer, note that RefServer will not
// do anything if the credentials are null. We are also
// not worried about errors as we want to use default
// credentials in that case.
hr = Credentials.RefServer(pszElementName);
if (SUCCEEDED(hr)) { fRefAdded = TRUE; }
nasStatus = NetWkstaGetInfo( pszElementName, 100, (LPBYTE*) &lpWI );
hr = HRESULT_FROM_WIN32(nasStatus); BAIL_ON_FAILURE(hr);
#ifdef WIN95
//
// No NetpNameCompare for Win9x
//
if (lpWI->wki100_computername && (_wcsicmp(pszElementName, lpWI->wki100_computername) == 0) ) #else
if (lpWI->wki100_computername && ( NetpNameCompare( NULL, pszElementName, lpWI->wki100_computername, NAMETYPE_COMPUTER, 0 ) == 0 ) ) #endif
{
// Want to add the correct capitalized name
// Not what the user gave
hr = pgPDCNameCache->addentry( lpWI->wki100_computername, TRUE, COMPUTER_ENTRY_TYPE, lpWI->wki100_langroup );
wcscpy(pszSAMName, lpWI->wki100_computername);
} else {
//
// user actually passes in ipaddress as the computer name
//
if(IsAddressNumeric(pszElementName)) { hr = pgPDCNameCache->addentry( pszElementName, TRUE, COMPUTER_ENTRY_TYPE, lpWI->wki100_langroup );
wcscpy(pszSAMName, L""); } //
// user may pass in the dns name of the computer
//
else { hr = HRESULT_FROM_WIN32(DsRoleGetPrimaryDomainInformation( pszElementName, DsRolePrimaryDomainInfoBasic, // InfoLevel
(PBYTE*)&pdomainInfo // pBuffer
)); if(SUCCEEDED(hr)) { if(((pdomainInfo->DomainNameDns) && _wcsicmp(pszElementName, pdomainInfo->DomainNameDns) == 0) || ((pdomainInfo->DomainNameFlat) && NetpNameCompare( NULL, pszElementName, pdomainInfo->DomainNameFlat, NAMETYPE_COMPUTER, 0 ) == 0) ) { BAIL_ON_FAILURE(hr=HRESULT_FROM_WIN32(ERROR_BAD_NETPATH)); } else { hr = pgPDCNameCache->addentry( pszElementName, TRUE, COMPUTER_ENTRY_TYPE, lpWI->wki100_langroup );
wcscpy(pszSAMName, L""); } } else { BAIL_ON_FAILURE(hr=HRESULT_FROM_WIN32(ERROR_BAD_NETPATH)); } } } wcscpy(pszName, lpWI->wki100_langroup); break;
default: hr = E_FAIL; break; }
error:
if (fRefAdded) { Credentials.DeRefServer(); // even if we fail, we have no recovery path
fRefAdded = FALSE; }
if(lpWI){ NetApiBufferFree(lpWI); }
if(pszServerName){ NetApiBufferFree(pszServerName); }
if (pszADsStrServerName) { FreeADsStr(pszADsStrServerName); }
if ( pdomainInfo ) { DsRoleFreeMemory(pdomainInfo); }
RRETURN(hr); }
//+------------------------------------------------------------------------
//
// Function:
//
// Synopsis:
// This function is called by Heuristic GetObject to identify what
// kind of object we are dealing with. Here we try to get a cached
// entry if it is a hit/miss. If it fails, then we try each kind
// of object in turn. (Domain/Computer/Workgroup). Once we do this,
// we cache this information internally
//
//
//
// Arguments:
//
//
//-------------------------------------------------------------------------
HRESULT WinNTGetCachedName( LPWSTR pszElementName, PDWORD pdwElementType, LPWSTR pszName, LPWSTR pszSAMName, CWinNTCredentials& Credentials ) { HRESULT hr = S_OK; BOOL fCacheHit; DWORD dwEntryType; WCHAR szSAMName[MAX_ADS_PATH]; BOOL fRefAdded = FALSE; DWORD dwUserFlags = Credentials.GetFlags();
szSAMName[0] = L'\0';
if (!pszElementName || !*pszElementName) { RRETURN(E_FAIL); }
hr = pgPDCNameCache->getentry( pszElementName, &fCacheHit, &dwEntryType, pszName );
if (SUCCEEDED(hr)) { //
// we found the entry.
//
if (!fCacheHit){ //
// cache miss saved as a workgroup
//
*pdwElementType = WORKGROUP_ENTRY_TYPE; goto error;
} else { if(dwEntryType == DOMAIN_ENTRY_TYPE_RO) { if(dwUserFlags & ADS_READONLY_SERVER) { // HeuristicGetObj doesn't recognize DOMAIN_ENTRY_TYPE_RO
*pdwElementType = DOMAIN_ENTRY_TYPE; goto error; } } else { *pdwElementType = dwEntryType; goto error; } }
}
{
// at this point, we can try and ref the domain as
// we are looking to bind to the domain
hr = Credentials.RefDomain(pszElementName); // note that even if this fails we want to continue
// as there is the chance that the current users
// credentials are good enough for the operation
if (SUCCEEDED(hr)) { fRefAdded = TRUE; }
hr = WinNTGetCachedObject( pszElementName, DOMAIN_ENTRY_TYPE, pszName, szSAMName, Credentials.GetFlags(), Credentials );
if (fRefAdded) { Credentials.DeRefDomain(); // we cannot really do anything useful with HR
fRefAdded = FALSE; }
if (SUCCEEDED(hr)){ *pdwElementType = DOMAIN_ENTRY_TYPE; wcscpy(pszSAMName, szSAMName); RRETURN(hr); }
hr = WinNTGetCachedObject( pszElementName, COMPUTER_ENTRY_TYPE, pszName, szSAMName, Credentials.GetFlags(), Credentials );
if (SUCCEEDED(hr)){ *pdwElementType = COMPUTER_ENTRY_TYPE; wcscpy(pszSAMName, szSAMName); RRETURN(hr); }
//
// if you are here, it means that you have to cache a miss as a
// workgroup.
// Note that pszSAMName rather than pszElementName is added
// if it is valid
// AjayR - to handle the no workstation case,
// We should not add anything if the error was NOWksta service
if (hr != HRESULT_FROM_WIN32(NERR_WkstaNotStarted)) {
if (szSAMName[0] != L'\0') {
hr = pgPDCNameCache->addentry( szSAMName, FALSE, WORKGROUP_ENTRY_TYPE, TEXT("") );
} else {
hr = pgPDCNameCache->addentry( pszElementName, FALSE, WORKGROUP_ENTRY_TYPE, TEXT("") );
} } // No Wksta started
*pdwElementType = WORKGROUP_ENTRY_TYPE; wcscpy(pszName, TEXT("")); goto error; }
error: RRETURN(hr); }
LONG TimeDifference( SYSTEMTIME st1, SYSTEMTIME st2 )
{ //
// This function gives the difference between st1 and st2 (st1-st2)in secs.
// This will be used by our internal cache object so as to find out if
// a certain entry in the cache is too old.
// Assumption: st1 is later than st2.
DWORD dwTime1; DWORD dwTime2; DWORD dwMonth1; DWORD dwMonth2; LONG lRetval; //
// Ignore milliseconds because it is immaterial for our purposes
//
dwTime1= st1.wSecond + 60 * (st1.wMinute + 60* (st1.wHour + 24 * (st1.wDay)));
dwTime2= st2.wSecond + 60 * (st2.wMinute + 60* (st2.wHour + 24 * (st2.wDay)));
if (dwTime1 == dwTime2) { return(0); }
if (dwTime1 > dwTime2 && (st1.wMonth == st2.wMonth) && st1.wYear == st2.wYear) { lRetval = (LONG)(dwTime1-dwTime2); goto cleanup; }
dwMonth1 = 12*st1.wYear+ st1.wMonth; dwMonth2 = 12*st2.wYear+ st2.wMonth;
if (dwMonth1 < dwMonth2) { //
// looks like we got a bogus value. return -1
//
lRetval = -1; goto cleanup; }
//
// if there is a month difference of more than 1 then we return
// a large positive number (0xFFFFFFF)
//
if (dwMonth1 > dwMonth2+1) { lRetval = 0xFFFFFFF; goto cleanup; }
//
// we crossed a month boundary
//
dwTime1= st1.wSecond + 60 * (st1.wMinute + 60* (st1.wHour));
dwTime2= st2.wSecond + 60 * (st2.wMinute);
lRetval = ( dwTime2- dwTime1 + 60*60*24); goto cleanup;
cleanup: return(lRetval); }
BOOL IsAddressNumeric( LPWSTR HostName ) { BOOLEAN rc = FALSE;
//
// to check to see if it's a TCP address, we check for it to only
// contain only numerals and periods.
//
while (((*HostName >= L'0') && (*HostName <= L'9')) || (*HostName == L'.')) { HostName++; }
//
// if we hit the end of the hostname, then it's an address.
//
if (*HostName == L'\0' || *HostName == L':') {
rc = TRUE; } return rc;
}
|