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.

467 lines
19 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORPORATION, 1998
  4. *
  5. * TITLE: SCANPROC.CPP
  6. *
  7. * VERSION: 1.0
  8. *
  9. * AUTHOR: ShaunIv
  10. *
  11. * DATE: 10/7/1999
  12. *
  13. * DESCRIPTION: Scan Thread
  14. *
  15. *******************************************************************************/
  16. #include "precomp.h"
  17. #pragma hdrstop
  18. // Constructor
  19. CScanPreviewThread::CScanPreviewThread(
  20. DWORD dwIWiaItemCookie, // specifies the entry in the global interface table
  21. HWND hwndPreview, // handle to the preview window
  22. HWND hwndNotify, // handle to the window that receives notifications
  23. const POINT &ptOrigin, // Origin
  24. const SIZE &sizeResolution, // Resolution
  25. const SIZE &sizeExtent, // Extent
  26. const CSimpleEvent &CancelEvent // Cancel event name
  27. )
  28. : m_dwIWiaItemCookie(dwIWiaItemCookie),
  29. m_hwndPreview(hwndPreview),
  30. m_hwndNotify(hwndNotify),
  31. m_ptOrigin(ptOrigin),
  32. m_sizeResolution(sizeResolution),
  33. m_sizeExtent(sizeExtent),
  34. m_nMsgBegin(RegisterWindowMessage(SCAN_NOTIFYBEGINSCAN)),
  35. m_nMsgEnd(RegisterWindowMessage(SCAN_NOTIFYENDSCAN)),
  36. m_nMsgProgress(RegisterWindowMessage(SCAN_NOTIFYPROGRESS)),
  37. m_sCancelEvent(CancelEvent),
  38. m_bFirstTransfer(true),
  39. m_nImageSize(0)
  40. {
  41. }
  42. // Destructor
  43. CScanPreviewThread::~CScanPreviewThread(void)
  44. {
  45. }
  46. HRESULT _stdcall CScanPreviewThread::BandedDataCallback( LONG lMessage,
  47. LONG lStatus,
  48. LONG lPercentComplete,
  49. LONG lOffset,
  50. LONG lLength,
  51. LONG lReserved,
  52. LONG lResLength,
  53. BYTE *pbBuffer )
  54. {
  55. WIA_TRACE((TEXT("ImageDataCallback: lMessage: %d, lStatus: %d, lPercentComplete: %d, lOffset: %d, lLength: %d, lReserved: %d"), lMessage, lStatus, lPercentComplete, lOffset, lLength, lReserved ));
  56. HRESULT hr = S_OK;
  57. if (!m_sCancelEvent.Signalled())
  58. {
  59. switch (lMessage)
  60. {
  61. case IT_MSG_DATA_HEADER:
  62. {
  63. m_bFirstTransfer = true;
  64. break;
  65. } // IT_MSG_DATA_HEADER
  66. case IT_MSG_DATA:
  67. if (lStatus & IT_STATUS_TRANSFER_TO_CLIENT)
  68. {
  69. if (m_bFirstTransfer)
  70. {
  71. // Assuming there is no way we could get a lLength smaller than the image header size
  72. m_bFirstTransfer = false;
  73. m_sImageData.Initialize( reinterpret_cast<PBITMAPINFO>(pbBuffer) );
  74. lLength -= WiaUiUtil::GetBmiSize(reinterpret_cast<PBITMAPINFO>(pbBuffer));
  75. lOffset += WiaUiUtil::GetBmiSize(reinterpret_cast<PBITMAPINFO>(pbBuffer));
  76. }
  77. if (SUCCEEDED(hr))
  78. {
  79. if (lLength)
  80. {
  81. // Figure out which line we are on
  82. int nCurrentLine = (lOffset - m_sImageData.GetHeaderLength())/m_sImageData.GetUnpackedWidthInBytes();
  83. // BUGBUG: This should be an even number of lines. If it isn't, things are going to get messed up
  84. int nLineCount = lLength / m_sImageData.GetUnpackedWidthInBytes();
  85. // Copy the data to our bitmap
  86. m_sImageData.SetUnpackedData( pbBuffer, nCurrentLine, nLineCount );
  87. // Tell the preview window to repaint the DIB
  88. if (IsWindow(m_hwndPreview))
  89. {
  90. PostMessage( m_hwndPreview, PWM_SETBITMAP, MAKEWPARAM(1,1), (LPARAM)m_sImageData.Bitmap() );
  91. }
  92. // Tell the notify window we've made progress
  93. if (IsWindow(m_hwndNotify))
  94. {
  95. PostMessage( m_hwndNotify, m_nMsgProgress, SCAN_PROGRESS_SCANNING, lPercentComplete );
  96. }
  97. }
  98. }
  99. } // IT_STATUS_TRANSFER_TO_CLIENT
  100. break;
  101. case IT_MSG_STATUS:
  102. {
  103. } // IT_MSG_STATUS
  104. break;
  105. case IT_MSG_TERMINATION:
  106. {
  107. } // IT_MSG_TERMINATION
  108. break;
  109. default:
  110. WIA_ERROR((TEXT("ImageDataCallback, unknown lMessage: %d"), lMessage ));
  111. break;
  112. }
  113. }
  114. else hr = S_FALSE;
  115. return(hr);
  116. }
  117. // The actual thread proc for this thread
  118. DWORD CScanPreviewThread::ThreadProc( LPVOID pParam )
  119. {
  120. DWORD dwResult = 0;
  121. CScanPreviewThread *This = (CScanPreviewThread *)pParam;
  122. if (This)
  123. {
  124. WIA_TRACE((TEXT("Beginning scan")));
  125. dwResult = (DWORD)This->Scan();
  126. WIA_TRACE((TEXT("Ending scan")));
  127. delete This;
  128. }
  129. return(dwResult);
  130. }
  131. // Returns a handle to the created thread
  132. HANDLE CScanPreviewThread::Scan(
  133. DWORD dwIWiaItemCookie, // specifies the entry in the global interface table
  134. HWND hwndPreview, // handle to the preview window
  135. HWND hwndNotify, // handle to the window that receives notifications
  136. const POINT &ptOrigin, // Origin
  137. const SIZE &sizeResolution, // Resolution
  138. const SIZE &sizeExtent, // Extent
  139. const CSimpleEvent &CancelEvent // Cancel event name
  140. )
  141. {
  142. CScanPreviewThread *scanThread = new CScanPreviewThread( dwIWiaItemCookie, hwndPreview, hwndNotify, ptOrigin, sizeResolution, sizeExtent, CancelEvent );
  143. if (scanThread)
  144. {
  145. DWORD dwThreadId;
  146. return CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc, scanThread, 0, &dwThreadId );
  147. }
  148. return NULL;
  149. }
  150. HRESULT CScanPreviewThread::ScanBandedTransfer( IWiaItem *pIWiaItem )
  151. {
  152. WIA_PUSHFUNCTION(TEXT("CScanPreviewThread::ScanBandedTransfer"));
  153. CComPtr<IWiaDataTransfer> pWiaDataTransfer;
  154. WIA_DATA_TRANSFER_INFO wiaDataTransInfo;
  155. HRESULT hr = pIWiaItem->QueryInterface(IID_IWiaDataTransfer, (void**)&pWiaDataTransfer);
  156. if (SUCCEEDED(hr))
  157. {
  158. CComPtr<IWiaDataCallback> pWiaDataCallback;
  159. hr = this->QueryInterface(IID_IWiaDataCallback,(void **)&pWiaDataCallback);
  160. if (SUCCEEDED(hr))
  161. {
  162. LONG nItemSize = 0;
  163. if (PropStorageHelpers::GetProperty( pIWiaItem, WIA_IPA_ITEM_SIZE, nItemSize ))
  164. {
  165. ZeroMemory(&wiaDataTransInfo, sizeof(WIA_DATA_TRANSFER_INFO));
  166. wiaDataTransInfo.ulSize = sizeof(WIA_DATA_TRANSFER_INFO);
  167. wiaDataTransInfo.ulBufferSize = WiaUiUtil::Max<ULONG>( nItemSize / 8, (sizeof(BITMAPINFO)+sizeof(RGBQUAD)*255) );
  168. hr = pWiaDataTransfer->idtGetBandedData( &wiaDataTransInfo, pWiaDataCallback );
  169. if (FAILED(hr))
  170. {
  171. WIA_PRINTHRESULT((hr,TEXT("CScanPreviewThread::Scan, itGetImage failed")));
  172. }
  173. }
  174. else
  175. {
  176. WIA_PRINTHRESULT((hr,TEXT("CScanPreviewThread::Scan, unable to get image size")));
  177. hr = E_FAIL;
  178. }
  179. }
  180. }
  181. else
  182. {
  183. WIA_PRINTHRESULT((hr,TEXT("CScanPreviewThread::Scan, QI of IID_IImageTransfer failed")));
  184. }
  185. WIA_TRACE((TEXT("End CScanPreviewThread::ScanBandedTransfer")));
  186. return(hr);
  187. }
  188. /*
  189. * The worker which does the actual scan
  190. */
  191. bool CScanPreviewThread::Scan(void)
  192. {
  193. WIA_PUSHFUNCTION(TEXT("CScanPreviewThread::Scan"));
  194. if (IsWindow(m_hwndNotify))
  195. {
  196. PostMessage( m_hwndNotify, m_nMsgBegin, 0, 0 );
  197. }
  198. if (IsWindow(m_hwndNotify))
  199. {
  200. PostMessage( m_hwndNotify, m_nMsgProgress, SCAN_PROGRESS_INITIALIZING, 0 );
  201. }
  202. HRESULT hr = CoInitialize( NULL );
  203. if (SUCCEEDED(hr))
  204. {
  205. CComPtr<IGlobalInterfaceTable> pGlobalInterfaceTable;
  206. hr = CoCreateInstance( CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable, (void **)&pGlobalInterfaceTable );
  207. if (SUCCEEDED(hr))
  208. {
  209. CComPtr<IWiaItem> pIWiaItem;
  210. pGlobalInterfaceTable->GetInterfaceFromGlobal( m_dwIWiaItemCookie, IID_IWiaItem, (LPVOID*)&pIWiaItem );
  211. if (SUCCEEDED(hr))
  212. {
  213. if (PropStorageHelpers::SetProperty( pIWiaItem, WIA_IPS_CUR_INTENT, (LONG)WIA_INTENT_NONE))
  214. {
  215. CPropertyStream SavedProperties;
  216. hr = SavedProperties.AssignFromWiaItem(pIWiaItem);
  217. if (SUCCEEDED(hr))
  218. {
  219. //
  220. // Set the new properties
  221. //
  222. if (PropStorageHelpers::SetProperty( pIWiaItem, WIA_IPS_XRES, m_sizeResolution.cx ) &&
  223. PropStorageHelpers::SetProperty( pIWiaItem, WIA_IPS_YRES, m_sizeResolution.cy ) &&
  224. PropStorageHelpers::SetProperty( pIWiaItem, WIA_IPS_XPOS, m_ptOrigin.x) &&
  225. PropStorageHelpers::SetProperty( pIWiaItem, WIA_IPS_YPOS, m_ptOrigin.y) &&
  226. PropStorageHelpers::SetProperty( pIWiaItem, WIA_IPS_XEXTENT, m_sizeExtent.cx ) &&
  227. PropStorageHelpers::SetProperty( pIWiaItem, WIA_IPS_YEXTENT, m_sizeExtent.cy ) &&
  228. PropStorageHelpers::SetProperty( pIWiaItem, WIA_IPA_FORMAT, WiaImgFmt_MEMORYBMP ) &&
  229. PropStorageHelpers::SetProperty( pIWiaItem, WIA_IPA_TYMED, (LONG)TYMED_CALLBACK ))
  230. {
  231. //
  232. // Set the preview property. Ignore failure (it is an optional property)
  233. //
  234. PropStorageHelpers::SetProperty( pIWiaItem, WIA_DPS_PREVIEW, 1 );
  235. WIA_TRACE((TEXT("SCANPROC.CPP: Making sure pIWiaItem is not NULL")));
  236. // Make sure pIWiaItem is not NULL
  237. if (pIWiaItem)
  238. {
  239. WIA_TRACE((TEXT("SCANPROC.CPP: Attempting banded transfer")));
  240. hr = ScanBandedTransfer( pIWiaItem );
  241. if (SUCCEEDED(hr))
  242. {
  243. if (IsWindow(m_hwndNotify))
  244. PostMessage( m_hwndNotify, m_nMsgProgress, SCAN_PROGRESS_SCANNING, 100 );
  245. if (IsWindow(m_hwndPreview))
  246. PostMessage( m_hwndPreview, PWM_SETBITMAP, MAKEWPARAM(1,0), (LPARAM)m_sImageData.DetachBitmap() );
  247. }
  248. else
  249. {
  250. WIA_PRINTHRESULT((hr,TEXT("SCANPROC.CPP: ScanBandedTransfer failed, attempting IDataObject transfer")));
  251. }
  252. }
  253. else
  254. {
  255. WIA_ERROR((TEXT("SCANPROC.CPP: pIWiaItem was null")));
  256. hr = MAKE_HRESULT(3,FACILITY_WIN32,ERROR_INVALID_FUNCTION);
  257. }
  258. }
  259. else
  260. {
  261. WIA_ERROR((TEXT("SCANPROC.CPP: Error setting scanner properties")));
  262. hr = MAKE_HRESULT(3,FACILITY_WIN32,ERROR_INVALID_FUNCTION);
  263. }
  264. // Restore the saved properties
  265. SavedProperties.ApplyToWiaItem(pIWiaItem);
  266. }
  267. else
  268. {
  269. WIA_ERROR((TEXT("SCANPROC.CPP: Error saving scanner properties")));
  270. }
  271. }
  272. else
  273. {
  274. WIA_ERROR((TEXT("SCANPROC.CPP: Unable to clear intent")));
  275. }
  276. }
  277. else
  278. {
  279. WIA_PRINTHRESULT((hr,TEXT("SCANPROC.CPP: Unable to unmarshall IWiaItem * from global interface table" )));
  280. }
  281. }
  282. else
  283. {
  284. WIA_PRINTHRESULT((hr,TEXT("SCANPROC.CPP: Unable to QI global interface table" )));
  285. }
  286. CoUninitialize();
  287. }
  288. else
  289. {
  290. WIA_PRINTHRESULT((hr,TEXT("SCANPROC.CPP: CoInitialize failed" )));
  291. }
  292. if (IsWindow(m_hwndNotify))
  293. PostMessage( m_hwndNotify, m_nMsgEnd, hr, 0 );
  294. if (IsWindow(m_hwndNotify))
  295. PostMessage( m_hwndNotify, m_nMsgProgress, SCAN_PROGRESS_COMPLETE, 0 );
  296. return(SUCCEEDED(hr));
  297. }
  298. // COM stuff
  299. HRESULT _stdcall CScanPreviewThread::QueryInterface( const IID& riid, void** ppvObject )
  300. {
  301. if (IsEqualIID( riid, IID_IUnknown ))
  302. {
  303. *ppvObject = static_cast<IWiaDataCallback*>(this);
  304. }
  305. else if (IsEqualIID( riid, IID_IWiaDataCallback ))
  306. {
  307. *ppvObject = static_cast<IWiaDataCallback*>(this);
  308. }
  309. else
  310. {
  311. *ppvObject = NULL;
  312. return(E_NOINTERFACE);
  313. }
  314. reinterpret_cast<IUnknown*>(*ppvObject)->AddRef();
  315. return(S_OK);
  316. }
  317. ULONG _stdcall CScanPreviewThread::AddRef()
  318. {
  319. return(1);
  320. }
  321. ULONG _stdcall CScanPreviewThread::Release()
  322. {
  323. return(1);
  324. }
  325. /*************************************************************************************************************************
  326. CScanToFileThread
  327. Scans to a file
  328. **************************************************************************************************************************/
  329. CScanToFileThread::CScanToFileThread(
  330. DWORD dwIWiaItemCookie, // specifies the entry in the global interface table
  331. HWND hwndNotify, // handle to the window that receives notifications
  332. GUID guidFormat,
  333. const CSimpleStringWide &strFilename // Filename to scan to
  334. )
  335. : m_dwIWiaItemCookie(dwIWiaItemCookie),
  336. m_hwndNotify(hwndNotify),
  337. m_nMsgBegin(RegisterWindowMessage(SCAN_NOTIFYBEGINSCAN)),
  338. m_nMsgEnd(RegisterWindowMessage(SCAN_NOTIFYENDSCAN)),
  339. m_nMsgProgress(RegisterWindowMessage(SCAN_NOTIFYPROGRESS)),
  340. m_guidFormat(guidFormat),
  341. m_strFilename(strFilename)
  342. {
  343. }
  344. // The actual thread proc for this thread
  345. DWORD CScanToFileThread::ThreadProc( LPVOID pParam )
  346. {
  347. DWORD dwResult = 0;
  348. CScanToFileThread *This = (CScanToFileThread *)pParam;
  349. if (This)
  350. {
  351. WIA_TRACE((TEXT("Beginning scan")));
  352. dwResult = (DWORD)This->Scan();
  353. WIA_TRACE((TEXT("Ending scan")));
  354. delete This;
  355. }
  356. return(dwResult);
  357. }
  358. // Returns a handle to the created thread
  359. HANDLE CScanToFileThread::Scan(
  360. DWORD dwIWiaItemCookie, // specifies the entry in the global interface table
  361. HWND hwndNotify, // handle to the window that receives notifications
  362. GUID guidFormat,
  363. const CSimpleStringWide &strFilename // Filename to save to
  364. )
  365. {
  366. CScanToFileThread *scanThread = new CScanToFileThread( dwIWiaItemCookie, hwndNotify, guidFormat, strFilename );
  367. if (scanThread)
  368. {
  369. DWORD dwThreadId;
  370. return(::CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc, scanThread, 0, &dwThreadId ));
  371. }
  372. return(NULL);
  373. }
  374. CScanToFileThread::~CScanToFileThread(void)
  375. {
  376. }
  377. /*
  378. * The worker which does the actual scan
  379. */
  380. bool CScanToFileThread::Scan(void)
  381. {
  382. WIA_PUSHFUNCTION(TEXT("CScanToFileThread::Scan"));
  383. if (IsWindow(m_hwndNotify))
  384. PostMessage( m_hwndNotify, m_nMsgBegin, 0, 0 );
  385. HRESULT hr = CoInitialize( NULL );
  386. if (SUCCEEDED(hr))
  387. {
  388. CComPtr<IGlobalInterfaceTable> pGlobalInterfaceTable;
  389. hr = CoCreateInstance( CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable, (void **)&pGlobalInterfaceTable );
  390. if (SUCCEEDED(hr))
  391. {
  392. CComPtr<IWiaItem> pIWiaItem;
  393. WIA_TRACE((TEXT("SCANPROC.CPP: Calling GetInterfaceFromGlobal(%08X) for IID_IWiaItem"),m_dwIWiaItemCookie));
  394. pGlobalInterfaceTable->GetInterfaceFromGlobal( m_dwIWiaItemCookie, IID_IWiaItem, (LPVOID*)&pIWiaItem );
  395. if (SUCCEEDED(hr))
  396. {
  397. CComPtr<IWiaTransferHelper> pWiaTransferHelper;
  398. hr = CoCreateInstance( CLSID_WiaDefaultUi, NULL, CLSCTX_INPROC_SERVER, IID_IWiaTransferHelper, (void**)&pWiaTransferHelper );
  399. if (SUCCEEDED(hr))
  400. {
  401. hr = pWiaTransferHelper->TransferItemFile( pIWiaItem, m_hwndNotify, 0, m_guidFormat, m_strFilename.String(), NULL, TYMED_FILE );
  402. if (!SUCCEEDED(hr))
  403. {
  404. WIA_PRINTHRESULT((hr,TEXT("SCANPROC.CPP: pWiaTransferHelper->TransferItemFile failed")));
  405. }
  406. }
  407. else
  408. {
  409. WIA_PRINTHRESULT((hr,TEXT("SCANPROC.CPP: CoCreateInstance on IID_IWiaTransferHelper failed")));
  410. }
  411. }
  412. else
  413. {
  414. WIA_PRINTHRESULT((hr,TEXT("SCANPROC.CPP: Unable to unmarshall IWiaItem * from global interface table" )));
  415. }
  416. }
  417. else
  418. {
  419. WIA_PRINTHRESULT((hr,TEXT("SCANPROC.CPP: Unable to QI global interface table" )));
  420. }
  421. CoUninitialize();
  422. }
  423. else
  424. {
  425. WIA_PRINTHRESULT((hr,TEXT("SCANPROC.CPP: CoInitialize failed" )));
  426. }
  427. if (IsWindow(m_hwndNotify))
  428. PostMessage( m_hwndNotify, m_nMsgEnd, hr, 0 );
  429. return(SUCCEEDED(hr));
  430. }