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.

338 lines
11 KiB

  1. #include "precomp.h"
  2. //
  3. // WIA data callback implementation
  4. //
  5. STDMETHODIMP_(ULONG) CWiaDataCallback::AddRef()
  6. {
  7. InterlockedIncrement((LONG*)&m_Ref);
  8. return m_Ref;
  9. }
  10. STDMETHODIMP_(ULONG) CWiaDataCallback::Release()
  11. {
  12. if (!InterlockedDecrement((LONG*)&m_Ref)) {
  13. m_Ref++;
  14. delete this;
  15. return(ULONG) 0;
  16. }
  17. return m_Ref;
  18. }
  19. STDMETHODIMP CWiaDataCallback::QueryInterface(REFIID iid, void **ppv)
  20. {
  21. if (!ppv)
  22. return E_INVALIDARG;
  23. *ppv = NULL;
  24. if (IID_IUnknown == iid) {
  25. *ppv = (IUnknown*)this;
  26. AddRef();
  27. return S_OK;
  28. } else if (IID_IWiaDataCallback == iid) {
  29. *ppv = (IWiaDataCallback *)this;
  30. AddRef();
  31. return S_OK;
  32. }
  33. return E_NOINTERFACE;
  34. }
  35. HRESULT CWiaDataCallback::Initialize(HWND hWndOwner,BOOL bShowProgress)
  36. {
  37. m_hwndOwner = hWndOwner;
  38. if (bShowProgress) {
  39. if (NULL == m_pProgDlg) {
  40. m_pProgDlg = new CProgressDlg();
  41. if (!m_pProgDlg) {
  42. return E_OUTOFMEMORY;
  43. }
  44. m_pProgDlg->Initialize(g_hInstance, IDD_PROGRESSDLG);
  45. }
  46. //
  47. // Preload progress title strings
  48. //
  49. m_pszXferFromDevice = LoadResourceString(IDS_PROGRESS_XFER_FROM_DEVICE);
  50. m_pszProcessingData = LoadResourceString(IDS_PROGRESS_PROCESSING_DATA);
  51. m_pszXferToClient = LoadResourceString(IDS_PROGRESS_XFER_TO_CLIENT);
  52. m_bSetTitle = FALSE;
  53. if (!m_pszXferFromDevice || !m_pszProcessingData || !m_pszXferToClient) {
  54. return HRESULT_FROM_WIN32(GetLastError());
  55. }
  56. if (m_pProgDlg->DoModeless(m_hwndOwner, (LPARAM)m_pProgDlg)) {
  57. m_pProgDlg->SetRange(0, 100);
  58. m_pProgDlg->SetPos(0);
  59. m_lCurrentTextUpdate = TITLE_TRANSFERTOCLIENT;
  60. m_pProgDlg->SetTitle(m_pszXferToClient);
  61. } else {
  62. DBG_ERR(("DoModeless Failed to create Progress Dialog"));
  63. }
  64. }
  65. return S_OK;
  66. }
  67. #define WIADSMSG_PROGRESS MSG_USER + 0
  68. STDMETHODIMP CWiaDataCallback::BandedDataCallback(LONG lMessage,LONG lStatus,LONG lPercentComplete,
  69. LONG lOffset,LONG Length,LONG lReserved,
  70. LONG lResLength,BYTE *pData)
  71. {
  72. HRESULT hr = S_OK;
  73. switch (lMessage) {
  74. case IT_MSG_FILE_PREVIEW_DATA_HEADER: // we do nothing with file preview header data
  75. break;
  76. case IT_MSG_DATA_HEADER:
  77. {
  78. PWIA_DATA_CALLBACK_HEADER pHeader = NULL;
  79. pHeader = (PWIA_DATA_CALLBACK_HEADER)pData;
  80. if(pHeader->guidFormatID == WiaImgFmt_MEMORYBMP){
  81. DBG_TRC(("pHeader->guidFormatID = WiaImgFmt_MEMORYBMP"));
  82. m_bBitmapData = TRUE;
  83. } else if(pHeader->guidFormatID == WiaImgFmt_MEMORYBMP){
  84. DBG_TRC(("pHeader->guidFormatID = WiaImgFmt_RAWRGB"));
  85. m_bBitmapData = FALSE;
  86. } else {
  87. DBG_TRC(("pHeader->guidFormatID = (unknown)"));
  88. m_bBitmapData = TRUE;
  89. }
  90. m_MemBlockSize = pHeader->lBufferSize;
  91. DBG_TRC(("CWiaDataCallback::BandedDataCallback(), IT_MSG_DATA_HEADER Reports"));
  92. DBG_TRC(("pHeader->lBufferSize = %d",pHeader->lBufferSize));
  93. DBG_TRC(("pHeader->lPageCount = %d",pHeader->lPageCount));
  94. DBG_TRC(("pHeader->lSize = %d",pHeader->lSize));
  95. //
  96. // if we get a lbuffer size of zero, allocate one for us,
  97. // and maintain the size.
  98. //
  99. DBG_TRC(("MemBlockSize = %d",pHeader->lBufferSize));
  100. if(m_MemBlockSize <= 0){
  101. m_MemBlockSize = (520288 * 2);
  102. DBG_WRN(("CWiaDataCallback::BandedDataCallback(), adjusting MemBlockSize to %d",m_MemBlockSize));
  103. }
  104. if (m_hImage) {
  105. GlobalFree(m_hImage);
  106. m_hImage = NULL;
  107. m_pImage = NULL;
  108. m_ImageSize = 0;
  109. m_SizeTransferred = 0;
  110. }
  111. m_SizeTransferred = 0;
  112. //
  113. // allocate the buffer
  114. //
  115. m_hImage = (HGLOBAL)GlobalAlloc(GHND, m_MemBlockSize);
  116. hr = E_OUTOFMEMORY;
  117. if (m_hImage) {
  118. hr = S_OK;
  119. }
  120. break;
  121. }
  122. case IT_MSG_FILE_PREVIEW_DATA: // we do nothing with file preview data
  123. break;
  124. case IT_MSG_DATA:
  125. {
  126. m_SizeTransferred += Length;
  127. if((LONG)m_SizeTransferred >= m_MemBlockSize){
  128. m_MemBlockSize += (Length * MEMORY_BLOCK_FACTOR);
  129. //
  130. // process allocation into a temp handle, and fail, if allocation
  131. // fails.
  132. //
  133. HGLOBAL hTempMemory = (HGLOBAL)GlobalReAlloc(m_hImage,m_MemBlockSize,LMEM_MOVEABLE);
  134. if(hTempMemory){
  135. m_hImage = hTempMemory;
  136. } else {
  137. if(m_hImage){
  138. GlobalFree(m_hImage);
  139. m_hImage = NULL;
  140. }
  141. return E_OUTOFMEMORY;
  142. }
  143. }
  144. //
  145. // lock memory down
  146. //
  147. m_pImage = (BYTE*)GlobalLock(m_hImage);
  148. if (m_pImage) {
  149. DBG_TRC(("Copying %d into m_pImage (m_hImage = 0x%X, m_pImage = 0x%X) buffer",Length,m_hImage,m_pImage));
  150. memcpy(m_pImage + lOffset, pData, Length);
  151. //
  152. // unlock memory
  153. //
  154. GlobalUnlock(m_hImage);
  155. } else {
  156. DBG_ERR(("Could not lock down m_hImage memory block"));
  157. }
  158. /*
  159. if (Length == 40) {
  160. BITMAPINFOHEADER* pbmi = NULL;
  161. pbmi = (BITMAPINFOHEADER*)pData;
  162. DBG_TRC(("CWiaDataCallback::BandedDataCallback(), Reported BITMAPINFOHEADER from IT_MSG_DATA"));
  163. DBG_TRC(("pbmi->biSize = %d",pbmi->biSize));
  164. DBG_TRC(("pbmi->biSizeImage = %d",pbmi->biSizeImage));
  165. DBG_TRC(("pbmi->biBitCount = %d",pbmi->biBitCount));
  166. DBG_TRC(("pbmi->biClrImportant = %d",pbmi->biClrImportant));
  167. DBG_TRC(("pbmi->biClrUsed = %d",pbmi->biClrUsed));
  168. DBG_TRC(("pbmi->biCompression = %d",pbmi->biCompression));
  169. DBG_TRC(("pbmi->biHeight = %d",pbmi->biHeight));
  170. DBG_TRC(("pbmi->biWidth = %d",pbmi->biWidth));
  171. DBG_TRC(("pbmi->biPlanes = %d",pbmi->biPlanes));
  172. DBG_TRC(("pbmi->biXPelsPerMeter = %d",pbmi->biXPelsPerMeter));
  173. DBG_TRC(("pbmi->biYPelsPerMeter = %d",pbmi->biYPelsPerMeter));
  174. }
  175. */
  176. if (m_pProgDlg) {
  177. m_lCurrentTextUpdate = TITLE_TRANSFERTOCLIENT;
  178. if(m_lLastTextUpdate != m_lCurrentTextUpdate){
  179. m_lLastTextUpdate = m_lCurrentTextUpdate;
  180. m_pProgDlg->SetTitle(m_pszXferToClient);
  181. }
  182. m_pProgDlg->SetPos(lPercentComplete);
  183. }
  184. }
  185. break;
  186. case IT_MSG_STATUS:
  187. if (m_pProgDlg) {
  188. if (lStatus & IT_STATUS_TRANSFER_FROM_DEVICE) {
  189. m_lCurrentTextUpdate = TITLE_FROMDEVICE;
  190. if(m_lLastTextUpdate != m_lCurrentTextUpdate){
  191. m_lLastTextUpdate = m_lCurrentTextUpdate;
  192. m_pProgDlg->SetTitle(m_pszXferFromDevice);
  193. }
  194. } else if (lStatus & IT_STATUS_PROCESSING_DATA) {
  195. m_lCurrentTextUpdate = TITLE_PROCESSINGDATA;
  196. if(m_lLastTextUpdate != m_lCurrentTextUpdate){
  197. m_lLastTextUpdate = m_lCurrentTextUpdate;
  198. m_pProgDlg->SetTitle(m_pszProcessingData);
  199. }
  200. } else if (lStatus & IT_STATUS_TRANSFER_TO_CLIENT) {
  201. m_lCurrentTextUpdate = TITLE_TRANSFERTOCLIENT;
  202. if(m_lLastTextUpdate != m_lCurrentTextUpdate){
  203. m_lLastTextUpdate = m_lCurrentTextUpdate;
  204. m_pProgDlg->SetTitle(m_pszXferToClient);
  205. }
  206. }
  207. m_pProgDlg->SetPos(lPercentComplete);
  208. }
  209. break;
  210. case IT_MSG_TERMINATION:
  211. if (m_pProgDlg) {
  212. delete m_pProgDlg;
  213. m_pProgDlg = NULL;
  214. }
  215. break;
  216. default:
  217. break;
  218. }
  219. //
  220. // check for user cancel operation
  221. //
  222. if (m_pProgDlg && m_pProgDlg->CheckCancelled()) {
  223. hr = S_FALSE;
  224. }
  225. //
  226. // transfer failed, or user pressed cancel
  227. //
  228. if (FAILED(hr) || S_FALSE == hr) {
  229. if(FAILED(hr)){
  230. DBG_ERR(("CWiaDataCallback::BandedDataCallback(), The transfer failed"));
  231. } else {
  232. DBG_WRN(("CWiaDataCallback::BandedDataCallback(), The user pressed cancel"));
  233. }
  234. if (m_pProgDlg) {
  235. delete m_pProgDlg;
  236. m_pProgDlg = NULL;
  237. }
  238. }
  239. //
  240. // save last hr
  241. //
  242. m_hrLast = hr;
  243. return hr;
  244. }
  245. HRESULT CWiaDataCallback::GetImage(HGLOBAL *phImage,ULONG *pImageSize)
  246. {
  247. if (!phImage)
  248. return E_INVALIDARG;
  249. if (pImageSize)
  250. *pImageSize = 0;
  251. *phImage = NULL;
  252. if (SUCCEEDED(m_hrLast)) {
  253. if (m_bBitmapData) {
  254. //
  255. // we need to adjust any headers, because the height and image size information
  256. // could be incorrect. (this will handle infinite page length devices)
  257. //
  258. BITMAPINFOHEADER *pbmh = NULL;
  259. pbmh = (BITMAPINFOHEADER*)GlobalLock(m_hImage);
  260. if (pbmh) {
  261. // only fix the BITMAPINFOHEADER if height needs to be calculated
  262. if (pbmh->biHeight == 0) {
  263. LONG lPaletteSize = pbmh->biClrUsed * sizeof(RGBQUAD);
  264. LONG lWidthBytes = CalculateWidthBytes(pbmh->biWidth,pbmh->biBitCount);
  265. pbmh->biSizeImage = m_SizeTransferred - lPaletteSize - sizeof(BITMAPINFOHEADER);
  266. pbmh->biHeight = -(LONG)(pbmh->biSizeImage/lWidthBytes); // 0 also means upside down
  267. pbmh->biXPelsPerMeter = 0; // zero out
  268. pbmh->biYPelsPerMeter = 0; // zero out
  269. }
  270. m_lImageHeight = abs(pbmh->biHeight);
  271. m_lImageWidth = abs(pbmh->biWidth);
  272. GlobalUnlock(m_hImage);
  273. }
  274. }
  275. if (pImageSize){
  276. *pImageSize = m_SizeTransferred;
  277. }
  278. *phImage = m_hImage;
  279. //
  280. // reset internal variables, for next data transfer
  281. //
  282. m_hImage = NULL;
  283. m_pImage = NULL;
  284. m_SizeTransferred = 0;
  285. DBG_TRC(("CWiaDataCallback::GetImage(), Returned 0x%X (HANDLE pointer)",*phImage));
  286. }
  287. return m_hrLast;
  288. }
  289. LONG CWiaDataCallback::CalculateWidthBytes(LONG lWidthPixels,LONG lbpp)
  290. {
  291. LONG lWidthBytes = 0;
  292. lWidthBytes = (lWidthPixels * lbpp) + 31;
  293. lWidthBytes = ((lWidthBytes/8) & 0xfffffffc);
  294. return lWidthBytes;
  295. }