294 lines
9.8 KiB
C++
294 lines
9.8 KiB
C++
// acqmgr.h : Declaration of the CAcquisitionManager
|
|
|
|
#ifndef __AcquisitionManager_H_INCLUDED
|
|
#define __AcquisitionManager_H_INCLUDED
|
|
|
|
#include "resource.h" // main symbols
|
|
#include "acqthrd.h"
|
|
#include "shmemsec.h"
|
|
#include "mintrans.h"
|
|
#include "stievent.h"
|
|
|
|
//
|
|
// Number of times we will spin before giving up on
|
|
// getting the window of the previous wizard's instance
|
|
//
|
|
const int c_nMaxActivationRetryCount = 40;
|
|
|
|
//
|
|
// Amount of time to wait between efforts to obtain the previous
|
|
// wizard's instance
|
|
//
|
|
const DWORD c_nActivationRetryWait = 500;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CAcquisitionManager
|
|
class ATL_NO_VTABLE CAcquisitionManager :
|
|
public CComObjectRootEx<CComSingleThreadModel>,
|
|
public CComCoClass<CAcquisitionManager, &CLSID_AcquisitionManager>,
|
|
public IWiaEventCallback
|
|
{
|
|
public:
|
|
CAcquisitionManager()
|
|
{
|
|
}
|
|
|
|
~CAcquisitionManager()
|
|
{
|
|
}
|
|
|
|
DECLARE_REGISTRY_RESOURCEID(IDR_ACQUISITIONMANAGER)
|
|
|
|
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
|
|
|
BEGIN_COM_MAP(CAcquisitionManager)
|
|
COM_INTERFACE_ENTRY(IWiaEventCallback)
|
|
END_COM_MAP()
|
|
|
|
public:
|
|
// IManager
|
|
HRESULT STDMETHODCALLTYPE ImageEventCallback( const GUID *pEventGUID,
|
|
BSTR bstrEventDescription,
|
|
BSTR bstrDeviceID,
|
|
BSTR bstrDeviceDescription,
|
|
DWORD dwDeviceType,
|
|
BSTR bstrFullItemName,
|
|
ULONG *pulEventType,
|
|
ULONG ulReserved
|
|
)
|
|
{
|
|
WIA_PUSHFUNCTION((TEXT("CAcquisitionManager::ImageEventCallback")));
|
|
|
|
//
|
|
// Don't want to run if this is a scanner connection event
|
|
//
|
|
if (pEventGUID && *pEventGUID==WIA_EVENT_DEVICE_CONNECTED && GET_STIDEVICE_TYPE(dwDeviceType)==StiDeviceTypeScanner)
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
//
|
|
// Try to create or open the shared memory section.
|
|
//
|
|
CSharedMemorySection<HWND> *pWizardSharedMemory = new CSharedMemorySection<HWND>;
|
|
if (pWizardSharedMemory)
|
|
{
|
|
//
|
|
// Assume we'll be running the wizard.
|
|
//
|
|
bool bRun = true;
|
|
|
|
//
|
|
// If we were able to open the memory section
|
|
//
|
|
if (CSharedMemorySection<HWND>::SmsOpened == pWizardSharedMemory->Open( CSimpleStringConvert::NaturalString(CSimpleStringWide(bstrDeviceID)), true ))
|
|
{
|
|
//
|
|
// Try to get the previous instance
|
|
//
|
|
for (int i=0;i<c_nMaxActivationRetryCount;i++)
|
|
{
|
|
//
|
|
// if we were able to open the shared memory section, there is already one running.
|
|
// so get a mutex'ed pointer to the shared memory.
|
|
//
|
|
HWND *pHwnd = pWizardSharedMemory->Lock();
|
|
if (pHwnd)
|
|
{
|
|
//
|
|
// If we were able to get the pointer, get the window handle stored in it.
|
|
// Set bRun to false, so we don't start up a new wizard
|
|
//
|
|
bRun = false;
|
|
if (*pHwnd && IsWindow(*pHwnd))
|
|
{
|
|
//
|
|
// If it is a valid window, bring it to the foreground.
|
|
//
|
|
SetForegroundWindow(*pHwnd);
|
|
}
|
|
//
|
|
// Release the mutex
|
|
//
|
|
pWizardSharedMemory->Release();
|
|
|
|
//
|
|
// We found the window the window handle, so we can exit the loop now.
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Wait a while for the previous instance to be created
|
|
//
|
|
Sleep(c_nActivationRetryWait);
|
|
}
|
|
}
|
|
|
|
//
|
|
// We only do this if we need to open a new instance
|
|
//
|
|
if (bRun)
|
|
{
|
|
//
|
|
// Prepare the event data
|
|
//
|
|
CEventParameters EventParameters;
|
|
EventParameters.EventGUID = *pEventGUID;
|
|
EventParameters.strEventDescription = static_cast<LPCWSTR>(bstrEventDescription);
|
|
EventParameters.strDeviceID = static_cast<LPCWSTR>(bstrDeviceID);
|
|
EventParameters.strDeviceDescription = static_cast<LPCWSTR>(bstrDeviceDescription);
|
|
EventParameters.ulReserved = ulReserved;
|
|
EventParameters.ulEventType = *pulEventType;
|
|
EventParameters.hwndParent = NULL;
|
|
EventParameters.pWizardSharedMemory = pWizardSharedMemory;
|
|
|
|
//
|
|
// If we are started manually, it will be with the IID_NULL event
|
|
// If this is the case, we are going to treat the number stored as text as
|
|
// the "parent" window handle, over which all windows will be centered
|
|
//
|
|
if (pEventGUID && *pEventGUID==IID_NULL)
|
|
{
|
|
EventParameters.hwndParent = reinterpret_cast<HWND>(static_cast<UINT_PTR>(WiaUiUtil::StringToLong(CSimpleStringConvert::NaturalString(CSimpleStringWide(bstrEventDescription)))));
|
|
}
|
|
|
|
//
|
|
// Start up the thread that actually displays the wizard
|
|
//
|
|
HANDLE hThread = CAcquisitionThread::Create( EventParameters );
|
|
if (hThread)
|
|
{
|
|
//
|
|
// Prevent deletion of this structure later
|
|
//
|
|
pWizardSharedMemory = NULL;
|
|
|
|
//
|
|
// Don't need this anymore
|
|
//
|
|
CloseHandle(hThread);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WIA_TRACE((TEXT("There is already an instance of %ws running"), bstrDeviceID ));
|
|
}
|
|
|
|
//
|
|
// Delete this memory mapped file, to prevent leaks
|
|
//
|
|
if (pWizardSharedMemory)
|
|
{
|
|
delete pWizardSharedMemory;
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
};
|
|
|
|
|
|
class ATL_NO_VTABLE CMinimalTransfer :
|
|
public CComObjectRootEx<CComSingleThreadModel>,
|
|
public CComCoClass<CMinimalTransfer, &CLSID_MinimalTransfer>,
|
|
public IWiaEventCallback
|
|
{
|
|
public:
|
|
CMinimalTransfer()
|
|
{
|
|
}
|
|
|
|
~CMinimalTransfer()
|
|
{
|
|
}
|
|
|
|
DECLARE_REGISTRY_RESOURCEID(IDR_MINIMALTRANSFER)
|
|
|
|
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
|
|
|
BEGIN_COM_MAP(CMinimalTransfer)
|
|
COM_INTERFACE_ENTRY(IWiaEventCallback)
|
|
END_COM_MAP()
|
|
|
|
public:
|
|
// IManager
|
|
HRESULT STDMETHODCALLTYPE ImageEventCallback( const GUID *pEventGUID,
|
|
BSTR bstrEventDescription,
|
|
BSTR bstrDeviceID,
|
|
BSTR bstrDeviceDescription,
|
|
DWORD dwDeviceType,
|
|
BSTR bstrFullItemName,
|
|
ULONG *pulEventType,
|
|
ULONG ulReserved
|
|
)
|
|
{
|
|
if (pEventGUID && *pEventGUID==WIA_EVENT_DEVICE_CONNECTED && GET_STIDEVICE_TYPE(dwDeviceType)==StiDeviceTypeScanner)
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
DWORD dwThreadId;
|
|
_Module.Lock();
|
|
HANDLE hThread = CreateThread( NULL, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(MinimalTransferThreadProc), SysAllocString(bstrDeviceID), 0, &dwThreadId );
|
|
if (hThread)
|
|
{
|
|
CloseHandle(hThread);
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
_Module.Unlock();
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
class ATL_NO_VTABLE CStiEventHandler :
|
|
public CComObjectRootEx<CComSingleThreadModel>,
|
|
public CComCoClass<CStiEventHandler, &CLSID_StiEventHandler>,
|
|
public IWiaEventCallback
|
|
{
|
|
public:
|
|
CStiEventHandler()
|
|
{
|
|
}
|
|
|
|
~CStiEventHandler()
|
|
{
|
|
}
|
|
|
|
DECLARE_REGISTRY_RESOURCEID(IDR_STIEVENTHANDLER)
|
|
|
|
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
|
|
|
BEGIN_COM_MAP(CStiEventHandler)
|
|
COM_INTERFACE_ENTRY(IWiaEventCallback)
|
|
END_COM_MAP()
|
|
|
|
public:
|
|
HRESULT STDMETHODCALLTYPE ImageEventCallback( const GUID *pEventGUID,
|
|
BSTR bstrEventDescription,
|
|
BSTR bstrDeviceID,
|
|
BSTR bstrDeviceDescription,
|
|
DWORD dwDeviceType,
|
|
BSTR bstrFullItemName,
|
|
ULONG *pulEventType,
|
|
ULONG ulReserved
|
|
)
|
|
{
|
|
//
|
|
// Package the event data for the handler
|
|
//
|
|
CStiEventData StiEventData( pEventGUID, bstrEventDescription, bstrDeviceID, bstrDeviceDescription, dwDeviceType, bstrFullItemName, pulEventType, ulReserved );
|
|
|
|
//
|
|
// Just call the handler and return it.
|
|
//
|
|
return StiEventHandler( StiEventData );
|
|
}
|
|
};
|
|
|
|
|
|
#endif //__AcquisitionManager_H_INCLUDED
|
|
|