/******************************************************************************* * * (C) COPYRIGHT MICROSOFT CORP., 2000 * * TITLE: wiasvc.cpp * * VERSION: 1.0 * * AUTHOR: ByronC * * DATE: 10 May, 2000 * * DESCRIPTION: * Class implementation for WIA Service manager. This class controls the * lifetime of the Wia Service. * *******************************************************************************/ #include "precomp.h" #include "stiexe.h" #include "wiasvc.h" HRESULT CWiaSvc::Initialize() { return S_OK; } bool CWiaSvc::CanShutdown() { // // We are only safe to shutdown if there are no devices capable of generating events, // and we have no outstanding interfaces. // return (! (s_cActiveInterfaces || s_bEventDeviceExists)); } bool CWiaSvc::ADeviceIsInstalled() { bool bRet = TRUE; // On error, we assume there is a device installed #ifdef WINNT SC_HANDLE hSCM = NULL; SC_HANDLE hService = NULL; QUERY_SERVICE_CONFIG qscDummy; QUERY_SERVICE_CONFIG *pqscConfig = NULL; DWORD cbBytesNeeded = 0; __try { hSCM = ::OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); if (!hSCM) { __leave; } // // Check startup type of the service. If it is DEMAND_START, then no devices are // installed, so return FALSE. // // First get a handle to the SCM // hService = OpenService( hSCM, STI_SERVICE_NAME, SERVICE_ALL_ACCESS ); if (hService) { LONG lQueryRet = 0; // // Next, get the size needed for the service config struct. // lQueryRet = QueryServiceConfig(hService, &qscDummy, 1, &cbBytesNeeded); pqscConfig = (QUERY_SERVICE_CONFIG*) LocalAlloc(LPTR, cbBytesNeeded); if (pqscConfig) { // // Now, get the sevice info so we can check the startup type // lQueryRet = QueryServiceConfig(hService, pqscConfig, cbBytesNeeded, &cbBytesNeeded); if (lQueryRet) { if (pqscConfig->dwStartType == SERVICE_DEMAND_START) { // // Startup type is demand start, so no devices are // currently installed // bRet = FALSE; } } } } } __finally { CloseServiceHandle( hService ); CloseServiceHandle( hSCM ); if (pqscConfig) { LocalFree(pqscConfig); pqscConfig = NULL; } } #else // // On Win9x systems, always return TRUE. This will keep us active all the time. // bRet = TRUE; #endif return bRet; } unsigned long CWiaSvc::AddRef() { // // NOTE: For now, assume that if any device exists, then it may generate events, so // set s_bEventDeviceExists to TRUE. Also, note that once s_bEventDeviceExists is // set to TRUE, it is never set to FALSE. This is to cover the case when the device // is unplugged. In this case the device count could be zero, but we still need the service // running to catch when it is plugged in again (so it can launch appropriate app. // notify event listeners etc.) // if (!s_bEventDeviceExists) { if (ADeviceIsInstalled()) { s_bEventDeviceExists = TRUE; } } InterlockedIncrement(&s_cActiveInterfaces); // // If no devices with events exists, we must live purely on number of outstanding active // interfaces we have handed out i.e. when the last interface is released by the caller, // we are free to shut down. // If a device capable of generating events does exist, we must remain running, since // we have to listen/poll for event which could come at any time. // if (!s_bEventDeviceExists) { return CoAddRefServerProcess(); } return 2; } unsigned long CWiaSvc::Release() { InterlockedIncrement(&s_cActiveInterfaces); // // If no devices with events exists, we must live purely on number of outstanding active // interfaces we have handed out i.e. when the last interface is released by the caller, // we are free to shut down. // If a device capable of generating events does exist, we must remain running, since // we have to listen/poll for event which could come at any time. // if (!s_bEventDeviceExists) { unsigned long ulRef = 1; /* NOTE!!! This is TEMPORARY. This will guarantee we don't get errors during setup regarding StartRPCServerListen(...). A beneficial side-effect is that WIA Acquisition Manager's event registration will succeed (it will fail if StartRPCServerListen fails). One noted side-effect is that the WIA service will not automatically shutdown if no devices are installed and an imaging application exits. ulRef = CoReleaseServerProcess(); if (ulRef == 0) { // // We have no devices that can generate events, and we have no outstanding // interfaces, so shutdown... // ShutDown(); } */ return ulRef; } // // NOTE: If a device capable of generating events exists, we NEVER call CoReleaseServerProcess(), // since this will suspend the creation of our Class Objects when ref count is 0, which means a new // server process would need to be started when a WIA application did a CoCreate to talk to WIA. // return 1; } void CWiaSvc::ShutDown() { // // Inform COM to ignore all activation requests // CoSuspendClassObjects(); // // Call the control entry to stop the service // StiServiceStop(); } // // Initialize static data members // long CWiaSvc::s_cActiveInterfaces = 0; bool CWiaSvc::s_bEventDeviceExists = FALSE;