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.
 
 
 
 
 
 

1149 lines
28 KiB

/*--------------------------------------------------------------
*
* FILE: SKeys.c
*
* PURPOSE: The main interface routines between the service
* manager and the Serial Keys program.
*
* CREATION: June 1994
*
* COPYRIGHT: Black Diamond Software (C) 1994
*
* AUTHOR: Ronald Moak
*
* NOTES:
*
* This file, and all others associated with it contains trade secrets
* and information that is proprietary to Black Diamond Software.
* It may not be copied copied or distributed to any person or firm
* without the express written permission of Black Diamond Software.
* This permission is available only in the form of a Software Source
* License Agreement.
*
* $Header: %Z% %F% %H% %T% %I%
*
*--- Includes ---------------------------------------------------------*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <tchar.h>
#include "vars.h"
#include "w95trace.c"
#define DEFDATA 1
#include "sk_defs.h"
#include "sk_comm.h"
#include "sk_reg.h"
#include "sk_dll.h"
#include "sk_login.h"
#include "sk_ex.h"
#include "..\skdll\skeys.h"
#define LONGSTRINGSIZE 1024
#define WAITMAX 0x7FFFFFFF
#define RUNNINGEVENT TEXT("SkeysRunning")
#if defined(DEBUG) && 0
// give us a long time to startup in case we're debugging
#define WAITSTARTUP WAITMAX
#else
// normal startup time
#define WAITSTARTUP 60000
#endif
// --- Local Variables --------------------------------------------------
static SERVICE_STATUS_HANDLE s_sshStatusHandle;
static SERVICE_STATUS s_ssStatus; // current status of the service
PTSTR SERVICENAME = TEXT("SerialKeys");
PTSTR SKEYSUSERINITCMD = TEXT("SKEYS /I");
PTSTR WINLOGONPATH = TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon");
PTSTR USERINIT = TEXT("Userinit");
PTSTR USERINITCMDSEP = TEXT(",");
DWORD s_dwServiceCommand;
static HANDLE s_hEventServiceRequest = NULL;
static HANDLE s_hEventServiceRequestReady = NULL;
static HANDLE s_hEventServiceTerminate = NULL;
static HANDLE s_hEventSkeysServiceRunning = NULL;
void DoService();
void DoInit();
void InstallUserInit();
BOOL IsSerialKeysAutoStart();
//--- SCM Function Prototypes ------------------------------------------------
//
// Note: The following fuctions manage the connection of the service
// with the Service Contol Manager.
void PostEventLog(LPTSTR lpszMsg,DWORD Error);
VOID ServiceMain(DWORD dwArgc, LPTSTR *ppszArgv);
VOID StopSerialKeys(LPTSTR lpszMsg);
BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
DWORD dwWin32ExitCode,
DWORD dwCheckPoint,
DWORD dwWaitHint);
LPHANDLER_FUNCTION ServiceCtrl(DWORD dwCtrlCode);
// Service Routines -----------------------------------------------
//
// Note: The following fuctions manage the internal control of the
// Service
static void InitReg();
static BOOL InitService();
static void PauseService();
static void ProcessService();
static void ResumeService();
static void TerminateService();
static void ProcessLogout(DWORD dwCtrlType);
static BOOL InstallLogout();
static BOOL TerminateLogout();
static void EnableService(BOOL fOn);
// CONSIDER - Removing this code. It only gets executed when SKeys is
// run from the command line. When run as a service, ServiceMain is
// called when the service is started. The sources file pulls in
// winmain from the runtime lib. DoInit and DoService could also be
// removed with _tWinMain.
int WINAPI _tWinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PTSTR pszCmdLine,
int nCmdShow)
{
if ((TEXT('/') == pszCmdLine[0] || TEXT('-') == pszCmdLine[0]) &&
(TEXT('I') == pszCmdLine[1] || TEXT('i') == pszCmdLine[1]))
{
DoInit();
}
else
{
DoService();
}
ExitProcess(0);
return(0);
}
/*---------------------------------------------------------------
*
* FUNCTION DoInit()
*
* TYPE Global
*
* PURPOSE This function is called to read skeys configuration
* from HKEY_CURRENT_USER at logon session startup and
* send the information to the service
*
* INPUTS None
*
* RETURNS None
*
*---------------------------------------------------------------*/
void DoInit()
{
HANDLE hEventSkeysServiceRunning = NULL;
PSECURITY_DESCRIPTOR pSD;
SECURITY_ATTRIBUTES sa;
pSD = CreateSd(SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE);
if (pSD)
{
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = pSD;
hEventSkeysServiceRunning = CreateEvent(
&sa, // Security
TRUE, // Manual reset?
FALSE, // initial state - not signaled
RUNNINGEVENT); // name
free(pSD);
}
if (NULL != hEventSkeysServiceRunning)
{
DWORD dwWait;
dwWait = WaitForSingleObject(hEventSkeysServiceRunning, 60 * 1000);
if (WAIT_OBJECT_0 == dwWait)
{
SKEY_SystemParametersInfo((UINT)SK_SPI_INITUSER, 0, NULL, 0);
}
CloseHandle(hEventSkeysServiceRunning);
}
return;
}
/*---------------------------------------------------------------
*
* SCM Interface Functions
*
/*---------------------------------------------------------------
*
* FUNCTION DoService()
*
* TYPE Global
*
* PURPOSE all DoService does is call StartServiceCtrlDispatcher
* to register the main service thread. When the
* API returns, the service has stopped, so exit.
*
* INPUTS None
*
* RETURNS None
*
*---------------------------------------------------------------*/
void DoService()
{
SERVICE_TABLE_ENTRY dispatchTable[] =
{
{ SERVICENAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain },
{ NULL, NULL }
};
PSECURITY_DESCRIPTOR pSD;
SECURITY_ATTRIBUTES sa;
s_hEventServiceRequest = CreateEvent(
NULL, // Security
FALSE, // Manual reset?
FALSE, // initial state - not signaled
NULL); // name
s_hEventServiceRequestReady = CreateEvent(
NULL, // Security
FALSE, // Manual reset?
TRUE, // initial state - signaled (can accept one request even before ready)
NULL); // name
s_hEventServiceTerminate = CreateEvent(
NULL, // Security
TRUE, // Manual reset?
FALSE, // initial state - not signaled
NULL); // name
s_hEventSkeysServiceRunning = NULL;
pSD = CreateSd(SYNCHRONIZE|EVENT_MODIFY_STATE|GENERIC_READ|GENERIC_WRITE);
DBPRINTF(TEXT("DoService: CreateSd %s\r\n"), (pSD)?TEXT("Succeeded"):TEXT("Failed"));
if (pSD)
{
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = pSD;
s_hEventSkeysServiceRunning = CreateEvent(
&sa, // Security
TRUE, // Manual reset?
FALSE, // initial state - not signaled
RUNNINGEVENT); // name
free(pSD);
}
if (NULL != s_hEventServiceRequest &&
NULL != s_hEventServiceRequestReady &&
NULL != s_hEventServiceTerminate &&
NULL != s_hEventSkeysServiceRunning)
{
DBPRINTF(TEXT("DoService: calling StartServiceCtrlDispatcher... \r\n"));
if (!StartServiceCtrlDispatcher(dispatchTable))
{
DBPRINTF(TEXT("DoService: StartServiceCtrlDispatcher FAILED\r\n"));
StopSerialKeys(TEXT("StartServiceCtrlDispatcher failed."));
}
}
else
{
DBPRINTF(TEXT("DoService: Unable to create event %p %p %p %p\r\n"), s_hEventServiceRequest, s_hEventServiceRequestReady, s_hEventServiceTerminate, s_hEventSkeysServiceRunning);
StopSerialKeys(TEXT("Unable to create event."));
}
if (NULL != s_hEventServiceRequest)
{
CloseHandle(s_hEventServiceRequest);
}
if (NULL != s_hEventServiceRequestReady)
{
CloseHandle(s_hEventServiceRequestReady);
}
if (NULL != s_hEventServiceTerminate)
{
CloseHandle(s_hEventServiceTerminate);
}
if (NULL != s_hEventSkeysServiceRunning)
{
ResetEvent(s_hEventSkeysServiceRunning);
CloseHandle(s_hEventSkeysServiceRunning);
}
}
/*---------------------------------------------------------------
*
* FUNCTION ServiceMain()
*
* TYPE Global
*
* PURPOSE this function takes care of actually starting the service,
* informing the service controller at each step along the way.
* After launching the worker thread, it waits on the event
* that the worker thread will signal at its termination.
*
* INPUTS None
*
* RETURNS None
*
*---------------------------------------------------------------*/
VOID ServiceMain(DWORD dwArgc, LPTSTR *ppszArgv)
{
DBPRINTF(TEXT("ServiceMain()\r\n"));
//
// SERVICE_STATUS members that don't change
s_ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
s_ssStatus.dwServiceSpecificExitCode = 0;
//
// register our service control handler:
s_sshStatusHandle = RegisterServiceCtrlHandler(
SERVICENAME,
(LPHANDLER_FUNCTION) ServiceCtrl);
if (!s_sshStatusHandle)
{
TerminateService(GetLastError());
return;
}
// report the status to Service Control Manager.
ReportStatusToSCMgr(
SERVICE_START_PENDING, // service state
NO_ERROR, // exit code
1, // checkpoint
WAITSTARTUP); // wait hint
#if defined(DEBUG) && 0 /////////////////////////////////////////////////
// This debug code gives us time to attach a debugger
{
int i;
for (i = 0; i < 180; i++) // 180 sec = 3 min
{
Sleep(1000); // one second
}
}
#endif ////////////////////////////////////////////////////////
InitReg();
GetUserValues(REG_DEF);
////EnableService(skNewKey.dwFlags & SERKF_SERIALKEYSON);
if (!InitService()) // Did Service Initiate successfully?
{
TerminateService(GetLastError()); // No Terminate With Error
return;
}
ReportStatusToSCMgr( // report status to service manager.
SERVICE_RUNNING, // service state
NO_ERROR, // exit code
0, // checkpoint
0); // wait hint
SetEvent(s_hEventSkeysServiceRunning);
ProcessService(); // Process the Service
TerminateService(0); // Terminate
return;
}
BOOL IsSerialKeysAutoStart()
{
BOOL fAutoStart = FALSE;
BOOL fOk;
SC_HANDLE schService = NULL;
SC_HANDLE schSCManager = NULL;
schSCManager = OpenSCManager( // Open Service Manager
NULL, // machine (NULL == local)
NULL, // database (NULL == default)
MAXIMUM_ALLOWED);
if (NULL != schSCManager) // Did Open Service succeed?
{
schService = OpenService(
schSCManager ,
__TEXT("SerialKeys"),
MAXIMUM_ALLOWED);
if (NULL != schService)
{
BYTE abServiceConfig[1024];
LPQUERY_SERVICE_CONFIG pqsc = (LPQUERY_SERVICE_CONFIG)abServiceConfig;
DWORD cbBytesNeeded;
fOk = QueryServiceConfig(
schService,
pqsc,
sizeof(abServiceConfig),
&cbBytesNeeded);
if (fOk)
{
fAutoStart = (SERVICE_AUTO_START == pqsc->dwStartType);
}
CloseServiceHandle(schService);
}
CloseServiceHandle(schSCManager);
}
return fAutoStart;
}
void InstallUserInit()
{
BOOL fOk = FALSE;
HKEY hkey;
LONG lErr;
DWORD dwType;
TCHAR szUserinit[LONGSTRINGSIZE];
DWORD cbData = sizeof(szUserinit);
lErr = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
WINLOGONPATH,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
&hkey);
if (ERROR_SUCCESS == lErr)
{
lErr = RegQueryValueEx(
hkey,
USERINIT,
0,
&dwType,
(LPBYTE)szUserinit,
&cbData);
szUserinit[LONGSTRINGSIZE-1]='\0';
if (ERROR_SUCCESS == lErr && dwType == REG_SZ)
{
// check to see if we are already installed and if we have
// enough room to install
// the + 2 allows for the terminating null and for the command seperator char
if (NULL == _tcsstr(szUserinit, SKEYSUSERINITCMD) &&
lstrlen(szUserinit) + lstrlen(SKEYSUSERINITCMD) + 2 <
ARRAY_SIZE(szUserinit))
{
lstrcat(szUserinit, USERINITCMDSEP);
lstrcat(szUserinit, SKEYSUSERINITCMD);
RegSetValueEx(
hkey,
USERINIT,
0,
REG_SZ,
(CONST LPBYTE)szUserinit,
(lstrlen(szUserinit) + 1) *
sizeof(*szUserinit));
}
}
RegCloseKey(hkey);
}
return;
}
void RemoveUserInit()
{
BOOL fOk = FALSE;
HKEY hkey;
LONG lErr;
DWORD dwType;
TCHAR szUserinit[LONGSTRINGSIZE];
PTSTR pszDest;
PTSTR pszSrc;
DWORD cbData = sizeof(szUserinit);
lErr = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
WINLOGONPATH,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
&hkey);
if (ERROR_SUCCESS == lErr)
{
lErr = RegQueryValueEx(
hkey,
USERINIT,
0,
&dwType,
(LPBYTE)szUserinit,
&cbData);
szUserinit[LONGSTRINGSIZE-1]='\0';
if (ERROR_SUCCESS == lErr && dwType == REG_SZ)
{
// check to see if we are already installed
pszDest = _tcsstr(szUserinit, SKEYSUSERINITCMD);
if (NULL != pszDest)
{
pszSrc =_tcsstr(pszDest, USERINITCMDSEP);
if (NULL != pszSrc)
{
_tcscpy(pszDest, pszSrc+1);
}
else
{
while(szUserinit < pszDest && *SKEYSUSERINITCMD != *pszDest)
{
--pszDest;
}
*pszDest = 0; // null terminate
}
}
RegSetValueEx(
hkey,
USERINIT,
0,
REG_SZ,
(CONST LPBYTE)szUserinit,
(lstrlen(szUserinit) + 1) *
sizeof(*szUserinit));
}
RegCloseKey(hkey);
}
return;
}
static void EnableService(BOOL fOn)
{
SC_HANDLE schService = NULL;
SC_HANDLE schSCManager = NULL;
schSCManager = OpenSCManager( // Open Service Manager
NULL, // machine (NULL == local)
NULL, // database (NULL == default)
MAXIMUM_ALLOWED);
if (NULL != schSCManager) // Did Open Service succeed?
{
schService = OpenService(
schSCManager ,
__TEXT("SerialKeys"),
SERVICE_CHANGE_CONFIG | SERVICE_STOP);
if (NULL != schService)
{
ChangeServiceConfig(
schService,
SERVICE_WIN32_OWN_PROCESS,
(fOn) ? SERVICE_AUTO_START : SERVICE_DEMAND_START,
SERVICE_NO_CHANGE, // severity if service fails to start
NULL, // pointer to service binary file name
NULL, // pointer to load ordering group name
NULL, // pointer to variable to get tag identifier
NULL, // pointer to array of dependency names
NULL, // pointer to account name of service
NULL, // pointer to password for service account
__TEXT("SerialKeys")); // name to display
CloseServiceHandle(schService);
}
CloseServiceHandle(schSCManager);
}
if (fOn)
{
InstallUserInit();
}
else
{
RemoveUserInit();
}
return;
}
//---------------------------------------------------------------
//
// FUNCTION void ServiceCtrl(DWORD dwCtrlCode)
//
// TYPE Global
//
// PURPOSE this function is called by the Service Controller whenever
// someone calls ControlService in reference to our service.
//
// INPUTS DWORD dwCtrlCode -
//
// RETURNS None
//
//-----------------------------------------------------------------
LPHANDLER_FUNCTION ServiceCtrl(DWORD dwCtrlCode)
{
DWORD dwState = SERVICE_RUNNING;
DWORD dwWait = 0;
DBPRINTF(TEXT("ServiceCtrl()\r\n"));
// Handle the requested control code.
switch(dwCtrlCode)
{
case SERVICE_CONTROL_PAUSE: // Pause the service if it is running.
if (s_ssStatus.dwCurrentState == SERVICE_RUNNING)
{
PauseService();
dwState = SERVICE_PAUSED;
}
break;
case SERVICE_CONTROL_CONTINUE: // Resume the paused service.
if (s_ssStatus.dwCurrentState == SERVICE_PAUSED)
{
ResumeService();
dwState = SERVICE_RUNNING;
}
break;
case SERVICE_CONTROL_STOP: // Stop the service.
// Report the status, specifying the checkpoint and waithint,
// before setting the termination event.
if (s_ssStatus.dwCurrentState == SERVICE_RUNNING)
{
dwState = SERVICE_STOP_PENDING;
dwWait = 20000;
SetEvent(s_hEventServiceTerminate);
}
break;
case SERVICE_CONTROL_INTERROGATE: // Update the service status.
default: // invalid control code
break;
}
// send a status response.
ReportStatusToSCMgr(dwState, NO_ERROR, 0, dwWait);
return(0);
}
/*---------------------------------------------------------------
*
* FUNCTION BOOL ReportStatusToSCMgr()
*
* TYPE Global
*
* PURPOSE This function is called by the ServMainFunc() and
* ServCtrlHandler() functions to update the service's status
* to the service control manager.
*
* INPUTS DWORD dwCurrentState
* DWORD dwWin32ExitCode
* DWORD dwCheckPoint
* DWORD dwWaitHint
*
* RETURNS None
*
*---------------------------------------------------------------*/
BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
DWORD dwWin32ExitCode,
DWORD dwCheckPoint,
DWORD dwWaitHint)
{
BOOL fResult;
#ifdef DEBUG
{
switch (dwCurrentState)
{
case SERVICE_START_PENDING:
DBPRINTF(TEXT("ReportStatusToSCMgr(SERVICE_START_PENDING:)\r\n"));
break;
case SERVICE_PAUSED:
DBPRINTF(TEXT("ReportStatusToSCMgr(SERVICE_PAUSED:)\r\n"));
break;
case SERVICE_CONTINUE_PENDING:
DBPRINTF(TEXT("ReportStatusToSCMgr(SERVICE_CONTINUE_PENDING:)\r\n"));
break;
case SERVICE_STOP_PENDING:
DBPRINTF(TEXT("ReportStatusToSCMgr(SERVICE_STOP_PENDING:)\r\n"));
break;
case SERVICE_STOPPED:
DBPRINTF(TEXT("ReportStatusToSCMgr(SERVICE_STOPPED:)\r\n"));
break;
case SERVICE_RUNNING:
DBPRINTF(TEXT("ReportStatusToSCMgr(SERVICE_RUNNING:)\r\n"));
break;
default:
DBPRINTF(TEXT("ReportStatusToSCMgr(ERROR - SERVICE_UNKNOWN)\r\n"));
break;
}
}
#endif
switch (dwCurrentState)
{
case SERVICE_STOPPED:
case SERVICE_START_PENDING:
case SERVICE_STOP_PENDING:
s_ssStatus.dwControlsAccepted = 0;
break;
default:
s_ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
break;
}
// These SERVICE_STATUS members are set from parameters.
s_ssStatus.dwCurrentState = dwCurrentState;
s_ssStatus.dwWin32ExitCode = dwWin32ExitCode;
s_ssStatus.dwCheckPoint = dwCheckPoint;
s_ssStatus.dwWaitHint = dwWaitHint;
// Report the status of the service to the service control manager.
fResult = SetServiceStatus(
s_sshStatusHandle, // service reference handle
&s_ssStatus); // SERVICE_STATUS structure
if (!fResult)
{
StopSerialKeys(TEXT("SetServiceStatus")); // If an error occurs, stop the service.
}
return fResult;
}
/*---------------------------------------------------------------
*
* FUNCTION void StopSerialKeys(LPTSTR lpszMsg)
*
* TYPE Global
*
* PURPOSE The StopSerialKeys function can be used by any thread
* to report an error, or stop the service.
*
* INPUTS LPTSTR lpszMsg -
*
* RETURNS None
*
*---------------------------------------------------------------*/
VOID StopSerialKeys(LPTSTR lpszMsg)
{
DBPRINTF(TEXT("StopSerialKeys()\r\n"));
PostEventLog(lpszMsg,GetLastError()); // Post to Event Log
SetEvent(s_hEventServiceTerminate);
}
/*---------------------------------------------------------------
*
* FUNCTION void PostEventLog(LPTSTR lpszMsg, DWORD Error)
*
* TYPE Local
*
* PURPOSE This function post strings to the Event Log
*
* INPUTS LPTSTR lpszMsg - String to send
* DWORD Error - Error Code (if 0 no error)
*
* RETURNS None
*
*---------------------------------------------------------------*/
void PostEventLog(LPTSTR lpszMsg,DWORD Error)
{
WORD ErrType = EVENTLOG_INFORMATION_TYPE;
WORD ErrStrings = 0;
TCHAR szMsg[256];
HANDLE hEventSource;
LPTSTR lpszStrings[2];
DBPRINTF(TEXT("PostEventLog()\r\n"));
lpszStrings[0] = lpszMsg;
if (Error)
{
ErrType = EVENTLOG_ERROR_TYPE;
ErrStrings = 2;
wsprintf(szMsg, TEXT("SerialKeys error: %d"), Error);
lpszStrings[0] = szMsg;
lpszStrings[1] = lpszMsg;
}
hEventSource = RegisterEventSource(NULL,SERVICENAME);
if (hEventSource != NULL)
{
ReportEvent
(
hEventSource, // handle of event source
ErrType, // event type
0, // event category
0, // event ID
NULL, // current user's SID
ErrStrings, // strings in lpszStrings
0, // no bytes of raw data
lpszStrings, // array of error strings
NULL // no raw data
);
(VOID) DeregisterEventSource(hEventSource);
}
}
/*---------------------------------------------------------------
*
* Internal Service Control Functions
*
/*---------------------------------------------------------------
*
* FUNCTION void InitService()
*
* PURPOSE This function Initializes the Service & starts the
* major threads of the service.
*
* INPUTS None
*
* RETURNS None
*
*---------------------------------------------------------------*/
static BOOL InitService()
{
DBPRINTF(TEXT("InitService()\r\n"));
InstallLogout();
if (!InitDLL())
return(FALSE);
if (!InitLogin())
return(FALSE);
if (!InitComm())
return(FALSE);
DoServiceCommand(SC_LOG_IN); // Set ProcessService to Login Serial Keys
return(TRUE);
}
static void InitReg()
{
// Set Structure pointers to Buffers
skNewKey.cbSize = sizeof(skNewKey);
skNewKey.lpszActivePort = szNewActivePort;
skNewKey.lpszPort = szNewPort;
skCurKey.cbSize = sizeof(skCurKey);
skCurKey.lpszActivePort = szCurActivePort;
skCurKey.lpszPort = szCurPort;
// Set Default Values
skNewKey.dwFlags = SERKF_AVAILABLE;
skNewKey.iBaudRate = 300;
skNewKey.iPortState = 2;
lstrcpy(szNewPort,TEXT("COM1:"));
lstrcpy(szNewActivePort,TEXT("COM1:"));
}
/*---------------------------------------------------------------
*
* FUNCTION void PauseService()
*
* PURPOSE This function is called to pause the service
*
* INPUTS None
*
* RETURNS None
*
*---------------------------------------------------------------*/
static void PauseService()
{
DBPRINTF(TEXT("PauseService()\r\n"));
SuspendDLL();
SuspendComm();
SuspendLogin();
}
/*---------------------------------------------------------------
*
* FUNCTION void DoServiceCommand()
*
* PURPOSE Passes a command to the service thread
*
* INPUTS None
*
* RETURNS None
*
*---------------------------------------------------------------*/
void DoServiceCommand(DWORD dwServiceCommand)
{
DWORD dwWaitRet;
dwWaitRet = WaitForSingleObject(s_hEventServiceRequestReady, 10*1000);
if (WAIT_OBJECT_0 == dwWaitRet)
{
s_dwServiceCommand = dwServiceCommand;
SetEvent(s_hEventServiceRequest);
}
else
{
DBPRINTF(TEXT("DoServiceCommand - wait failed or timed-out, request ignored\r\n"));
}
}
/*---------------------------------------------------------------
*
* FUNCTION void ProcessService()
*
* PURPOSE This function is the main service thread for Serial
* Keys. Is monitors the status of the other theads
* and responds to their request.
*
* INPUTS None
*
* RETURNS None
*
*---------------------------------------------------------------*/
static void ProcessService()
{
DWORD dwServiceCommand;
DWORD dwWaitRet;
typedef enum {
iheventServiceRequest,
iheventServiceTerminate
};
HANDLE ahevent[2] = {s_hEventServiceRequest, s_hEventServiceTerminate};
DBPRINTF(TEXT("ProcessService()\r\n"));
dwWaitRet = WaitForMultipleObjects(ARRAY_SIZE(ahevent), ahevent,
FALSE, // wait all?
INFINITE);
// This loop will terminate when iheventServiceTerminate is signaled or
// WaitForMultipleObjects fails
while (iheventServiceRequest == dwWaitRet - WAIT_OBJECT_0)
{
dwServiceCommand = s_dwServiceCommand;
SetEvent(s_hEventServiceRequestReady);
switch (dwServiceCommand)
{
case SC_LOG_OUT: // Login to New User
DBPRINTF(TEXT("---- User Logging Out\r\n"));
StopComm(); // Stop SerialKey Processing
if(GetUserValues(REG_DEF)) // Get Default values & Do we Start?
{
EnableService(skNewKey.dwFlags & SERKF_SERIALKEYSON);
StartComm(); // Yes - Process SerialKey
}
break;
case SC_LOG_IN: // Login to New User
DBPRINTF(TEXT("---- User Logging In\r\n"));
StopComm(); // Stop SerialKey Processing
if(GetUserValues(REG_DEF))
{
EnableService(skNewKey.dwFlags & SERKF_SERIALKEYSON);
StartComm(); // Yes - Process SerialKey
}
break;
case SC_CHANGE_COMM: // Change Comm Configuration
DBPRINTF(TEXT("---- Making Comm Change\r\n"));
StopComm(); // Stop SerialKey Processing
StartComm(); // Restart SerialKey Processing
break;
case SC_DISABLE_SKEY: // Disable Serial Keys
DBPRINTF(TEXT("---- Disable Serial Keys\r\n"));
StopComm();
break;
case SC_ENABLE_SKEY: // Enable Serial Keys
DBPRINTF(TEXT("---- Enable Serial Keys\r\n"));
StartComm();
break;
}
dwWaitRet = WaitForMultipleObjects(ARRAY_SIZE(ahevent), ahevent,
FALSE, // wait all?
INFINITE);
}
}
/*---------------------------------------------------------------
*
* FUNCTION void ResumeService()
*
* PURPOSE This function is called to restore the service
*
* INPUTS None
*
* RETURNS None
*
*---------------------------------------------------------------*/
static void ResumeService()
{
DBPRINTF(TEXT("ResumeService()\r\n"));
ResumeDLL();
ResumeComm();
ResumeLogin();
}
//---------------------------------------------------------------
//
// FUNCTION void TerminateService(DWORD Error)
//
// TYPE Local
//
// PURPOSE This function is called by ServiceMain to terminate
// the server. It closes all of the open handles &
// and reports the service is stopped.
//
// INPUTS DWORD Error - Any Errors that could abort the
// Service. 0 = Normal Stop
//
// RETURNS None
//
//---------------------------------------------------------------
static void TerminateService(DWORD Error)
{
DBPRINTF(TEXT("TerminateService()\r\n"));
TerminateLogout(); // Remove Logout Monitoring
TerminateComm(); // Init Comm Thread Shutdown
TerminateDLL(); // Init DLL Thread Shutdown
TerminateLogin(); // Init Login Thread Shutdown
// Loop untill all of the Threads are shut down.
while (!DoneLogin()) // Loop until Login Thread is terminated
Sleep(250); // Sleep
while (!DoneDLL()) // Loop until DLL Thread is terminated
Sleep(250); // Sleep
// reload registery values to insure we have the current values
GetUserValues(REG_DEF);
EnableService(skNewKey.dwFlags & SERKF_SERIALKEYSON);
// Report the status is stopped
if (s_sshStatusHandle)
(VOID)ReportStatusToSCMgr(SERVICE_STOPPED,Error,0,0);
}
/*---------------------------------------------------------------
*
* Logout Functions - Process Logout request
*
/*---------------------------------------------------------------
*
* FUNCTION void InstallLogout()
*
* PURPOSE This function installs a Control Handler to process
* logout events.
*
* INPUTS None
*
* RETURNS None
*
*---------------------------------------------------------------*/
static BOOL InstallLogout()
{
DBPRINTF(TEXT("InstallLogout()\r\n"));
return(SetConsoleCtrlHandler((PHANDLER_ROUTINE)ProcessLogout,TRUE));
}
/*---------------------------------------------------------------
*
* FUNCTION void TerminateLogout()
*
* PURPOSE This function Removes a Control Handler to process
* logout events.
*
* INPUTS None
*
* RETURNS None
*
*---------------------------------------------------------------*/
static BOOL TerminateLogout()
{
DBPRINTF(TEXT("TerminateLogout()\r\n"));
return(SetConsoleCtrlHandler((PHANDLER_ROUTINE)ProcessLogout,FALSE));
}
/*---------------------------------------------------------------
*
* FUNCTION void ProcessLogout()
*
* PURPOSE This function processes logout events.
*
* INPUTS None
*
* RETURNS None
*
*---------------------------------------------------------------*/
static void ProcessLogout(DWORD dwCtrlType)
{
DBPRINTF(TEXT("ProcessLogout()\r\n"));
if (dwCtrlType == CTRL_LOGOFF_EVENT)
{
DoServiceCommand(SC_LOG_OUT);
// we'll do this each time the currently logged in user logs out
}
}