Windows2003-3790/termsrv/license/licmgr/lsmgrdoc.cpp
2020-09-30 16:53:55 +02:00

813 lines
20 KiB
C++

//Copyright (c) 1998 - 1999 Microsoft Corporation
/*++
Module Name:
LsMgrDoc.cpp
Abstract:
This Module contains the implementation of CLicMgrDoc class
(The Document class)
Author:
Arathi Kundapur (v-akunda) 11-Feb-1998
Revision History:
--*/
#include "stdafx.h"
#include "defines.h"
#include "LicMgr.h"
#include "LSMgrDoc.h"
#include "LSServer.h"
#include "MainFrm.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CLicMgrDoc
IMPLEMENT_DYNCREATE(CLicMgrDoc, CDocument)
BEGIN_MESSAGE_MAP(CLicMgrDoc, CDocument)
//{{AFX_MSG_MAP(CLicMgrDoc)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CLicMgrDoc construction/destruction
CLicMgrDoc::CLicMgrDoc()
{
// TODO: add one-time construction code here
m_NodeType = NODE_NONE;
m_pAllServers = NULL;
}
CLicMgrDoc::~CLicMgrDoc()
{
if(m_pAllServers)
{
delete m_pAllServers;
m_pAllServers = NULL;
}
}
BOOL CLicMgrDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: add reinitialization code here
// (SDI documents will reuse this document)
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CLicMgrDoc serialization
void CLicMgrDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
}
/////////////////////////////////////////////////////////////////////////////
// CLicMgrDoc diagnostics
#ifdef _DEBUG
void CLicMgrDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CLicMgrDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
HRESULT CLicMgrDoc::EnumerateKeyPacks(CLicServer *pServer,DWORD dwSearchParm,BOOL bMatchAll)
{
ASSERT(pServer);
HRESULT hResult = S_OK;
if(pServer == NULL)
return E_FAIL;
if(TRUE == pServer->IsExpanded())
return ALREADY_EXPANDED;
PCONTEXT_HANDLE hBinding = NULL;
BOOL bContext = FALSE;
RPC_STATUS status;
LSKeyPack keypack;
DWORD dwErrCode;
CString Server;
hBinding = pServer->GetContext();
if(NULL == hBinding)
{
if(pServer->UseIpAddress())
Server = pServer->GetIpAddress();
else
Server = pServer->GetName();
hBinding=TLSConnectToLsServer(Server.GetBuffer(Server.GetLength()));
if(hBinding == NULL)
{
hResult = CONNECTION_FAILED;
goto cleanup;
}
}
memset(&keypack, 0, sizeof(keypack));
keypack.dwLanguageId = GetUserDefaultUILanguage();
status = TLSKeyPackEnumBegin(hBinding, dwSearchParm, bMatchAll, &keypack, &dwErrCode);
if(status != RPC_S_OK || dwErrCode != ERROR_SUCCESS)
{
hResult = status;
goto cleanup;
}
else
{
do
{
status = TLSKeyPackEnumNext(hBinding, &keypack, &dwErrCode);
if(status == RPC_S_OK && dwErrCode == ERROR_SUCCESS)
{
DBGMSG( L"LICMGR:CLicMgrDoc::EnumerateKeyPacks - TLSKeyPackEnumNext\n" , 0 );
CKeyPack * pKeyPack = new CKeyPack(keypack);
if(pKeyPack == NULL)
{
hResult = E_OUTOFMEMORY;
goto cleanup;
}
pServer->AddKeyPack(pKeyPack);
}
} while((status == RPC_S_OK) && (dwErrCode == ERROR_SUCCESS));
TLSKeyPackEnumEnd(hBinding, &dwErrCode);
pServer->Expand(TRUE);
}
cleanup:
//put cleanup code here.
if(hBinding)
TLSDisconnectFromServer(&hBinding);
return hResult;
}
HRESULT
CLicMgrDoc::EnumerateLicenses(
CKeyPack *pKeyPack,
DWORD dwSearchParm,
BOOL bMatchAll
)
/*++
--*/
{
ASSERT(pKeyPack);
if(NULL == pKeyPack)
{
return E_FAIL;
}
CLicServer *pServer = pKeyPack->GetServer();
ASSERT(pServer);
if(NULL == pKeyPack)
{
return E_FAIL;
}
HRESULT hResult = S_OK;
if(TRUE == pKeyPack->IsExpanded())
{
return ALREADY_EXPANDED;
}
PCONTEXT_HANDLE hBinding = NULL;
BOOL bContext = FALSE;
DWORD status = ERROR_SUCCESS;
LSLicenseEx sLicense;
CString Server;
hBinding = pServer->GetContext();
if(NULL == hBinding)
{
if(pServer->UseIpAddress())
{
Server = pServer->GetIpAddress();
}
else
{
Server = pServer->GetName();
}
hBinding=TLSConnectToLsServer(Server.GetBuffer(Server.GetLength()));
if(hBinding == NULL)
{
hResult = CONNECTION_FAILED;
goto cleanup;
}
}
memset(&sLicense, 0, sizeof(LSLicenseEx));
sLicense.dwKeyPackId = pKeyPack->GetKeyPackStruct().dwKeyPackId;
TLSLicenseEnumBegin( hBinding, dwSearchParm,bMatchAll ,(LPLSLicenseSearchParm) &sLicense, &status);
if(status != ERROR_SUCCESS)
{
hResult = status;
goto cleanup;
}
else
{
DWORD TLSLicenseEnumNextResult = ERROR_SUCCESS;
do {
memset(&sLicense, 0, sizeof(LSLicenseEx));
sLicense.dwKeyPackId = pKeyPack->GetKeyPackStruct().dwKeyPackId;
TLSLicenseEnumNextResult = TLSLicenseEnumNextEx(hBinding,&sLicense,&status);
if ((status == ERROR_SUCCESS) && (TLSLicenseEnumNextResult == RPC_S_OK))
{
CLicense * pLicense = new CLicense(sLicense);
if(NULL == pLicense)
{
hResult = E_OUTOFMEMORY;
goto cleanup;
}
pKeyPack->AddIssuedLicense(pLicense);
}
} while ((status == ERROR_SUCCESS) && (TLSLicenseEnumNextResult == RPC_S_OK));
TLSLicenseEnumEnd(hBinding,&status);
pKeyPack->Expand(TRUE);
}
cleanup:
//put cleanup code here
if(hBinding)
{
TLSDisconnectFromServer(&hBinding);
}
return hResult;
}
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 );
}
//
// GetProcAddress needed because admin pack can install this binary on an
// XP machine with an old mstlsapi.dll
//
typedef DWORD (WINAPI* PTLSGETSERVERNAMEFIXED) (
TLS_HANDLE hHandle,
LPTSTR *pszMachineName,
PDWORD pdwErrCode
);
RPC_STATUS
TryGetServerName(PCONTEXT_HANDLE hBinding,
CString &Server)
{
RPC_STATUS status;
DWORD dwErrCode;
HINSTANCE hModule = LoadLibrary(L"mstlsapi.dll");
if (hModule)
{
LPTSTR szMachineName = NULL;
PTLSGETSERVERNAMEFIXED pfnGetServerNameFixed = (PTLSGETSERVERNAMEFIXED) GetProcAddress(hModule,"TLSGetServerNameFixed");
if (pfnGetServerNameFixed)
{
status = pfnGetServerNameFixed(hBinding,&szMachineName,&dwErrCode);
if(status == RPC_S_OK && dwErrCode == ERROR_SUCCESS && szMachineName != NULL)
{
Server = szMachineName;
MIDL_user_free(szMachineName);
FreeLibrary(hModule);
return status;
}
}
FreeLibrary(hModule);
}
{
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, &dwErrCode);
if(status == RPC_S_OK && dwErrCode == ERROR_SUCCESS)
{
Server = lpszMachineName;
}
}
catch(...)
{
status = ERROR_NOACCESS;
}
if( lpszMachineName )
MyVirtualFree(lpszMachineName);
}
return status;
}
typedef DWORD (WINAPI* PTLSGETSERVERSCOPEFIXED) (
TLS_HANDLE hHandle,
LPTSTR *pszScopeName,
PDWORD pdwErrCode
);
RPC_STATUS
TryGetServerScope(PCONTEXT_HANDLE hBinding,
CString &Scope)
{
RPC_STATUS status;
DWORD dwErrCode;
HINSTANCE hModule = LoadLibrary(L"mstlsapi.dll");
if (hModule)
{
LPTSTR szServerScope = NULL;
PTLSGETSERVERSCOPEFIXED pfnGetServerScopeFixed = (PTLSGETSERVERSCOPEFIXED) GetProcAddress(hModule,"TLSGetServerScopeFixed");
if (pfnGetServerScopeFixed)
{
status = pfnGetServerScopeFixed(hBinding,&szServerScope,&dwErrCode);
if(status == RPC_S_OK && dwErrCode == ERROR_SUCCESS && szServerScope != NULL)
{
Scope = szServerScope;
MIDL_user_free(szServerScope);
FreeLibrary(hModule);
return status;
}
}
FreeLibrary(hModule);
}
{
LPTSTR lpszServerScope = NULL;
try
{
if ( !MyVirtualAlloc( ( MAX_COMPUTERNAME_LENGTH+1 ) * sizeof( TCHAR ),
(PVOID*) &lpszServerScope ) )
{
return RPC_S_OUT_OF_MEMORY;
}
DWORD uSize = MAX_COMPUTERNAME_LENGTH+1 ;
memset(lpszServerScope, 0, ( MAX_COMPUTERNAME_LENGTH+1 ) * sizeof( TCHAR ));
status = TLSGetServerScope(hBinding, lpszServerScope, &uSize, &dwErrCode);
if(status == RPC_S_OK && dwErrCode == ERROR_SUCCESS)
{
Scope = lpszServerScope;
}
}
catch(...)
{
status = ERROR_NOACCESS;
}
if(lpszServerScope)
MyVirtualFree(lpszServerScope);
}
return status;
}
HRESULT
CLicMgrDoc::ConnectToServer(
CString& Server,
CString& Scope,
SERVER_TYPE& ServerType
)
/*++
--*/
{
PCONTEXT_HANDLE hBinding = NULL;
HRESULT hResult = ERROR_SUCCESS;
RPC_STATUS status;
LPTSTR szServerScope = NULL;
LPTSTR szMachineName = NULL;
DWORD dwVersion = 0;
PBYTE pbData = NULL;
DWORD cbData = 0;
DWORD dwErrCode;
hBinding = TLSConnectToLsServer(Server.GetBuffer(Server.GetLength()));
if(hBinding == NULL)
{
hResult = E_FAIL;
goto cleanup;
}
TryGetServerName(hBinding,Server);
Scope.Empty();
status = TryGetServerScope(hBinding,Scope);
if(status != RPC_S_OK || Scope.IsEmpty())
{
Scope.LoadString(IDS_UNKNOWN);
}
//Get whether this is a TS4 server or TS5Enforced or TS5NonEnforced
status = TLSGetVersion (hBinding, &dwVersion);
if(status == RPC_S_OK)
{
if(dwVersion & 0x40000000)
{
ServerType = SERVER_TS5_ENFORCED;
}
else
{
ServerType = SERVER_TS5_NONENFORCED;
}
}
else if(status == RPC_S_UNKNOWN_IF)
{
ServerType = SERVER_TS4;
Scope = Server ;
}
else
{
hResult = E_FAIL;
}
cleanup:
if(pbData != NULL)
{
midl_user_free(pbData);
}
if(hBinding)
{
TLSDisconnectFromServer(&hBinding);
}
return hResult;
}
HRESULT CLicMgrDoc::ConnectWithCurrentParams()
{
CLicMgrApp *pApp = (CLicMgrApp*)AfxGetApp();
CMainFrame * pWnd = (CMainFrame *)pApp->m_pMainWnd ;
HRESULT hResult = ERROR_SUCCESS;
CString Scope;
CString IpAddress;
CString Server = pApp->m_Server;
if(NULL == m_pAllServers)
m_pAllServers = new CAllServers(_T(""));
if(NULL == m_pAllServers)
{
hResult = E_OUTOFMEMORY;
goto cleanup;
}
pWnd->SendMessage(WM_ADD_ALL_SERVERS,0,(LPARAM)m_pAllServers);
if(!Server.IsEmpty())
{
if(TRUE == IsServerInList(Server))
{
hResult = E_DUPLICATE;
}
if( hResult == ERROR_SUCCESS )
{
pWnd->ConnectServer( Server );
}
/* Why did we have this here?
IpAddress = Server;
hResult = ConnectToServer(
Server,
Scope,
ServerType
);
if(ERROR_SUCCESS == hResult)
{
CAllServers * pAllServers = m_pAllServers;
CLicServer *pServer1 = NULL;
if(IpAddress != Server)
{
if(TRUE == IsServerInList(Server))
{
hResult = E_DUPLICATE;
goto cleanup;
}
pServer1 = new CLicServer(Server,ServerType,Scope,IpAddress);
}
else
{
pServer1 = new CLicServer(Server,ServerType,Scope);
}
if(pServer1)
{
pAllServers->AddLicServer(pServer1);
pWnd->SendMessage(WM_ADD_SERVER,0,(LPARAM)pServer1);
}
else
{
return E_OUTOFMEMORY;
}
}
*/
}
cleanup:
//Add any cleanup code required here.
return hResult;
}
void CLicMgrDoc:: TimeToString(DWORD *ptime, CString& rString)
{
TCHAR m_szTime[MAX_PATH];
time_t time;
rString.Empty();
ASSERT(ptime);
if(NULL == ptime)
return;
//
// Times are stored in the ANSI time_t style in the database,
// however they are type cast to a DWORD (unsigned long). Because
// time_t is 64 bit on a 64 bit machine, and because it is a signed
// value, we must be careful here to make sure that the sign of the
// value is not lost as the value goes from 32 to 64 bit.
//
time = (time_t)(LONG)(*ptime);
LPTSTR lpszTime = NULL;
//Getting the local time as the time is stored as GMT
//in the license server database.
struct tm * pTm = localtime(&time);
if(NULL == pTm)
return;
SYSTEMTIME SystemTime;
SystemTime.wYear = (WORD)(pTm->tm_year + 1900);
SystemTime.wMonth = (WORD)(pTm->tm_mon + 1);
SystemTime.wDayOfWeek = (WORD)pTm->tm_wday;
SystemTime.wDay = (WORD)pTm->tm_mday;
SystemTime.wHour = (WORD)pTm->tm_hour;
SystemTime.wMinute = (WORD)pTm->tm_min;
SystemTime.wSecond = (WORD)pTm->tm_sec;
SystemTime.wMilliseconds = 0;
int RetLen;
TCHAR DateFormat[MAX_PATH];
TCHAR TimeFormat[MAX_PATH];
RetLen = ::GetLocaleInfo(LOCALE_USER_DEFAULT,
LOCALE_SLONGDATE,
DateFormat,
sizeof(DateFormat)/sizeof(TCHAR));
ASSERT(RetLen!=0);
RetLen = ::GetLocaleInfo(LOCALE_USER_DEFAULT,
LOCALE_STIMEFORMAT,
TimeFormat,
sizeof(TimeFormat)/sizeof(TCHAR));
ASSERT(RetLen!=0);
RetLen = ::GetDateFormat(LOCALE_USER_DEFAULT,
0, /* dwFlag */
&SystemTime,
DateFormat, /* lpFormat */
m_szTime,
sizeof(m_szTime)/sizeof(TCHAR));
if (RetLen == 0)
return;
_tcscat(m_szTime, _T(" ")); /* Separator of date and time */
lpszTime = &m_szTime[lstrlen(m_szTime)];
RetLen = ::GetTimeFormat(LOCALE_USER_DEFAULT,
0, /* dwFlag */
&SystemTime,
TimeFormat, /* lpFormat */
lpszTime,
sizeof(m_szTime)/sizeof(TCHAR) - lstrlen(m_szTime));
if (RetLen == 0)
return;
rString = m_szTime;
return;
}
BOOL CLicMgrDoc::IsServerInList(CString & Server)
{
ASSERT(m_pAllServers);
if(NULL == m_pAllServers)
return FALSE;
BOOL bServerInList = FALSE;
LicServerList * pServerList = m_pAllServers->GetLicServerList();
//Assumption: ServerName is unique
POSITION pos = pServerList->GetHeadPosition();
while(pos)
{
CLicServer *pLicServer = (CLicServer *)pServerList->GetNext(pos);
ASSERT(pLicServer);
if(NULL == pLicServer)
continue;
if((0 == Server.CompareNoCase(pLicServer->GetName())) || (0 == Server.CompareNoCase(pLicServer->GetIpAddress())))
{
bServerInList = TRUE;
break;
}
}
return bServerInList;
}