int DnDManager::nextMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) { if (!m_pCurMsg) { /* Check for pending messages in our queue. */ if (m_dndMessageQueue.isEmpty()) return VERR_NO_DATA; m_pCurMsg = m_dndMessageQueue.first(); m_dndMessageQueue.removeFirst(); } /* Fetch the current message info */ int rc = m_pCurMsg->currentMessage(uMsg, cParms, paParms); /* If this message not provide any additional sub messages, clear it. */ if (!m_pCurMsg->isMessageWaiting()) { delete m_pCurMsg; m_pCurMsg = 0; } /* If the user has canceled the operation, we need to cleanup all pending * events and inform the progress callback about our successful cleanup. */ if ( rc == VERR_CANCELLED && m_pfnProgressCallback) { /* Clear any pending messages */ clear(); /* Create a new cancel message to inform the guest. */ m_pCurMsg = new DnDHGCancelMessage(); m_pfnProgressCallback(100.0, DragAndDropSvc::DND_PROGRESS_CANCELLED, m_pvProgressUser); } DO(("next msg: %d %d %Rrc\n", uMsg, cParms, rc)); return rc; }
int DnDManager::nextMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) { LogFlowFunc(("uMsg=%RU32, cParms=%RU32\n", uMsg, cParms)); if (!m_pCurMsg) { /* Check for pending messages in our queue. */ if (m_dndMessageQueue.isEmpty()) { LogFlowFunc(("Message queue is empty, returning\n")); return VERR_NO_DATA; } m_pCurMsg = m_dndMessageQueue.first(); m_dndMessageQueue.removeFirst(); } /* Fetch the current message info */ int rc = m_pCurMsg->currentMessage(uMsg, cParms, paParms); /* If this message doesn't provide any additional sub messages, clear it. */ if (!m_pCurMsg->isMessageWaiting()) { delete m_pCurMsg; m_pCurMsg = NULL; } /* * If there was an error handling the current message or the user has canceled * the operation, we need to cleanup all pending events and inform the progress * callback about our exit. */ if ( RT_FAILURE(rc) && m_pfnProgressCallback) { /* Clear any pending messages. */ clear(); /* Create a new cancel message to inform the guest + call * the host whether the current transfer was canceled or aborted * due to an error. */ try { Assert(!m_pCurMsg); m_pCurMsg = new DnDHGCancelMessage(); m_pfnProgressCallback(100 /* Percent */, rc == VERR_CANCELLED ? DragAndDropSvc::DND_PROGRESS_CANCELLED : DragAndDropSvc::DND_PROGRESS_ERROR, rc, m_pvProgressUser); } catch(std::bad_alloc &) { rc = VERR_NO_MEMORY; } } LogFlowFunc(("Message processed with rc=%Rrc\n", rc)); return rc; }
int currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) { int rc = DnDMessage::currentMessage(uMsg, cParms, paParms); /* Advance progress info */ if ( RT_SUCCESS(rc) && m_pfnProgressCallback) rc = m_pfnProgressCallback(m_URIObject.GetSize(), m_pvProgressUser); return rc; }
STDMETHODIMP CDataCallback::BandedDataCallback( LONG lReason, LONG lStatus, LONG lPercentComplete, LONG lOffset, LONG lLength, LONG, LONG, PBYTE pbBuffer ) { HRESULT hr; // Parse the message switch (lReason) { case IT_MSG_DATA_HEADER: { PWIA_DATA_CALLBACK_HEADER pHeader = (PWIA_DATA_CALLBACK_HEADER) pbBuffer; // Determine if this is a BMP transfer m_bBMP = pHeader->guidFormatID == WiaImgFmt_MEMORYBMP || pHeader->guidFormatID == WiaImgFmt_BMP; // For WiaImgFmt_MEMORYBMP transfers, WIA does not send a BITMAPFILEHEADER before the data. // In this program, we desire all BMP files to contain a BITMAPFILEHEADER, so add it manually m_nHeaderSize = pHeader->guidFormatID == WiaImgFmt_MEMORYBMP ? sizeof(BITMAPFILEHEADER) : 0; // Allocate memory for the image if the size is given in the header if (pHeader != NULL && pHeader->lBufferSize != 0) { hr = ReAllocBuffer(m_nHeaderSize + pHeader->lBufferSize); if (FAILED(hr)) { return hr; } } break; } case IT_MSG_DATA: { // Invoke the callback function hr = m_pfnProgressCallback(lStatus, lPercentComplete, m_pProgressCallbackParam); if (FAILED(hr) || hr == S_FALSE) { return hr; } // If the buffer is not allocated yet and this is the first block, // and the transferred image is in BMP format, allocate the buffer // according to the size information in the bitmap header if (m_pStream == NULL && lOffset == 0 && m_bBMP) { LONG nBufferSize = BitmapUtil::GetBitmapSize(pbBuffer); if (nBufferSize != 0) { hr = ReAllocBuffer(m_nHeaderSize + nBufferSize); if (FAILED(hr)) { return hr; } } } if (m_nHeaderSize + lOffset + lLength < 0) { return E_OUTOFMEMORY; } // If the transfer goes past the buffer, try to expand it if (m_nHeaderSize + lOffset + lLength > m_nDataSize) { hr = ReAllocBuffer(m_nHeaderSize + lOffset + lLength); if (FAILED(hr)) { return hr; } } // copy the transfer buffer hr = CopyToBuffer(m_nHeaderSize + lOffset, pbBuffer, lLength); if (FAILED(hr)) { return hr; } break; } case IT_MSG_STATUS: { // Invoke the callback function hr = m_pfnProgressCallback(lStatus, lPercentComplete, m_pProgressCallbackParam); if (FAILED(hr) || hr == S_FALSE) { return hr; } break; } case IT_MSG_TERMINATION: case IT_MSG_NEW_PAGE: { if (m_pStream != NULL) { // For BMP files, we should validate the the image header // So, obtain the memory buffer from the stream if (m_bBMP) { // Since the stream is created using CreateStreamOnHGlobal, // we can get the memory buffer with GetHGlobalFromStream. HGLOBAL hBuffer; hr = GetHGlobalFromStream(m_pStream, &hBuffer); if (FAILED(hr)) { return hr; } PBITMAPFILEHEADER pBuffer = (PBITMAPFILEHEADER) GlobalLock(hBuffer); if (pBuffer == NULL) { return HRESULT_FROM_WIN32(GetLastError()); } // Some scroll-fed scanners may return 0 as the bitmap height // In this case, calculate the image height and modify the header BitmapUtil::FixBitmapHeight(pBuffer + 1, m_nDataSize, TRUE); // For WiaImgFmt_MEMORYBMP transfers, the WIA service does not // include a BITMAPFILEHEADER preceeding the bitmap data. // In this case, fill in the BITMAPFILEHEADER structure. if (m_nHeaderSize != 0) { BitmapUtil::FillBitmapFileHeader(pBuffer + 1, pBuffer); } GlobalUnlock(hBuffer); } // Store this buffer in the successfully transferred images array hr = StoreBuffer(); if (FAILED(hr)) { return hr; } } break; } } return S_OK; }