windows-nt/Source/XPSP1/NT/termsrv/license/lsreport/lsreport.cpp
2020-09-26 16:20:57 +08:00

440 lines
12 KiB
C++

//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1999
//
// File: lsreport.cpp
//
// Contents: LSReport engine - complete back end
//
// History: 06-10-99 t-BStern Created
//
//---------------------------------------------------------------------------
#include "lsreport.h"
#include "lsrepdef.h"
#include <time.h>
#include <oleauto.h>
TCHAR noExpire[NOEXPIRE_LENGTH] = { 0 };
TCHAR header[HEADER_LENGTH] = { 0 };
TCHAR szTemp[TYPESTR_LENGTH] = { 0 };
TCHAR szActive[TYPESTR_LENGTH] = { 0 };
TCHAR szUpgrade[TYPESTR_LENGTH] = { 0 };
TCHAR szRevoked[TYPESTR_LENGTH] = { 0 };
TCHAR szPending[TYPESTR_LENGTH] = { 0 };
TCHAR szConcur[TYPESTR_LENGTH] = { 0 };
TCHAR szUnknown[TYPESTR_LENGTH] = { 0 };
// Returns TRUE on success.
BOOL
InitLSReportStrings(VOID)
{
return (
LoadString(NULL, IDS_HEADER_TEXT, header, HEADER_LENGTH) &&
LoadString(NULL, IDS_NO_EXPIRE, noExpire, NOEXPIRE_LENGTH) &&
LoadString(NULL, IDS_TEMPORARY_LICENSE, szTemp, TYPESTR_LENGTH) &&
LoadString(NULL, IDS_ACTIVE_LICENSE, szActive, TYPESTR_LENGTH) &&
LoadString(NULL, IDS_UPGRADED_LICENSE, szUpgrade, TYPESTR_LENGTH) &&
LoadString(NULL, IDS_REVOKED_LICENSE, szRevoked, TYPESTR_LENGTH) &&
LoadString(NULL, IDS_PENDING_LICENSE, szPending, TYPESTR_LENGTH) &&
LoadString(NULL, IDS_CONCURRENT_LICENSE, szConcur, TYPESTR_LENGTH) &&
LoadString(NULL, IDS_UNKNOWN_LICENSE, szUnknown, TYPESTR_LENGTH)
);
}
// Given a keypack and a machine to connect to, read every license in that kp.
// Is not called directly.
DWORD
LicenseLoop(
IN FILE *OutFile,
IN LPWSTR szName, // who owns this keypack?
IN DWORD kpID, // which keypack
IN LPCTSTR szProductDesc,
IN BOOL bTempOnly,
IN const PSYSTEMTIME stStart,
IN const PSYSTEMTIME stEnd,
IN BOOL fUseLimits) // are the above 2 parms valid
{
TLS_HANDLE subHand;
DWORD dwStatus;
DWORD dwErrCode = ERROR_SUCCESS;
WCHAR msg[TLS_ERROR_LENGTH];
LSLicense lsl;
subHand = TLSConnectToLsServer(szName);
if (subHand == NULL)
{
// The machine suddenly went away.
ShowError(GetLastError(), NULL, TRUE);
dwErrCode = ERROR_BAD_CONNECT;
}
else
{
lsl.dwKeyPackId = kpID;
dwStatus = TLSLicenseEnumBegin(
subHand,
LSLICENSE_SEARCH_KEYPACKID,
TRUE,
&lsl,
&dwErrCode);
if (dwErrCode != ERROR_SUCCESS)
{
TLSGetLastError(subHand, TLS_ERROR_LENGTH, msg, &dwStatus);
_fputts(msg, stderr);
return dwErrCode;
}
else if (dwStatus)
{
return dwStatus;
}
do {
dwStatus = TLSLicenseEnumNext(subHand, &lsl, &dwErrCode);
if ((dwStatus == RPC_S_OK) && (dwErrCode == ERROR_SUCCESS)) {
if ((lsl.ucLicenseStatus == LSLICENSE_STATUS_TEMPORARY) ||
!bTempOnly) { // Does it fit the temp. requirements?
// We want to print if at any of the following are true:
// a) There are no limits
// b) Issued between stStart and stEnd
// c) Expired between stStart and stEnd
// d) issued before stStart and expired after stEnd
if (!fUseLimits // case a
|| ((CompDate(lsl.ftIssueDate, stStart) >= 0) &&
(CompDate(lsl.ftIssueDate, stEnd) <= 0)) // case b
|| ((CompDate(lsl.ftExpireDate, stStart) >= 0) &&
(CompDate(lsl.ftExpireDate, stEnd) <= 0)) // case c
|| ((CompDate(lsl.ftIssueDate, stStart) <= 0) &&
(CompDate(lsl.ftExpireDate, stEnd) >= 0))) // case d
{
PrintLicense(szName, // print it.
&lsl,
szProductDesc,
OutFile);
} // end check cases
} // end check for temp license
} // end good getnext
} while ((dwStatus == RPC_S_OK) && (dwErrCode == ERROR_SUCCESS));
if (dwStatus != RPC_S_OK)
{
return ShowError(dwStatus, NULL, TRUE);
}
if (dwErrCode != LSERVER_I_NO_MORE_DATA)
{
TLSGetLastError(subHand, TLS_ERROR_LENGTH, msg, &dwStatus);
_fputts(msg, stderr);
}
TLSLicenseEnumEnd(subHand, &dwErrCode);
if (dwErrCode != ERROR_SUCCESS)
{
TLSGetLastError(subHand, TLS_ERROR_LENGTH, msg, &dwStatus);
_fputts(msg, stderr);
}
TLSDisconnectFromServer(subHand);
}
return dwErrCode;
}
// Given a machine to connect to, iterate through the keypacks.
// Is not called directly.
DWORD
KeyPackLoop(
IN FILE *OutFile,
IN LPWSTR szName, // machine to connect to
IN BOOL bTempOnly,
IN const PSYSTEMTIME stStart,
IN const PSYSTEMTIME stEnd,
IN BOOL fUseLimits) // do we care about the previous 2 parms?
{
TLS_HANDLE hand;
DWORD dwStatus, dwErrCode;
LSKeyPack lskpKeyPack;
TCHAR msg[TLS_ERROR_LENGTH];
hand = TLSConnectToLsServer(szName);
if (hand == NULL)
{
return GetLastError();
}
lskpKeyPack.dwLanguageId = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
dwStatus = TLSKeyPackEnumBegin(hand,
LSKEYPACK_SEARCH_ALL,
FALSE,
&lskpKeyPack,
&dwErrCode);
if (dwErrCode != ERROR_SUCCESS)
{
return dwErrCode;
}
if (dwStatus != RPC_S_OK)
{
return dwStatus;
}
do {
dwStatus = TLSKeyPackEnumNext(hand, &lskpKeyPack, &dwErrCode);
if ((dwStatus == RPC_S_OK) && (dwErrCode == ERROR_SUCCESS))
{
LicenseLoop(OutFile,
szName,
lskpKeyPack.dwKeyPackId,
lskpKeyPack.szProductDesc,
bTempOnly,
stStart,
stEnd,
fUseLimits);
}
} while ((dwStatus == RPC_S_OK) && (dwErrCode == ERROR_SUCCESS));
if (dwStatus != RPC_S_OK)
{
return ShowError(dwStatus, NULL, TRUE);
}
if (dwErrCode != LSERVER_I_NO_MORE_DATA)
{
TLSGetLastError(hand, TLS_ERROR_LENGTH, msg, &dwStatus);
_fputts(msg, stderr);
}
TLSKeyPackEnumEnd(hand, &dwErrCode);
if (dwErrCode != ERROR_SUCCESS)
{
TLSGetLastError(hand, TLS_ERROR_LENGTH, msg, &dwStatus);
_fputts(msg, stderr);
}
TLSDisconnectFromServer(hand);
return dwErrCode;
}
// If bTempOnly is FALSE, all licenses will be dumped to the file. Otherwise,
// only Temporary licenses will be written. This is the one function to call
// to do all of the program's magic.
DWORD
ExportLicenses(
IN FILE *OutFile, // must be opened for writing first
IN PServerHolder pshServers,
IN BOOL fTempOnly,
IN const PSYSTEMTIME stStart,
IN const PSYSTEMTIME stEnd,
IN BOOL fUseLimits) // are the above 2 parms valid?
{
DWORD i;
DWORD dwStatus;
DWORD dwRetVal = ERROR_SUCCESS;
_fputts(header, OutFile);
for (i = 0; i < pshServers->dwCount; i++) {
dwStatus = KeyPackLoop(OutFile,
pshServers->pszNames[i],
fTempOnly,
stStart,
stEnd,
fUseLimits);
if (dwStatus != ERROR_SUCCESS)
{
INT_PTR arg;
dwRetVal = dwStatus;
arg = (INT_PTR)pshServers->pszNames[i];
ShowError(IDS_BAD_LOOP, &arg, FALSE);
ShowError(dwStatus, NULL, TRUE);
}
}
if (dwRetVal == ERROR_SUCCESS)
{
// Show a success banner.
ShowError(ERROR_SUCCESS, NULL, TRUE);
}
return dwRetVal;
}
// Performs actual output. of must be open.
// Not called directly.
VOID
PrintLicense(
IN LPCWSTR szName, // server allocating this license
IN const LPLSLicense p,
IN LPCTSTR szProductDesc,
IN FILE *of)
{
// All of these are used solely to convert a time_t to a short date.
BSTR bszDate;
UDATE uDate;
DATE Date;
HRESULT hr;
LPTSTR szType;
// server name
_fputts(szName, of);
// license ID and keypack ID
_ftprintf(of, _T("\t%d\t%d\t"),
p->dwLicenseId,
p->dwKeyPackId);
// license holder (machine)
_fputts(p->szMachineName, of);
_fputtc('\t', of);
// license requestor (username)
_fputts(p->szUserName, of);
_fputtc('\t', of);
// Print issue date in locale-appropriate way
UnixTimeToSystemTime((const time_t)p->ftIssueDate, &uDate.st);
hr = VarDateFromUdate(&uDate, 0, &Date);
if (S_OK != hr)
{
return;
}
hr = VarBstrFromDate(Date, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), VAR_DATEVALUEONLY, &bszDate);
if (S_OK != hr)
{
return;
}
_fputts(bszDate, of);
SysFreeString(bszDate);
_fputtc('\t', of);
// print either "No Expiration" or locale-nice expiration date
if (0x7FFFFFFF != p->ftExpireDate)
{
_fputts(noExpire, of);
}
else
{
UnixTimeToSystemTime((const time_t)p->ftExpireDate, &uDate.st);
hr = VarDateFromUdate(&uDate, 0, &Date);
if (S_OK != hr)
{
return;
}
hr = VarBstrFromDate(Date, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), VAR_DATEVALUEONLY, &bszDate);
if (S_OK != hr)
{
return;
}
_fputts(bszDate, of);
SysFreeString(bszDate);
}
_fputtc('\t', of);
// Assign the right kind of text for the type of license,
// and then print the license type.
switch (p->ucLicenseStatus) {
case LSLICENSE_STATUS_TEMPORARY:
szType = szTemp;
break;
case LSLICENSE_STATUS_ACTIVE:
szType = szActive;
break;
case LSLICENSE_STATUS_UPGRADED:
szType = szUpgrade;
break;
case LSLICENSE_STATUS_REVOKE:
szType = szRevoked;
break;
case LSLICENSE_STATUS_PENDING:
szType = szPending;
break;
case LSLICENSE_STATUS_CONCURRENT:
szType = szConcur;
break;
case LSLICENSE_STATUS_UNKNOWN:
// Fall through
default:
szType = szUnknown;
}
_fputts(szType, of);
_fputtc('\t', of);
// Print the description
_fputts(szProductDesc, of);
_fputtc('\n', of);
}
// returns <0 if when is before st, ==0 if they are the same date, and
// >0 if when is after st.
int CompDate(
IN DWORD when, // treated as a time_t
IN const PSYSTEMTIME st)
{
time_t when_t;
//
// time_t is 64 bits in win64. Convert, being careful to sign extend.
//
when_t = (time_t)((LONG)(when));
struct tm *t = localtime(&when_t);
if ((t->tm_year+1900) < st->wYear) {
return -1;
}
if ((t->tm_year+1900) > st->wYear) {
return 1;
}
if ((t->tm_mon+1) < st->wMonth) {
return -1;
}
if ((t->tm_mon+1) > st->wMonth) {
return 1;
}
if (t->tm_mday < st->wDay) {
return -1;
}
if (t->tm_mday > st->wDay) {
return 1;
}
return 0;
}
// From the Platform SDK.
void
UnixTimeToFileTime(
IN time_t t,
OUT LPFILETIME pft)
{
// Note that LONGLONG is a 64-bit value
LONGLONG ll;
ll = Int32x32To64(t, 10000000) + 116444736000000000;
pft->dwLowDateTime = (DWORD)ll;
pft->dwHighDateTime = (DWORD)(ll >> 32);
}
// Also from the Platform SDK.
void
UnixTimeToSystemTime(
IN time_t t,
OUT LPSYSTEMTIME pst)
{
FILETIME ft;
UnixTimeToFileTime(t, &ft);
FileTimeToSystemTime(&ft, pst);
}