|
|
/*--------------------------------------------------------------
* * 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
} }
|