Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

555 lines
14 KiB

//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 2000-2000
//
// File: expperm.cpp
//
// Contents:
//
// History:
//
// Note:
//---------------------------------------------------------------------------
#include "pch.cpp"
#include <tchar.h>
#include <process.h>
#include "lscommon.h"
#include "debug.h"
#include "globals.h"
#include "db.h"
#include "keypack.h"
#include "clilic.h"
#include "server.h"
#define EXPIRE_THREAD_INITIAL_SLEEP (1000*60) /* 1 minute */
#define EXPIRATION_DAYS 30
#define DELETE_EXPIRED_TEMPORARY_IN_DAYS L"EffectiveDaysToDeleteTemporary"
/*++
Function:
CalculateEffectiveTemporaryExpiration
Description:
Calculate the license expiration.
Argument:
pExpiration - The expiration date and time of the license.
Return:
TRUE if the expiration is calculated successfully or FALSE otherwise.
--*/
BOOL
CalculateEffectiveTemporaryExpiration(
PDWORD pdwExpiration )
{
DWORD dwDays = EXPIRATION_DAYS;
DWORD dwStatus = ERROR_SUCCESS;
HKEY hKey = NULL;
time_t
now = time( NULL );
if( NULL == pdwExpiration )
{
return( FALSE );
}
//-------------------------------------------------------------------
//
// Open HKLM\system\currentcontrolset\sevices\termservlicensing\parameters
//
//-------------------------------------------------------------------
dwStatus =RegCreateKeyEx(
HKEY_LOCAL_MACHINE,
LSERVER_REGISTRY_BASE _TEXT(SZSERVICENAME) _TEXT("\\") LSERVER_PARAMETERS,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_READ,
NULL,
&hKey,
NULL
);
if(dwStatus == ERROR_SUCCESS)
{
DWORD dwBuffer;
DWORD cbBuffer = sizeof(DWORD);
dwStatus = RegQueryValueEx(
hKey,
DELETE_EXPIRED_TEMPORARY_IN_DAYS,
NULL,
NULL,
(LPBYTE)&dwBuffer,
&cbBuffer
);
RegCloseKey(hKey);
if(dwStatus == ERROR_SUCCESS)
{
dwDays = (dwBuffer <7) ? 30: (dwBuffer);
}
}
DWORD dwTemp = (dwDays * 24 *60 *60);
DWORD dwNow = (DWORD)now;
if(dwNow > dwTemp)
dwNow -= dwTemp;
else
dwNow -= (EXPIRATION_DAYS * 24 *60 *60);
*pdwExpiration = dwNow;
return( TRUE );
}
unsigned int WINAPI
DeleteExpiredTemporaryLicenses()
{
DWORD dwStatus=ERROR_SUCCESS;
LICENSEDCLIENT search_license;
DWORD dwTempLicenseExpiration;
memset(&search_license,0,sizeof(search_license));
DBGPrintf(
DBG_INFORMATION,
DBGLEVEL_FUNCTION_DETAILSIMPLE,
DBG_ALL_LEVEL,
_TEXT("ExpireTemporary : ready...\n")
);
PTLSDbWorkSpace pDbWkSpace = NULL;
LICENSEDCLIENT found_license;
TLSLICENSEPACK search_keypack;
TLSLICENSEPACK found_keypack;
if( !CalculateEffectiveTemporaryExpiration(&dwTempLicenseExpiration))
return TLS_E_INTERNAL;
search_license.ftExpireDate = dwTempLicenseExpiration;
memset(&found_license,0,sizeof(found_license));
memset(&search_keypack,0,sizeof(search_keypack));
memset(&found_keypack,0,sizeof(found_keypack));
if (!(ALLOCATEDBHANDLE(pDbWkSpace, g_EnumDbTimeout)))
{
dwStatus = TLS_E_ALLOCATE_HANDLE;
return dwStatus;
}
TLSDBLockKeyPackTable();
TLSDBLockLicenseTable();
CLEANUPSTMT;
dwStatus = TLSDBLicenseEnumBeginEx(
USEHANDLE(pDbWkSpace),
TRUE,
LSLICENSE_SEARCH_EXPIREDATE,
&search_license,
JET_bitSeekLE
);
if (ERROR_SUCCESS != dwStatus)
{
TLSDBUnlockLicenseTable();
TLSDBUnlockKeyPackTable();
FREEDBHANDLE(pDbWkSpace);
return TLS_E_INTERNAL;
}
while (1)
{
dwStatus = TLSDBLicenseEnumNextEx(
USEHANDLE(pDbWkSpace),
TRUE, // bReverse
TRUE, // bAnyRecord
&found_license
);
if(dwStatus != ERROR_SUCCESS)
{
goto next_time;
}
//
// See if this is the right product type
//
search_keypack.dwKeyPackId = found_license.dwKeyPackId;
dwStatus = TLSDBKeyPackFind(
USEHANDLE(pDbWkSpace),
TRUE,
LSKEYPACK_EXSEARCH_DWINTERNAL,
&search_keypack,
&found_keypack
);
if(dwStatus != ERROR_SUCCESS)
{
continue;
}
//
// Only check per-seat temporary
//
if (found_keypack.ucAgreementType != LSKEYPACKTYPE_TEMPORARY)
{
continue;
}
BEGIN_TRANSACTION(pDbWorkSpace);
// Delete currently enumerated license.
dwStatus = TLSDBDeleteEnumeratedLicense(USEHANDLE(pDbWkSpace));
if (dwStatus == ERROR_SUCCESS)
{
dwStatus = TLSDBReturnLicenseToKeyPack(
USEHANDLE(pDbWkSpace),
found_license.dwKeyPackId,
found_license.dwNumLicenses
);
}
if(dwStatus == ERROR_SUCCESS)
{
COMMIT_TRANSACTION(pDbWkSpace);
}
else
{
ROLLBACK_TRANSACTION(pDbWkSpace);
}
}
next_time:
TLSDBLicenseEnumEnd(USEHANDLE(pDbWkSpace));
TLSDBUnlockLicenseTable();
TLSDBUnlockKeyPackTable();
FREEDBHANDLE(pDbWkSpace);
return dwStatus;
}
//---------------------------------------------------------------------
unsigned int WINAPI
ExpirePermanentThread(void* ptr)
{
HANDLE hEvent=(HANDLE) ptr;
DWORD dwStatus=ERROR_SUCCESS;
LICENSEDCLIENT search_license;
memset(&search_license,0,sizeof(search_license));
//
// Signal initializer thread we are ready
//
SetEvent(hEvent);
DBGPrintf(
DBG_INFORMATION,
DBGLEVEL_FUNCTION_DETAILSIMPLE,
DBG_ALL_LEVEL,
_TEXT("ExpirePermanent : ready...\n")
);
//
// Give service chance to initialize
//
Sleep(EXPIRE_THREAD_INITIAL_SLEEP);
//
// Forever loop
//
while(1)
{
DeleteExpiredTemporaryLicenses();
PTLSDbWorkSpace pDbWkSpace = NULL;
LICENSEDCLIENT found_license;
TLSLICENSEPACK search_keypack;
TLSLICENSEPACK found_keypack;
search_license.ftExpireDate = time(NULL);
memset(&found_license,0,sizeof(found_license));
memset(&search_keypack,0,sizeof(search_keypack));
memset(&found_keypack,0,sizeof(found_keypack));
if (!(ALLOCATEDBHANDLE(pDbWkSpace, g_EnumDbTimeout)))
{
goto do_sleep;
}
TLSDBLockKeyPackTable();
TLSDBLockLicenseTable();
CLEANUPSTMT;
dwStatus = TLSDBLicenseEnumBeginEx(
USEHANDLE(pDbWkSpace),
TRUE,
LSLICENSE_SEARCH_EXPIREDATE,
&search_license,
JET_bitSeekLE
);
if (ERROR_SUCCESS != dwStatus)
{
TLSDBUnlockLicenseTable();
TLSDBUnlockKeyPackTable();
FREEDBHANDLE(pDbWkSpace);
goto do_sleep;
}
while (1)
{
dwStatus = TLSDBLicenseEnumNextEx(
USEHANDLE(pDbWkSpace),
TRUE, // bReverse
TRUE, // bAnyRecord
&found_license
);
if(dwStatus != ERROR_SUCCESS)
{
goto next_time;
}
//
// See if this is the right product type
//
search_keypack.dwKeyPackId = found_license.dwKeyPackId;
dwStatus = TLSDBKeyPackFind(
USEHANDLE(pDbWkSpace),
TRUE,
LSKEYPACK_EXSEARCH_DWINTERNAL,
&search_keypack,
&found_keypack
);
if(dwStatus != ERROR_SUCCESS)
{
continue;
}
//
// only check licenses that we reissue
//
if(found_keypack.ucAgreementType != LSKEYPACKTYPE_RETAIL &&
found_keypack.ucAgreementType != LSKEYPACKTYPE_SELECT &&
found_keypack.ucAgreementType != LSKEYPACKTYPE_FREE &&
found_keypack.ucAgreementType != LSKEYPACKTYPE_OPEN )
{
continue;
}
UCHAR ucKeyPackStatus = found_keypack.ucKeyPackStatus &
~LSKEYPACKSTATUS_RESERVED;
//
// Don't check pending activation key pack
//
if(ucKeyPackStatus != LSKEYPACKSTATUS_ACTIVE)
{
continue;
}
//
// Only check per-seat and concurrent
//
if ((_tcsnicmp(found_keypack.szProductId,
TERMSERV_PRODUCTID_SKU,
_tcslen(TERMSERV_PRODUCTID_SKU)) != 0)
&& (_tcsnicmp(found_keypack.szProductId,
TERMSERV_PRODUCTID_CONCURRENT_SKU,
_tcslen(TERMSERV_PRODUCTID_CONCURRENT_SKU)) != 0))
{
continue;
}
BEGIN_TRANSACTION(pDbWorkSpace);
//
// Return currently enumerated license.
//
dwStatus = TLSDBDeleteEnumeratedLicense(USEHANDLE(pDbWkSpace));
if (dwStatus == ERROR_SUCCESS)
{
//
// Adjust available license number.
//
dwStatus = TLSDBReturnLicenseToKeyPack(
USEHANDLE(pDbWkSpace),
found_license.dwKeyPackId,
found_license.dwNumLicenses
);
}
if (dwStatus == ERROR_SUCCESS)
{
COMMIT_TRANSACTION(pDbWkSpace);
InterlockedIncrement(&g_lPermanentLicensesReturned);
}
else
{
ROLLBACK_TRANSACTION(pDbWkSpace);
}
}
next_time:
TLSDBLicenseEnumEnd(USEHANDLE(pDbWkSpace));
TLSDBUnlockLicenseTable();
TLSDBUnlockKeyPackTable();
FREEDBHANDLE(pDbWkSpace);
do_sleep:
if (WAIT_OBJECT_0 == WaitForSingleObject(GetServiceShutdownHandle(),g_dwReissueExpireThreadSleep))
{
break;
}
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_DETAILSIMPLE,
_TEXT("ExpirePermanent : woke up\n")
);
}
//
// Initializer function will close the event handle
//
return dwStatus;
}
//---------------------------------------------------------------------
DWORD
InitExpirePermanentThread()
/*++
++*/
{
HANDLE hThread = NULL;
unsigned int dwThreadId;
HANDLE hEvent = NULL;
DWORD dwStatus = ERROR_SUCCESS;
HANDLE waithandles[2];
//
// Create a event for namedpipe thread to signal it is ready.
//
hEvent = CreateEvent(
NULL,
FALSE,
FALSE, // non-signal
NULL
);
if(hEvent == NULL)
{
dwStatus = GetLastError();
goto cleanup;
}
hThread = (HANDLE)_beginthreadex(
NULL,
0,
ExpirePermanentThread,
hEvent,
0,
&dwThreadId
);
if(hThread == NULL)
{
dwStatus = GetLastError();
goto cleanup;
}
waithandles[0] = hEvent;
waithandles[1] = hThread;
//
// Wait 30 second for thread to complete initialization
//
dwStatus = WaitForMultipleObjects(
sizeof(waithandles)/sizeof(waithandles[0]),
waithandles,
FALSE,
30*1000
);
if(dwStatus == WAIT_OBJECT_0)
{
//
// thread is ready
//
dwStatus = ERROR_SUCCESS;
}
else
{
if(dwStatus == (WAIT_OBJECT_0 + 1))
{
//
// Thread terminate abnormally
//
GetExitCodeThread(
hThread,
&dwStatus
);
}
else
{
dwStatus = TLS_E_SERVICE_STARTUP_CREATE_THREAD;
}
}
cleanup:
if(hEvent != NULL)
{
CloseHandle(hEvent);
}
if(hThread != NULL)
{
CloseHandle(hThread);
}
return dwStatus;
}