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.
1100 lines
21 KiB
1100 lines
21 KiB
/*++
|
|
|
|
|
|
Copyright (c) 1997-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
STIEXE.CPP
|
|
|
|
Abstract:
|
|
|
|
This module contains code for process, running STI+WIA services
|
|
|
|
Author:
|
|
|
|
Vlad Sadovsky (vlads) 09-20-97
|
|
|
|
Environment:
|
|
|
|
User Mode - Win32
|
|
|
|
Revision History:
|
|
|
|
22-Sep-1997 VladS created
|
|
13-Apr-1999 VladS merged with WIA service code
|
|
|
|
|
|
--*/
|
|
|
|
//
|
|
// Include Headers
|
|
//
|
|
#include "precomp.h"
|
|
#include "stiexe.h"
|
|
#include "stirpc.h"
|
|
#include "device.h"
|
|
#include "wiapriv.h"
|
|
#include "lockmgr.h"
|
|
|
|
#include <shlwapi.h>
|
|
#include <regstr.h>
|
|
|
|
CComModule _Module;
|
|
|
|
BEGIN_OBJECT_MAP(ObjectMap)
|
|
// OBJECT_ENTRY(CLSID_Ubj, CObj)
|
|
END_OBJECT_MAP()
|
|
|
|
extern CRITICAL_SECTION g_semDeviceMan;
|
|
extern CRITICAL_SECTION g_semEventNode;
|
|
|
|
|
|
//
|
|
// Local variables and types definitions
|
|
//
|
|
|
|
//
|
|
// Event used for detecting previously started instance of the server
|
|
//
|
|
static HANDLE ServerStartedEvent;
|
|
|
|
//
|
|
// Flag to use service controller PnP event sink vs window message based sink
|
|
//
|
|
extern BOOL g_fUseServiceCtrlSink;
|
|
|
|
//
|
|
// Still Image entry in Registry
|
|
//
|
|
|
|
char* g_szStiKey = "SYSTEM\\CurrentControlSet\\Control\\StillImage";
|
|
|
|
//
|
|
// WIA Debug Window value name
|
|
//
|
|
|
|
char* g_szWiaDebugValue = "ShowWiaDebugWindow";
|
|
|
|
//
|
|
// String value to indicate that debug window should be shown
|
|
//
|
|
|
|
char* g_szShowWiaWinString = "Yes";
|
|
|
|
//
|
|
// Bool values indicating whether Critical Section initialization was successful
|
|
//
|
|
BOOL g_bEventCritSectInitialized = FALSE;
|
|
BOOL g_bDevManCritSectInitialized = FALSE;
|
|
|
|
//
|
|
// Local prototypes
|
|
//
|
|
|
|
DWORD
|
|
InitGlobalConfigFromReg(
|
|
VOID
|
|
);
|
|
|
|
BOOL
|
|
DoGlobalInit(
|
|
UINT argc,
|
|
LPTSTR *argv
|
|
);
|
|
|
|
BOOL
|
|
DoGlobalTermination(
|
|
VOID
|
|
);
|
|
|
|
|
|
BOOL
|
|
UpdateRunningServer(
|
|
VOID
|
|
);
|
|
|
|
HWND
|
|
CreateMasterWindow(
|
|
VOID
|
|
);
|
|
|
|
BOOL
|
|
StartMasterLoop(
|
|
LPVOID lpv
|
|
);
|
|
|
|
BOOL
|
|
StartOperation(
|
|
VOID
|
|
);
|
|
|
|
//
|
|
// Code section
|
|
//
|
|
|
|
extern "C"
|
|
BOOL
|
|
APIENTRY
|
|
DllEntryPoint(
|
|
HINSTANCE hinst,
|
|
DWORD dwReason,
|
|
LPVOID lpReserved
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
DllEntryPoint
|
|
|
|
Main DLL entry point.
|
|
|
|
Arguments:
|
|
|
|
hinst - module instance
|
|
dwReason - reason called
|
|
lpReserved - reserved
|
|
|
|
Return Value:
|
|
|
|
Status
|
|
|
|
Side effects:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
switch (dwReason) {
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
DBG_INIT(hinst);
|
|
#if 0
|
|
#ifdef DEBUG
|
|
StiSetDebugMask(0xffff);
|
|
StiSetDebugParameters(TEXT("WIASERVC"),TEXT(""));
|
|
#endif
|
|
#endif
|
|
|
|
g_hInst = hinst;
|
|
|
|
::DisableThreadLibraryCalls(hinst);
|
|
|
|
InitializeCriticalSection(&g_RpcEvent.cs);
|
|
|
|
_Module.Init(ObjectMap,hinst);
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
|
|
DeleteCriticalSection(&g_RpcEvent.cs);
|
|
|
|
_Module.Term();
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
extern "C"
|
|
BOOL
|
|
APIENTRY
|
|
DllMain(
|
|
HINSTANCE hinst,
|
|
DWORD dwReason,
|
|
LPVOID lpReserved
|
|
)
|
|
{
|
|
return DllEntryPoint(hinst, dwReason, lpReserved );
|
|
}
|
|
|
|
|
|
VOID
|
|
WINAPI
|
|
ServiceMain(
|
|
UINT argc,
|
|
LPTSTR *argv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Main initialization point of imaging services library
|
|
|
|
Arguments:
|
|
|
|
argc - counter of arguments
|
|
argv - arguments array
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
Side effects:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
|
|
DBG_FN(ServiceMain);
|
|
|
|
//
|
|
// Register our Service control handler. Note that we must do this as early as possible.
|
|
//
|
|
if (!RegisterServiceControlHandler()) {
|
|
goto ExitMain;
|
|
}
|
|
|
|
//
|
|
// Do global initialization, independent of specific service
|
|
//
|
|
if (!DoGlobalInit(argc,argv)) {
|
|
goto ExitMain;
|
|
}
|
|
|
|
//
|
|
// Start running service
|
|
//
|
|
|
|
StartOperation();
|
|
|
|
ExitMain:
|
|
|
|
//
|
|
// Global cleanup
|
|
//
|
|
DoGlobalTermination();
|
|
|
|
UpdateServiceStatus(SERVICE_STOPPED,NOERROR,0);
|
|
} /* Endproc ServiceMain */
|
|
|
|
|
|
BOOL
|
|
DoGlobalInit(
|
|
UINT argc,
|
|
LPTSTR *argv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Perform one time service initialization
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
|
|
DBG_FN(DoGlobalInit);
|
|
|
|
//
|
|
// To use built-in ATL conversion macros
|
|
//
|
|
|
|
USES_CONVERSION;
|
|
|
|
#ifdef DEBUG
|
|
|
|
//
|
|
// Create a debug context.
|
|
//
|
|
|
|
#define VALUE_SIZE 5
|
|
char valueData[VALUE_SIZE];
|
|
DWORD retVal, type = 0, size = VALUE_SIZE;
|
|
|
|
//
|
|
// Search the registry
|
|
//
|
|
|
|
retVal = SHGetValueA(HKEY_LOCAL_MACHINE,
|
|
g_szStiKey,
|
|
g_szWiaDebugValue,
|
|
&type,
|
|
valueData,
|
|
&size);
|
|
|
|
//
|
|
// Found the entry in the registry
|
|
//
|
|
|
|
BOOLEAN bDisplayUi = FALSE;
|
|
|
|
if (retVal == ERROR_SUCCESS) {
|
|
|
|
//
|
|
// Compare value found in registry to g_szShowWinString
|
|
// If same, then show it
|
|
//
|
|
|
|
if (lstrcmpiA(g_szShowWiaWinString, valueData) == 0) {
|
|
bDisplayUi = TRUE;
|
|
}
|
|
}
|
|
|
|
//remove
|
|
//WIA_DEBUG_CREATE( g_hInst,
|
|
// TEXT("OLD Debugging/TRACE Window (STI/WIA Service)"),
|
|
// bDisplayUi,
|
|
// FALSE);
|
|
|
|
#endif
|
|
|
|
//
|
|
// Initialize COM.
|
|
//
|
|
|
|
HRESULT hr = CoInitializeEx(0,COINIT_MULTITHREADED);
|
|
if (FAILED(hr)) {
|
|
#ifdef DEBUG
|
|
OutputDebugString(TEXT("DoGlobalInit, CoInitializeEx failed\n"));
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Initialize our global critical sections...
|
|
//
|
|
__try {
|
|
|
|
//
|
|
// Initialize the critical sections.
|
|
//
|
|
if (InitializeCriticalSectionAndSpinCount(&g_semDeviceMan, MINLONG)) {
|
|
g_bDevManCritSectInitialized = TRUE;
|
|
}
|
|
if (InitializeCriticalSectionAndSpinCount(&g_semEventNode, MINLONG)) {
|
|
g_bEventCritSectInitialized = TRUE;
|
|
}
|
|
|
|
if(!g_bDevManCritSectInitialized || !g_bEventCritSectInitialized)
|
|
{
|
|
#ifdef DEBUG
|
|
OutputDebugString(TEXT("DoGlobalInit, InitializeCriticalSectionAndSpinCount failed\n"));
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
//
|
|
// Couldn't initialize critical sections - this is really bad,
|
|
// so bail
|
|
//
|
|
|
|
#ifdef DEBUG
|
|
OutputDebugString(TEXT("DoGlobalInit, InitializeCriticalSectionAndSpinCount threw an exception!\n"));
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Setup some global variables from the registry.
|
|
//
|
|
|
|
#ifndef WINNT
|
|
g_fRunningAsService = FALSE;
|
|
#endif
|
|
|
|
InitGlobalConfigFromReg();
|
|
|
|
//
|
|
// Create event log class object
|
|
//
|
|
|
|
g_EventLog = new EVENT_LOG(TEXT("StillImage"));
|
|
if (!g_EventLog) {
|
|
#ifdef DEBUG
|
|
OutputDebugString(TEXT("DoGlobalInit, unable to allocate EVENT_LOG\n"));
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Create file log class object, requesting truncating file if set by user
|
|
//
|
|
|
|
g_StiFileLog = new STI_FILE_LOG(TEXT("STISVC"),NULL,STIFILELOG_CHECK_TRUNCATE_ON_BOOT, g_hInst);
|
|
if (g_StiFileLog) {
|
|
if(g_StiFileLog->IsValid()) {
|
|
// Set UI bit in reporting
|
|
if (g_fUIPermitted) {
|
|
g_StiFileLog->SetReportMode(g_StiFileLog->QueryReportMode() | STI_TRACE_LOG_TOUI);
|
|
}
|
|
}
|
|
else {
|
|
#ifdef DEBUG
|
|
OutputDebugString(TEXT("DoGlobalInit, could not open log file\n"));
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
}
|
|
else {
|
|
#ifdef DEBUG
|
|
OutputDebugString(TEXT("DoGlobalInit, unable to allocate STI_FILE_LOG\n"));
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Start Logging object's class factory
|
|
//
|
|
|
|
hr = StartLOGClassFactories();
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Create COM Logging Object
|
|
//
|
|
|
|
IWiaLog *pWiaLog = NULL;
|
|
|
|
hr = CWiaLog::CreateInstance(IID_IWiaLog,(void**)&g_pIWiaLog);
|
|
if (SUCCEEDED(hr)) {
|
|
g_pIWiaLog->InitializeLogEx((BYTE*)g_hInst);
|
|
DBG_TRC(("Starting STI/WIA Service..."));
|
|
} else {
|
|
#ifdef DEBUG
|
|
OutputDebugString(TEXT("Failed to QI for IWiaLogEx...\n"));
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Initialize the lock manager
|
|
//
|
|
|
|
g_pStiLockMgr = new StiLockMgr();
|
|
if (g_pStiLockMgr) {
|
|
|
|
hr = g_pStiLockMgr->Initialize();
|
|
if (FAILED(hr)) {
|
|
#ifdef DEBUG
|
|
OutputDebugString(TEXT("DoGlobalInit, could not initialize Lock Manager\n"));
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
#ifdef DEBUG
|
|
OutputDebugString(TEXT("DoGlobalInit, unable to allocate Lock Manager\n"));
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
//
|
|
// Initialize work item scheduler
|
|
//
|
|
|
|
SchedulerInitialize();
|
|
|
|
//
|
|
// Create DeviceList event.
|
|
//
|
|
g_hDevListCompleteEvent = CreateEvent( NULL, // lpsaSecurity
|
|
TRUE, // fManualReset
|
|
FALSE, // fInitialState
|
|
NULL ); // lpszEventName
|
|
if( g_hDevListCompleteEvent == NULL ) {
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Create and initialize global Device Manager
|
|
//
|
|
|
|
g_pDevMan = new CWiaDevMan();
|
|
if (g_pDevMan) {
|
|
hr = g_pDevMan->Initialize();
|
|
if (SUCCEEDED(hr)) {
|
|
hr = g_pDevMan->ReEnumerateDevices(DEV_MAN_FULL_REFRESH | DEV_MAN_STATUS_STARTP);
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("::DoGlobalInit, unable to enumerate devices"));
|
|
}
|
|
} else {
|
|
DBG_ERR(("::DoGlobalInit, unable to initialize WIA device manager"));
|
|
}
|
|
} else {
|
|
DBG_ERR(("::DoGlobalInit, Out of memory, could not create WIA device manager"));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Create and initialize global message handler
|
|
//
|
|
|
|
g_pMsgHandler = new CMsgHandler();
|
|
if (g_pMsgHandler) {
|
|
hr = g_pMsgHandler->Initialize();
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("::DoGlobalInit, unable to initialize internal Message handler"));
|
|
}
|
|
} else {
|
|
DBG_ERR(("::DoGlobalInit, Out of memory, could not create internal Message handler"));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Create and initialize the object resposible for WIA Runtime event notifications
|
|
//
|
|
g_pWiaEventNotifier = new WiaEventNotifier();
|
|
if (g_pWiaEventNotifier)
|
|
{
|
|
hr = g_pWiaEventNotifier->Initialize();
|
|
if (FAILED(hr))
|
|
{
|
|
DBG_ERR(("::DoGlobalInit, WIA runtime event notifier failed to initialize...exiting"));
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBG_ERR(("::DoGlobalInit, Out of memory, could not create WIA runtime event notifier...exiting"));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Initialize the Wia Service controller
|
|
//
|
|
|
|
hr = CWiaSvc::Initialize();
|
|
if (FAILED(hr)) {
|
|
#ifdef DEBUG
|
|
OutputDebugString(TEXT("DoGlobalInit, unable to initialize Wia Service controller\n"));
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Read the command line arguments and set global data.
|
|
//
|
|
|
|
for (UINT uiParam = 0; uiParam < argc; uiParam ++ ) {
|
|
|
|
switch (*argv[uiParam]) {
|
|
case TEXT('A'): case TEXT('a'):
|
|
// Running as user mode process
|
|
g_fRunningAsService = FALSE;
|
|
break;
|
|
case TEXT('V'): case TEXT('v'):
|
|
// Service UI is allowed
|
|
g_fUIPermitted = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// 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.
|
|
//
|
|
|
|
{
|
|
HKEY hkRun = NULL;
|
|
LONG lRet ;
|
|
LONG lcbValue = 0;
|
|
BOOL fNeedToRegister = FALSE;
|
|
|
|
if (RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_RUN, &hkRun) == NO_ERROR) {
|
|
|
|
DBG_TRC(("Removing erroneous entry on cleanup: HKLM\\..\\Run\\%S",REGSTR_VAL_MONITOR));
|
|
|
|
lRet = RegQueryValue(hkRun,REGSTR_VAL_MONITOR,NULL,&lcbValue);
|
|
|
|
fNeedToRegister = (lRet == NOERROR);
|
|
|
|
RegDeleteValue (hkRun, REGSTR_VAL_MONITOR);
|
|
RegCloseKey(hkRun);
|
|
}
|
|
|
|
// If needed register service
|
|
if (fNeedToRegister ) {
|
|
StiServiceInstall(NULL,NULL);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
DoGlobalTermination(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Final termination
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DBG_FN(DoGlobalTermination);
|
|
|
|
//
|
|
// Terminate work item scheduler
|
|
//
|
|
SchedulerTerminate();
|
|
|
|
//
|
|
// Delete the lock manager (which also removes it from the ROT)
|
|
//
|
|
|
|
if (g_pStiLockMgr) {
|
|
delete g_pStiLockMgr;
|
|
g_pStiLockMgr = NULL;
|
|
}
|
|
|
|
//
|
|
// Delete global device manager
|
|
//
|
|
if (g_pDevMan) {
|
|
delete g_pDevMan;
|
|
g_pDevMan = NULL;
|
|
}
|
|
|
|
//
|
|
// Close hDevListRefreshCompleteEvent event handle
|
|
//
|
|
CloseHandle(g_hDevListCompleteEvent);
|
|
g_hDevListCompleteEvent = NULL;
|
|
|
|
//
|
|
// Release WIA Logging object
|
|
//
|
|
|
|
if(g_pIWiaLog) {
|
|
DBG_TRC(("Exiting STI/WIA Service..."));
|
|
|
|
if (g_pIWiaLog) {
|
|
g_pIWiaLog->Release();
|
|
}
|
|
g_pIWiaLog = NULL;
|
|
}
|
|
|
|
if(g_EventLog) {
|
|
delete g_EventLog;
|
|
g_EventLog = NULL;
|
|
}
|
|
|
|
if (g_StiFileLog) {
|
|
delete g_StiFileLog;
|
|
g_StiFileLog = NULL;
|
|
}
|
|
|
|
if (ServerStartedEvent) {
|
|
::CloseHandle(ServerStartedEvent);
|
|
}
|
|
|
|
//
|
|
// Shut down message loop
|
|
//
|
|
|
|
::PostQuitMessage(0);
|
|
|
|
//
|
|
// Uninitialize COM.
|
|
//
|
|
|
|
::CoUninitialize();
|
|
|
|
if (g_bEventCritSectInitialized) {
|
|
DeleteCriticalSection(&g_semEventNode);
|
|
}
|
|
if (g_bDevManCritSectInitialized) {
|
|
DeleteCriticalSection(&g_semDeviceMan);
|
|
}
|
|
|
|
//
|
|
// Destroy the debug context.
|
|
//
|
|
|
|
// WIA_DEBUG_DESTROY();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Guard to avoid reentrance in refresh routine
|
|
//
|
|
static LONG lRunningMessageLoop = 0L;
|
|
|
|
HANDLE
|
|
CreateMessageLoopThread(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Running primary service thread.
|
|
If process is running as NT service, we don't have any messages to
|
|
pump, so call it synchronously.
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
if (InterlockedExchange(&lRunningMessageLoop,1L)) {
|
|
return 0;
|
|
}
|
|
HANDLE hThread = NULL;
|
|
|
|
#ifndef WINNT
|
|
|
|
hThread = ::CreateThread(NULL,
|
|
0,
|
|
(LPTHREAD_START_ROUTINE)StartMasterLoop,
|
|
(LPVOID)NULL,
|
|
0,
|
|
&g_dwMessagePumpThreadId);
|
|
|
|
#else
|
|
StartMasterLoop(NULL);
|
|
#endif
|
|
|
|
return hThread;
|
|
}
|
|
|
|
BOOL
|
|
StartMasterLoop(
|
|
LPVOID lpParam
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Running primary service thread
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
MSG msg;
|
|
|
|
DBG_FN(StartMasterLoop);
|
|
|
|
//
|
|
// If visible create master window
|
|
//
|
|
|
|
CreateMasterWindow();
|
|
|
|
VisualizeServer(g_fUIPermitted);
|
|
|
|
//
|
|
// Initialize WIA.
|
|
//
|
|
|
|
InitWiaDevMan(WiaInitialize);
|
|
|
|
#ifndef WINNT
|
|
//Don't use windows messaging on NT
|
|
|
|
//
|
|
// Run message pump
|
|
//
|
|
while(GetMessage(&msg,NULL,0,0)) {
|
|
|
|
//
|
|
// Give WIA the first chance at dispatching messages. Note that
|
|
// WIA hooks both message dispatch and the window proc. so that
|
|
// both posted and sent messages can be detected.
|
|
//
|
|
//
|
|
// currently there are no cases where sti needs to dispatch messages
|
|
// to wia. Events are now dealt with directly.
|
|
//
|
|
|
|
#if 0
|
|
|
|
if (DispatchWiaMsg(&msg) == S_OK) {
|
|
continue;
|
|
}
|
|
|
|
#endif
|
|
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
|
|
// Indicate we are entering shutdown
|
|
g_fServiceInShutdown = TRUE;
|
|
|
|
InterlockedExchange(&lRunningMessageLoop,0L);
|
|
#endif
|
|
|
|
return TRUE;
|
|
|
|
} // StartMasterLoop
|
|
|
|
BOOL
|
|
StartOperation(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Running primary service thread.
|
|
If process is running as NT service, separate thread is created to
|
|
handle window messages. This is necessary because primary thread becomes
|
|
blocked as a control dispatcher , but we still need to have message loop
|
|
running to deliver window messages.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DBG_FN(StartOperation);
|
|
|
|
DWORD dwError;
|
|
|
|
#ifdef MAXDEBUG
|
|
DBG_TRC(("Start operation entered"));
|
|
#endif
|
|
|
|
if (g_fRunningAsService) {
|
|
|
|
//
|
|
// If UI is permitted - create visible window
|
|
// Note that we always create window for now, to allow hiding/unhiding it dynamically
|
|
//
|
|
g_hMessageLoopThread = CreateMessageLoopThread();
|
|
|
|
// !!!??? need to pass command line args down from svchost.
|
|
StiServiceMain(0, NULL);
|
|
|
|
if ( g_hMessageLoopThread ) {
|
|
::CloseHandle(g_hMessageLoopThread);
|
|
g_hMessageLoopThread = NULL;
|
|
}
|
|
|
|
}
|
|
else {
|
|
//
|
|
// Running as application
|
|
//
|
|
|
|
// First thing - allow PnP sink to register properly
|
|
g_fUseServiceCtrlSink = FALSE;
|
|
|
|
|
|
dwError = StiServiceInitialize();
|
|
|
|
g_dwMessagePumpThreadId = GetCurrentThreadId();
|
|
|
|
StartMasterLoop(NULL);
|
|
|
|
StiServiceStop();
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
} // StartOperation
|
|
|
|
BOOL
|
|
VisualizeServer(
|
|
BOOL fVisualize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
|
|
g_fUIPermitted = fVisualize;
|
|
|
|
if (::IsWindow(g_hMainWindow)) {
|
|
::ShowWindow(g_hMainWindow,fVisualize ? SW_SHOWNORMAL : SW_HIDE);
|
|
}
|
|
|
|
if (g_StiFileLog) {
|
|
if(g_StiFileLog->IsValid()) {
|
|
// Set UI bit in reporting
|
|
if (g_fUIPermitted) {
|
|
g_StiFileLog->SetReportMode(g_StiFileLog->QueryReportMode() | STI_TRACE_LOG_TOUI);
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
UpdateRunningServer(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
HWND hExistingWindow;
|
|
|
|
hExistingWindow = FindWindow(g_szClass,NULL);
|
|
|
|
if (!hExistingWindow) {
|
|
return FALSE;
|
|
}
|
|
|
|
DBG_TRC(("Updating running service with refresh parameters"));
|
|
|
|
//
|
|
// Server already running , find it 's window and send a message
|
|
// with new values of parameters
|
|
//
|
|
::ShowWindow(hExistingWindow,g_fUIPermitted ? SW_SHOWNORMAL : SW_HIDE);
|
|
|
|
// 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;
|
|
}
|
|
|
|
|
|
STDAPI
|
|
DllRegisterServer(
|
|
VOID
|
|
)
|
|
{
|
|
StiServiceInstall(NULL,NULL);
|
|
|
|
InitWiaDevMan(WiaRegister);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func void | DllUnregisterServer |
|
|
*
|
|
* Unregister our classes from OLE/COM/ActiveX/whatever its name is.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
STDAPI
|
|
DllUnregisterServer(
|
|
VOID
|
|
)
|
|
{
|
|
InitWiaDevMan(WiaUnregister);
|
|
|
|
StiServiceRemove();
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
//
|
|
// Methods needed for linking to STIRT (stiobj.c calls these).
|
|
// Some of these methods are simply dummies.
|
|
//
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
BOOL
|
|
EXTERNAL
|
|
DllInitializeCOM(
|
|
void
|
|
)
|
|
{
|
|
//
|
|
// Initialize COM.
|
|
//
|
|
|
|
HRESULT hr = CoInitializeEx(0,COINIT_MULTITHREADED);
|
|
if (FAILED(hr)) {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL EXTERNAL
|
|
DllUnInitializeCOM(
|
|
void
|
|
)
|
|
{
|
|
//
|
|
// Uninitialize COM
|
|
//
|
|
|
|
CoUninitialize();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void EXTERNAL
|
|
DllAddRef(void)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void EXTERNAL
|
|
DllRelease(void)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
};
|
|
#endif
|