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.
705 lines
17 KiB
705 lines
17 KiB
/*--------------------------------------------------------------
|
|
*
|
|
* FILE: SKEYDLL.C
|
|
*
|
|
* PURPOSE: The file contains the SerialKeys DLL Functions
|
|
*
|
|
* CREATION: June 1994
|
|
*
|
|
* COPYRIGHT: Black Diamond Software (C) 1994
|
|
*
|
|
* AUTHOR: Ronald Moak
|
|
*
|
|
* $Header: %Z% %F% %H% %T% %I%
|
|
*
|
|
*------------------------------------------------------------*/
|
|
|
|
#include "windows.h"
|
|
#include "..\skeys\sk_dllif.h"
|
|
#include "..\skeys\sk_dll.h"
|
|
#include "..\skeys\sk_reg.h"
|
|
#include "skeys.h"
|
|
#include <malloc.h>
|
|
#include "w95trace.c"
|
|
|
|
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
|
|
|
#define RUNNINGEVENT TEXT("SkeysRunning")
|
|
#define ONE_MINUTE (60 * 1000)
|
|
|
|
static BOOL SerialKeysInstall(void);
|
|
static BOOL IsSerialKeysRunning();
|
|
static BOOL IsServiceStartAllowed();
|
|
static BOOL WaitForServiceRunning();
|
|
|
|
|
|
/*---------------------------------------------------------------
|
|
*
|
|
* FUNCTION int APIENTRY LibMain
|
|
*
|
|
* TYPE Global
|
|
*
|
|
* PURPOSE LibMain is called by Windows when
|
|
* the DLL is initialized, Thread Attached, and other times.
|
|
* Refer to SDK documentation, as to the different ways this
|
|
* may be called.
|
|
*
|
|
* The LibMain function should perform additional initialization
|
|
* tasks required by the DLL. In this example, no initialization
|
|
* tasks are required. LibMain should return a value of 1 if
|
|
* the initialization is successful.
|
|
*
|
|
* INPUTS
|
|
*
|
|
* RETURNS TRUE - Transfer Ok
|
|
* FALSE- Transfer Failed
|
|
*
|
|
*---------------------------------------------------------------*/
|
|
INT APIENTRY LibMain(HANDLE hInst, DWORD ul_reason_being_called, LPVOID lpReserved)
|
|
{
|
|
return 1;
|
|
|
|
UNREFERENCED_PARAMETER(hInst);
|
|
UNREFERENCED_PARAMETER(ul_reason_being_called);
|
|
UNREFERENCED_PARAMETER(lpReserved);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------
|
|
*
|
|
* FUNCTION void SkeyGetRegistryValues()
|
|
*
|
|
* TYPE Global
|
|
*
|
|
* PURPOSE Reads the values from the registry into the
|
|
* SerialKeys structure
|
|
*
|
|
* INPUTS None
|
|
*
|
|
* RETURNS None
|
|
*
|
|
*---------------------------------------------------------------*/
|
|
static BOOL SkeyGetRegistryValues(HKEY hkey, LPSERIALKEYS psk)
|
|
{
|
|
LONG lErr;
|
|
DWORD dwType;
|
|
DWORD cbData;
|
|
|
|
psk->iPortState = 0;
|
|
psk->iActive = 0;
|
|
|
|
psk->dwFlags = 0;
|
|
cbData = sizeof(psk->dwFlags);
|
|
|
|
lErr = RegQueryValueEx(
|
|
hkey,
|
|
REG_FLAGS,
|
|
0,
|
|
&dwType,
|
|
(LPBYTE)&psk->dwFlags,
|
|
&cbData);
|
|
|
|
if (ERROR_SUCCESS != lErr || dwType != REG_DWORD)
|
|
{
|
|
psk->dwFlags = 0;
|
|
}
|
|
|
|
psk->dwFlags |= SERKF_AVAILABLE;
|
|
|
|
if (NULL != psk->lpszActivePort)
|
|
{
|
|
cbData = MAX_PATH * sizeof(*psk->lpszActivePort);
|
|
lErr = RegQueryValueEx(
|
|
hkey,
|
|
REG_ACTIVEPORT,
|
|
0,
|
|
&dwType,
|
|
(LPBYTE)psk->lpszActivePort,
|
|
&cbData);
|
|
|
|
psk->lpszActivePort[ MAX_PATH - 1 ] = '\0'; // ports are all MAX_PATH tchars
|
|
|
|
if (ERROR_SUCCESS != lErr || dwType != REG_SZ)
|
|
{
|
|
lstrcpy(psk->lpszActivePort, TEXT("COM1"));
|
|
}
|
|
}
|
|
|
|
if (NULL != psk->lpszPort)
|
|
{
|
|
cbData = MAX_PATH * sizeof(*psk->lpszPort);
|
|
lErr = RegQueryValueEx(
|
|
hkey,
|
|
REG_PORT,
|
|
0,
|
|
&dwType,
|
|
(LPBYTE)psk->lpszPort,
|
|
&cbData);
|
|
|
|
psk->lpszPort[ MAX_PATH - 1 ] = '\0'; // ports are all MAX_PATH tchars
|
|
|
|
if (ERROR_SUCCESS != lErr || dwType != REG_SZ)
|
|
{
|
|
lstrcpy(psk->lpszPort, TEXT("COM1"));
|
|
}
|
|
}
|
|
|
|
cbData = sizeof(psk->iBaudRate);
|
|
lErr = RegQueryValueEx(
|
|
hkey,
|
|
REG_BAUD,
|
|
0,&dwType,
|
|
(LPBYTE)&psk->iBaudRate,
|
|
&cbData);
|
|
|
|
if (ERROR_SUCCESS != lErr || dwType != REG_DWORD)
|
|
{
|
|
psk->iBaudRate = 300;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------
|
|
*
|
|
* FUNCTION BOOL SkeyGetUserValues()
|
|
*
|
|
* TYPE Local
|
|
*
|
|
* PURPOSE Read the registery an collect the data for the current
|
|
* user.
|
|
*
|
|
* RETURNS TRUE - User wants Serial Keys Enabled
|
|
* FALSE- User wants Serial Keys Disabled
|
|
*
|
|
*---------------------------------------------------------------*/
|
|
BOOL SkeyGetUserValues(LPSERIALKEYS psk)
|
|
{
|
|
BOOL fOk = FALSE;
|
|
HKEY hkey;
|
|
DWORD dwRet;
|
|
DWORD dwDisposition;
|
|
|
|
dwRet = RegCreateKeyEx( HKEY_CURRENT_USER,
|
|
TEXT("Control Panel\\Accessibility\\SerialKeys"),
|
|
0,
|
|
NULL, // CLASS NAME??
|
|
0, // by default is non-volatile
|
|
KEY_READ,
|
|
NULL, // default security descriptor
|
|
&hkey,
|
|
&dwDisposition); // yes we throw this away
|
|
|
|
if (ERROR_SUCCESS == dwRet)
|
|
{
|
|
fOk = SkeyGetRegistryValues(hkey, psk);
|
|
RegCloseKey(hkey);
|
|
}
|
|
if (fOk)
|
|
{
|
|
// Not available unless the service is running or this
|
|
// user can start it
|
|
if (IsSerialKeysRunning() || IsServiceStartAllowed())
|
|
{
|
|
psk->dwFlags |= SERKF_AVAILABLE;
|
|
}
|
|
else
|
|
{
|
|
psk->dwFlags &= ~SERKF_AVAILABLE;
|
|
}
|
|
}
|
|
return(fOk);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------
|
|
*
|
|
* FUNCTION void SetRegistryValues()
|
|
*
|
|
* TYPE Global
|
|
*
|
|
* PURPOSE Writes the values in the SerialKeys structure to
|
|
* the Registry.
|
|
*
|
|
* INPUTS None
|
|
*
|
|
* RETURNS None
|
|
*
|
|
*---------------------------------------------------------------*/
|
|
static BOOL SkeySetRegistryValues(HKEY hkey, LPSERIALKEYS psk)
|
|
{
|
|
LONG lErr;
|
|
BOOL fOk;
|
|
DWORD dwFlags;
|
|
|
|
dwFlags = psk->dwFlags | SERKF_AVAILABLE;
|
|
lErr = RegSetValueEx( // Write dwFlags
|
|
hkey,
|
|
REG_FLAGS,
|
|
0,REG_DWORD,
|
|
(CONST LPBYTE)&dwFlags,
|
|
sizeof(DWORD));
|
|
|
|
fOk = (ERROR_SUCCESS == lErr);
|
|
|
|
if (fOk)
|
|
{
|
|
lErr = RegSetValueEx( // Write Active Port
|
|
hkey,
|
|
REG_ACTIVEPORT,
|
|
0,REG_SZ,
|
|
(CONST LPBYTE) psk->lpszActivePort,
|
|
(NULL == psk->lpszActivePort) ? 0 :
|
|
(lstrlen(psk->lpszActivePort) + 1) *
|
|
sizeof(*psk->lpszActivePort));
|
|
|
|
fOk = (ERROR_SUCCESS == lErr);
|
|
}
|
|
|
|
if (fOk)
|
|
{
|
|
lErr = RegSetValueEx( // Write Active Port
|
|
hkey,
|
|
REG_PORT,
|
|
0,REG_SZ,
|
|
(CONST LPBYTE)psk->lpszPort,
|
|
(NULL == psk->lpszPort) ? 0 :
|
|
(lstrlen(psk->lpszPort) + 1) * sizeof(*psk->lpszPort));
|
|
|
|
fOk = (ERROR_SUCCESS == lErr);
|
|
}
|
|
|
|
if (fOk)
|
|
{
|
|
lErr = RegSetValueEx( // Write Active Port
|
|
hkey,
|
|
REG_BAUD,
|
|
0,REG_DWORD,
|
|
(CONST LPBYTE) &psk->iBaudRate,
|
|
sizeof(psk->iBaudRate));
|
|
|
|
fOk = (ERROR_SUCCESS == lErr);
|
|
}
|
|
|
|
return fOk;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------
|
|
*
|
|
* FUNCTION void SetUserValues()
|
|
*
|
|
* TYPE Global
|
|
*
|
|
* PURPOSE This function writes out information to the
|
|
* registry.
|
|
*
|
|
* INPUTS None
|
|
*
|
|
* RETURNS TRUE - Write Successful
|
|
* FALSE- Write Failed
|
|
*
|
|
*---------------------------------------------------------------*/
|
|
BOOL SkeySetUserValues(LPSERIALKEYS psk)
|
|
{
|
|
BOOL fOk = FALSE;
|
|
HKEY hkey;
|
|
DWORD dwRet;
|
|
DWORD dwDisposition;
|
|
|
|
dwRet = RegCreateKeyEx(
|
|
HKEY_CURRENT_USER,
|
|
TEXT("Control Panel\\Accessibility\\SerialKeys"),
|
|
0,
|
|
NULL, // class name
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_READ | KEY_WRITE,
|
|
NULL, // default security descriptor
|
|
&hkey,
|
|
&dwDisposition); // yes we throw this away
|
|
|
|
if (ERROR_SUCCESS == dwRet)
|
|
{
|
|
fOk = SkeySetRegistryValues(hkey, psk);
|
|
RegCloseKey(hkey);
|
|
}
|
|
return(fOk);
|
|
}
|
|
|
|
#if 0 // This old code is no longer needed ////////////////////////////////////
|
|
/*---------------------------------------------------------------
|
|
*
|
|
* FUNCTION BOOL IsSerialKeysInstalled();
|
|
*
|
|
* TYPE Local
|
|
*
|
|
* PURPOSE This function passes the information from the
|
|
* Serial Keys application to the Server
|
|
*
|
|
* INPUTS None
|
|
*
|
|
* RETURNS TRUE - SerialKeys is Installed
|
|
* FALSE- SerialKeys Not Installed
|
|
*
|
|
*---------------------------------------------------------------*/
|
|
static BOOL IsSerialKeysInstalled()
|
|
{
|
|
|
|
SC_HANDLE schService = NULL;
|
|
SC_HANDLE schSCManager = NULL;
|
|
|
|
BOOL fOk = FALSE;
|
|
//
|
|
// Check if the Serial Keys Service is installed
|
|
schSCManager = OpenSCManager
|
|
(
|
|
NULL, // machine (NULL == local)
|
|
NULL, // database (NULL == default)
|
|
SC_MANAGER_ALL_ACCESS // access required
|
|
);
|
|
|
|
if (NULL != schSCManager)
|
|
{
|
|
schService = OpenService(schSCManager, "SerialKeys", SERVICE_ALL_ACCESS);
|
|
|
|
if (NULL != schService)
|
|
{
|
|
CloseServiceHandle(schService);
|
|
fOk = TRUE;
|
|
}
|
|
|
|
CloseServiceHandle(schSCManager);
|
|
}
|
|
|
|
return fOk;
|
|
}
|
|
#endif ////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL IsSerialKeysRunning()
|
|
{
|
|
BOOL fRunning = FALSE;
|
|
HANDLE hEventSkeysServiceRunning;
|
|
|
|
hEventSkeysServiceRunning = OpenEvent(SYNCHRONIZE, FALSE, RUNNINGEVENT);
|
|
if (NULL != hEventSkeysServiceRunning)
|
|
{
|
|
DWORD dwWait;
|
|
|
|
dwWait = WaitForSingleObject(hEventSkeysServiceRunning, 0);
|
|
|
|
fRunning = (WAIT_OBJECT_0 == dwWait);
|
|
CloseHandle(hEventSkeysServiceRunning);
|
|
}
|
|
return fRunning;
|
|
}
|
|
|
|
|
|
BOOL IsServiceStartAllowed()
|
|
{
|
|
BOOL fServiceStartAllowed = FALSE;
|
|
|
|
SC_HANDLE schSCManager = NULL;
|
|
|
|
schSCManager = OpenSCManager( // Open Service Manager
|
|
NULL, // machine (NULL == local)
|
|
NULL, // database (NULL == default)
|
|
SC_MANAGER_CREATE_SERVICE); // access required
|
|
|
|
if (NULL != schSCManager) // Did Open Service succeed?
|
|
{
|
|
CloseServiceHandle(schSCManager);
|
|
fServiceStartAllowed = TRUE;
|
|
}
|
|
|
|
return fServiceStartAllowed;
|
|
}
|
|
|
|
|
|
BOOL SkeyServiceRequest(UINT uAction, LPSERIALKEYS psk, BOOL fWinIni)
|
|
{
|
|
BOOL fOk = FALSE;
|
|
SKEYDLL SKeyDLL;
|
|
DWORD bytesRead;
|
|
|
|
if (IsSerialKeysRunning())
|
|
{
|
|
memset(&SKeyDLL, 0, sizeof(SKeyDLL));
|
|
SKeyDLL.Message = uAction;
|
|
if (psk->lpszActivePort != NULL)
|
|
{
|
|
strcpy(SKeyDLL.szActivePort,psk->lpszActivePort);
|
|
}
|
|
|
|
if (psk->lpszPort != NULL)
|
|
{
|
|
strcpy(SKeyDLL.szPort,psk->lpszPort);
|
|
}
|
|
|
|
SKeyDLL.dwFlags = psk->dwFlags | SERKF_AVAILABLE;
|
|
SKeyDLL.iBaudRate = psk->iBaudRate;
|
|
SKeyDLL.iPortState = psk->iPortState;
|
|
SKeyDLL.iSave = fWinIni;
|
|
|
|
fOk = CallNamedPipe(
|
|
SKEY_NAME, // Pipe name
|
|
&SKeyDLL,
|
|
sizeof(SKeyDLL),
|
|
&SKeyDLL,
|
|
sizeof(SKeyDLL),
|
|
&bytesRead,
|
|
NMPWAIT_USE_DEFAULT_WAIT);
|
|
|
|
if (fOk)
|
|
{
|
|
if (psk->lpszActivePort != NULL)
|
|
{
|
|
strcpy(psk->lpszActivePort,SKeyDLL.szActivePort);
|
|
}
|
|
|
|
if (psk->lpszPort != NULL)
|
|
{
|
|
strcpy(psk->lpszPort,SKeyDLL.szPort);
|
|
}
|
|
|
|
psk->dwFlags = SKeyDLL.dwFlags | SERKF_AVAILABLE;
|
|
psk->iBaudRate = SKeyDLL.iBaudRate;
|
|
psk->iPortState = SKeyDLL.iPortState;
|
|
}
|
|
}
|
|
return fOk;
|
|
}
|
|
|
|
|
|
BOOL SkeyInitUser()
|
|
{
|
|
BOOL fOk;
|
|
SERIALKEYS sk;
|
|
TCHAR szActivePort[MAX_PATH]; // all ports are expected to be MAX_PATH tchars
|
|
TCHAR szPort[MAX_PATH]; // all ports are expected to be MAX_PATH tchars
|
|
|
|
|
|
memset(&sk, 0, sizeof(sk));
|
|
sk.cbSize = sizeof(sk);
|
|
sk.lpszActivePort = szActivePort;
|
|
sk.lpszPort = szPort;
|
|
|
|
fOk = SkeyGetUserValues(&sk);
|
|
if (fOk)
|
|
{
|
|
fOk = SkeyServiceRequest(SPI_SETSERIALKEYS, &sk, FALSE);
|
|
}
|
|
return fOk;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------
|
|
*
|
|
* FUNCTION int APIENTRY SKEY_SystemParameterInfo
|
|
*
|
|
* TYPE Global
|
|
*
|
|
* PURPOSE This function passes the information from the
|
|
* Serial Keys application to the Server
|
|
*
|
|
* INPUTS
|
|
*
|
|
* RETURNS TRUE - Transfer Ok
|
|
* FALSE- Transfer Failed
|
|
*
|
|
*---------------------------------------------------------------*/
|
|
BOOL APIENTRY SKEY_SystemParametersInfo(
|
|
UINT uAction,
|
|
UINT uParam,
|
|
LPSERIALKEYS psk,
|
|
BOOL fWinIni)
|
|
{
|
|
BOOL fOk;
|
|
BOOL fStarted;
|
|
|
|
fOk = ((uAction == SK_SPI_INITUSER) ||
|
|
(NULL != psk && (0 != psk->cbSize)));
|
|
|
|
if (fOk)
|
|
{
|
|
switch (uAction)
|
|
{
|
|
case SPI_SETSERIALKEYS:
|
|
fOk = SkeySetUserValues(psk);
|
|
|
|
if (fOk && (psk->dwFlags & SERKF_SERIALKEYSON) && IsServiceStartAllowed())
|
|
{
|
|
fOk = SerialKeysInstall();
|
|
}
|
|
|
|
if (fOk && IsSerialKeysRunning())
|
|
{
|
|
fOk = SkeyInitUser();
|
|
}
|
|
|
|
break;
|
|
|
|
case SPI_GETSERIALKEYS:
|
|
fOk = SkeyGetUserValues(psk);
|
|
if (fOk && (psk->dwFlags & SERKF_SERIALKEYSON) &&
|
|
!IsSerialKeysRunning() && IsServiceStartAllowed())
|
|
{
|
|
fOk = SerialKeysInstall();
|
|
}
|
|
|
|
if (fOk && IsSerialKeysRunning())
|
|
{
|
|
fOk = SkeyInitUser();
|
|
}
|
|
|
|
break;
|
|
|
|
case SK_SPI_INITUSER:
|
|
// give the service a chance to start
|
|
fStarted = WaitForServiceRunning();
|
|
|
|
if (!fStarted)
|
|
{
|
|
// service does not seem to be running
|
|
// let's try to start it
|
|
fOk = SkeyGetUserValues(psk);
|
|
|
|
if (fOk && (psk->dwFlags & SERKF_SERIALKEYSON) &&
|
|
!IsSerialKeysRunning() && IsServiceStartAllowed())
|
|
{
|
|
SerialKeysInstall();
|
|
}
|
|
|
|
if (IsSerialKeysRunning())
|
|
{
|
|
fOk = SkeyInitUser();
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
fOk = FALSE; // No - Fail
|
|
}
|
|
}
|
|
return fOk;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* WaitForServiceRunning - wait up to one minute for the SerialKeys service
|
|
* to signal it is ready. CreateEvent has been called by SKeys.exe before
|
|
* this function is executed.
|
|
*/
|
|
BOOL WaitForServiceRunning()
|
|
{
|
|
BOOL fOk = FALSE;
|
|
HANDLE hEventSkeysServiceRunning = OpenEvent(SYNCHRONIZE, FALSE, RUNNINGEVENT);
|
|
|
|
if (hEventSkeysServiceRunning)
|
|
{
|
|
DWORD dwWait = WaitForSingleObject(hEventSkeysServiceRunning, ONE_MINUTE);
|
|
CloseHandle(hEventSkeysServiceRunning);
|
|
|
|
fOk = (WAIT_OBJECT_0 == dwWait);
|
|
}
|
|
|
|
return fOk;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
BOOL SerialKeysInstall(void)
|
|
{
|
|
BOOL fStarted = FALSE;
|
|
SERVICE_STATUS ssStatus;
|
|
DWORD dwOldCheckPoint;
|
|
TCHAR szFileName[MAX_PATH + 1];
|
|
|
|
SC_HANDLE schService = NULL;
|
|
SC_HANDLE schSCManager = NULL;
|
|
|
|
schSCManager = OpenSCManager( // Open Service Manager
|
|
NULL, // machine (NULL == local)
|
|
NULL, // database (NULL == default)
|
|
SC_MANAGER_ALL_ACCESS); // access required
|
|
|
|
if (NULL != schSCManager) // Did Open Service succeed?
|
|
{
|
|
schService = OpenService(
|
|
schSCManager ,
|
|
__TEXT("SerialKeys"),
|
|
SERVICE_ALL_ACCESS);
|
|
|
|
if (NULL != schService)
|
|
{
|
|
// insure the serivce is auto-start
|
|
|
|
ChangeServiceConfig(
|
|
schService,
|
|
SERVICE_WIN32_OWN_PROCESS,
|
|
SERVICE_AUTO_START, // when to start service
|
|
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
|
|
}
|
|
else
|
|
{
|
|
if (!GetWindowsDirectory(szFileName, ARRAY_SIZE(szFileName)))
|
|
return FALSE; // PREFIX #113665 don't use szFileName if call fails
|
|
|
|
lstrcat(szFileName, __TEXT("\\system32\\skeys.exe"));
|
|
|
|
// Is Service File installed?
|
|
if (0xFFFFFFFF != GetFileAttributes(szFileName))
|
|
{
|
|
schService = CreateService(
|
|
schSCManager, // SCManager database
|
|
__TEXT("SerialKeys"), // name of service
|
|
__TEXT("SerialKeys"), // name to display
|
|
SERVICE_ALL_ACCESS, // desired access
|
|
SERVICE_WIN32_OWN_PROCESS, // service type
|
|
SERVICE_AUTO_START, // start type
|
|
SERVICE_ERROR_NORMAL, // error control type
|
|
szFileName, // service's binary
|
|
NULL, // no load ordering group
|
|
NULL, // no tag identifier
|
|
NULL, // no dependencies
|
|
NULL, // LocalSystem account
|
|
NULL); // no password
|
|
}
|
|
}
|
|
if (NULL != schService)
|
|
{
|
|
BOOL fOk = QueryServiceStatus(schService,&ssStatus);
|
|
if (fOk && ssStatus.dwCurrentState != SERVICE_RUNNING)
|
|
{
|
|
static PTSTR pszArg = TEXT("F\0"); // force service to start
|
|
PTSTR apszArg[] = {pszArg, NULL};
|
|
|
|
if (StartService(schService, 1, apszArg))
|
|
{
|
|
while(fOk && ssStatus.dwCurrentState != SERVICE_RUNNING)
|
|
{
|
|
dwOldCheckPoint = ssStatus.dwCheckPoint;
|
|
Sleep(max(ssStatus.dwWaitHint, 1000));
|
|
fOk = QueryServiceStatus(schService,&ssStatus);
|
|
fOk = (fOk && (dwOldCheckPoint >= ssStatus.dwCheckPoint));
|
|
}
|
|
}
|
|
}
|
|
fStarted = fOk && (ssStatus.dwCurrentState == SERVICE_RUNNING);
|
|
CloseServiceHandle(schService);
|
|
|
|
if (fStarted)
|
|
{
|
|
fStarted = WaitForServiceRunning();
|
|
}
|
|
}
|
|
CloseServiceHandle(schSCManager);
|
|
}
|
|
return fStarted;
|
|
}
|