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.

1110 lines
35 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT 2001, MICROSOFT CORP.
  4. *
  5. * TITLE: Child.cpp
  6. *
  7. * VERSION: 1.0
  8. *
  9. * DATE: 15 Nov, 2000
  10. *
  11. * DESCRIPTION:
  12. * This file implements the helper methods for IWiaMiniDrv for child items.
  13. *
  14. *******************************************************************************/
  15. #include "pch.h"
  16. // extern FORMAT_INFO *g_FormatInfo;
  17. // extern UINT g_NumFormatInfo;
  18. /**************************************************************************\
  19. * BuildChildItemProperties
  20. *
  21. * This helper creates the properties for a child item.
  22. *
  23. * Arguments:
  24. *
  25. * pWiasContext - WIA service context
  26. *
  27. \**************************************************************************/
  28. HRESULT CWiaCameraDevice::BuildChildItemProperties(
  29. BYTE *pWiasContext
  30. )
  31. {
  32. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  33. WIALOG_NO_RESOURCE_ID,
  34. WIALOG_LEVEL1,
  35. "CWiaCameraDevice::BuildChildItemProperties");
  36. HRESULT hr = S_OK;
  37. BOOL bBitmap;
  38. FORMAT_INFO *pFormatInfo;
  39. LONG pTymedArray[] = { TYMED_FILE, TYMED_CALLBACK };
  40. GUID *pFormatArray = NULL;
  41. BSTR bstrFileExt = NULL;
  42. //
  43. // Get the driver item context
  44. //
  45. ITEM_CONTEXT *pItemCtx;
  46. hr = GetDrvItemContext(pWiasContext, &pItemCtx);
  47. if (FAILED(hr))
  48. {
  49. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildChildItemProperties, GetDrvItemContext failed"));
  50. return hr;
  51. }
  52. ITEM_INFO *pItemInfo = pItemCtx->ItemHandle;
  53. //
  54. // Set up properties that are used for all item types
  55. //
  56. CWiauPropertyList ItemProps;
  57. const INT NUM_ITEM_PROPS = 21;
  58. hr = ItemProps.Init(NUM_ITEM_PROPS);
  59. if (FAILED(hr))
  60. {
  61. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildChildItemProperties, iten prop Init failed"));
  62. WIAS_LHRESULT(m_pIWiaLog, hr);
  63. return hr;
  64. }
  65. INT index;
  66. //
  67. // WIA_IPA_ITEM_TIME
  68. //
  69. hr = ItemProps.DefineProperty(&index, WIA_IPA_ITEM_TIME, WIA_IPA_ITEM_TIME_STR,
  70. WIA_PROP_READ, WIA_PROP_NONE);
  71. if (FAILED(hr)) goto failure;
  72. ItemProps.SetCurrentValue(index, &pItemInfo->Time);
  73. //
  74. // WIA_IPA_ACCESS_RIGHTS
  75. //
  76. hr = ItemProps.DefineProperty(&index, WIA_IPA_ACCESS_RIGHTS, WIA_IPA_ACCESS_RIGHTS_STR,
  77. WIA_PROP_READ, WIA_PROP_FLAG);
  78. if (FAILED(hr)) goto failure;
  79. //
  80. // If device supports changing the read-only status, item access rights is r/w
  81. //
  82. LONG AccessRights;
  83. if (pItemInfo->bReadOnly)
  84. AccessRights = WIA_ITEM_READ;
  85. else
  86. AccessRights = WIA_ITEM_RD;
  87. if (pItemInfo->bCanSetReadOnly)
  88. {
  89. ItemProps.SetAccessSubType(index, WIA_PROP_RW, WIA_PROP_FLAG);
  90. ItemProps.SetValidValues(index, AccessRights, AccessRights, WIA_ITEM_RD);
  91. }
  92. else
  93. {
  94. ItemProps.SetCurrentValue(index, AccessRights);
  95. }
  96. //
  97. // Set up non-folder properties
  98. //
  99. if (!(pItemInfo->bIsFolder))
  100. {
  101. //
  102. // WIA_IPA_PREFERRED_FORMAT
  103. //
  104. pFormatInfo = FormatCode2FormatInfo(pItemInfo->Format);
  105. hr = ItemProps.DefineProperty(&index, WIA_IPA_PREFERRED_FORMAT, WIA_IPA_PREFERRED_FORMAT_STR,
  106. WIA_PROP_READ, WIA_PROP_NONE);
  107. if (FAILED(hr)) goto failure;
  108. ItemProps.SetCurrentValue(index, &(pFormatInfo->FormatGuid));
  109. bBitmap = IsEqualGUID(WiaImgFmt_BMP, pFormatInfo->FormatGuid);
  110. //
  111. // WIA_IPA_FILENAME_EXTENSION
  112. //
  113. hr = ItemProps.DefineProperty(&index, WIA_IPA_FILENAME_EXTENSION, WIA_IPA_FILENAME_EXTENSION_STR,
  114. WIA_PROP_READ, WIA_PROP_NONE);
  115. if (FAILED(hr)) goto failure;
  116. if( pFormatInfo->ExtensionString[0] )
  117. {
  118. bstrFileExt = SysAllocString(pFormatInfo->ExtensionString);
  119. }
  120. else // unknown file extension, get it from filename
  121. {
  122. WCHAR *pwcsTemp = wcsrchr(pItemInfo->pName, L'.');
  123. if( pwcsTemp )
  124. {
  125. bstrFileExt = SysAllocString(pwcsTemp+1);
  126. }
  127. else
  128. {
  129. bstrFileExt = SysAllocString(pFormatInfo->ExtensionString);
  130. }
  131. }
  132. ItemProps.SetCurrentValue(index, bstrFileExt);
  133. //
  134. // WIA_IPA_TYMED
  135. //
  136. hr = ItemProps.DefineProperty(&index, WIA_IPA_TYMED, WIA_IPA_TYMED_STR,
  137. WIA_PROP_RW, WIA_PROP_LIST);
  138. if (FAILED(hr)) goto failure;
  139. ItemProps.SetValidValues(index, TYMED_FILE, TYMED_FILE,
  140. sizeof(pTymedArray) / sizeof(pTymedArray[0]), pTymedArray);
  141. //
  142. // WIA_IPA_FORMAT
  143. //
  144. // First call drvGetWiaFormatInfo to get the valid formats
  145. //
  146. int NumFormats = 0;
  147. GUID *pFormatArray = NULL;
  148. hr = GetValidFormats(pWiasContext, TYMED_FILE, &NumFormats, &pFormatArray);
  149. if (FAILED(hr) || NumFormats == 0)
  150. {
  151. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildChildItemProperties, GetValidFormats failed"));
  152. goto failure;
  153. }
  154. hr = ItemProps.DefineProperty(&index, WIA_IPA_FORMAT, WIA_IPA_FORMAT_STR,
  155. WIA_PROP_RW, WIA_PROP_LIST);
  156. if (FAILED(hr)) goto failure;
  157. ItemProps.SetValidValues(index, &(pFormatInfo->FormatGuid), &(pFormatInfo->FormatGuid),
  158. NumFormats, &pFormatArray);
  159. //
  160. // WIA_IPA_COMPRESSION
  161. //
  162. // This property is mainly used by scanners. Set to no compression.
  163. //
  164. hr = ItemProps.DefineProperty(&index, WIA_IPA_COMPRESSION, WIA_IPA_COMPRESSION_STR,
  165. WIA_PROP_READ, WIA_PROP_NONE);
  166. if (FAILED(hr)) goto failure;
  167. ItemProps.SetCurrentValue(index, (LONG) WIA_COMPRESSION_NONE);
  168. //
  169. // WIA_IPA_ITEM_SIZE
  170. //
  171. hr = ItemProps.DefineProperty(&index, WIA_IPA_ITEM_SIZE, WIA_IPA_ITEM_SIZE_STR,
  172. WIA_PROP_READ, WIA_PROP_NONE);
  173. if (FAILED(hr)) goto failure;
  174. ItemProps.SetCurrentValue(index, pItemInfo->Size);
  175. //
  176. // WIA_IPA_MIN_BUFFER_SIZE
  177. //
  178. hr = ItemProps.DefineProperty(&index, WIA_IPA_MIN_BUFFER_SIZE, WIA_IPA_MIN_BUFFER_SIZE_STR,
  179. WIA_PROP_READ, WIA_PROP_NONE);
  180. if (FAILED(hr)) goto failure;
  181. LONG minBufSize;
  182. if (!bBitmap && pItemInfo->Size > 0)
  183. minBufSize = min(MIN_BUFFER_SIZE, pItemInfo->Size);
  184. else
  185. minBufSize = MIN_BUFFER_SIZE;
  186. ItemProps.SetCurrentValue(index, minBufSize);
  187. }
  188. //
  189. // Set up the image-only properties
  190. //
  191. if (m_FormatInfo[pItemInfo->Format].ItemType == ITEMTYPE_IMAGE)
  192. {
  193. //
  194. // WIA_IPA_DATATYPE
  195. //
  196. // This property is mainly used by scanners. Set to color since most camera
  197. // images will be color.
  198. //
  199. hr = ItemProps.DefineProperty(&index, WIA_IPA_DATATYPE, WIA_IPA_DATATYPE_STR,
  200. WIA_PROP_READ, WIA_PROP_NONE);
  201. if (FAILED(hr)) goto failure;
  202. ItemProps.SetCurrentValue(index, (LONG) WIA_DATA_COLOR);
  203. //
  204. // WIA_IPA_PLANAR
  205. //
  206. hr = ItemProps.DefineProperty(&index, WIA_IPA_PLANAR, WIA_IPA_PLANAR_STR,
  207. WIA_PROP_READ, WIA_PROP_NONE);
  208. if (FAILED(hr)) goto failure;
  209. ItemProps.SetCurrentValue(index, (LONG) WIA_PACKED_PIXEL);
  210. //
  211. // WIA_IPA_DEPTH
  212. //
  213. hr = ItemProps.DefineProperty(&index, WIA_IPA_DEPTH, WIA_IPA_DEPTH_STR,
  214. WIA_PROP_READ, WIA_PROP_NONE);
  215. if (FAILED(hr)) goto failure;
  216. ItemProps.SetCurrentValue(index, pItemInfo->Depth);
  217. //
  218. // WIA_IPA_CHANNELS_PER_PIXEL
  219. //
  220. hr = ItemProps.DefineProperty(&index, WIA_IPA_CHANNELS_PER_PIXEL, WIA_IPA_CHANNELS_PER_PIXEL_STR,
  221. WIA_PROP_READ, WIA_PROP_NONE);
  222. if (FAILED(hr)) goto failure;
  223. ItemProps.SetCurrentValue(index, pItemInfo->Channels);
  224. //
  225. // WIA_IPA_BITS_PER_CHANNEL
  226. //
  227. hr = ItemProps.DefineProperty(&index, WIA_IPA_BITS_PER_CHANNEL, WIA_IPA_BITS_PER_CHANNEL_STR,
  228. WIA_PROP_READ, WIA_PROP_NONE);
  229. if (FAILED(hr)) goto failure;
  230. ItemProps.SetCurrentValue(index, pItemInfo->BitsPerChannel);
  231. //
  232. // WIA_IPA_PIXELS_PER_LINE
  233. //
  234. hr = ItemProps.DefineProperty(&index, WIA_IPA_PIXELS_PER_LINE, WIA_IPA_PIXELS_PER_LINE_STR,
  235. WIA_PROP_READ, WIA_PROP_NONE);
  236. if (FAILED(hr)) goto failure;
  237. ItemProps.SetCurrentValue(index, pItemInfo->Width);
  238. //
  239. // WIA_IPA_BYTES_PER_LINE
  240. //
  241. hr = ItemProps.DefineProperty(&index, WIA_IPA_BYTES_PER_LINE, WIA_IPA_BYTES_PER_LINE_STR,
  242. WIA_PROP_READ, WIA_PROP_NONE);
  243. if (FAILED(hr)) goto failure;
  244. if (bBitmap)
  245. ItemProps.SetCurrentValue(index, pItemInfo->Width * 3);
  246. else
  247. ItemProps.SetCurrentValue(index, (LONG) 0);
  248. //
  249. // WIA_IPA_NUMBER_OF_LINES
  250. //
  251. hr = ItemProps.DefineProperty(&index, WIA_IPA_NUMBER_OF_LINES, WIA_IPA_NUMBER_OF_LINES_STR,
  252. WIA_PROP_READ, WIA_PROP_NONE);
  253. if (FAILED(hr)) goto failure;
  254. ItemProps.SetCurrentValue(index, pItemInfo->Height);
  255. //
  256. // WIA_IPC_THUMBNAIL
  257. //
  258. hr = ItemProps.DefineProperty(&index, WIA_IPC_THUMBNAIL, WIA_IPC_THUMBNAIL_STR,
  259. WIA_PROP_READ, WIA_PROP_NONE);
  260. if (FAILED(hr)) goto failure;
  261. ItemProps.SetCurrentValue(index, (BYTE *) NULL, 0);
  262. //
  263. // WIA_IPC_THUMB_WIDTH
  264. //
  265. // This field is probably zero until the thumbnail is read in, but set it anyway
  266. //
  267. hr = ItemProps.DefineProperty(&index, WIA_IPC_THUMB_WIDTH, WIA_IPC_THUMB_WIDTH_STR,
  268. WIA_PROP_READ, WIA_PROP_NONE);
  269. if (FAILED(hr)) goto failure;
  270. ItemProps.SetCurrentValue(index, pItemInfo->ThumbWidth);
  271. //
  272. // WIA_IPC_THUMB_HEIGHT
  273. //
  274. // This field is probably zero until the thumbnail is read in, but set it anyway
  275. //
  276. hr = ItemProps.DefineProperty(&index, WIA_IPC_THUMB_HEIGHT, WIA_IPC_THUMB_HEIGHT_STR,
  277. WIA_PROP_READ, WIA_PROP_NONE);
  278. if (FAILED(hr)) goto failure;
  279. ItemProps.SetCurrentValue(index, pItemInfo->ThumbHeight);
  280. //
  281. // WIA_IPC_SEQUENCE
  282. //
  283. if (pItemInfo->SequenceNum > 0)
  284. {
  285. hr = ItemProps.DefineProperty(&index, WIA_IPC_SEQUENCE, WIA_IPC_SEQUENCE_STR,
  286. WIA_PROP_READ, WIA_PROP_NONE);
  287. if (FAILED(hr)) goto failure;
  288. ItemProps.SetCurrentValue(index, pItemInfo->SequenceNum);
  289. }
  290. }
  291. // For video
  292. #if 1
  293. if( ( pItemInfo->Format < (FORMAT_CODE)m_NumFormatInfo) &&
  294. (ITEMTYPE_VIDEO == m_FormatInfo[pItemInfo->Format].ItemType) )
  295. {
  296. //
  297. // WIA_IPC_THUMBNAIL
  298. //
  299. hr = ItemProps.DefineProperty(&index, WIA_IPC_THUMBNAIL, WIA_IPC_THUMBNAIL_STR,
  300. WIA_PROP_READ, WIA_PROP_NONE);
  301. if (FAILED(hr)) goto failure;
  302. ItemProps.SetCurrentValue(index, (BYTE *) NULL, 0);
  303. //
  304. // WIA_IPC_THUMB_WIDTH
  305. //
  306. // This field is probably zero until the thumbnail is read in, but set it anyway
  307. //
  308. hr = ItemProps.DefineProperty(&index, WIA_IPC_THUMB_WIDTH, WIA_IPC_THUMB_WIDTH_STR,
  309. WIA_PROP_READ, WIA_PROP_NONE);
  310. if (FAILED(hr)) goto failure;
  311. ItemProps.SetCurrentValue(index, pItemInfo->ThumbWidth);
  312. //
  313. // WIA_IPC_THUMB_HEIGHT
  314. //
  315. // This field is probably zero until the thumbnail is read in, but set it anyway
  316. //
  317. hr = ItemProps.DefineProperty(&index, WIA_IPC_THUMB_HEIGHT, WIA_IPC_THUMB_HEIGHT_STR,
  318. WIA_PROP_READ, WIA_PROP_NONE);
  319. if (FAILED(hr)) goto failure;
  320. ItemProps.SetCurrentValue(index, pItemInfo->ThumbHeight);
  321. }
  322. #endif
  323. //
  324. // Last step: send all the properties to WIA
  325. //
  326. hr = ItemProps.SendToWia(pWiasContext);
  327. if (FAILED(hr))
  328. {
  329. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildChildItemProperties, SendToWia failed"));
  330. WIAS_LHRESULT(m_pIWiaLog, hr);
  331. }
  332. // Nb: hr is used for routine return code - careful to not overwrite it from here till return statement
  333. if (bstrFileExt) {
  334. SysFreeString(bstrFileExt);
  335. bstrFileExt = NULL;
  336. }
  337. if (pFormatArray)
  338. delete []pFormatArray;
  339. return hr;
  340. //
  341. // Any failures from DefineProperty will end up here
  342. //
  343. failure:
  344. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildChildItemProperties, DefineProperty failed"));
  345. WIAS_LHRESULT(m_pIWiaLog, hr);
  346. if (bstrFileExt) {
  347. SysFreeString(bstrFileExt);
  348. bstrFileExt = NULL;
  349. }
  350. if (pFormatArray)
  351. delete []pFormatArray;
  352. return hr;
  353. }
  354. /**************************************************************************\
  355. * GetValidFormats
  356. *
  357. * Calls drvGetWiaFormatInfo and makes a list of valid formats given
  358. * a tymed value. Caller is responsible for freeing the format array.
  359. *
  360. * Arguments:
  361. *
  362. * pWiasContext - WIA service context
  363. * TymedValue - tymed value to search for
  364. * pNumFormats - pointer to value to receive number of formats
  365. * ppFormatArray - pointer to a pointer location to receive array address
  366. *
  367. \**************************************************************************/
  368. HRESULT
  369. CWiaCameraDevice::GetValidFormats(
  370. BYTE *pWiasContext,
  371. LONG TymedValue,
  372. int *pNumFormats,
  373. GUID **ppFormatArray
  374. )
  375. {
  376. HRESULT hr = S_OK;
  377. if (!ppFormatArray || !pNumFormats)
  378. {
  379. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetValidFormats, invalid arg"));
  380. return E_INVALIDARG;
  381. }
  382. *ppFormatArray = NULL;
  383. *pNumFormats = 0;
  384. LONG NumFi = 0;
  385. WIA_FORMAT_INFO *pFiArray = NULL;
  386. LONG lErrVal = 0;
  387. hr = drvGetWiaFormatInfo(pWiasContext, 0, &NumFi, &pFiArray, &lErrVal);
  388. if (FAILED(hr))
  389. {
  390. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetValidFormats, drvGetWiaFormatInfo failed"));
  391. return hr;
  392. }
  393. //
  394. // This will allocate more spots than necessary, but pNumFormats will be set correctly
  395. //
  396. GUID *pFA = new GUID[NumFi];
  397. if( !pFA )
  398. return E_OUTOFMEMORY;
  399. for (int count = 0; count < NumFi; count++)
  400. {
  401. if (pFiArray[count].lTymed == TymedValue)
  402. {
  403. pFA[*pNumFormats] = pFiArray[count].guidFormatID;
  404. (*pNumFormats)++;
  405. }
  406. }
  407. *ppFormatArray = pFA;
  408. return hr;
  409. }
  410. /**************************************************************************\
  411. * ReadChildItemProperties
  412. *
  413. * Update the properties for the child items.
  414. *
  415. * Arguments:
  416. *
  417. * pWiasContext - WIA service context
  418. *
  419. \**************************************************************************/
  420. HRESULT
  421. CWiaCameraDevice::ReadChildItemProperties(
  422. BYTE *pWiasContext,
  423. LONG NumPropSpecs,
  424. const PROPSPEC *pPropSpecs
  425. )
  426. {
  427. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  428. WIALOG_NO_RESOURCE_ID,
  429. WIALOG_LEVEL1,
  430. "CWiaCameraDevice::ReadChildItemProperties");
  431. HRESULT hr = S_OK;
  432. if (!NumPropSpecs || !pPropSpecs)
  433. {
  434. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ReadChildItemProperties, invalid arg"));
  435. return E_INVALIDARG;
  436. }
  437. //
  438. // Get the driver item context
  439. //
  440. ITEM_CONTEXT *pItemCtx;
  441. hr = GetDrvItemContext(pWiasContext, &pItemCtx);
  442. if (FAILED(hr))
  443. {
  444. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildChildItemProperties, GetDrvItemContext failed"));
  445. return hr;
  446. }
  447. ITEM_INFO *pItemInfo = pItemCtx->ItemHandle;
  448. //
  449. // The only child property on a camera that could change is the item time
  450. //
  451. if (wiauPropInPropSpec(NumPropSpecs, pPropSpecs, WIA_IPA_ITEM_TIME))
  452. {
  453. PROPVARIANT propVar;
  454. PROPSPEC propSpec;
  455. propVar.vt = VT_VECTOR | VT_UI2;
  456. propVar.caui.cElems = sizeof(SYSTEMTIME) / sizeof(WORD);
  457. propVar.caui.pElems = (WORD *) &pItemInfo->Time;
  458. propSpec.ulKind = PRSPEC_PROPID;
  459. propSpec.propid = WIA_IPA_ITEM_TIME;
  460. hr = wiasWriteMultiple(pWiasContext, 1, &propSpec, &propVar );
  461. if (FAILED(hr))
  462. {
  463. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ReadChildItemProperties, wiasWriteMultiple failed"));
  464. WIAS_LHRESULT(m_pIWiaLog, hr);
  465. return hr;
  466. }
  467. }
  468. //
  469. // For images & video, update the thumbnail properties if requested
  470. //
  471. ULONG uItemType;
  472. uItemType = m_FormatInfo[pItemInfo->Format].ItemType;
  473. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, ("ReadChildItemProperties, File %S, Type =%d", pItemInfo->pName, uItemType));
  474. PROPSPEC propSpecs[9];
  475. PROPVARIANT propVars[9];
  476. UINT nNumProps;
  477. // The following is needed because we delayed parsing these properties until read
  478. if( uItemType == ITEMTYPE_IMAGE || uItemType == ITEMTYPE_VIDEO )
  479. {
  480. //
  481. // Get the thumbnail if requested to update any of the thumbnail properties and
  482. // the thumbnail is not already cached.
  483. //
  484. PROPID propsToUpdate[] = {
  485. WIA_IPA_DEPTH,
  486. WIA_IPA_CHANNELS_PER_PIXEL,
  487. WIA_IPA_BITS_PER_CHANNEL,
  488. WIA_IPA_PIXELS_PER_LINE,
  489. WIA_IPA_BYTES_PER_LINE,
  490. WIA_IPA_NUMBER_OF_LINES,
  491. WIA_IPC_THUMB_WIDTH,
  492. WIA_IPC_THUMB_HEIGHT,
  493. WIA_IPC_THUMBNAIL
  494. };
  495. if (wiauPropsInPropSpec(NumPropSpecs, pPropSpecs, sizeof(propsToUpdate) / sizeof(PROPID), propsToUpdate))
  496. {
  497. if (!pItemCtx->pThumb)
  498. {
  499. hr = CacheThumbnail(pItemCtx, uItemType);
  500. if (FAILED(hr))
  501. {
  502. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ReadChildItemProperties, CacheThumbnail failed"));
  503. pItemInfo->ThumbWidth = 0;
  504. pItemInfo->ThumbHeight = 0;
  505. pItemCtx->ThumbSize = 0;
  506. pItemCtx->pThumb = NULL;
  507. // return hr;
  508. }
  509. }
  510. //
  511. // Update the related thumbnail properties. Update the thumb width and height in case
  512. // the device didn't report them in the ObjectInfo structure (they are optional there).
  513. //
  514. propSpecs[0].ulKind = PRSPEC_PROPID;
  515. propSpecs[0].propid = WIA_IPC_THUMB_WIDTH;
  516. propVars[0].vt = VT_I4;
  517. propVars[0].lVal = pItemInfo->ThumbWidth;
  518. propSpecs[1].ulKind = PRSPEC_PROPID;
  519. propSpecs[1].propid = WIA_IPC_THUMB_HEIGHT;
  520. propVars[1].vt = VT_I4;
  521. propVars[1].lVal = pItemInfo->ThumbHeight;
  522. propSpecs[2].ulKind = PRSPEC_PROPID;
  523. propSpecs[2].propid = WIA_IPC_THUMBNAIL;
  524. propVars[2].vt = VT_VECTOR | VT_UI1;
  525. propVars[2].caub.cElems = pItemCtx->ThumbSize;
  526. propVars[2].caub.pElems = pItemCtx->pThumb;
  527. if( uItemType == ITEMTYPE_IMAGE )
  528. {
  529. propSpecs[3].ulKind = PRSPEC_PROPID;
  530. propSpecs[3].propid = WIA_IPA_DEPTH;
  531. propVars[3].vt = VT_I4;
  532. propVars[3].lVal = pItemInfo->Depth;
  533. propSpecs[4].ulKind = PRSPEC_PROPID;
  534. propSpecs[4].propid = WIA_IPA_CHANNELS_PER_PIXEL;
  535. propVars[4].vt = VT_I4;
  536. propVars[4].lVal = pItemInfo->Channels;
  537. propSpecs[5].ulKind = PRSPEC_PROPID;
  538. propSpecs[5].propid = WIA_IPA_BITS_PER_CHANNEL;
  539. propVars[5].vt = VT_I4;
  540. propVars[5].lVal = pItemInfo->BitsPerChannel;
  541. propSpecs[6].ulKind = PRSPEC_PROPID;
  542. propSpecs[6].propid = WIA_IPA_PIXELS_PER_LINE;
  543. propVars[6].vt = VT_I4;
  544. propVars[6].lVal = pItemInfo->Width;
  545. propSpecs[7].ulKind = PRSPEC_PROPID;
  546. propSpecs[7].propid = WIA_IPA_BYTES_PER_LINE;
  547. propVars[7].vt = VT_I4;
  548. propVars[7].lVal = (pItemInfo->Width * pItemInfo->Depth) >> 3;
  549. propSpecs[8].ulKind = PRSPEC_PROPID;
  550. propSpecs[8].propid = WIA_IPA_NUMBER_OF_LINES;
  551. propVars[8].vt = VT_I4;
  552. propVars[8].lVal = pItemInfo->Height;
  553. nNumProps = 9;
  554. } else {
  555. nNumProps = 3;
  556. }
  557. hr = wiasWriteMultiple(pWiasContext, nNumProps, propSpecs, propVars);
  558. if (FAILED(hr))
  559. {
  560. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ReadChildItemProperties, wiasWriteMultiple for size properties failed"));
  561. WIAS_LHRESULT(m_pIWiaLog, hr);
  562. }
  563. } // end of IF wiauPropsInProp
  564. } // end of IF Image or Video
  565. return hr;
  566. }
  567. //
  568. // This function caches the thumbnail into the given ITEM_CONTEXT
  569. //
  570. // Input:
  571. // pItemCtx -- the designated ITEM_CONTEXT
  572. //
  573. HRESULT
  574. CWiaCameraDevice::CacheThumbnail(ITEM_CONTEXT *pItemCtx, ULONG uItemType)
  575. {
  576. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  577. WIALOG_NO_RESOURCE_ID,
  578. WIALOG_LEVEL1,
  579. "CWiaCameraDevice::CacheThumbnail");
  580. HRESULT hr = S_OK;
  581. //
  582. // Local variables
  583. //
  584. ITEM_INFO *pItemInfo = NULL;
  585. BYTE *pDest = NULL;
  586. INT iThumbSize = 0;
  587. BYTE *pNativeThumb = NULL;
  588. BOOL bGotNativeThumbnail=TRUE;
  589. BMP_IMAGE_INFO BmpImageInfo;
  590. INT iSize=0;
  591. //
  592. // Check arguments
  593. //
  594. if (!pItemCtx)
  595. {
  596. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CacheThumbnail, invalid arg"));
  597. hr = E_INVALIDARG;
  598. goto Cleanup;
  599. }
  600. //
  601. // Make sure thumbnail isn't already created
  602. //
  603. if (pItemCtx->pThumb)
  604. {
  605. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CacheThumbnail, thumbnail is already cached"));
  606. hr = E_FAIL;
  607. goto Cleanup;
  608. }
  609. //
  610. // Get the thumbnail from the camera in it's native format
  611. //
  612. pItemInfo = pItemCtx->ItemHandle;
  613. pItemInfo->ThumbWidth = 0;
  614. pItemInfo->ThumbHeight = 0;
  615. pItemCtx->ThumbSize = 0;
  616. pItemCtx->pThumb = NULL;
  617. pDest=NULL;
  618. iSize=0;
  619. if( uItemType == ITEMTYPE_VIDEO )
  620. {
  621. hr = m_pDevice->CreateVideoThumbnail(pItemInfo, &iSize, &pDest, &BmpImageInfo);
  622. }
  623. else
  624. {
  625. hr = m_pDevice->CreateThumbnail(pItemInfo, &iSize, &pDest, &BmpImageInfo);
  626. }
  627. if (FAILED(hr))
  628. {
  629. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CacheThumbnail, CreateThumbnail failed"));
  630. goto Cleanup;
  631. }
  632. pItemInfo->ThumbWidth = BmpImageInfo.Width;
  633. pItemInfo->ThumbHeight = BmpImageInfo.Height;
  634. // pItemInfo->ThumbFormat = TYPE_BMP;
  635. //
  636. // Cache the buffer returned from ConvertToBmp in the driver item context. Set pDest
  637. // to NULL, so it won't be freed below.
  638. //
  639. pItemCtx->ThumbSize = iSize;
  640. pItemCtx->pThumb = pDest;
  641. pDest = NULL;
  642. Cleanup:
  643. if (pNativeThumb) {
  644. delete []pNativeThumb;
  645. pNativeThumb = NULL;
  646. }
  647. if (pDest) {
  648. delete []pDest;
  649. pDest = NULL;
  650. }
  651. return hr;
  652. }
  653. //
  654. // This function transfers native data to the application without translating it.
  655. //
  656. HRESULT
  657. CWiaCameraDevice::AcquireData(
  658. ITEM_CONTEXT *pItemCtx,
  659. PMINIDRV_TRANSFER_CONTEXT pmdtc,
  660. BYTE *pBuf,
  661. LONG lBufSize,
  662. BOOL bConverting
  663. )
  664. {
  665. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  666. WIALOG_NO_RESOURCE_ID,
  667. WIALOG_LEVEL1,
  668. "CWiaCameraDevice::AcquireData");
  669. HRESULT hr = S_OK;
  670. BYTE *pCur = NULL;
  671. LONG lState = STATE_FIRST;
  672. LONG lPercentComplete = 0;
  673. LONG lTotalToRead = pItemCtx->ItemHandle->Size;
  674. LONG lOffset = 0;
  675. DWORD dwBytesToRead = 0;
  676. BOOL bFileTransfer = pmdtc->tymed & TYMED_FILE;
  677. LONG lMessage = 0;
  678. LONG lStatus = 0;
  679. //
  680. // If pBuf is non-null use that as the buffer, otherwise use the buffer
  681. // and size in pmdtc
  682. //
  683. if (pBuf)
  684. {
  685. pCur = pBuf;
  686. dwBytesToRead = lBufSize;
  687. }
  688. else
  689. {
  690. pCur = pmdtc->pTransferBuffer;
  691. dwBytesToRead = pmdtc->lBufferSize;
  692. }
  693. //
  694. // If the transfer size is the entire item, split it into approximately
  695. // 10 equal transfers in order to show progress to the app
  696. //
  697. if (dwBytesToRead == (DWORD) lTotalToRead)
  698. {
  699. dwBytesToRead = (lTotalToRead / 10 + 3) & ~0x3;
  700. }
  701. //
  702. // Set up parameters for the callback function
  703. //
  704. if (bConverting)
  705. {
  706. lMessage = IT_MSG_STATUS;
  707. lStatus = IT_STATUS_TRANSFER_FROM_DEVICE;
  708. }
  709. else if (bFileTransfer)
  710. {
  711. lMessage = IT_MSG_STATUS;
  712. lStatus = IT_STATUS_TRANSFER_TO_CLIENT;
  713. }
  714. else // e.g. memory transfer
  715. {
  716. lMessage = IT_MSG_DATA;
  717. lStatus = IT_STATUS_TRANSFER_TO_CLIENT;
  718. }
  719. //
  720. // Read data until finished
  721. //
  722. while (lOffset < lTotalToRead)
  723. {
  724. //
  725. // If this is the last read, adjust the amount of data to read
  726. // and the state
  727. //
  728. if (dwBytesToRead >= (DWORD) (lTotalToRead - lOffset))
  729. {
  730. dwBytesToRead = (lTotalToRead - lOffset);
  731. lState |= STATE_LAST;
  732. }
  733. //
  734. // Get the data from the camera
  735. //
  736. hr = m_pDevice->GetItemData(pItemCtx->ItemHandle, lState, pCur, dwBytesToRead);
  737. if (FAILED(hr))
  738. {
  739. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("AcquireData, GetItemData failed"));
  740. goto Cleanup;
  741. }
  742. //
  743. // Calculate the percent complete for the callback function. If converting,
  744. // report the percent complete as TRANSFER_PERCENT of the actual. From
  745. // TRANSFER_PERCENT to 100% will be reported during format conversion.
  746. //
  747. if (bConverting)
  748. lPercentComplete = (lOffset + dwBytesToRead) * TRANSFER_PERCENT / lTotalToRead;
  749. else
  750. lPercentComplete = (lOffset + dwBytesToRead) * 100 / lTotalToRead;
  751. //
  752. // Call the callback function to send status and/or data to the app
  753. //
  754. hr = pmdtc->pIWiaMiniDrvCallBack->
  755. MiniDrvCallback(lMessage, lStatus, lPercentComplete,
  756. lOffset, dwBytesToRead, pmdtc, 0);
  757. if (FAILED(hr))
  758. {
  759. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("AcquireData, callback failed"));
  760. goto Cleanup;
  761. }
  762. if (hr == S_FALSE)
  763. {
  764. //
  765. // Transfer is being cancelled by the app
  766. //
  767. WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("AcquireData, transfer cancelled"));
  768. goto Cleanup;
  769. }
  770. //
  771. // Increment buffer pointer only if converting or this is a
  772. // file transfer
  773. //
  774. if (bConverting || bFileTransfer)
  775. {
  776. pCur += dwBytesToRead;
  777. }
  778. //
  779. // For a memory transfer not using a buffer allocated by the minidriver,
  780. // update the buffer pointer and size from the transfer context in case
  781. // of double buffering
  782. //
  783. else if (!pBuf)
  784. {
  785. pCur = pmdtc->pTransferBuffer;
  786. // dwBytesToRead = pmdtc->lBufferSize;
  787. }
  788. //
  789. // Adjust variables for the next iteration
  790. //
  791. lOffset += dwBytesToRead;
  792. lState &= ~STATE_FIRST;
  793. }
  794. //
  795. // For file transfers, write the data to file
  796. //
  797. if (!pBuf && bFileTransfer)
  798. {
  799. //
  800. // Call WIA to write the data to the file
  801. //
  802. hr = wiasWriteBufToFile(0, pmdtc);
  803. if (FAILED(hr))
  804. {
  805. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("AcquireData, wiasWriteBufToFile failed"));
  806. return hr;
  807. }
  808. }
  809. Cleanup:
  810. //
  811. // If the transfer wasn't completed, send cancel to the device
  812. //
  813. if (!(lState & STATE_LAST))
  814. {
  815. lState = STATE_CANCEL;
  816. m_pDevice->GetItemData(pItemCtx->ItemHandle, lState, NULL, 0);
  817. }
  818. return hr;
  819. }
  820. //
  821. // This function translates native data to BMP and sends the data to the app
  822. //
  823. HRESULT
  824. CWiaCameraDevice::Convert(
  825. BYTE *pWiasContext,
  826. ITEM_CONTEXT *pItemCtx,
  827. PMINIDRV_TRANSFER_CONTEXT pmdtc,
  828. BYTE *pNativeImage,
  829. LONG lNativeSize
  830. )
  831. {
  832. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  833. WIALOG_NO_RESOURCE_ID,
  834. WIALOG_LEVEL1,
  835. "CWiaCameraDevice::Convert");
  836. HRESULT hr = S_OK;
  837. //
  838. // Locals
  839. //
  840. LONG lMsg = 0; // Parameter to the callback function
  841. LONG lPercentComplete = 0; // Parameter to the callback function
  842. BOOL bUseAppBuffer = FALSE; // Indicates whether to transfer directly into the app's buffer
  843. BYTE *pBmpBuffer = NULL; // Buffer used to hold converted image
  844. INT iBmpBufferSize = 0; // Size of the converted image buffer
  845. LONG lBytesToCopy = 0;
  846. LONG lOffset = 0;
  847. BYTE *pCurrent = NULL;
  848. BMP_IMAGE_INFO BmpImageInfo;
  849. SKIP_AMOUNT iSkipAmt = SKIP_OFF;
  850. //
  851. // Check arguments
  852. //
  853. if (!pNativeImage)
  854. {
  855. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("Convert, invalid arg"));
  856. hr = E_INVALIDARG;
  857. goto Cleanup;
  858. }
  859. //
  860. // The msg to send to the app via the callback depends on whether
  861. // this is a file or callback transfer
  862. //
  863. lMsg = ((pmdtc->tymed & TYMED_FILE) ? IT_MSG_STATUS : IT_MSG_DATA);
  864. //
  865. // If the class driver allocated a buffer and the buffer is large
  866. // enough, convert directly into that buffer. Otherwise, pass NULL
  867. // to the ConvertToBmp function so that it will allocate a buffer.
  868. //
  869. if (pmdtc->bClassDrvAllocBuf &&
  870. pmdtc->lBufferSize >= pmdtc->lItemSize) {
  871. bUseAppBuffer = TRUE;
  872. pBmpBuffer = pmdtc->pTransferBuffer;
  873. iBmpBufferSize = pmdtc->lBufferSize;
  874. }
  875. //
  876. // Convert the image to BMP. Skip the BMP file header if the app asked
  877. // for a "memory bitmap" (aka DIB).
  878. //
  879. memset(&BmpImageInfo, 0, sizeof(BmpImageInfo));
  880. if (IsEqualGUID(pmdtc->guidFormatID, WiaImgFmt_MEMORYBMP)) {
  881. iSkipAmt = SKIP_FILEHDR;
  882. }
  883. hr = m_Converter.ConvertToBmp(pNativeImage, lNativeSize, &pBmpBuffer,
  884. &iBmpBufferSize, &BmpImageInfo, iSkipAmt);
  885. if (FAILED(hr))
  886. {
  887. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("Convert, ConvertToBmp failed"));
  888. WIAS_LHRESULT(m_pIWiaLog, hr);
  889. goto Cleanup;
  890. }
  891. //
  892. // Send the data to the app. If the class driver allocated the buffer,
  893. // but it was too small, send the data back one chunk at a time.
  894. // Otherwise send all the data back at once.
  895. //
  896. if (pmdtc->bClassDrvAllocBuf &&
  897. pmdtc->lBufferSize < BmpImageInfo.Size) {
  898. pCurrent = pBmpBuffer;
  899. while (lOffset < BmpImageInfo.Size)
  900. {
  901. lBytesToCopy = BmpImageInfo.Size - lOffset;
  902. if (lBytesToCopy > pmdtc->lBufferSize) {
  903. lBytesToCopy = pmdtc->lBufferSize;
  904. //
  905. // Calculate how much of the data has been sent back so far. Report percentages to
  906. // the app between TRANSFER_PERCENT and 100 percent. Make sure it is never larger
  907. // than 99 until the end.
  908. //
  909. lPercentComplete = TRANSFER_PERCENT + ((100 - TRANSFER_PERCENT) * lOffset) / pmdtc->lItemSize;
  910. if (lPercentComplete > 99) {
  911. lPercentComplete = 99;
  912. }
  913. }
  914. //
  915. // This will complete the transfer, so set the percentage to 100
  916. else {
  917. lPercentComplete = 100;
  918. }
  919. memcpy(pmdtc->pTransferBuffer, pCurrent, lBytesToCopy);
  920. //
  921. // Call the application's callback transfer to report status and/or transfer data
  922. //
  923. hr = pmdtc->pIWiaMiniDrvCallBack->MiniDrvCallback(lMsg, IT_STATUS_TRANSFER_TO_CLIENT,
  924. lPercentComplete, lOffset, lBytesToCopy, pmdtc, 0);
  925. if (FAILED(hr))
  926. {
  927. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("Convert, sending data to app failed"));
  928. WIAS_LHRESULT(m_pIWiaLog, hr);
  929. goto Cleanup;
  930. }
  931. if (hr == S_FALSE)
  932. {
  933. WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("Convert, transfer cancelled"));
  934. hr = S_FALSE;
  935. goto Cleanup;
  936. }
  937. pCurrent += lBytesToCopy;
  938. lOffset += lBytesToCopy;
  939. }
  940. }
  941. else
  942. {
  943. //
  944. // Send the data to the app in one big chunk
  945. //
  946. pmdtc->pTransferBuffer = pBmpBuffer;
  947. hr = pmdtc->pIWiaMiniDrvCallBack->MiniDrvCallback(lMsg, IT_STATUS_TRANSFER_TO_CLIENT,
  948. 100, 0, BmpImageInfo.Size, pmdtc, 0);
  949. if (FAILED(hr))
  950. {
  951. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("Convert, sending data to app failed"));
  952. WIAS_LHRESULT(m_pIWiaLog, hr);
  953. goto Cleanup;
  954. }
  955. }
  956. Cleanup:
  957. if (!bUseAppBuffer) {
  958. if (pBmpBuffer) {
  959. delete []pBmpBuffer;
  960. pBmpBuffer = NULL;
  961. iBmpBufferSize = 0;
  962. }
  963. }
  964. return hr;
  965. }