📄 wiadriver.cpp
字号:
else
{
WIAS_ERROR((g_hInst, "wiasReadPropLong(WIA_IPS_PHOTOMETRIC_INTERP) failed, hr: 0x%X", hr));
}
}
//
// The discrete bits per channel table is described by the new WIA_IPA_RAW_BITS_PER_CHANNEL:
//
if(S_OK == hr)
{
memset(&RawHeader.BitsPerChannel[0], 0, sizeof(RawHeader.BitsPerChannel));
PROPSPEC ps;
ps.ulKind = PRSPEC_PROPID;
ps.propid = WIA_IPA_RAW_BITS_PER_CHANNEL;
PROPVARIANT pv = {0};
hr = wiasReadMultiple(pWiasContext, 1, &ps, &pv, NULL);
if(S_OK == hr)
{
ULONG ulItemCount = (pv.caub.cElems > 8) ? 8 : pv.caub.cElems;
for(ULONG i = 0; i < pv.caub.cElems; i++)
{
RawHeader.BitsPerChannel[i] = *(BYTE *)((BYTE *)pv.caub.pElems + i * sizeof(BYTE));
}
}
}
//
// In the case of this sample the image data is retrieved from a resource bitmap.
//
// Important: this bitmap must be initialized by the WiaDevice::InitializeForDownload
// before calling this function.
//
if(S_OK == hr)
{
if(!m_WiaDevice.InitializedForDownload())
{
//
// S_FALSE returned from this function would be interpreted as a cancel request:
//
hr = E_INVALIDARG;
WIAS_ERROR((g_hInst, "Bitmap not initialized correctly, hr: 0x%X", hr));
}
}
if(S_OK == hr)
{
//
// For the line order use the BitmapData object initialized for the sample bitmap that
// we are using: the "Stride" field value sign indicates the line order:
//
RawHeader.LineOrder = ((m_WiaDevice.GetBitmapData())->Stride < 0) ?
WIA_LINE_ORDER_BOTTOM_TO_TOP : WIA_LINE_ORDER_TOP_TO_BOTTOM;
//
// We won't be using a color palette here but it would be possible to try to retrieve
// the color palette, if any, from the DIB header describing the sample bitmap:
//
RawHeader.PaletteSize = 0;
RawHeader.PaletteOffset = 0;
}
//
// Write the header to the stream provided to us:
//
ULONG ulBytesWritten = 0;
if(S_OK == hr)
{
hr = pDestination->Write(&RawHeader, RawHeader.HeaderSize, &ulBytesWritten);
}
return hr;
}
HRESULT CWIADriver::DownloadToStream( LONG lFlags,
__in BYTE *pWiasContext,
__in PMINIDRV_TRANSFER_CONTEXT pmdtc,
const GUID &guidItemCategory,
const GUID &guidFormatID,
__callback IWiaMiniDrvTransferCallback *pTransferCallback,
__out LONG *plDevErrVal)
{
HRESULT hr = S_OK;
BSTR bstrItemName = NULL;
BSTR bstrFullItemName = NULL;
UINT uiBitmapResourceID = GetBitmapResourceIDFromCategory(guidItemCategory);
//
// A maximum of 10 image transfers (including final and preview scans) can be requested
// from the Feeder item before the driver will return WIA_ERROR_PAPER_EMPTY. In order to
// reset the counter (used only for the Feeder item) the application must change a Feeder
// item property current value or reload the driver.
//
// IMPORTANT:
//
// Legacy WIA applications such as Scan Wizard requires WIA_ERROR_PAPER_EMPTY
// (as the return code for IWiaMiniDrv::drvAcquireItemData) in order to stop
// normally a Feeder acquisition sequence.
//
WIA_DRIVER_ITEM_CONTEXT *pWiaDriverItemContext = NULL;
hr = wiasGetDriverItemPrivateContext(pWiasContext, (BYTE**)&pWiaDriverItemContext);
if ((!pWiaDriverItemContext) && (SUCCEEDED(hr)))
{
hr = E_POINTER;
}
if (FAILED(hr))
{
WIAS_ERROR((g_hInst, "Failed to get private driver item context data, hr = 0x%lx", hr));
}
const ULONG ulMaxTransfers = 10;
if ((SUCCEEDED(hr)) && (IsEqualGUID(WIA_CATEGORY_FEEDER, guidItemCategory)))
{
//
// Limit the number of "continuous" transfers from the Feeder item -
// without this Scan Wizard would not stop requesting transfers:
//
if (pWiaDriverItemContext->ulFeederTransferCount >= ulMaxTransfers)
{
hr = WIA_ERROR_PAPER_EMPTY;
}
}
if (S_OK == hr)
{
// Get the item name
hr = wiasReadPropStr(pWiasContext, WIA_IPA_ITEM_NAME, &bstrItemName, NULL, TRUE);
if (SUCCEEDED(hr))
{
// Get the full item name
hr = wiasReadPropStr(pWiasContext, WIA_IPA_FULL_ITEM_NAME, &bstrFullItemName, NULL, TRUE);
if (SUCCEEDED(hr))
{
// Get the destination stream
IStream *pDestination = NULL;
hr = pTransferCallback->GetNextStream(0, bstrItemName, bstrFullItemName, &pDestination);
if (hr == S_OK)
{
WiaTransferParams *pParams = (WiaTransferParams*)CoTaskMemAlloc(sizeof(WiaTransferParams));
if (pParams)
{
memset(pParams, 0, sizeof(WiaTransferParams));
BYTE *pBuffer = NULL;
ULONG ulBufferSize = 0;
hr = AllocateTransferBuffer(pWiasContext, &pBuffer, &ulBufferSize);
if (SUCCEEDED(hr))
{
if ((S_OK == hr) && (guidItemCategory != WIA_CATEGORY_FINISHED_FILE) && (WIA_CATEGORY_FOLDER != guidItemCategory))
{
LONG lErrorHandling = ERROR_HANDLING_NONE;
hr = wiasReadPropLong(pWiasContext, MY_WIA_ERROR_HANDLING_PROP, &lErrorHandling, NULL, TRUE);
BOOL bSendWarmingUpMsg = lErrorHandling & ERROR_HANDLING_WARMING_UP;
BOOL bSendCoverOpenMsg = lErrorHandling & ERROR_HANDLING_COVER_OPEN;
BOOL bSendPrivateErrorMsg = lErrorHandling & ERROR_HANDLING_PRIVATE_ERROR;
BOOL bSendUnhandledStatusMsg = lErrorHandling & ERROR_HANDLING_UNHANDLED_STATUS;
BOOL bSendUnhandledErrorMsg = lErrorHandling & ERROR_HANDLING_UNHANDLED_ERROR;
// We need to initialize our device object for each item we transfer.
// Each item may have it's own selection area, data type and so on.
hr = m_WiaDevice.InitializeForDownload(pWiasContext,
g_hInst,
uiBitmapResourceID,
guidFormatID);
if ((S_OK == hr) && bSendWarmingUpMsg)
{
//
// Send non-modal warming up message. To be catched by default UI
// unless application handles it (WiaPreview does not handle this
// message).
//
// Sending "update messages" makes it possible for a user to cancel transfer
// and also for an error handler to provide progress dialog.
//
for (int i = 0; i < 10 ; i++)
{
pParams->lMessage = WIA_TRANSFER_MSG_DEVICE_STATUS;
pParams->hrErrorStatus = WIA_STATUS_WARMING_UP;
pParams->lPercentComplete = i * 10;
pParams->ulTransferredBytes = 0;
hr = pTransferCallback->SendMessage(0, pParams);
if (S_OK != hr)
{
break;
}
Sleep(500);
}
}
if (S_OK == hr)
{
BOOL bProblemFixed = FALSE;
// Data transfer loop
// Read from device
ULONG ulBytesRead = 0;
LONG lPercentComplete = 0;
if (bSendUnhandledStatusMsg)
{
//
// Send "special" unhandled status message
//
pParams->lMessage = WIA_TRANSFER_MSG_DEVICE_STATUS;
pParams->hrErrorStatus = UNHANDLED_PRIVATE_STATUS_MESSAGE_1;
pParams->lPercentComplete = 0;
pParams->ulTransferredBytes = 0;
hr = pTransferCallback->SendMessage(0, pParams);
}
if ((S_OK == hr) && bSendUnhandledErrorMsg)
{
//
// Since none handles this device error it will cause our transfer to be
// be aborted.
//
pParams->lMessage = WIA_TRANSFER_MSG_DEVICE_STATUS;
pParams->hrErrorStatus = UNHANDLED_PRIVATE_STATUS_ERROR_1;
pParams->lPercentComplete = 0;
pParams->ulTransferredBytes = 0;
hr = pTransferCallback->SendMessage(0, pParams);
}
if ((S_OK == hr) && bSendCoverOpenMsg)
{
pParams->lMessage = WIA_TRANSFER_MSG_DEVICE_STATUS;
pParams->hrErrorStatus = WIA_ERROR_COVER_OPEN;
pParams->lPercentComplete = 0;
pParams->ulTransferredBytes = 0;
hr = pTransferCallback->SendMessage(0, pParams);
}
//
// If this is a Raw format transfer we should transfer the raw header first.
// WiaDevice::InitializeForDownload suceedeed and it is safe to execute
// now DownloadRawHeader:
//
if((S_OK == hr) && (IsEqualGUID(guidFormatID, WiaImgFmt_RAW)))
{
hr = DownloadRawHeader(pDestination, pWiasContext, pmdtc);
if(S_OK == hr)
{
WIA_RAW_HEADER& RawHeader = m_WiaDevice.m_RawHeader;
LONG lPercentComplete = (LONG)((((float)RawHeader.HeaderSize /
(float)(RawHeader.RawDataSize + RawHeader.HeaderSize + RawHeader.PaletteSize))) * 100.0f);
pParams->lMessage = WIA_TRANSFER_MSG_STATUS;
pParams->lPercentComplete = lPercentComplete;
pParams->ulTransferredBytes += RawHeader.HeaderSize;
hr = pTransferCallback->SendMessage(0, pParams);
}
}
while((S_OK == hr) &&
((hr = m_WiaDevice.GetNextBand(pBuffer, ulBufferSize, &ulBytesRead, &lPercentComplete, guidFormatID)) == S_OK))
{
// Check whether the transfer has been cancelled
// Write to stream
ULONG ulBytesWritten = 0;
hr = pDestination->Write(pBuffer, ulBytesRead, &ulBytesWritten);
if (S_OK == hr)
{
// Make progress callback
pParams->lMessage = WIA_TRANSFER_MSG_STATUS;
pParams->lPercentComplete = lPercentComplete;
pParams->ulTransferredBytes += ulBytesWritten;
hr = pTransferCallback->SendMessage(0, pParams);
if (FAILED(hr))
{
WIAS_ERROR((g_hInst, "Failed to send progress notification during download, hr = 0x%lx",hr));
break;
}
else if (S_FALSE == hr)
{
//
// Transfer cancelled
//
break;
}
else if (S_OK != hr)
{
WIAS_ERROR((g_hInst, "SendMessage returned unknown Success value, hr = 0x%lx",hr));
hr = E_UNEXPECTED;
break;
}
if ((lPercentComplete > 50) && !bProblemFixed)
{
if (bSendPrivateErrorMsg)
{
//
// Send "special" driver status message that only our error handling extension knows about
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -