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.
712 lines
13 KiB
712 lines
13 KiB
/*++
|
|
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
STIMON.CPP
|
|
|
|
Abstract:
|
|
|
|
This module contains code for process, running STI/WIA services
|
|
|
|
Service process is specific for Windows9x OS and represents a wrapper necessary
|
|
to create execution environment. On NT svchost.exe or similar will be used to host
|
|
service.
|
|
|
|
|
|
Author:
|
|
|
|
Vlad Sadovsky (vlads) 03-20-99
|
|
|
|
Environment:
|
|
|
|
User Mode - Win32
|
|
|
|
Revision History:
|
|
|
|
03-20-99 VladS created
|
|
|
|
--*/
|
|
|
|
//
|
|
// Include Headers
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "resource.h"
|
|
#include "initguid.h"
|
|
|
|
#include <atlapp.h>
|
|
#include <atltmp.h>
|
|
|
|
#include <regstr.h>
|
|
|
|
#include "stimon.h"
|
|
#include "memory.h"
|
|
#include "util.h"
|
|
|
|
|
|
//
|
|
// STL includes
|
|
//
|
|
#include <algorithm>
|
|
#include <vector>
|
|
#include <list>
|
|
|
|
|
|
#include <eventlog.h>
|
|
|
|
//
|
|
// Service list manager
|
|
//
|
|
#include "svclist.h"
|
|
#include <winsvc.h>
|
|
|
|
|
|
//
|
|
// Local variables and types definitions
|
|
//
|
|
|
|
using namespace std;
|
|
|
|
#ifdef USE_MULTIPLE_SERVICES
|
|
list<SERVICE_ENTRY> ServiceList;
|
|
CComAutoCriticalSection csServiceList;
|
|
#endif
|
|
|
|
HANDLE ServerStartedEvent = NULL;
|
|
|
|
CMainWindow * pMainWindow = NULL;
|
|
|
|
SERVICE_ENTRY * pImageServices = NULL;
|
|
|
|
//
|
|
// Local prototypes
|
|
//
|
|
|
|
DWORD
|
|
InitGlobalConfigFromReg(
|
|
VOID
|
|
);
|
|
|
|
BOOL
|
|
DoGlobalInit(
|
|
VOID
|
|
);
|
|
|
|
BOOL
|
|
DoGlobalTermination(
|
|
VOID
|
|
);
|
|
|
|
BOOL
|
|
UpdateRunningServer(
|
|
VOID
|
|
);
|
|
|
|
HWND
|
|
CreateMasterWindow(
|
|
VOID
|
|
);
|
|
|
|
BOOL
|
|
StartMasterLoop(
|
|
PVOID pv
|
|
);
|
|
|
|
BOOL
|
|
StartOperation(
|
|
VOID
|
|
);
|
|
|
|
BOOL
|
|
ParseCommandLine(
|
|
LPSTR lpszCmdLine,
|
|
UINT *pargc,
|
|
PTSTR *argv
|
|
);
|
|
|
|
|
|
BOOL
|
|
LoadImageService(
|
|
PTSTR pszServiceName,
|
|
UINT argc,
|
|
LPTSTR *argv
|
|
);
|
|
|
|
LONG
|
|
OpenServiceParametersKey (
|
|
LPCTSTR pszServiceName,
|
|
HKEY* phkey
|
|
);
|
|
|
|
LONG
|
|
WINAPI
|
|
StimonUnhandledExceptionFilter(
|
|
struct _EXCEPTION_POINTERS *ExceptionInfo
|
|
);
|
|
|
|
DWORD
|
|
WINAPI
|
|
StiServiceInstall(
|
|
LPTSTR lpszUserName,
|
|
LPTSTR lpszUserPassword
|
|
);
|
|
|
|
DWORD
|
|
WINAPI
|
|
StiServiceRemove(
|
|
VOID
|
|
);
|
|
|
|
//
|
|
// Missing definitions from Win9x version of windows.h
|
|
//
|
|
|
|
#define RSP_UNREGISTER_SERVICE 0x00000000
|
|
#define RSP_SIMPLE_SERVICE 0x00000001
|
|
|
|
typedef DWORD WINAPI REGISTERSERVICEPROCESS(
|
|
DWORD dwProcessId,
|
|
DWORD dwServiceType);
|
|
|
|
//#include "atlexe_i.c"
|
|
|
|
LONG CExeModule::Unlock()
|
|
{
|
|
LONG l = CComModule::Unlock();
|
|
return l;
|
|
}
|
|
|
|
CExeModule _Module;
|
|
|
|
BEGIN_OBJECT_MAP(ObjectMap)
|
|
END_OBJECT_MAP()
|
|
|
|
|
|
extern "C"
|
|
int
|
|
WINAPI
|
|
#ifdef UNICODE
|
|
_tWinMain
|
|
#else
|
|
WinMain
|
|
#endif
|
|
(
|
|
HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPTSTR lpCmdLine,
|
|
int nShowCmd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
WinMain
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
Side effects:
|
|
|
|
--*/
|
|
{
|
|
|
|
UINT argc;
|
|
PTSTR argv[10];
|
|
|
|
DWORD err;
|
|
HRESULT hres;
|
|
|
|
TCHAR szCommandLine[255];
|
|
UINT i = 0;
|
|
REGISTERSERVICEPROCESS *pfnRegServiceProcess = NULL;
|
|
|
|
DBGTRACE __s(TEXT("StiMON::WinMain"));
|
|
|
|
HRESULT hRes = CoInitializeEx(0,COINIT_MULTITHREADED);
|
|
// ASSERT SUCCEEDED(hRes)
|
|
|
|
//
|
|
// To use built-in ATL conversion macros
|
|
//
|
|
USES_CONVERSION;
|
|
|
|
_Module.Init(ObjectMap, hInstance);
|
|
|
|
CMessageLoop cMasterLoop;
|
|
|
|
lpCmdLine = GetCommandLine(); //this line necessary for _ATL_MIN_CRT
|
|
|
|
::lstrcpyn(szCommandLine,lpCmdLine,(sizeof(szCommandLine) / sizeof(szCommandLine[0])) - 1);
|
|
szCommandLine[sizeof(szCommandLine)/sizeof(szCommandLine[0]) - 1] = TEXT('\0');
|
|
|
|
//
|
|
// Disable hard-error popups and set unhnadled exception filter
|
|
//
|
|
::SetErrorMode( SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX );
|
|
|
|
::SetUnhandledExceptionFilter(&StimonUnhandledExceptionFilter);
|
|
|
|
//
|
|
// Initialize globals. If this routine fails, we have to exit immideately
|
|
//
|
|
if(NOERROR != InitGlobalConfigFromReg()) {
|
|
goto ExitMain;
|
|
}
|
|
|
|
//
|
|
// Parse command line , set up needed options
|
|
//
|
|
ParseCommandLine(szCommandLine,&argc,&argv[0]);
|
|
|
|
DPRINTF(DM_TRACE,TEXT("STIMON: starting with the commnd line : %s "), lpCmdLine);
|
|
|
|
//
|
|
// Other instances of STIMON running ?
|
|
//
|
|
ServerStartedEvent = ::CreateSemaphore( NULL,
|
|
0,
|
|
1,
|
|
STIStartedEvent_name);
|
|
err = ::GetLastError();
|
|
|
|
if ((hPrevInstance) || (err == ERROR_ALREADY_EXISTS)) {
|
|
|
|
if (UpdateRunningServer()) {
|
|
goto ExitAlreadyRunning;
|
|
}
|
|
|
|
//
|
|
// Win9x specific: If first instance exists - signal it should stop
|
|
//
|
|
if ( g_fStoppingRequest ) {
|
|
ReleaseSemaphore(ServerStartedEvent,1,NULL);
|
|
}
|
|
}
|
|
|
|
DPRINTF(DM_TRACE ,TEXT("STIMON proceeding to create service instance"));
|
|
|
|
//
|
|
// Do global initialization, independent of specific service
|
|
//
|
|
if (!DoGlobalInit()) {
|
|
goto ExitMain;
|
|
}
|
|
|
|
//
|
|
// If command line is special - process it and bail out
|
|
//
|
|
if (g_fRemovingRequest) {
|
|
StiServiceRemove();
|
|
goto ExitMain;
|
|
}
|
|
else if (g_fInstallingRequest) {
|
|
StiServiceInstall(NULL,NULL);
|
|
goto ExitMain;
|
|
}
|
|
|
|
//
|
|
// Tell system we are running as service to prevent shutting down on relogon
|
|
//
|
|
|
|
#ifndef WINNT
|
|
if (g_fRunningAsService) {
|
|
|
|
pfnRegServiceProcess = (REGISTERSERVICEPROCESS *)GetProcAddress(
|
|
GetModuleHandleA("kernel32.dll"),
|
|
"RegisterServiceProcess");
|
|
if (pfnRegServiceProcess) {
|
|
pfnRegServiceProcess(::GetCurrentProcessId(), RSP_SIMPLE_SERVICE);
|
|
} else {
|
|
|
|
//
|
|
// Print out the warning and let the server continue
|
|
//
|
|
DPRINTF(DM_ERROR, TEXT("RegisterServiceProcess() is not exported by kernel32.dll"));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Load and prepare service DLL for execution
|
|
//
|
|
if ( !LoadImageService(STI_SERVICE_NAME,argc,argv) ) {
|
|
DPRINTF(DM_ERROR, TEXT("Unable load imaging service DLL Error=%d"),::GetLastError() );
|
|
goto ExitMain;
|
|
}
|
|
|
|
#if USE_HIDDEN_WINDOW
|
|
//
|
|
// Create hidden window to receive system-wide notifications
|
|
//
|
|
pMainWindow = new CMainWindow;
|
|
pMainWindow->Create();
|
|
|
|
cMasterLoop.Run();
|
|
#else
|
|
|
|
//
|
|
// Wait till somebody wakes us up
|
|
//
|
|
// WaitForSingleObject(ServerStartedEvent,INFINITE);
|
|
|
|
#endif
|
|
|
|
ExitMain:
|
|
|
|
//
|
|
// Global cleanup
|
|
//
|
|
DPRINTF(DM_TRACE, TEXT("STIMON coming to global cleanup") );
|
|
|
|
//
|
|
// Deregister with kernel (Win9x specific)
|
|
//
|
|
#ifndef WINNT
|
|
if (g_fRunningAsService) {
|
|
|
|
if (pfnRegServiceProcess) {
|
|
pfnRegServiceProcess(::GetCurrentProcessId(), RSP_UNREGISTER_SERVICE);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
DoGlobalTermination();
|
|
|
|
ExitAlreadyRunning:
|
|
|
|
CoUninitialize();
|
|
|
|
return 0;
|
|
}
|
|
|
|
BOOL
|
|
DoGlobalInit(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
#ifdef MAXDEBUG
|
|
StiSetDebugMask(0xffff);
|
|
StiSetDebugParameters(TEXT("STIMON"),TEXT(""));
|
|
#endif
|
|
|
|
|
|
//
|
|
// Do misc. cleanup, which we need to do on startup .
|
|
//
|
|
// 1. Some shipping packages for Win98 register STIMON entry to Run section, which
|
|
// after upgrade creates problem with racing two copies of STIMON. Remove it.
|
|
// 2. Register WIA service if there is STIMON left over in Run section
|
|
//
|
|
|
|
HKEY hkRun = NULL;
|
|
LONG lRet ;
|
|
ULONG lcbValue = 0;
|
|
BOOL fNeedToRegister = FALSE;
|
|
TCHAR szSvcPath[MAX_PATH] = {TEXT('0')};
|
|
|
|
if (RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_RUN, &hkRun) == NO_ERROR) {
|
|
|
|
DPRINTF(DM_TRACE,TEXT("Removing erroneous entry on cleanup: HKLM\\..\\Run\\%s"),REGSTR_VAL_MONITOR);
|
|
|
|
lcbValue = sizeof(szSvcPath);
|
|
lRet = RegQueryValueEx(hkRun,REGSTR_VAL_MONITOR,NULL,NULL,(LPBYTE)szSvcPath,&lcbValue);
|
|
|
|
fNeedToRegister = (lRet == NOERROR);
|
|
|
|
lRet = RegDeleteValue (hkRun, REGSTR_VAL_MONITOR);
|
|
RegCloseKey(hkRun);
|
|
}
|
|
|
|
if (fNeedToRegister ) {
|
|
|
|
LONG lLen;
|
|
LONG lNameIndex = 0;
|
|
|
|
lLen = ::GetModuleFileName(NULL, szSvcPath, sizeof(szSvcPath)/sizeof(szSvcPath[0]));
|
|
|
|
DPRINTF(DM_TRACE,TEXT("Adding STIMON to RunServices entry on cleanup path is : %s"),szSvcPath);
|
|
|
|
if ( lLen) {
|
|
|
|
if (RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_RUNSERVICES , &hkRun) == NO_ERROR) {
|
|
|
|
DPRINTF(DM_TRACE,TEXT("Adding STIMON to RunServices entry on cleanup: HKLM\\..\\RunServices\\%s"),REGSTR_VAL_MONITOR);
|
|
|
|
lcbValue = (::lstrlen(szSvcPath) + 1 ) * sizeof(szSvcPath[0]);
|
|
lRet = RegSetValueEx(hkRun,REGSTR_VAL_MONITOR,NULL,REG_SZ,(LPBYTE)szSvcPath,(DWORD)lcbValue);
|
|
|
|
RegCloseKey(hkRun);
|
|
}
|
|
}
|
|
else {
|
|
DPRINTF(DM_ERROR ,TEXT("Failed to get my own path registering Still Image service monitor. LastError=%d "), ::GetLastError());
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
DoGlobalTermination(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
|
|
if (ServerStartedEvent) {
|
|
::CloseHandle(ServerStartedEvent);
|
|
}
|
|
|
|
//
|
|
// Shut down message loop
|
|
//
|
|
PostQuitMessage(0);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
UpdateRunningServer(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
HWND hExistingWindow;
|
|
|
|
hExistingWindow = ::FindWindow(g_szClass,NULL);
|
|
|
|
if (!hExistingWindow) {
|
|
|
|
DPRINTF(DM_TRACE ,TEXT("STIMON second instance did not find first one "));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Server already running , find it 's window and send a message
|
|
// with new values of parameters
|
|
//
|
|
|
|
//
|
|
// If instructed to stop - do that
|
|
//
|
|
if ( g_fStoppingRequest ) {
|
|
//
|
|
// This is Win9x specific
|
|
//
|
|
DPRINTF(DM_TRACE ,TEXT("STIMON is trying to close first service instance with handle %X"),hExistingWindow);
|
|
|
|
::PostMessage(hExistingWindow,WM_CLOSE,0,0L);
|
|
}
|
|
else {
|
|
|
|
// Refresh requested ?
|
|
if (g_fRefreshDeviceList) {
|
|
// Refresh device list
|
|
::PostMessage(hExistingWindow,STIMON_MSG_REFRESH,1,0L);
|
|
}
|
|
|
|
if (STIMON_AD_DEFAULT_POLL_INTERVAL != g_uiDefaultPollTimeout) {
|
|
::SendMessage(hExistingWindow,STIMON_MSG_SET_PARAMETERS,STIMON_MSG_SET_TIMEOUT,g_uiDefaultPollTimeout);
|
|
}
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
LoadImageService(
|
|
PTSTR pszServiceName,
|
|
UINT argc,
|
|
LPTSTR *argv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Attempts to load and initialize the imaging services DLL.
|
|
|
|
Calls initialization related services.
|
|
|
|
Arguments:
|
|
|
|
Action - Specifies the initialization action.
|
|
|
|
Return Value:
|
|
|
|
TRUE on success, FALSE on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
HKEY hkeyService;
|
|
HKEY hkeyParams;
|
|
|
|
LONG lr = 0;
|
|
|
|
pImageServices = new SERVICE_ENTRY(pszServiceName);
|
|
|
|
if (pImageServices) {
|
|
|
|
LPSERVICE_MAIN_FUNCTION pfnMain;
|
|
|
|
pfnMain = pImageServices->GetServiceMainFunction();
|
|
|
|
//
|
|
// Call main entry point
|
|
//
|
|
if (pfnMain) {
|
|
pfnMain(argc,argv);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
LONG
|
|
WINAPI
|
|
StimonUnhandledExceptionFilter(
|
|
struct _EXCEPTION_POINTERS *ExceptionInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Filter for catching unhnalded exceptions
|
|
|
|
Arguments:
|
|
|
|
Standard
|
|
|
|
Return Value:
|
|
|
|
NOERROR
|
|
|
|
Side effects:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PCTSTR pszCommandLine;
|
|
PVOID Addr;
|
|
|
|
pszCommandLine = GetCommandLine ();
|
|
if (!pszCommandLine || !*pszCommandLine) {
|
|
pszCommandLine = TEXT("<error getting command line>");
|
|
}
|
|
|
|
#if DBG
|
|
DebugBreak();
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
WINAPI
|
|
StiServiceInstall(
|
|
LPTSTR lpszUserName,
|
|
LPTSTR lpszUserPassword
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Service installation function.
|
|
Calls SCM to install STI service, which is running in user security context
|
|
|
|
BUGBUG Review
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
|
|
DWORD dwError = NOERROR;
|
|
|
|
return dwError;
|
|
|
|
} //StiServiceInstall
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
StiServiceRemove(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Service removal function. This function calls SCM to remove the STI service.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Return code. Return zero for success
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD dwError = NOERROR;
|
|
|
|
return dwError;
|
|
|
|
} // StiServiceRemove
|
|
|