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.

1601 lines
44 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1997
  4. *
  5. * TITLE: DevMgr.Cpp
  6. *
  7. * VERSION: 2.0
  8. *
  9. * AUTHOR: ReedB
  10. *
  11. * DATE: 26 Dec, 1997
  12. *
  13. * DESCRIPTION:
  14. * Class implementation for WIA device manager.
  15. * 07/12/2000 - Added support for shell's Hardware Event notification to
  16. * receive volume arrival notification and start the WIA Wizard.
  17. *
  18. *******************************************************************************/
  19. #include "precomp.h"
  20. #include "stiexe.h"
  21. #include "wiacfact.h"
  22. #include "wiamindr.h"
  23. #include "devmgr.h"
  24. #include "devinfo.h"
  25. #include "helpers.h"
  26. #include "wiaevntp.h"
  27. #include "wiapriv.h"
  28. #include "device.h"
  29. #include "lockmgr.h"
  30. #include "fstidev.h"
  31. #define INITGUID
  32. #include "initguid.h"
  33. //
  34. // Acquisition Manager's class ID {D13E3F25-1688-45A0-9743-759EB35CDF9A}
  35. // NOTE: We shouldn't really use this. Rather GetCLSIDFromProgID and use the
  36. // version independant AppID name.
  37. //
  38. DEFINE_GUID(
  39. CLSID_Manager,
  40. 0xD13E3F25, 0x1688, 0x45A0, 0x97, 0x43, 0x75, 0x9E, 0xB3, 0x5C, 0xDF, 0x9A);
  41. /**************************************************************************\
  42. * CWiaDevMgr::CreateInstance
  43. *
  44. * Create the CWiaDevMgr object.
  45. *
  46. * Arguments:
  47. *
  48. * iid - iid of dev manager
  49. * ppv - return interface pointer
  50. *
  51. * Return Value:
  52. *
  53. * status
  54. *
  55. * History:
  56. *
  57. * 9/2/1998 Original Version
  58. *
  59. \**************************************************************************/
  60. HRESULT CWiaDevMgr::CreateInstance(const IID& iid, void** ppv)
  61. {
  62. DBG_FN(CWiaDevMgr::CreateInstance);
  63. HRESULT hr;
  64. if ((iid == IID_IWiaDevMgr) || (iid == IID_IUnknown) || (iid == IID_IHWEventHandler)) {
  65. // Create the WIA device manager component.
  66. CWiaDevMgr* pDevMgr = new CWiaDevMgr();
  67. if (!pDevMgr) {
  68. DBG_ERR(("CWiaDevMgr::CreateInstance, Out of Memory"));
  69. return E_OUTOFMEMORY;
  70. }
  71. // Initialize the WIA device manager component.
  72. hr = pDevMgr->Initialize();
  73. if (FAILED(hr)) {
  74. delete pDevMgr;
  75. DBG_ERR(("CWiaDevMgr::CreateInstance, Initialize failed"));
  76. return hr;
  77. }
  78. // Get the requested interface from the device manager component.
  79. hr = pDevMgr->QueryInterface(iid, ppv);
  80. if (FAILED(hr)) {
  81. delete pDevMgr;
  82. DBG_ERR(("CWiaDevMgr::CreateInstance, QI failed"));
  83. return hr;
  84. }
  85. DBG_TRC(("CWiaDevMgr::CreateInstance, Created WiaDevMgr"));
  86. }
  87. else {
  88. hr = E_NOINTERFACE;
  89. DBG_ERR(("CWiaDevMgr::CreateInstance, Unknown interface (0x%X)", hr));
  90. }
  91. return hr;
  92. }
  93. /**************************************************************************\
  94. * QueryInterface
  95. * AddRef
  96. * Release
  97. *
  98. * CWiaDevMgr IUnknown Interface
  99. *
  100. * Arguments:
  101. *
  102. *
  103. *
  104. * Return Value:
  105. *
  106. *
  107. *
  108. * History:
  109. *
  110. * 9/2/1998 Original Version
  111. *
  112. \**************************************************************************/
  113. HRESULT __stdcall CWiaDevMgr::QueryInterface(const IID& iid, void** ppv)
  114. {
  115. *ppv = NULL;
  116. if ((iid == IID_IUnknown) || (iid == IID_IWiaDevMgr)) {
  117. *ppv = (IWiaDevMgr*) this;
  118. } else if (iid == IID_IWiaNotifyDevMgr) {
  119. *ppv = (IWiaNotifyDevMgr*) this;
  120. } else if (iid == IID_IHWEventHandler) {
  121. *ppv = (IHWEventHandler*) this;
  122. } else {
  123. return E_NOINTERFACE;
  124. }
  125. AddRef();
  126. return S_OK;
  127. }
  128. ULONG __stdcall CWiaDevMgr::AddRef()
  129. {
  130. InterlockedIncrement((long*) &m_cRef);
  131. return m_cRef;
  132. }
  133. ULONG __stdcall CWiaDevMgr::Release()
  134. {
  135. ULONG ulRefCount = m_cRef - 1;
  136. if (InterlockedDecrement((long*) &m_cRef) == 0) {
  137. delete this;
  138. return 0;
  139. }
  140. return ulRefCount;
  141. }
  142. /*******************************************************************************
  143. *
  144. * CWiaDevMgr
  145. * ~CWiaDevMgr
  146. *
  147. * CWiaDevMgr Constructor/Initialize/Destructor Methods.
  148. *
  149. * History:
  150. *
  151. * 9/2/1998 Original Version
  152. *
  153. \**************************************************************************/
  154. CWiaDevMgr::CWiaDevMgr():m_cRef(0)
  155. {
  156. m_cRef = 0;
  157. m_pITypeInfo = NULL;
  158. //
  159. // We're creating a component that exposes interfaces to clients, so
  160. // inform service to make sure service wont shutdown prematurely.
  161. //
  162. CWiaSvc::AddRef();
  163. }
  164. CWiaDevMgr::~CWiaDevMgr()
  165. {
  166. DBG_FN(CWiaDevMgr::~CWiaDevMgr);
  167. if (m_pITypeInfo != NULL) {
  168. m_pITypeInfo->Release();
  169. }
  170. //
  171. // Component is destroyed, so no more interfaces are exposed from here.
  172. // Inform server by decrementing it's reference count. This will allow
  173. // it to shutdown if it's no longer needed.
  174. //
  175. CWiaSvc::Release();
  176. }
  177. /**************************************************************************\
  178. * CWiaDevMgr::Initialize
  179. *
  180. * Create global sti instance
  181. *
  182. * Arguments:
  183. *
  184. * none
  185. *
  186. * Return Value:
  187. *
  188. * status
  189. *
  190. * History:
  191. *
  192. * 9/2/1998 Original Version
  193. *
  194. \**************************************************************************/
  195. HRESULT CWiaDevMgr::Initialize()
  196. {
  197. DBG_FN(CWiaDevMgr::Initialize);
  198. HRESULT hr = S_OK;
  199. return hr;
  200. }
  201. /**************************************************************************\
  202. * EnumWIADevInfo
  203. *
  204. * Create an WIA device information enumerator object.
  205. *
  206. * Arguments:
  207. *
  208. * lFlag - type of device to enumerate
  209. * ppIEnum - return enumerator
  210. *
  211. * Return Value:
  212. *
  213. * status
  214. *
  215. * History:
  216. *
  217. * 9/2/1998 Original Version
  218. *
  219. \**************************************************************************/
  220. HRESULT _stdcall CWiaDevMgr::EnumDeviceInfo(
  221. LONG lFlag,
  222. IEnumWIA_DEV_INFO** ppIEnum)
  223. {
  224. DBG_FN(CWiaDevMgr::EnumDeviceInfo);
  225. HRESULT hr = S_OK;
  226. DWORD dwWait = 0;
  227. //
  228. // Make sure that refreshing of the device list has completed. If
  229. // it hasn't, we'll wait up to DEVICE_LIST_WAIT_TIME, before proceeding
  230. // anyway. This will ensure the device list is not empty because
  231. // WIA device enumeration was called too soon after start-up (e.g.
  232. // app's CoCreateInstance call started the service).
  233. //
  234. //
  235. // Enumerate LPT if necessary.
  236. //
  237. EnumLpt();
  238. dwWait = WaitForSingleObject(g_hDevListCompleteEvent, DEVICE_LIST_WAIT_TIME);
  239. if (dwWait != WAIT_OBJECT_0) {
  240. DBG_WRN(("CWiaDevMgr::EnumDeviceInfo, Device list was not complete before enumeration call..."));
  241. }
  242. *ppIEnum = NULL;
  243. CEnumWIADevInfo* pEnum = new CEnumWIADevInfo;
  244. if (!pEnum) {
  245. DBG_ERR(("CWiaDevMgr::EnumDeviceInfo, Out of Memory"));
  246. return E_OUTOFMEMORY;
  247. }
  248. hr = pEnum->Initialize(lFlag);
  249. if (FAILED(hr)) {
  250. DBG_ERR(("CWiaDevMgr::EnumDeviceInfo, Initialize failed"));
  251. delete pEnum;
  252. return hr;
  253. }
  254. hr = pEnum->QueryInterface(IID_IEnumWIA_DEV_INFO,
  255. (void**) ppIEnum);
  256. if (FAILED(hr)) {
  257. DBG_ERR(("CWiaDevMgr::EnumDeviceInfo, QI for IWiaPropertyStorage failed"));
  258. delete pEnum;
  259. return E_UNEXPECTED;
  260. }
  261. return S_OK;
  262. }
  263. /**************************************************************************\
  264. * FindMatchingDevice
  265. *
  266. * search enumeration info for named device
  267. *
  268. * Arguments:
  269. *
  270. * ppIPropStg
  271. * pbstrDeviceID
  272. *
  273. * Return Value:
  274. *
  275. * Status
  276. *
  277. * History:
  278. *
  279. * 9/3/1998 Original Version
  280. *
  281. \**************************************************************************/
  282. HRESULT CWiaDevMgr::FindMatchingDevice(
  283. BSTR pbstrDeviceID,
  284. IWiaPropertyStorage **ppIWiaPropStg)
  285. {
  286. DBG_FN(CWiaDevMgr::FindMatchingDevice);
  287. // Enumerate the WIA devices, getting a IWIADevInfo
  288. // pointer for each. Use this interface to query the registry
  289. // based properties for each installed device.
  290. HRESULT hr;
  291. ULONG ul, ulFound = 0;
  292. BSTR bstrDevId;
  293. IEnumWIA_DEV_INFO *pIEnum;
  294. //
  295. // Notice that we specify DEV_MAN_ENUM_TYPE_ALL here.
  296. //
  297. hr = EnumDeviceInfo(DEV_MAN_ENUM_TYPE_ALL,&pIEnum);
  298. if (SUCCEEDED(hr)) {
  299. ul = 1;
  300. while ((hr = pIEnum->Next(1, ppIWiaPropStg, &ul)) == S_OK) {
  301. DBG_TRC(("# Found device candidate"));
  302. hr = ReadPropStr(WIA_DIP_DEV_ID, *ppIWiaPropStg, &bstrDevId);
  303. if (SUCCEEDED(hr)) {
  304. DBG_TRC(("# \tDevice Name: %S", bstrDevId));
  305. ulFound = !lstrcmpiW(bstrDevId, pbstrDeviceID);
  306. SysFreeString(bstrDevId);
  307. if (ulFound) {
  308. break;
  309. }
  310. }
  311. else {
  312. DBG_ERR(("FindMatchingDevice, ReadPropStr of WIA_DIP_DEV_ID failed"));
  313. }
  314. (*ppIWiaPropStg)->Release();
  315. *ppIWiaPropStg = NULL;
  316. }
  317. pIEnum->Release();
  318. }
  319. else {
  320. DBG_ERR(("FindMatchingDevice:Failed to create enumerator"));
  321. }
  322. if (SUCCEEDED(hr)) {
  323. if (!ulFound) {
  324. hr = S_FALSE;
  325. }
  326. }
  327. return hr;
  328. }
  329. #ifdef WINNT
  330. /**************************************************************************\
  331. * IsDeviceRemote
  332. *
  333. *
  334. *
  335. * Arguments:
  336. *
  337. *
  338. *
  339. * Return Value:
  340. *
  341. * TRUE if device is remote, caller must free server name.
  342. *
  343. * History:
  344. *
  345. * 1/5/1999 Original Version
  346. *
  347. \**************************************************************************/
  348. BOOL IsDeviceRemote(
  349. IWiaPropertyStorage *pIWiaPropStg,
  350. BSTR *pbstrServer)
  351. {
  352. DBG_FN(::IsDeviceRemote);
  353. HRESULT hr;
  354. hr = ReadPropStr(WIA_DIP_SERVER_NAME, pIWiaPropStg, pbstrServer);
  355. if ((SUCCEEDED(hr)) && (**pbstrServer)) {
  356. if (lstrcmpiW(*pbstrServer, L"local") != 0) {
  357. return TRUE;
  358. }
  359. }
  360. else {
  361. DBG_ERR(("IsDeviceRemote, ReadPropStr of WIA_DIP_SERVER_NAME failed"));
  362. DBG_ERR(("Registry value DeviceData\\Server may not have been set during installation"));
  363. }
  364. if (*pbstrServer) {
  365. SysFreeString(*pbstrServer);
  366. }
  367. return FALSE;
  368. }
  369. /**************************************************************************\
  370. * CreateRemoteDevice
  371. *
  372. *
  373. *
  374. * Arguments:
  375. *
  376. *
  377. *
  378. * Return Value:
  379. *
  380. * Status
  381. *
  382. * History:
  383. *
  384. * 1/5/1999 Original Version
  385. *
  386. \**************************************************************************/
  387. HRESULT CreateRemoteDevice(
  388. BSTR bstrServer,
  389. IWiaPropertyStorage *pIWiaPropStg,
  390. IWiaItem **ppWiaDevice
  391. )
  392. {
  393. DBG_FN(::CreateRemoteDevice);
  394. *ppWiaDevice = NULL;
  395. if (!bstrServer || !*bstrServer) {
  396. DBG_ERR(("CreateRemoteDevice, bad remote server name"));
  397. return E_INVALIDARG;
  398. }
  399. //
  400. // must use client
  401. //
  402. HRESULT hr = CoImpersonateClient();
  403. if (FAILED(hr)) {
  404. DBG_ERR(("CreateRemoteDevice, CoImpersonateClient failed (0x%X)", hr));
  405. return hr;
  406. }
  407. COSERVERINFO coServInfo;
  408. MULTI_QI multiQI[1];
  409. multiQI[0].pIID = &IID_IWiaDevMgr;
  410. multiQI[0].pItf = NULL;
  411. coServInfo.pwszName = bstrServer;
  412. coServInfo.pAuthInfo = NULL;
  413. coServInfo.dwReserved1 = 0;
  414. coServInfo.dwReserved2 = 0;
  415. //
  416. // create connection to dev mgr
  417. //
  418. hr = CoCreateInstanceEx(
  419. CLSID_WiaDevMgr,
  420. NULL,
  421. CLSCTX_REMOTE_SERVER,
  422. &coServInfo,
  423. 1,
  424. &multiQI[0]
  425. );
  426. if (hr == S_OK) {
  427. BSTR bstrRemoteDevId;
  428. BSTR bstrDevId;
  429. IWiaDevMgr *pIWiaDevMgr = (IWiaDevMgr*)multiQI[0].pItf;
  430. IWiaItem *pIWiaItem;
  431. //
  432. // use remote dev id to create
  433. //
  434. hr = ReadPropStr(WIA_DIP_DEV_ID, pIWiaPropStg, &bstrDevId);
  435. if (hr == S_OK) {
  436. hr = ReadPropStr(WIA_DIP_REMOTE_DEV_ID, pIWiaPropStg, &bstrRemoteDevId);
  437. }
  438. if (hr == S_OK) {
  439. //
  440. // create remote device
  441. //
  442. hr = pIWiaDevMgr->CreateDevice(bstrRemoteDevId, &pIWiaItem);
  443. if (hr == S_OK) {
  444. *ppWiaDevice = pIWiaItem;
  445. //
  446. // set devinfo props for remote access
  447. //
  448. IWiaPropertyStorage *pIPropDev;
  449. hr = pIWiaItem->QueryInterface(IID_IWiaPropertyStorage,
  450. (void **)&pIPropDev);
  451. if (hr == S_OK) {
  452. //
  453. // set copy of devinfo to contain correct Remote DEVID, DEVID and server name
  454. //
  455. PROPSPEC PropSpec[3];
  456. PROPVARIANT PropVar[3];
  457. memset(PropVar,0,sizeof(PropVar));
  458. // server name
  459. PropSpec[0].ulKind = PRSPEC_PROPID;
  460. PropSpec[0].propid = WIA_DIP_SERVER_NAME;
  461. PropVar[0].vt = VT_BSTR;
  462. PropVar[0].bstrVal = bstrServer;
  463. // DEVID
  464. PropSpec[1].ulKind = PRSPEC_PROPID;
  465. PropSpec[1].propid = WIA_DIP_DEV_ID;
  466. PropVar[1].vt = VT_BSTR;
  467. PropVar[1].bstrVal = bstrDevId;
  468. //Remote DEVID
  469. PropSpec[2].ulKind = PRSPEC_PROPID;
  470. PropSpec[2].propid = WIA_DIP_REMOTE_DEV_ID;
  471. PropVar[2].vt = VT_BSTR;
  472. PropVar[2].bstrVal = bstrRemoteDevId;
  473. hr = pIPropDev->WriteMultiple(sizeof(PropVar)/sizeof(PROPVARIANT),
  474. PropSpec,
  475. PropVar,
  476. WIA_DIP_FIRST);
  477. if (FAILED(hr)) {
  478. ReportReadWriteMultipleError(hr, "CreateRemoteDevice", NULL, FALSE, sizeof(PropVar)/sizeof(PROPVARIANT), PropSpec);
  479. }
  480. //
  481. // !!! hack to fix device over-checking
  482. //
  483. hr = S_OK;
  484. pIPropDev->Release();
  485. }
  486. else {
  487. DBG_ERR(("CreateRemoteDevice, remote QI of IID_IWiaPropertyStorage failed (0x%X)", hr));
  488. }
  489. } else {
  490. DBG_ERR(("CreateRemoteDevice, Remote CreateDevice call failed (0x%X)", hr));
  491. }
  492. } else {
  493. DBG_ERR(("CreateRemoteDevice, Read propeties for BSTRDevID failed (0x%X)", hr));
  494. }
  495. pIWiaDevMgr->Release();
  496. }
  497. else {
  498. DBG_ERR(("CreateRemoteDevice, remote CoCreateInstanceEx failed (0x%X)", hr));
  499. }
  500. CoRevertToSelf();
  501. return hr;
  502. }
  503. #endif
  504. /**************************************************************************\
  505. * CreateLocalDevice
  506. *
  507. *
  508. *
  509. * Arguments:
  510. *
  511. *
  512. *
  513. * Return Value:
  514. *
  515. * Status
  516. *
  517. * History:
  518. *
  519. * 1/5/1999 Original Version
  520. *
  521. \**************************************************************************/
  522. HRESULT CreateLocalDevice(
  523. BSTR bstrDeviceID,
  524. IWiaPropertyStorage *pIWiaPropStg,
  525. IWiaItem **ppWiaItemRoot)
  526. {
  527. DBG_FN(::CreateLocalDevice);
  528. USES_CONVERSION;
  529. *ppWiaItemRoot = NULL;
  530. //
  531. // Build the root full item name.
  532. //
  533. WCHAR szTmp[32], *psz;
  534. BSTR bstrRootFullItemName;
  535. #ifdef WINNT
  536. psz = wcsstr(bstrDeviceID, L"}\\");
  537. #else
  538. psz = wcsstr(bstrDeviceID, L"\\");
  539. #endif
  540. if (!psz) {
  541. //This is no longer true
  542. //DBG_ERR(("CreateLocalDevice, parse of device ID failed"));
  543. //return E_INVALIDARG;
  544. psz = bstrDeviceID;
  545. } else {
  546. #ifdef WINNT
  547. psz += 2;
  548. #else
  549. psz += 1;
  550. #endif
  551. }
  552. wcscpy(szTmp, psz);
  553. wcscat(szTmp, L"\\Root");
  554. bstrRootFullItemName = SysAllocString(szTmp);
  555. if (!bstrRootFullItemName) {
  556. DBG_ERR(("CreateLocalDevice, unable to allocate property stream device name"));
  557. return E_OUTOFMEMORY;
  558. }
  559. //
  560. // Get an interface pointer to the STI USD object.
  561. //
  562. HRESULT hr = E_FAIL;
  563. ACTIVE_DEVICE *pActiveDevice = NULL;
  564. PSTIDEVICE pFakeStiDevice = NULL;
  565. CWiaItem *pWiaItemRoot = NULL;
  566. pActiveDevice = g_pDevMan->IsInList(DEV_MAN_IN_LIST_DEV_ID, bstrDeviceID);
  567. if (pActiveDevice) {
  568. //
  569. // Make sure driver is loaded
  570. //
  571. pActiveDevice->LoadDriver();
  572. //
  573. // Create the FakeStiDevice if we don't have one
  574. //
  575. if (!pActiveDevice->m_pFakeStiDevice) {
  576. pActiveDevice->m_pFakeStiDevice = new FakeStiDevice();
  577. }
  578. if (pActiveDevice->m_pFakeStiDevice) {
  579. pActiveDevice->m_pFakeStiDevice->Init(pActiveDevice);
  580. hr = pActiveDevice->m_pFakeStiDevice->QueryInterface(IID_IStiDevice, (VOID**)&pFakeStiDevice);
  581. if (SUCCEEDED(hr)) {
  582. //
  583. // Get a pointer to the WIA mini driver interface.
  584. //
  585. //
  586. // Create the root item.
  587. //
  588. pWiaItemRoot = new CWiaItem;
  589. if (pWiaItemRoot) {
  590. //
  591. // Query the root item for the IWiaItem interface.
  592. //
  593. hr = pWiaItemRoot->QueryInterface(IID_IWiaItem,
  594. (void**)ppWiaItemRoot);
  595. if (SUCCEEDED(hr)) {
  596. //
  597. // Initialize the USD.
  598. //
  599. IUnknown *pIUnknownInner = NULL;
  600. IWiaDrvItem *pIDrvItemRoot = NULL;
  601. LONG lFlags = 0;
  602. //
  603. // Call Sti Lock Manager to lock the device. Before
  604. // drvInitializeWia is called, drivers wont have their
  605. // IStiDevice pointer yet, so we can't call
  606. // drvLockWiaDevice.
  607. //
  608. hr = g_pStiLockMgr->RequestLock(pActiveDevice, STIMON_AD_DEFAULT_WAIT_LOCK);
  609. if (SUCCEEDED(hr)) {
  610. _try {
  611. pWiaItemRoot->m_bInitialized = TRUE;
  612. DBG_WRN(("=> drvInitializeWia <="));
  613. //DPRINTF(DM_TRACE, TEXT("=> drvInitializeWia <=\n"));
  614. hr = pActiveDevice->m_DrvWrapper.WIA_drvInitializeWia(
  615. (BYTE*)*ppWiaItemRoot,
  616. lFlags,
  617. bstrDeviceID,
  618. bstrRootFullItemName,
  619. (IUnknown *)pFakeStiDevice,
  620. *ppWiaItemRoot,
  621. &pIDrvItemRoot,
  622. &pIUnknownInner,
  623. &(pWiaItemRoot->m_lLastDevErrVal));
  624. DBG_WRN(("=> Returned from drvInitializeWia <="));
  625. } _except(EXCEPTION_EXECUTE_HANDLER){
  626. DBG_ERR(("CreateLocalDevice, exception in drvInitializeWia: %X", GetExceptionCode()));
  627. hr = E_FAIL;
  628. }
  629. pWiaItemRoot->m_bInitialized = FALSE;
  630. g_pStiLockMgr->RequestUnlock(pActiveDevice);
  631. }
  632. if (SUCCEEDED(hr) && pIDrvItemRoot) {
  633. if (pIUnknownInner) {
  634. DBG_TRC(("CreateLocalDevice driver provided optional inner component"));
  635. }
  636. //
  637. // Store the root to the driver item tree for later use.
  638. //
  639. pActiveDevice->SetDriverItem((CWiaDrvItem*) pIDrvItemRoot);
  640. //
  641. // Initialize the root item.
  642. //
  643. hr = pWiaItemRoot->Initialize(pWiaItemRoot,
  644. pIWiaPropStg,
  645. pActiveDevice,
  646. (CWiaDrvItem *)pIDrvItemRoot,
  647. pIUnknownInner);
  648. if (SUCCEEDED(hr)) {
  649. //
  650. // AddRef the ActiveDevice since we're keeping it
  651. //
  652. pActiveDevice->AddRef();
  653. } else {
  654. DBG_ERR(("CreateLocalDevice Initialize of root item failed"));
  655. pWiaItemRoot = NULL;
  656. }
  657. }
  658. else {
  659. DBG_ERR(("CreateLocalDevice drvInitializeWia failed. lDevErrVal: 0x%08X hr: 0x%X", pWiaItemRoot->m_lLastDevErrVal, hr));
  660. }
  661. }
  662. else {
  663. DBG_ERR(("CreateLocalDevice unable to QI item for its IWIaItem interface"));
  664. }
  665. }
  666. else {
  667. DBG_ERR(("CreateLocalDevice unable to allocate root item"));
  668. hr = E_OUTOFMEMORY;
  669. }
  670. } else {
  671. DBG_ERR(("CreateLocalDevice, QI for fake STI device failed"));
  672. }
  673. } else {
  674. DBG_ERR(("CreateLocalDevice, unable to allocate fake device"));
  675. hr = E_OUTOFMEMORY;
  676. }
  677. }
  678. else {
  679. DBG_ERR(("CreateLocalDevice, unable to find active STI USD device object"));
  680. hr = WIA_S_NO_DEVICE_AVAILABLE;
  681. }
  682. //
  683. // Failure cleanup
  684. //
  685. if (FAILED(hr)) {
  686. *ppWiaItemRoot = NULL;
  687. if (pWiaItemRoot) {
  688. delete pWiaItemRoot;
  689. pWiaItemRoot = NULL;
  690. }
  691. }
  692. //
  693. // Other cleanup
  694. //
  695. if (pActiveDevice) {
  696. pActiveDevice->Release();
  697. pActiveDevice = NULL;
  698. }
  699. SysFreeString(bstrRootFullItemName);
  700. return hr;
  701. }
  702. /**************************************************************************\
  703. * CWiaDevMgr::CreateDevice
  704. *
  705. * Create a WIA device from pbstrDeviceID
  706. *
  707. * Arguments:
  708. *
  709. * pbstrDeviceID - device ID
  710. * ppWiaItemRoot - return interface
  711. *
  712. * Return Value:
  713. *
  714. * Status
  715. *
  716. * History:
  717. *
  718. * 9/3/1998 Original Version
  719. *
  720. \**************************************************************************/
  721. HRESULT _stdcall CWiaDevMgr::CreateDevice(
  722. BSTR bstrDeviceID,
  723. IWiaItem **ppWiaItemRoot)
  724. {
  725. DBG_FN(CWiaDevMgr::CreateDevice);
  726. HRESULT hr;
  727. // Validate parameters.
  728. if (bstrDeviceID == NULL) {
  729. DBG_ERR(("CWiaDevMgr::CreateDevice: invalid bstrDeviceID"));
  730. return E_INVALIDARG;
  731. }
  732. if (ppWiaItemRoot == NULL) {
  733. DBG_ERR(("CWiaDevMgr::CreateDevice: invalid ppWiaItemRoot"));
  734. return E_INVALIDARG;
  735. }
  736. *ppWiaItemRoot = NULL;
  737. // try to find a device matching pbstrDeviceID
  738. IWiaPropertyStorage *pIWiaPropStg = NULL;
  739. hr = FindMatchingDevice(bstrDeviceID, &pIWiaPropStg);
  740. if (hr != S_OK) {
  741. //
  742. // Do a full refresh.
  743. //
  744. g_pDevMan->ReEnumerateDevices(DEV_MAN_FULL_REFRESH | DEV_MAN_GEN_EVENTS);
  745. hr = FindMatchingDevice(bstrDeviceID, &pIWiaPropStg);
  746. }
  747. if (hr == S_OK) {
  748. //
  749. // find out if this is a remote device
  750. //
  751. #ifdef WINNT
  752. BOOL bRemote = FALSE;
  753. BSTR bstrServer;
  754. bRemote = IsDeviceRemote(pIWiaPropStg, &bstrServer);
  755. if (bRemote) {
  756. hr = CreateRemoteDevice(bstrServer, pIWiaPropStg, ppWiaItemRoot);
  757. SysFreeString(bstrServer);
  758. } else {
  759. hr = CreateLocalDevice(bstrDeviceID, pIWiaPropStg, ppWiaItemRoot);
  760. }
  761. #else
  762. hr = CreateLocalDevice(bstrDeviceID, pIWiaPropStg, ppWiaItemRoot);
  763. #endif
  764. pIWiaPropStg->Release();
  765. }
  766. else {
  767. DBG_ERR(("CWiaDevMgr::CreateDevice Failed to find device: %ls", bstrDeviceID));
  768. hr = WIA_S_NO_DEVICE_AVAILABLE;
  769. }
  770. return hr;
  771. }
  772. /*******************************************************************************
  773. *
  774. * SelectDevice
  775. *
  776. * Never called. This method executes completely on the client side.
  777. *
  778. * History:
  779. *
  780. * 9/2/1998 Original Version
  781. *
  782. *******************************************************************************/
  783. HRESULT _stdcall CWiaDevMgr::SelectDeviceDlg(
  784. HWND hwndParent,
  785. LONG lDeviceType,
  786. LONG lFlags,
  787. BSTR *pbstrDeviceID,
  788. IWiaItem **ppWiaItemRoot)
  789. {
  790. DBG_FN(CWiaDevMgr::SelectDeviceDlg);
  791. DBG_ERR(("CWiaDevMgr::SelectDeviceDlg, Illegal server call, bad proxy"));
  792. return E_UNEXPECTED;
  793. }
  794. /*******************************************************************************
  795. *
  796. * SelectDevice
  797. *
  798. * Never called. This method executes completely on the client side.
  799. *
  800. * History:
  801. *
  802. * 9/2/1998 Original Version
  803. *
  804. *******************************************************************************/
  805. HRESULT _stdcall CWiaDevMgr::SelectDeviceDlgID(
  806. HWND hwndParent,
  807. LONG lDeviceType,
  808. LONG lFlags,
  809. BSTR *pbstrDeviceID )
  810. {
  811. DBG_FN(CWiaDevMgr::SelectDeviceDlgID);
  812. DBG_ERR(("CWiaDevMgr::SelectDeviceDlgID, Illegal server call, bad proxy"));
  813. return E_UNEXPECTED;
  814. }
  815. /*******************************************************************************
  816. *
  817. * AddDeviceDlg
  818. *
  819. * Never called. This method executes completely on the client side.
  820. *
  821. * History:
  822. *
  823. * 9/2/1998 Original Version
  824. *
  825. *******************************************************************************/
  826. HRESULT _stdcall CWiaDevMgr::AddDeviceDlg(
  827. HWND hwndParent,
  828. LONG lFlags)
  829. {
  830. DBG_FN(CWiaDevMgr::AddDeviceDlg);
  831. HRESULT hres = E_NOTIMPL;
  832. return hres;
  833. }
  834. /*******************************************************************************
  835. *
  836. * GetImage
  837. *
  838. * Never called. This method executes completely on the client side.
  839. *
  840. * History:
  841. *
  842. * 9/2/1998 Original Version
  843. *
  844. *******************************************************************************/
  845. HRESULT _stdcall CWiaDevMgr::GetImageDlg(
  846. HWND hwndParent,
  847. LONG lDeviceType,
  848. LONG lFlags,
  849. LONG lIntent,
  850. IWiaItem *pItemRoot,
  851. BSTR bstrFilename,
  852. GUID *pguidFormat)
  853. {
  854. DBG_FN(CWiaDevMgr::GetImageDlg);
  855. DBG_ERR(("CWiaDevMgr::GetImageDlg, Illegal server call, bad proxy"));
  856. return E_UNEXPECTED;
  857. }
  858. /*******************************************************************************
  859. *
  860. * CWiaDevMgr::RegisterEventCallbackProgram
  861. *
  862. * Register an WIA destination application
  863. *
  864. * Arguments:
  865. *
  866. * lFlags -
  867. * bstrDeviceID -
  868. * pEventGUID -
  869. * bstrCommandline -
  870. * bstrName -
  871. * bstrDescription -
  872. * bstrIcon -
  873. *
  874. * Return Value:
  875. *
  876. * status
  877. *
  878. * History:
  879. *
  880. * 10/14/1999 Original Version
  881. *
  882. *******************************************************************************/
  883. HRESULT _stdcall CWiaDevMgr::RegisterEventCallbackProgram(
  884. LONG lFlags,
  885. BSTR bstrDeviceID,
  886. const GUID *pEventGUID,
  887. BSTR bstrCommandline,
  888. BSTR bstrName,
  889. BSTR bstrDescription,
  890. BSTR bstrIcon)
  891. {
  892. DBG_FN(CWiaDevMgr::RegisterEventCallbackProgram);
  893. HRESULT hr;
  894. #ifndef UNICODE
  895. CHAR szCommandline[MAX_PATH];
  896. #endif
  897. WCHAR *pPercentSign;
  898. //
  899. // Basic sanity check
  900. //
  901. if (! pEventGUID) {
  902. DBG_ERR(("CWiaDevMgr::RegisterEventCallbackProgram, bad pEventGUID"));
  903. return (E_INVALIDARG);
  904. }
  905. if (! bstrCommandline) {
  906. DBG_ERR(("CWiaDevMgr::RegisterEventCallbackProgram, bad bstrCommandline"));
  907. return (E_INVALIDARG);
  908. }
  909. //
  910. // Check the commandline, there are either 2 % or 0
  911. //
  912. pPercentSign = wcschr(bstrCommandline, L'%');
  913. if (pPercentSign) {
  914. if ((*(pPercentSign + 1) < L'0') || (*(pPercentSign + 1) > L'9')) {
  915. return (E_INVALIDARG);
  916. }
  917. pPercentSign = wcschr(pPercentSign + 1, L'%');
  918. if (! pPercentSign) {
  919. return (E_INVALIDARG);
  920. }
  921. if ((*(pPercentSign + 1) < L'0') || (*(pPercentSign + 1) > L'9')) {
  922. return (E_INVALIDARG);
  923. }
  924. }
  925. if ((lFlags != WIA_REGISTER_EVENT_CALLBACK) &&
  926. (lFlags != WIA_SET_DEFAULT_HANDLER) &&
  927. (lFlags != WIA_UNREGISTER_EVENT_CALLBACK)) {
  928. DBG_ERR(("CWiaDevMgr::RegisterEventCallbackProgram, bad lFlags"));
  929. return (E_INVALIDARG);
  930. }
  931. hr = CoImpersonateClient();
  932. if (FAILED(hr)) {
  933. DBG_ERR(("RegisterEventCallbackProgram, CoImpersonateClient failed (0x%X)", hr));
  934. return hr;
  935. }
  936. #ifndef UNICODE
  937. WideCharToMultiByte(CP_ACP,
  938. 0,
  939. bstrCommandline,
  940. -1,
  941. szCommandline,
  942. MAX_PATH,
  943. NULL,
  944. NULL);
  945. hr = g_eventNotifier.RegisterEventCallback(
  946. lFlags,
  947. bstrDeviceID,
  948. pEventGUID,
  949. NULL, // No CLSID available
  950. szCommandline,
  951. bstrName,
  952. bstrDescription,
  953. bstrIcon);
  954. #else
  955. hr = g_eventNotifier.RegisterEventCallback(
  956. lFlags,
  957. bstrDeviceID,
  958. pEventGUID,
  959. NULL, // No CLSID available
  960. bstrCommandline,
  961. bstrName,
  962. bstrDescription,
  963. bstrIcon);
  964. #endif
  965. //
  966. // Revert back to ourselves.
  967. //
  968. CoRevertToSelf();
  969. return (hr);
  970. }
  971. /***************************************************************************
  972. *
  973. * RegisterEventCallbackInterface
  974. *
  975. * Registers an WIA Event Callback
  976. *
  977. * Arguments:
  978. *
  979. * lFlags -
  980. * pWiaItemRoot -
  981. * llEvents -
  982. * pClsID - app can register using clsid or interface
  983. * pIWIAEventCallback - app can register using clsid or interface
  984. *
  985. * Return Value:
  986. *
  987. * status
  988. *
  989. * History:
  990. *
  991. * 9/2/1998 Original Version
  992. *
  993. \**************************************************************************/
  994. HRESULT _stdcall CWiaDevMgr::RegisterEventCallbackInterface(
  995. LONG lFlags,
  996. BSTR bstrDeviceID,
  997. const GUID *pEventGUID,
  998. IWiaEventCallback *pIWIAEventCallback,
  999. IUnknown **ppIEventObj)
  1000. {
  1001. DBG_FN(CWiaDevMgr::RegisterEventCallbackInterface);
  1002. HRESULT hr;
  1003. //
  1004. // Validate params
  1005. //
  1006. if (pEventGUID == NULL) {
  1007. DBG_ERR(("CWiaDevMgr::RegisterEventCallbackInterface, bad pEventGUID"));
  1008. return (E_INVALIDARG);
  1009. }
  1010. if (pIWIAEventCallback == NULL) {
  1011. DBG_ERR(("CWiaDevMgr::RegisterEventCallbackInterface, bad pIWIAEventCallback"));
  1012. return (E_INVALIDARG);
  1013. }
  1014. if (ppIEventObj == NULL) {
  1015. DBG_ERR(("CWiaDevMgr::RegisterEventCallbackInterface, bad ppIEventObj"));
  1016. return (E_INVALIDARG);
  1017. }
  1018. //
  1019. // lFlags is ignored, register the callback always
  1020. //
  1021. //
  1022. // Register event
  1023. //
  1024. hr = g_eventNotifier.RegisterEventCallback(
  1025. lFlags,
  1026. bstrDeviceID,
  1027. pEventGUID,
  1028. pIWIAEventCallback,
  1029. ppIEventObj);
  1030. return (hr);
  1031. }
  1032. /***************************************************************************
  1033. *
  1034. * RegisterEventCallbackCLSID
  1035. *
  1036. * Registers an WIA Event Callback
  1037. *
  1038. * Arguments:
  1039. *
  1040. * lFlags -
  1041. * bstrDeviceID -
  1042. * pEventGUID -
  1043. * pClsID - app can register using clsid or interface
  1044. * bstrDescription -
  1045. * bstrIcon -
  1046. *
  1047. * Return Value:
  1048. *
  1049. * status
  1050. *
  1051. * History:
  1052. *
  1053. * 9/2/1998 Original Version
  1054. *
  1055. \**************************************************************************/
  1056. HRESULT _stdcall CWiaDevMgr::RegisterEventCallbackCLSID(
  1057. LONG lFlags,
  1058. BSTR bstrDeviceID,
  1059. const GUID *pEventGUID,
  1060. const GUID *pClsID,
  1061. BSTR bstrName,
  1062. BSTR bstrDescription,
  1063. BSTR bstrIcon)
  1064. {
  1065. DBG_FN(CWiaDevMgr::RegisterEventCallbackCLSID);
  1066. HRESULT hr;
  1067. //
  1068. // Validate params
  1069. //
  1070. if (pEventGUID == NULL) {
  1071. DBG_ERR(("CWiaDevMgr::RegisterEventCallbackCLSID, bad pEventGUID"));
  1072. return (E_INVALIDARG);
  1073. }
  1074. if (pClsID == NULL) {
  1075. DBG_ERR(("CWiaDevMgr::RegisterEventCallbackCLSID, bad pClsID"));
  1076. return (E_INVALIDARG);
  1077. }
  1078. if (lFlags == WIA_REGISTER_EVENT_CALLBACK) {
  1079. DBG_TRC(("CWiaDevMgr::RegisterEventCallback"));
  1080. } else {
  1081. if (lFlags == WIA_UNREGISTER_EVENT_CALLBACK) {
  1082. DBG_TRC(("CWiaDevMgr::UnregisterEventCallback"));
  1083. } else {
  1084. if (lFlags == WIA_SET_DEFAULT_HANDLER) {
  1085. DBG_TRC(("CWiaDevMgr::SetDefaultHandler"));
  1086. } else {
  1087. DBG_ERR(("CWiaDevMgr::RegisterEventCallbackCLSID, Invalid operation"));
  1088. return (HRESULT_FROM_WIN32(ERROR_INVALID_OPERATION));
  1089. }
  1090. }
  1091. }
  1092. //
  1093. // register event
  1094. //
  1095. hr = CoImpersonateClient();
  1096. if (FAILED(hr)) {
  1097. DBG_ERR(("RegisterEventCallbackProgram, CoImpersonateClient failed (0x%X)", hr));
  1098. return hr;
  1099. }
  1100. hr = g_eventNotifier.RegisterEventCallback(
  1101. lFlags,
  1102. bstrDeviceID,
  1103. pEventGUID,
  1104. pClsID,
  1105. NULL, // No commandline necessary
  1106. bstrName,
  1107. bstrDescription,
  1108. bstrIcon);
  1109. //
  1110. // Revert back to ourselves.
  1111. //
  1112. CoRevertToSelf();
  1113. return (hr);
  1114. }
  1115. /***************************************************************************
  1116. *
  1117. * Initialize
  1118. *
  1119. * This is the first call received from the Shell's Hardware event
  1120. * notification.
  1121. *
  1122. * Arguments:
  1123. *
  1124. * pszParams - The parameter string we wrote in our registration.
  1125. * Currently, we don't specify a parameter string, so this
  1126. * will be empty.
  1127. *
  1128. * Return Value:
  1129. *
  1130. * status
  1131. *
  1132. * History:
  1133. *
  1134. * 07/12/2000 Original Version
  1135. *
  1136. \**************************************************************************/
  1137. HRESULT _stdcall CWiaDevMgr::Initialize(
  1138. LPCWSTR pszParams)
  1139. {
  1140. HRESULT hr = E_FAIL;
  1141. //
  1142. // Initialize the device manager here. This is so that when HandleEvent gets
  1143. // processed, we can successfully enumerate the WIA devices.
  1144. //
  1145. hr = Initialize();
  1146. if (FAILED(hr)) {
  1147. DBG_ERR(("CWiaDevMgr::Initialize(string), Initialize() call failed"));
  1148. }
  1149. return hr;
  1150. }
  1151. /***************************************************************************
  1152. *
  1153. * HandleEventWithContent
  1154. *
  1155. * This is the second call received from the Shell's Hardware event
  1156. * notification. This tells us the driver letter of the volume that
  1157. * just arrived. Our action is to find the appropriate file system driver
  1158. * and launch the WIA Wizard.
  1159. *
  1160. * Arguments:
  1161. *
  1162. * pszDeviceID - The PnP device id. Ignored.
  1163. * pszAltDeviceID - Alternate device id. For volume arrivals,
  1164. * this is the drive letter.
  1165. * pszEventType - String signifying the event type. Ignored.
  1166. * pszContentTypeHandler - Content that triggered this event
  1167. * pdataobject - IDataObject to get an HDROP to enumerate
  1168. * the files found
  1169. *
  1170. * Return Value:
  1171. *
  1172. * status
  1173. *
  1174. * History:
  1175. *
  1176. * 08/04/2000 Original Version
  1177. *
  1178. \**************************************************************************/
  1179. HRESULT _stdcall CWiaDevMgr::HandleEventWithContent(
  1180. LPCWSTR pszDeviceID,
  1181. LPCWSTR pszAltDeviceID,
  1182. LPCWSTR pszEventType,
  1183. LPCWSTR /*pszContentTypeHandler*/,
  1184. IDataObject* pdataobject)
  1185. {
  1186. HRESULT hres = E_INVALIDARG;
  1187. BSTR bstrDeviceId = NULL;
  1188. // No need for this object
  1189. // NOTE: Appears to be a shell bug here - if I release it then it
  1190. // faults - looks like a double release.
  1191. //pdataobject->Release();
  1192. //pdataobject = NULL;
  1193. if (pszAltDeviceID)
  1194. {
  1195. hres = FindFileSystemDriver(pszAltDeviceID, &bstrDeviceId);
  1196. if (hres != S_OK) {
  1197. if (bstrDeviceId) {
  1198. SysFreeString(bstrDeviceId);
  1199. bstrDeviceId = NULL;
  1200. }
  1201. //
  1202. // Get the DeviceId of the file system driver
  1203. //
  1204. WCHAR wszDevId[STI_MAX_INTERNAL_NAME_LENGTH];
  1205. memset(wszDevId, 0, sizeof(wszDevId));
  1206. //
  1207. // Construct Device ID. Device ID looks like:
  1208. // {MountPoint}
  1209. // e.g. {e:\}
  1210. //
  1211. lstrcpyW(wszDevId, L"{");
  1212. //
  1213. // We don't want to overrun our internal name length constarint, so we first check
  1214. // to see whether the string length of pszAltDeviceID is short enough to allow concatenation
  1215. // of {, }, pszAltDeviceID and NULL terminator, and still fit all this into a string of
  1216. // length STI_MAX_INTERNAL_NAME_LENGTH.
  1217. // Note the space after the brackets in sizeof(L"{} ").
  1218. //
  1219. if (lstrlenW(pszAltDeviceID) > (STI_MAX_INTERNAL_NAME_LENGTH - (sizeof(L"{} ") / sizeof(WCHAR)))) {
  1220. //
  1221. // The name is too long, so we just insert our own name instead
  1222. //
  1223. lstrcatW(wszDevId, L"NameTooLong");
  1224. } else {
  1225. lstrcatW(wszDevId, pszAltDeviceID);
  1226. }
  1227. lstrcatW(wszDevId, L"}");
  1228. bstrDeviceId = SysAllocString(wszDevId);
  1229. }
  1230. //
  1231. // Run the Acquisition Manager on the file system driver.
  1232. //
  1233. hres = RunAcquisitionManager(bstrDeviceId);
  1234. if (bstrDeviceId) {
  1235. SysFreeString(bstrDeviceId);
  1236. bstrDeviceId = NULL;
  1237. }
  1238. }
  1239. return hres;
  1240. }
  1241. /***************************************************************************
  1242. *
  1243. * HandleEvent
  1244. *
  1245. * This should never be called. WIA does not register for it.
  1246. *
  1247. * Arguments:
  1248. *
  1249. * pszDeviceID - The PnP device id. Ignored.
  1250. * pszAltDeviceID - Alternate device id. For volume arrivals, this is
  1251. * the drive letter.
  1252. * pszEventType - String signifying the event type. Ignored.
  1253. *
  1254. * Return Value:
  1255. *
  1256. * status
  1257. *
  1258. * History:
  1259. *
  1260. * 07/12/2000 Original Version
  1261. * 08/04/2000 Replaced by HandleEventWithContent
  1262. *
  1263. \**************************************************************************/
  1264. HRESULT _stdcall CWiaDevMgr::HandleEvent(
  1265. LPCWSTR pszDeviceID,
  1266. LPCWSTR pszAltDeviceID,
  1267. LPCWSTR pszEventType)
  1268. {
  1269. return E_NOTIMPL;
  1270. }
  1271. HRESULT CWiaDevMgr::FindFileSystemDriver(
  1272. LPCWSTR pszAltDeviceID,
  1273. BSTR *pbstrDeviceId)
  1274. {
  1275. HRESULT hr = S_OK;
  1276. WCHAR *wszDevId = NULL;
  1277. ACTIVE_DEVICE *pActiveDevice = NULL;
  1278. DEVICE_INFO *pDeviceInfo = NULL;
  1279. *pbstrDeviceId = NULL;
  1280. //
  1281. // Do a full refresh.
  1282. //
  1283. hr = g_pDevMan->ReEnumerateDevices(DEV_MAN_FULL_REFRESH | DEV_MAN_GEN_EVENTS);
  1284. pActiveDevice = g_pDevMan->IsInList(DEV_MAN_IN_LIST_ALT_ID, pszAltDeviceID);
  1285. //
  1286. // Let's check whether we found the device - a full refresh would have been done
  1287. // by this point if it was not found initially.
  1288. //
  1289. if (pActiveDevice) {
  1290. //
  1291. // Update the device information
  1292. //
  1293. pDeviceInfo = pActiveDevice->m_DrvWrapper.getDevInfo();
  1294. if (pDeviceInfo) {
  1295. RefreshDevInfoFromMountPoint(pDeviceInfo, (WCHAR*)pszAltDeviceID);
  1296. }
  1297. wszDevId = pActiveDevice->GetDeviceID();
  1298. pActiveDevice->Release();
  1299. } else {
  1300. DBG_WRN(("CWiaDevMgr::FindFileSystemDriver, File system driver not available for this mount point"));
  1301. hr = E_FAIL;
  1302. }
  1303. if (wszDevId) {
  1304. *pbstrDeviceId = SysAllocString(wszDevId);
  1305. if (!*pbstrDeviceId) {
  1306. DBG_WRN(("CWiaDevMgr::FindFileSystemDriver, Out of memory!"));
  1307. hr = E_OUTOFMEMORY;
  1308. }
  1309. }
  1310. return hr;
  1311. }
  1312. HRESULT CWiaDevMgr::RunAcquisitionManager(BSTR bstrDeviceId)
  1313. {
  1314. HRESULT hr = E_FAIL;
  1315. IWiaEventCallback *pCallback = NULL;
  1316. //
  1317. // CoCreate the Wia Acquisition Manager
  1318. //
  1319. hr = _CoCreateInstanceInConsoleSession (CLSID_Manager,
  1320. NULL,
  1321. CLSCTX_LOCAL_SERVER,
  1322. IID_IWiaEventCallback,
  1323. (void**)(&pCallback));
  1324. if (SUCCEEDED(hr)) {
  1325. //
  1326. // Send a Device_Connected event for the file system driver, indicating
  1327. // StiDeviceTypeDigitalCamera, so Acquisition Manager will show it's
  1328. // camera UI.
  1329. //
  1330. ULONG ulEventType = 0;
  1331. hr = pCallback->ImageEventCallback(&WIA_EVENT_DEVICE_CONNECTED,
  1332. NULL,
  1333. bstrDeviceId,
  1334. NULL,
  1335. StiDeviceTypeDigitalCamera,
  1336. NULL,
  1337. &ulEventType,
  1338. 0);
  1339. if FAILED(hr) {
  1340. DBG_ERR(("CWiaDevMgr::RunAcquisitionManager, ImageEventCallback failed"));
  1341. }
  1342. pCallback->Release();
  1343. }
  1344. return hr;
  1345. }