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.

1899 lines
55 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT 2000, MICROSOFT CORP.
  4. *
  5. * TITLE: IWiaMiniDrv.cpp
  6. *
  7. * VERSION: 1.0
  8. *
  9. * DATE: 18 July, 2000
  10. *
  11. * DESCRIPTION:
  12. * Implementation of the WIA sample camera IWiaMiniDrv methods. This file
  13. * contains 3 sections. The first is the WIA minidriver entry points, all
  14. * starting with "drv". The next section is public help methods. The last
  15. * section is private helper methods.
  16. *
  17. *******************************************************************************/
  18. #include "pch.h"
  19. #ifndef INITGUID
  20. #include <initguid.h>
  21. #endif
  22. //
  23. // A few extra format GUIDs
  24. //
  25. DEFINE_GUID(GUID_NULL, 0,0,0,0,0,0,0,0,0,0,0);
  26. DEFINE_GUID(FMT_NOTHING, 0x81a566e7,0x8620,0x4fba,0xbc,0x8e,0xb2,0x7c,0x17,0xad,0x9e,0xfd);
  27. /**************************************************************************\
  28. * CWiaCameraDevice::drvInitializeWia
  29. *
  30. * Initialize the WIA mini driver. This function will be called each time an
  31. * application creates a device. The first time through, the driver item tree
  32. * will be created and other initialization will be done.
  33. *
  34. * Arguments:
  35. *
  36. * pWiasContext - Pointer to the WIA item, unused.
  37. * lFlags - Operation flags, unused.
  38. * bstrDeviceID - Device ID.
  39. * bstrRootFullItemName - Full item name.
  40. * pIPropStg - Device info. properties.
  41. * pStiDevice - STI device interface.
  42. * pIUnknownOuter - Outer unknown interface.
  43. * ppIDrvItemRoot - Pointer to returned root item.
  44. * ppIUnknownInner - Pointer to returned inner unknown.
  45. * plDevErrVal - Pointer to the device error value.
  46. *
  47. \**************************************************************************/
  48. HRESULT CWiaCameraDevice::drvInitializeWia(
  49. BYTE *pWiasContext,
  50. LONG lFlags,
  51. BSTR bstrDeviceID,
  52. BSTR bstrRootFullItemName,
  53. IUnknown *pStiDevice,
  54. IUnknown *pIUnknownOuter,
  55. IWiaDrvItem **ppIDrvItemRoot,
  56. IUnknown **ppIUnknownInner,
  57. LONG *plDevErrVal)
  58. {
  59. DBG_FN("CWiaCameraDevice::drvInitializeWia");
  60. if (!ppIUnknownInner || !pIUnknownOuter)
  61. {
  62. // optional arguments, may be NULLs
  63. }
  64. if (!pWiasContext || !bstrDeviceID || !bstrRootFullItemName ||
  65. !pStiDevice || !ppIDrvItemRoot || !plDevErrVal)
  66. {
  67. wiauDbgError("drvInitializeWia", "invalid arguments");
  68. return E_INVALIDARG;
  69. }
  70. HRESULT hr = S_OK;
  71. *plDevErrVal = 0;
  72. //
  73. // Locals
  74. //
  75. MCAM_ITEM_INFO *pItem = NULL;
  76. wiauDbgTrace("drvInitializeWia", "device ID: %S", bstrDeviceID);
  77. *ppIDrvItemRoot = NULL;
  78. if (ppIUnknownInner)
  79. {
  80. *ppIUnknownInner = NULL;
  81. }
  82. //
  83. // Count the number of apps connected so that resources can be
  84. // freed when it reaches zero
  85. //
  86. m_iConnectedApps++;;
  87. wiauDbgTrace("drvInitializeWia", "Number of connected apps is now %d", m_iConnectedApps);
  88. if (m_iConnectedApps == 1)
  89. {
  90. //
  91. // Save STI device interface for calling locking functions
  92. //
  93. m_pStiDevice = (IStiDevice *)pStiDevice;
  94. //
  95. // Cache the device ID
  96. //
  97. m_bstrDeviceID = SysAllocString(bstrDeviceID);
  98. REQUIRE_ALLOC(m_bstrDeviceID, hr, "drvInitializeWia");
  99. //
  100. // Cache the root item name
  101. //
  102. m_bstrRootFullItemName = SysAllocString(bstrRootFullItemName);
  103. REQUIRE_ALLOC(m_bstrRootFullItemName, hr, "drvInitializeWia");
  104. //
  105. // For devices connected to ports that can be shared (e.g. USB),
  106. // open the device and initialize access to the camera
  107. //
  108. if (!m_pDeviceInfo->bExclusivePort) {
  109. hr = m_pDevice->Open(m_pDeviceInfo, m_wszPortName);
  110. REQUIRE_SUCCESS(hr, "Initialize", "Open failed");
  111. }
  112. //
  113. // Get information from the device
  114. //
  115. hr = m_pDevice->GetDeviceInfo(m_pDeviceInfo, &pItem);
  116. REQUIRE_SUCCESS(hr, "drvInitializeWia", "GetDeviceInfo failed");
  117. //
  118. // Build the capabilities array
  119. //
  120. hr = BuildCapabilities();
  121. REQUIRE_SUCCESS(hr, "drvInitializeWia", "BuildCapabilities failed");
  122. //
  123. // Build the device item tree
  124. //
  125. hr = BuildItemTree(pItem);
  126. REQUIRE_SUCCESS(hr, "drvInitializeWia", "BuildItemTree failed");
  127. }
  128. *ppIDrvItemRoot = m_pRootItem;
  129. Cleanup:
  130. return hr;
  131. }
  132. /**************************************************************************\
  133. * CWiaCameraDevice::drvUnInitializeWia
  134. *
  135. * Gets called when a client connection is going away.
  136. *
  137. * Arguments:
  138. *
  139. * pWiasContext - Pointer to the WIA Root item context of the client's
  140. * item tree.
  141. *
  142. \**************************************************************************/
  143. HRESULT CWiaCameraDevice::drvUnInitializeWia(BYTE *pWiasContext)
  144. {
  145. DBG_FN("CWiaCameraDevice::drvUnInitializeWia");
  146. if (!pWiasContext)
  147. {
  148. wiauDbgError("drvUnInitializeWia", "invalid arguments");
  149. return E_INVALIDARG;
  150. }
  151. HRESULT hr = S_OK;
  152. m_iConnectedApps--;
  153. if (m_iConnectedApps == 0)
  154. {
  155. hr = FreeResources();
  156. if (FAILED(hr))
  157. wiauDbgErrorHr(hr, "drvUnInitializeWia", "FreeResources failed, continuing...");
  158. //
  159. // Do not delete the device object here, because GetStatus may still be called later.
  160. //
  161. }
  162. return hr;
  163. }
  164. /**************************************************************************\
  165. * CWiaCameraDevice::drvInitItemProperties
  166. *
  167. * Initialize the device item properties. Called during item
  168. * initialization. This is called by the WIA Class driver
  169. * after the item tree has been built. It is called once for every
  170. * item in the tree. For the root item, just set the properties already
  171. * set up in drvInitializeWia. For child items, access the camera for
  172. * information about the item and for images also get the thumbnail.
  173. *
  174. * Arguments:
  175. *
  176. * pWiasContext - Pointer to WIA item.
  177. * lFlags - Operation flags, unused.
  178. * plDevErrVal - Pointer to the device error value.
  179. *
  180. *
  181. \**************************************************************************/
  182. HRESULT CWiaCameraDevice::drvInitItemProperties(
  183. BYTE *pWiasContext,
  184. LONG lFlags,
  185. LONG *plDevErrVal)
  186. {
  187. DBG_FN("CWiaCameraDevice::drvInitItemProperties");
  188. if (!pWiasContext || !plDevErrVal)
  189. {
  190. wiauDbgError("drvInitItemProperties", "invalid arguments");
  191. return E_INVALIDARG;
  192. }
  193. HRESULT hr = S_OK;
  194. *plDevErrVal = 0;
  195. LONG lItemType;
  196. hr = wiasGetItemType(pWiasContext, &lItemType);
  197. REQUIRE_SUCCESS(hr, "drvInitItemProperties", "wiasGetItemType failed");
  198. if (lItemType & WiaItemTypeRoot) {
  199. //
  200. // Build root item properties, initializing global
  201. // structures with their default and valid values
  202. //
  203. hr = BuildRootItemProperties(pWiasContext);
  204. REQUIRE_SUCCESS(hr, "drvInitItemProperties", "BuildRootItemProperties failed");
  205. }
  206. else {
  207. //
  208. // Build child item properties, initializing global
  209. // structures with their default and valid values
  210. //
  211. hr = BuildChildItemProperties(pWiasContext);
  212. REQUIRE_SUCCESS(hr, "drvInitItemProperties", "BuildChildItemProperties failed");
  213. }
  214. Cleanup:
  215. return hr;
  216. }
  217. /**************************************************************************\
  218. * CWiaCameraDevice::drvLockWiaDevice
  219. *
  220. * Lock access to the device.
  221. *
  222. * Arguments:
  223. *
  224. * pWiasContext - unused, can be NULL
  225. * lFlags - Operation flags, unused.
  226. * plDevErrVal - Pointer to the device error value.
  227. *
  228. *
  229. \**************************************************************************/
  230. HRESULT CWiaCameraDevice::drvLockWiaDevice(
  231. BYTE *pWiasContext,
  232. LONG lFlags,
  233. LONG *plDevErrVal)
  234. {
  235. DBG_FN("CWiaCameraDevice::drvLockWiaDevice");
  236. if (!plDevErrVal)
  237. {
  238. wiauDbgError("drvLockWiaDevice", "invalid arguments");
  239. return E_INVALIDARG;
  240. }
  241. *plDevErrVal = 0;
  242. return m_pStiDevice->LockDevice(100);
  243. }
  244. /**************************************************************************\
  245. * CWiaCameraDevice::drvUnLockWiaDevice
  246. *
  247. * Unlock access to the device.
  248. *
  249. * Arguments:
  250. *
  251. * pWiasContext - Pointer to the WIA item, unused.
  252. * lFlags - Operation flags, unused.
  253. * plDevErrVal - Pointer to the device error value.
  254. *
  255. \**************************************************************************/
  256. HRESULT CWiaCameraDevice::drvUnLockWiaDevice(
  257. BYTE *pWiasContext,
  258. LONG lFlags,
  259. LONG *plDevErrVal)
  260. {
  261. DBG_FN("CWiaCameraDevice::drvUnLockWiaDevice");
  262. if (!pWiasContext || !plDevErrVal)
  263. {
  264. wiauDbgError("drvUnLockWiaDevice", "invalid arguments");
  265. return E_INVALIDARG;
  266. }
  267. *plDevErrVal = 0;
  268. return m_pStiDevice->UnLockDevice();
  269. }
  270. /**************************************************************************\
  271. * CWiaCameraDevice::drvFreeDrvItemContext
  272. *
  273. * Free any device specific context.
  274. *
  275. * Arguments:
  276. *
  277. * lFlags - Operation flags, unused.
  278. * pDevSpecContext - Pointer to device specific context.
  279. * plDevErrVal - Pointer to the device error value.
  280. *
  281. \**************************************************************************/
  282. HRESULT CWiaCameraDevice::drvFreeDrvItemContext(
  283. LONG lFlags,
  284. BYTE *pSpecContext,
  285. LONG *plDevErrVal)
  286. {
  287. DBG_FN("CWiaCameraDevice::drvFreeDrvItemContext");
  288. if (!pSpecContext || !plDevErrVal)
  289. {
  290. wiauDbgError("drvFreeDrvItemContext", "invalid arguments");
  291. return E_INVALIDARG;
  292. }
  293. HRESULT hr = S_OK;
  294. *plDevErrVal = 0;
  295. ITEM_CONTEXT *pItemCtx = (ITEM_CONTEXT *) pSpecContext;
  296. if (pItemCtx)
  297. {
  298. if (pItemCtx->pItemInfo) {
  299. hr = m_pDevice->FreeItemInfo(m_pDeviceInfo, pItemCtx->pItemInfo);
  300. if (FAILED(hr))
  301. wiauDbgErrorHr(hr, "drvFreeDrvItemContext", "FreeItemInfo failed");
  302. }
  303. pItemCtx->pItemInfo = NULL;
  304. if (pItemCtx->pFormatInfo)
  305. {
  306. delete []pItemCtx->pFormatInfo;
  307. pItemCtx->pFormatInfo = NULL;
  308. }
  309. pItemCtx->lNumFormatInfo = 0;
  310. }
  311. return hr;
  312. }
  313. /**************************************************************************\
  314. * CWiaCameraDevice::drvReadItemProperties
  315. *
  316. * Read the device item properties. When a client application tries to
  317. * read a WIA Item's properties, the WIA Class driver will first notify
  318. * the driver by calling this method.
  319. *
  320. * Arguments:
  321. *
  322. * pWiasContext - wia item
  323. * lFlags - Operation flags, unused.
  324. * nPropSpec - Number of elements in pPropSpec.
  325. * pPropSpec - Pointer to property specification, showing which properties
  326. * the application wants to read.
  327. * plDevErrVal - Pointer to the device error value.
  328. *
  329. \**************************************************************************/
  330. HRESULT CWiaCameraDevice::drvReadItemProperties(
  331. BYTE *pWiasContext,
  332. LONG lFlags,
  333. ULONG nPropSpec,
  334. const PROPSPEC *pPropSpec,
  335. LONG *plDevErrVal)
  336. {
  337. DBG_FN("CWiaCameraDevice::drvReadItemProperties");
  338. if (!pWiasContext || !pPropSpec || !plDevErrVal)
  339. {
  340. wiauDbgError("drvReadItemProperties", "invalid arguments");
  341. return E_INVALIDARG;
  342. }
  343. HRESULT hr = S_OK;
  344. *plDevErrVal = 0;
  345. LONG lItemType;
  346. hr = wiasGetItemType(pWiasContext, &lItemType);
  347. REQUIRE_SUCCESS(hr, "drvReadItemProperties", "wiasGetItemType failed");
  348. if (lItemType & WiaItemTypeRoot) {
  349. //
  350. // Build root item properties, initializing global
  351. // structures with their default and valid values
  352. //
  353. hr = ReadRootItemProperties(pWiasContext, nPropSpec, pPropSpec);
  354. REQUIRE_SUCCESS(hr, "drvReadItemProperties", "ReadRootItemProperties failed");
  355. }
  356. else {
  357. //
  358. // Build child item properties, initializing global
  359. // structures with their default and valid values
  360. //
  361. hr = ReadChildItemProperties(pWiasContext, nPropSpec, pPropSpec);
  362. REQUIRE_SUCCESS(hr, "drvReadItemProperties", "ReadChildItemProperties failed");
  363. }
  364. Cleanup:
  365. return hr;
  366. }
  367. /**************************************************************************\
  368. * CWiaCameraDevice::drvWriteItemProperties
  369. *
  370. * Write the device item properties to the hardware. This is called by the
  371. * WIA Class driver prior to drvAcquireItemData when the client requests
  372. * a data transfer.
  373. *
  374. * Arguments:
  375. *
  376. * pWiasContext - Pointer to WIA item.
  377. * lFlags - Operation flags, unused.
  378. * pmdtc - Pointer to mini driver context. On entry, only the
  379. * portion of the mini driver context which is derived
  380. * from the item properties is filled in.
  381. * plDevErrVal - Pointer to the device error value.
  382. *
  383. \**************************************************************************/
  384. HRESULT CWiaCameraDevice::drvWriteItemProperties(
  385. BYTE *pWiasContext,
  386. LONG lFlags,
  387. PMINIDRV_TRANSFER_CONTEXT pmdtc,
  388. LONG *plDevErrVal)
  389. {
  390. DBG_FN("CWiaCameraDevice::drvWriteItemProperties");
  391. if (!pWiasContext || !pmdtc || !plDevErrVal)
  392. {
  393. wiauDbgError("drvWriteItemProperties", "invalid arguments");
  394. return E_INVALIDARG;
  395. }
  396. HRESULT hr = S_OK;
  397. //
  398. // This function doesn't need to do anything, because all of the camera
  399. // properties are written in drvValidateItemProperties
  400. //
  401. *plDevErrVal = 0;
  402. return hr;
  403. }
  404. /**************************************************************************\
  405. * CWiaCameraDevice::drvAcquireItemData
  406. *
  407. * Transfer data from a mini driver item to device manger.
  408. *
  409. * Arguments:
  410. *
  411. * pWiasContext - Pointer to the WIA item.
  412. * lFlags - Operation flags, unused.
  413. * pmdtc - Pointer to mini driver context. On entry, only the
  414. * portion of the mini driver context which is derived
  415. * from the item properties is filled in.
  416. * plDevErrVal - Pointer to the device error value.
  417. *
  418. \**************************************************************************/
  419. HRESULT CWiaCameraDevice::drvAcquireItemData(
  420. BYTE *pWiasContext,
  421. LONG lFlags,
  422. PMINIDRV_TRANSFER_CONTEXT pmdtc,
  423. LONG *plDevErrVal)
  424. {
  425. DBG_FN("CWiaCameraDevice::drvAcquireItemData");
  426. if (!pWiasContext || !plDevErrVal || !pmdtc)
  427. {
  428. wiauDbgError("drvAcquireItemData", "invalid arguments");
  429. return E_INVALIDARG;
  430. }
  431. HRESULT hr = S_OK;
  432. *plDevErrVal = 0;
  433. //
  434. // Locals
  435. //
  436. BYTE *pTempBuf = NULL;
  437. LONG lBufSize = 0;
  438. ITEM_CONTEXT *pItemCtx = NULL;
  439. BOOL bConvert = FALSE;
  440. //
  441. // Get item context
  442. //
  443. hr = wiauGetDrvItemContext(pWiasContext, (VOID **) &pItemCtx);
  444. REQUIRE_SUCCESS(hr, "drvAcquireItemData", "wiauGetDrvItemContext failed");
  445. //
  446. // If the format requested is BMP or DIB, and the image is not already in BMP
  447. // format, convert it
  448. //
  449. bConvert = (IsEqualGUID(pmdtc->guidFormatID, WiaImgFmt_BMP) ||
  450. IsEqualGUID(pmdtc->guidFormatID, WiaImgFmt_MEMORYBMP)) &&
  451. !IsEqualGUID(*(pItemCtx->pItemInfo->pguidFormat), WiaImgFmt_BMP);
  452. //
  453. // If the class driver did not allocate the transfer buffer or the image is being
  454. // converted to DIB or BMP, allocate a temporary buffer.
  455. //
  456. if (bConvert || !pmdtc->bClassDrvAllocBuf) {
  457. lBufSize = pItemCtx->pItemInfo->lSize;
  458. pTempBuf = new BYTE[lBufSize];
  459. REQUIRE_ALLOC(pTempBuf, hr, "drvAcquireItemData");
  460. }
  461. //
  462. // Acquire the data from the device
  463. //
  464. hr = AcquireData(pItemCtx, pmdtc, pTempBuf, lBufSize, bConvert);
  465. REQUIRE_SUCCESS(hr, "drvAcquireItemData", "AcquireData failed");
  466. if (hr == S_FALSE)
  467. {
  468. wiauDbgWarning("drvAcquireItemData", "Transfer cancelled");
  469. goto Cleanup;
  470. }
  471. //
  472. // Now convert the data to BMP, if necessary
  473. //
  474. if (bConvert)
  475. {
  476. hr = Convert(pWiasContext, pItemCtx, pmdtc, pTempBuf, lBufSize);
  477. REQUIRE_SUCCESS(hr, "drvAcquireItemData", "Convert failed");
  478. }
  479. Cleanup:
  480. if (pTempBuf)
  481. {
  482. delete []pTempBuf;
  483. pTempBuf = NULL;
  484. lBufSize = 0;
  485. }
  486. return hr;
  487. }
  488. /**************************************************************************\
  489. * CWiaCameraDevice::drvGetWiaFormatInfo
  490. *
  491. * Returns an array of WIA_FORMAT_INFO structs, which specify the format
  492. * and media type pairs that are supported.
  493. *
  494. * Arguments:
  495. *
  496. * pWiasContext - Pointer to the WIA item context, unused.
  497. * lFlags - Operation flags, unused.
  498. * pcelt - Pointer to returned number of elements in
  499. * returned WIA_FORMAT_INFO array.
  500. * ppwfi - Pointer to returned WIA_FORMAT_INFO array.
  501. * plDevErrVal - Pointer to the device error value.
  502. *
  503. \**************************************************************************/
  504. HRESULT CWiaCameraDevice::drvGetWiaFormatInfo(
  505. BYTE *pWiasContext,
  506. LONG lFlags,
  507. LONG *pcelt,
  508. WIA_FORMAT_INFO **ppwfi,
  509. LONG *plDevErrVal)
  510. {
  511. DBG_FN("CWiaCameraDevice::drvGetWiaFormatInfo");
  512. if (!pWiasContext || !pcelt || !ppwfi || !plDevErrVal)
  513. {
  514. wiauDbgError("drvGetWiaFormatInfo", "invalid arguments");
  515. return E_INVALIDARG;
  516. }
  517. HRESULT hr = S_OK;
  518. *plDevErrVal = 0;
  519. //
  520. // Locals
  521. //
  522. IWiaDrvItem *pWiaDrvItem = NULL;
  523. ITEM_CONTEXT *pItemCtx = NULL;
  524. const GUID *pguidFormat = NULL;
  525. BOOL bAddBmp = FALSE;
  526. *pcelt = 0;
  527. *ppwfi = NULL;
  528. hr = wiauGetDrvItemContext(pWiasContext, (VOID **) &pItemCtx, &pWiaDrvItem);
  529. REQUIRE_SUCCESS(hr, "drvGetWiaFormatInfo", "wiauGetDrvItemContext failed");
  530. if (!pItemCtx->pFormatInfo)
  531. {
  532. //
  533. // The format info list is not intialized. Do it now.
  534. //
  535. LONG ItemType;
  536. DWORD ui32;
  537. hr = wiasGetItemType(pWiasContext, &ItemType);
  538. REQUIRE_SUCCESS(hr, "drvGetWiaFormatInfo", "wiasGetItemType");
  539. if ((ItemType & WiaItemTypeFolder) ||
  540. (ItemType & WiaItemTypeRoot))
  541. {
  542. //
  543. // Folders and the root don't really need format info, but some apps may fail
  544. // without it. Create a fake list just in case.
  545. //
  546. pItemCtx->pFormatInfo = new WIA_FORMAT_INFO[2];
  547. REQUIRE_ALLOC(pItemCtx->pFormatInfo, hr, "drvGetWiaFormatInfo");
  548. pItemCtx->lNumFormatInfo = 2;
  549. pItemCtx->pFormatInfo[0].lTymed = TYMED_FILE;
  550. pItemCtx->pFormatInfo[0].guidFormatID = FMT_NOTHING;
  551. pItemCtx->pFormatInfo[1].lTymed = TYMED_CALLBACK;
  552. pItemCtx->pFormatInfo[1].guidFormatID = FMT_NOTHING;
  553. }
  554. else if (ItemType & WiaItemTypeFile)
  555. {
  556. //
  557. // Create the supported format for the item, based on the format stored in the
  558. // ObjectInfo structure.
  559. //
  560. if (!pItemCtx->pItemInfo)
  561. {
  562. wiauDbgError("drvGetWiaFormatInfo", "Item info pointer in context is null");
  563. hr = E_FAIL;
  564. goto Cleanup;
  565. }
  566. pguidFormat = pItemCtx->pItemInfo->pguidFormat;
  567. //
  568. // If the format of the item is supported by the converter utility, add the
  569. // BMP types to the format array, since this driver can convert those to BMP
  570. //
  571. bAddBmp = m_Converter.IsFormatSupported(pguidFormat);
  572. ULONG NumWfi = bAddBmp ? 2 : 1;
  573. //
  574. // Allocate two entries for each format, one for file transfer and one for callback
  575. //
  576. WIA_FORMAT_INFO *pwfi = new WIA_FORMAT_INFO[2 * NumWfi];
  577. REQUIRE_ALLOC(pwfi, hr, "drvGetWiaFormatInfo");
  578. pwfi[0].guidFormatID = *pguidFormat;
  579. pwfi[0].lTymed = TYMED_FILE;
  580. pwfi[1].guidFormatID = *pguidFormat;
  581. pwfi[1].lTymed = TYMED_CALLBACK;
  582. //
  583. // Add the BMP entries when appropriate
  584. //
  585. if (bAddBmp)
  586. {
  587. pwfi[2].guidFormatID = WiaImgFmt_BMP;
  588. pwfi[2].lTymed = TYMED_FILE;
  589. pwfi[3].guidFormatID = WiaImgFmt_MEMORYBMP;
  590. pwfi[3].lTymed = TYMED_CALLBACK;
  591. }
  592. pItemCtx->lNumFormatInfo = 2 * NumWfi;
  593. pItemCtx->pFormatInfo = pwfi;
  594. }
  595. }
  596. *pcelt = pItemCtx->lNumFormatInfo;
  597. *ppwfi = pItemCtx->pFormatInfo;
  598. Cleanup:
  599. return hr;
  600. }
  601. /**************************************************************************\
  602. * CWiaCameraDevice::drvValidateItemProperties
  603. *
  604. * Validate the device item properties. It is called when changes are made
  605. * to an item's properties. Driver should not only check that the values
  606. * are valid, but must update any valid values that may change as a result.
  607. * If an a property is not being written by the application, and it's value
  608. * is invalid, then "fold" it to a new value, else fail validation (because
  609. * the application is setting the property to an invalid value).
  610. *
  611. * Arguments:
  612. *
  613. * pWiasContext - Pointer to the WIA item, unused.
  614. * lFlags - Operation flags, unused.
  615. * nPropSpec - The number of properties that are being written
  616. * pPropSpec - An array of PropSpecs identifying the properties that
  617. * are being written.
  618. * plDevErrVal - Pointer to the device error value.
  619. *
  620. ***************************************************************************/
  621. HRESULT CWiaCameraDevice::drvValidateItemProperties(
  622. BYTE *pWiasContext,
  623. LONG lFlags,
  624. ULONG nPropSpec,
  625. const PROPSPEC *pPropSpec,
  626. LONG *plDevErrVal)
  627. {
  628. DBG_FN("CWiaCameraDevice::drvValidateItemProperties");
  629. if (!pWiasContext || !pPropSpec || !plDevErrVal)
  630. {
  631. wiauDbgError("drvValidateItemProperties", "invalid arguments");
  632. return E_INVALIDARG;
  633. }
  634. HRESULT hr = S_OK;
  635. *plDevErrVal = 0;
  636. //
  637. // Locals
  638. //
  639. LONG lItemType = 0;
  640. ITEM_CONTEXT *pItemCtx = NULL;
  641. MCAM_ITEM_INFO *pItemInfo = NULL;
  642. BOOL bFormatUpdated = FALSE;
  643. LONG lRights = 0;
  644. BOOL bReadOnly = 0;
  645. //
  646. // Have the service validate against the valid values for each property
  647. //
  648. hr = wiasValidateItemProperties(pWiasContext, nPropSpec, pPropSpec);
  649. REQUIRE_SUCCESS(hr, "drvValidateItemProperties", "wiasValidateItemProperties failed");
  650. //
  651. // Get the item type
  652. //
  653. hr = wiasGetItemType(pWiasContext, &lItemType);
  654. REQUIRE_SUCCESS(hr, "drvValidateItemProperties", "wiasGetItemType");
  655. //
  656. // Validate root item properties
  657. //
  658. if (lItemType & WiaItemTypeRoot) {
  659. //
  660. // None yet
  661. //
  662. }
  663. //
  664. // Validate child item properties
  665. //
  666. else {
  667. //
  668. // Get the driver item context and item info pointer
  669. //
  670. hr = wiauGetDrvItemContext(pWiasContext, (VOID **) &pItemCtx);
  671. REQUIRE_SUCCESS(hr, "drvGetWiaFormatInfo", "wiauGetDrvItemContext failed");
  672. pItemInfo = pItemCtx->pItemInfo;
  673. //
  674. // See if access rights were changed
  675. //
  676. if (wiauPropInPropSpec(nPropSpec, pPropSpec, WIA_IPA_ACCESS_RIGHTS))
  677. {
  678. hr = wiasReadPropLong(pWiasContext, WIA_IPA_ACCESS_RIGHTS, &lRights, NULL, TRUE);
  679. REQUIRE_SUCCESS(hr, "drvValidateItemProperties", "wiasReadPropLong failed");
  680. bReadOnly = (lRights == WIA_ITEM_READ);
  681. hr = m_pDevice->SetItemProt(m_pDeviceInfo, pItemInfo, bReadOnly);
  682. REQUIRE_SUCCESS(hr, "drvValidateItemProperties", "SetItemProt failed");
  683. pItemInfo->bReadOnly = bReadOnly;
  684. }
  685. //
  686. // If tymed property was changed, update format and item size
  687. //
  688. if (wiauPropInPropSpec(nPropSpec, pPropSpec, WIA_IPA_TYMED)) {
  689. //
  690. // Create a property context needed by some WIA Service
  691. // functions used below.
  692. //
  693. WIA_PROPERTY_CONTEXT Context;
  694. hr = wiasCreatePropContext(nPropSpec, (PROPSPEC*)pPropSpec, 0,
  695. NULL, &Context);
  696. REQUIRE_SUCCESS(hr, "drvValidateItemProperties", "wiasCreatePropContext failed");
  697. //
  698. // Use the WIA Service to update the valid values
  699. // for format. It will pull the values from the
  700. // structure returned by drvGetWiaFormatInfo, using the
  701. // new value for tymed.
  702. //
  703. hr = wiasUpdateValidFormat(pWiasContext, &Context, (IWiaMiniDrv*) this);
  704. REQUIRE_SUCCESS(hr, "drvGetWiaFormatInfo", "wiasUpdateValidFormat failed");
  705. //
  706. // Free the property context
  707. //
  708. hr = wiasFreePropContext(&Context);
  709. REQUIRE_SUCCESS(hr, "drvGetWiaFormatInfo", "wiasFreePropContext failed");
  710. //
  711. // The format may have changed, so update the properties
  712. // dependent on format
  713. //
  714. bFormatUpdated = TRUE;
  715. }
  716. //
  717. // If the format was changed, just update the item size
  718. //
  719. if (bFormatUpdated || wiauPropInPropSpec(nPropSpec, pPropSpec, WIA_IPA_FORMAT))
  720. {
  721. //
  722. // Update the affected item properties
  723. //
  724. hr = wiauSetImageItemSize(pWiasContext, pItemInfo->lWidth, pItemInfo->lHeight,
  725. pItemInfo->lDepth, pItemInfo->lSize, pItemInfo->wszExt);
  726. REQUIRE_SUCCESS(hr, "drvGetWiaFormatInfo", "wiauSetImageItemSize failed");
  727. }
  728. }
  729. Cleanup:
  730. return hr;
  731. }
  732. /**************************************************************************\
  733. * CWiaCameraDevice::drvDeleteItem
  734. *
  735. * Delete an item from the device.
  736. *
  737. * Arguments:
  738. *
  739. * pWiasContext - Indicates the item to delete.
  740. * lFlags - Operation flags, unused.
  741. * plDevErrVal - Pointer to the device error value.
  742. *
  743. \**************************************************************************/
  744. HRESULT CWiaCameraDevice::drvDeleteItem(
  745. BYTE *pWiasContext,
  746. LONG lFlags,
  747. LONG *plDevErrVal)
  748. {
  749. DBG_FN("CWiaCameraDevice::drvDeleteItem");
  750. if (!pWiasContext || !plDevErrVal)
  751. {
  752. wiauDbgError("drvDeleteItem", "invalid arguments");
  753. return E_INVALIDARG;
  754. }
  755. HRESULT hr = S_OK;
  756. *plDevErrVal = 0;
  757. //
  758. // Locals
  759. //
  760. ITEM_CONTEXT *pItemCtx = NULL;
  761. IWiaDrvItem *pDrvItem = NULL;
  762. BSTR bstrFullName = NULL;
  763. hr = wiauGetDrvItemContext(pWiasContext, (VOID **) &pItemCtx, &pDrvItem);
  764. REQUIRE_SUCCESS(hr, "drvDeleteItem", "wiauGetDrvItemContext failed");
  765. hr = m_pDevice->DeleteItem(m_pDeviceInfo, pItemCtx->pItemInfo);
  766. REQUIRE_SUCCESS(hr, "drvDeleteItem", "DeleteItem failed");
  767. //
  768. // Get the item's full name
  769. //
  770. hr = pDrvItem->GetFullItemName(&bstrFullName);
  771. REQUIRE_SUCCESS(hr, "drvDeleteItem", "GetFullItemName failed");
  772. //
  773. // Queue an "item deleted" event
  774. //
  775. hr = wiasQueueEvent(m_bstrDeviceID, &WIA_EVENT_ITEM_DELETED, bstrFullName);
  776. REQUIRE_SUCCESS(hr, "drvDeleteItem", "wiasQueueEvent failed");
  777. Cleanup:
  778. if (bstrFullName)
  779. SysFreeString(bstrFullName);
  780. return hr;
  781. }
  782. /**************************************************************************\
  783. * CWiaCameraDevice::drvNotifyPnpEvent
  784. *
  785. * Pnp Event received by device manager. This is called when a Pnp event
  786. * is received for this device.
  787. *
  788. * Arguments:
  789. *
  790. *
  791. *
  792. \**************************************************************************/
  793. HRESULT CWiaCameraDevice::drvNotifyPnpEvent(
  794. const GUID *pEventGUID,
  795. BSTR bstrDeviceID,
  796. ULONG ulReserved)
  797. {
  798. DBG_FN("CWiaCameraDevice::DrvNotifyPnpEvent");
  799. if (!pEventGUID)
  800. {
  801. wiauDbgError("drvNotifyPnpEvent", "invalid arguments");
  802. return E_INVALIDARG;
  803. }
  804. HRESULT hr = S_OK;
  805. return hr;
  806. }
  807. /**************************************************************************\
  808. * CWiaCameraDevice::drvGetCapabilities
  809. *
  810. * Get supported device commands and events as an array of WIA_DEV_CAPS.
  811. *
  812. * Arguments:
  813. *
  814. * pWiasContext - Pointer to the WIA item, unused.
  815. * lFlags - Operation flags.
  816. * pcelt - Pointer to returned number of elements in
  817. * returned GUID array.
  818. * ppCapabilities - Pointer to returned GUID array.
  819. * plDevErrVal - Pointer to the device error value.
  820. *
  821. \**************************************************************************/
  822. HRESULT CWiaCameraDevice::drvGetCapabilities(
  823. BYTE *pWiasContext,
  824. LONG ulFlags,
  825. LONG *pcelt,
  826. WIA_DEV_CAP_DRV **ppCapabilities,
  827. LONG *plDevErrVal)
  828. {
  829. DBG_FN("CWiaCameraDevice::drvGetCapabilites");
  830. if (!pWiasContext)
  831. {
  832. //
  833. // The WIA service may pass in a NULL for the pWiasContext. This is expected
  834. // because there is a case where no item was created at the time the event was fired.
  835. //
  836. }
  837. if (!pcelt || !ppCapabilities || !plDevErrVal)
  838. {
  839. wiauDbgError("drvGetCapabilities", "invalid arguments");
  840. return E_INVALIDARG;
  841. }
  842. *plDevErrVal = 0;
  843. //
  844. // Return values depend on the passed flags. Flags specify whether we should return
  845. // commands, events, or both.
  846. //
  847. if (ulFlags & (WIA_DEVICE_COMMANDS | WIA_DEVICE_EVENTS)) {
  848. //
  849. // Return both events and commands
  850. //
  851. *pcelt = m_lNumCapabilities;
  852. *ppCapabilities = m_pCapabilities;
  853. }
  854. else if (ulFlags & WIA_DEVICE_COMMANDS) {
  855. //
  856. // Return commands only
  857. //
  858. *pcelt = m_lNumSupportedCommands;
  859. *ppCapabilities = &m_pCapabilities[m_lNumSupportedEvents];
  860. }
  861. else if (ulFlags & WIA_DEVICE_EVENTS) {
  862. //
  863. // Return events only
  864. //
  865. *pcelt = m_lNumSupportedEvents;
  866. *ppCapabilities = m_pCapabilities;
  867. }
  868. return S_OK;
  869. }
  870. /**************************************************************************\
  871. * CWiaCameraDevice::drvDeviceCommand
  872. *
  873. * Issue a command to the device.
  874. *
  875. * Arguments:
  876. *
  877. * pWiasContext - Pointer to the WIA item.
  878. * lFlags - Operation flags, unused.
  879. * plCommand - Pointer to command GUID.
  880. * ppWiaDrvItem - Optional pointer to returned item, unused.
  881. * plDevErrVal - Pointer to the device error value.
  882. *
  883. \**************************************************************************/
  884. HRESULT CWiaCameraDevice::drvDeviceCommand(
  885. BYTE *pWiasContext,
  886. LONG lFlags,
  887. const GUID *plCommand,
  888. IWiaDrvItem **ppWiaDrvItem,
  889. LONG *plDevErrVal)
  890. {
  891. DBG_FN("CWiaCameraDevice::drvDeviceCommand");
  892. if (!pWiasContext || !plCommand || !ppWiaDrvItem || !plDevErrVal)
  893. {
  894. wiauDbgError("drvDeviceCommand", "invalid arguments");
  895. return E_INVALIDARG;
  896. }
  897. HRESULT hr = S_OK;
  898. *plDevErrVal = 0;
  899. //
  900. // Locals
  901. //
  902. MCAM_ITEM_INFO *pItem = NULL;
  903. //
  904. // Check which command was issued
  905. //
  906. if (*plCommand == WIA_CMD_SYNCHRONIZE) {
  907. //
  908. // SYNCHRONIZE - Re-build the item tree, if the device needs it.
  909. //
  910. if (m_pDeviceInfo->bSyncNeeded)
  911. {
  912. hr = m_pDevice->StopEvents(m_pDeviceInfo);
  913. REQUIRE_SUCCESS(hr, "drvDeviceCommand", "StopEvents failed");
  914. hr = DeleteItemTree(WiaItemTypeDisconnected);
  915. REQUIRE_SUCCESS(hr, "drvDeviceCommand", "DeleteItemTree failed");
  916. hr = m_pDevice->GetDeviceInfo(m_pDeviceInfo, &pItem);
  917. REQUIRE_SUCCESS(hr, "drvDeviceCommand", "GetDeviceInfo failed");
  918. hr = BuildItemTree(pItem);
  919. REQUIRE_SUCCESS(hr, "drvDeviceCommand", "BuildItemTree failed");
  920. }
  921. }
  922. #if DEADCODE
  923. //
  924. // Not implemented yet
  925. //
  926. else if (*plCommand == WIA_CMD_TAKE_PICTURE) {
  927. //
  928. // TAKE_PICTURE - Command the camera to capture a new image.
  929. //
  930. hr = m_pDevice->TakePicture(&pItem);
  931. REQUIRE_SUCCESS(hr, "drvDeviceCommand", "TakePicture failed");
  932. hr = AddObject(pItem);
  933. REQUIRE_SUCCESS(hr, "drvDeviceCommand", "AddObject failed");
  934. hr = LinkToParent(pItem);
  935. REQUIRE_SUCCESS(hr, "drvDeviceCommand", "LinkToParent failed");
  936. }
  937. #endif
  938. else {
  939. wiauDbgWarning("drvDeviceCommand", "Unknown command 0x%08x", *plCommand);
  940. hr = E_NOTIMPL;
  941. goto Cleanup;
  942. }
  943. Cleanup:
  944. return hr;
  945. }
  946. /**************************************************************************\
  947. * CWiaCameraDevice::drvAnalyzeItem
  948. *
  949. * This device does not support image analysis, so return E_NOTIMPL.
  950. *
  951. * Arguments:
  952. *
  953. * pWiasContext - Pointer to the device item to be analyzed.
  954. * lFlags - Operation flags.
  955. * plDevErrVal - Pointer to the device error value.
  956. *
  957. \**************************************************************************/
  958. HRESULT CWiaCameraDevice::drvAnalyzeItem(
  959. BYTE *pWiasContext,
  960. LONG lFlags,
  961. LONG *plDevErrVal)
  962. {
  963. DBG_FN("CWiaCameraDevice::drvAnalyzeItem");
  964. if (!pWiasContext || !plDevErrVal)
  965. {
  966. wiauDbgError("drvAnalyzeItem", "invalid arguments");
  967. return E_INVALIDARG;
  968. }
  969. *plDevErrVal = 0;
  970. return E_NOTIMPL;
  971. }
  972. /**************************************************************************\
  973. * CWiaCameraDevice::drvGetDeviceErrorStr
  974. *
  975. * Map a device error value to a string.
  976. *
  977. * Arguments:
  978. *
  979. * lFlags - Operation flags, unused.
  980. * lDevErrVal - Device error value.
  981. * ppszDevErrStr - Pointer to returned error string.
  982. * plDevErrVal - Pointer to the device error value.
  983. *
  984. \**************************************************************************/
  985. HRESULT CWiaCameraDevice::drvGetDeviceErrorStr(
  986. LONG lFlags,
  987. LONG lDevErrVal,
  988. LPOLESTR *ppszDevErrStr,
  989. LONG *plDevErr)
  990. {
  991. DBG_FN("CWiaCameraDevice::drvGetDeviceErrorStr");
  992. if (!ppszDevErrStr || !plDevErr)
  993. {
  994. wiauDbgError("drvGetDeviceErrorStr", "invalid arguments");
  995. return E_INVALIDARG;
  996. }
  997. HRESULT hr = S_OK;
  998. *plDevErr = 0;
  999. //
  1000. // Map device errors to a string appropriate for showing to the user
  1001. //
  1002. switch (lDevErrVal) {
  1003. case 0:
  1004. *ppszDevErrStr = NULL;
  1005. break;
  1006. default:
  1007. *ppszDevErrStr = NULL;
  1008. hr = E_FAIL;
  1009. }
  1010. return hr;
  1011. }
  1012. /*******************************************************************************
  1013. *
  1014. * P R I V A T E M E T H O D S
  1015. *
  1016. *******************************************************************************/
  1017. /**************************************************************************\
  1018. * FreeResources
  1019. *
  1020. * Cleans up all of the resources held by the driver.
  1021. *
  1022. \**************************************************************************/
  1023. HRESULT
  1024. CWiaCameraDevice::FreeResources()
  1025. {
  1026. DBG_FN("CWiaCameraDevice::FreeResources");
  1027. HRESULT hr = S_OK;
  1028. wiauDbgTrace("FreeResources", "Connected apps is now zero, freeing resources...");
  1029. hr = m_pDevice->StopEvents(m_pDeviceInfo);
  1030. if (FAILED(hr))
  1031. wiauDbgErrorHr(hr, "FreeResources", "StopEvents failed");
  1032. // Destroy the driver item tree
  1033. hr = DeleteItemTree(WiaItemTypeDisconnected);
  1034. if (FAILED(hr))
  1035. wiauDbgErrorHr(hr, "FreeResources", "UnlinkItemTree failed");
  1036. // Delete allocated arrays
  1037. DeleteCapabilitiesArrayContents();
  1038. //
  1039. // For devices connected to ports that can be shared (e.g. USB),
  1040. // close the device
  1041. //
  1042. if (m_pDeviceInfo && !m_pDeviceInfo->bExclusivePort) {
  1043. hr = m_pDevice->Close(m_pDeviceInfo);
  1044. if (FAILED(hr))
  1045. wiauDbgErrorHr(hr, "FreeResources", "Close failed");
  1046. }
  1047. // Free the storage for the device ID
  1048. if (m_bstrDeviceID) {
  1049. SysFreeString(m_bstrDeviceID);
  1050. m_bstrDeviceID = NULL;
  1051. }
  1052. // Free the storage for the root item name
  1053. if (m_bstrRootFullItemName) {
  1054. SysFreeString(m_bstrRootFullItemName);
  1055. m_bstrRootFullItemName = NULL;
  1056. }
  1057. /*
  1058. // Kill notification thread if it exists.
  1059. SetNotificationHandle(NULL);
  1060. // Close event for syncronization of notifications shutdown.
  1061. if (m_hShutdownEvent && (m_hShutdownEvent != INVALID_HANDLE_VALUE)) {
  1062. CloseHandle(m_hShutdownEvent);
  1063. m_hShutdownEvent = NULL;
  1064. }
  1065. //
  1066. // WIA member destruction
  1067. //
  1068. // Cleanup the WIA event sink.
  1069. if (m_pIWiaEventCallback) {
  1070. m_pIWiaEventCallback->Release();
  1071. m_pIWiaEventCallback = NULL;
  1072. }
  1073. */
  1074. return hr;
  1075. }
  1076. /**************************************************************************\
  1077. * DeleteItemTree
  1078. *
  1079. * Call device manager to unlink and release our reference to
  1080. * all items in the driver item tree.
  1081. *
  1082. * Arguments:
  1083. *
  1084. *
  1085. *
  1086. \**************************************************************************/
  1087. HRESULT
  1088. CWiaCameraDevice::DeleteItemTree(LONG lReason)
  1089. {
  1090. DBG_FN("CWiaCameraDevice::DeleteItemTree");
  1091. HRESULT hr = S_OK;
  1092. //
  1093. // If no tree, return.
  1094. //
  1095. if (!m_pRootItem)
  1096. goto Cleanup;
  1097. //
  1098. // Call device manager to unlink the driver item tree.
  1099. //
  1100. hr = m_pRootItem->UnlinkItemTree(lReason);
  1101. REQUIRE_SUCCESS(hr, "DeleteItemTree", "UnlinkItemTree failed");
  1102. m_pRootItem->Release();
  1103. m_pRootItem = NULL;
  1104. Cleanup:
  1105. return hr;
  1106. }
  1107. /**************************************************************************\
  1108. * BuildItemTree
  1109. *
  1110. * The device uses the WIA Service functions to build up a tree of
  1111. * device items.
  1112. *
  1113. * Arguments:
  1114. *
  1115. *
  1116. *
  1117. \**************************************************************************/
  1118. HRESULT
  1119. CWiaCameraDevice::BuildItemTree(MCAM_ITEM_INFO *pItem)
  1120. {
  1121. DBG_FN("CWiaCameraDevice::BuildItemTree");
  1122. HRESULT hr = S_OK;
  1123. //
  1124. // Locals
  1125. //
  1126. BSTR bstrRoot = NULL;
  1127. ITEM_CONTEXT *pItemCtx = NULL;
  1128. MCAM_ITEM_INFO *pCurItem = NULL;
  1129. //
  1130. // Make sure the item tree doesn't already exist
  1131. //
  1132. if (m_pRootItem)
  1133. {
  1134. wiauDbgError("BuildItemTree", "Item tree already exists");
  1135. hr = E_FAIL;
  1136. goto Cleanup;
  1137. }
  1138. //
  1139. // Create the root item name
  1140. //
  1141. bstrRoot = SysAllocString(L"Root");
  1142. REQUIRE_ALLOC(bstrRoot, hr, "BuildItemTree");
  1143. //
  1144. // Create the root item
  1145. //
  1146. hr = wiasCreateDrvItem(WiaItemTypeFolder | WiaItemTypeDevice | WiaItemTypeRoot,
  1147. bstrRoot,
  1148. m_bstrRootFullItemName,
  1149. (IWiaMiniDrv *)this,
  1150. sizeof(ITEM_CONTEXT),
  1151. (BYTE **) &pItemCtx,
  1152. &m_pRootItem);
  1153. REQUIRE_SUCCESS(hr, "BuildItemTree", "wiasCreateDrvItem failed");
  1154. //
  1155. // Initialize item context fields for the root
  1156. //
  1157. memset(pItemCtx, 0, sizeof(ITEM_CONTEXT));
  1158. //
  1159. // Create a driver item for each item on the camera
  1160. //
  1161. pCurItem = pItem;
  1162. while (pCurItem) {
  1163. hr = AddObject(pCurItem);
  1164. REQUIRE_SUCCESS(hr, "BuildItemTree", "AddObject failed");
  1165. pCurItem = pCurItem->pNext;
  1166. }
  1167. //
  1168. // Link each item to its parent
  1169. //
  1170. pCurItem = pItem;
  1171. while (pCurItem) {
  1172. hr = LinkToParent(pCurItem);
  1173. REQUIRE_SUCCESS(hr, "BuildItemTree", "LinkToParent failed");
  1174. pCurItem = pCurItem->pNext;
  1175. }
  1176. Cleanup:
  1177. if (bstrRoot)
  1178. SysFreeString(bstrRoot);
  1179. return hr;
  1180. }
  1181. /**************************************************************************\
  1182. * AddObject
  1183. *
  1184. * Helper function to add an item to the driver item tree
  1185. *
  1186. * Arguments:
  1187. *
  1188. * pItemInfo - Pointer to the item info structure
  1189. *
  1190. \**************************************************************************/
  1191. HRESULT CWiaCameraDevice::AddObject(MCAM_ITEM_INFO *pItemInfo)
  1192. {
  1193. DBG_FN("CWiaCameraDevice::AddObject");
  1194. HRESULT hr = S_OK;
  1195. //
  1196. // Locals
  1197. //
  1198. LONG lItemType = 0;
  1199. BSTR bstrItemFullName = NULL;
  1200. BSTR bstrItemName = NULL;
  1201. WCHAR wszTemp[MAX_PATH];
  1202. IWiaDrvItem *pItem = NULL;
  1203. ITEM_CONTEXT *pItemCtx = NULL;
  1204. REQUIRE_ARGS(!pItemInfo, hr, "AddObject");
  1205. //
  1206. // Create the item's full name
  1207. //
  1208. hr = ConstructFullName(pItemInfo, wszTemp, sizeof(wszTemp) / sizeof(wszTemp[0]));
  1209. REQUIRE_SUCCESS(hr, "AddObject", "ConstructFullName failed");
  1210. wiauDbgTrace("AddObject", "Adding item %S", wszTemp);
  1211. bstrItemFullName = SysAllocString(wszTemp);
  1212. REQUIRE_ALLOC(bstrItemFullName, hr, "AddObject");
  1213. bstrItemName = SysAllocString(pItemInfo->pwszName);
  1214. REQUIRE_ALLOC(bstrItemName, hr, "AddObject");
  1215. //
  1216. // Make sure there is no filename extension in the name
  1217. //
  1218. if (wcschr(bstrItemFullName, L'.'))
  1219. {
  1220. wiauDbgError("AddObject", "Item names must not contain filename extensions");
  1221. hr = E_FAIL;
  1222. goto Cleanup;
  1223. }
  1224. //
  1225. // Set the item's type
  1226. //
  1227. switch (pItemInfo->iType) {
  1228. case WiaMCamTypeFolder:
  1229. lItemType = ITEMTYPE_FOLDER;
  1230. break;
  1231. case WiaMCamTypeImage:
  1232. lItemType = ITEMTYPE_IMAGE;
  1233. break;
  1234. case WiaMCamTypeAudio:
  1235. lItemType = ITEMTYPE_AUDIO;
  1236. break;
  1237. case WiaMCamTypeVideo:
  1238. lItemType = ITEMTYPE_VIDEO;
  1239. break;
  1240. default:
  1241. lItemType = ITEMTYPE_FILE;
  1242. break;
  1243. }
  1244. //
  1245. // See if the item has attachments
  1246. //
  1247. if (pItemInfo->bHasAttachments)
  1248. lItemType |= WiaItemTypeHasAttachments;
  1249. //
  1250. // Create the driver item
  1251. //
  1252. hr = wiasCreateDrvItem(lItemType,
  1253. bstrItemName,
  1254. bstrItemFullName,
  1255. (IWiaMiniDrv *)this,
  1256. sizeof(ITEM_CONTEXT),
  1257. (BYTE **) &pItemCtx,
  1258. &pItem);
  1259. REQUIRE_SUCCESS(hr, "AddObject", "wiasCreateDrvItem failed");
  1260. //
  1261. // Fill in the driver item context. Wait until the thumbnail is requested before
  1262. // reading it in.
  1263. //
  1264. memset(pItemCtx, 0, sizeof(ITEM_CONTEXT));
  1265. pItemCtx->pItemInfo = pItemInfo;
  1266. //
  1267. // Put a pointer to the driver item in the item info structure
  1268. //
  1269. pItemInfo->pDrvItem = pItem;
  1270. Cleanup:
  1271. if (bstrItemFullName)
  1272. SysFreeString(bstrItemFullName);
  1273. if (bstrItemName)
  1274. SysFreeString(bstrItemName);
  1275. return hr;
  1276. }
  1277. /**************************************************************************\
  1278. * ConstructFullName
  1279. *
  1280. * Helper function for creating the item's full name
  1281. *
  1282. * Arguments:
  1283. *
  1284. * pItemInfo - Pointer to the item info structure
  1285. * pwszFullName - Pointer to area to construct name
  1286. * cchFullNameSize - size (in characters) of buffer provided in pwszFullName
  1287. *
  1288. \**************************************************************************/
  1289. HRESULT CWiaCameraDevice::ConstructFullName(MCAM_ITEM_INFO *pItemInfo,
  1290. WCHAR *pwszFullName,
  1291. INT cchFullNameSize)
  1292. {
  1293. DBG_FN("CWiaCameraDevice::ConstructFullName");
  1294. HRESULT hr = S_OK;
  1295. if (!pItemInfo)
  1296. {
  1297. wiauDbgError("ConstructFullName", "pItemInfo arg is NULL");
  1298. return E_INVALIDARG;
  1299. }
  1300. if (pItemInfo->pParent)
  1301. {
  1302. hr = ConstructFullName(pItemInfo->pParent, pwszFullName, cchFullNameSize);
  1303. }
  1304. else
  1305. {
  1306. if (lstrlenW(m_bstrRootFullItemName) < cchFullNameSize)
  1307. {
  1308. lstrcpyW(pwszFullName, m_bstrRootFullItemName);
  1309. }
  1310. else
  1311. {
  1312. hr = E_FAIL;
  1313. }
  1314. }
  1315. if (SUCCEEDED(hr) && pItemInfo->pwszName)
  1316. {
  1317. //
  1318. // Verify that buffer is big enough to accommodate both strings + "\" + terminating zero
  1319. //
  1320. if (lstrlenW(pwszFullName) + lstrlenW(pItemInfo->pwszName) + 2 <= cchFullNameSize)
  1321. {
  1322. lstrcatW(pwszFullName, L"\\");
  1323. lstrcatW(pwszFullName, pItemInfo->pwszName);
  1324. }
  1325. else
  1326. {
  1327. hr = E_FAIL; // buffer is not big enough
  1328. }
  1329. }
  1330. return hr;
  1331. }
  1332. /**************************************************************************\
  1333. * LinkToParent
  1334. *
  1335. * Helper function to link an item to its parent in the item tree
  1336. *
  1337. * Arguments:
  1338. *
  1339. * pItemInfo - Pointer to the item info structure
  1340. * bQueueEvent - Indicates whether to queue an WIA event
  1341. *
  1342. \**************************************************************************/
  1343. HRESULT CWiaCameraDevice::LinkToParent(MCAM_ITEM_INFO *pItemInfo, BOOL bQueueEvent)
  1344. {
  1345. DBG_FN("CWiaCameraDevice::LinkToParent");
  1346. HRESULT hr = S_OK;
  1347. //
  1348. // Locals
  1349. //
  1350. IWiaDrvItem *pParentDrvItem = NULL;
  1351. IWiaDrvItem *pItem = NULL;
  1352. BSTR bstrItemFullName = NULL;
  1353. REQUIRE_ARGS(!pItemInfo, hr, "LinkToParent");
  1354. //
  1355. // Retrieve the driver item and make sure it's not null
  1356. //
  1357. pItem = pItemInfo->pDrvItem;
  1358. if (!pItem) {
  1359. wiauDbgError("LinkToParent", "Driver item pointer is null");
  1360. hr = E_FAIL;
  1361. goto Cleanup;
  1362. }
  1363. //
  1364. // Find the item's parent driver item object
  1365. //
  1366. if (pItemInfo->pParent) {
  1367. pParentDrvItem = pItemInfo->pParent->pDrvItem;
  1368. }
  1369. else {
  1370. //
  1371. // If the parent pointer is null, use the root as the parent
  1372. //
  1373. pParentDrvItem = m_pRootItem;
  1374. }
  1375. //
  1376. // The driver item should exist for the parent, but just make sure
  1377. //
  1378. if (!pParentDrvItem) {
  1379. wiauDbgError("LinkToParent", "Parent driver item is null");
  1380. hr = E_FAIL;
  1381. goto Cleanup;
  1382. }
  1383. //
  1384. // Place the item under it's parent
  1385. //
  1386. hr = pItem->AddItemToFolder(pParentDrvItem);
  1387. REQUIRE_SUCCESS(hr, "LinkToParent", "AddItemToFolder failed");
  1388. //
  1389. // The minidriver doesn't need the driver item pointer any more, so release it.
  1390. // The service will still keep a reference until the item is deleted.
  1391. //
  1392. pItem->Release();
  1393. //
  1394. // Post an item added event, if requested
  1395. //
  1396. if (bQueueEvent)
  1397. {
  1398. hr = pItem->GetFullItemName(&bstrItemFullName);
  1399. REQUIRE_SUCCESS(hr, "LinkToParent", "GetFullItemName failed");
  1400. hr = wiasQueueEvent(m_bstrDeviceID, &WIA_EVENT_ITEM_CREATED, bstrItemFullName);
  1401. REQUIRE_SUCCESS(hr, "LinkToParent", "wiasQueueEvent failed");
  1402. }
  1403. Cleanup:
  1404. if (bstrItemFullName)
  1405. SysFreeString(bstrItemFullName);
  1406. return hr;
  1407. }
  1408. /**************************************************************************\
  1409. * GetOLESTRResourceString
  1410. *
  1411. * This helper gets a LPOLESTR from a resource location
  1412. *
  1413. * Arguments:
  1414. *
  1415. * lResourceID - Resource ID of the target BSTR value
  1416. * ppsz - pointer to a OLESTR value (caller must free this string with CoTaskMemFree)
  1417. *
  1418. * Return Value:
  1419. *
  1420. * Status
  1421. *
  1422. \**************************************************************************/
  1423. HRESULT CWiaCameraDevice::GetOLESTRResourceString(LONG lResourceID, LPOLESTR *ppsz)
  1424. {
  1425. DBG_FN("GetOLESTRResourceString");
  1426. if (!ppsz)
  1427. {
  1428. return E_INVALIDARG;
  1429. }
  1430. HRESULT hr = S_OK;
  1431. TCHAR tszStringValue[255];
  1432. if (LoadString(g_hInst, lResourceID, tszStringValue, 255) == 0)
  1433. {
  1434. hr = HRESULT_FROM_WIN32(::GetLastError());
  1435. goto Cleanup;
  1436. }
  1437. #ifdef UNICODE
  1438. //
  1439. // just allocate memory and copy string
  1440. //
  1441. *ppsz = NULL;
  1442. *ppsz = (LPOLESTR)CoTaskMemAlloc(sizeof(tszStringValue));
  1443. if (*ppsz != NULL)
  1444. {
  1445. wcscpy(*ppsz, tszStringValue);
  1446. }
  1447. else
  1448. {
  1449. hr = E_OUTOFMEMORY;
  1450. goto Cleanup;
  1451. }
  1452. #else
  1453. WCHAR wszStringValue[255];
  1454. //
  1455. // convert szStringValue from char* to unsigned short* (ANSI only)
  1456. //
  1457. if (!MultiByteToWideChar(CP_ACP,
  1458. MB_PRECOMPOSED,
  1459. tszStringValue,
  1460. lstrlenA(tszStringValue)+1,
  1461. wszStringValue,
  1462. (sizeof(wszStringValue)/sizeof(wszStringValue[0]))))
  1463. {
  1464. hr = HRESULT_FROM_WIN32(::GetLastError());
  1465. goto Cleanup;
  1466. }
  1467. *ppsz = NULL;
  1468. *ppsz = (LPOLESTR)CoTaskMemAlloc(sizeof(wszStringValue));
  1469. if (*ppsz != NULL)
  1470. {
  1471. wcscpy(*ppsz,wszStringValue);
  1472. }
  1473. else
  1474. {
  1475. hr = E_OUTOFMEMORY;
  1476. goto Cleanup;
  1477. }
  1478. #endif
  1479. Cleanup:
  1480. return hr;
  1481. }
  1482. /**************************************************************************\
  1483. * BuildCapabilities
  1484. *
  1485. * This helper initializes the capabilities array
  1486. *
  1487. * Arguments:
  1488. *
  1489. * none
  1490. *
  1491. \**************************************************************************/
  1492. HRESULT CWiaCameraDevice::BuildCapabilities()
  1493. {
  1494. DBG_FN("BuildCapabilities");
  1495. HRESULT hr = S_OK;
  1496. if (m_pCapabilities != NULL) {
  1497. //
  1498. // Capabilities have already been initialized,
  1499. // so return S_OK.
  1500. //
  1501. return hr;
  1502. }
  1503. m_lNumSupportedCommands = 1;
  1504. m_lNumSupportedEvents = 3;
  1505. m_lNumCapabilities = (m_lNumSupportedCommands + m_lNumSupportedEvents);
  1506. m_pCapabilities = new WIA_DEV_CAP_DRV[m_lNumCapabilities];
  1507. REQUIRE_ALLOC(m_pCapabilities, hr, "BuildCapabilities");
  1508. //
  1509. // Initialize EVENTS
  1510. //
  1511. //
  1512. // WIA_EVENT_DEVICE_CONNECTED
  1513. //
  1514. hr = GetOLESTRResourceString(IDS_EVENT_DEVICE_CONNECTED_NAME, &m_pCapabilities[0].wszName);
  1515. REQUIRE_SUCCESS(hr, "BuildCapabilities", "GetOLESTRResourceString failed");
  1516. hr = GetOLESTRResourceString(IDS_EVENT_DEVICE_CONNECTED_DESC, &m_pCapabilities[0].wszDescription);
  1517. REQUIRE_SUCCESS(hr, "BuildCapabilities", "GetOLESTRResourceString failed");
  1518. m_pCapabilities[0].guid = (GUID*)&WIA_EVENT_DEVICE_CONNECTED;
  1519. m_pCapabilities[0].ulFlags = WIA_NOTIFICATION_EVENT;
  1520. m_pCapabilities[0].wszIcon = WIA_ICON_DEVICE_CONNECTED;
  1521. //
  1522. // WIA_EVENT_DEVICE_DISCONNECTED
  1523. //
  1524. hr = GetOLESTRResourceString(IDS_EVENT_DEVICE_DISCONNECTED_NAME, &m_pCapabilities[1].wszName);
  1525. REQUIRE_SUCCESS(hr, "BuildCapabilities", "GetOLESTRResourceString failed");
  1526. hr = GetOLESTRResourceString(IDS_EVENT_DEVICE_DISCONNECTED_DESC, &m_pCapabilities[1].wszDescription);
  1527. REQUIRE_SUCCESS(hr, "BuildCapabilities", "GetOLESTRResourceString failed");
  1528. m_pCapabilities[1].guid = (GUID*)&WIA_EVENT_DEVICE_DISCONNECTED;
  1529. m_pCapabilities[1].ulFlags = WIA_NOTIFICATION_EVENT;
  1530. m_pCapabilities[1].wszIcon = WIA_ICON_DEVICE_DISCONNECTED;
  1531. //
  1532. // WIA_EVENT_ITEM_DELETED
  1533. //
  1534. hr = GetOLESTRResourceString(IDS_EVENT_ITEM_DELETED_NAME, &m_pCapabilities[2].wszName);
  1535. REQUIRE_SUCCESS(hr, "BuildCapabilities", "GetOLESTRResourceString failed");
  1536. hr = GetOLESTRResourceString(IDS_EVENT_ITEM_DELETED_DESC, &m_pCapabilities[2].wszDescription);
  1537. REQUIRE_SUCCESS(hr, "BuildCapabilities", "GetOLESTRResourceString failed");
  1538. m_pCapabilities[2].guid = (GUID*)&WIA_EVENT_ITEM_DELETED;
  1539. m_pCapabilities[2].ulFlags = WIA_NOTIFICATION_EVENT;
  1540. m_pCapabilities[2].wszIcon = WIA_ICON_ITEM_DELETED;
  1541. //
  1542. // Initialize COMMANDS
  1543. //
  1544. //
  1545. // WIA_CMD_SYNCHRONIZE
  1546. //
  1547. hr = GetOLESTRResourceString(IDS_CMD_SYNCRONIZE_NAME, &m_pCapabilities[3].wszName);
  1548. REQUIRE_SUCCESS(hr, "BuildCapabilities", "GetOLESTRResourceString failed");
  1549. hr = GetOLESTRResourceString(IDS_CMD_SYNCRONIZE_DESC, &m_pCapabilities[3].wszDescription);
  1550. REQUIRE_SUCCESS(hr, "BuildCapabilities", "GetOLESTRResourceString failed");
  1551. m_pCapabilities[3].guid = (GUID*)&WIA_CMD_SYNCHRONIZE;
  1552. m_pCapabilities[3].ulFlags = 0;
  1553. m_pCapabilities[3].wszIcon = WIA_ICON_SYNCHRONIZE;
  1554. Cleanup:
  1555. return hr;
  1556. }
  1557. /**************************************************************************\
  1558. * DeleteCapabilitiesArrayContents
  1559. *
  1560. * This helper deletes the capabilities array
  1561. *
  1562. * Arguments:
  1563. *
  1564. * none
  1565. *
  1566. \**************************************************************************/
  1567. HRESULT CWiaCameraDevice::DeleteCapabilitiesArrayContents()
  1568. {
  1569. DBG_FN("DeleteCapabilitiesArrayContents");
  1570. HRESULT hr = S_OK;
  1571. if (m_pCapabilities) {
  1572. for (LONG i = 0; i < m_lNumCapabilities; i++)
  1573. {
  1574. CoTaskMemFree(m_pCapabilities[i].wszName);
  1575. CoTaskMemFree(m_pCapabilities[i].wszDescription);
  1576. }
  1577. delete []m_pCapabilities;
  1578. m_pCapabilities = NULL;
  1579. }
  1580. m_lNumSupportedCommands = 0;
  1581. m_lNumSupportedEvents = 0;
  1582. m_lNumCapabilities = 0;
  1583. return hr;
  1584. }