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.

1278 lines
45 KiB

  1. #include "precomp.h"
  2. const ULONG DEFAULT_BUFFER_SIZE = 65535;
  3. IMessageFilter * g_pOldOleMessageFilter = NULL;
  4. HRESULT CWiaDevice::Initialize(LPCTSTR DeviceId)
  5. {
  6. DBG_FN_WIADEV(CWiaDevice::Initialize());
  7. HRESULT hr = S_OK;
  8. HRESULT Temphr = S_OK;
  9. if (!DeviceId) {
  10. return E_INVALIDARG;
  11. }
  12. //
  13. // copy the deviceID string into the member variable for later use.
  14. //
  15. if(!lstrcpyn(m_szDeviceID,DeviceId, ((sizeof(m_szDeviceID)/sizeof(m_szDeviceID[0])) - 1))) {
  16. return HRESULT_FROM_WIN32(GetLastError());
  17. }
  18. //
  19. // we have a device ID, so now find it in the device enumeration, and
  20. // fill the needed values for TW_IDENTITY
  21. //
  22. if (SUCCEEDED(hr)) {
  23. IWiaDevMgr *pIWiaDevMgr = NULL;
  24. hr = CoCreateInstance(CLSID_WiaDevMgr, NULL,CLSCTX_LOCAL_SERVER,IID_IWiaDevMgr,(void **)&pIWiaDevMgr);
  25. if (SUCCEEDED(hr)) {
  26. //
  27. // create a WIA DEV info enumerator
  28. //
  29. IEnumWIA_DEV_INFO *pWiaEnumDevInfo = NULL;
  30. hr = pIWiaDevMgr->EnumDeviceInfo(0,&pWiaEnumDevInfo);
  31. if (SUCCEEDED(hr)) {
  32. do {
  33. IWiaPropertyStorage *pIWiaPropStg = NULL;
  34. hr = pWiaEnumDevInfo->Next(1,&pIWiaPropStg, NULL);
  35. if (hr == S_OK) {
  36. PROPSPEC PropSpec[4];
  37. PROPVARIANT PropVar[4];
  38. memset(PropVar,0,sizeof(PropVar));
  39. // Device ID (used for searching)
  40. PropSpec[0].ulKind = PRSPEC_PROPID;
  41. PropSpec[0].propid = WIA_DIP_DEV_ID;
  42. // Device Name
  43. PropSpec[1].ulKind = PRSPEC_PROPID;
  44. PropSpec[1].propid = WIA_DIP_DEV_NAME;
  45. // Device Description
  46. PropSpec[2].ulKind = PRSPEC_PROPID;
  47. PropSpec[2].propid = WIA_DIP_DEV_DESC;
  48. // Device Vendor Description
  49. PropSpec[3].ulKind = PRSPEC_PROPID;
  50. PropSpec[3].propid = WIA_DIP_VEND_DESC;
  51. hr = pIWiaPropStg->ReadMultiple(sizeof(PropSpec)/sizeof(PROPSPEC),
  52. PropSpec,
  53. PropVar);
  54. if (hr == S_OK) {
  55. DBG_TRC(("CWiaDevice::Initialize(), Reported Device Information from WIA device"));
  56. DBG_TRC(("Device ID = %ws",PropVar[0].bstrVal));
  57. DBG_TRC(("Device Name = %ws",PropVar[1].bstrVal));
  58. DBG_TRC(("Device Desc = %ws",PropVar[2].bstrVal));
  59. DBG_TRC(("Device Vendor Desc = %ws",PropVar[3].bstrVal));
  60. #ifdef UNICODE
  61. //
  62. // compare Device IDs to find the correct device
  63. //
  64. DBG_TRC(("comparing Device ID [in] = %ws, to Device ID [read] = %ws",m_szDeviceID,PropVar[0].bstrVal));
  65. if (lstrcmpi(m_szDeviceID,PropVar[0].bstrVal) == 0) {
  66. //
  67. // copy the device name
  68. //
  69. if(!lstrcpyn(m_szDeviceName,PropVar[1].bstrVal,((sizeof(m_szDeviceName)/sizeof(m_szDeviceName[0])) - 1))) {
  70. hr = HRESULT_FROM_WIN32(GetLastError());
  71. } else {
  72. //
  73. // copy the device description
  74. //
  75. if(!lstrcpyn(m_szDeviceDesc,PropVar[2].bstrVal,((sizeof(m_szDeviceDesc)/sizeof(m_szDeviceDesc[0])) - 1))){
  76. hr = HRESULT_FROM_WIN32(GetLastError());
  77. } else {
  78. //
  79. // copy the device vendor description
  80. //
  81. if(!lstrcpyn(m_szDeviceVendorDesc,PropVar[3].bstrVal,((sizeof(m_szDeviceVendorDesc)/sizeof(m_szDeviceVendorDesc[0])) - 1))) {
  82. hr = HRESULT_FROM_WIN32(GetLastError());
  83. }
  84. }
  85. }
  86. }
  87. #else
  88. TCHAR szTempString[MAX_PATH];
  89. memset(szTempString,0,sizeof(szTempString));
  90. LONG lLength = 0;
  91. lLength = WideCharToMultiByte(CP_ACP,0,PropVar[0].bstrVal,
  92. lstrlenW(PropVar[0].bstrVal),
  93. szTempString,
  94. (sizeof(szTempString)/sizeof(CHAR)),
  95. NULL,NULL);
  96. if (!lLength) {
  97. hr = HRESULT_FROM_WIN32(GetLastError());
  98. } else {
  99. //
  100. // compare Device IDs to find the correct device
  101. //
  102. DBG_TRC(("comparing Device ID [in] = %s, to Device ID [read] = %s",m_szDeviceID,szTempString));
  103. if (lstrcmpi(m_szDeviceID,szTempString) == 0) {
  104. // convert and copy Device Name
  105. memset(szTempString,0,sizeof(szTempString));
  106. lLength = WideCharToMultiByte(CP_ACP,0,PropVar[1].bstrVal,
  107. lstrlenW(PropVar[1].bstrVal),
  108. szTempString,
  109. (sizeof(szTempString)/sizeof(CHAR)),
  110. NULL,NULL);
  111. if (!lLength) {
  112. hr = HRESULT_FROM_WIN32(GetLastError());
  113. } else {
  114. if (!lstrcpyn(m_szDeviceName,szTempString,((sizeof(m_szDeviceName)/sizeof(m_szDeviceName[0])) - 1))) {
  115. hr = HRESULT_FROM_WIN32(GetLastError());
  116. } else {
  117. // convert and copy Device Description
  118. memset(szTempString,0,sizeof(szTempString));
  119. lLength = WideCharToMultiByte(CP_ACP,0,PropVar[2].bstrVal,
  120. lstrlenW(PropVar[2].bstrVal),
  121. szTempString,
  122. (sizeof(szTempString)/sizeof(CHAR)),
  123. NULL,NULL);
  124. if (!lLength) {
  125. hr = HRESULT_FROM_WIN32(GetLastError());
  126. } else {
  127. if(!lstrcpyn(m_szDeviceDesc,szTempString,((sizeof(m_szDeviceDesc)/sizeof(m_szDeviceDesc[0])) - 1))){
  128. hr = HRESULT_FROM_WIN32(GetLastError());
  129. } else {
  130. // convert and copy Device Vendor Description
  131. memset(szTempString,0,sizeof(szTempString));
  132. lLength = WideCharToMultiByte(CP_ACP,0,
  133. PropVar[3].bstrVal,
  134. lstrlenW(PropVar[3].bstrVal),
  135. szTempString,
  136. (sizeof(szTempString)/sizeof(CHAR)),
  137. NULL,NULL);
  138. if (!lLength) {
  139. hr = HRESULT_FROM_WIN32(GetLastError());
  140. } else {
  141. if (!lstrcpyn(m_szDeviceVendorDesc,szTempString,((sizeof(m_szDeviceVendorDesc)/sizeof(m_szDeviceVendorDesc[0])) - 1))) {
  142. hr = HRESULT_FROM_WIN32(GetLastError());
  143. } else {
  144. //
  145. // Set hr to S_FALSE, to signal that we are finished with
  146. // the device enumeration
  147. //
  148. hr = S_FALSE;
  149. }
  150. }
  151. }
  152. }
  153. }
  154. }
  155. }
  156. }
  157. #endif
  158. //
  159. // free property variant array
  160. //
  161. FreePropVariantArray(sizeof(PropSpec)/sizeof(PROPSPEC),PropVar);
  162. //
  163. // release Property Storage
  164. //
  165. if(pIWiaPropStg) {
  166. pIWiaPropStg->Release();
  167. pIWiaPropStg = NULL;
  168. }
  169. }
  170. }
  171. } while (hr == S_OK);
  172. //
  173. // release WIA device Enumerator
  174. //
  175. if(pWiaEnumDevInfo) {
  176. pWiaEnumDevInfo->Release();
  177. }
  178. }
  179. //
  180. // release WIA device manager
  181. //
  182. if(pIWiaDevMgr) {
  183. pIWiaDevMgr->Release();
  184. }
  185. }
  186. }
  187. if(S_FALSE == hr){
  188. //
  189. // set this to OK, because enumeration termination could set hr to S_FALSE
  190. //
  191. hr = S_OK;
  192. }
  193. return hr;
  194. }
  195. HRESULT CWiaDevice::Open( PFNDEVICEEVENTCALLBACK pCallback, LPARAM lParam)
  196. {
  197. DBG_FN_WIADEV(CWiaDevice::Open());
  198. HRESULT hr = S_OK;
  199. IWiaDevMgr *pIWiaDevMgr = NULL;
  200. BSTR bstrDeviceId = NULL;
  201. hr = CoCreateInstance(CLSID_WiaDevMgr, NULL,CLSCTX_LOCAL_SERVER,IID_IWiaDevMgr,
  202. (void **)&pIWiaDevMgr);
  203. if (S_OK == hr) {
  204. #ifdef UNICODE
  205. bstrDeviceId = SysAllocString(m_szDeviceID);
  206. #else
  207. WCHAR DeviceIdW[MAX_PATH];
  208. MultiByteToWideChar(CP_ACP, 0, m_szDeviceID, -1,DeviceIdW, (sizeof(DeviceIdW) / sizeof(DeviceIdW[0])));
  209. bstrDeviceId = SysAllocString(DeviceIdW);
  210. #endif
  211. if (bstrDeviceId) {
  212. hr = pIWiaDevMgr->CreateDevice(bstrDeviceId,&m_pRootItem);
  213. SysFreeString(bstrDeviceId);
  214. } else {
  215. hr = E_OUTOFMEMORY;
  216. }
  217. pIWiaDevMgr->Release();
  218. }
  219. return hr;
  220. }
  221. HRESULT CWiaDevice::Close()
  222. {
  223. DBG_FN_WIADEV(CWiaDevice::Close());
  224. HRESULT hr = S_OK;
  225. FreeAcquiredImages();
  226. if (m_pRootItem) {
  227. m_pRootItem->Release();
  228. m_pRootItem = NULL;
  229. }
  230. return hr;
  231. }
  232. HRESULT CWiaDevice::GetDeviceName(LPTSTR Name,UINT NameSize,UINT *pActualSize)
  233. {
  234. DBG_FN_WIADEV(CWiaDevice::GetDeviceName());
  235. HRESULT hr = S_OK;
  236. memset(Name,0,NameSize);
  237. lstrcpyn(Name,m_szDeviceName,NameSize-1);
  238. if(pActualSize){
  239. *pActualSize = 0;
  240. *pActualSize = lstrlen(Name);
  241. }
  242. return hr;
  243. }
  244. HRESULT CWiaDevice::GetDeviceDesc(LPTSTR Desc,UINT DescSize,UINT *pActualSize)
  245. {
  246. DBG_FN_WIADEV(CWiaDevice::GetDeviceDesc());
  247. HRESULT hr = S_OK;
  248. memset(Desc,0,DescSize);
  249. lstrcpyn(Desc,m_szDeviceDesc,DescSize-1);
  250. if(pActualSize){
  251. *pActualSize = 0;
  252. *pActualSize = lstrlen(Desc);
  253. }
  254. return hr;
  255. }
  256. HRESULT CWiaDevice::GetDeviceVendorName(LPTSTR Name,UINT NameSize,UINT *pActualSize)
  257. {
  258. DBG_FN_WIADEV(CWiaDevice::GetDeviceVendorName);
  259. HRESULT hr = S_OK;
  260. memset(Name,0,NameSize);
  261. lstrcpyn(Name,m_szDeviceVendorDesc,NameSize-1);
  262. if(pActualSize){
  263. *pActualSize = 0;
  264. *pActualSize = lstrlen(Name);
  265. }
  266. return hr;
  267. }
  268. HRESULT CWiaDevice::AcquireImages(HWND hwndOwner,BOOL ShowUI)
  269. {
  270. DBG_FN_WIADEV(CWiaDevice::AcquireImages());
  271. HRESULT hr = S_OK;
  272. if (!m_NumImageItems) {
  273. //
  274. // If we have not done so, do it.
  275. //
  276. if (ShowUI) {
  277. DBG_TRC(("CWiaDevice::AcquireImages(), called for UI mode Initialization"));
  278. //
  279. // We will present the acquistion UI, use the default
  280. // dialog to do it. The dialog is modal.
  281. // It will return an array of (IWiaItem *) with each item
  282. // represent a image(camera) or scan head(scanner).
  283. // For a camera item, a call to LoadImage will load the image
  284. // it represents; for a scanner item, a call to LoadImage
  285. // will trigger scanning.
  286. //
  287. hr = m_pRootItem->DeviceDlg(hwndOwner,
  288. // WIA_DEVICE_DIALOG_USE_COMMON_UI,// flags - removed because it was forcing Common UI
  289. 0, // flags
  290. WIA_INTENT_MINIMIZE_SIZE, // intent
  291. &m_NumImageItems, // item count
  292. &m_ImageItemArray); // item array
  293. DBG_TRC(("CWiaDevice::AcquireImages(),Number of images from DeviceDlg to Transfer = %d",m_NumImageItems));
  294. } else {
  295. DBG_TRC(("CWiaDevice::AcquireImages(), called for UI-LESS mode Initialization"));
  296. DBG_TRC(("or...DS needs information for CAPABILITY initialization"));
  297. //
  298. // Non-UI mode, every item with
  299. // ItemType == (WiaItemTypeImage | WiaItemTypeFile) is a data acquire
  300. // item. Here we go through two passes:
  301. // - The first pass determines how many items are available.
  302. // - The second pass allocates buffer and retrieves all the items
  303. // into that buffer
  304. //
  305. IEnumWiaItem *pEnum = NULL;
  306. hr = m_pRootItem->EnumChildItems(&pEnum);
  307. if (S_OK == hr) {
  308. DWORD Count = 0;
  309. pEnum->Reset();
  310. IWiaItem *pIWiaItem = NULL;
  311. while (SUCCEEDED(hr) && S_OK == pEnum->Next(1, &pIWiaItem, &Count)) {
  312. hr = CollectImageItems(pIWiaItem, NULL, 0, &Count);
  313. if (SUCCEEDED(hr)) {
  314. m_NumImageItems += Count;
  315. }
  316. }
  317. if (SUCCEEDED(hr)) {
  318. // Second pass .....
  319. //
  320. // m_NumImageItems has the number of image items
  321. // Allocate buffer to hold all the image items
  322. //
  323. m_ImageItemArray = (IWiaItem**)CoTaskMemAlloc((sizeof(IWiaItem*) * m_NumImageItems));
  324. if (m_ImageItemArray) {
  325. IWiaItem **ppIWiaItems = NULL;
  326. DWORD BufferSize = 0;
  327. ppIWiaItems = m_ImageItemArray;
  328. BufferSize = m_NumImageItems;
  329. pEnum->Reset();
  330. while (SUCCEEDED(hr) && S_OK == pEnum->Next(1, &pIWiaItem, &Count)) {
  331. hr = CollectImageItems(pIWiaItem, ppIWiaItems,BufferSize, &Count);
  332. if (SUCCEEDED(hr)) {
  333. // advance the buffer
  334. ppIWiaItems += Count;
  335. // adjust the buffer size
  336. BufferSize -= Count;
  337. }
  338. }
  339. if (FAILED(hr)) {
  340. m_NumImageItems -= BufferSize;
  341. FreeAcquiredImages();
  342. }
  343. } else {
  344. hr = E_OUTOFMEMORY;
  345. }
  346. }
  347. }
  348. }
  349. }
  350. return hr;
  351. }
  352. HRESULT CWiaDevice::CollectImageItems(IWiaItem *pStartItem,IWiaItem **ItemList,
  353. DWORD ItemListSize, DWORD *pCount)
  354. {
  355. DBG_FN_WIADEV(CWiaDevice::CollectImageItems());
  356. HRESULT hr = S_OK;
  357. DWORD Count = 0;
  358. if (!pStartItem || (ItemListSize && !ItemList))
  359. return E_INVALIDARG;
  360. if (pStartItem) {
  361. LONG ItemType = 0;
  362. hr = pStartItem->GetItemType(&ItemType);
  363. if (SUCCEEDED(hr)) {
  364. if (ItemType & WiaItemTypeImage) {
  365. //
  366. // Count this is as an image item even though
  367. // we may not have buffer to put it.
  368. //
  369. Count++;
  370. if (ItemList && ItemListSize) {
  371. //
  372. // AddRef since will call Release on each item
  373. // we ever receive
  374. //
  375. pStartItem->AddRef();
  376. *ItemList = pStartItem;
  377. ItemListSize--;
  378. }
  379. }
  380. IEnumWiaItem *pEnum = NULL;
  381. hr = pStartItem->EnumChildItems(&pEnum);
  382. if (SUCCEEDED(hr)) {
  383. IWiaItem *pChildItem = NULL;
  384. DWORD ChildrenCount = 0;
  385. pEnum->Reset();
  386. while (SUCCEEDED(hr) && S_OK == pEnum->Next(1, &pChildItem, &ChildrenCount)) {
  387. hr = CollectImageItems(pChildItem,&ItemList[Count],ItemListSize,&ChildrenCount);
  388. if (SUCCEEDED(hr)) {
  389. Count += ChildrenCount;
  390. if (ItemListSize > ChildrenCount) {
  391. ItemListSize -= ChildrenCount;
  392. } else {
  393. ItemListSize = 0;
  394. ItemList = NULL;
  395. }
  396. }
  397. }
  398. pEnum->Release();
  399. } else {
  400. hr = S_OK;
  401. }
  402. }
  403. pStartItem->Release();
  404. }
  405. if (pCount)
  406. *pCount = Count;
  407. return hr;
  408. }
  409. HRESULT CWiaDevice::FreeAcquiredImages()
  410. {
  411. DBG_FN_WIADEV(CWiaDevice::FreeAcquiredImages());
  412. HRESULT hr = S_OK;
  413. if (m_ImageItemArray) {
  414. DBG_TRC(("CWiaDevice::FreeAcquiredImages(), Freeing %d IWiaItems",m_NumImageItems));
  415. for(LONG lItemIndex = 0; lItemIndex < m_NumImageItems; lItemIndex++){
  416. if(NULL != m_ImageItemArray[lItemIndex]){
  417. DBG_TRC(("CWiaDevice::FreeAcquiredImages(), Free IWiaItem (%d)",m_ImageItemArray[lItemIndex]));
  418. m_ImageItemArray[lItemIndex]->Release();
  419. m_ImageItemArray[lItemIndex] = NULL;
  420. DBG_TRC(("CWiaDevice::FreeAcquiredImages(), Finished Freeing IWiaItem (%d)",lItemIndex));
  421. }
  422. }
  423. CoTaskMemFree(m_ImageItemArray);
  424. m_ImageItemArray = NULL;
  425. m_NumImageItems = 0;
  426. }
  427. return hr;
  428. }
  429. HRESULT CWiaDevice::GetNumAcquiredImages(LONG *pNumImages)
  430. {
  431. DBG_FN_WIADEV(CWiaDevice::GetNumAcquiredImages());
  432. HRESULT hr = S_OK;
  433. if (!pNumImages){
  434. return E_INVALIDARG;
  435. }
  436. *pNumImages = m_NumImageItems;
  437. return hr;
  438. }
  439. HRESULT CWiaDevice::GetAcquiredImageList(LONG lBufferSize,IWiaItem **ppIWiaItem,LONG *plActualSize)
  440. {
  441. DBG_FN_WIADEV(CWiaDevice::GetAcquiredImageList());
  442. HRESULT hr = S_OK;
  443. if (lBufferSize && !ppIWiaItem) {
  444. hr = E_INVALIDARG;
  445. }
  446. if (SUCCEEDED(hr)) {
  447. if (lBufferSize >= m_NumImageItems) {
  448. for (lBufferSize = 0; lBufferSize < m_NumImageItems; lBufferSize++) {
  449. ppIWiaItem[lBufferSize] = m_ImageItemArray[lBufferSize];
  450. }
  451. } else {
  452. hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  453. }
  454. if (plActualSize) {
  455. *plActualSize = m_NumImageItems;
  456. }
  457. }
  458. return hr;
  459. }
  460. HRESULT CWiaDevice::EnumAcquiredImage(DWORD Index,IWiaItem **ppIWiaItem)
  461. {
  462. DBG_FN_WIADEV(CWiaDevice::EnumAcquiredImages);
  463. HRESULT hr = S_OK;
  464. if (!ppIWiaItem) {
  465. hr = E_INVALIDARG;
  466. }
  467. if (SUCCEEDED(hr)) {
  468. if (Index < (DWORD)m_NumImageItems) {
  469. *ppIWiaItem = m_ImageItemArray[Index];
  470. hr = S_OK;
  471. } else {
  472. hr = HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
  473. }
  474. }
  475. return hr;
  476. }
  477. HRESULT CWiaDevice::GetImageInfo(IWiaItem *pIWiaItem,PMEMORY_TRANSFER_INFO pImageInfo)
  478. {
  479. DBG_FN_WIADEV(CWiaDevice::GetImageInfo());
  480. if (!pIWiaItem || !pImageInfo)
  481. return E_INVALIDARG;
  482. HRESULT hr = S_OK;
  483. CWiahelper WIA;
  484. hr = WIA.SetIWiaItem(pIWiaItem);
  485. if(FAILED(hr)){
  486. DBG_ERR(("CWiaDevice::GetImageInfo(), failed to set IWiaItem for property reading"));
  487. return hr;
  488. }
  489. hr = WIA.ReadPropertyLong(WIA_IPA_DATATYPE,&pImageInfo->mtiDataType);
  490. if(FAILED(hr)){
  491. DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPA_DATATYPE"));
  492. return hr;
  493. }
  494. #ifdef SUPPORT_COMPRESSION_TYPES
  495. hr = WIA.ReadPropertyLong(WIA_IPA_COMPRESSION,&pImageInfo->mtiCompression);
  496. if(FAILED(hr)){
  497. DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPA_COMPRESSION"));
  498. return hr;
  499. }
  500. #else // SUPPORT_COMPRESSION_TYPES
  501. pImageInfo->mtiCompression = WIA_COMPRESSION_NONE;
  502. #endif // SUPPORT_COMPRESSION_TYPES
  503. hr = WIA.ReadPropertyLong(WIA_IPA_CHANNELS_PER_PIXEL,&pImageInfo->mtiNumChannels);
  504. if(FAILED(hr)){
  505. DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPA_CHANNELS_PER_PIXEL"));
  506. return hr;
  507. }
  508. hr = WIA.ReadPropertyLong(WIA_IPA_BITS_PER_CHANNEL,&pImageInfo->mtiBitsPerChannel[0]);
  509. if(FAILED(hr)){
  510. DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPA_BITS_PER_CHANNEL"));
  511. return hr;
  512. }
  513. for(LONG i = 0; i<pImageInfo->mtiNumChannels; i++){
  514. pImageInfo->mtiBitsPerChannel[i] = pImageInfo->mtiBitsPerChannel[0];
  515. }
  516. hr = WIA.ReadPropertyLong(WIA_IPA_PIXELS_PER_LINE,&pImageInfo->mtiWidthPixels);
  517. if(FAILED(hr)){
  518. DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPA_PIXELS_PER_LINE"));
  519. return hr;
  520. }
  521. hr = WIA.ReadPropertyLong(WIA_IPA_BYTES_PER_LINE,&pImageInfo->mtiBytesPerLine);
  522. if(FAILED(hr)){
  523. DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPA_BYTES_PER_LINE"));
  524. return hr;
  525. }
  526. hr = WIA.ReadPropertyLong(WIA_IPA_PLANAR,&pImageInfo->mtiPlanar);
  527. if(FAILED(hr)){
  528. DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPA_PLANAR"));
  529. return hr;
  530. }
  531. hr = WIA.ReadPropertyLong(WIA_IPA_NUMBER_OF_LINES,&pImageInfo->mtiHeightPixels);
  532. if(FAILED(hr)){
  533. DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPA_NUMBER_OF_LINES"));
  534. return hr;
  535. }
  536. hr = WIA.ReadPropertyLong(WIA_IPA_DEPTH,&pImageInfo->mtiBitsPerPixel);
  537. if(FAILED(hr)){
  538. DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPA_DEPTH"));
  539. return hr;
  540. }
  541. hr = WIA.ReadPropertyLong(WIA_IPS_XRES,&pImageInfo->mtiXResolution);
  542. if(FAILED(hr)){
  543. DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPS_XRES"));
  544. return hr;
  545. } else if (S_FALSE == hr) {
  546. DBG_WRN(("CWiaDevice::GetImageInfo(), S_FALSE was returned from reading X Resolution, defaulting to 300 dpi (dummy value)"));
  547. // set default
  548. pImageInfo->mtiXResolution = 300;
  549. }
  550. hr = WIA.ReadPropertyLong(WIA_IPS_YRES,&pImageInfo->mtiYResolution);
  551. if(FAILED(hr)){
  552. DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPS_YRES"));
  553. return hr;
  554. } else if (S_FALSE == hr) {
  555. DBG_WRN(("CWiaDevice::GetImageInfo(), S_FALSE was returned from reading Y Resolution, defaulting to 300 dpi (dummy value)"));
  556. // set default
  557. pImageInfo->mtiYResolution = 300;
  558. }
  559. hr = WIA.ReadPropertyGUID(WIA_IPA_FORMAT,&pImageInfo->mtiguidFormat);
  560. if(FAILED(hr)){
  561. DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPA_FORMAT"));
  562. return hr;
  563. }
  564. return hr;
  565. }
  566. HRESULT CWiaDevice::GetThumbnailImageInfo(IWiaItem *pIWiaItem,PMEMORY_TRANSFER_INFO pImageInfo)
  567. {
  568. DBG_FN_WIADEV(CWiaDevice::GetThumbnailImageInfo());
  569. if (!pIWiaItem || !pImageInfo)
  570. return E_INVALIDARG;
  571. HRESULT hr = S_OK;
  572. CWiahelper WIA;
  573. hr = WIA.SetIWiaItem(pIWiaItem);
  574. if(FAILED(hr)){
  575. DBG_ERR(("CWiaDevice::GetThumbnailImageInfo(), failed to set IWiaItem for property reading"));
  576. return hr;
  577. }
  578. hr = WIA.ReadPropertyLong(WIA_IPC_THUMB_WIDTH,&pImageInfo->mtiWidthPixels);
  579. if(FAILED(hr)){
  580. DBG_ERR(("CWiaDevice::GetThumbnailImageInfo(), failed to read WIA_IPC_THUMB_WIDTH"));
  581. return hr;
  582. }
  583. hr = WIA.ReadPropertyLong(WIA_IPC_THUMB_HEIGHT,&pImageInfo->mtiHeightPixels);
  584. if(FAILED(hr)){
  585. DBG_ERR(("CWiaDevice::GetThumbnailImageInfo(), failed to read WIA_IPC_THUMB_HEIGHT"));
  586. return hr;
  587. }
  588. if (SUCCEEDED(hr)) {
  589. //
  590. // Thumbnail is always in 24bits color in DIB format without
  591. // BITMAPINFO header.
  592. //
  593. pImageInfo->mtiNumChannels = 3;
  594. pImageInfo->mtiBitsPerChannel[0] = 8;
  595. pImageInfo->mtiBitsPerChannel[1] = 8;
  596. pImageInfo->mtiBitsPerChannel[2] = 8;
  597. pImageInfo->mtiBitsPerPixel = 24;
  598. pImageInfo->mtiPlanar = FALSE;
  599. pImageInfo->mtiBytesPerLine = (pImageInfo->mtiWidthPixels * 24/8 + 3) / 4;
  600. pImageInfo->mtiCompression = WIA_COMPRESSION_NONE;
  601. pImageInfo->mtiXResolution = 75;
  602. pImageInfo->mtiYResolution = 75;
  603. }
  604. return hr;
  605. }
  606. HRESULT CWiaDevice::GetImageRect(IWiaItem *pIWiaItem,LPRECT pRect)
  607. {
  608. DBG_FN_WIADEV(CWiaDevice::GetImageRect());
  609. if (!pRect || !pIWiaItem)
  610. return E_INVALIDARG;
  611. HRESULT hr = S_OK;
  612. LONG lXPos = 0;
  613. LONG lYPos = 0;
  614. LONG lXExtent = 0;
  615. LONG lYExtent = 0;
  616. CWiahelper WIA;
  617. hr = WIA.SetIWiaItem(pIWiaItem);
  618. if(FAILED(hr)){
  619. DBG_ERR(("CWiaDevice::GetImageRect(), failed to set IWiaItem for property reading"));
  620. return hr;
  621. }
  622. hr = WIA.ReadPropertyLong(WIA_IPS_XPOS,&lXPos);
  623. if(FAILED(hr)){
  624. DBG_ERR(("CWiaDevice::GetImageRect(), failed to read WIA_IPS_XPOS"));
  625. return hr;
  626. }
  627. hr = WIA.ReadPropertyLong(WIA_IPS_YPOS,&lYPos);
  628. if(FAILED(hr)){
  629. DBG_ERR(("CWiaDevice::GetImageRect(), failed to read WIA_IPS_YPOS"));
  630. return hr;
  631. }
  632. hr = WIA.ReadPropertyLong(WIA_IPS_XEXTENT,&lXExtent);
  633. if(FAILED(hr)){
  634. DBG_ERR(("CWiaDevice::GetImageRect(), failed to read WIA_IPS_XEXTENT"));
  635. return hr;
  636. }
  637. hr = WIA.ReadPropertyLong(WIA_IPS_YEXTENT,&lYExtent);
  638. if(FAILED(hr)){
  639. DBG_ERR(("CWiaDevice::GetImageRect(), failed to read WIA_IPS_YEXTENT"));
  640. return hr;
  641. }
  642. if (SUCCEEDED(hr)) {
  643. pRect->left = lXPos;
  644. pRect->right = lXExtent + lXPos - 1;
  645. pRect->top = lYPos;
  646. pRect->bottom = lYExtent + lYPos - 1;
  647. }
  648. return hr;
  649. }
  650. HRESULT CWiaDevice::GetThumbnailRect(IWiaItem *pIWiaItem,LPRECT pRect)
  651. {
  652. DBG_FN_WIADEV(CWiaDevice::GetThumbnailRect());
  653. if (!pIWiaItem || !pRect)
  654. return E_INVALIDARG;
  655. HRESULT hr = S_OK;
  656. LONG lWidth = 0;
  657. LONG lHeight = 0;
  658. CWiahelper WIA;
  659. hr = WIA.SetIWiaItem(pIWiaItem);
  660. if(FAILED(hr)){
  661. DBG_ERR(("CWiaDevice::GetThumbnailRect(), failed to set IWiaItem for property reading"));
  662. return hr;
  663. }
  664. hr = WIA.ReadPropertyLong(WIA_IPC_THUMB_WIDTH,&lWidth);
  665. if(FAILED(hr)){
  666. DBG_ERR(("CWiaDevice::GetThumbnailRect(), failed to read WIA_IPC_THUMB_WIDTH"));
  667. return hr;
  668. }
  669. hr = WIA.ReadPropertyLong(WIA_IPC_THUMB_HEIGHT,&lHeight);
  670. if(FAILED(hr)){
  671. DBG_ERR(("CWiaDevice::GetThumbnailRect(), failed to read WIA_IPC_THUMB_HEIGHT"));
  672. return hr;
  673. }
  674. if (SUCCEEDED(hr)) {
  675. pRect->left = 0;
  676. pRect->top = 0;
  677. pRect->right = lWidth - 1;
  678. pRect->bottom = lHeight - 1;
  679. }
  680. return hr;
  681. }
  682. HRESULT CWiaDevice::LoadImage(IWiaItem *pIWiaItem,GUID guidFormatID,IWiaDataCallback *pIDataCB)
  683. {
  684. DBG_FN_WIADEV(CWiaDevice::LoadImage());
  685. HRESULT hr = S_OK;
  686. if (!pIWiaItem || !pIDataCB) {
  687. return E_INVALIDARG;
  688. }
  689. CWiahelper WIA;
  690. hr = WIA.SetIWiaItem(pIWiaItem);
  691. if(FAILED(hr)){
  692. DBG_ERR(("CWiaDevice::LoadImage(), failed to set IWiaItem for property writing"));
  693. return hr;
  694. }
  695. IWiaDataTransfer *pDataTransfer = NULL;
  696. hr = pIWiaItem->QueryInterface(IID_IWiaDataTransfer,(void**)&pDataTransfer);
  697. if (S_OK == hr) {
  698. //
  699. // write TYMED
  700. //
  701. hr = WIA.WritePropertyLong(WIA_IPA_TYMED,TYMED_CALLBACK);
  702. if (FAILED(hr)) {
  703. DBG_ERR(("CWiaDevice::LoadImage(), failed to write WIA_IPA_TYMED"));
  704. //
  705. // release IWiaDataTransfer Interface, (we are bailing early)
  706. //
  707. pDataTransfer->Release();
  708. pDataTransfer = NULL;
  709. return hr;
  710. }
  711. //
  712. // write format
  713. //
  714. hr = WIA.WritePropertyGUID(WIA_IPA_FORMAT, guidFormatID);
  715. if(FAILED(hr)){
  716. DBG_ERR(("CWiaDevice::LoadImage(), failed to write WIA_IPA_FORMAT"));
  717. //
  718. // release IWiaDataTransfer Interface, (we are bailing early)
  719. //
  720. pDataTransfer->Release();
  721. pDataTransfer = NULL;
  722. return hr;
  723. }
  724. LONG BufferSize = DEFAULT_BUFFER_SIZE;
  725. hr = WIA.ReadPropertyLong(WIA_IPA_MIN_BUFFER_SIZE, &BufferSize);
  726. if (FAILED(hr)) {
  727. DBG_WRN(("CWiaDevice::LoadImage(), failed to read WIA_IPA_MIN_BUFFER_SIZE, (defaulting to %d)",DEFAULT_BUFFER_SIZE));
  728. BufferSize = DEFAULT_BUFFER_SIZE;
  729. }
  730. //
  731. // Before we do the blocking call, we need to temporarily disable
  732. // the registered IMessageFilter (if any). We do this primarily
  733. // for MFC based apps, as in some situations they can put up
  734. // the "Server Busy" dialog when things are fine -- it's just
  735. // taking a while to scan, etc. Unfortunately, we can't detect
  736. // if it's MFC's IMessageFilter we're disabling. Apps can actually
  737. // do interesting work in IMessageFilter, but it's not likely. This
  738. // is a risk we're taking by nuking the message filter for the duration
  739. // of the transfer.
  740. //
  741. // Nb: Note we ignore result of this call. It is generally harmless, but asserting it
  742. // may be useful
  743. g_pOldOleMessageFilter = NULL;
  744. HRESULT hr_ServerBusyFix = S_OK;
  745. hr_ServerBusyFix = ::CoRegisterMessageFilter( NULL, &g_pOldOleMessageFilter );
  746. if(FAILED(hr_ServerBusyFix)){
  747. DBG_WRN(("CWiaDevice::LoadImage(), failed to (Saving IMessageFilter) CoRegisterMessageFilter..(Server Busy code fix)"));
  748. }
  749. WIA_DATA_TRANSFER_INFO wiadtInfo;
  750. memset(&wiadtInfo,0,sizeof(wiadtInfo));
  751. wiadtInfo.ulSize = sizeof(wiadtInfo);
  752. wiadtInfo.ulBufferSize = BufferSize * 4;
  753. //
  754. // acquire data from the IWiaItem
  755. //
  756. hr = pDataTransfer->idtGetBandedData(&wiadtInfo, pIDataCB);
  757. //
  758. // Restore the old IMessageFilter if there was one
  759. //
  760. if (g_pOldOleMessageFilter) {
  761. hr_ServerBusyFix = ::CoRegisterMessageFilter( g_pOldOleMessageFilter, NULL );
  762. if(FAILED(hr_ServerBusyFix)){
  763. DBG_WRN(("CWiaDevice::LoadImage(), failed to (Restoring IMessageFilter) CoRegisterMessageFilter..(Server Busy code fix)"));
  764. }
  765. g_pOldOleMessageFilter = NULL;
  766. }
  767. //
  768. // release IWiaDataTransfer Interface
  769. //
  770. pDataTransfer->Release();
  771. }
  772. return hr;
  773. }
  774. HRESULT CWiaDevice::LoadImageToDisk(IWiaItem *pIWiaItem,CHAR *pFileName, GUID guidFormatID,IWiaDataCallback *pIDataCB)
  775. {
  776. DBG_FN_WIADEV(CWiaDevice::LoadImage());
  777. HRESULT hr = S_OK;
  778. if (!pIWiaItem || !pIDataCB || !pFileName) {
  779. return E_INVALIDARG;
  780. }
  781. CWiahelper WIA;
  782. hr = WIA.SetIWiaItem(pIWiaItem);
  783. if(FAILED(hr)){
  784. DBG_ERR(("CWiaDevice::LoadImageToDisk(), failed to set IWiaItem for property writing"));
  785. return hr;
  786. }
  787. IWiaDataTransfer *pDataTransfer = NULL;
  788. hr = pIWiaItem->QueryInterface(IID_IWiaDataTransfer,(void**)&pDataTransfer);
  789. if (S_OK == hr) {
  790. //
  791. // write TYMED
  792. //
  793. hr = WIA.WritePropertyLong(WIA_IPA_TYMED,TYMED_FILE);
  794. if (FAILED(hr)) {
  795. DBG_ERR(("CWiaDevice::LoadImageToDisk(), failed to write WIA_IPA_TYMED"));
  796. //
  797. // release IWiaDataTransfer Interface, (we are bailing early)
  798. //
  799. pDataTransfer->Release();
  800. pDataTransfer = NULL;
  801. return hr;
  802. }
  803. //
  804. // write format
  805. //
  806. hr = WIA.WritePropertyGUID(WIA_IPA_FORMAT, guidFormatID);
  807. if(FAILED(hr)){
  808. DBG_ERR(("CWiaDevice::LoadImageToDisk(), failed to write WIA_IPA_FORMAT"));
  809. //
  810. // release IWiaDataTransfer Interface, (we are bailing early)
  811. //
  812. pDataTransfer->Release();
  813. pDataTransfer = NULL;
  814. return hr;
  815. }
  816. //
  817. // Before we do the blocking call, we need to temporarily disable
  818. // the registered IMessageFilter (if any). We do this primarily
  819. // for MFC based apps, as in some situations they can put up
  820. // the "Server Busy" dialog when things are fine -- it's just
  821. // taking a while to scan, etc. Unfortunately, we can't detect
  822. // if it's MFC's IMessageFilter we're disabling. Apps can actually
  823. // do interesting work in IMessageFilter, but it's not likely. This
  824. // is a risk we're taking by nuking the message filter for the duration
  825. // of the transfer.
  826. //
  827. // Nb: Note we ignore result of this call. It is generally harmless, but asserting it
  828. // may be useful
  829. g_pOldOleMessageFilter = NULL;
  830. HRESULT hr_ServerBusyFix = S_OK;
  831. hr_ServerBusyFix = ::CoRegisterMessageFilter( NULL, &g_pOldOleMessageFilter );
  832. if(FAILED(hr_ServerBusyFix)){
  833. DBG_WRN(("CWiaDevice::LoadImageToDisk(), failed to (Saving IMessageFilter) CoRegisterMessageFilter..(Server Busy code fix)"));
  834. }
  835. //
  836. // load the StgMedium
  837. //
  838. WCHAR wszFileName[MAX_PATH];
  839. memset(wszFileName,0,sizeof(wszFileName));
  840. MultiByteToWideChar(CP_ACP, 0,pFileName,-1,wszFileName,(sizeof(wszFileName)/sizeof(wszFileName[0])));
  841. STGMEDIUM StgMedium;
  842. memset(&StgMedium,0,sizeof(StgMedium));
  843. StgMedium.tymed = TYMED_FILE;
  844. StgMedium.pUnkForRelease = NULL;
  845. StgMedium.hGlobal = NULL;
  846. StgMedium.lpszFileName = wszFileName;
  847. //
  848. // acquire data from the IWiaItem
  849. //
  850. hr = pDataTransfer->idtGetData(&StgMedium, pIDataCB);
  851. //
  852. // Restore the old IMessageFilter if there was one
  853. //
  854. if (g_pOldOleMessageFilter) {
  855. hr_ServerBusyFix = ::CoRegisterMessageFilter( g_pOldOleMessageFilter, NULL );
  856. if(FAILED(hr_ServerBusyFix)){
  857. DBG_WRN(("CWiaDevice::LoadImageToDisk(), failed to (Restoring IMessageFilter) CoRegisterMessageFilter..(Server Busy code fix)"));
  858. }
  859. g_pOldOleMessageFilter = NULL;
  860. }
  861. //
  862. // release IWiaDataTransfer Interface
  863. //
  864. pDataTransfer->Release();
  865. }
  866. return hr;
  867. }
  868. HRESULT CWiaDevice::GetBasicScannerInfo(PBASIC_INFO pBasicInfo)
  869. {
  870. if (!pBasicInfo || pBasicInfo->Size < sizeof(BASIC_INFO))
  871. return E_INVALIDARG;
  872. HRESULT hr = S_OK;
  873. LONG lDocumentHandlingCapabilites = 0;
  874. LONG lHorizontalBedSize = 0;
  875. LONG lVerticalBedSize = 0;
  876. LONG lXOpticalResolution = 0;
  877. LONG lYOpticalResolution = 0;
  878. pBasicInfo->FeederCaps = 0;
  879. pBasicInfo->xBedSize = 0;
  880. pBasicInfo->xOpticalRes = 0;
  881. pBasicInfo->yOpticalRes = 0;
  882. pBasicInfo->yBedSize = 0;
  883. CWiahelper WIA;
  884. hr = WIA.SetIWiaItem(m_pRootItem);
  885. if(FAILED(hr)){
  886. DBG_ERR(("CWiaDevice::GetBasicScannerInfo(), failed to set IWiaItem for property reading"));
  887. return hr;
  888. }
  889. hr = WIA.ReadPropertyLong(WIA_DPS_DOCUMENT_HANDLING_CAPABILITIES,&lDocumentHandlingCapabilites);
  890. if(FAILED(hr)){
  891. DBG_ERR(("CWiaDevice::GetBasicScannerInfo(), failed to read WIA_DPS_DOCUMENT_HANDLING_CAPABILITIES"));
  892. return hr;
  893. }
  894. pBasicInfo->FeederCaps = (TW_UINT32)lDocumentHandlingCapabilites;
  895. hr = WIA.ReadPropertyLong(WIA_DPS_OPTICAL_XRES,&lXOpticalResolution);
  896. if(FAILED(hr)){
  897. DBG_ERR(("CWiaDevice::GetBasicScannerInfo(), failed to read WIA_DPS_OPTICAL_XRES"));
  898. return hr;
  899. }
  900. pBasicInfo->xOpticalRes = (TW_UINT32)lXOpticalResolution;
  901. hr = WIA.ReadPropertyLong(WIA_DPS_OPTICAL_YRES,&lYOpticalResolution);
  902. if(FAILED(hr)){
  903. DBG_ERR(("CWiaDevice::GetBasicScannerInfo(), failed to read WIA_DPS_OPTICAL_YRES"));
  904. return hr;
  905. }
  906. pBasicInfo->yOpticalRes = (TW_UINT32)lYOpticalResolution;
  907. hr = WIA.ReadPropertyLong(WIA_DPS_HORIZONTAL_BED_SIZE,&lHorizontalBedSize);
  908. if(FAILED(hr)){
  909. DBG_ERR(("CWiaDevice::GetBasicScannerInfo(), failed to read WIA_DPS_HORIZONTAL_BED_SIZE"));
  910. return hr;
  911. } else if(S_FALSE == hr){
  912. DBG_WRN(("CWiaDevice::GetBasicScannerInfo(), WIA_DPS_HORIZONTAL_BED_SIZE property not found"));
  913. hr = WIA.ReadPropertyLong(WIA_DPS_HORIZONTAL_SHEET_FEED_SIZE,&lHorizontalBedSize);
  914. if(FAILED(hr)){
  915. DBG_ERR(("CWiaDevice::GetBasicScannerInfo(), failed to read WIA_DPS_HORIZONTAL_SHEET_FEED_SIZE"));
  916. return hr;
  917. }
  918. }
  919. pBasicInfo->xBedSize = lHorizontalBedSize;
  920. hr = WIA.ReadPropertyLong(WIA_DPS_VERTICAL_BED_SIZE,&lVerticalBedSize);
  921. if(FAILED(hr)){
  922. DBG_ERR(("CWiaDevice::GetBasicScannerInfo(), failed to read WIA_DPS_VERTICAL_BED_SIZE"));
  923. return hr;
  924. } else if(S_FALSE == hr){
  925. DBG_WRN(("CWiaDevice::GetBasicScannerInfo(), WIA_DPS_VERTICAL_BED_SIZE property not found"));
  926. hr = WIA.ReadPropertyLong(WIA_DPS_VERTICAL_SHEET_FEED_SIZE,&lVerticalBedSize);
  927. if(FAILED(hr)){
  928. DBG_ERR(("CWiaDevice::GetBasicScannerInfo(), failed to read WIA_DPS_VERTICAL_SHEET_FEED_SIZE"));
  929. return hr;
  930. }
  931. }
  932. pBasicInfo->yBedSize = lVerticalBedSize;
  933. return hr;
  934. }
  935. BOOL CWiaDevice::TwainCapabilityPassThrough()
  936. {
  937. HRESULT hr = S_OK;
  938. LONG lRootItemFlags = 0;
  939. CWiahelper WIA;
  940. hr = WIA.SetIWiaItem(m_pRootItem);
  941. if(FAILED(hr)){
  942. DBG_ERR(("CWiaDevice::TwainCapabilityPassThrough(), failed to set IWiaItem for property reading"));
  943. return FALSE;
  944. }
  945. hr = WIA.ReadPropertyLong(WIA_IPA_ITEM_FLAGS,&lRootItemFlags);
  946. if(FAILED(hr)){
  947. DBG_ERR(("CWiaDevice::TwainCapabilityPassThrough(), failed to read WIA_IPA_ITEM_FLAGS"));
  948. return FALSE;
  949. }
  950. return (lRootItemFlags & WiaItemTypeTwainCapabilityPassThrough);
  951. }
  952. HRESULT CWiaDevice::LoadThumbnail(IWiaItem *pIWiaItem,HGLOBAL *phThumbnail,ULONG *pThumbnailSize)
  953. {
  954. DBG_FN_WIADEV(CWiaDevice::LoadThumbnail());
  955. HRESULT hr = S_OK;
  956. if (!phThumbnail || !pIWiaItem)
  957. return E_INVALIDARG;
  958. *phThumbnail = NULL;
  959. HGLOBAL hThumbnail = NULL;
  960. CWiahelper WIA;
  961. hr = WIA.SetIWiaItem(pIWiaItem);
  962. if(FAILED(hr)){
  963. DBG_ERR(("CWiaDevice::LoadThumbnail(), failed to set IWiaItem for property writing"));
  964. return hr;
  965. }
  966. LONG ThumbWidth = 0;
  967. LONG ThumbHeight = 0;
  968. hr = WIA.ReadPropertyLong(WIA_IPC_THUMB_WIDTH, &ThumbWidth);
  969. if (SUCCEEDED(hr)) {
  970. hr = WIA.ReadPropertyLong(WIA_IPC_THUMB_HEIGHT, &ThumbHeight);
  971. if (SUCCEEDED(hr)) {
  972. LONG lDataSize = 0;
  973. BYTE* pThumbData = NULL;
  974. hr = WIA.ReadPropertyData(WIA_IPC_THUMBNAIL,&pThumbData,&lDataSize);
  975. if (SUCCEEDED(hr)) {
  976. hThumbnail = NULL;
  977. hThumbnail = GlobalAlloc(GHND, (lDataSize + sizeof(BITMAPINFOHEADER)));
  978. if (hThumbnail) {
  979. BITMAPINFOHEADER *pbmih = NULL;
  980. pbmih = (BITMAPINFOHEADER*)GlobalLock(hThumbnail);
  981. if (pbmih) {
  982. DBG_TRC(("CWiaDevice::LoadThumbnail(), Reported thumbnail information"));
  983. DBG_TRC(("Width = %d",ThumbWidth));
  984. DBG_TRC(("Height = %d",ThumbHeight));
  985. DBG_TRC(("Data Size = %d",lDataSize));
  986. //
  987. // Initialize the BITMAPINFOHEADER
  988. //
  989. pbmih->biSize = sizeof(BITMAPINFOHEADER);
  990. pbmih->biWidth = ThumbWidth;
  991. pbmih->biHeight = ThumbHeight;
  992. pbmih->biPlanes = 1;
  993. pbmih->biBitCount = 24;
  994. pbmih->biCompression = BI_RGB;
  995. pbmih->biSizeImage = lDataSize;
  996. pbmih->biXPelsPerMeter = 0;
  997. pbmih->biYPelsPerMeter = 0;
  998. pbmih->biClrUsed = 0;
  999. pbmih->biClrImportant = 0;
  1000. //
  1001. // Copy the bits. The bits buffer is right after
  1002. // the header.
  1003. //
  1004. BYTE *pDst = (BYTE*)pbmih;
  1005. pDst = pDst + sizeof(BITMAPINFOHEADER);
  1006. memcpy(pDst, pThumbData,lDataSize);
  1007. GlobalUnlock(hThumbnail);
  1008. *phThumbnail = hThumbnail;
  1009. if (pThumbnailSize){
  1010. *pThumbnailSize = (lDataSize + sizeof(BITMAPINFOHEADER));
  1011. }
  1012. } else {
  1013. GlobalFree(hThumbnail);
  1014. hr = E_OUTOFMEMORY;
  1015. }
  1016. } else {
  1017. hr = E_OUTOFMEMORY;
  1018. }
  1019. //
  1020. // free any temporary buffers
  1021. //
  1022. if (pThumbData) {
  1023. DBG_TRC(("CWiaDevice::LoadThumbnail(), freeing temporary thumbnail buffer"));
  1024. GlobalFree(pThumbData);
  1025. pThumbData = NULL;
  1026. DBG_TRC(("CWiaDevice::LoadThumbnail(), finished freeing temporary thumbnail buffer"));
  1027. }
  1028. }
  1029. }
  1030. }
  1031. return hr;
  1032. }
  1033. //
  1034. // CWiaEventCallback object implementation
  1035. //
  1036. HRESULT CWiaEventCallback::ImageEventCallback(const GUID *pEventGuid,BSTR bstrEventDescription,
  1037. BSTR bstrDeviceId,BSTR bstrDeviceDescription,
  1038. DWORD dwDeviceType,BSTR bstrFullItemName,
  1039. ULONG *pulEventType,ULONG ulReserved)
  1040. {
  1041. DBG_FN_WIADEV(CWiaEventCallback::ImageEventCallback);
  1042. //
  1043. // translate WIA event guid to event code.
  1044. // Note that we do not verify device id here because
  1045. // we will not receive events not meant for the device this
  1046. // object was created for.
  1047. //
  1048. if (m_pfnCallback && WIA_EVENT_DEVICE_DISCONNECTED == *pEventGuid) {
  1049. return(*m_pfnCallback)(0, m_CallbackParam);
  1050. }
  1051. return S_OK;
  1052. }