#include "precomp.h" // // WIA data callback implementation // STDMETHODIMP_(ULONG) CWiaDataCallback::AddRef() { InterlockedIncrement((LONG*)&m_Ref); return m_Ref; } STDMETHODIMP_(ULONG) CWiaDataCallback::Release() { if (!InterlockedDecrement((LONG*)&m_Ref)) { m_Ref++; delete this; return(ULONG) 0; } return m_Ref; } STDMETHODIMP CWiaDataCallback::QueryInterface(REFIID iid, void **ppv) { if (!ppv) return E_INVALIDARG; *ppv = NULL; if (IID_IUnknown == iid) { *ppv = (IUnknown*)this; AddRef(); return S_OK; } else if (IID_IWiaDataCallback == iid) { *ppv = (IWiaDataCallback *)this; AddRef(); return S_OK; } return E_NOINTERFACE; } HRESULT CWiaDataCallback::Initialize(HWND hWndOwner,BOOL bShowProgress) { m_hwndOwner = hWndOwner; if (bShowProgress) { if (NULL == m_pProgDlg) { m_pProgDlg = new CProgressDlg(); if (!m_pProgDlg) { return E_OUTOFMEMORY; } m_pProgDlg->Initialize(g_hInstance, IDD_PROGRESSDLG); } // // Preload progress title strings // m_pszXferFromDevice = LoadResourceString(IDS_PROGRESS_XFER_FROM_DEVICE); m_pszProcessingData = LoadResourceString(IDS_PROGRESS_PROCESSING_DATA); m_pszXferToClient = LoadResourceString(IDS_PROGRESS_XFER_TO_CLIENT); m_bSetTitle = FALSE; if (!m_pszXferFromDevice || !m_pszProcessingData || !m_pszXferToClient) { return HRESULT_FROM_WIN32(GetLastError()); } if (m_pProgDlg->DoModeless(m_hwndOwner, (LPARAM)m_pProgDlg)) { m_pProgDlg->SetRange(0, 100); m_pProgDlg->SetPos(0); m_lCurrentTextUpdate = TITLE_TRANSFERTOCLIENT; m_pProgDlg->SetTitle(m_pszXferToClient); } else { DBG_ERR(("DoModeless Failed to create Progress Dialog")); } } return S_OK; } #define WIADSMSG_PROGRESS MSG_USER + 0 STDMETHODIMP CWiaDataCallback::BandedDataCallback(LONG lMessage,LONG lStatus,LONG lPercentComplete, LONG lOffset,LONG Length,LONG lReserved, LONG lResLength,BYTE *pData) { HRESULT hr = S_OK; switch (lMessage) { case IT_MSG_FILE_PREVIEW_DATA_HEADER: // we do nothing with file preview header data break; case IT_MSG_DATA_HEADER: { PWIA_DATA_CALLBACK_HEADER pHeader = NULL; pHeader = (PWIA_DATA_CALLBACK_HEADER)pData; if(pHeader->guidFormatID == WiaImgFmt_MEMORYBMP){ DBG_TRC(("pHeader->guidFormatID = WiaImgFmt_MEMORYBMP")); m_bBitmapData = TRUE; } else if(pHeader->guidFormatID == WiaImgFmt_MEMORYBMP){ DBG_TRC(("pHeader->guidFormatID = WiaImgFmt_RAWRGB")); m_bBitmapData = FALSE; } else { DBG_TRC(("pHeader->guidFormatID = (unknown)")); m_bBitmapData = TRUE; } m_MemBlockSize = pHeader->lBufferSize; DBG_TRC(("CWiaDataCallback::BandedDataCallback(), IT_MSG_DATA_HEADER Reports")); DBG_TRC(("pHeader->lBufferSize = %d",pHeader->lBufferSize)); DBG_TRC(("pHeader->lPageCount = %d",pHeader->lPageCount)); DBG_TRC(("pHeader->lSize = %d",pHeader->lSize)); // // if we get a lbuffer size of zero, allocate one for us, // and maintain the size. // DBG_TRC(("MemBlockSize = %d",pHeader->lBufferSize)); if(m_MemBlockSize <= 0){ m_MemBlockSize = (520288 * 2); DBG_WRN(("CWiaDataCallback::BandedDataCallback(), adjusting MemBlockSize to %d",m_MemBlockSize)); } if (m_hImage) { GlobalFree(m_hImage); m_hImage = NULL; m_pImage = NULL; m_ImageSize = 0; m_SizeTransferred = 0; } m_SizeTransferred = 0; // // allocate the buffer // m_hImage = (HGLOBAL)GlobalAlloc(GHND, m_MemBlockSize); hr = E_OUTOFMEMORY; if (m_hImage) { hr = S_OK; } break; } case IT_MSG_FILE_PREVIEW_DATA: // we do nothing with file preview data break; case IT_MSG_DATA: { m_SizeTransferred += Length; if((LONG)m_SizeTransferred >= m_MemBlockSize){ m_MemBlockSize += (Length * MEMORY_BLOCK_FACTOR); // // process allocation into a temp handle, and fail, if allocation // fails. // HGLOBAL hTempMemory = (HGLOBAL)GlobalReAlloc(m_hImage,m_MemBlockSize,LMEM_MOVEABLE); if(hTempMemory){ m_hImage = hTempMemory; } else { if(m_hImage){ GlobalFree(m_hImage); m_hImage = NULL; } return E_OUTOFMEMORY; } } // // lock memory down // m_pImage = (BYTE*)GlobalLock(m_hImage); if (m_pImage) { DBG_TRC(("Copying %d into m_pImage (m_hImage = 0x%X, m_pImage = 0x%X) buffer",Length,m_hImage,m_pImage)); memcpy(m_pImage + lOffset, pData, Length); // // unlock memory // GlobalUnlock(m_hImage); } else { DBG_ERR(("Could not lock down m_hImage memory block")); } /* if (Length == 40) { BITMAPINFOHEADER* pbmi = NULL; pbmi = (BITMAPINFOHEADER*)pData; DBG_TRC(("CWiaDataCallback::BandedDataCallback(), Reported BITMAPINFOHEADER from IT_MSG_DATA")); DBG_TRC(("pbmi->biSize = %d",pbmi->biSize)); DBG_TRC(("pbmi->biSizeImage = %d",pbmi->biSizeImage)); DBG_TRC(("pbmi->biBitCount = %d",pbmi->biBitCount)); DBG_TRC(("pbmi->biClrImportant = %d",pbmi->biClrImportant)); DBG_TRC(("pbmi->biClrUsed = %d",pbmi->biClrUsed)); DBG_TRC(("pbmi->biCompression = %d",pbmi->biCompression)); DBG_TRC(("pbmi->biHeight = %d",pbmi->biHeight)); DBG_TRC(("pbmi->biWidth = %d",pbmi->biWidth)); DBG_TRC(("pbmi->biPlanes = %d",pbmi->biPlanes)); DBG_TRC(("pbmi->biXPelsPerMeter = %d",pbmi->biXPelsPerMeter)); DBG_TRC(("pbmi->biYPelsPerMeter = %d",pbmi->biYPelsPerMeter)); } */ if (m_pProgDlg) { m_lCurrentTextUpdate = TITLE_TRANSFERTOCLIENT; if(m_lLastTextUpdate != m_lCurrentTextUpdate){ m_lLastTextUpdate = m_lCurrentTextUpdate; m_pProgDlg->SetTitle(m_pszXferToClient); } m_pProgDlg->SetPos(lPercentComplete); } } break; case IT_MSG_STATUS: if (m_pProgDlg) { if (lStatus & IT_STATUS_TRANSFER_FROM_DEVICE) { m_lCurrentTextUpdate = TITLE_FROMDEVICE; if(m_lLastTextUpdate != m_lCurrentTextUpdate){ m_lLastTextUpdate = m_lCurrentTextUpdate; m_pProgDlg->SetTitle(m_pszXferFromDevice); } } else if (lStatus & IT_STATUS_PROCESSING_DATA) { m_lCurrentTextUpdate = TITLE_PROCESSINGDATA; if(m_lLastTextUpdate != m_lCurrentTextUpdate){ m_lLastTextUpdate = m_lCurrentTextUpdate; m_pProgDlg->SetTitle(m_pszProcessingData); } } else if (lStatus & IT_STATUS_TRANSFER_TO_CLIENT) { m_lCurrentTextUpdate = TITLE_TRANSFERTOCLIENT; if(m_lLastTextUpdate != m_lCurrentTextUpdate){ m_lLastTextUpdate = m_lCurrentTextUpdate; m_pProgDlg->SetTitle(m_pszXferToClient); } } m_pProgDlg->SetPos(lPercentComplete); } break; case IT_MSG_TERMINATION: if (m_pProgDlg) { delete m_pProgDlg; m_pProgDlg = NULL; } break; default: break; } // // check for user cancel operation // if (m_pProgDlg && m_pProgDlg->CheckCancelled()) { hr = S_FALSE; } // // transfer failed, or user pressed cancel // if (FAILED(hr) || S_FALSE == hr) { if(FAILED(hr)){ DBG_ERR(("CWiaDataCallback::BandedDataCallback(), The transfer failed")); } else { DBG_WRN(("CWiaDataCallback::BandedDataCallback(), The user pressed cancel")); } if (m_pProgDlg) { delete m_pProgDlg; m_pProgDlg = NULL; } } // // save last hr // m_hrLast = hr; return hr; } HRESULT CWiaDataCallback::GetImage(HGLOBAL *phImage,ULONG *pImageSize) { if (!phImage) return E_INVALIDARG; if (pImageSize) *pImageSize = 0; *phImage = NULL; if (SUCCEEDED(m_hrLast)) { if (m_bBitmapData) { // // we need to adjust any headers, because the height and image size information // could be incorrect. (this will handle infinite page length devices) // BITMAPINFOHEADER *pbmh = NULL; pbmh = (BITMAPINFOHEADER*)GlobalLock(m_hImage); if (pbmh) { // only fix the BITMAPINFOHEADER if height needs to be calculated if (pbmh->biHeight == 0) { LONG lPaletteSize = pbmh->biClrUsed * sizeof(RGBQUAD); LONG lWidthBytes = CalculateWidthBytes(pbmh->biWidth,pbmh->biBitCount); pbmh->biSizeImage = m_SizeTransferred - lPaletteSize - sizeof(BITMAPINFOHEADER); pbmh->biHeight = -(LONG)(pbmh->biSizeImage/lWidthBytes); // 0 also means upside down pbmh->biXPelsPerMeter = 0; // zero out pbmh->biYPelsPerMeter = 0; // zero out } m_lImageHeight = abs(pbmh->biHeight); m_lImageWidth = abs(pbmh->biWidth); GlobalUnlock(m_hImage); } } if (pImageSize){ *pImageSize = m_SizeTransferred; } *phImage = m_hImage; // // reset internal variables, for next data transfer // m_hImage = NULL; m_pImage = NULL; m_SizeTransferred = 0; DBG_TRC(("CWiaDataCallback::GetImage(), Returned 0x%X (HANDLE pointer)",*phImage)); } return m_hrLast; } LONG CWiaDataCallback::CalculateWidthBytes(LONG lWidthPixels,LONG lbpp) { LONG lWidthBytes = 0; lWidthBytes = (lWidthPixels * lbpp) + 31; lWidthBytes = ((lWidthBytes/8) & 0xfffffffc); return lWidthBytes; }