Leaked source code of windows server 2003
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.
 
 
 
 
 
 

234 lines
6.7 KiB

/*******************************************************************************
*
* (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;