|
|
/*******************************************************************************
* * (C) COPYRIGHT MICROSOFT CORP., 1997 * * TITLE: DevMgr.Cpp * * VERSION: 2.0 * * AUTHOR: ReedB * * DATE: 26 Dec, 1997 * * DESCRIPTION: * Class implementation for WIA device manager. * 07/12/2000 - Added support for shell's Hardware Event notification to * receive volume arrival notification and start the WIA Wizard. * *******************************************************************************/ #include "precomp.h"
#include "stiexe.h"
#include "wiacfact.h"
#include "wiamindr.h"
#include "devmgr.h"
#include "devinfo.h"
#include "helpers.h"
#include "wiaevntp.h"
#include "wiapriv.h"
#include "device.h"
#include "lockmgr.h"
#include "fstidev.h"
#define INITGUID
#include "initguid.h"
//
// Acquisition Manager's class ID {D13E3F25-1688-45A0-9743-759EB35CDF9A}
// NOTE: We shouldn't really use this. Rather GetCLSIDFromProgID and use the
// version independant AppID name.
//
DEFINE_GUID( CLSID_Manager, 0xD13E3F25, 0x1688, 0x45A0, 0x97, 0x43, 0x75, 0x9E, 0xB3, 0x5C, 0xDF, 0x9A);
/**************************************************************************\
* CWiaDevMgr::CreateInstance * * Create the CWiaDevMgr object. * * Arguments: * * iid - iid of dev manager * ppv - return interface pointer * * Return Value: * * status * * History: * * 9/2/1998 Original Version * \**************************************************************************/
HRESULT CWiaDevMgr::CreateInstance(const IID& iid, void** ppv) { DBG_FN(CWiaDevMgr::CreateInstance); HRESULT hr;
if ((iid == IID_IWiaDevMgr) || (iid == IID_IUnknown) || (iid == IID_IHWEventHandler)) {
// Create the WIA device manager component.
CWiaDevMgr* pDevMgr = new CWiaDevMgr();
if (!pDevMgr) { DBG_ERR(("CWiaDevMgr::CreateInstance, Out of Memory")); return E_OUTOFMEMORY; }
// Initialize the WIA device manager component.
hr = pDevMgr->Initialize(); if (FAILED(hr)) { delete pDevMgr; DBG_ERR(("CWiaDevMgr::CreateInstance, Initialize failed")); return hr; }
// Get the requested interface from the device manager component.
hr = pDevMgr->QueryInterface(iid, ppv); if (FAILED(hr)) { delete pDevMgr; DBG_ERR(("CWiaDevMgr::CreateInstance, QI failed")); return hr; }
DBG_TRC(("CWiaDevMgr::CreateInstance, Created WiaDevMgr")); } else { hr = E_NOINTERFACE; DBG_ERR(("CWiaDevMgr::CreateInstance, Unknown interface (0x%X)", hr)); } return hr; }
/**************************************************************************\
* QueryInterface * AddRef * Release * * CWiaDevMgr IUnknown Interface * * Arguments: * * * * Return Value: * * * * History: * * 9/2/1998 Original Version * \**************************************************************************/
HRESULT __stdcall CWiaDevMgr::QueryInterface(const IID& iid, void** ppv) { *ppv = NULL;
if ((iid == IID_IUnknown) || (iid == IID_IWiaDevMgr)) { *ppv = (IWiaDevMgr*) this; } else if (iid == IID_IWiaNotifyDevMgr) { *ppv = (IWiaNotifyDevMgr*) this; } else if (iid == IID_IHWEventHandler) { *ppv = (IHWEventHandler*) this; } else { return E_NOINTERFACE; } AddRef(); return S_OK; }
ULONG __stdcall CWiaDevMgr::AddRef() { InterlockedIncrement((long*) &m_cRef); return m_cRef; }
ULONG __stdcall CWiaDevMgr::Release() { ULONG ulRefCount = m_cRef - 1;
if (InterlockedDecrement((long*) &m_cRef) == 0) { delete this; return 0; } return ulRefCount; }
/*******************************************************************************
* * CWiaDevMgr * ~CWiaDevMgr * * CWiaDevMgr Constructor/Initialize/Destructor Methods. * * History: * * 9/2/1998 Original Version * \**************************************************************************/
CWiaDevMgr::CWiaDevMgr():m_cRef(0) { m_cRef = 0; m_pITypeInfo = NULL;
//
// We're creating a component that exposes interfaces to clients, so
// inform service to make sure service wont shutdown prematurely.
//
CWiaSvc::AddRef(); }
CWiaDevMgr::~CWiaDevMgr() { DBG_FN(CWiaDevMgr::~CWiaDevMgr);
if (m_pITypeInfo != NULL) { m_pITypeInfo->Release(); }
//
// Component is destroyed, so no more interfaces are exposed from here.
// Inform server by decrementing it's reference count. This will allow
// it to shutdown if it's no longer needed.
//
CWiaSvc::Release(); }
/**************************************************************************\
* CWiaDevMgr::Initialize * * Create global sti instance * * Arguments: * * none * * Return Value: * * status * * History: * * 9/2/1998 Original Version * \**************************************************************************/
HRESULT CWiaDevMgr::Initialize() { DBG_FN(CWiaDevMgr::Initialize); HRESULT hr = S_OK;
return hr; }
/**************************************************************************\
* EnumWIADevInfo * * Create an WIA device information enumerator object. * * Arguments: * * lFlag - type of device to enumerate * ppIEnum - return enumerator * * Return Value: * * status * * History: * * 9/2/1998 Original Version * \**************************************************************************/
HRESULT _stdcall CWiaDevMgr::EnumDeviceInfo( LONG lFlag, IEnumWIA_DEV_INFO** ppIEnum) { DBG_FN(CWiaDevMgr::EnumDeviceInfo); HRESULT hr = S_OK; DWORD dwWait = 0;
//
// Make sure that refreshing of the device list has completed. If
// it hasn't, we'll wait up to DEVICE_LIST_WAIT_TIME, before proceeding
// anyway. This will ensure the device list is not empty because
// WIA device enumeration was called too soon after start-up (e.g.
// app's CoCreateInstance call started the service).
//
//
// Enumerate LPT if necessary.
//
EnumLpt();
dwWait = WaitForSingleObject(g_hDevListCompleteEvent, DEVICE_LIST_WAIT_TIME); if (dwWait != WAIT_OBJECT_0) { DBG_WRN(("CWiaDevMgr::EnumDeviceInfo, Device list was not complete before enumeration call...")); }
*ppIEnum = NULL;
CEnumWIADevInfo* pEnum = new CEnumWIADevInfo;
if (!pEnum) { DBG_ERR(("CWiaDevMgr::EnumDeviceInfo, Out of Memory")); return E_OUTOFMEMORY; }
hr = pEnum->Initialize(lFlag); if (FAILED(hr)) { DBG_ERR(("CWiaDevMgr::EnumDeviceInfo, Initialize failed")); delete pEnum; return hr; }
hr = pEnum->QueryInterface(IID_IEnumWIA_DEV_INFO, (void**) ppIEnum); if (FAILED(hr)) { DBG_ERR(("CWiaDevMgr::EnumDeviceInfo, QI for IWiaPropertyStorage failed")); delete pEnum; return E_UNEXPECTED; } return S_OK; }
/**************************************************************************\
* FindMatchingDevice * * search enumeration info for named device * * Arguments: * * ppIPropStg * pbstrDeviceID * * Return Value: * * Status * * History: * * 9/3/1998 Original Version * \**************************************************************************/
HRESULT CWiaDevMgr::FindMatchingDevice( BSTR pbstrDeviceID, IWiaPropertyStorage **ppIWiaPropStg) { DBG_FN(CWiaDevMgr::FindMatchingDevice); // Enumerate the WIA devices, getting a IWIADevInfo
// pointer for each. Use this interface to query the registry
// based properties for each installed device.
HRESULT hr; ULONG ul, ulFound = 0; BSTR bstrDevId; IEnumWIA_DEV_INFO *pIEnum;
//
// Notice that we specify DEV_MAN_ENUM_TYPE_ALL here.
//
hr = EnumDeviceInfo(DEV_MAN_ENUM_TYPE_ALL,&pIEnum);
if (SUCCEEDED(hr)) {
ul = 1;
while ((hr = pIEnum->Next(1, ppIWiaPropStg, &ul)) == S_OK) {
DBG_TRC(("# Found device candidate"));
hr = ReadPropStr(WIA_DIP_DEV_ID, *ppIWiaPropStg, &bstrDevId);
if (SUCCEEDED(hr)) {
DBG_TRC(("# \tDevice Name: %S", bstrDevId)); ulFound = !lstrcmpiW(bstrDevId, pbstrDeviceID); SysFreeString(bstrDevId);
if (ulFound) { break; } } else { DBG_ERR(("FindMatchingDevice, ReadPropStr of WIA_DIP_DEV_ID failed")); }
(*ppIWiaPropStg)->Release(); *ppIWiaPropStg = NULL; }
pIEnum->Release(); } else { DBG_ERR(("FindMatchingDevice:Failed to create enumerator")); } if (SUCCEEDED(hr)) { if (!ulFound) { hr = S_FALSE; } } return hr; }
#ifdef WINNT
/**************************************************************************\
* IsDeviceRemote * * * * Arguments: * * * * Return Value: * * TRUE if device is remote, caller must free server name. * * History: * * 1/5/1999 Original Version * \**************************************************************************/
BOOL IsDeviceRemote( IWiaPropertyStorage *pIWiaPropStg, BSTR *pbstrServer) { DBG_FN(::IsDeviceRemote); HRESULT hr;
hr = ReadPropStr(WIA_DIP_SERVER_NAME, pIWiaPropStg, pbstrServer);
if ((SUCCEEDED(hr)) && (**pbstrServer)) { if (lstrcmpiW(*pbstrServer, L"local") != 0) { return TRUE; } } else { DBG_ERR(("IsDeviceRemote, ReadPropStr of WIA_DIP_SERVER_NAME failed")); DBG_ERR(("Registry value DeviceData\\Server may not have been set during installation")); } if (*pbstrServer) { SysFreeString(*pbstrServer); } return FALSE; }
/**************************************************************************\
* CreateRemoteDevice * * * * Arguments: * * * * Return Value: * * Status * * History: * * 1/5/1999 Original Version * \**************************************************************************/
HRESULT CreateRemoteDevice( BSTR bstrServer, IWiaPropertyStorage *pIWiaPropStg, IWiaItem **ppWiaDevice ) { DBG_FN(::CreateRemoteDevice); *ppWiaDevice = NULL;
if (!bstrServer || !*bstrServer) { DBG_ERR(("CreateRemoteDevice, bad remote server name")); return E_INVALIDARG; }
//
// must use client
//
HRESULT hr = CoImpersonateClient(); if (FAILED(hr)) { DBG_ERR(("CreateRemoteDevice, CoImpersonateClient failed (0x%X)", hr)); return hr; }
COSERVERINFO coServInfo; MULTI_QI multiQI[1];
multiQI[0].pIID = &IID_IWiaDevMgr; multiQI[0].pItf = NULL;
coServInfo.pwszName = bstrServer; coServInfo.pAuthInfo = NULL; coServInfo.dwReserved1 = 0; coServInfo.dwReserved2 = 0;
//
// create connection to dev mgr
//
hr = CoCreateInstanceEx( CLSID_WiaDevMgr, NULL, CLSCTX_REMOTE_SERVER, &coServInfo, 1, &multiQI[0] );
if (hr == S_OK) {
BSTR bstrRemoteDevId; BSTR bstrDevId;
IWiaDevMgr *pIWiaDevMgr = (IWiaDevMgr*)multiQI[0].pItf; IWiaItem *pIWiaItem;
//
// use remote dev id to create
//
hr = ReadPropStr(WIA_DIP_DEV_ID, pIWiaPropStg, &bstrDevId);
if (hr == S_OK) {
hr = ReadPropStr(WIA_DIP_REMOTE_DEV_ID, pIWiaPropStg, &bstrRemoteDevId); }
if (hr == S_OK) {
//
// create remote device
//
hr = pIWiaDevMgr->CreateDevice(bstrRemoteDevId, &pIWiaItem);
if (hr == S_OK) {
*ppWiaDevice = pIWiaItem;
//
// set devinfo props for remote access
//
IWiaPropertyStorage *pIPropDev;
hr = pIWiaItem->QueryInterface(IID_IWiaPropertyStorage, (void **)&pIPropDev);
if (hr == S_OK) {
//
// set copy of devinfo to contain correct Remote DEVID, DEVID and server name
//
PROPSPEC PropSpec[3]; PROPVARIANT PropVar[3];
memset(PropVar,0,sizeof(PropVar));
// server name
PropSpec[0].ulKind = PRSPEC_PROPID; PropSpec[0].propid = WIA_DIP_SERVER_NAME;
PropVar[0].vt = VT_BSTR; PropVar[0].bstrVal = bstrServer;
// DEVID
PropSpec[1].ulKind = PRSPEC_PROPID; PropSpec[1].propid = WIA_DIP_DEV_ID;
PropVar[1].vt = VT_BSTR; PropVar[1].bstrVal = bstrDevId;
//Remote DEVID
PropSpec[2].ulKind = PRSPEC_PROPID; PropSpec[2].propid = WIA_DIP_REMOTE_DEV_ID;
PropVar[2].vt = VT_BSTR; PropVar[2].bstrVal = bstrRemoteDevId;
hr = pIPropDev->WriteMultiple(sizeof(PropVar)/sizeof(PROPVARIANT), PropSpec, PropVar, WIA_DIP_FIRST); if (FAILED(hr)) { ReportReadWriteMultipleError(hr, "CreateRemoteDevice", NULL, FALSE, sizeof(PropVar)/sizeof(PROPVARIANT), PropSpec); }
//
// !!! hack to fix device over-checking
//
hr = S_OK;
pIPropDev->Release(); } else { DBG_ERR(("CreateRemoteDevice, remote QI of IID_IWiaPropertyStorage failed (0x%X)", hr)); } } else { DBG_ERR(("CreateRemoteDevice, Remote CreateDevice call failed (0x%X)", hr)); } } else { DBG_ERR(("CreateRemoteDevice, Read propeties for BSTRDevID failed (0x%X)", hr)); }
pIWiaDevMgr->Release(); } else { DBG_ERR(("CreateRemoteDevice, remote CoCreateInstanceEx failed (0x%X)", hr)); }
CoRevertToSelf(); return hr; }
#endif
/**************************************************************************\
* CreateLocalDevice * * * * Arguments: * * * * Return Value: * * Status * * History: * * 1/5/1999 Original Version * \**************************************************************************/
HRESULT CreateLocalDevice( BSTR bstrDeviceID, IWiaPropertyStorage *pIWiaPropStg, IWiaItem **ppWiaItemRoot) { DBG_FN(::CreateLocalDevice); USES_CONVERSION; *ppWiaItemRoot = NULL;
//
// Build the root full item name.
//
WCHAR szTmp[32], *psz; BSTR bstrRootFullItemName;
#ifdef WINNT
psz = wcsstr(bstrDeviceID, L"}\\"); #else
psz = wcsstr(bstrDeviceID, L"\\"); #endif
if (!psz) { //This is no longer true
//DBG_ERR(("CreateLocalDevice, parse of device ID failed"));
//return E_INVALIDARG;
psz = bstrDeviceID; } else { #ifdef WINNT
psz += 2; #else
psz += 1; #endif
}
wcscpy(szTmp, psz); wcscat(szTmp, L"\\Root"); bstrRootFullItemName = SysAllocString(szTmp);
if (!bstrRootFullItemName) { DBG_ERR(("CreateLocalDevice, unable to allocate property stream device name")); return E_OUTOFMEMORY; }
//
// Get an interface pointer to the STI USD object.
//
HRESULT hr = E_FAIL; ACTIVE_DEVICE *pActiveDevice = NULL; PSTIDEVICE pFakeStiDevice = NULL; CWiaItem *pWiaItemRoot = NULL;
pActiveDevice = g_pDevMan->IsInList(DEV_MAN_IN_LIST_DEV_ID, bstrDeviceID); if (pActiveDevice) {
//
// Make sure driver is loaded
//
pActiveDevice->LoadDriver();
//
// Create the FakeStiDevice if we don't have one
//
if (!pActiveDevice->m_pFakeStiDevice) { pActiveDevice->m_pFakeStiDevice = new FakeStiDevice(); }
if (pActiveDevice->m_pFakeStiDevice) { pActiveDevice->m_pFakeStiDevice->Init(pActiveDevice); hr = pActiveDevice->m_pFakeStiDevice->QueryInterface(IID_IStiDevice, (VOID**)&pFakeStiDevice); if (SUCCEEDED(hr)) {
//
// Get a pointer to the WIA mini driver interface.
//
//
// Create the root item.
//
pWiaItemRoot = new CWiaItem; if (pWiaItemRoot) { //
// Query the root item for the IWiaItem interface.
//
hr = pWiaItemRoot->QueryInterface(IID_IWiaItem, (void**)ppWiaItemRoot); if (SUCCEEDED(hr)) { //
// Initialize the USD.
//
IUnknown *pIUnknownInner = NULL; IWiaDrvItem *pIDrvItemRoot = NULL; LONG lFlags = 0; //
// Call Sti Lock Manager to lock the device. Before
// drvInitializeWia is called, drivers wont have their
// IStiDevice pointer yet, so we can't call
// drvLockWiaDevice.
//
hr = g_pStiLockMgr->RequestLock(pActiveDevice, STIMON_AD_DEFAULT_WAIT_LOCK); if (SUCCEEDED(hr)) { _try { pWiaItemRoot->m_bInitialized = TRUE; DBG_WRN(("=> drvInitializeWia <=")); //DPRINTF(DM_TRACE, TEXT("=> drvInitializeWia <=\n"));
hr = pActiveDevice->m_DrvWrapper.WIA_drvInitializeWia( (BYTE*)*ppWiaItemRoot, lFlags, bstrDeviceID, bstrRootFullItemName, (IUnknown *)pFakeStiDevice, *ppWiaItemRoot, &pIDrvItemRoot, &pIUnknownInner, &(pWiaItemRoot->m_lLastDevErrVal)); DBG_WRN(("=> Returned from drvInitializeWia <=")); } _except(EXCEPTION_EXECUTE_HANDLER){ DBG_ERR(("CreateLocalDevice, exception in drvInitializeWia: %X", GetExceptionCode())); hr = E_FAIL; } pWiaItemRoot->m_bInitialized = FALSE; g_pStiLockMgr->RequestUnlock(pActiveDevice); } if (SUCCEEDED(hr) && pIDrvItemRoot) { if (pIUnknownInner) { DBG_TRC(("CreateLocalDevice driver provided optional inner component")); }
//
// Store the root to the driver item tree for later use.
//
pActiveDevice->SetDriverItem((CWiaDrvItem*) pIDrvItemRoot); //
// Initialize the root item.
//
hr = pWiaItemRoot->Initialize(pWiaItemRoot, pIWiaPropStg, pActiveDevice, (CWiaDrvItem *)pIDrvItemRoot, pIUnknownInner); if (SUCCEEDED(hr)) {
//
// AddRef the ActiveDevice since we're keeping it
//
pActiveDevice->AddRef(); } else { DBG_ERR(("CreateLocalDevice Initialize of root item failed")); pWiaItemRoot = NULL; } } else { DBG_ERR(("CreateLocalDevice drvInitializeWia failed. lDevErrVal: 0x%08X hr: 0x%X", pWiaItemRoot->m_lLastDevErrVal, hr)); } } else { DBG_ERR(("CreateLocalDevice unable to QI item for its IWIaItem interface")); } } else { DBG_ERR(("CreateLocalDevice unable to allocate root item")); hr = E_OUTOFMEMORY; } } else { DBG_ERR(("CreateLocalDevice, QI for fake STI device failed")); } } else { DBG_ERR(("CreateLocalDevice, unable to allocate fake device")); hr = E_OUTOFMEMORY; } } else { DBG_ERR(("CreateLocalDevice, unable to find active STI USD device object")); hr = WIA_S_NO_DEVICE_AVAILABLE; }
//
// Failure cleanup
//
if (FAILED(hr)) { *ppWiaItemRoot = NULL; if (pWiaItemRoot) { delete pWiaItemRoot; pWiaItemRoot = NULL; } }
//
// Other cleanup
//
if (pActiveDevice) { pActiveDevice->Release(); pActiveDevice = NULL; } SysFreeString(bstrRootFullItemName); return hr; }
/**************************************************************************\
* CWiaDevMgr::CreateDevice * * Create a WIA device from pbstrDeviceID * * Arguments: * * pbstrDeviceID - device ID * ppWiaItemRoot - return interface * * Return Value: * * Status * * History: * * 9/3/1998 Original Version * \**************************************************************************/
HRESULT _stdcall CWiaDevMgr::CreateDevice( BSTR bstrDeviceID, IWiaItem **ppWiaItemRoot) { DBG_FN(CWiaDevMgr::CreateDevice); HRESULT hr;
// Validate parameters.
if (bstrDeviceID == NULL) { DBG_ERR(("CWiaDevMgr::CreateDevice: invalid bstrDeviceID")); return E_INVALIDARG; }
if (ppWiaItemRoot == NULL) { DBG_ERR(("CWiaDevMgr::CreateDevice: invalid ppWiaItemRoot")); return E_INVALIDARG; }
*ppWiaItemRoot = NULL; // try to find a device matching pbstrDeviceID
IWiaPropertyStorage *pIWiaPropStg = NULL;
hr = FindMatchingDevice(bstrDeviceID, &pIWiaPropStg); if (hr != S_OK) { //
// Do a full refresh.
//
g_pDevMan->ReEnumerateDevices(DEV_MAN_FULL_REFRESH | DEV_MAN_GEN_EVENTS);
hr = FindMatchingDevice(bstrDeviceID, &pIWiaPropStg); }
if (hr == S_OK) { //
// find out if this is a remote device
//
#ifdef WINNT
BOOL bRemote = FALSE; BSTR bstrServer;
bRemote = IsDeviceRemote(pIWiaPropStg, &bstrServer);
if (bRemote) {
hr = CreateRemoteDevice(bstrServer, pIWiaPropStg, ppWiaItemRoot);
SysFreeString(bstrServer);
} else {
hr = CreateLocalDevice(bstrDeviceID, pIWiaPropStg, ppWiaItemRoot);
} #else
hr = CreateLocalDevice(bstrDeviceID, pIWiaPropStg, ppWiaItemRoot); #endif
pIWiaPropStg->Release(); } else { DBG_ERR(("CWiaDevMgr::CreateDevice Failed to find device: %ls", bstrDeviceID)); hr = WIA_S_NO_DEVICE_AVAILABLE; } return hr; }
/*******************************************************************************
* * SelectDevice * * Never called. This method executes completely on the client side. * * History: * * 9/2/1998 Original Version * *******************************************************************************/
HRESULT _stdcall CWiaDevMgr::SelectDeviceDlg( HWND hwndParent, LONG lDeviceType, LONG lFlags, BSTR *pbstrDeviceID, IWiaItem **ppWiaItemRoot) { DBG_FN(CWiaDevMgr::SelectDeviceDlg); DBG_ERR(("CWiaDevMgr::SelectDeviceDlg, Illegal server call, bad proxy")); return E_UNEXPECTED; }
/*******************************************************************************
* * SelectDevice * * Never called. This method executes completely on the client side. * * History: * * 9/2/1998 Original Version * *******************************************************************************/
HRESULT _stdcall CWiaDevMgr::SelectDeviceDlgID( HWND hwndParent, LONG lDeviceType, LONG lFlags, BSTR *pbstrDeviceID ) { DBG_FN(CWiaDevMgr::SelectDeviceDlgID); DBG_ERR(("CWiaDevMgr::SelectDeviceDlgID, Illegal server call, bad proxy")); return E_UNEXPECTED; }
/*******************************************************************************
* * AddDeviceDlg * * Never called. This method executes completely on the client side. * * History: * * 9/2/1998 Original Version * *******************************************************************************/
HRESULT _stdcall CWiaDevMgr::AddDeviceDlg( HWND hwndParent, LONG lFlags) { DBG_FN(CWiaDevMgr::AddDeviceDlg); HRESULT hres = E_NOTIMPL;
return hres; }
/*******************************************************************************
* * GetImage * * Never called. This method executes completely on the client side. * * History: * * 9/2/1998 Original Version * *******************************************************************************/
HRESULT _stdcall CWiaDevMgr::GetImageDlg( HWND hwndParent, LONG lDeviceType, LONG lFlags, LONG lIntent, IWiaItem *pItemRoot, BSTR bstrFilename, GUID *pguidFormat) { DBG_FN(CWiaDevMgr::GetImageDlg); DBG_ERR(("CWiaDevMgr::GetImageDlg, Illegal server call, bad proxy"));
return E_UNEXPECTED; }
/*******************************************************************************
* * CWiaDevMgr::RegisterEventCallbackProgram * * Register an WIA destination application * * Arguments: * * lFlags - * bstrDeviceID - * pEventGUID - * bstrCommandline - * bstrName - * bstrDescription - * bstrIcon - * * Return Value: * * status * * History: * * 10/14/1999 Original Version * *******************************************************************************/
HRESULT _stdcall CWiaDevMgr::RegisterEventCallbackProgram( LONG lFlags, BSTR bstrDeviceID, const GUID *pEventGUID, BSTR bstrCommandline, BSTR bstrName, BSTR bstrDescription, BSTR bstrIcon) { DBG_FN(CWiaDevMgr::RegisterEventCallbackProgram);
HRESULT hr; #ifndef UNICODE
CHAR szCommandline[MAX_PATH]; #endif
WCHAR *pPercentSign;
//
// Basic sanity check
//
if (! pEventGUID) { DBG_ERR(("CWiaDevMgr::RegisterEventCallbackProgram, bad pEventGUID")); return (E_INVALIDARG); }
if (! bstrCommandline) { DBG_ERR(("CWiaDevMgr::RegisterEventCallbackProgram, bad bstrCommandline")); return (E_INVALIDARG); }
//
// Check the commandline, there are either 2 % or 0
//
pPercentSign = wcschr(bstrCommandline, L'%'); if (pPercentSign) { if ((*(pPercentSign + 1) < L'0') || (*(pPercentSign + 1) > L'9')) { return (E_INVALIDARG); }
pPercentSign = wcschr(pPercentSign + 1, L'%'); if (! pPercentSign) { return (E_INVALIDARG); }
if ((*(pPercentSign + 1) < L'0') || (*(pPercentSign + 1) > L'9')) { return (E_INVALIDARG); } }
if ((lFlags != WIA_REGISTER_EVENT_CALLBACK) && (lFlags != WIA_SET_DEFAULT_HANDLER) && (lFlags != WIA_UNREGISTER_EVENT_CALLBACK)) { DBG_ERR(("CWiaDevMgr::RegisterEventCallbackProgram, bad lFlags")); return (E_INVALIDARG); }
hr = CoImpersonateClient(); if (FAILED(hr)) { DBG_ERR(("RegisterEventCallbackProgram, CoImpersonateClient failed (0x%X)", hr)); return hr; }
#ifndef UNICODE
WideCharToMultiByte(CP_ACP, 0, bstrCommandline, -1, szCommandline, MAX_PATH, NULL, NULL);
hr = g_eventNotifier.RegisterEventCallback( lFlags, bstrDeviceID, pEventGUID, NULL, // No CLSID available
szCommandline, bstrName, bstrDescription, bstrIcon); #else
hr = g_eventNotifier.RegisterEventCallback( lFlags, bstrDeviceID, pEventGUID, NULL, // No CLSID available
bstrCommandline, bstrName, bstrDescription, bstrIcon); #endif
//
// Revert back to ourselves.
//
CoRevertToSelf();
return (hr); }
/***************************************************************************
* * RegisterEventCallbackInterface * * Registers an WIA Event Callback * * Arguments: * * lFlags - * pWiaItemRoot - * llEvents - * pClsID - app can register using clsid or interface * pIWIAEventCallback - app can register using clsid or interface * * Return Value: * * status * * History: * * 9/2/1998 Original Version * \**************************************************************************/
HRESULT _stdcall CWiaDevMgr::RegisterEventCallbackInterface( LONG lFlags, BSTR bstrDeviceID, const GUID *pEventGUID, IWiaEventCallback *pIWIAEventCallback, IUnknown **ppIEventObj) { DBG_FN(CWiaDevMgr::RegisterEventCallbackInterface); HRESULT hr;
//
// Validate params
//
if (pEventGUID == NULL) { DBG_ERR(("CWiaDevMgr::RegisterEventCallbackInterface, bad pEventGUID")); return (E_INVALIDARG); }
if (pIWIAEventCallback == NULL) { DBG_ERR(("CWiaDevMgr::RegisterEventCallbackInterface, bad pIWIAEventCallback")); return (E_INVALIDARG); }
if (ppIEventObj == NULL) { DBG_ERR(("CWiaDevMgr::RegisterEventCallbackInterface, bad ppIEventObj")); return (E_INVALIDARG); }
//
// lFlags is ignored, register the callback always
//
//
// Register event
//
hr = g_eventNotifier.RegisterEventCallback( lFlags, bstrDeviceID, pEventGUID, pIWIAEventCallback, ppIEventObj);
return (hr); }
/***************************************************************************
* * RegisterEventCallbackCLSID * * Registers an WIA Event Callback * * Arguments: * * lFlags - * bstrDeviceID - * pEventGUID - * pClsID - app can register using clsid or interface * bstrDescription - * bstrIcon - * * Return Value: * * status * * History: * * 9/2/1998 Original Version * \**************************************************************************/
HRESULT _stdcall CWiaDevMgr::RegisterEventCallbackCLSID( LONG lFlags, BSTR bstrDeviceID, const GUID *pEventGUID, const GUID *pClsID, BSTR bstrName, BSTR bstrDescription, BSTR bstrIcon) { DBG_FN(CWiaDevMgr::RegisterEventCallbackCLSID); HRESULT hr;
//
// Validate params
//
if (pEventGUID == NULL) { DBG_ERR(("CWiaDevMgr::RegisterEventCallbackCLSID, bad pEventGUID")); return (E_INVALIDARG); }
if (pClsID == NULL) { DBG_ERR(("CWiaDevMgr::RegisterEventCallbackCLSID, bad pClsID")); return (E_INVALIDARG); }
if (lFlags == WIA_REGISTER_EVENT_CALLBACK) { DBG_TRC(("CWiaDevMgr::RegisterEventCallback")); } else {
if (lFlags == WIA_UNREGISTER_EVENT_CALLBACK) { DBG_TRC(("CWiaDevMgr::UnregisterEventCallback")); } else {
if (lFlags == WIA_SET_DEFAULT_HANDLER) { DBG_TRC(("CWiaDevMgr::SetDefaultHandler")); } else { DBG_ERR(("CWiaDevMgr::RegisterEventCallbackCLSID, Invalid operation")); return (HRESULT_FROM_WIN32(ERROR_INVALID_OPERATION)); } } }
//
// register event
//
hr = CoImpersonateClient(); if (FAILED(hr)) { DBG_ERR(("RegisterEventCallbackProgram, CoImpersonateClient failed (0x%X)", hr)); return hr; }
hr = g_eventNotifier.RegisterEventCallback( lFlags, bstrDeviceID, pEventGUID, pClsID, NULL, // No commandline necessary
bstrName, bstrDescription, bstrIcon); //
// Revert back to ourselves.
//
CoRevertToSelf();
return (hr); }
/***************************************************************************
* * Initialize * * This is the first call received from the Shell's Hardware event * notification. * * Arguments: * * pszParams - The parameter string we wrote in our registration. * Currently, we don't specify a parameter string, so this * will be empty. * * Return Value: * * status * * History: * * 07/12/2000 Original Version * \**************************************************************************/
HRESULT _stdcall CWiaDevMgr::Initialize( LPCWSTR pszParams) { HRESULT hr = E_FAIL;
//
// Initialize the device manager here. This is so that when HandleEvent gets
// processed, we can successfully enumerate the WIA devices.
//
hr = Initialize(); if (FAILED(hr)) { DBG_ERR(("CWiaDevMgr::Initialize(string), Initialize() call failed")); } return hr; }
/***************************************************************************
* * HandleEventWithContent * * This is the second call received from the Shell's Hardware event * notification. This tells us the driver letter of the volume that * just arrived. Our action is to find the appropriate file system driver * and launch the WIA Wizard. * * Arguments: * * pszDeviceID - The PnP device id. Ignored. * pszAltDeviceID - Alternate device id. For volume arrivals, * this is the drive letter. * pszEventType - String signifying the event type. Ignored. * pszContentTypeHandler - Content that triggered this event * pdataobject - IDataObject to get an HDROP to enumerate * the files found * * Return Value: * * status * * History: * * 08/04/2000 Original Version * \**************************************************************************/ HRESULT _stdcall CWiaDevMgr::HandleEventWithContent( LPCWSTR pszDeviceID, LPCWSTR pszAltDeviceID, LPCWSTR pszEventType, LPCWSTR /*pszContentTypeHandler*/, IDataObject* pdataobject) { HRESULT hres = E_INVALIDARG; BSTR bstrDeviceId = NULL;
// No need for this object
// NOTE: Appears to be a shell bug here - if I release it then it
// faults - looks like a double release.
//pdataobject->Release();
//pdataobject = NULL;
if (pszAltDeviceID) { hres = FindFileSystemDriver(pszAltDeviceID, &bstrDeviceId); if (hres != S_OK) { if (bstrDeviceId) { SysFreeString(bstrDeviceId); bstrDeviceId = NULL; }
//
// Get the DeviceId of the file system driver
//
WCHAR wszDevId[STI_MAX_INTERNAL_NAME_LENGTH];
memset(wszDevId, 0, sizeof(wszDevId));
//
// Construct Device ID. Device ID looks like:
// {MountPoint}
// e.g. {e:\}
//
lstrcpyW(wszDevId, L"{");
//
// We don't want to overrun our internal name length constarint, so we first check
// to see whether the string length of pszAltDeviceID is short enough to allow concatenation
// of {, }, pszAltDeviceID and NULL terminator, and still fit all this into a string of
// length STI_MAX_INTERNAL_NAME_LENGTH.
// Note the space after the brackets in sizeof(L"{} ").
//
if (lstrlenW(pszAltDeviceID) > (STI_MAX_INTERNAL_NAME_LENGTH - (sizeof(L"{} ") / sizeof(WCHAR)))) { //
// The name is too long, so we just insert our own name instead
//
lstrcatW(wszDevId, L"NameTooLong"); } else { lstrcatW(wszDevId, pszAltDeviceID); } lstrcatW(wszDevId, L"}");
bstrDeviceId = SysAllocString(wszDevId);
} //
// Run the Acquisition Manager on the file system driver.
//
hres = RunAcquisitionManager(bstrDeviceId); if (bstrDeviceId) { SysFreeString(bstrDeviceId); bstrDeviceId = NULL; } }
return hres; }
/***************************************************************************
* * HandleEvent * * This should never be called. WIA does not register for it. * * Arguments: * * pszDeviceID - The PnP device id. Ignored. * pszAltDeviceID - Alternate device id. For volume arrivals, this is * the drive letter. * pszEventType - String signifying the event type. Ignored. * * Return Value: * * status * * History: * * 07/12/2000 Original Version * 08/04/2000 Replaced by HandleEventWithContent * \**************************************************************************/
HRESULT _stdcall CWiaDevMgr::HandleEvent( LPCWSTR pszDeviceID, LPCWSTR pszAltDeviceID, LPCWSTR pszEventType) { return E_NOTIMPL; }
HRESULT CWiaDevMgr::FindFileSystemDriver( LPCWSTR pszAltDeviceID, BSTR *pbstrDeviceId) { HRESULT hr = S_OK; WCHAR *wszDevId = NULL; ACTIVE_DEVICE *pActiveDevice = NULL; DEVICE_INFO *pDeviceInfo = NULL;
*pbstrDeviceId = NULL;
//
// Do a full refresh.
//
hr = g_pDevMan->ReEnumerateDevices(DEV_MAN_FULL_REFRESH | DEV_MAN_GEN_EVENTS); pActiveDevice = g_pDevMan->IsInList(DEV_MAN_IN_LIST_ALT_ID, pszAltDeviceID);
//
// Let's check whether we found the device - a full refresh would have been done
// by this point if it was not found initially.
//
if (pActiveDevice) {
//
// Update the device information
//
pDeviceInfo = pActiveDevice->m_DrvWrapper.getDevInfo(); if (pDeviceInfo) { RefreshDevInfoFromMountPoint(pDeviceInfo, (WCHAR*)pszAltDeviceID); }
wszDevId = pActiveDevice->GetDeviceID(); pActiveDevice->Release(); } else { DBG_WRN(("CWiaDevMgr::FindFileSystemDriver, File system driver not available for this mount point")); hr = E_FAIL; }
if (wszDevId) { *pbstrDeviceId = SysAllocString(wszDevId); if (!*pbstrDeviceId) { DBG_WRN(("CWiaDevMgr::FindFileSystemDriver, Out of memory!")); hr = E_OUTOFMEMORY; } } return hr; }
HRESULT CWiaDevMgr::RunAcquisitionManager(BSTR bstrDeviceId) { HRESULT hr = E_FAIL; IWiaEventCallback *pCallback = NULL;
//
// CoCreate the Wia Acquisition Manager
//
hr = _CoCreateInstanceInConsoleSession (CLSID_Manager, NULL, CLSCTX_LOCAL_SERVER, IID_IWiaEventCallback, (void**)(&pCallback)); if (SUCCEEDED(hr)) {
//
// Send a Device_Connected event for the file system driver, indicating
// StiDeviceTypeDigitalCamera, so Acquisition Manager will show it's
// camera UI.
//
ULONG ulEventType = 0; hr = pCallback->ImageEventCallback(&WIA_EVENT_DEVICE_CONNECTED, NULL, bstrDeviceId, NULL, StiDeviceTypeDigitalCamera, NULL, &ulEventType, 0); if FAILED(hr) { DBG_ERR(("CWiaDevMgr::RunAcquisitionManager, ImageEventCallback failed")); } pCallback->Release(); }
return hr; }
|