|
|
//+-----------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996-1996
//
// File: srvlist.cpp
//
// Contents: List of registed server
//
// History: 09-09-98 HueiWang Created
//
//-------------------------------------------------------------
#include "pch.cpp"
#include "srvlist.h"
#include "globals.h"
#include "srvdef.h"
#define STRSAFE_NO_DEPRECATE
#include "strsafe.h"
CTLServerMgr g_ServerMgr;
///////////////////////////////////////////////////////////////
DWORD GetPageSize( VOID ) {
static DWORD dwPageSize = 0;
if ( !dwPageSize ) {
SYSTEM_INFO sysInfo = { 0 }; GetSystemInfo( &sysInfo ); // cannot fail.
dwPageSize = sysInfo.dwPageSize;
}
return dwPageSize;
}
/*++**************************************************************
NAME: MyVirtualAlloc
as Malloc, but automatically protects the last page of the allocation. This simulates pageheap behavior without requiring it.
MODIFIES: ppvData -- receives memory
TAKES: dwSize -- minimum amount of data to get
RETURNS: TRUE when the function succeeds. FALSE otherwise. LASTERROR: not set Free with MyVirtualFree
**************************************************************--*/
BOOL MyVirtualAlloc( IN DWORD dwSize, OUT PVOID *ppvData ) {
PBYTE pbData; DWORD dwTotalSize; PVOID pvLastPage;
// ensure that we allocate one extra page
dwTotalSize = dwSize / GetPageSize(); if( dwSize % GetPageSize() ) { dwTotalSize ++; }
// this is the guard page
dwTotalSize++; dwTotalSize *= GetPageSize();
// do the alloc
pbData = (PBYTE) VirtualAlloc( NULL, // don't care where
dwTotalSize, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE ); if ( pbData ) {
pbData += dwTotalSize;
// find the LAST page.
pbData -= GetPageSize();
pvLastPage = pbData;
// now, carve out a chunk for the caller:
pbData -= dwSize;
// last, protect the last page:
if ( VirtualProtect( pvLastPage, 1, // protect the page containing the last byte
PAGE_NOACCESS, &dwSize ) ) {
*ppvData = pbData; return TRUE;
}
VirtualFree( pbData, 0, MEM_RELEASE );
}
return FALSE;
}
VOID MyVirtualFree( IN PVOID pvData ) {
VirtualFree( pvData, 0, MEM_RELEASE );
}
///////////////////////////////////////////////////////////////
RPC_STATUS TryLookupServer(PCONTEXT_HANDLE hBinding, LPTSTR pszLookupSetupId, LPTSTR *pszLsSetupId, LPTSTR *pszDomainName, LPTSTR *pszLsName, PDWORD pdwErrCode) { RPC_STATUS status; DWORD dwErrCode;
status = TLSLookupServerFixed(hBinding, pszLookupSetupId, pszLsSetupId, pszDomainName, pszLsName, pdwErrCode);
if(status != RPC_S_OK) {
LPTSTR lpszSetupId = NULL; LPTSTR lpszDomainName = NULL; LPTSTR lpszServerName = NULL; status = ERROR_NOACCESS;
size_t cbError; try { if ( !MyVirtualAlloc( (LSERVER_MAX_STRING_SIZE+2) * sizeof( TCHAR ), (PVOID*) &lpszSetupId ) ) { return RPC_S_OUT_OF_MEMORY; }
memset(lpszSetupId, 0, ( LSERVER_MAX_STRING_SIZE +2 ) * sizeof( TCHAR ));
if ( !MyVirtualAlloc( (LSERVER_MAX_STRING_SIZE+2) * sizeof( TCHAR ), (PVOID*) &lpszDomainName ) ) { status = RPC_S_OUT_OF_MEMORY; goto cleanup; }
memset(lpszDomainName, 0, ( LSERVER_MAX_STRING_SIZE +2 ) * sizeof( TCHAR ));
if ( !MyVirtualAlloc( (MAX_COMPUTERNAME_LENGTH+2) * sizeof( TCHAR ), (PVOID*) &lpszServerName ) ) { status = RPC_S_OUT_OF_MEMORY; goto cleanup; }
memset(lpszServerName, 0, ( MAX_COMPUTERNAME_LENGTH +2 ) * sizeof( TCHAR ));
DWORD cbSetupId = LSERVER_MAX_STRING_SIZE+1; DWORD cbDomainName = LSERVER_MAX_STRING_SIZE+1; DWORD cbServerName = MAX_COMPUTERNAME_LENGTH+1; status = TLSLookupServer(hBinding, pszLookupSetupId, lpszSetupId, &cbSetupId, lpszDomainName, &cbDomainName, lpszServerName, &cbServerName, pdwErrCode);
if((status == RPC_S_OK) && (pdwErrCode != NULL) && (*pdwErrCode == ERROR_SUCCESS)) { if (NULL != pszLsSetupId) { size_t cb;
if (SUCCEEDED(StringCbLength(lpszSetupId,cbSetupId,&cb))) { *pszLsSetupId = (LPTSTR) MIDL_user_allocate(cb+sizeof(TCHAR)); if (NULL != *pszLsSetupId) { lstrcpy(*pszLsSetupId,lpszSetupId); } else { status = RPC_S_OUT_OF_MEMORY; goto cleanup; } } else { status = RPC_S_INVALID_ARG; goto cleanup; } }
if (NULL != pszDomainName) { size_t cb;
if (SUCCEEDED(StringCbLength(lpszDomainName,cbDomainName,&cb))) { *pszDomainName = (LPTSTR) MIDL_user_allocate(cb+sizeof(TCHAR)); if (NULL != *pszDomainName) { lstrcpy(*pszDomainName,lpszDomainName); } else { MIDL_user_free(*pszLsSetupId); status = RPC_S_OUT_OF_MEMORY; goto cleanup; } } else { MIDL_user_free(*pszLsSetupId); status = RPC_S_INVALID_ARG; goto cleanup; } }
if (NULL != pszLsName) { size_t cb;
if (SUCCEEDED(StringCbLength(lpszServerName,cbServerName,&cb))) { *pszLsName = (LPTSTR) MIDL_user_allocate(cb+sizeof(TCHAR)); if (NULL != *pszLsName) { lstrcpy(*pszLsName,lpszServerName); } else { MIDL_user_free(*pszLsSetupId); MIDL_user_free(*pszDomainName); status = RPC_S_OUT_OF_MEMORY; goto cleanup; } } else { MIDL_user_free(*pszLsSetupId); MIDL_user_free(*pszDomainName); status = RPC_S_INVALID_ARG; goto cleanup; } } } } catch (...) { status = ERROR_NOACCESS; } cleanup: if(lpszSetupId) MyVirtualFree(lpszSetupId);
if(lpszDomainName) MyVirtualFree(lpszDomainName);
if(lpszServerName) MyVirtualFree(lpszServerName); }
return status; }
RPC_STATUS TryGetServerName(PCONTEXT_HANDLE hBinding, LPTSTR *pszServer, DWORD *pdwErrCode) { RPC_STATUS status;
status = TLSGetServerNameFixed(hBinding,pszServer,pdwErrCode);
if (status != RPC_S_OK) { LPTSTR lpszMachineName = NULL;
try { if ( !MyVirtualAlloc( ( MAX_COMPUTERNAME_LENGTH+1 ) * sizeof( TCHAR ), (PVOID*) &lpszMachineName ) ) { return RPC_S_OUT_OF_MEMORY; }
DWORD uSize = MAX_COMPUTERNAME_LENGTH+1 ;
memset(lpszMachineName, 0, ( MAX_COMPUTERNAME_LENGTH+1 ) * sizeof( TCHAR ));
status = TLSGetServerNameEx(hBinding, lpszMachineName, &uSize, pdwErrCode);
if((status == RPC_S_OK) && (pdwErrCode != NULL) && (*pdwErrCode == ERROR_SUCCESS)) { size_t cb;
if (SUCCEEDED(StringCbLength(lpszMachineName,( MAX_COMPUTERNAME_LENGTH+1 ) * sizeof( TCHAR ),&cb))) { *pszServer = (LPTSTR) MIDL_user_allocate(cb+sizeof(TCHAR));
if (NULL != *pszServer) { lstrcpy(*pszServer,lpszMachineName); } else { status = RPC_S_OUT_OF_MEMORY; } } else { status = RPC_S_INVALID_ARG; } } } catch(...) { status = ERROR_NOACCESS; } if(lpszMachineName) MyVirtualFree(lpszMachineName); }
return status; }
RPC_STATUS TryGetServerScope(PCONTEXT_HANDLE hBinding, LPTSTR *pszScope, DWORD *pdwErrCode) { RPC_STATUS status;
status = TLSGetServerScopeFixed(hBinding,pszScope,pdwErrCode);
if (status != RPC_S_OK) { LPTSTR lpszScope = NULL; DWORD uSize = LSERVER_MAX_STRING_SIZE + 2;
try { if ( !MyVirtualAlloc( ( LSERVER_MAX_STRING_SIZE + 2 ) * sizeof( TCHAR ), (PVOID*) &lpszScope ) ) { return RPC_S_OUT_OF_MEMORY; }
memset(lpszScope, 0, ( LSERVER_MAX_STRING_SIZE + 2 ) * sizeof( TCHAR ));
status = TLSGetServerScope(hBinding, lpszScope, &uSize, pdwErrCode); if((status == RPC_S_OK) && (pdwErrCode != NULL) && (*pdwErrCode == ERROR_SUCCESS)) { size_t cb;
if (SUCCEEDED(StringCbLength(lpszScope, ( LSERVER_MAX_STRING_SIZE + 2 ) * sizeof( TCHAR ), &cb))) { *pszScope = (LPTSTR) MIDL_user_allocate(cb+sizeof(TCHAR));
if (NULL != *pszScope) { lstrcpy(*pszScope,lpszScope); } else { status = RPC_S_OUT_OF_MEMORY; } } else { status = RPC_S_INVALID_ARG; } } } catch(...) { status = ERROR_NOACCESS; }
if(lpszScope) MyVirtualFree(lpszScope);
}
return status; }
DWORD TLSResolveServerIdToServer( LPTSTR pszServerId, DWORD cbServerName, LPTSTR pszServerName ) /*++
--*/ { DWORD dwStatus = ERROR_SUCCESS; TLS_HANDLE hEServer = NULL; TLServerInfo EServerInfo; DWORD dwErrCode;
TCHAR *szSetupId = NULL; TCHAR *szDomainName = NULL; TCHAR *szServerName = NULL;
dwStatus = TLSLookupServerById( pszServerId, pszServerName );
if(dwStatus != ERROR_SUCCESS) { // try to resolve server name with enterprise server
dwStatus = TLSLookupAnyEnterpriseServer(&EServerInfo); if(dwStatus == ERROR_SUCCESS) { hEServer = TLSConnectAndEstablishTrust( EServerInfo.GetServerName(), NULL ); if(hEServer != NULL) { dwStatus = TryLookupServer( hEServer, pszServerId, &szSetupId, &szDomainName, &szServerName, &dwErrCode );
if(dwStatus == ERROR_SUCCESS && dwErrCode == ERROR_SUCCESS) { StringCbCopy(pszServerName, cbServerName, szServerName);
MIDL_user_free(szSetupId); MIDL_user_free(szDomainName); MIDL_user_free(szServerName); } } } }
if(hEServer != NULL) { TLSDisconnectFromServer(hEServer); }
return dwStatus; }
///////////////////////////////////////////////////////////////
DWORD TLSAnnounceServerToRemoteServerWithHandle( IN DWORD dwAnnounceType, IN TLS_HANDLE hHandle, IN LPTSTR pszLocalSetupId, IN LPTSTR pszLocalDomainName, IN LPTSTR pszLocalServerName, IN FILETIME* pftLocalLastShutdownTime ) /*++
Abstract:
Announce to a license server that already connected.
Parameters:
dwAnnounceType : Announcement type, currently define are startup, and response. hHandle : Connection handle to remote server. pszLocalSetupId : Local server's setup ID. pszLocalDomainName : Local server's domain name. pszLocalServerName : Local server name. pftLocalLastShutdownTime : Pointer to FILETIME, local server's last shutdown time.
Returns:
ERROR_SUCCESS or error code.
--*/ { DWORD dwStatus; DWORD dwErrCode; TLServerInfo ServerInfo;
if(hHandle == NULL) { SetLastError(dwStatus = ERROR_INVALID_PARAMETER); return dwStatus; }
//
// First, try to register to server list manager.
//
dwStatus = TLSRegisterServerWithHandle( hHandle, &ServerInfo ); if(dwStatus != ERROR_SUCCESS) { return dwStatus; }
dwErrCode = LSERVER_E_LASTERROR + 1;
//
// RPC call to announce server
//
dwStatus = TLSAnnounceServer( hHandle, dwAnnounceType, pftLocalLastShutdownTime, pszLocalSetupId, (pszLocalDomainName) ? _TEXT("") : pszLocalDomainName, pszLocalServerName, &dwErrCode );
if(dwStatus == ERROR_SUCCESS) { ServerInfo.m_dwPushAnnounceTimes++;
//
// Update how many time we have announce to
// this server.
TLSRegisterServerWithServerInfo(&ServerInfo); }
if(dwStatus == ERROR_SUCCESS && dwErrCode >= LSERVER_ERROR_BASE) { TLSLogEvent( EVENTLOG_INFORMATION_TYPE, TLS_E_SERVERTOSERVER, TLS_E_UNEXPECTED_RETURN, ServerInfo.GetServerName(), (dwErrCode < LSERVER_E_LASTERROR) ? dwErrCode : LSERVER_ERROR_BASE );
SetLastError(dwStatus = dwErrCode); }
return dwStatus; }
///////////////////////////////////////////////////////////////
DWORD TLSAnnounceServerToRemoteServer( IN DWORD dwAnnounceType, IN LPTSTR pszRemoteSetupId, IN LPTSTR pszRemoteDomainName, IN LPTSTR pszRemoteServerName, IN LPTSTR pszLocalSetupId, IN LPTSTR pszLocalDomainName, IN LPTSTR pszLocalServerName, IN FILETIME* pftLocalLastShutdownTime ) /*++
Abstract:
Similar to TLSAnnounceServerToRemoteServerWithHandle() except we haven't have make any connection to this server yet.
Parameter:
dwAnnounceType : Announce type. pszRemoteSetupId : Remote server's setup ID. pszRemoteDomainName : Remote server's domain. pszRemoteServerName : Remote server's name. pszLocalSetupId : Local server setup ID. pszLocalDomainName : Local server's domain. pszLocalServerName : Local server's name. pftLocalLastShutdownTime : Local server last shutdown time.
Returns:
ERROR_SUCCESS or error code.
--*/ { TLServerInfo RemoteServer; DWORD dwStatus = ERROR_SUCCESS; DWORD dwErrCode = ERROR_SUCCESS;
HANDLE hHandle = NULL;
//
// Always try to register with local list.
//
dwStatus = TLSRegisterServerWithName( pszRemoteSetupId, pszRemoteDomainName, pszRemoteServerName ); if(dwStatus != ERROR_SUCCESS && dwStatus != TLS_E_DUPLICATE_RECORD ) { return dwStatus; }
//
// Query again to make sure we have it in our server list.
//
dwStatus = TLSLookupRegisteredServer( pszRemoteSetupId, pszRemoteDomainName, pszRemoteServerName, &RemoteServer ); if(dwStatus != ERROR_SUCCESS) { dwStatus = TLS_E_INTERNAL; TLSASSERT(FALSE); return dwStatus; }
//
// Establish trust with remote server.
//
hHandle = TLSConnectAndEstablishTrust( RemoteServer.GetServerName(), NULL );
if(hHandle != NULL) { dwErrCode = LSERVER_E_LASTERROR + 1;
//
// Announce server
//
dwStatus = TLSAnnounceServer( hHandle, dwAnnounceType, pftLocalLastShutdownTime, pszLocalSetupId, (pszLocalDomainName) ? _TEXT("") : pszLocalDomainName, pszLocalServerName, &dwErrCode );
if(dwStatus == ERROR_SUCCESS) { RemoteServer.m_dwPushAnnounceTimes++;
// update announce time.
TLSRegisterServerWithServerInfo(&RemoteServer); }
if(dwStatus == ERROR_SUCCESS && dwErrCode >= LSERVER_ERROR_BASE) { TLSLogEvent( EVENTLOG_INFORMATION_TYPE, TLS_E_SERVERTOSERVER, TLS_E_UNEXPECTED_RETURN, RemoteServer.GetServerName(), (dwErrCode <= LSERVER_E_LASTERROR) ? dwErrCode : LSERVER_ERROR_BASE );
SetLastError(dwStatus = dwErrCode); } }
if(hHandle != NULL) { TLSDisconnectFromServer(hHandle); hHandle = NULL; }
return dwStatus; }
///////////////////////////////////////////////////////////////
TLS_HANDLE TLSConnectAndEstablishTrust( IN LPTSTR pszServerName, IN HANDLE hHandle ) /*++
Abstract:
Connect and establish trust with remote server.
Parameter:
pszServerName : Name of the remote server if any. hHandle : Connection handle to this remote server if any.
Returns:
Connection handle to remote server or NULL if error.
--*/ { DWORD dwStatus = ERROR_SUCCESS; DWORD dwErrCode = ERROR_SUCCESS; BOOL bCleanupContextHandle = FALSE;
if(hHandle == NULL && pszServerName == NULL) { SetLastError(ERROR_INVALID_PARAMETER); return NULL; }
//
// Use server name to connect
//
if(hHandle == NULL) { hHandle = TLSConnectToLsServer(pszServerName);
// we make connection here so we need to cleanup
bCleanupContextHandle = TRUE;
if(hHandle == NULL) { dwStatus = GetLastError(); } }
if(hHandle != NULL) { //
// establish trust with remote server
//
dwStatus = TLSEstablishTrustWithServer( hHandle, g_hCryptProv, // GLOBAL crypto provider
CLIENT_TYPE_TLSERVER, &dwErrCode );
if(dwStatus == ERROR_SUCCESS && dwErrCode >= LSERVER_ERROR_BASE) { //
// BUGBUG : We still have lots of old license server running,
// ignore this error code for now.
//
if(dwErrCode != LSERVER_E_ACCESS_DENIED) { LPTSTR szServer = NULL; DWORD dwCode;
if(pszServerName == NULL) { dwStatus = TryGetServerName( hHandle, &szServer, &dwCode );
if(dwStatus == RPC_S_OK && dwCode == ERROR_SUCCESS && szServer != NULL) { pszServerName = szServer; } }
TLSLogEvent( EVENTLOG_ERROR_TYPE, TLS_E_SERVERTOSERVER, TLS_E_ESTABLISHTRUST, pszServerName, dwErrCode );
if (NULL != szServer) { MIDL_user_free(szServer); } }
SetLastError(dwStatus = dwErrCode); }
if(dwStatus != ERROR_SUCCESS && hHandle != NULL && bCleanupContextHandle == TRUE) { // only cleanup if we make the connection in this routine.
TLSDisconnectFromServer(hHandle); hHandle = NULL; } }
return (dwStatus == ERROR_SUCCESS) ? hHandle : NULL; }
///////////////////////////////////////////////////////////////
TLS_HANDLE TLSConnectToServerWithServerId( LPTSTR pszServerSetupId )
/*++
Abstract:
Resolve a license server's unique ID to server name, then connect and establish trust relationship with the server.
Parameter:
pszServerSetupId : Server's unique ID.
Returns:
Server connection handle or NULL if error.
--*/
{ TLS_HANDLE hHandle = NULL; TCHAR szServer[MAX_COMPUTERNAME_LENGTH+2];
if(TLSLookupServerById(pszServerSetupId, szServer) != ERROR_SUCCESS) { //
// server might not be available
//
SetLastError(TLS_E_SERVERLOOKUP); goto cleanup; }
hHandle = TLSConnectAndEstablishTrust(szServer, NULL);
cleanup:
return hHandle; }
///////////////////////////////////////////////////////////////
DWORD TLSRetrieveServerInfo( IN TLS_HANDLE hHandle, OUT PTLServerInfo pServerInfo ) /*++
Abstract:
Retrieve server information from remote server.
Parameter:
hHandle : Connection handle to remote server. pServerInfo : Pointer to TLServerInfo to receive remote server's information.
Return:
ERROR_SUCCESS or error code.
--*/ { DWORD dwStatus; DWORD dwErrCode; DWORD dwBufSize; PBYTE pbServerPid = NULL; LPTSTR szServerName = NULL; LPTSTR szServerScope = NULL;
if(hHandle == NULL) { SetLastError(dwStatus = ERROR_INVALID_PARAMETER); return dwStatus; }
//
// Retrieve Server name.
//
dwStatus = TryGetServerName( hHandle, &szServerName, &dwErrCode );
if(dwStatus != ERROR_SUCCESS || dwErrCode != ERROR_SUCCESS) { if(dwStatus == ERROR_SUCCESS) { dwStatus = dwErrCode; } goto cleanup; } else { StringCbCopy( pServerInfo->m_szServerName, sizeof(pServerInfo->m_szServerName), szServerName);
MIDL_user_free(szServerName); }
//
// Retrieve server's scope, currently, server scope = domain/workgroup name
// except in the case of enterprise server.
//
dwStatus = TryGetServerScope( hHandle, &szServerScope, &dwErrCode ); if(dwStatus != ERROR_SUCCESS || dwErrCode != ERROR_SUCCESS) { if(dwStatus == ERROR_SUCCESS) { dwStatus = dwErrCode; } goto cleanup; } else { StringCbCopy( pServerInfo->m_szDomainName, sizeof(pServerInfo->m_szDomainName), szServerScope);
MIDL_user_free(szServerScope); }
//
// Get Server's ID
//
dwStatus = TLSGetServerPID( hHandle, &dwBufSize, &pbServerPid, &dwErrCode ); if(dwStatus != ERROR_SUCCESS || dwErrCode != ERROR_SUCCESS) { if(dwStatus == ERROR_SUCCESS) { dwStatus = dwErrCode; } goto cleanup; }
if(pbServerPid == NULL || dwBufSize == 0) { // invalid return...
// TLSASSERT(FALSE);
dwStatus = ERROR_INVALID_DATA; goto cleanup; }
StringCbCopyN( pServerInfo->m_szSetupId, sizeof(pServerInfo->m_szSetupId), (LPCTSTR)pbServerPid, min(sizeof(pServerInfo->m_szSetupId) - sizeof(TCHAR), dwBufSize) );
midl_user_free(pbServerPid);
//
// retrieve server version information
//
dwStatus = TLSGetVersion( hHandle, &(pServerInfo->m_dwTLSVersion) );
if(dwStatus == ERROR_SUCCESS) { DWORD dwMajorVersion; DWORD dwMinorVersion;
dwMajorVersion = GET_SERVER_MAJOR_VERSION(pServerInfo->m_dwTLSVersion); dwMinorVersion = GET_SERVER_MINOR_VERSION(pServerInfo->m_dwTLSVersion); if(dwMajorVersion < GET_SERVER_MAJOR_VERSION(TLS_CURRENT_VERSION)) { pServerInfo->m_dwCapability = TLSERVER_OLDVERSION; } else if( dwMajorVersion >= GET_SERVER_MAJOR_VERSION(TLS_CURRENT_VERSION) && dwMinorVersion < GET_SERVER_MINOR_VERSION(TLS_CURRENT_VERSION) ) { pServerInfo->m_dwCapability = TLSERVER_OLDVERSION; }
// version 5.1 and above
if(dwMajorVersion >= 0x5 && dwMinorVersion > 0) { pServerInfo->m_dwCapability |= TLSERVER_SUPPORTREPLICATION; } }
cleanup:
return dwStatus; }
///////////////////////////////////////////////////////////////
DWORD TLSLookupAnyEnterpriseServer( OUT PTLServerInfo pServerInfo ) /*++
Abstract:
Find any enterprise server in the registered server list.
Parameter:
pServerInfo - Pointer to TLServerInfo to receive enterprise server info.
Returns:
ERROR_SUCCESS or error code.
--*/ { TLServerInfo* pServer = NULL; BOOL bFound = FALSE;
TLSBeginEnumKnownServerList();
while(bFound == FALSE) { pServer = TLSGetNextKnownServer(); if(pServer == NULL) { break; }
if(pServer->IsServerEnterpriseServer() == TRUE) { *pServerInfo = *pServer; bFound = TRUE; } }
TLSEndEnumKnownServerList();
return (bFound == TRUE) ? ERROR_SUCCESS : TLS_E_RECORD_NOTFOUND; }
///////////////////////////////////////////////////////////////
//
// Various interface function to CTLServerMgr
//
///////////////////////////////////////////////////////////////
//------------------------------------------------------------
//
void TLSBeginEnumKnownServerList() { g_ServerMgr.ServerListEnumBegin(); }
//------------------------------------------------------------
//
const PTLServerInfo TLSGetNextKnownServer() { return g_ServerMgr.ServerListEnumNext(); }
//------------------------------------------------------------
//
void TLSEndEnumKnownServerList() { g_ServerMgr.ServerListEnumEnd(); }
//------------------------------------------------------------
//
DWORD TLSLookupServerById( IN LPTSTR pszServerSetupId, OUT LPTSTR pszServer ) /*++
Abstract:
Loopup server name via server ID.
Parameter:
pszServerSetupId : remote server's setup ID. pszServer : name of the server, must be MAX_COMPUTERNAMELENGTH+1.
Returns: ERROR_SUCCESS or error code.
Remark:
Internal call, no error checking on buffer side.
++*/ { DWORD dwStatus = ERROR_SUCCESS;
TLServerInfo ServerInfo;
dwStatus = TLSLookupRegisteredServer( pszServerSetupId, NULL, NULL, &ServerInfo );
if(dwStatus == ERROR_SUCCESS) { _tcscpy(pszServer, ServerInfo.GetServerName()); }
return dwStatus; }
//------------------------------------------------------------
//
DWORD TLSRegisterServerWithName( IN LPTSTR pszSetupId, IN LPTSTR pszDomainName, IN LPTSTR pszServerName ) /*++
Abstract:
Register a server with local server list manager.
Parameter:
pszSetupId : Remote server setup ID. pszDomainName : Remote server domain. pszServerName : Remote server name.
Returns:
ERROR_SUCCESS or error code.
++*/ { TLS_HANDLE hHandle = NULL; TLServerInfo ServerInfo; DWORD dwStatus;
//
// Lookup server with local server list manager.
//
dwStatus = TLSLookupRegisteredServer( pszSetupId, pszDomainName, pszServerName, &ServerInfo );
if( (dwStatus == ERROR_SUCCESS && ServerInfo.GetServerVersion() != 0) ) { //
// this server already registeted
//
return dwStatus; }
if(dwStatus != ERROR_SUCCESS && dwStatus != TLS_E_RECORD_NOTFOUND) { // Error...
return dwStatus; }
dwStatus = ERROR_SUCCESS;
//
// retrieve remote server information
//
hHandle = TLSConnectAndEstablishTrust( pszServerName, NULL ); if(hHandle != NULL) { dwStatus = TLSRetrieveServerInfo( hHandle, &ServerInfo );
if(dwStatus == ERROR_SUCCESS) { dwStatus = TLSRegisterServerWithServerInfo(&ServerInfo); } }
//
// close conection
//
if(hHandle != NULL) { TLSDisconnectFromServer(hHandle); }
return dwStatus; }
//-----------------------------------------------------------
//
DWORD TLSRegisterServerWithHandle( IN TLS_HANDLE hHandle, OUT PTLServerInfo pServerInfo ) /*++
Abstract:
Register a remote server with local server list manager, this differ from TLSRegisterServerWithName() in that it already has make a connection to server.
Parameter:
hHandle - Connection handle to remote server. pServerInfo - return remote server's information.
Returns:
ERROR_SUCCESS or error code.
++*/ { DWORD dwStatus; TLS_HANDLE hTrustHandle; TLServerInfo ServerInfo;
if(hHandle == NULL) { SetLastError(dwStatus = ERROR_INVALID_PARAMETER); return dwStatus; }
//
// Establish trust with remote server.
//
hTrustHandle = TLSConnectAndEstablishTrust( NULL, hHandle ); if(hTrustHandle == NULL) { dwStatus = GetLastError(); return dwStatus; }
//
// Retrieve remote server information.
//
dwStatus = TLSRetrieveServerInfo( hHandle, &ServerInfo );
if(dwStatus == ERROR_SUCCESS) { if(pServerInfo != NULL) { *pServerInfo = ServerInfo; }
dwStatus = TLSRegisterServerWithServerInfo(&ServerInfo); }
return dwStatus; }
//----------------------------------------------------------
DWORD TLSRegisterServerWithServerInfo( IN PTLServerInfo pServerInfo ) /*++
Abstract:
Register a server with local server list manager.
Parameter:
pServerInfo : remote server information.
Returns:
ERROR_SUCCESS or error code.
++*/ { return g_ServerMgr.AddServerToList(pServerInfo); }
//------------------------------------------------------------
//
DWORD TLSLookupRegisteredServer( IN LPTSTR pszSetupId, IN LPTSTR pszDomainName, IN LPTSTR pszServerName, OUT PTLServerInfo pServerInfo ) /*++
Abstract:
Look up and retrieve remote server information from local server list manager.
Parameter:
pszSetupId : remote server setup ID if any. pszDomainName : useless parameter, ignore pszServerName : remote server name if any. pServerInfo : Pointer to TLServerInfo to receive info. about remote server.
Returns:
ERROR_SUCCESS or error code.
Remark:
Always try to resolve server with server's setup ID first then server name. ++*/ { DWORD dwStatus;
if(pszSetupId == NULL && pszServerName == NULL) { SetLastError(dwStatus = ERROR_INVALID_PARAMETER); return dwStatus; }
if(pszSetupId) { dwStatus = g_ServerMgr.LookupBySetupId( pszSetupId, pServerInfo ); } else if(pszServerName) { dwStatus = g_ServerMgr.LookupByServerName( pszServerName, pServerInfo ); }
return dwStatus; } ///////////////////////////////////////////////////////////////
//
// class CTLServerMgr
//
///////////////////////////////////////////////////////////////
CTLServerMgr::CTLServerMgr() { }
//-----------------------------------------------------
CTLServerMgr::~CTLServerMgr() { PTLServerInfo pServer = NULL; m_ReadWriteLock.Acquire(WRITER_LOCK);
//
// Disconnect from Server
//
for( MapIdToInfo::iterator it = m_Handles.begin(); it != m_Handles.end(); it++ ) { pServer = (*it).second;
if(pServer != NULL) { delete pServer; } }
m_Handles.erase(m_Handles.begin(), m_Handles.end());
m_ReadWriteLock.Release(WRITER_LOCK); }
//----------------------------------------------------
DWORD CTLServerMgr::AddServerToList( IN PTLServerInfo pServerInfo ) /*++
Abstract:
Add a server into our server list.
Parameters:
pServerInfo - Information about remote server.
Returns:
ERROR_SUCCESS or error code.
--*/ { DWORD dwStatus = ERROR_SUCCESS; MapSetupIdToInfo findMap; MapIdToInfo::iterator it;
if( pServerInfo == NULL ) { SetLastError(dwStatus = ERROR_INVALID_PARAMETER); return dwStatus; }
findMap.pszSetupId = pServerInfo->GetServerId(); m_ReadWriteLock.Acquire(WRITER_LOCK);
it = m_Handles.find(findMap);
if(it == m_Handles.end()) { PTLServerInfo pServer = NULL; MapSetupIdToInfo serverMap;
// make a copy of input
pServer = new TLServerInfo; *pServer = *pServerInfo; serverMap.pszSetupId = pServer->GetServerId();
// Insert into our list
m_Handles[serverMap] = pServer; } else { dwStatus = TLS_E_DUPLICATE_RECORD;
// update information
*((*it).second) = *pServerInfo; } m_ReadWriteLock.Release(WRITER_LOCK);
return dwStatus; }
//-----------------------------------------------------
DWORD CTLServerMgr::AddServerToList( IN LPCTSTR pszSetupId, IN LPCTSTR pszDomainName, IN LPCTSTR pszServerName ) /*++
Abstract:
Add a server into our server list.
Parameter:
pszSetupId : remote server's ID. pszDomainName : remote server's domain. pszServerName : remote server name.
Returns:
ERROR_SUCCESS or error code.
++*/ { DWORD dwStatus = ERROR_SUCCESS;
if(pszSetupId == NULL || pszServerName == NULL) { SetLastError(dwStatus = ERROR_INVALID_PARAMETER); return dwStatus; }
PTLServerInfo pServerInfo = NULL; MapSetupIdToInfo serverMap; MapIdToInfo::iterator it;
serverMap.pszSetupId = pszSetupId; m_ReadWriteLock.Acquire(WRITER_LOCK);
it = m_Handles.find(serverMap);
if(it == m_Handles.end()) { pServerInfo = new TLServerInfo(pszSetupId, pszDomainName, pszServerName); serverMap.pszSetupId = pServerInfo->GetServerId();
// Win64 compiler error
//m_Handles.insert( pair<MapSetupIdToInfo, PTLServerInfo>(serverMap, pServerHandle) );
// Insert into our list
m_Handles[serverMap] = pServerInfo; } else { if(lstrcmpi((*it).second->GetServerName(), pszServerName) != 0) { // update server name
(*it).second->UpdateServerName(pszServerName); }
SetLastError(dwStatus = TLS_E_DUPLICATE_RECORD); }
m_ReadWriteLock.Release(WRITER_LOCK); return dwStatus; }
//-----------------------------------------------------
DWORD CTLServerMgr::LookupBySetupId( IN LPCTSTR pszSetupId, OUT PTLServerInfo pServerInfo ) /*++
Abstract:
Lookup a server via its ID.
Parameters:
pszSetupId : Remote server setup ID. pServerInfo : Pointer to TLServerInfo to receive information about remote server.
Returns:
ERROR_SUCCESS or error code.
++*/ { DWORD dwStatus = ERROR_SUCCESS;
MapSetupIdToInfo serverMap; MapIdToInfo::iterator it;
m_ReadWriteLock.Acquire(READER_LOCK);
serverMap.pszSetupId = pszSetupId; it = m_Handles.find(serverMap);
if(it != m_Handles.end()) { *pServerInfo = *((*it).second); } else { dwStatus = TLS_E_RECORD_NOTFOUND; }
m_ReadWriteLock.Release(READER_LOCK); return dwStatus; }
//------------------------------------------------------
DWORD CTLServerMgr::LookupByServerName( IN LPCTSTR pszServerName, OUT PTLServerInfo pServerInfo ) /*++
Abstract:
Lookup server inforation via server name.
Parameters:
pszServerName : Name of server. pServerInfo : Pointer to TLServerInfo to receive information about remote server.
Returns:
ERROR_SUCCESS or error code.
Remark:
machine name might change from one boot to another, it is not reliable to query by server name.
++*/ { DWORD dwStatus = ERROR_SUCCESS;
m_ReadWriteLock.Acquire(READER_LOCK);
for( MapIdToInfo::iterator it = m_Handles.begin(); it != m_Handles.end(); it++ ) { if(_tcsicmp((*it).second->GetServerName(), pszServerName) == 0) { break; } }
if(it != m_Handles.end()) { *pServerInfo = *((*it).second); } else { dwStatus = TLS_E_RECORD_NOTFOUND; }
m_ReadWriteLock.Release(READER_LOCK); return dwStatus; }
//------------------------------------------------------
void CTLServerMgr::ServerListEnumBegin() /*++
Abstract:
Begin a enumeration on local server list.
Parameter:
None.
Returns:
None.
Remark:
This locks local server list into read only mode.
--*/ { m_ReadWriteLock.Acquire(READER_LOCK);
enumIterator = m_Handles.begin(); }
//------------------------------------------------------
const PTLServerInfo CTLServerMgr::ServerListEnumNext() /*++
Abstract:
Retrieve next server in local server list.
Parameter:
None.
Returns:
Pointer to a server information.
Remark:
Must call ServerListEnumBegin().
--*/ { PTLServerInfo pServerInfo = NULL;
if(enumIterator != m_Handles.end()) { pServerInfo = (*enumIterator).second; enumIterator++; } return pServerInfo; }
//------------------------------------------------------
void CTLServerMgr::ServerListEnumEnd() /*++
Abstract:
End enumeration of local server list.
Parameter:
None.
Returns:
Pointer to a server information.
Remark:
Must call ServerListEnumBegin().
--*/ { enumIterator = m_Handles.end(); m_ReadWriteLock.Release(READER_LOCK); }
|