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.
1601 lines
44 KiB
1601 lines
44 KiB
/*******************************************************************************
|
|
*
|
|
* (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;
|
|
}
|
|
|