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.

1951 lines
58 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 2000
  4. *
  5. * TITLE: drvwrap.cpp
  6. *
  7. * VERSION: 1.0
  8. *
  9. * AUTHOR: ByronC
  10. *
  11. * DATE: 6 Nov, 2000
  12. *
  13. * DESCRIPTION:
  14. * Declarations and definitions for the WIA driver wrapper class.
  15. * It faciliates JIT loading/unloading of drivers and provides an extra layer
  16. * of abstraction for WIA server components - they don't deal directly with
  17. * driver interfaces. This is to make us more robust and implement smart
  18. * driver handling.
  19. *
  20. *******************************************************************************/
  21. #include "precomp.h"
  22. #include "stiexe.h"
  23. #include "lockmgr.h"
  24. /**************************************************************************\
  25. * CDrvWrap::CDrvWrap
  26. *
  27. * Constructor for driver wrapper.
  28. *
  29. * Arguments:
  30. *
  31. * None.
  32. *
  33. * Return Value:
  34. *
  35. * None.
  36. *
  37. * History:
  38. *
  39. * 11/06/2000 Original Version
  40. *
  41. \**************************************************************************/
  42. CDrvWrap::CDrvWrap()
  43. {
  44. m_hDriverDLL = NULL;
  45. m_hInternalMutex = NULL;
  46. m_pDeviceInfo = NULL;
  47. m_pUsdIUnknown = NULL;
  48. m_pIStiUSD = NULL;
  49. m_pIWiaMiniDrv = NULL;
  50. m_pIStiDeviceControl = NULL;
  51. m_bJITLoading = FALSE;
  52. m_lWiaTreeCount = 0;
  53. m_bPreparedForUse = FALSE;
  54. m_bUnload = FALSE;
  55. }
  56. /**************************************************************************\
  57. * CDrvWrap::~CDrvWrap
  58. *
  59. * Desctructor for driver wrapper. Calls internal clear to make sure
  60. * driver is unloaded if it hasn't been already. Releases any
  61. * resources help by the wrapper that needs to live accross driver
  62. * loading/unloading, such as the DEVICE_INFO
  63. *
  64. * Arguments:
  65. *
  66. * None.
  67. *
  68. * Return Value:
  69. *
  70. * None.
  71. *
  72. * History:
  73. *
  74. * 11/06/2000 Original Version
  75. *
  76. \**************************************************************************/
  77. CDrvWrap::~CDrvWrap()
  78. {
  79. //
  80. // Release driver interfaces and unload driver
  81. //
  82. InternalClear();
  83. if (m_hInternalMutex) {
  84. CloseHandle(m_hInternalMutex);
  85. m_hInternalMutex = NULL;
  86. }
  87. if (m_pDeviceInfo) {
  88. DestroyDevInfo(m_pDeviceInfo);
  89. m_pDeviceInfo = NULL;
  90. }
  91. }
  92. /**************************************************************************\
  93. * CDrvWrap::Initialize
  94. *
  95. * Initializes any object members that could not be set in the constructor,
  96. * such as allocating resources that may fail.
  97. *
  98. * Arguments:
  99. *
  100. * None.
  101. *
  102. * Return Value:
  103. *
  104. * Status
  105. *
  106. * History:
  107. *
  108. * 11/06/2000 Original Version
  109. *
  110. \**************************************************************************/
  111. HRESULT CDrvWrap::Initialize()
  112. {
  113. HRESULT hr = E_FAIL;
  114. m_hInternalMutex = CreateMutex(NULL, FALSE, NULL);
  115. m_pDeviceInfo = (DEVICE_INFO*) LocalAlloc(LPTR, sizeof(DEVICE_INFO));
  116. if (!m_hInternalMutex || !m_pDeviceInfo) {
  117. DBG_ERR(("CDrvWrap::Initialize, out of memory!"));
  118. hr = E_OUTOFMEMORY;
  119. } else {
  120. hr = S_OK;
  121. }
  122. if (FAILED(hr)) {
  123. if (m_hInternalMutex) {
  124. CloseHandle(m_hInternalMutex);
  125. m_hInternalMutex = NULL;
  126. }
  127. if (m_pDeviceInfo) {
  128. LocalFree(m_pDeviceInfo);
  129. m_pDeviceInfo = NULL;
  130. }
  131. }
  132. return hr;
  133. }
  134. /**************************************************************************\
  135. * CDrvWrap::QueryInterface
  136. *
  137. * This QI will return it's own "this" pointer for IUnknown, but will
  138. * delegate down to the USD for any other interface.
  139. *
  140. * Arguments:
  141. *
  142. * iid - The interface ID of the requested interface.
  143. * ppv - Pointer to variable receiving the interface pointer.
  144. *
  145. * Return Value:
  146. *
  147. * Status
  148. *
  149. * History:
  150. *
  151. * 11/06/2000 Original Version
  152. *
  153. \**************************************************************************/
  154. HRESULT _stdcall CDrvWrap::QueryInterface(const IID& iid, void** ppv)
  155. {
  156. HRESULT hr = E_NOINTERFACE;
  157. //
  158. // Always delegate down to USD, unless asking for IUnknown
  159. //
  160. if (iid == IID_IUnknown) {
  161. *ppv = (IUnknown*) this;
  162. AddRef();
  163. hr = S_OK;
  164. } else {
  165. if (PrepForUse(FALSE)) {
  166. if (m_pUsdIUnknown) {
  167. hr = m_pUsdIUnknown->QueryInterface(iid, ppv);
  168. } else {
  169. DBG_TRC(("CDrvWrap::QueryInterface, m_pUsdIUnknown == NULL"))
  170. }
  171. } else {
  172. DBG_WRN(("CDrvWrap::QueryInterface, attempting to call IStiUSD::QueryInterface when driver is not loaded"));
  173. }
  174. }
  175. return hr;
  176. }
  177. /**************************************************************************\
  178. * CDrvWrap::AddRef
  179. *
  180. * Notice that this method simply returns 2. We don't want to subject the
  181. * lifetime of this object to ref-counting.
  182. *
  183. * Arguments:
  184. *
  185. * None.
  186. *
  187. * Return Value:
  188. *
  189. * 2
  190. *
  191. * History:
  192. *
  193. * 11/06/2000 Original Version
  194. *
  195. \**************************************************************************/
  196. ULONG _stdcall CDrvWrap::AddRef(void)
  197. {
  198. ULONG ulCount = 2;
  199. //
  200. // Since we plan to manually load/unload the driver, we don't really want
  201. // to honor any AddRef/Release calls.
  202. //
  203. return ulCount;
  204. }
  205. /**************************************************************************\
  206. * CDrvWrap::Release
  207. *
  208. * Notice that this method simply returns 1. We don't want to subject the
  209. * lifetime of this object to ref-counting.
  210. *
  211. * Arguments:
  212. *
  213. *
  214. *
  215. * Return Value:
  216. *
  217. * 1
  218. *
  219. * History:
  220. *
  221. * 11/06/2000 Original Version
  222. *
  223. \**************************************************************************/
  224. ULONG _stdcall CDrvWrap::Release(void)
  225. {
  226. ULONG ulCount = 1;
  227. //
  228. // We don't want this object to be controlled with refcounting - the
  229. // DEVICE_OBJECT will manually delete us when it's done. Also, since
  230. // we want to manually load/unload the driver, we don't really want
  231. // to honor any AddRef/Release calls down to it..
  232. //
  233. return ulCount;
  234. }
  235. /**************************************************************************\
  236. * CDrvWrap::LoadInitDriver
  237. *
  238. * Load the USD and initialize it appropriately.
  239. *
  240. * Arguments:
  241. *
  242. * hKeyDeviceParams - The device registry key. This is handed down to the
  243. * driver during intialization. If it is NULL, we will
  244. * attempt to find the real one to hand down to the
  245. * driver. For volume devices, there is no registry
  246. * key and NULL will be handed down.
  247. *
  248. * Return Value:
  249. *
  250. * Status
  251. *
  252. * History:
  253. *
  254. * 11/06/2000 Original Version
  255. *
  256. \**************************************************************************/
  257. HRESULT CDrvWrap::LoadInitDriver(HKEY hKeyDeviceParams)
  258. {
  259. HRESULT hr = E_UNEXPECTED;
  260. IUnknown *pThisUnk = NULL;
  261. BOOL bOpenedKey = FALSE;
  262. if (!m_pDeviceInfo) {
  263. DBG_WRN(("CDrvWrap::LoadInitDriver, can't load driver with no Device Information"));
  264. return hr;
  265. }
  266. if (!m_pDeviceInfo->bValid) {
  267. DBG_WRN(("CDrvWrap::LoadInitDriver, called with invalid Device Information"));
  268. return hr;
  269. }
  270. //
  271. // Create a new IStiDeviceControl object. This needs to be handed down to the
  272. // driver during initialization. If we can't create it, then bail, since we
  273. // wont be able to initialize the driver properly.
  274. //
  275. hr = CreateDeviceControl();
  276. if (FAILED(hr)) {
  277. DBG_WRN(("CDrvWrap::LoadInitDriver, could not create IStiDeviceControl object. Aborting driver loading"));
  278. return hr;
  279. }
  280. //
  281. // If the hKeyDeviceParams is NULL, see if it is a real WIA device. If not, then
  282. // it is supposed to be NULL, else see if we can get it from our DevMan, using
  283. // this device's DevInfoData.
  284. //
  285. if ((hKeyDeviceParams == NULL) && (m_pDeviceInfo->dwInternalType & INTERNAL_DEV_TYPE_REAL)) {
  286. //
  287. // Check whether device is interface or devnode type device. Grab the
  288. // HKey from the appropriate place
  289. //
  290. hKeyDeviceParams = g_pDevMan->GetDeviceHKey(m_pDeviceInfo->wszDeviceInternalName, NULL);
  291. bOpenedKey = TRUE;
  292. }
  293. //
  294. // We always create the USD object as aggregated, so first we get our IUnknown
  295. // pointer to pass it it during CoCreate.
  296. //
  297. hr = QueryInterface(IID_IUnknown, (void**) &pThisUnk);
  298. if (SUCCEEDED(hr)) {
  299. //
  300. // Call our own version of CoCreate. This is to facilitate manual loading/unloading
  301. // of drivers.
  302. //
  303. hr = MyCoCreateInstanceW(m_pDeviceInfo->wszUSDClassId,
  304. pThisUnk,
  305. IID_IUnknown,
  306. (PPV) &m_pUsdIUnknown,
  307. &m_hDriverDLL);
  308. if (SUCCEEDED(hr)) {
  309. //
  310. // QI for the IStiUSD interface. Notice that we can call our own
  311. // QueryInterface since it delegates down to the driver via m_pUsdIUnknown.
  312. //
  313. hr = m_pUsdIUnknown->QueryInterface(IID_IStiUSD, (void**) &m_pIStiUSD);
  314. if (SUCCEEDED(hr)) {
  315. //
  316. // If this is a WIA device, QI for IWiaMiniDrv
  317. //
  318. if (IsWiaDevice()) {
  319. hr = m_pUsdIUnknown->QueryInterface(IID_IWiaMiniDrv, (void**) &m_pIWiaMiniDrv);
  320. if (FAILED(hr)) {
  321. DBG_WRN(("CDrvWrap::LoadInitDriver, WIA driver did not return IWiaMiniDrv interface for device (%ws)", getDeviceId()));
  322. //
  323. // Change hr here to indicate success. Even if WIA portoin of driver
  324. // doesn't work, the STI portion does so far. Any WIA calls down to this
  325. // driver will result in a E_NOINTERFACE error returned by the wrapper.
  326. //
  327. hr = S_OK;
  328. }
  329. }
  330. //
  331. // We now have the Sti USD, so let's initialize it
  332. //
  333. hr = STI_Initialize(m_pIStiDeviceControl,
  334. STI_VERSION_REAL,
  335. hKeyDeviceParams);
  336. if (SUCCEEDED(hr)) {
  337. //
  338. // Now get capabilities of the USD and verify version
  339. //
  340. STI_USD_CAPS DeviceCapabilities;
  341. hr = STI_GetCapabilities(&DeviceCapabilities);
  342. if (SUCCEEDED(hr)) {
  343. if (STI_VERSION_MIN_ALLOWED <= DeviceCapabilities.dwVersion) {
  344. //
  345. // Everything's fine, we've loaded the USD. Do any post
  346. // initialization steps e.g. for MSC devices, make sure
  347. // we tell the driver what drive/mount point is should
  348. // be attached to.
  349. //
  350. } else {
  351. //
  352. // Driver version is too old, driver will probably not work, so unload it.
  353. //
  354. DBG_WRN(("CDrvWrap::LoadInitDriver, driver version is incompatible (too old)"));
  355. hr = STIERR_OLD_VERSION;
  356. }
  357. } else {
  358. DBG_WRN(("CDrvWrap::LoadInitDriver, STI_GetCapabilities failed"));
  359. }
  360. } else {
  361. DBG_WRN(("CDrvWrap::LoadInitDriver, STI_Initialize failed"));
  362. }
  363. } else {
  364. DBG_WRN(("CDrvWrap::LoadInitDriver, QI to driver failed to return IStiUSD"));
  365. }
  366. } else {
  367. DBG_WRN(("CDrvWrap::LoadInitDriver, failed to CoCreate driver, hr = 0x%08X", hr));
  368. }
  369. //
  370. // If anything failed, call UnloadDriver to clean up.
  371. //
  372. if (FAILED(hr)) {
  373. DBG_WRN(("CDrvWrap::LoadInitDriver, Aborting driver loading"));
  374. pThisUnk->Release();
  375. UnLoadDriver();
  376. }
  377. } else {
  378. DBG_ERR(("CDrvWrap::LoadInitDriver, could not get this IUnknown to hand to driver for aggregation"));
  379. }
  380. //
  381. // If we had to open the key, make sure we close it. We don't want to close the key
  382. // if it was handed to us.
  383. //
  384. if(hKeyDeviceParams && bOpenedKey) RegCloseKey(hKeyDeviceParams);
  385. return hr;
  386. }
  387. /**************************************************************************\
  388. * CDrvWrap::UnLoadDriver
  389. *
  390. * This method will unload the driver. NOTE assumption: This method
  391. * assumes all WIA item references have already been released when this
  392. * is called. The reason is that drvUnInitializeWia needs to be called for
  393. * each WIA Item tree.
  394. * TBD:
  395. * One possible way to get around this is: Keep a list of WIA items
  396. * attached to this device. Then, if we get here, call drvUnitializeWia,
  397. * passing the root of each item tree. Another, much better way: store
  398. * the driver item tree in the wrapper. Then destroy the tree either when
  399. * asked, or when unloading the driver.
  400. *
  401. * Arguments:
  402. *
  403. * None.
  404. *
  405. * Return Value:
  406. *
  407. * Status
  408. *
  409. * History:
  410. *
  411. * 11/06/2000 Original Version
  412. *
  413. \**************************************************************************/
  414. HRESULT CDrvWrap::UnLoadDriver()
  415. {
  416. HRESULT hr = E_UNEXPECTED;
  417. //
  418. // Release all driver interfaces we're holding
  419. //
  420. if (m_pIWiaMiniDrv) {
  421. m_pIWiaMiniDrv->Release();
  422. m_pIWiaMiniDrv = NULL;
  423. }
  424. if (m_pIStiUSD) {
  425. m_pIStiUSD->Release();
  426. m_pIStiUSD = NULL;
  427. }
  428. if (m_pUsdIUnknown) {
  429. m_pUsdIUnknown->Release();
  430. m_pUsdIUnknown = NULL;
  431. }
  432. //
  433. // Release the device control object
  434. //
  435. if (m_pIStiDeviceControl) {
  436. m_pIStiDeviceControl->Release();
  437. m_pIStiDeviceControl = NULL;
  438. }
  439. //
  440. // Unload the driver DLL. We load/unload the DLL manually to ensure the driver
  441. // DLL is released when requested e.g. when the user wants to update the driver.
  442. //
  443. if (m_hDriverDLL) {
  444. FreeLibrary(m_hDriverDLL);
  445. m_hDriverDLL = NULL;
  446. }
  447. m_lWiaTreeCount = 0;
  448. m_bPreparedForUse = FALSE;
  449. m_bUnload = FALSE;
  450. //
  451. // Notice that we don't clear m_pDeviceInfo. This information is needed if we
  452. // decide to reload the driver.
  453. //
  454. return hr;
  455. }
  456. /**************************************************************************\
  457. * CDrvWrap::IsValid
  458. *
  459. * This object is considered valid if there is nothing preventing it from
  460. * loading the driver.
  461. *
  462. * Arguments:
  463. *
  464. * None.
  465. *
  466. * Return Value:
  467. *
  468. * Status
  469. *
  470. * History:
  471. *
  472. * 11/06/2000 Original Version
  473. *
  474. \**************************************************************************/
  475. BOOL CDrvWrap::IsValid()
  476. {
  477. //
  478. // This object is considered valid if there is nothing preventing
  479. // it from loading the driver.
  480. // We should be able to load the driver if:
  481. // - We have a non-NULL DeviceInfo struct
  482. // - The DeviceInfo struct contains valid data
  483. // - The device is marked as active
  484. //
  485. if (m_pDeviceInfo) {
  486. if (m_pDeviceInfo->bValid && (m_pDeviceInfo->dwDeviceState & DEV_STATE_ACTIVE)) {
  487. return TRUE;
  488. }
  489. }
  490. return FALSE;
  491. }
  492. /**************************************************************************\
  493. * CDrvWrap::IsDriverLoaded
  494. *
  495. * Checks whether driver is loaded
  496. *
  497. * Arguments:
  498. *
  499. * None.
  500. *
  501. * Return Value:
  502. *
  503. * True - driver is loaded
  504. * False - driver is not loaded
  505. *
  506. * History:
  507. *
  508. * 11/06/2000 Original Version
  509. *
  510. \**************************************************************************/
  511. BOOL CDrvWrap::IsDriverLoaded()
  512. {
  513. HRESULT hr = E_UNEXPECTED;
  514. //
  515. // We know driver is loaded if we have a valid interface pointer to it.
  516. //
  517. if (m_pUsdIUnknown) {
  518. return TRUE;
  519. }
  520. return FALSE;
  521. }
  522. /**************************************************************************\
  523. * CDrvWrap::IsWiaDevice
  524. *
  525. * This method looks at the capabilities to decide whether a driver is
  526. * WIA capable or not.
  527. *
  528. * Arguments:
  529. *
  530. * None.
  531. *
  532. * Return Value:
  533. *
  534. * TRUE - Is a WIA device
  535. * FALSE - Not a WIA device
  536. *
  537. * History:
  538. *
  539. * 11/06/2000 Original Version
  540. *
  541. \**************************************************************************/
  542. BOOL CDrvWrap::IsWiaDevice()
  543. {
  544. if (m_pDeviceInfo) {
  545. //
  546. // Drivers report that they're WIA capable in their STI capabilties
  547. // entry.
  548. //
  549. return (m_pDeviceInfo->dwInternalType & INTERNAL_DEV_TYPE_WIA);
  550. }
  551. //
  552. // If we don't know for sure it's a WIA device, then assume it isn't
  553. //
  554. return FALSE;
  555. }
  556. /**************************************************************************\
  557. * CDrvWrap::IsWiaDriverLoaded
  558. *
  559. * This method looks at the IWIaMiniDrv interface pointer from the driver
  560. * and returns whether it is valid or not.
  561. *
  562. * Arguments:
  563. *
  564. * None.
  565. *
  566. * Return Value:
  567. *
  568. * TRUE - WIA portion of driver is loaded
  569. * FALSE - WIA portion of driver is not loaded
  570. *
  571. * History:
  572. *
  573. * 12/15/2000 Original Version
  574. *
  575. \**************************************************************************/
  576. BOOL CDrvWrap::IsWiaDriverLoaded()
  577. {
  578. if (m_pIWiaMiniDrv) {
  579. //
  580. // If this interface is non-NULL, it means we successfully QI'd
  581. // for it during initialization. Therefore the driver is loaded
  582. // and is WIA capable.
  583. //
  584. return TRUE;
  585. }
  586. return FALSE;
  587. }
  588. /**************************************************************************\
  589. * CDrvWrap::IsPlugged
  590. *
  591. * Checks the DEVICE_INFO to see whether the device has been marked as
  592. * active. Devies on a PnP bus like USB are inactive if not plugged in.
  593. *
  594. * Arguments:
  595. *
  596. * None.
  597. *
  598. * Return Value:
  599. *
  600. * TRUE - Device is active, and is considered plugged
  601. * FALSE - Device is inactive, and is not considered to be plugged in.
  602. *
  603. * History:
  604. *
  605. * 11/06/2000 Original Version
  606. *
  607. \**************************************************************************/
  608. BOOL CDrvWrap::IsPlugged()
  609. {
  610. if (m_pDeviceInfo) {
  611. //
  612. // Check the device state
  613. //
  614. return (m_pDeviceInfo->dwDeviceState & DEV_STATE_ACTIVE);
  615. }
  616. //
  617. // If we don't know for sure it's plugged in, then assume it isn't
  618. //
  619. return FALSE;
  620. }
  621. /**************************************************************************\
  622. * CDrvWrap::IsVolumeDevice
  623. *
  624. * Checks the DEVICE_INFO to see whether the device is marked as a volume
  625. * device.
  626. *
  627. * Arguments:
  628. *
  629. * None.
  630. *
  631. * Return Value:
  632. *
  633. * TRUE - Device is a volume device
  634. * FALSE - Device is not a volume device
  635. *
  636. * History:
  637. *
  638. * 12/13/2000 Original Version
  639. *
  640. \**************************************************************************/
  641. BOOL CDrvWrap::IsVolumeDevice()
  642. {
  643. if (m_pDeviceInfo) {
  644. //
  645. // Check the device internal type
  646. //
  647. return (m_pDeviceInfo->dwInternalType & INTERNAL_DEV_TYPE_VOL);
  648. }
  649. //
  650. // If we don't know for sure it's a volume device, then assume it isn't
  651. //
  652. return FALSE;
  653. }
  654. /**************************************************************************\
  655. * CDrvWrap::PrepForUse
  656. *
  657. * This method is generally called just before making a call down to the
  658. * driver. It checks to see whether the driver is loaded, and if it isn't,
  659. * will attempt to load it.
  660. *
  661. * Arguments:
  662. *
  663. * bForWiaCall - Indicates whether this is being called because a WIA
  664. * call is about to be made. This will check that the
  665. * IWiaMiniDrv interface is valid.
  666. * pRootItem - not used
  667. *
  668. * Return Value:
  669. *
  670. * TRUE - Device is ready to be used
  671. * FALSE - Device cannot be used (driver could not be loaded/initialized)
  672. *
  673. * History:
  674. *
  675. * 11/06/2000 Original Version
  676. *
  677. \**************************************************************************/
  678. BOOL CDrvWrap::PrepForUse(BOOL bForWiaCall, IWiaItem *pRootItem)
  679. {
  680. HRESULT hr = S_OK;
  681. if (!m_bPreparedForUse || (bForWiaCall && !m_pIWiaMiniDrv)) {
  682. //
  683. // Only attempt to load if the device is marked as ACTIVE
  684. //
  685. if (m_pDeviceInfo->dwDeviceState & DEV_STATE_ACTIVE) {
  686. if (!IsDriverLoaded()) {
  687. hr = LoadInitDriver();
  688. }
  689. if (SUCCEEDED(hr)) {
  690. if (m_pDeviceInfo) {
  691. if (bForWiaCall) {
  692. //
  693. // For WIA devices, check that we have a valid IWiaMiniDrv interface
  694. //
  695. if (IsWiaDevice()) {
  696. if (!m_pIWiaMiniDrv) {
  697. //
  698. // Attempt to Q.I. for IWiaMiniDrv again.
  699. //
  700. hr = m_pUsdIUnknown->QueryInterface(IID_IWiaMiniDrv,
  701. (VOID**) &m_pIWiaMiniDrv);
  702. if (FAILED(hr) || !m_pIWiaMiniDrv) {
  703. DBG_WRN(("CDrvWrap::PrepForUse, attempting to use WIA driver which doesn't have IWiaMiniDrv interface"));
  704. hr = E_NOINTERFACE;
  705. }
  706. }
  707. }
  708. }
  709. } else {
  710. DBG_WRN(("CDrvWrap::PrepForUse, attempting to use driver with NULL DeviceInfo"));
  711. hr = E_UNEXPECTED;
  712. }
  713. if (SUCCEEDED(hr)) {
  714. m_bPreparedForUse = TRUE;
  715. }
  716. } else {
  717. DBG_ERR(("CDrvWrap::PrepForUse, LoadInitDriver() failed (%x)", hr));
  718. }
  719. }
  720. }
  721. if (!m_bPreparedForUse) {
  722. DBG_TRC(("CDrvWrap::PrepForUse, Driver could NOT be loaded!"));
  723. }
  724. return m_bPreparedForUse;
  725. }
  726. /*****************************************************************************/
  727. //
  728. // Accessor methods
  729. //
  730. WCHAR* CDrvWrap::getPnPId()
  731. {
  732. if (m_pDeviceInfo) {
  733. //TBD:
  734. //return m_pDeviceInfo->wszPnPId;
  735. }
  736. return NULL;
  737. }
  738. WCHAR* CDrvWrap::getDeviceId()
  739. {
  740. if (m_pDeviceInfo) {
  741. return m_pDeviceInfo->wszDeviceInternalName;
  742. }
  743. return NULL;
  744. }
  745. DWORD CDrvWrap::getLockHoldingTime()
  746. {
  747. if (m_pDeviceInfo) {
  748. return m_pDeviceInfo->dwLockHoldingTime;
  749. }
  750. return 0;
  751. }
  752. DWORD CDrvWrap::getGenericCaps()
  753. {
  754. if (m_pDeviceInfo) {
  755. return m_pDeviceInfo->DeviceCapabilities.dwGenericCaps;
  756. }
  757. return 0;
  758. }
  759. DWORD CDrvWrap::getPollTimeout()
  760. {
  761. if (m_pDeviceInfo) {
  762. return m_pDeviceInfo->dwPollTimeout;
  763. }
  764. return 0;
  765. }
  766. DWORD CDrvWrap::getDisableNotificationsValue()
  767. {
  768. if (m_pDeviceInfo) {
  769. return m_pDeviceInfo->dwDisableNotifications;
  770. }
  771. return 0;
  772. }
  773. DWORD CDrvWrap::getHWConfig()
  774. {
  775. if (m_pDeviceInfo) {
  776. return m_pDeviceInfo->dwHardwareConfiguration;
  777. }
  778. return 0;
  779. }
  780. DWORD CDrvWrap::getDeviceState()
  781. {
  782. if (m_pDeviceInfo) {
  783. return m_pDeviceInfo->dwDeviceState;
  784. }
  785. return 0;
  786. }
  787. HRESULT CDrvWrap::setDeviceState(
  788. DWORD dwNewDevState)
  789. {
  790. if (m_pDeviceInfo) {
  791. m_pDeviceInfo->dwDeviceState = dwNewDevState;
  792. return S_OK;
  793. }
  794. DBG_WRN(("CDrvWrap::setDeviceState, attempting to set device state when DeviceInfo is NULL"));
  795. return E_UNEXPECTED;
  796. }
  797. DEVICE_INFO* CDrvWrap::getDevInfo()
  798. {
  799. return m_pDeviceInfo;
  800. }
  801. HRESULT CDrvWrap::setDevInfo(DEVICE_INFO *pInfo)
  802. {
  803. HRESULT hr = E_UNEXPECTED;
  804. if (pInfo) {
  805. //
  806. // Caller allocates pInfo. We release it when we're done.
  807. // DeviceInfo must be set before driver can be loaded.
  808. //
  809. m_pDeviceInfo = pInfo;
  810. } else {
  811. DBG_ERR(("CDrvWrap::setDevInfo, attempting to set DeviceInfo to invalid value (NULL)"));
  812. }
  813. return hr;
  814. }
  815. ULONG CDrvWrap::getInternalType()
  816. {
  817. if (m_pDeviceInfo) {
  818. return m_pDeviceInfo->dwInternalType;
  819. }
  820. return 0;
  821. }
  822. VOID CDrvWrap::setJITLoading(BOOL bJITLoading)
  823. {
  824. m_bJITLoading = bJITLoading;
  825. }
  826. BOOL CDrvWrap::getJITLoading()
  827. {
  828. return m_bJITLoading;
  829. }
  830. LONG CDrvWrap::getWiaClientCount()
  831. {
  832. return m_lWiaTreeCount;
  833. }
  834. BOOL CDrvWrap::wasConnectEventThrown()
  835. {
  836. if (m_pDeviceInfo) {
  837. return (m_pDeviceInfo->dwDeviceState & DEV_STATE_CON_EVENT_WAS_THROWN);
  838. }
  839. return FALSE;
  840. }
  841. VOID CDrvWrap::setConnectEventState(
  842. BOOL bEventState)
  843. {
  844. if (m_pDeviceInfo) {
  845. if (bEventState) {
  846. //
  847. // Set the bit to indicate that connect event was thrown
  848. //
  849. m_pDeviceInfo->dwDeviceState = (m_pDeviceInfo->dwDeviceState | DEV_STATE_CON_EVENT_WAS_THROWN);
  850. } else {
  851. //
  852. // Clear the bit that indicated the connect event was thrown
  853. //
  854. m_pDeviceInfo->dwDeviceState = (m_pDeviceInfo->dwDeviceState & (~DEV_STATE_CON_EVENT_WAS_THROWN));
  855. }
  856. }
  857. }
  858. //
  859. // End of accessor methods
  860. //
  861. /*****************************************************************************/
  862. /*****************************************************************************/
  863. //
  864. // Wrapper methods for IStiUSD
  865. //
  866. HRESULT CDrvWrap::STI_Initialize(
  867. IStiDeviceControl *pHelDcb,
  868. DWORD dwStiVersion,
  869. HKEY hParametersKey)
  870. {
  871. HRESULT hr = WIA_ERROR_OFFLINE;
  872. if (PrepForUse(FALSE)) {
  873. //
  874. // Initialize USD object
  875. //
  876. __try {
  877. hr = m_pIStiUSD->Initialize(pHelDcb,
  878. dwStiVersion,
  879. hParametersKey);
  880. }
  881. __except(EXCEPTION_EXECUTE_HANDLER ) {
  882. DBG_WRN(("CDrvWrap::STI_Initialize, exception in driver calling IStiUSD::Initialize"));
  883. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  884. }
  885. } else {
  886. DBG_WRN(("CDrvWrap::STI_Initialize, attempting to call IStiUSD::Initialize when driver is not loaded"));
  887. }
  888. return hr;
  889. }
  890. HRESULT CDrvWrap::STI_GetCapabilities(STI_USD_CAPS *pDevCaps)
  891. {
  892. HRESULT hr = WIA_ERROR_OFFLINE;
  893. if (PrepForUse(FALSE)) {
  894. //
  895. // Get STI capabilities from USD object
  896. //
  897. __try {
  898. hr = m_pIStiUSD->GetCapabilities(pDevCaps);
  899. }
  900. __except(EXCEPTION_EXECUTE_HANDLER ) {
  901. DBG_WRN(("CDrvWrap::STI_GetCapabilities, exception in driver calling IStiUSD::GetCapabilities"));
  902. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  903. }
  904. } else {
  905. DBG_WRN(("CDrvWrap::STI_GetCapabilities, attempting to call IStiUSD::GetCapabilities when driver is not loaded"));
  906. }
  907. return hr;
  908. }
  909. HRESULT CDrvWrap::STI_GetStatus(
  910. STI_DEVICE_STATUS *pDevStatus)
  911. {
  912. HRESULT hr = WIA_ERROR_OFFLINE;
  913. if (PrepForUse(FALSE)) {
  914. //
  915. // Get status from USD object
  916. //
  917. __try {
  918. hr = m_pIStiUSD->GetStatus(pDevStatus);
  919. }
  920. __except(EXCEPTION_EXECUTE_HANDLER ) {
  921. DBG_WRN(("CDrvWrap::STI_GetStatus, exception in driver calling IStiUSD::GetStatus"));
  922. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  923. }
  924. } else {
  925. DBG_WRN(("CDrvWrap::STI_GetStatus, attempting to call IStiUSD::GetStatus when driver is not loaded"));
  926. }
  927. return hr;
  928. }
  929. HRESULT CDrvWrap::STI_GetNotificationData(
  930. STINOTIFY *lpNotify)
  931. {
  932. HRESULT hr = WIA_ERROR_OFFLINE;
  933. if (PrepForUse(FALSE)) {
  934. //
  935. // Get event data from USD object
  936. //
  937. __try {
  938. hr = m_pIStiUSD->GetNotificationData(lpNotify);
  939. }
  940. __except(EXCEPTION_EXECUTE_HANDLER ) {
  941. DBG_WRN(("CDrvWrap::STI_GetNotificationData, exception in driver calling IStiUSD::GetNotificationData"));
  942. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  943. }
  944. } else {
  945. DBG_WRN(("CDrvWrap::STI_GetNotificationData, attempting to call IStiUSD::GetNotificationData when driver is not loaded"));
  946. }
  947. return hr;
  948. }
  949. HRESULT CDrvWrap::STI_SetNotificationHandle(
  950. HANDLE hEvent)
  951. {
  952. HRESULT hr = WIA_ERROR_OFFLINE;
  953. if (PrepForUse(FALSE)) {
  954. //
  955. // Set notification handle for USD object
  956. //
  957. __try {
  958. hr = m_pIStiUSD->SetNotificationHandle(hEvent);
  959. }
  960. __except(EXCEPTION_EXECUTE_HANDLER ) {
  961. DBG_WRN(("CDrvWrap::STI_SetNotificationHandle, exception in driver calling IStiUSD::SetNotificationHandle"));
  962. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  963. }
  964. } else {
  965. DBG_WRN(("CDrvWrap::STI_SetNotificationHandle, attempting to call IStiUSD::SetNotificationHandle when driver is not loaded"));
  966. }
  967. return hr;
  968. }
  969. HRESULT CDrvWrap::STI_DeviceReset()
  970. {
  971. HRESULT hr = WIA_ERROR_OFFLINE;
  972. if (PrepForUse(FALSE)) {
  973. //
  974. // Get status from USD object
  975. //
  976. __try {
  977. hr = m_pIStiUSD->DeviceReset();
  978. if (FAILED(hr)) {
  979. DBG_ERR(("CDrvWrap::STI_DeviceReset, driver returned failure with hr = 0x%08X", hr));
  980. }
  981. }
  982. __except(EXCEPTION_EXECUTE_HANDLER) {
  983. DBG_ERR(("CDrvWrap::STI_DeviceReset, exception in driver calling IStiUSD::DeviceReset"));
  984. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  985. }
  986. } else {
  987. DBG_WRN(("CDrvWrap::STI_DeviceReset, attempting to call IStiUSD::DeviceReset when driver is not loaded"));
  988. }
  989. return hr;
  990. }
  991. HRESULT CDrvWrap::STI_Diagnostic(
  992. STI_DIAG *pDiag)
  993. {
  994. HRESULT hr = WIA_ERROR_OFFLINE;
  995. if (PrepForUse(FALSE)) {
  996. __try {
  997. hr = m_pIStiUSD->Diagnostic(pDiag);
  998. if (FAILED(hr)) {
  999. DBG_ERR(("CDrvWrap::STI_Diagnostic, driver returned failure with hr = 0x%08X", hr));
  1000. }
  1001. }
  1002. __except(EXCEPTION_EXECUTE_HANDLER) {
  1003. DBG_ERR(("CDrvWrap::STI_Diagnostic, exception in Diagnostic: 0x%X", GetExceptionCode()));
  1004. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  1005. }
  1006. } else {
  1007. DBG_WRN(("CDrvWrap::STI_Diagnostic, attempting to call IStiUSD::Diagnostic when driver is not loaded"));
  1008. }
  1009. return hr;
  1010. }
  1011. HRESULT CDrvWrap::STI_LockDevice()
  1012. {
  1013. HRESULT hr = WIA_ERROR_OFFLINE;
  1014. if (PrepForUse(FALSE)) {
  1015. __try {
  1016. hr = m_pIStiUSD->LockDevice();
  1017. if (FAILED(hr)) {
  1018. DBG_ERR(("CDrvWrap::STI_LockDevice, driver returned failure with hr = 0x%08X", hr));
  1019. }
  1020. }
  1021. __except(EXCEPTION_EXECUTE_HANDLER) {
  1022. DBG_ERR(("CDrvWrap::STI_LockDevice, exception in LockDevice: 0x%X", GetExceptionCode()));
  1023. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  1024. }
  1025. } else {
  1026. DBG_WRN(("CDrvWrap::STI_LockDevice, attempting to call IStiUSD::LockDevice when driver is not loaded"));
  1027. }
  1028. return hr;
  1029. }
  1030. HRESULT CDrvWrap::STI_UnLockDevice()
  1031. {
  1032. HRESULT hr = WIA_ERROR_OFFLINE;
  1033. if (PrepForUse(FALSE)) {
  1034. __try {
  1035. hr = m_pIStiUSD->UnLockDevice();
  1036. if (FAILED(hr)) {
  1037. DBG_ERR(("CDrvWrap::STI_UnLockDevice, driver returned failure with hr = 0x%08X", hr));
  1038. }
  1039. }
  1040. __except(EXCEPTION_EXECUTE_HANDLER) {
  1041. DBG_ERR(("CDrvWrap::STI_UnLockDevice, exception in UnLockDevice: 0x%X", GetExceptionCode()));
  1042. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  1043. }
  1044. } else {
  1045. DBG_WRN(("CDrvWrap::STI_UnlockDevice, attempting to call IStiUSD::UnLockDevice when driver is not loaded"));
  1046. }
  1047. return hr;
  1048. }
  1049. HRESULT CDrvWrap::STI_Escape(
  1050. STI_RAW_CONTROL_CODE EscapeFunction,
  1051. LPVOID lpInData,
  1052. DWORD cbInDataSize,
  1053. LPVOID pOutData,
  1054. DWORD dwOutDataSize,
  1055. LPDWORD pdwActualData)
  1056. {
  1057. HRESULT hr = WIA_ERROR_OFFLINE;
  1058. if (PrepForUse(FALSE)) {
  1059. __try {
  1060. hr = m_pIStiUSD->Escape(EscapeFunction,
  1061. lpInData,
  1062. cbInDataSize,
  1063. pOutData,
  1064. dwOutDataSize,
  1065. pdwActualData);
  1066. if (FAILED(hr)) {
  1067. DBG_ERR(("CDrvWrap::STI_Escape, driver returned failure with hr = 0x%08X", hr));
  1068. }
  1069. }
  1070. __except(EXCEPTION_EXECUTE_HANDLER) {
  1071. DBG_ERR(("CDrvWrap::STI_Escape, exception in Escape: 0x%X", GetExceptionCode()));
  1072. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  1073. }
  1074. } else {
  1075. DBG_WRN(("CDrvWrap::STI_Escape, attempting to call IStiUSD::Escape when driver is not loaded"));
  1076. }
  1077. return hr;
  1078. }
  1079. //
  1080. // End of IStiUSD wrapper methods
  1081. //
  1082. /*****************************************************************************/
  1083. /*****************************************************************************/
  1084. //
  1085. // Wrapper methods for IWiaMiniDrv. All mini-driver wrapper methods call PrepForUse(...) to make sure
  1086. // the driver is loaded before using.
  1087. //
  1088. HRESULT CDrvWrap::WIA_drvInitializeWia(
  1089. BYTE *pWiasContext,
  1090. LONG lFlags,
  1091. BSTR bstrDeviceID,
  1092. BSTR bstrRootFullItemName,
  1093. IUnknown *pStiDevice,
  1094. IUnknown *pIUnknownOuter,
  1095. IWiaDrvItem **ppIDrvItemRoot,
  1096. IUnknown **ppIUnknownInner,
  1097. LONG *plDevErrVal)
  1098. {
  1099. HRESULT hr = WIA_ERROR_OFFLINE;
  1100. if (PrepForUse(TRUE)) {
  1101. __try {
  1102. hr = m_pIWiaMiniDrv->drvInitializeWia(pWiasContext,
  1103. lFlags,
  1104. bstrDeviceID,
  1105. bstrRootFullItemName,
  1106. pStiDevice,
  1107. pIUnknownOuter,
  1108. ppIDrvItemRoot,
  1109. ppIUnknownInner,
  1110. plDevErrVal);
  1111. if(FAILED(hr)) {
  1112. DBG_ERR(("CDrvWrap::WIA_drvInitializeWia, Error calling driver: drvInitializeWia failed with hr = 0x%08X", hr));
  1113. ReportMiniDriverError(*plDevErrVal, NULL);
  1114. }
  1115. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1116. DBG_ERR(("CDrvWrap::WIA_drvInitializeWia, exception in drvInitializeWia: 0x%X", GetExceptionCode()));
  1117. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  1118. }
  1119. } else {
  1120. DBG_WRN(("CDrvWrap::WIA_drvInitializeWia, attempting to call IWiaMiniDrv::drvInitializeWia when driver is not loaded"));
  1121. }
  1122. if (SUCCEEDED(hr)) {
  1123. // TBD: Take a sync primitive?
  1124. InterlockedIncrement(&m_lWiaTreeCount);
  1125. }
  1126. return hr;
  1127. }
  1128. HRESULT CDrvWrap::WIA_drvGetDeviceErrorStr(
  1129. LONG lFlags,
  1130. LONG lDevErr,
  1131. LPOLESTR *ppszDevErrStr,
  1132. LONG *plDevErrVal)
  1133. {
  1134. HRESULT hr = WIA_ERROR_OFFLINE;
  1135. if (PrepForUse(TRUE)) {
  1136. __try {
  1137. hr = m_pIWiaMiniDrv->drvGetDeviceErrorStr(lFlags,
  1138. lDevErr,
  1139. ppszDevErrStr,
  1140. plDevErrVal);
  1141. if (FAILED(hr)) {
  1142. DBG_ERR(("CDrvWrap::WIA_drvGetDeviceErrorStr, call to driver's drvGetDeviceErrorStr failed (0x%08X)", hr));
  1143. }
  1144. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1145. DBG_ERR(("CDrvWrap::WIA_drvGetDeviceErrorStr, attempting to call IWiaMiniDrv::drvGetDeviceErrorStr when driver is not loaded"));
  1146. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  1147. }
  1148. }
  1149. return hr;
  1150. }
  1151. HRESULT CDrvWrap::WIA_drvDeviceCommand(
  1152. BYTE *pWiasContext,
  1153. LONG lFlags,
  1154. const GUID *plCommand,
  1155. IWiaDrvItem **ppWiaDrvItem,
  1156. LONG *plDevErrVal)
  1157. {
  1158. HRESULT hr = WIA_ERROR_OFFLINE;
  1159. if (PrepForUse(TRUE)) {
  1160. __try {
  1161. hr = m_pIWiaMiniDrv->drvDeviceCommand(pWiasContext, lFlags, plCommand, ppWiaDrvItem, plDevErrVal);
  1162. if(FAILED(hr)) {
  1163. DBG_ERR(("CDrvWrap::WIA_drvDeviceCommand, Error calling driver: drvDeviceCommand failed with hr = 0x%08X", hr));
  1164. ReportMiniDriverError(*plDevErrVal, NULL);
  1165. }
  1166. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1167. DBG_ERR(("CDrvWrap::WIA_drvDeviceCommand, exception in drvDeviceCommand: 0x%X", GetExceptionCode()));
  1168. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  1169. }
  1170. } else {
  1171. DBG_WRN(("CDrvWrap::WIA_drvDeviceCommand, attempting to call IWiaMiniDrv::drvDeviceCommand when driver is not loaded"));
  1172. }
  1173. return hr;
  1174. }
  1175. HRESULT CDrvWrap::WIA_drvAcquireItemData(
  1176. BYTE *pWiasContext,
  1177. LONG lFlags,
  1178. PMINIDRV_TRANSFER_CONTEXT pmdtc,
  1179. LONG *plDevErrVal)
  1180. {
  1181. HRESULT hr = WIA_ERROR_OFFLINE;
  1182. if (PrepForUse(TRUE)) {
  1183. __try {
  1184. hr = m_pIWiaMiniDrv->drvAcquireItemData(pWiasContext, lFlags, pmdtc, plDevErrVal);
  1185. if(FAILED(hr)) {
  1186. DBG_ERR(("CDrvWrap::WIA_drvAcquireItemData, Error calling driver : drvAcquireItemData failed with hr = 0x%08X", hr));
  1187. ReportMiniDriverError(*plDevErrVal, NULL);
  1188. }
  1189. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1190. DBG_ERR(("CDrvWrap::WIA_drvAcquireItemData, exception in drvAcquireItemData: 0x%X", GetExceptionCode()));
  1191. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  1192. }
  1193. } else {
  1194. DBG_WRN(("CDrvWrap::WIA_drvAcquireItemData, attempting to call IWiaMiniDrv::drvAcquireItemData when driver is not loaded"));
  1195. }
  1196. return hr;
  1197. }
  1198. HRESULT CDrvWrap::WIA_drvInitItemProperties(
  1199. BYTE *pWiasContext,
  1200. LONG lFlags,
  1201. LONG *plDevErrVal)
  1202. {
  1203. HRESULT hr = WIA_ERROR_OFFLINE;
  1204. if (PrepForUse(TRUE)) {
  1205. __try {
  1206. hr = m_pIWiaMiniDrv->drvInitItemProperties(pWiasContext,lFlags, plDevErrVal);
  1207. if(FAILED(hr)) {
  1208. DBG_ERR(("CDrvWrap::WIA_drvInitItemProperties, Error calling driver: drvInitItemProperties failed with hr = 0x%08X", hr));
  1209. ReportMiniDriverError(*plDevErrVal, NULL);
  1210. }
  1211. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1212. DBG_ERR(("CDrvWrap::WIA_drvInitItemProperties, exception in drvInitItemProperties: 0x%X", GetExceptionCode()));
  1213. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  1214. }
  1215. } else {
  1216. DBG_WRN(("CDrvWrap::WIA_drvInitItemProperties, attempting to call IWiaMiniDrv::drvInitItemProperties when driver is not loaded"));
  1217. }
  1218. return hr;
  1219. }
  1220. HRESULT CDrvWrap::WIA_drvValidateItemProperties(
  1221. BYTE *pWiasContext,
  1222. LONG lFlags,
  1223. ULONG nPropSpec,
  1224. const PROPSPEC *pPropSpec,
  1225. LONG *plDevErrVal)
  1226. {
  1227. HRESULT hr = WIA_ERROR_OFFLINE;
  1228. if (PrepForUse(TRUE)) {
  1229. __try {
  1230. hr = m_pIWiaMiniDrv->drvValidateItemProperties(pWiasContext,
  1231. lFlags,
  1232. nPropSpec,
  1233. pPropSpec,
  1234. plDevErrVal);
  1235. if(FAILED(hr)) {
  1236. DBG_ERR(("CDrvWrap::WIA_drvValidateItemProperties, Error calling driver: drvValidateItemProperties with hr = 0x%08X (This is normal if the app wrote an invalid value)", hr));
  1237. ReportMiniDriverError(*plDevErrVal, NULL);
  1238. }
  1239. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1240. DBG_ERR(("CDrvWrap::WIA_drvValidateItemProperties, exception in drvValidateItemProperties: 0x%X", GetExceptionCode()));
  1241. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  1242. }
  1243. } else {
  1244. DBG_WRN(("CDrvWrap::WIA_drvValidateItemProperties, attempting to call IWiaMiniDrv::drvValidateItemProperties when driver is not loaded"));
  1245. }
  1246. return hr;
  1247. }
  1248. HRESULT CDrvWrap::WIA_drvWriteItemProperties(
  1249. BYTE *pWiasContext,
  1250. LONG lFlags,
  1251. PMINIDRV_TRANSFER_CONTEXT pmdtc,
  1252. LONG *plDevErrVal)
  1253. {
  1254. HRESULT hr = WIA_ERROR_OFFLINE;
  1255. if (PrepForUse(TRUE)) {
  1256. __try {
  1257. hr = m_pIWiaMiniDrv->drvWriteItemProperties(pWiasContext,
  1258. lFlags,
  1259. pmdtc,
  1260. plDevErrVal);
  1261. if(FAILED(hr)) {
  1262. DBG_ERR(("CDrvWrap::WIA_drvWriteItemProperties, error calling driver: drvWriteItemProperties failed with hr = 0x%08X", hr));
  1263. ReportMiniDriverError(*plDevErrVal, NULL);
  1264. }
  1265. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1266. DBG_ERR(("CDrvWrap::WIA_drvWriteItemProperties, exception in drvWriteItemProperties: 0x%X", GetExceptionCode()));
  1267. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  1268. }
  1269. } else {
  1270. DBG_WRN(("CDrvWrap::WIA_drvWriteItemProperties, attempting to call IWiaMiniDrv::drvWriteItemProperties when driver is not loaded"));
  1271. }
  1272. return hr;
  1273. }
  1274. HRESULT CDrvWrap::WIA_drvReadItemProperties(
  1275. BYTE *pWiasContext,
  1276. LONG lFlags,
  1277. ULONG nPropSpec,
  1278. const PROPSPEC *pPropSpec,
  1279. LONG *plDevErrVal)
  1280. {
  1281. HRESULT hr = WIA_ERROR_OFFLINE;
  1282. if (PrepForUse(TRUE)) {
  1283. __try {
  1284. hr = m_pIWiaMiniDrv->drvReadItemProperties(pWiasContext,
  1285. lFlags,
  1286. nPropSpec,
  1287. pPropSpec,
  1288. plDevErrVal);
  1289. if(FAILED(hr)) {
  1290. DBG_ERR(("CDrvWrap::WIA_drvReadItemProperties, Error calling driver: drvReadItemProperties failed with hr = 0x%08X", hr));
  1291. ReportMiniDriverError(*plDevErrVal, NULL);
  1292. }
  1293. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1294. DBG_ERR(("CDrvWrap::WIA_drvReadItemProperties, exception in drvReadItemProperties: 0x%X", GetExceptionCode()));
  1295. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  1296. }
  1297. } else {
  1298. DBG_WRN(("CDrvWrap::WIA_drvReadItemProperties, attempting to call IWiaMiniDrv::drvReadItemProperties when driver is not loaded"));
  1299. }
  1300. return hr;
  1301. }
  1302. HRESULT CDrvWrap::WIA_drvLockWiaDevice(
  1303. BYTE *pWiasContext,
  1304. LONG lFlags,
  1305. LONG *plDevErrVal)
  1306. {
  1307. HRESULT hr = WIA_ERROR_OFFLINE;
  1308. if (PrepForUse(TRUE)) {
  1309. //
  1310. // We request a lock on the device here. This is to ensure we don't
  1311. // make calls down to the driver, which then turns around and
  1312. // makes a call to us e.g. via the Fake Sti Device.
  1313. // We no longer require driver to use the Fake Sti Device for
  1314. // mutally exclusive locking - this way we do it automatically.
  1315. //
  1316. hr = g_pStiLockMgr->RequestLock(((CWiaItem*) pWiasContext)->m_pActiveDevice, WIA_LOCK_WAIT_TIME);
  1317. if (SUCCEEDED(hr)) {
  1318. __try {
  1319. hr = m_pIWiaMiniDrv->drvLockWiaDevice(pWiasContext, lFlags, plDevErrVal);
  1320. if(FAILED(hr)) {
  1321. DBG_ERR(("CDrvWrap::WIA_drvLockWiaDevice, driver returned failure with hr = 0x%08X", hr));
  1322. ReportMiniDriverError(*plDevErrVal, NULL);
  1323. }
  1324. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1325. DBG_ERR(("CDrvWrap::WIA_drvLockWiaDevice, exception in drvLockWiaDevice: 0x%X", GetExceptionCode()));
  1326. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  1327. }
  1328. } else {
  1329. DBG_WRN(("CDrvWrap::WIA_drvLockWiaDevice, could not get device lock"));
  1330. }
  1331. } else {
  1332. DBG_WRN(("CDrvWrap::WIA_drvLockWiaDevice, attempting to call IWiaMiniDrv::drvLockWiaDevice when driver is not loaded"));
  1333. }
  1334. return hr;
  1335. }
  1336. HRESULT CDrvWrap::WIA_drvUnLockWiaDevice(
  1337. BYTE *pWiasContext,
  1338. LONG lFlags,
  1339. LONG *plDevErrVal)
  1340. {
  1341. HRESULT hr = WIA_ERROR_OFFLINE;
  1342. //
  1343. // Note that we only want to call if the driver is loaded, therefore we don't
  1344. // call PrepForUse. PrepForUse will attempt to load the driver if it wasn't
  1345. // already loaded.
  1346. //
  1347. if (IsDriverLoaded()) {
  1348. //
  1349. // Request to unlock the device for mutally exclusive access.
  1350. // Ignore the return, we must still call the drvUnlockWiaDevice entry
  1351. // point.
  1352. //
  1353. __try {
  1354. hr = m_pIWiaMiniDrv->drvUnLockWiaDevice(pWiasContext, lFlags, plDevErrVal);
  1355. if(FAILED(hr)) {
  1356. DBG_ERR(("CDrvWrap::WIA_drvUnLockWiaDevice, driver returned failure with hr = 0x%08X", hr));
  1357. ReportMiniDriverError(*plDevErrVal, NULL);
  1358. }
  1359. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1360. DBG_ERR(("CDrvWrap::WIA_drvUnLockWiaDevice, exception in drvUnLockWiaDevice: 0x%X", GetExceptionCode()));
  1361. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  1362. }
  1363. hr = g_pStiLockMgr->RequestUnlock(((CWiaItem*) pWiasContext)->m_pActiveDevice);
  1364. if (SUCCEEDED(hr) && m_bUnload) {
  1365. UnLoadDriver();
  1366. }
  1367. } else {
  1368. DBG_WRN(("CDrvWrap::WIA_drvUnLockWiaDevice, attempting to call IWiaMiniDrv::drvUnLockWiaDevice when driver is not loaded"));
  1369. }
  1370. return hr;
  1371. }
  1372. HRESULT CDrvWrap::WIA_drvAnalyzeItem(
  1373. BYTE *pWiasContext,
  1374. LONG lFlags,
  1375. LONG *plDevErrVal)
  1376. {
  1377. HRESULT hr = WIA_ERROR_OFFLINE;
  1378. if (PrepForUse(TRUE)) {
  1379. __try {
  1380. hr = m_pIWiaMiniDrv->drvAnalyzeItem(pWiasContext, lFlags, plDevErrVal);
  1381. if(FAILED(hr)) {
  1382. DBG_ERR(("CDrvWrap::WIA_drvAnalyzeItem, Error calling driver: drvAnalyzeItem failed with hr = 0x%08X", hr));
  1383. ReportMiniDriverError(*plDevErrVal, NULL);
  1384. }
  1385. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1386. DBG_ERR(("CDrvWrap::WIA_drvAnalyzeItem, exception in drvAnalyzeItem: 0x%X", GetExceptionCode()));
  1387. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  1388. }
  1389. } else {
  1390. DBG_WRN(("CDrvWrap::WIA_drvAnalyzeItem, attempting to call IWiaMiniDrv::drvAnalyzeItem when driver is not loaded"));
  1391. }
  1392. return hr;
  1393. }
  1394. HRESULT CDrvWrap::WIA_drvDeleteItem(
  1395. BYTE *pWiasContext,
  1396. LONG lFlags,
  1397. LONG *plDevErrVal)
  1398. {
  1399. HRESULT hr = WIA_ERROR_OFFLINE;
  1400. if (PrepForUse(TRUE)) {
  1401. __try {
  1402. hr = m_pIWiaMiniDrv->drvDeleteItem(pWiasContext, lFlags, plDevErrVal);
  1403. if(FAILED(hr)) {
  1404. DBG_ERR(("CDrvWrap::WIA_drvDeleteItem, Error calling driver: drvDeleteItem failed with hr = 0x%08X", hr));
  1405. ReportMiniDriverError(*plDevErrVal, NULL);
  1406. }
  1407. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1408. DBG_ERR( ("CDrvWrap::WIA_drvDeleteItem, exception in drvDeleteItem: %0xX", GetExceptionCode()));
  1409. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  1410. }
  1411. } else {
  1412. DBG_WRN(("CDrvWrap::WIA_drvDeleteItem, attempting to call IWiaMiniDrv::drvDeleteItem when driver is not loaded"));
  1413. }
  1414. return hr;
  1415. }
  1416. HRESULT CDrvWrap::WIA_drvFreeDrvItemContext(
  1417. LONG lFlags,
  1418. BYTE *pSpecContext,
  1419. LONG *plDevErrVal)
  1420. {
  1421. HRESULT hr = WIA_ERROR_OFFLINE;
  1422. if (PrepForUse(TRUE)) {
  1423. __try {
  1424. hr = m_pIWiaMiniDrv->drvFreeDrvItemContext(lFlags, pSpecContext, plDevErrVal);
  1425. if(FAILED(hr)) {
  1426. DBG_ERR(("CDrvWrap::WIA_drvFreeDrvItemContext, Error calling driver: drvFreeDrvItemContext failed with hr = 0x%08X", hr));
  1427. ReportMiniDriverError(*plDevErrVal, NULL);
  1428. }
  1429. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1430. DBG_ERR( ("CDrvWrap::WIA_drvFreeDrvItemContext, exception in drvFreeDrvItemContext: %0xX", GetExceptionCode()));
  1431. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  1432. }
  1433. } else {
  1434. DBG_WRN(("CDrvWrap::WIA_drvFreeDrvItemContext, attempting to call IWiaMiniDrv::drvFreeDrvItemContext when driver is not loaded"));
  1435. }
  1436. return hr;
  1437. }
  1438. HRESULT CDrvWrap::WIA_drvGetCapabilities(
  1439. BYTE *pWiasContext,
  1440. LONG ulFlags,
  1441. LONG *pcelt,
  1442. WIA_DEV_CAP_DRV **ppCapabilities,
  1443. LONG *plDevErrVal)
  1444. {
  1445. HRESULT hr = WIA_ERROR_OFFLINE;
  1446. if (PrepForUse(TRUE)) {
  1447. __try {
  1448. hr = m_pIWiaMiniDrv->drvGetCapabilities(pWiasContext, ulFlags, pcelt, ppCapabilities, plDevErrVal);
  1449. if(FAILED(hr)) {
  1450. DBG_ERR(("CDrvWrap::WIA_drvGetCapabilities, driver returned failure with hr = 0x%08X", hr));
  1451. ReportMiniDriverError(*plDevErrVal, NULL);
  1452. }
  1453. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1454. DBG_ERR(("CDrvWrap::WIA_drvGetCapabilities, exception in drvGetCapabilities: 0x%X", GetExceptionCode()));
  1455. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  1456. }
  1457. } else {
  1458. DBG_WRN(("CDrvWrap::WIA_drvGetCapabilities, attempting to call IWiaMiniDrv::drvGetCapabilities when driver is not loaded"));
  1459. }
  1460. return hr;
  1461. }
  1462. HRESULT CDrvWrap::WIA_drvGetWiaFormatInfo(
  1463. BYTE *pWiasContext,
  1464. LONG lFlags,
  1465. LONG *pcelt,
  1466. WIA_FORMAT_INFO **ppwfi,
  1467. LONG *plDevErrVal)
  1468. {
  1469. HRESULT hr = WIA_ERROR_OFFLINE;
  1470. if (PrepForUse(TRUE)) {
  1471. __try {
  1472. hr = m_pIWiaMiniDrv->drvGetWiaFormatInfo(pWiasContext,
  1473. lFlags,
  1474. pcelt,
  1475. ppwfi,
  1476. plDevErrVal);
  1477. if(FAILED(hr)) {
  1478. DBG_ERR(("CDrvWrap::WIA_drvGetWiaFormatInfo, Error calling driver : drvGetWiaFormatInfo failed with hr = 0x%08X", hr));
  1479. ReportMiniDriverError(*plDevErrVal, NULL);
  1480. }
  1481. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1482. DBG_ERR( ("CDrvWrap::WIA_drvGetWiaFormatInfo, exception in drvGetWiaFormatInfo: 0x%X", GetExceptionCode()));
  1483. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  1484. }
  1485. } else {
  1486. DBG_WRN(("CDrvWrap::WIA_drvGetWiaFormatInfo, attempting to call IWiaMiniDrv::drvGetWiaFormatInfo when driver is not loaded"));
  1487. }
  1488. return hr;
  1489. }
  1490. HRESULT CDrvWrap::WIA_drvNotifyPnpEvent(
  1491. const GUID *pEventGUID,
  1492. BSTR bstrDeviceID,
  1493. ULONG ulReserved)
  1494. {
  1495. HRESULT hr = WIA_ERROR_OFFLINE;
  1496. LONG lDevErrVal = 0;
  1497. if (PrepForUse(TRUE)) {
  1498. __try {
  1499. hr = m_pIWiaMiniDrv->drvNotifyPnpEvent(pEventGUID, bstrDeviceID, ulReserved);
  1500. if(FAILED(hr)) {
  1501. DBG_ERR(("CDrvWrap::WIA_drvNotifyPnpEvent, driver returned failure with hr = 0x%08X", hr));
  1502. ReportMiniDriverError(lDevErrVal, NULL);
  1503. }
  1504. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1505. DBG_ERR(("CDrvWrap::WIA_drvNotifyPnpEvent, exception in drvNotifyPnpEvent: 0x%X", GetExceptionCode()));
  1506. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  1507. }
  1508. } else {
  1509. DBG_WRN(("CDrvWrap::WIA_drvNotifyPnpEvent, attempting to call IWiaMiniDrv::drvNotifyPnpEvent when driver is not loaded"));
  1510. }
  1511. return hr;
  1512. }
  1513. HRESULT CDrvWrap::WIA_drvUnInitializeWia(
  1514. BYTE *pWiasContext)
  1515. {
  1516. HRESULT hr = WIA_ERROR_OFFLINE;
  1517. LONG lDevErrVal = 0;
  1518. if (PrepForUse(TRUE)) {
  1519. __try {
  1520. hr = m_pIWiaMiniDrv->drvUnInitializeWia(pWiasContext);
  1521. if(FAILED(hr)) {
  1522. DBG_ERR(("CDrvWrap::WIA_drvUnInitializeWia, Error calling driver: drvUnInitializeWia failed with hr = 0x%08X", hr));
  1523. ReportMiniDriverError(lDevErrVal, NULL);
  1524. }
  1525. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1526. DBG_ERR(("CDrvWrap::WIA_drvUnInitializeWia, exception in drvUnInitializeWia: 0x%X", GetExceptionCode()));
  1527. hr = WIA_ERROR_EXCEPTION_IN_DRIVER;
  1528. }
  1529. } else {
  1530. DBG_WRN(("CDrvWrap::WIA_drvUnInitializeWia, attempting to call IWiaMiniDrv::drvUnInitializeWia when driver is not loaded"));
  1531. }
  1532. if (SUCCEEDED(hr)) {
  1533. // TBD: Take a sync primitive?
  1534. if(InterlockedDecrement(&m_lWiaTreeCount) == 0) {
  1535. // No item trees left.
  1536. // Note that we can't unload now, since the device still needs to
  1537. // be unlocked, therefore simply mark it to be unloaded by
  1538. // WIA_drvUnlockWiaDevice.
  1539. if (m_bJITLoading) {
  1540. m_bUnload = TRUE;
  1541. }
  1542. }
  1543. }
  1544. return hr;
  1545. }
  1546. //
  1547. // End of wrapper methods for IWiaMiniDrv
  1548. //
  1549. /*****************************************************************************/
  1550. //
  1551. // Private methods
  1552. //
  1553. /**************************************************************************\
  1554. * CDrvWrap::CreateDeviceControl
  1555. *
  1556. * Creates a IStiDeviceControl object to hand down to the driver during
  1557. * its initialization.
  1558. *
  1559. * Arguments:
  1560. *
  1561. * None.
  1562. *
  1563. * Return Value:
  1564. *
  1565. * Status
  1566. *
  1567. * History:
  1568. *
  1569. * 11/06/2000 Original Version
  1570. *
  1571. \**************************************************************************/
  1572. HRESULT CDrvWrap::CreateDeviceControl()
  1573. {
  1574. HRESULT hr = E_FAIL;
  1575. if (m_pDeviceInfo) {
  1576. DWORD dwBusType = 0;
  1577. DWORD dwControlTypeType = 0;
  1578. //
  1579. // Bus type is retrieved from dwHardwareConfiguration in the DeviceInformation struct
  1580. // Use this to determine ControlTypeType
  1581. //
  1582. dwBusType = m_pDeviceInfo->dwHardwareConfiguration;
  1583. //
  1584. // Convert STI bit flags for device mode into HEL_ bit mask
  1585. //
  1586. if (dwBusType & (STI_HW_CONFIG_USB | STI_HW_CONFIG_SCSI)) {
  1587. dwControlTypeType = HEL_DEVICE_TYPE_WDM;
  1588. }
  1589. else if (dwBusType & STI_HW_CONFIG_PARALLEL) {
  1590. dwControlTypeType = HEL_DEVICE_TYPE_PARALLEL;
  1591. }
  1592. else if (dwBusType & STI_HW_CONFIG_SERIAL) {
  1593. dwControlTypeType = HEL_DEVICE_TYPE_SERIAL;
  1594. }
  1595. else {
  1596. DBG_WRN(("CDrvWrap::CreateDeviceControl, Cannot determine device control type, resorting to WDM"));
  1597. dwControlTypeType = HEL_DEVICE_TYPE_WDM;
  1598. }
  1599. hr = NewDeviceControl(dwControlTypeType,
  1600. (STI_DEVICE_CREATE_STATUS | STI_DEVICE_CREATE_FOR_MONITOR),
  1601. m_pDeviceInfo->wszPortName,
  1602. 0,
  1603. &m_pIStiDeviceControl);
  1604. if (FAILED(hr)) {
  1605. m_pIStiDeviceControl = NULL;
  1606. DBG_WRN(("CDrvWrap::CreateDeviceControl, failed to create new device control object"));
  1607. }
  1608. } else {
  1609. DBG_WRN(("CDrvWrap::CreateDeviceControl, can't create IStiDeviceControl with NULL device information"));
  1610. }
  1611. return hr;
  1612. }
  1613. /**************************************************************************\
  1614. * CDrvWrap::InternalClear
  1615. *
  1616. * This will unload the driver, if it is loaded, and clear member
  1617. * variables associated with the loaded driver state.
  1618. *
  1619. * Arguments:
  1620. *
  1621. * InternalClear
  1622. *
  1623. * Return Value:
  1624. *
  1625. * Status
  1626. *
  1627. * History:
  1628. *
  1629. * 11/06/2000 Original Version
  1630. *
  1631. \**************************************************************************/
  1632. HRESULT CDrvWrap::InternalClear()
  1633. {
  1634. HRESULT hr = S_OK;
  1635. if (IsDriverLoaded()) {
  1636. hr = UnLoadDriver();
  1637. if (FAILED(hr)) {
  1638. DBG_ERR(("CDrvWrap::InternalClear, Error unloading driver"));
  1639. }
  1640. }
  1641. m_hDriverDLL = NULL;
  1642. m_pUsdIUnknown = NULL;
  1643. m_pIStiUSD = NULL;
  1644. m_pIWiaMiniDrv = NULL;
  1645. m_pIStiDeviceControl = NULL;
  1646. m_bJITLoading = FALSE;
  1647. m_lWiaTreeCount = 0;
  1648. m_bPreparedForUse = FALSE;
  1649. m_bUnload = FALSE;
  1650. return hr;
  1651. }
  1652. /**************************************************************************\
  1653. * CDrvWrap::::ReportMiniDriverError
  1654. *
  1655. * Report a mini driver error. The caller is responsible for
  1656. * locking/unlocking the device. In most cases, the driver is already
  1657. * locked when ReportMiniDriverError is called, so there is no need to lock
  1658. * is again here.
  1659. *
  1660. * Arguments:
  1661. *
  1662. * lDevErr - Error value returned from the mini driver.
  1663. * pszWhat - What the class driver was doing when the error ocured.
  1664. *
  1665. * Return Value:
  1666. *
  1667. * Status
  1668. *
  1669. * History:
  1670. *
  1671. * 10/20/1998 Original Version
  1672. *
  1673. \**************************************************************************/
  1674. HRESULT CDrvWrap::ReportMiniDriverError(
  1675. LONG lDevErr,
  1676. LPOLESTR pszWhat)
  1677. {
  1678. DBG_FN(CDrvWrap::ReportMiniDriverError);
  1679. HRESULT hr = S_OK;
  1680. LONG lFlags = 0;
  1681. LONG lDevErrVal;
  1682. if (lDevErr) {
  1683. LPOLESTR pszErr = NULL;
  1684. WIA_drvGetDeviceErrorStr(lFlags, lDevErr, &pszErr, &lDevErrVal);
  1685. _try {
  1686. if (FAILED(hr)) {
  1687. pszErr = NULL;
  1688. }
  1689. if (pszWhat) {
  1690. DBG_ERR(("Device error during %ws", pszWhat));
  1691. }
  1692. if (pszErr) {
  1693. DBG_ERR((" %ws", pszErr));
  1694. }
  1695. }
  1696. _finally {
  1697. };
  1698. }
  1699. else {
  1700. hr = S_FALSE;
  1701. }
  1702. return hr;
  1703. }