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.
4924 lines
151 KiB
4924 lines
151 KiB
/*******************************************************************************
|
|
*
|
|
* (C) COPYRIGHT MICROSOFT CORP., 2000
|
|
*
|
|
* TITLE: IWiaMiniDrv.cpp
|
|
*
|
|
* VERSION: 1.0
|
|
*
|
|
* DATE: 18 July, 2000
|
|
*
|
|
* DESCRIPTION:
|
|
* Implementation of the WIA sample scanner IWiaMiniDrv methods.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#include "pch.h"
|
|
extern HINSTANCE g_hInst; // used for WIAS_LOGPROC macro
|
|
#define _64BIT_ALIGNMENT // the real 64-bit alignment fix
|
|
#define _SERVICE_EXTENT_VALIDATION // let the WIA service validate the extent settings
|
|
//#define _OOB_DATA // Out Of Band data support (File Transfers only)
|
|
|
|
#define BUFFER_PAD 1024 // buffer padding
|
|
|
|
/**************************************************************************\
|
|
* CWIAScannerDevice::drvDeleteItem
|
|
*
|
|
* This helper is called to delete a device item.
|
|
* Note: Device items for this device may not be modified.
|
|
* Return access denied.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pWiasContext - Indicates the item to delete.
|
|
* lFlags - Operation flags, unused.
|
|
* plDevErrVal - Pointer to the device error value.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWIAScannerDevice::drvDeleteItem(
|
|
BYTE *pWiasContext,
|
|
LONG lFlags,
|
|
LONG *plDevErrVal)
|
|
{
|
|
if (plDevErrVal)
|
|
{
|
|
*plDevErrVal = 0;
|
|
}
|
|
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::drvDeleteItem");
|
|
return STG_E_ACCESSDENIED;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* SendBitmapHeader
|
|
*
|
|
* This helper is called to send the bitmap header info to the callback
|
|
* routine.
|
|
* Note: This is a helper function used in TYMED_CALLBACK transfers.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pmdtc - a pointer to a transfer context.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT CWIAScannerDevice::SendBitmapHeader(
|
|
PMINIDRV_TRANSFER_CONTEXT pmdtc)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL3,
|
|
"CWIAScannerDevice::SendBitmapHeader");
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
BITMAPINFO UNALIGNED *pbmi = (LPBITMAPINFO)pmdtc->pTransferBuffer;
|
|
|
|
#ifdef _64BIT_ALIGNMENT
|
|
BITMAPINFOHEADER UNALIGNED *pbmih = &pbmi->bmiHeader;
|
|
pbmih->biHeight = -pbmih->biHeight;
|
|
#else
|
|
pbmi->bmiHeader.biHeight = -pbmi->bmiHeader.biHeight;
|
|
#endif
|
|
|
|
//
|
|
// Send to class driver. WIA Class driver will pass
|
|
// data through to client.
|
|
//
|
|
|
|
hr = pmdtc->pIWiaMiniDrvCallBack->MiniDrvCallback(IT_MSG_DATA,
|
|
IT_STATUS_TRANSFER_TO_CLIENT,
|
|
0,
|
|
0,
|
|
pmdtc->lHeaderSize,
|
|
pmdtc,
|
|
0);
|
|
|
|
if (hr == S_OK) {
|
|
|
|
//
|
|
// If the transfer was successfull, advance offset for
|
|
// destination copy by the size of the data just sent.
|
|
//
|
|
|
|
pmdtc->cbOffset += pmdtc->lHeaderSize;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* SendFilePreviewBitmapHeader
|
|
*
|
|
* This helper is called to send the bitmap header info to the callback
|
|
* routine.
|
|
* Note: This is a helper function used in TYMED_FILE transfers with
|
|
* (out of band data) enabled.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pmdtc - a pointer to a transfer context.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT CWIAScannerDevice::SendFilePreviewBitmapHeader(
|
|
PMINIDRV_TRANSFER_CONTEXT pmdtc)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL3,
|
|
"CWIAScannerDevice::SendBitmapHeader");
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
#ifdef _OOB_DATA
|
|
|
|
WIAS_DOWN_SAMPLE_INFO DownSampleInfo;
|
|
memset(&DownSampleInfo,0,sizeof(DownSampleInfo));
|
|
|
|
DownSampleInfo.ulBitsPerPixel = pmdtc->lDepth;
|
|
DownSampleInfo.ulOriginalWidth = pmdtc->lWidthInPixels;
|
|
DownSampleInfo.ulOriginalHeight = pmdtc->lLines;
|
|
DownSampleInfo.ulDownSampledHeight = 0;
|
|
DownSampleInfo.ulDownSampledWidth = 0;
|
|
DownSampleInfo.ulXRes = pmdtc->lXRes;
|
|
DownSampleInfo.ulYRes = pmdtc->lYRes;
|
|
|
|
hr = wiasDownSampleBuffer(WIAS_GET_DOWNSAMPLED_SIZE_ONLY,
|
|
&DownSampleInfo);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SendFilePreviewBitmapHeader, wiasDownSampleBuffer Failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
} else {
|
|
|
|
//
|
|
// acquire BITMAPHEADER pointer from pmdtc
|
|
//
|
|
|
|
LPBITMAPINFO UNALIGNED pbmi = (LPBITMAPINFO)pmdtc->pBaseBuffer;
|
|
|
|
#ifdef _64BIT_ALIGNMENT
|
|
BITMAPINFOHEADER UNALIGNED *pbmih = &pbmi->bmiHeader;
|
|
pbmih->biHeight = 0; // set height to zero (0)
|
|
pbmih->biWidth = DownSampleInfo.ulDownSampledWidth; // set down sampled width
|
|
#else
|
|
pmdtc->pBaseBuffer = pmdtc->pTransferBuffer + sizeof(BITMAPFILEHEADER);
|
|
#endif
|
|
|
|
|
|
|
|
//
|
|
// adjust width and height
|
|
//
|
|
|
|
pbmi->bmiHeader.biHeight = 0; // set height to zero (0)
|
|
pbmi->bmiHeader.biWidth = DownSampleInfo.ulDownSampledWidth; // set down sampled width
|
|
|
|
//
|
|
// Send to class driver. WIA Class driver will pass
|
|
// data through to client.
|
|
//
|
|
|
|
hr = pmdtc->pIWiaMiniDrvCallBack->MiniDrvCallback(IT_MSG_FILE_PREVIEW_DATA,
|
|
IT_STATUS_TRANSFER_TO_CLIENT,
|
|
0,
|
|
0,
|
|
pmdtc->lHeaderSize - sizeof(BITMAPFILEHEADER),
|
|
pmdtc,
|
|
0);
|
|
}
|
|
|
|
#endif
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* ScanItem
|
|
*
|
|
* This helper is called to do a FILE transfer.
|
|
* Note: This routine must fill the complete buffer, and return percent
|
|
* complete status back to the client if a callback routine is
|
|
* provided.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pItemContext - private item data
|
|
* pMiniTranCtx - minidriver supplied transfer info
|
|
* plDevErrVal - device error value
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWIAScannerDevice::ScanItem(
|
|
PMINIDRIVERITEMCONTEXT pItemContext,
|
|
PMINIDRV_TRANSFER_CONTEXT pmdtc,
|
|
LONG *plDevErrVal)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL3,
|
|
"CWIAScannerDevice::ScanItem");
|
|
HRESULT hr = S_OK;
|
|
|
|
|
|
//
|
|
// init buffer info
|
|
//
|
|
|
|
DWORD cbWritten = 0;
|
|
LONG cbSize = 0;
|
|
LONG cbRemaining = pmdtc->lBufferSize - pmdtc->lHeaderSize;
|
|
PBYTE pBuf = pmdtc->pTransferBuffer + pmdtc->lHeaderSize;
|
|
LONG lItemSize = pmdtc->lHeaderSize;
|
|
BOOL bSwapBGRData = TRUE;
|
|
BOOL bDWORDAlign = TRUE;
|
|
BOOL bVerticalFlip= TRUE;
|
|
LONG lScanPhase = SCAN_START;
|
|
ULONG ulDestDataOffset = 0;
|
|
BOOL bBitmapData = ((pmdtc->guidFormatID == WiaImgFmt_BMP) || (pmdtc->guidFormatID == WiaImgFmt_MEMORYBMP));
|
|
LONG PercentComplete = 0;
|
|
|
|
#ifdef _OOB_DATA
|
|
|
|
WIAS_DOWN_SAMPLE_INFO DownSampleInfo;
|
|
memset(&DownSampleInfo,0,sizeof(DownSampleInfo));
|
|
|
|
//
|
|
// SEND BITMAPHEADER to client
|
|
//
|
|
|
|
hr = SendFilePreviewBitmapHeader(pmdtc);
|
|
if(hr == S_OK){
|
|
|
|
//
|
|
// move offset past file header
|
|
//
|
|
|
|
ulDestDataOffset += (pmdtc->lHeaderSize - sizeof(BITMAPFILEHEADER));
|
|
} else {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ScanItem, SendFilePreviewBitmapHeader Failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
if (bBitmapData) {
|
|
|
|
//
|
|
// check to see if the color data needs to be swapped
|
|
//
|
|
|
|
hr = m_pScanAPI->IsColorDataBGR(&bSwapBGRData);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ScanItem, IsColorDataBGR() Failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// check to see if data needs to be aligned
|
|
//
|
|
|
|
hr = m_pScanAPI->IsAlignmentNeeded(&bDWORDAlign);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ScanItem, IsAlignmentNeeded() Failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
//
|
|
// scan until buffer runs out or scanner completes transfer
|
|
//
|
|
|
|
while ((lScanPhase == SCAN_START) || (cbWritten)) {
|
|
|
|
//
|
|
// default transfer size is m_MaxBufferSize
|
|
//
|
|
|
|
cbSize = m_MaxBufferSize;
|
|
|
|
if (bBitmapData) {
|
|
|
|
//
|
|
// Limit requests to max buffer size or less.
|
|
//
|
|
|
|
cbSize = (cbRemaining > m_MaxBufferSize) ? m_MaxBufferSize : cbRemaining;
|
|
|
|
//
|
|
// Request size to scanner must be modula the raw bytes per scan row.
|
|
// Enough space for the alignment padding must be reserved.
|
|
// These are requirements for AlignInPlace
|
|
//
|
|
|
|
cbSize = (cbSize / pItemContext->lBytesPerScanLine) *
|
|
pItemContext->lBytesPerScanLineRaw;
|
|
|
|
//
|
|
// check if finished
|
|
//
|
|
|
|
if (cbSize == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Device specific call to get data from the scanner and put it into
|
|
// a buffer. lScanPhase indicates whether this is the first call to Scan,
|
|
// pBuf is a pointer to the buffer, cbSize is the amount of data
|
|
// requested from the scanner, and cbWritten will be set to the actual
|
|
// amount of data returned by the scanner.
|
|
//
|
|
|
|
hr = m_pScanAPI->Scan(lScanPhase, pBuf, cbSize, &cbWritten);
|
|
|
|
//
|
|
// set flag to SCAN_CONTINUE, for other calls
|
|
//
|
|
|
|
lScanPhase = SCAN_CONTINUE;
|
|
|
|
if (hr == S_OK) {
|
|
|
|
if (cbWritten) {
|
|
|
|
if (bBitmapData) {
|
|
|
|
//
|
|
// Place the scan data in correct byte order for 3 bytes ber pixel data.
|
|
//
|
|
|
|
if ((pmdtc->lDepth == 24)) {
|
|
|
|
//
|
|
// swap data if needed
|
|
//
|
|
|
|
if (bSwapBGRData) {
|
|
SwapBuffer24(pBuf, cbWritten);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Align the data on DWORD boundries.
|
|
//
|
|
|
|
if (bDWORDAlign) {
|
|
cbWritten = AlignInPlace(pBuf,
|
|
cbWritten,
|
|
pItemContext->lBytesPerScanLine,
|
|
pItemContext->lBytesPerScanLineRaw);
|
|
}
|
|
}
|
|
|
|
//
|
|
// advance buffer
|
|
//
|
|
|
|
lItemSize += cbWritten;
|
|
pBuf += cbWritten;
|
|
cbRemaining -= cbWritten;
|
|
|
|
//
|
|
// If a status callback was specified callback the class driver.
|
|
//
|
|
|
|
if (pmdtc->pIWiaMiniDrvCallBack) {
|
|
|
|
FLOAT FractionComplete = 0.0f;
|
|
|
|
if (pmdtc->lBufferSize) {
|
|
if(bBitmapData){
|
|
PercentComplete = 0;
|
|
FractionComplete = (FLOAT)(pmdtc->lBufferSize - cbRemaining) / (FLOAT)pmdtc->lBufferSize;
|
|
}
|
|
} else {
|
|
WIAS_LERROR(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
("ScanItemCB, pmdtc->lBufferSize = 0!"));
|
|
}
|
|
|
|
//
|
|
// calculate percent complete
|
|
//
|
|
|
|
if(bBitmapData){
|
|
PercentComplete = (LONG)(100 * FractionComplete);
|
|
} else {
|
|
PercentComplete += 25;
|
|
if(PercentComplete >= 100){
|
|
PercentComplete = 90;
|
|
}
|
|
}
|
|
|
|
//
|
|
// call back client with status on the transfer
|
|
//
|
|
|
|
hr = pmdtc->pIWiaMiniDrvCallBack->MiniDrvCallback(IT_MSG_STATUS,
|
|
IT_STATUS_TRANSFER_TO_CLIENT,
|
|
PercentComplete,
|
|
0,
|
|
0,
|
|
NULL,
|
|
0);
|
|
//
|
|
// check for user cancel (from IT_MSG_STATUS callback)
|
|
//
|
|
|
|
if (hr == S_FALSE) {
|
|
|
|
WIAS_LTRACE(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL4,
|
|
("ScanItem, Transfer canceled by client (IT_MSG_STATUS callback)"));
|
|
break;
|
|
|
|
} else if (FAILED(hr)) {
|
|
|
|
//
|
|
// transfer failed
|
|
//
|
|
|
|
WIAS_LERROR(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
("ScanItem, MiniDrvCallback failed (IT_MSG_STATUS callback)"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
break;
|
|
}
|
|
|
|
#ifdef _OOB_DATA
|
|
DownSampleInfo.pDestBuffer = NULL; // allocate this for me?
|
|
DownSampleInfo.pSrcBuffer = pBuf - cbWritten;
|
|
DownSampleInfo.ulActualSize = 0; // Actual of what? data written?
|
|
DownSampleInfo.ulBitsPerPixel = pmdtc->lDepth;
|
|
DownSampleInfo.ulDestBufSize = 0;
|
|
DownSampleInfo.ulDownSampledHeight = 0;
|
|
DownSampleInfo.ulDownSampledWidth = 0;
|
|
DownSampleInfo.ulOriginalHeight = (cbWritten / pItemContext->lBytesPerScanLine);
|
|
DownSampleInfo.ulOriginalWidth = pmdtc->lWidthInPixels;
|
|
DownSampleInfo.ulSrcBufSize = cbWritten;
|
|
DownSampleInfo.ulXRes = pmdtc->lXRes;
|
|
DownSampleInfo.ulYRes = pmdtc->lYRes;
|
|
|
|
hr = wiasDownSampleBuffer(0, &DownSampleInfo);
|
|
if(FAILED(hr)){
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ScanItem, wiasDownSampleBuffer Failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
} else {
|
|
|
|
pmdtc->pBaseBuffer = DownSampleInfo.pDestBuffer;
|
|
|
|
//
|
|
// call back client with down sampled buffer
|
|
//
|
|
|
|
hr = pmdtc->pIWiaMiniDrvCallBack->MiniDrvCallback(IT_MSG_FILE_PREVIEW_DATA,
|
|
IT_STATUS_TRANSFER_TO_CLIENT,
|
|
PercentComplete,
|
|
ulDestDataOffset,
|
|
DownSampleInfo.ulActualSize,
|
|
pmdtc,
|
|
0);
|
|
//
|
|
// update offset
|
|
//
|
|
|
|
ulDestDataOffset += DownSampleInfo.ulActualSize;
|
|
}
|
|
|
|
|
|
//
|
|
// check for user cancel (from IT_MSG_FILE_PREVIEW_DATA callback)
|
|
//
|
|
|
|
if (hr == S_FALSE) {
|
|
|
|
WIAS_LTRACE(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL4,
|
|
("ScanItem, Transfer canceled by client (IT_MSG_FILE_PREVIEW_DATA callback)"));
|
|
break;
|
|
|
|
} else if (FAILED(hr)) {
|
|
|
|
//
|
|
// transfer failed
|
|
//
|
|
|
|
WIAS_LERROR(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
("ScanItem, MiniDrvCallback failed (IT_MSG_FILE_PREVIEW_DATA callback)"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//
|
|
// write the band of data here
|
|
//
|
|
|
|
if (!bBitmapData) {
|
|
if (hr == S_OK) {
|
|
if (!pmdtc->bClassDrvAllocBuf) {
|
|
pmdtc->lItemSize = cbWritten;
|
|
hr = wiasWritePageBufToFile(pmdtc);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
("ScanItem, WritePageBufToFile failed"));
|
|
}
|
|
}
|
|
pBuf = pmdtc->pTransferBuffer;
|
|
}
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// Get the device error
|
|
//
|
|
if (plDevErrVal) {
|
|
*plDevErrVal = (LONG) hr;
|
|
WIAS_LERROR(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
("ScanItem, data transfer failed, status: 0x%X", hr));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (hr == S_OK) {
|
|
|
|
//
|
|
// On success, flip the buffer about the vertical access if
|
|
// we have a DIB header and data.
|
|
//
|
|
|
|
if (pmdtc->guidFormatID == WiaImgFmt_BMP) {
|
|
if(bVerticalFlip){
|
|
VerticalFlip(pItemContext, pmdtc);
|
|
}
|
|
}
|
|
|
|
if (bBitmapData) {
|
|
|
|
//
|
|
// If the mini driver allocated a page buffer, we need to write the
|
|
// buffer to the open file handle (opened by class driver).
|
|
//
|
|
|
|
if (!pmdtc->bClassDrvAllocBuf) {
|
|
|
|
//
|
|
// Now that we know the true item size, update the mini driver
|
|
// context.
|
|
//
|
|
|
|
pmdtc->lItemSize = lItemSize;
|
|
|
|
hr = wiasWritePageBufToFile(pmdtc);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
("ScanItem, WritePageBufToFile failed"));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
HRESULT Temphr = m_pScanAPI->Scan(SCAN_END, NULL, 0, NULL);
|
|
if(FAILED(Temphr)){
|
|
WIAS_LERROR(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
("ScanItem, Ending a scanning session failed"));
|
|
hr = Temphr;
|
|
}
|
|
|
|
#ifdef _OOB_DATA
|
|
|
|
//
|
|
// free down sampled, temporary buffer
|
|
//
|
|
|
|
if(DownSampleInfo.pDestBuffer){
|
|
CoTaskMemFree(DownSampleInfo.pDestBuffer);
|
|
DownSampleInfo.pDestBuffer = NULL;
|
|
}
|
|
|
|
#endif
|
|
|
|
if (!bBitmapData) {
|
|
|
|
//
|
|
// call back client with status on the transfer with 100% complete
|
|
//
|
|
|
|
hr = pmdtc->pIWiaMiniDrvCallBack->MiniDrvCallback(IT_MSG_STATUS,
|
|
IT_STATUS_TRANSFER_TO_CLIENT,
|
|
100,
|
|
0,
|
|
0,
|
|
NULL,
|
|
0);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* ScanItemCB
|
|
*
|
|
* This helper is called to do a MEMORY transfer.
|
|
* Note: This routine must fill buffers, adjust the buffer offset and
|
|
* return percent complete status back to the client via a callback
|
|
* routine. (a callback interface must be supplied by the caller for
|
|
* this routine to function).
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pItemContext - private item data
|
|
* pmdtc - buffer and callback information
|
|
* plDevErrVal - device error value
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWIAScannerDevice::ScanItemCB(
|
|
PMINIDRIVERITEMCONTEXT pItemContext,
|
|
PMINIDRV_TRANSFER_CONTEXT pmdtc,
|
|
LONG *plDevErrVal)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL3,
|
|
"CWIAScannerDevice::ScanItemCB");
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// init buffer info
|
|
//
|
|
|
|
DWORD cbWritten = 0;
|
|
LONG cbSize = 0;
|
|
LONG cbRemaining = pmdtc->lImageSize; //pmdtc->lBufferSize - pmdtc->lHeaderSize;
|
|
PBYTE pBuf = pmdtc->pTransferBuffer + pmdtc->lHeaderSize;
|
|
LONG lItemSize = pmdtc->lHeaderSize;
|
|
BOOL bSwapBGRData = TRUE;
|
|
BOOL bDWORDAlign = TRUE;
|
|
BOOL bVerticalFlip= TRUE;
|
|
LONG lScanPhase = SCAN_START;
|
|
pmdtc->cbOffset = 0;
|
|
BOOL bBitmapData = ((pmdtc->guidFormatID == WiaImgFmt_BMP) || (pmdtc->guidFormatID == WiaImgFmt_MEMORYBMP));
|
|
LONG PercentComplete = 0;
|
|
|
|
//
|
|
// This must be a callback transfer request
|
|
//
|
|
|
|
if ((pmdtc->pIWiaMiniDrvCallBack == NULL) ||
|
|
(!pmdtc->bTransferDataCB)) {
|
|
WIAS_LERROR(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
("ScanItemCB, invalid callback params"));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (bBitmapData) {
|
|
|
|
//
|
|
// SEND BITMAPHEADER to client
|
|
//
|
|
|
|
hr = SendBitmapHeader(pmdtc);
|
|
if (hr != S_OK) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ScanItemCB, SendBitmapHeader failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// check to see if the color data needs to be swapped
|
|
//
|
|
|
|
hr = m_pScanAPI->IsColorDataBGR(&bSwapBGRData);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ScanItemCB, IsColorDataBGR() Failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// check to see if data needs to be aligned
|
|
//
|
|
|
|
hr = m_pScanAPI->IsAlignmentNeeded(&bDWORDAlign);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ScanItem, IsAlignmentNeeded() Failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// scan until buffer runs out or scanner completes transfer
|
|
//
|
|
|
|
while ((lScanPhase == SCAN_START) || (cbWritten)) {
|
|
|
|
//
|
|
// assign the pointer to the transfer buffer
|
|
//
|
|
|
|
pBuf = pmdtc->pTransferBuffer;
|
|
|
|
cbSize = m_MaxBufferSize; // default
|
|
|
|
if (bBitmapData) {
|
|
|
|
//
|
|
// Limit requests to requested buffer size or less.
|
|
//
|
|
|
|
cbSize = (cbRemaining > pmdtc->lBufferSize) ? pmdtc->lBufferSize : cbRemaining;
|
|
|
|
//
|
|
// Request size to scanner must be modula the raw bytes per scan row.
|
|
// Enough space for the alignment padding must be reserved.
|
|
// These are requirements for AlignInPlace
|
|
//
|
|
|
|
cbSize = (cbSize / pItemContext->lBytesPerScanLine) *
|
|
pItemContext->lBytesPerScanLineRaw;
|
|
|
|
//
|
|
// check if finished
|
|
//
|
|
|
|
if (cbSize == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Device specific call to get data from the scanner and put it into
|
|
// a buffer. lScanPhase indicates whether this is the first call to Scan,
|
|
// pBuf is a pointer to the buffer, cbSize is the amount of data
|
|
// requested from the scanner, and cbWritten will be set to the actual
|
|
// amount of data returned by the scanner.
|
|
//
|
|
|
|
hr = m_pScanAPI->Scan(lScanPhase, pBuf, cbSize, &cbWritten);
|
|
|
|
//
|
|
// set flag to SCAN_CONTINUE, for other calls
|
|
//
|
|
|
|
lScanPhase = SCAN_CONTINUE;
|
|
|
|
if (hr == S_OK) {
|
|
|
|
if (cbWritten) {
|
|
|
|
if (bBitmapData) {
|
|
|
|
//
|
|
// Place the scan data in correct byte order for 3 bytes ber pixel data.
|
|
//
|
|
|
|
if ((pmdtc->lDepth == 24)) {
|
|
|
|
//
|
|
// swap data if needed
|
|
//
|
|
|
|
if (bSwapBGRData) {
|
|
SwapBuffer24(pBuf, cbWritten);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Align the data on DWORD boundries.
|
|
//
|
|
|
|
if (bDWORDAlign) {
|
|
cbWritten = AlignInPlace(pBuf,
|
|
cbWritten,
|
|
pItemContext->lBytesPerScanLine,
|
|
pItemContext->lBytesPerScanLineRaw);
|
|
}
|
|
}
|
|
|
|
//
|
|
// advance buffer
|
|
//
|
|
|
|
cbRemaining -= cbWritten;
|
|
|
|
//
|
|
// If a status callback was specified callback the class driver.
|
|
// There has to be a callback provided, this is the callback
|
|
// transfer.
|
|
//
|
|
|
|
if (pmdtc->pIWiaMiniDrvCallBack) {
|
|
|
|
FLOAT FractionComplete = 0.0f;
|
|
|
|
if ((pmdtc->lImageSize + pmdtc->lHeaderSize)) {
|
|
if (bBitmapData) {
|
|
PercentComplete = 0;
|
|
FractionComplete = (FLOAT) (pmdtc->cbOffset + cbWritten) /
|
|
(FLOAT) (pmdtc->lImageSize + pmdtc->lHeaderSize);
|
|
}
|
|
} else {
|
|
WIAS_LERROR(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
("ScanItemCB, pmdtc->lBufferSize = 0!"));
|
|
}
|
|
|
|
//
|
|
// calculate percent complete
|
|
//
|
|
|
|
if (bBitmapData) {
|
|
PercentComplete = (LONG)(100 * FractionComplete);
|
|
} else {
|
|
PercentComplete += 25;
|
|
if (PercentComplete >= 100) {
|
|
PercentComplete = 90;
|
|
}
|
|
}
|
|
|
|
//
|
|
// call back client with status on the transfer and data offset
|
|
//
|
|
|
|
hr = pmdtc->pIWiaMiniDrvCallBack->MiniDrvCallback(IT_MSG_DATA,
|
|
IT_STATUS_TRANSFER_TO_CLIENT,
|
|
PercentComplete,
|
|
pmdtc->cbOffset,
|
|
cbWritten,
|
|
pmdtc,
|
|
0);
|
|
|
|
//
|
|
// check for user cancel
|
|
//
|
|
|
|
if (hr == S_FALSE) {
|
|
|
|
WIAS_LTRACE(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL4,
|
|
("ScanItemCB, Transfer canceled by client (IT_MSG_DATA callback)"));
|
|
break;
|
|
|
|
} else if (FAILED(hr)) {
|
|
|
|
//
|
|
// transfer failed
|
|
//
|
|
|
|
WIAS_LERROR(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
("ScanItemCB, MiniDrvCallback failed (IT_MSG_DATA callback)"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// move offset
|
|
//
|
|
|
|
pmdtc->cbOffset += cbWritten;
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// Get the device error
|
|
//
|
|
|
|
if (plDevErrVal) {
|
|
*plDevErrVal = (LONG) hr;
|
|
WIAS_LERROR(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
("ScanItemCB, data transfer failed, status: 0x%X", hr));
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
HRESULT Temphr = m_pScanAPI->Scan(SCAN_END, NULL, 0, NULL);
|
|
if(FAILED(Temphr)){
|
|
WIAS_LERROR(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
("ScanItemCB, Ending a scanning session failed"));
|
|
return Temphr;
|
|
}
|
|
|
|
if (!bBitmapData) {
|
|
|
|
//
|
|
// call back client to show 100% with status on the transfer and data offset
|
|
//
|
|
|
|
hr = pmdtc->pIWiaMiniDrvCallBack->MiniDrvCallback(IT_MSG_DATA,
|
|
IT_STATUS_TRANSFER_TO_CLIENT,
|
|
100,
|
|
pmdtc->cbOffset,
|
|
cbWritten,
|
|
pmdtc,
|
|
0);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWIAScannerDevice::drvAcquireItemData
|
|
*
|
|
* This driver entry point is called when image data is requested from the
|
|
* device.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pWiasContext - Pointer to the WIA item.
|
|
* lFlags - Operation flags, unused.
|
|
* pmdtc - Pointer to mini driver context. On entry, only the
|
|
* portion of the mini driver context which is derived
|
|
* from the item properties is filled in.
|
|
* plDevErrVal - Pointer to the device error value.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWIAScannerDevice::drvAcquireItemData(
|
|
BYTE *pWiasContext,
|
|
LONG lFlags,
|
|
PMINIDRV_TRANSFER_CONTEXT pmdtc,
|
|
LONG *plDevErrVal)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::drvAcquireItemData");
|
|
HRESULT hr = S_OK;
|
|
BOOL bBitmapData = ((pmdtc->guidFormatID == WiaImgFmt_BMP) || (pmdtc->guidFormatID == WiaImgFmt_MEMORYBMP));
|
|
if (plDevErrVal) {
|
|
*plDevErrVal = 0;
|
|
}
|
|
|
|
//
|
|
// Get a pointer to the associated driver item.
|
|
//
|
|
|
|
IWiaDrvItem* pDrvItem;
|
|
|
|
hr = wiasGetDrvItem(pWiasContext, &pDrvItem);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, wiasGetDrvItem() failed."));
|
|
WIAS_LHRESULT(m_pIWiaLog,hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Validate the data transfer context.
|
|
//
|
|
|
|
hr = ValidateDataTransferContext(pmdtc);
|
|
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, ValidateDataTransferContext() failed."));
|
|
WIAS_LHRESULT(m_pIWiaLog,hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Get item specific driver data
|
|
//
|
|
|
|
PMINIDRIVERITEMCONTEXT pItemContext = NULL;
|
|
|
|
hr = pDrvItem->GetDeviceSpecContext((BYTE**)&pItemContext);
|
|
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, NULL item context"));
|
|
WIAS_LHRESULT(m_pIWiaLog,hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// allocate a buffer to be used for the data transfer. This will only happen, when the
|
|
// the data format is non-bitmap. Item Size is set to 0, telling the WIA service, that
|
|
// we will be allocating the buffer for transfer.
|
|
//
|
|
|
|
if (!pmdtc->bClassDrvAllocBuf) {
|
|
|
|
LONG lClassDrvAllocSize = m_MaxBufferSize + BUFFER_PAD; // max buffer band size
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvAcquireItemData, Attempting to Allocate (%d)bytes for pmdtc->pTransferBuffer",lClassDrvAllocSize));
|
|
|
|
pmdtc->pTransferBuffer = (PBYTE) CoTaskMemAlloc(lClassDrvAllocSize);
|
|
if (!pmdtc->pTransferBuffer) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, unable to allocate temp transfer buffer, size: %d",(pmdtc->lImageSize + pmdtc->lHeaderSize)));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
//
|
|
// set new buffer size
|
|
//
|
|
|
|
pmdtc->lBufferSize = lClassDrvAllocSize;
|
|
}
|
|
|
|
if (bBitmapData) {
|
|
|
|
//
|
|
// Use WIA services to fetch format specific info. This information
|
|
// is based on the property settings.
|
|
//
|
|
|
|
hr = wiasGetImageInformation(pWiasContext, 0, pmdtc);
|
|
|
|
if (hr != S_OK) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, wiasGetImageInformation failed."));
|
|
WIAS_LHRESULT(m_pIWiaLog,hr);
|
|
return hr;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Check if we are in Preview Mode
|
|
//
|
|
|
|
if(IsPreviewScan(pWiasContext)){
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvAcquireItemData, Preview Property is SET"));
|
|
m_pScanAPI->SetScanMode(SCANMODE_PREVIEWSCAN);
|
|
} else {
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvAcquireItemData, Preview Property is NOT SET"));
|
|
m_pScanAPI->SetScanMode(SCANMODE_FINALSCAN);
|
|
}
|
|
|
|
//
|
|
// Get number of pages requested, for ADF scanning loop
|
|
//
|
|
|
|
BOOL bEmptyTheADF = FALSE;
|
|
LONG lPagesRequested = GetPageCount(pWiasContext);
|
|
if (lPagesRequested == 0) {
|
|
bEmptyTheADF = TRUE;
|
|
lPagesRequested = 1;// set to 1 so we can enter our loop
|
|
// WIA_STATUS_END_OF_MEDIA will terminate
|
|
// the loop...or an error, or a cancel..
|
|
//
|
|
}
|
|
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvAcquireItemData, Pages to Scan = %d",lPagesRequested));
|
|
|
|
if (IsADFEnabled(pWiasContext)) { // FEEDER is enabled for scanning
|
|
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvAcquireItemData, Feeder is enabled for use"));
|
|
|
|
//
|
|
// clear an potential paper that may be blocking the
|
|
// scan pathway.
|
|
//
|
|
|
|
hr = m_pScanAPI->ADFUnFeedPage();
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, ADFUnFeedPage (begin transfer) Failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
} else { // FLATBED is enabled for scanning
|
|
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvAcquireItemData, Feeder is disabled or no feeder exists"));
|
|
|
|
//
|
|
// Transfer only a single image
|
|
//
|
|
|
|
bEmptyTheADF = FALSE;
|
|
lPagesRequested = 1;
|
|
}
|
|
|
|
//
|
|
// WIA document scanning loop
|
|
//
|
|
|
|
LONG lPagesScanned = 0; // number of pages currently scanned
|
|
BOOL bCallBackTransfer = FALSE; // callback transfer flag
|
|
while (lPagesRequested > 0) {
|
|
|
|
if (IsADFEnabled(pWiasContext)) {
|
|
|
|
//
|
|
// Check feeder for paper
|
|
//
|
|
|
|
hr = m_pScanAPI->ADFHasPaper();
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, ADFHasPaper Failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
} else if(hr == S_FALSE){
|
|
return WIA_ERROR_PAPER_EMPTY;
|
|
}
|
|
|
|
//
|
|
// Attempt to load a page (only if needed)
|
|
//
|
|
|
|
hr = m_pScanAPI->ADFFeedPage();
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, ADFFeedPage Failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Check feeder's status
|
|
//
|
|
|
|
hr = m_pScanAPI->ADFStatus();
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, ADFStatus Failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
if (bBitmapData) {
|
|
|
|
//
|
|
// update image information
|
|
//
|
|
|
|
hr = wiasGetImageInformation(pWiasContext, 0, pmdtc);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, wiasGetImageInformation Failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Determine if this is a callback or file transfer.
|
|
//
|
|
|
|
if (pmdtc->tymed == TYMED_CALLBACK) {
|
|
|
|
//
|
|
// Scan the page to memory
|
|
//
|
|
|
|
bCallBackTransfer = TRUE;
|
|
|
|
hr = ScanItemCB(pItemContext,
|
|
pmdtc,
|
|
plDevErrVal);
|
|
|
|
} else {
|
|
|
|
//
|
|
// Scan the page to file
|
|
//
|
|
|
|
hr = ScanItem(pItemContext,
|
|
pmdtc,
|
|
plDevErrVal);
|
|
|
|
}
|
|
|
|
if (!bEmptyTheADF) {
|
|
|
|
//
|
|
// update pages requested counter
|
|
//
|
|
|
|
lPagesRequested--;
|
|
}
|
|
|
|
if (hr == S_FALSE) {
|
|
|
|
//
|
|
// user canceled the scan
|
|
//
|
|
|
|
lPagesRequested = 0; // set pages to 0 to cleanly exit loop
|
|
}
|
|
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvAcquireItemData, Pages left to scan = %d",lPagesRequested));
|
|
|
|
if (IsADFEnabled(pWiasContext)) {
|
|
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvAcquireItemData, Unloading a page from the feeder"));
|
|
|
|
//
|
|
// Attempt to unload the scanned page (only if needed)
|
|
//
|
|
|
|
hr = m_pScanAPI->ADFUnFeedPage();
|
|
if (SUCCEEDED(hr)) {
|
|
if (bCallBackTransfer) {
|
|
|
|
//
|
|
// send the NEW_PAGE message, when scanning multiple pages
|
|
// in callback mode. This will let the calling application
|
|
// know when an end-of-page has been hit.
|
|
//
|
|
|
|
hr = wiasSendEndOfPage(pWiasContext, lPagesScanned, pmdtc);
|
|
if (FAILED(hr)) {
|
|
lPagesRequested = 0;
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, wiasSendEndOfPage Failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
}
|
|
}
|
|
|
|
//
|
|
// increment pages scanned counter
|
|
//
|
|
|
|
lPagesScanned++;
|
|
} else {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, ADFUnFeedPage (end transfer) Failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
}
|
|
}
|
|
|
|
//
|
|
// free any allocated memory between scans to avoid memory leaks
|
|
//
|
|
|
|
if (!pmdtc->bClassDrvAllocBuf) {
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvAcquireItemData, Freeing any allocated memory (single scan operation complete)"));
|
|
if (NULL != pmdtc->pTransferBuffer) {
|
|
CoTaskMemFree(pmdtc->pTransferBuffer);
|
|
pmdtc->pTransferBuffer = NULL;
|
|
}
|
|
}
|
|
|
|
if (IsADFEnabled(pWiasContext)) { // FEEDER is enabled for scanning
|
|
|
|
//
|
|
// Check feeder for paper, to avoid error conditions
|
|
//
|
|
|
|
hr = m_pScanAPI->ADFHasPaper();
|
|
if (S_FALSE == hr) {
|
|
|
|
LONG lPages = GetPageCount(pWiasContext);
|
|
|
|
//
|
|
// have we scanned more than 1 page?
|
|
//
|
|
|
|
if(lPagesScanned > 0){
|
|
|
|
//
|
|
// Pages is set to n, and we successfully scanned n pages, return S_OK
|
|
//
|
|
|
|
if(lPagesScanned == lPages){
|
|
WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, We are out of paper, but we successfully scanned the requested amount"));
|
|
WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, returning S_OK"));
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// Pages is set to 0, and 1 or more pages have been scanned, return S_OK
|
|
//
|
|
|
|
if(lPages == 0){
|
|
WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, We are out of paper, but we successfully scanned more than 1 page"));
|
|
WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, returning S_OK"));
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// Pages is set to n, and we successfully scanned lPagesScanned but
|
|
// that is less than n...and the file is OK, return WIA_STATUS_END_OF_MEDIA
|
|
//
|
|
|
|
if ((lPages > 0)&&(lPagesScanned < lPages)) {
|
|
WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, We are out of paper, but we successfully scanned more than 1 page..but less than requested"));
|
|
WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, returning WIA_STATUS_END_OF_MEDIA"));
|
|
return WIA_STATUS_END_OF_MEDIA;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// we are now finished scanning all documents
|
|
//
|
|
|
|
if (!pmdtc->bClassDrvAllocBuf) {
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvAcquireItemData, Freeing any allocated memory (entire scan operation complete)"));
|
|
if (NULL != pmdtc->pTransferBuffer) {
|
|
CoTaskMemFree(pmdtc->pTransferBuffer);
|
|
pmdtc->pTransferBuffer = NULL;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* IsPreviewScan
|
|
*
|
|
* Get the current preview setting from the item properties.
|
|
* A helper for drvAcquireItemData.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pWiasContext - pointer to an Item context.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* TRUE - Preview is set, FALSE - Final is set
|
|
*
|
|
* History:
|
|
*
|
|
* 8/10/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL CWIAScannerDevice::IsPreviewScan(BYTE *pWiasContext)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL3,
|
|
"CWIAScannerDevice::IsPreviewScan");
|
|
//
|
|
// Get a pointer to the root item, for property access.
|
|
//
|
|
|
|
BYTE *pRootItemCtx = NULL;
|
|
|
|
HRESULT hr = wiasGetRootItem(pWiasContext, &pRootItemCtx);
|
|
if (FAILED(hr)) {
|
|
WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("IsPreviewScan, No Preview Property Found on ROOT item!"));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Get the current preview setting.
|
|
//
|
|
|
|
LONG lPreview = 0;
|
|
|
|
hr = wiasReadPropLong(pRootItemCtx, WIA_DPS_PREVIEW, &lPreview, NULL, true);
|
|
if (hr != S_OK) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("IsPreviewScan, Failed to read Preview Property."));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return FALSE;
|
|
}
|
|
|
|
return (lPreview > 0);
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* IsADFEnabled
|
|
*
|
|
* Get the current Document Handling Select setting from the item properties.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pWiasContext - pointer to an Item context.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* TRUE - enabled, FALSE - disabled
|
|
*
|
|
* History:
|
|
*
|
|
* 5/01/2001 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
BOOL CWIAScannerDevice::IsADFEnabled(BYTE *pWiasContext)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL bEnabled = FALSE;
|
|
//
|
|
// Get a pointer to the root item, for property access.
|
|
//
|
|
|
|
BYTE *pRootItemCtx = NULL;
|
|
|
|
hr = wiasGetRootItem(pWiasContext, &pRootItemCtx);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// read Document Handling Select property value
|
|
//
|
|
|
|
LONG lDocumentHandlingSelect = FLATBED;
|
|
hr = wiasReadPropLong(pRootItemCtx,WIA_DPS_DOCUMENT_HANDLING_SELECT,&lDocumentHandlingSelect,NULL,TRUE);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("IsADFEnabled, wiasReadPropLong(WIA_DPS_DOCUMENT_HANDLING_SELECT) failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
} else {
|
|
if (lDocumentHandlingSelect & FEEDER) {
|
|
|
|
//
|
|
// FEEDER is set
|
|
//
|
|
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("IsADFEnabled - ADF Enabled"));
|
|
bEnabled = TRUE;
|
|
} else {
|
|
|
|
//
|
|
// FEEDER is not set, default to FLATBED (WIAFBDRV only supports simple Document feeders at this time)
|
|
//
|
|
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("IsADFEnabled - ADF Disabled"));
|
|
bEnabled = FALSE;
|
|
}
|
|
}
|
|
} else {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("IsADFEnabled, wiasGetRootItem failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
}
|
|
return bEnabled;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* GetPageCount
|
|
*
|
|
* Get the requested number of pages to scan from the item properties.
|
|
* A helper for drvAcquireItemData.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pWiasContext - pointer to an Item context.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Number of pages to scan.
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
LONG CWIAScannerDevice::GetPageCount(BYTE *pWiasContext)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL3,
|
|
"CWIAScannerDevice::GetPageCount");
|
|
//
|
|
// Get a pointer to the root item, for property access.
|
|
//
|
|
|
|
BYTE *pRootItemCtx = NULL;
|
|
|
|
HRESULT hr = wiasGetRootItem(pWiasContext, &pRootItemCtx);
|
|
if (FAILED(hr)) {
|
|
return 1;
|
|
}
|
|
|
|
//
|
|
// Get the requested page count.
|
|
//
|
|
|
|
LONG lPagesRequested = 0;
|
|
|
|
hr = wiasReadPropLong(pRootItemCtx, WIA_DPS_PAGES, &lPagesRequested, NULL, true);
|
|
if (hr != S_OK) {
|
|
return 1;
|
|
}
|
|
|
|
return lPagesRequested;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* SetItemSize
|
|
*
|
|
* Calulate the new item size, and write the new Item Size property value.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pWiasContext - item
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT CWIAScannerDevice::SetItemSize(
|
|
BYTE *pWiasContext)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL3,
|
|
"CWIAScannerDevice::SetItemSize");
|
|
HRESULT hr = S_OK;
|
|
LONG lWidthInBytes = 0;
|
|
LONG lMinBufSize = 0;
|
|
GUID guidFormatID = GUID_NULL;
|
|
MINIDRV_TRANSFER_CONTEXT mdtc;
|
|
|
|
LONG lNumProperties = 3;
|
|
PROPVARIANT pv[3];
|
|
PROPSPEC ps[3] = {{PRSPEC_PROPID, WIA_IPA_ITEM_SIZE},
|
|
{PRSPEC_PROPID, WIA_IPA_BYTES_PER_LINE},
|
|
{PRSPEC_PROPID, WIA_IPA_MIN_BUFFER_SIZE}};
|
|
|
|
//
|
|
// Clear the MiniDrvTransferContext
|
|
//
|
|
|
|
memset(&mdtc,0,sizeof(MINIDRV_TRANSFER_CONTEXT));
|
|
|
|
//
|
|
// read format GUID
|
|
//
|
|
|
|
hr = wiasReadPropGuid(pWiasContext, WIA_IPA_FORMAT, &guidFormatID, NULL, TRUE);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetItemSize, ReadPropLong WIA_IPA_FORMAT error"));
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// read TYMED
|
|
//
|
|
|
|
hr = wiasReadPropLong(pWiasContext,WIA_IPA_TYMED, (LONG*)&mdtc.tymed, NULL, TRUE);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetItemSize, ReadPropLong WIA_IPA_TYMED error"));
|
|
return hr;
|
|
}
|
|
|
|
if ((guidFormatID == WiaImgFmt_BMP)||(guidFormatID == WiaImgFmt_MEMORYBMP)) {
|
|
|
|
//
|
|
// wias works for DIB, or uncompressed standard TIFF formats
|
|
// Standard TIFFs are constructed using a DIB-like implementation.
|
|
// The data is stored as one huge strip, rather than multiple smaller
|
|
// strips.
|
|
//
|
|
|
|
hr = wiasGetImageInformation(pWiasContext, WIAS_INIT_CONTEXT, &mdtc);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetItemSize, could not get image information"));
|
|
return hr;
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// manually set the data transfer context members
|
|
//
|
|
|
|
mdtc.lImageSize = 0;
|
|
mdtc.lHeaderSize = 0;
|
|
mdtc.lItemSize = 0;
|
|
mdtc.cbWidthInBytes = 0;
|
|
|
|
}
|
|
|
|
//
|
|
// Set the MinBufferSize property. MinBufferSize is the minimum buffer
|
|
// that a client can request for a data transfer.
|
|
//
|
|
|
|
switch (mdtc.tymed) {
|
|
case TYMED_CALLBACK:
|
|
|
|
//
|
|
// callback uses driver's minimum buffer size.
|
|
// This is could be taken from the micro driver at
|
|
// initialization time.
|
|
//
|
|
|
|
lMinBufSize = m_MinBufferSize;
|
|
break;
|
|
|
|
case TYMED_FILE:
|
|
|
|
//
|
|
// file transfers, require that the minimum buffer size be the
|
|
// entire length of the file.
|
|
//
|
|
|
|
lMinBufSize = mdtc.lImageSize + mdtc.lHeaderSize;
|
|
break;
|
|
|
|
default:
|
|
|
|
//
|
|
// unknown TYMED
|
|
//
|
|
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetItemSize, unknown tymed: 0x%08X", mdtc.tymed));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// Initialize propvar's. Then write the values. Don't need to call
|
|
// PropVariantClear when done, since there are only LONG values.
|
|
//
|
|
|
|
for (int i = 0; i < lNumProperties; i++) {
|
|
PropVariantInit(&pv[i]);
|
|
pv[i].vt = VT_I4;
|
|
}
|
|
|
|
pv[0].lVal = mdtc.lItemSize;
|
|
pv[1].lVal = mdtc.cbWidthInBytes;
|
|
pv[2].lVal = lMinBufSize;
|
|
|
|
//
|
|
// Write WIA_IPA_ITEM_SIZE, WIA_IPA_BYTES_PER_LINE, and WIA_IPA_MIN_BUFFER_SIZE
|
|
// property values
|
|
//
|
|
|
|
hr = wiasWriteMultiple(pWiasContext, lNumProperties, ps, pv);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Now update the MINIDRIVER TRANSFER CONTEXT with new values
|
|
//
|
|
|
|
//
|
|
// Get a pointer to the associated driver item.
|
|
//
|
|
|
|
IWiaDrvItem* pDrvItem = NULL;
|
|
|
|
hr = wiasGetDrvItem(pWiasContext, &pDrvItem);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Get driver item's context
|
|
//
|
|
|
|
PMINIDRIVERITEMCONTEXT pItemContext = NULL;
|
|
|
|
hr = pDrvItem->GetDeviceSpecContext((BYTE**)&pItemContext);
|
|
if (SUCCEEDED(hr)) {
|
|
if ((guidFormatID == WiaImgFmt_BMP)||(guidFormatID == WiaImgFmt_MEMORYBMP)) {
|
|
|
|
//
|
|
// Calculate how many scan lines will fit in the buffer.
|
|
//
|
|
|
|
pItemContext->lBytesPerScanLineRaw = ((mdtc.lWidthInPixels * mdtc.lDepth) + 7) / 8;
|
|
pItemContext->lBytesPerScanLine = (((mdtc.lWidthInPixels * mdtc.lDepth) + 31) / 8) & 0xfffffffc;
|
|
pItemContext->lTotalRequested = pItemContext->lBytesPerScanLineRaw * mdtc.lLines;
|
|
} else {
|
|
pItemContext->lBytesPerScanLineRaw = 0;
|
|
pItemContext->lBytesPerScanLine = 0;
|
|
pItemContext->lTotalRequested = 0;
|
|
}
|
|
} else {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvWriteItemProperties, NULL item context"));
|
|
}
|
|
} else {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetItemSize, WriteMultiple failed"));
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWIAScannerDevice::drvInitItemProperties
|
|
*
|
|
* Initialize the device item properties. Called during item
|
|
* initialization. This is called by the WIA Class driver
|
|
* after the item tree has been built. It is called once for every
|
|
* item in the tree.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pWiasContext - Pointer to WIA context (item information).
|
|
* lFlags - Operation flags, unused.
|
|
* plDevErrVal - Pointer to the device error value.
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWIAScannerDevice::drvInitItemProperties(
|
|
BYTE *pWiasContext,
|
|
LONG lFlags,
|
|
LONG *plDevErrVal)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::drvInitItemProperties");
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// This device doesn't touch hardware to initialize the device item
|
|
// properties, so set plDevErrVal to 0.
|
|
//
|
|
|
|
if (plDevErrVal) {
|
|
*plDevErrVal = 0;
|
|
}
|
|
|
|
//
|
|
// Get a pointer to the associated driver item.
|
|
//
|
|
|
|
IWiaDrvItem* pDrvItem;
|
|
hr = wiasGetDrvItem(pWiasContext, &pDrvItem);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitItemProperties, wiasGetDrvItem failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Set initial item properties.
|
|
//
|
|
|
|
LONG lItemType = 0;
|
|
|
|
pDrvItem->GetItemFlags(&lItemType);
|
|
|
|
if (lItemType & WiaItemTypeRoot) {
|
|
|
|
//
|
|
// This is for the root item.
|
|
//
|
|
|
|
//
|
|
// Build Root Item Properties, initializing global
|
|
// structures with their default and valid values
|
|
//
|
|
|
|
hr = BuildRootItemProperties();
|
|
|
|
if(FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitItemProperties, BuildRootItemProperties failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
DeleteRootItemProperties();
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Add the device specific root item property names,
|
|
// using WIA service.
|
|
//
|
|
|
|
hr = wiasSetItemPropNames(pWiasContext,
|
|
m_NumRootItemProperties,
|
|
m_piRootItemDefaults,
|
|
m_pszRootItemDefaults);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitItemProperties, wiasSetItemPropNames failed"));
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvInitItemProperties, m_NumRootItemPropeties = %d",m_NumRootItemProperties));
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvInitItemProperties, m_piRootItemDefaults = %x",m_piRootItemDefaults));
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvInitItemProperties, m_pszRootItemDefaults = %x",m_pszRootItemDefaults));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
DeleteRootItemProperties();
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Set the device specific root item properties to
|
|
// their default values using WIA service.
|
|
//
|
|
|
|
hr = wiasWriteMultiple(pWiasContext,
|
|
m_NumRootItemProperties,
|
|
m_psRootItemDefaults,
|
|
m_pvRootItemDefaults);
|
|
//
|
|
// Free PROPVARIANT array, This frees any memory that was allocated for a prop variant value.
|
|
//
|
|
|
|
// FreePropVariantArray(m_NumRootItemProperties,m_pvRootItemDefaults);
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitItemProperties, wiasWriteMultiple failed"));
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvInitItemProperties, m_NumRootItemPropeties = %d",m_NumRootItemProperties));
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvInitItemProperties, m_pszRootItemDefaults = %x",m_pszRootItemDefaults));
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvInitItemProperties, m_pvRootItemDefaults = %x",m_pvRootItemDefaults));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
DeleteRootItemProperties();
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Use WIA services to set the property access and
|
|
// valid value information from m_wpiItemDefaults.
|
|
//
|
|
|
|
hr = wiasSetItemPropAttribs(pWiasContext,
|
|
m_NumRootItemProperties,
|
|
m_psRootItemDefaults,
|
|
m_wpiRootItemDefaults);
|
|
|
|
if(FAILED(hr)){
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitItemProperties, wiasSetItemPropAttribs failed"));
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvInitItemProperties, m_NumRootItemPropeties = %d",m_NumRootItemProperties));
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvInitItemProperties, m_psRootItemDefaults = %x",m_psRootItemDefaults));
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvInitItemProperties, m_wpiRootItemDefaults = %x",m_wpiRootItemDefaults));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
}
|
|
|
|
//
|
|
// free allocated property arrays, for more memory
|
|
//
|
|
|
|
DeleteRootItemProperties();
|
|
|
|
|
|
} else {
|
|
|
|
//
|
|
// This is for the child item.(Top)
|
|
//
|
|
|
|
//
|
|
// Build Top Item Properties, initializing global
|
|
// structures with their default and valid values
|
|
//
|
|
|
|
hr = BuildTopItemProperties();
|
|
|
|
if(FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitItemProperties, BuildTopItemProperties failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
DeleteTopItemProperties();
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Use the WIA service to set the item property names.
|
|
//
|
|
|
|
hr = wiasSetItemPropNames(pWiasContext,
|
|
m_NumItemProperties,
|
|
m_piItemDefaults,
|
|
m_pszItemDefaults);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitItemProperties, wiasSetItemPropNames failed"));
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvInitItemProperties, m_NumItemPropeties = %d",m_NumItemProperties));
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvInitItemProperties, m_piItemDefaults = %x",m_piItemDefaults));
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvInitItemProperties, m_pszItemDefaults = %x",m_pszItemDefaults));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
DeleteTopItemProperties();
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Use WIA services to set the item properties to their default
|
|
// values.
|
|
//
|
|
|
|
hr = wiasWriteMultiple(pWiasContext,
|
|
m_NumItemProperties,
|
|
m_psItemDefaults,
|
|
(PROPVARIANT*)m_pvItemDefaults);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitItemProperties, wiasWriteMultiple failed"));
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvInitItemProperties, m_NumItemPropeties = %d",m_NumItemProperties));
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvInitItemProperties, m_pszItemDefaults = %x",m_pszItemDefaults));
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvInitItemProperties, m_pvItemDefaults = %x",m_pvItemDefaults));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
DeleteTopItemProperties();
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Use WIA services to set the property access and
|
|
// valid value information from m_wpiItemDefaults.
|
|
//
|
|
|
|
hr = wiasSetItemPropAttribs(pWiasContext,
|
|
m_NumItemProperties,
|
|
m_psItemDefaults,
|
|
m_wpiItemDefaults);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitItemProperties, wiasSetItemPropAttribs failed"));
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvInitItemProperties, m_NumItemPropeties = %d",m_NumItemProperties));
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvInitItemProperties, m_psItemDefaults = %x",m_psItemDefaults));
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvInitItemProperties, m_wpiItemDefaults = %x",m_wpiItemDefaults));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
DeleteTopItemProperties();
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Set item size properties.
|
|
//
|
|
|
|
hr = SetItemSize(pWiasContext);
|
|
if(FAILED(hr)){
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitItemProperties, SetItemSize failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
}
|
|
|
|
//
|
|
// free allocated property arrays, for more memory
|
|
//
|
|
|
|
DeleteTopItemProperties();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* CWIAScannerDevice::drvValidateItemProperties
|
|
*
|
|
* Validate the device item properties. It is called when changes are made
|
|
* to an item's properties. Driver should not only check that the values
|
|
* are valid, but must update any valid values that may change as a result.
|
|
* If an a property is not being written by the application, and it's value
|
|
* is invalid, then "fold" it to a new value, else fail validation (because
|
|
* the application is setting the property to an invalid value).
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pWiasContext - Pointer to the WIA item, unused.
|
|
* lFlags - Operation flags, unused.
|
|
* nPropSpec - The number of properties that are being written
|
|
* pPropSpec - An array of PropSpecs identifying the properties that
|
|
* are being written.
|
|
* plDevErrVal - Pointer to the device error value.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
***************************************************************************/
|
|
|
|
HRESULT _stdcall CWIAScannerDevice::drvValidateItemProperties(
|
|
BYTE *pWiasContext,
|
|
LONG lFlags,
|
|
ULONG nPropSpec,
|
|
const PROPSPEC *pPropSpec,
|
|
LONG *plDevErrVal)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::drvValidateItemProperties");
|
|
|
|
HRESULT hr = S_OK;
|
|
LONG lItemType = 0;
|
|
WIA_PROPERTY_CONTEXT Context;
|
|
|
|
if (plDevErrVal) {
|
|
*plDevErrVal = 0;
|
|
}
|
|
|
|
hr = wiasGetItemType(pWiasContext, &lItemType);
|
|
if (SUCCEEDED(hr)) {
|
|
if (lItemType & WiaItemTypeRoot) {
|
|
|
|
//
|
|
// Validate root item
|
|
//
|
|
|
|
|
|
hr = wiasCreatePropContext(nPropSpec,
|
|
(PROPSPEC*)pPropSpec,
|
|
0,
|
|
NULL,
|
|
&Context);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Check ADF to see if the status settings need to be updated
|
|
// Also switch between FEEDER/FLATBED modes
|
|
//
|
|
|
|
hr = CheckADFStatus(pWiasContext, &Context);
|
|
if(FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvValidateItemProperties, CheckADFStatus failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
}
|
|
|
|
//
|
|
// check Preview Property only if validation is successful so far....
|
|
//
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Check Preview property to see if the settings are valid
|
|
//
|
|
|
|
hr = CheckPreview(pWiasContext, &Context);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvValidateItemProperties, CheckPreview failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
}
|
|
}
|
|
} else {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvValidateItemProperties, wiasCreatePropContext failed (Root Item)"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
}
|
|
|
|
//
|
|
// call WIA service helper to validate other properties
|
|
//
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = wiasValidateItemProperties(pWiasContext, nPropSpec, pPropSpec);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvValidateItemProperties, wiasValidateItemProperties failed."));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// validate item properties here
|
|
//
|
|
|
|
//
|
|
// Create a property context needed by some WIA Service
|
|
// functions used below.
|
|
//
|
|
|
|
hr = wiasCreatePropContext(nPropSpec,
|
|
(PROPSPEC*)pPropSpec,
|
|
0,
|
|
NULL,
|
|
&Context);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Check Current Intent first
|
|
//
|
|
|
|
hr = CheckIntent(pWiasContext, &Context);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Check if DataType is being written
|
|
//
|
|
|
|
hr = CheckDataType(pWiasContext, &Context);
|
|
if (SUCCEEDED(hr)) {
|
|
#ifdef _SERVICE_EXTENT_VALIDATION
|
|
|
|
//
|
|
// Use the WIA service to update the scan rect
|
|
// properties and valid values.
|
|
//
|
|
|
|
LONG lBedWidth = 0;
|
|
LONG lBedHeight = 0;
|
|
hr = m_pScanAPI->GetBedWidthAndHeight(&lBedWidth,&lBedHeight);
|
|
if(FAILED(hr)){
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvValidateItemProperties, m_pScanAPI->GetBedWidthAndHeight failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
hr = wiasUpdateScanRect(pWiasContext,
|
|
&Context,
|
|
lBedWidth,
|
|
lBedHeight);
|
|
|
|
#endif
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Use the WIA Service to update the valid values
|
|
// for Format. These are based on the value of
|
|
// WIA_IPA_TYMED, so validation is also performed
|
|
// on the tymed property by the service.
|
|
//
|
|
|
|
hr = wiasUpdateValidFormat(pWiasContext,
|
|
&Context,
|
|
(IWiaMiniDrv*) this);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Check Preferred format
|
|
//
|
|
|
|
hr = CheckPreferredFormat(pWiasContext, &Context);
|
|
if(FAILED(hr)){
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvValidateItemProperties, CheckPreferredFormat failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
}
|
|
} else {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvValidateItemProperties, wiasUpdateValidFormat failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
}
|
|
} else {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvValidateItemProperties, wiasUpdateScanRect failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
}
|
|
} else {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvValidateItemProperties, CheckDataType failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
}
|
|
} else {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvValidateItemProperties, CheckIntent failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
}
|
|
wiasFreePropContext(&Context);
|
|
} else {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvValidateItemProperties, wiasCreatePropContext failed (Child Item)"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
}
|
|
|
|
//
|
|
// Update the item size
|
|
//
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = SetItemSize(pWiasContext);
|
|
if(FAILED(hr)){
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvValidateItemProperties, SetItemSize failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
}
|
|
|
|
//
|
|
// call WIA service helper to validate other properties
|
|
//
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = wiasValidateItemProperties(pWiasContext, nPropSpec, pPropSpec);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvValidateItemProperties, wiasValidateItemProperties failed."));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
} else {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvValidateItemProperties, wiasGetItemType failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
}
|
|
|
|
//
|
|
// log HRESULT sent back to caller
|
|
//
|
|
|
|
if(FAILED(hr)){
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWIAScannerDevice::drvWriteItemProperties
|
|
*
|
|
* Write the device item properties to the hardware. This is called by the
|
|
* WIA Class driver prior to drvAcquireItemData when the client requests
|
|
* a data transfer.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pWiasContext - Pointer to WIA item.
|
|
* lFlags - Operation flags, unused.
|
|
* pmdtc - Pointer to mini driver context. On entry, only the
|
|
* portion of the mini driver context which is derived
|
|
* from the item properties is filled in.
|
|
* plDevErrVal - Pointer to the device error value.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWIAScannerDevice::drvWriteItemProperties(
|
|
BYTE *pWiasContext,
|
|
LONG lFlags,
|
|
PMINIDRV_TRANSFER_CONTEXT pmdtc,
|
|
LONG *plDevErrVal)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::drvWriteItemProperties");
|
|
HRESULT hr = S_OK;
|
|
if (plDevErrVal) {
|
|
*plDevErrVal = 0;
|
|
}
|
|
LONG lNumProperties = 10;
|
|
PROPVARIANT pv[10];
|
|
|
|
//
|
|
// The order of these should not change. They are referenced below
|
|
// by index.
|
|
//
|
|
|
|
PROPSPEC ps[10] = {
|
|
{PRSPEC_PROPID, WIA_IPS_XRES},
|
|
{PRSPEC_PROPID, WIA_IPS_YRES},
|
|
{PRSPEC_PROPID, WIA_IPS_XPOS},
|
|
{PRSPEC_PROPID, WIA_IPS_YPOS},
|
|
{PRSPEC_PROPID, WIA_IPS_XEXTENT},
|
|
{PRSPEC_PROPID, WIA_IPS_YEXTENT},
|
|
{PRSPEC_PROPID, WIA_IPA_DATATYPE},
|
|
{PRSPEC_PROPID, WIA_IPS_BRIGHTNESS},
|
|
{PRSPEC_PROPID, WIA_IPS_CONTRAST},
|
|
{PRSPEC_PROPID, WIA_IPA_FORMAT}
|
|
};
|
|
|
|
//
|
|
// initialize propvariant structures
|
|
//
|
|
|
|
for (int i = 0; i< lNumProperties;i++) {
|
|
pv[i].vt = VT_I4;
|
|
}
|
|
|
|
//
|
|
// read child item properties
|
|
//
|
|
|
|
hr = wiasReadMultiple(pWiasContext, lNumProperties, ps, pv, NULL);
|
|
|
|
if (hr == S_OK) {
|
|
|
|
hr = m_pScanAPI->SetXYResolution(pv[0].lVal,pv[1].lVal);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
("drvWriteItemProperties, Setting x any y resolutions failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
hr = m_pScanAPI->SetDataType(pv[6].lVal);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
("drvWriteItemProperties, Setting data type failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
hr = m_pScanAPI->SetIntensity(pv[7].lVal);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
("drvWriteItemProperties, Setting intensity failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
hr = m_pScanAPI->SetContrast(pv[8].lVal);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
("drvWriteItemProperties, Setting contrast failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
hr = m_pScanAPI->SetSelectionArea(pv[2].lVal, pv[3].lVal, pv[4].lVal, pv[5].lVal);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
("drvWriteItemProperties, Setting selection area (extents) failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
hr = m_pScanAPI->SetFormat((GUID*)pv[9].puuid);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
("drvWriteItemProperties, Setting current format failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
PropVariantClear(&pv[9]);
|
|
return hr;
|
|
}
|
|
PropVariantClear(&pv[9]);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWIAScannerDevice::drvReadItemProperties
|
|
*
|
|
* Read the device item properties. When a client application tries to
|
|
* read a WIA Item's properties, the WIA Class driver will first notify
|
|
* the driver by calling this method.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pWiasContext - wia item
|
|
* lFlags - Operation flags, unused.
|
|
* nPropSpec - Number of elements in pPropSpec.
|
|
* pPropSpec - Pointer to property specification, showing which properties
|
|
* the application wants to read.
|
|
* plDevErrVal - Pointer to the device error value.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWIAScannerDevice::drvReadItemProperties(
|
|
BYTE *pWiasContext,
|
|
LONG lFlags,
|
|
ULONG nPropSpec,
|
|
const PROPSPEC *pPropSpec,
|
|
LONG *plDevErrVal)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::drvReadItemProperties");
|
|
if (plDevErrVal) {
|
|
*plDevErrVal = 0;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWIAScannerDevice::drvLockWiaDevice
|
|
*
|
|
* Lock access to the device.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pWiasContext - unused, can be NULL
|
|
* lFlags - Operation flags, unused.
|
|
* plDevErrVal - Pointer to the device error value.
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWIAScannerDevice::drvLockWiaDevice(
|
|
BYTE *pWiasContext,
|
|
LONG lFlags,
|
|
LONG *plDevErrVal)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::drvLockWiaDevice");
|
|
if (plDevErrVal) {
|
|
*plDevErrVal = 0;
|
|
}
|
|
return m_pStiDevice->LockDevice(m_dwLockTimeout);
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWIAScannerDevice::drvUnLockWiaDevice
|
|
*
|
|
* Unlock access to the device.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pWiasContext - Pointer to the WIA item, unused.
|
|
* lFlags - Operation flags, unused.
|
|
* plDevErrVal - Pointer to the device error value.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWIAScannerDevice::drvUnLockWiaDevice(
|
|
BYTE *pWiasContext,
|
|
LONG lFlags,
|
|
LONG *plDevErrVal)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::drvUnLockWiaDevice");
|
|
if (plDevErrVal) {
|
|
*plDevErrVal = 0;
|
|
}
|
|
return m_pStiDevice->UnLockDevice();
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWIAScannerDevice::drvAnalyzeItem
|
|
*
|
|
* This device does not support image analysis, so return E_NOTIMPL.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pWiasContext - Pointer to the device item to be analyzed.
|
|
* lFlags - Operation flags.
|
|
* plDevErrVal - Pointer to the device error value.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWIAScannerDevice::drvAnalyzeItem(
|
|
BYTE *pWiasContext,
|
|
LONG lFlags,
|
|
LONG *plDevErrVal)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::drvAnalyzeItem");
|
|
if (plDevErrVal) {
|
|
*plDevErrVal = 0;
|
|
}
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWIAScannerDevice::drvFreeDrvItemContext
|
|
*
|
|
* Free any device specific context.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* lFlags - Operation flags, unused.
|
|
* pDevSpecContext - Pointer to device specific context.
|
|
* plDevErrVal - Pointer to the device error value.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWIAScannerDevice::drvFreeDrvItemContext(
|
|
LONG lFlags,
|
|
BYTE *pSpecContext,
|
|
LONG *plDevErrVal)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::drvFreeDrvItemContext");
|
|
if (plDevErrVal) {
|
|
*plDevErrVal = 0;
|
|
}
|
|
PMINIDRIVERITEMCONTEXT pContext = NULL;
|
|
pContext = (PMINIDRIVERITEMCONTEXT) pSpecContext;
|
|
|
|
if (pContext){
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvFreeDrvItemContext, Freeing my allocated context members"));
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWIAScannerDevice::drvInitializeWia
|
|
*
|
|
* Initialize the WIA mini driver. This will build up the driver item tree
|
|
* and perform any other initialization code that's needed for WIA.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pWiasContext - Pointer to the WIA item, unused.
|
|
* lFlags - Operation flags, unused.
|
|
* bstrDeviceID - Device ID.
|
|
* bstrRootFullItemName - Full item name.
|
|
* pIPropStg - Device info. properties.
|
|
* pStiDevice - STI device interface.
|
|
* pIUnknownOuter - Outer unknown interface.
|
|
* ppIDrvItemRoot - Pointer to returned root item.
|
|
* ppIUnknownInner - Pointer to returned inner unknown.
|
|
* plDevErrVal - Pointer to the device error value.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWIAScannerDevice::drvInitializeWia(
|
|
BYTE *pWiasContext,
|
|
LONG lFlags,
|
|
BSTR bstrDeviceID,
|
|
BSTR bstrRootFullItemName,
|
|
IUnknown *pStiDevice,
|
|
IUnknown *pIUnknownOuter,
|
|
IWiaDrvItem **ppIDrvItemRoot,
|
|
IUnknown **ppIUnknownInner,
|
|
LONG *plDevErrVal)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::drvInitializeWia");
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvInitializeWia, bstrDeviceID = %ws", bstrDeviceID));
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvInitializeWia, bstrRootFullItemName = %ws",bstrRootFullItemName));
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvInitializeWia, lFlags = %d",lFlags));
|
|
HRESULT hr = S_OK;
|
|
|
|
if (plDevErrVal) {
|
|
*plDevErrVal = 0;
|
|
}
|
|
|
|
*ppIDrvItemRoot = NULL;
|
|
*ppIUnknownInner = NULL;
|
|
|
|
//
|
|
// Need to init names and STI pointer?
|
|
//
|
|
|
|
if (m_pStiDevice == NULL) {
|
|
|
|
//
|
|
// save STI device interface for locking
|
|
//
|
|
|
|
m_pStiDevice = (IStiDevice *)pStiDevice;
|
|
|
|
//
|
|
// Cache the device ID.
|
|
//
|
|
|
|
m_bstrDeviceID = SysAllocString(bstrDeviceID);
|
|
|
|
if (!m_bstrDeviceID) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitializeWia, unable to allocate device ID string"));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
//
|
|
// Cache the root property stream name.
|
|
//
|
|
|
|
m_bstrRootFullItemName = SysAllocString(bstrRootFullItemName);
|
|
|
|
if (!m_bstrRootFullItemName) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitializeWia, unable to allocate prop stream name"));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Initialize Capabilities array
|
|
//
|
|
|
|
hr = BuildCapabilities();
|
|
|
|
if(FAILED(hr)) {
|
|
DeleteCapabilitiesArrayContents();
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitializeWia, BuildCapabilities failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Initialize SupportedFormats array
|
|
//
|
|
|
|
hr = BuildSupportedFormats();
|
|
|
|
if(FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitializeWia, BuildSupportedFormats failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Initialize Supported Data Type array
|
|
//
|
|
|
|
hr = BuildSupportedDataTypes();
|
|
|
|
if(FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitializeWia, BuildSupportedDataTypes failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Initialize Supported Intents array
|
|
//
|
|
|
|
hr = BuildSupportedIntents();
|
|
|
|
if(FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitializeWia, BuildSupportedIntents failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Initialize Supported TYMED array
|
|
//
|
|
|
|
hr = BuildSupportedTYMED();
|
|
|
|
if(FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitializeWia, BuildSuportedTYMED failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Initialize Supported compression types array
|
|
//
|
|
|
|
hr = BuildSupportedCompressions();
|
|
|
|
if(FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitializeWia, BuildSupportedCompressions"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Initialize Supported Preview modes array
|
|
//
|
|
|
|
hr = BuildSupportedPreviewModes();
|
|
|
|
if(FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitializeWia, BuildSupportedPreviewModes"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Initialize initial formats array
|
|
//
|
|
|
|
hr = BuildInitialFormats();
|
|
|
|
if(FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitializeWia, BuildInitialFormats failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Initialize supported resolutions array
|
|
//
|
|
|
|
hr = BuildSupportedResolutions();
|
|
if(FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitializeWia, BuildSupportedResolutions failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Build the device item tree, if it hasn't been built yet.
|
|
//
|
|
// Send a Device Command to yourself, or Call BuildItemTree manually
|
|
//
|
|
|
|
if (!m_pIDrvItemRoot) {
|
|
LONG lDevErrVal = 0;
|
|
hr = drvDeviceCommand(NULL, 0, &WIA_CMD_SYNCHRONIZE, NULL, &lDevErrVal);
|
|
if(FAILED(hr)){
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitializeWia, drvDeviceCommand(WIA_CMD_SYNCHRONIZE) failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
}
|
|
}
|
|
|
|
//
|
|
// save root item pointer. (REMEMBER TO RELEASE THIS INTERFACE)
|
|
//
|
|
|
|
*ppIDrvItemRoot = m_pIDrvItemRoot;
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWIAScannerDevice::drvUnInitializeWia
|
|
*
|
|
* Gets called when a client connection is going away.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pWiasContext - Pointer to the WIA Root item context of the client's
|
|
* item tree.
|
|
*
|
|
* Return Value:
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWIAScannerDevice::drvUnInitializeWia(
|
|
BYTE *pWiasContext)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* drvGetDeviceErrorStr
|
|
*
|
|
* Map a device error value to a string.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* lFlags - Operation flags, unused.
|
|
* lDevErrVal - Device error value.
|
|
* ppszDevErrStr - Pointer to returned error string.
|
|
* plDevErrVal - Pointer to the device error value.
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWIAScannerDevice::drvGetDeviceErrorStr(
|
|
LONG lFlags,
|
|
LONG lDevErrVal,
|
|
LPOLESTR *ppszDevErrStr,
|
|
LONG *plDevErr)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::drvGetDeviceErrorStr");
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Map device errors to a string to be placed in the event log.
|
|
//
|
|
|
|
if (plDevErr) {
|
|
if (*ppszDevErrStr) {
|
|
|
|
//
|
|
// look up error strings in resource file.
|
|
//
|
|
|
|
switch (lDevErrVal) {
|
|
case 0:
|
|
*ppszDevErrStr = L"No Error"; // hard coded for now
|
|
*plDevErr = 0;
|
|
hr = S_OK;
|
|
break;
|
|
default:
|
|
*ppszDevErrStr = L"Device Error, Unknown Error";// hard coded for now
|
|
*plDevErr = 0;
|
|
hr = E_FAIL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* drvDeviceCommand
|
|
*
|
|
* Issue a command to the device.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pWiasContext - Pointer to the WIA item.
|
|
* lFlags - Operation flags, unused.
|
|
* plCommand - Pointer to command GUID.
|
|
* ppWiaDrvItem - Optional pointer to returned item, unused.
|
|
* plDevErrVal - Pointer to the device error value.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWIAScannerDevice::drvDeviceCommand(
|
|
BYTE *pWiasContext,
|
|
LONG lFlags,
|
|
const GUID *plCommand,
|
|
IWiaDrvItem **ppWiaDrvItem,
|
|
LONG *plDevErrVal)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::drvDeviceCommand");
|
|
if(plDevErrVal){
|
|
*plDevErrVal = 0;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Check which command was issued
|
|
//
|
|
|
|
if (*plCommand == WIA_CMD_SYNCHRONIZE) {
|
|
|
|
//
|
|
// SYNCHRONIZE - Build the minidriver representation of
|
|
// the current item list, if it doesn't exist.
|
|
//
|
|
|
|
if (!m_pIDrvItemRoot) {
|
|
hr = BuildItemTree();
|
|
} else {
|
|
hr = S_OK;
|
|
}
|
|
} else {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvDeviceCommand, unknown command sent to this device"));
|
|
hr = E_NOTIMPL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* CWIAScannerDevice::drvGetCapabilities
|
|
*
|
|
* Get supported device commands and events as an array of WIA_DEV_CAPS.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pWiasContext - Pointer to the WIA item, unused.
|
|
* lFlags - Operation flags.
|
|
* pcelt - Pointer to returned number of elements in
|
|
* returned GUID array.
|
|
* ppCapabilities - Pointer to returned GUID array.
|
|
* plDevErrVal - Pointer to the device error value.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWIAScannerDevice::drvGetCapabilities(
|
|
BYTE *pWiasContext,
|
|
LONG ulFlags,
|
|
LONG *pcelt,
|
|
WIA_DEV_CAP_DRV **ppCapabilities,
|
|
LONG *plDevErrVal)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::drvGetCapabilites");
|
|
if(plDevErrVal){
|
|
*plDevErrVal = 0;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Initialize Capabilities array
|
|
//
|
|
|
|
hr = BuildCapabilities();
|
|
|
|
if(FAILED(hr)) {
|
|
DeleteCapabilitiesArrayContents();
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvGetCapabilities, BuildCapabilities failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Return depends on flags. Flags specify whether we should return
|
|
// commands, events, or both.
|
|
//
|
|
//
|
|
|
|
switch (ulFlags) {
|
|
case WIA_DEVICE_COMMANDS:
|
|
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvGetCapabilities, (WIA_DEVICE_COMMANDS)"));
|
|
|
|
//
|
|
// report commands only
|
|
//
|
|
|
|
*pcelt = m_NumSupportedCommands;
|
|
*ppCapabilities = &m_pCapabilities[m_NumSupportedEvents];
|
|
break;
|
|
case WIA_DEVICE_EVENTS:
|
|
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvGetCapabilities, (WIA_DEVICE_EVENTS)"));
|
|
|
|
//
|
|
// report events only
|
|
//
|
|
|
|
*pcelt = m_NumSupportedEvents;
|
|
*ppCapabilities = m_pCapabilities;
|
|
break;
|
|
case (WIA_DEVICE_COMMANDS | WIA_DEVICE_EVENTS):
|
|
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvGetCapabilities, (WIA_DEVICE_COMMANDS|WIA_DEVICE_EVENTS)"));
|
|
|
|
//
|
|
// report both events and commands
|
|
//
|
|
|
|
*pcelt = m_NumCapabilities;
|
|
*ppCapabilities = m_pCapabilities;
|
|
break;
|
|
default:
|
|
|
|
//
|
|
// invalid request
|
|
//
|
|
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvGetCapabilities, invalid flags"));
|
|
return E_INVALIDARG;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* drvGetWiaFormatInfo
|
|
*
|
|
* Returns an array of WIA_FORMAT_INFO structs, which specify the format
|
|
* and media type pairs that are supported.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pWiasContext - Pointer to the WIA item context, unused.
|
|
* lFlags - Operation flags, unused.
|
|
* pcelt - Pointer to returned number of elements in
|
|
* returned WIA_FORMAT_INFO array.
|
|
* ppwfi - Pointer to returned WIA_FORMAT_INFO array.
|
|
* plDevErrVal - Pointer to the device error value.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWIAScannerDevice::drvGetWiaFormatInfo(
|
|
BYTE *pWiasContext,
|
|
LONG lFlags,
|
|
LONG *pcelt,
|
|
WIA_FORMAT_INFO **ppwfi,
|
|
LONG *plDevErrVal)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::drvGetWiaFormatInfo");
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if(NULL == m_pSupportedFormats){
|
|
hr = BuildSupportedFormats();
|
|
}
|
|
|
|
if(plDevErrVal){
|
|
*plDevErrVal = 0;
|
|
}
|
|
*pcelt = m_NumSupportedFormats;
|
|
*ppwfi = m_pSupportedFormats;
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvGetWiaFormatInfo, m_NumSupportedFormats = %d",m_NumSupportedFormats));
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvGetWiaFormatInfo, m_pSupportedFormats = %x",m_pSupportedFormats));
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* drvNotifyPnpEvent
|
|
*
|
|
* Pnp Event received by device manager. This is called when a Pnp event
|
|
* is received for this device.
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWIAScannerDevice::drvNotifyPnpEvent(
|
|
const GUID *pEventGUID,
|
|
BSTR bstrDeviceID,
|
|
ULONG ulReserved)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::drvNotifyPnpEvent");
|
|
HRESULT hr = S_OK;
|
|
|
|
if (*pEventGUID == WIA_EVENT_DEVICE_DISCONNECTED) {
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvNotifyPnpEvent, (WIA_EVENT_DEVICE_DISCONNECTED)"));
|
|
hr = m_pScanAPI->DisableDevice();
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvNotifyPnpEvent, disable failed"));
|
|
}
|
|
}
|
|
|
|
if (*pEventGUID == WIA_EVENT_POWER_SUSPEND){
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvNotifyPnpEvent, (WIA_EVENT_POWER_SUSPEND)"));
|
|
hr = m_pScanAPI->DisableDevice();
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvNotifyPnpEvent, disable failed"));
|
|
}
|
|
}
|
|
|
|
if (*pEventGUID == WIA_EVENT_POWER_RESUME){
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvNotifyPnpEvent, (WIA_EVENT_POWER_RESUME)"));
|
|
hr = m_pScanAPI->EnableDevice();
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvNotifyPnpEvent, enable failed"));
|
|
}
|
|
|
|
if (NULL != m_hSignalEvent) {
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvNotifyPnpEvent, (restarting interrrupt event system)"));
|
|
hr = SetNotificationHandle(m_hSignalEvent);
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvNotifyPnpEvent, SetNotificationHandle failed"));
|
|
}
|
|
} else {
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvNotifyPnpEvent, (not restarting interrrupt event system), device may not need it."));
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* P R I V A T E M E T H O D S
|
|
*
|
|
*******************************************************************************/
|
|
|
|
/**************************************************************************\
|
|
* AlignInPlace
|
|
*
|
|
* DWORD align a data buffer in place.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pBuffer - Pointer to the data buffer.
|
|
* cbWritten - Size of the data in bytes.
|
|
* lBytesPerScanLine - Number of bytes per scan line in the output data.
|
|
* lBytesPerScanLineRaw - Number of bytes per scan line in the input data.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
UINT CWIAScannerDevice::AlignInPlace(
|
|
PBYTE pBuffer,
|
|
LONG cbWritten,
|
|
LONG lBytesPerScanLine,
|
|
LONG lBytesPerScanLineRaw)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL3,
|
|
"::AlignInPlace");
|
|
if (lBytesPerScanLineRaw % 4) {
|
|
|
|
UINT uiPadBytes = lBytesPerScanLine - lBytesPerScanLineRaw;
|
|
UINT uiDevLinesWritten = cbWritten / lBytesPerScanLineRaw;
|
|
|
|
PBYTE pSrc = pBuffer + cbWritten - 1;
|
|
PBYTE pDst = pBuffer + (uiDevLinesWritten * lBytesPerScanLine) - 1;
|
|
|
|
while (pSrc >= pBuffer) {
|
|
pDst -= uiPadBytes;
|
|
|
|
for (LONG i = 0; i < lBytesPerScanLineRaw; i++) {
|
|
*pDst-- = *pSrc--;
|
|
}
|
|
}
|
|
return uiDevLinesWritten * lBytesPerScanLine;
|
|
}
|
|
return cbWritten;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* UnlinkItemTree
|
|
*
|
|
* Call device manager to unlink and release our reference to
|
|
* all items in the driver item tree.
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWIAScannerDevice::DeleteItemTree(void)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL3,
|
|
"CWIAScannerDevice::DeleteItemTree");
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// If no tree, return.
|
|
//
|
|
|
|
if (!m_pIDrvItemRoot) {
|
|
WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("DeleteItemTree, no tree to delete..."));
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// Call device manager to unlink the driver item tree.
|
|
//
|
|
|
|
hr = m_pIDrvItemRoot->UnlinkItemTree(WiaItemTypeDisconnected);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("DeleteItemTree, m_pIDrvItemRoot is being released!!"));
|
|
m_pIDrvItemRoot->Release();
|
|
m_pIDrvItemRoot = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* BuildItemTree
|
|
*
|
|
* The device uses the WIA Service functions to build up a tree of
|
|
* device items. This device supports only a single data acquisition item so
|
|
* build a device item tree with only one child off the root.
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWIAScannerDevice::BuildItemTree(void)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL3,
|
|
"CWIAScannerDevice::BuildItemTree");
|
|
//
|
|
// The device item tree must not exist.
|
|
//
|
|
|
|
WIAS_ASSERT( (g_hInst), (m_pIDrvItemRoot == NULL));
|
|
|
|
//
|
|
// Call the class driver to create the root item.
|
|
//
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
//
|
|
// Name the root.
|
|
//
|
|
|
|
BSTR bstrRootItemName = NULL;
|
|
hr = GetBSTRResourceString(IDS_ROOTITEM_NAME,&bstrRootItemName,TRUE);
|
|
if (SUCCEEDED(hr)) {
|
|
hr = wiasCreateDrvItem(WiaItemTypeFolder |
|
|
WiaItemTypeDevice |
|
|
WiaItemTypeRoot,
|
|
bstrRootItemName,
|
|
m_bstrRootFullItemName,
|
|
(IWiaMiniDrv *)this,
|
|
sizeof(MINIDRIVERITEMCONTEXT),
|
|
NULL,
|
|
&m_pIDrvItemRoot);
|
|
|
|
SysFreeString(bstrRootItemName);
|
|
}
|
|
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildItemTree, wiasCreateDrvItem failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Create and add the Top/Front and Bottom/Back device items.
|
|
//
|
|
|
|
for (INT i = 0; i < NUM_DEVICE_ITEM; i++) {
|
|
|
|
//
|
|
// Build the item names.
|
|
//
|
|
|
|
BSTR bstrItemName = NULL;
|
|
hr = GetBSTRResourceString(IDS_TOPITEM_NAME,&bstrItemName,TRUE);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
// SBB - RAID 370299 - orenr - 2001/04/18 - Security fix -
|
|
// potential buffer overrun. Changed wcscpy and wcscat
|
|
// to use _snwprintf instead
|
|
|
|
WCHAR szFullItemName[MAX_PATH + 1] = {0};
|
|
|
|
_snwprintf(szFullItemName,
|
|
(sizeof(szFullItemName) / sizeof(WCHAR)) - 1,
|
|
L"%ls\\%ls",
|
|
m_bstrRootFullItemName,
|
|
bstrItemName);
|
|
|
|
//
|
|
// Call the class driver to create another driver item.
|
|
// This will be inserted as the child item.
|
|
//
|
|
|
|
PMINIDRIVERITEMCONTEXT pItemContext;
|
|
IWiaDrvItem *pItem = NULL;
|
|
|
|
hr = wiasCreateDrvItem(WiaItemTypeFile |
|
|
WiaItemTypeImage |
|
|
WiaItemTypeDevice,
|
|
bstrItemName,
|
|
szFullItemName,
|
|
(IWiaMiniDrv *)this,
|
|
sizeof(MINIDRIVERITEMCONTEXT),
|
|
(PBYTE*) &pItemContext,
|
|
&pItem);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Initialize device specific context.
|
|
//
|
|
|
|
memset(pItemContext, 0, sizeof(MINIDRIVERITEMCONTEXT));
|
|
pItemContext->lSize = sizeof(MINIDRIVERITEMCONTEXT);
|
|
|
|
//
|
|
// Call the class driver to add pItem to the folder
|
|
// m_pIDrvItemRoot (i.e. make pItem a child of
|
|
// m_pIDrvItemRoot).
|
|
//
|
|
|
|
hr = pItem->AddItemToFolder(m_pIDrvItemRoot);
|
|
|
|
if (FAILED(hr)) {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildItemTree, AddItemToFolder failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
}
|
|
|
|
//
|
|
// release and created items
|
|
//
|
|
|
|
pItem->Release();
|
|
|
|
} else {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildItemTree, wiasCreateDrvItem failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
}
|
|
|
|
//
|
|
// free the BSTR allocated by the BSTRResourceString helper
|
|
//
|
|
|
|
SysFreeString(bstrItemName);
|
|
|
|
} else {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildItemTree, unable to allocate item name"));
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
break; // Error if here, quit iterating.
|
|
}
|
|
|
|
if (FAILED(hr)) {
|
|
DeleteItemTree();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* DeleteRootItemProperties
|
|
*
|
|
* This helper deletes the arrays used for Property intialization.
|
|
*
|
|
* [Array Name] [Description] [Array Type]
|
|
*
|
|
* m_pszRootItemDefaults - Property name array (LPOLESTR)
|
|
* m_piRootItemDefaults - Property ID array (PROPID)
|
|
* m_pvRootItemDefaults - Property Variant array (PROPVARIANT)
|
|
* m_psRootItemDefaults - Property Spec array (PROPSPEC)
|
|
* m_wpiRootItemDefaults - WIA Property Info array (WIA_PROPERTY_INFO)
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT CWIAScannerDevice::DeleteRootItemProperties()
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::DeleteRootItemProperties");
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// delete any allocated arrays
|
|
//
|
|
|
|
DeleteSupportedPreviewModesArrayContents();
|
|
|
|
if(NULL != m_pszRootItemDefaults){
|
|
delete [] m_pszRootItemDefaults;
|
|
m_pszRootItemDefaults = NULL;
|
|
}
|
|
|
|
if(NULL != m_piRootItemDefaults){
|
|
delete [] m_piRootItemDefaults;
|
|
m_piRootItemDefaults = NULL;
|
|
}
|
|
|
|
if(NULL != m_pvRootItemDefaults){
|
|
FreePropVariantArray(m_NumRootItemProperties,m_pvRootItemDefaults);
|
|
delete [] m_pvRootItemDefaults;
|
|
m_pvRootItemDefaults = NULL;
|
|
}
|
|
|
|
if(NULL != m_psRootItemDefaults){
|
|
delete [] m_psRootItemDefaults;
|
|
m_psRootItemDefaults = NULL;
|
|
}
|
|
|
|
if(NULL != m_wpiRootItemDefaults){
|
|
delete [] m_wpiRootItemDefaults;
|
|
m_wpiRootItemDefaults = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* BuildRootItemProperties
|
|
*
|
|
* This helper creates/initializes the arrays used for Property intialization.
|
|
*
|
|
* [Array Name] [Description] [Array Type]
|
|
*
|
|
* m_pszRootItemDefaults - Property name array (LPOLESTR)
|
|
* m_piRootItemDefaults - Property ID array (PROPID)
|
|
* m_pvRootItemDefaults - Property Variant array (PROPVARIANT)
|
|
* m_psRootItemDefaults - Property Spec array (PROPSPEC)
|
|
* m_wpiRootItemDefaults - WIA Property Info array (WIA_PROPERTY_INFO)
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT CWIAScannerDevice::BuildRootItemProperties()
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::BuildRootItemProperties");
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if(m_pScanAPI->ADFAttached() == S_OK){
|
|
m_bADFAttached = TRUE;
|
|
}
|
|
|
|
WIAPROPERTIES RootItemProperties;
|
|
memset(&RootItemProperties,0,sizeof(RootItemProperties));
|
|
|
|
// set host driver numeric values
|
|
RootItemProperties.NumSupportedPreviewModes = m_NumSupportedPreviewModes;
|
|
|
|
// set host driver allocated pointers
|
|
RootItemProperties.pSupportedPreviewModes = m_pSupportedPreviewModes;
|
|
|
|
hr = m_pScanAPI->BuildRootItemProperties(&RootItemProperties);
|
|
if(FAILED(hr)){
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildRootItemProperties, m_pScanAPI->BuildRootItemProperties failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
DeleteRootItemProperties();
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// assign pointers to members
|
|
//
|
|
|
|
m_NumRootItemProperties = RootItemProperties.NumItemProperties;
|
|
m_piRootItemDefaults = RootItemProperties.piItemDefaults;
|
|
m_psRootItemDefaults = RootItemProperties.psItemDefaults;
|
|
m_pszRootItemDefaults = RootItemProperties.pszItemDefaults;
|
|
m_pvRootItemDefaults = RootItemProperties.pvItemDefaults;
|
|
m_wpiRootItemDefaults = RootItemProperties.wpiItemDefaults;
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* DeleteTopItemProperties
|
|
*
|
|
* This helper deletes the arrays used for Property intialization.
|
|
*
|
|
* [Array Name] [Description] [Array Type]
|
|
*
|
|
* m_pszItemDefaults - Property name array (LPOLESTR)
|
|
* m_piItemDefaults - Property ID array (PROPID)
|
|
* m_pvItemDefaults - Property Variant array (PROPVARIANT)
|
|
* m_psItemDefaults - Property Spec array (PROPSPEC)
|
|
* m_wpiItemDefaults - WIA Property Info array (WIA_PROPERTY_INFO)
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT CWIAScannerDevice::DeleteTopItemProperties()
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::DeleteTopItemProperties");
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// delete any allocated arrays
|
|
//
|
|
|
|
DeleteSupportedFormatsArrayContents();
|
|
DeleteSupportedDataTypesArrayContents();
|
|
DeleteSupportedCompressionsArrayContents();
|
|
DeleteSupportedTYMEDArrayContents();
|
|
DeleteInitialFormatsArrayContents();
|
|
DeleteSupportedResolutionsArrayContents();
|
|
|
|
if(NULL != m_pszItemDefaults){
|
|
delete [] m_pszItemDefaults;
|
|
m_pszItemDefaults = NULL;
|
|
}
|
|
|
|
if(NULL != m_piItemDefaults){
|
|
delete [] m_piItemDefaults;
|
|
m_piItemDefaults = NULL;
|
|
}
|
|
|
|
if(NULL != m_pvItemDefaults){
|
|
for(LONG lPropIndex = 0; lPropIndex < m_NumItemProperties; lPropIndex++){
|
|
|
|
//
|
|
// set CLSID pointers to NULL, because we freed the memory above.
|
|
// If this pointer is not NULL FreePropVariantArray would
|
|
// try to free it again.
|
|
//
|
|
|
|
if(m_pvItemDefaults[lPropIndex].vt == VT_CLSID){
|
|
m_pvItemDefaults[lPropIndex].puuid = NULL;
|
|
}
|
|
}
|
|
FreePropVariantArray(m_NumItemProperties,m_pvItemDefaults);
|
|
delete [] m_pvItemDefaults;
|
|
m_pvItemDefaults = NULL;
|
|
}
|
|
|
|
if(NULL != m_psItemDefaults){
|
|
delete [] m_psItemDefaults;
|
|
m_psItemDefaults = NULL;
|
|
}
|
|
|
|
if(NULL != m_wpiItemDefaults){
|
|
delete [] m_wpiItemDefaults;
|
|
m_wpiItemDefaults = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* BuildTopItemProperties
|
|
*
|
|
* This helper creates/initializes the arrays used for Property intialization.
|
|
*
|
|
* [Array Name] [Description] [Array Type]
|
|
*
|
|
* m_pszItemDefaults - Property name array (LPOLESTR)
|
|
* m_piItemDefaults - Property ID array (PROPID)
|
|
* m_pvItemDefaults - Property Variant array (PROPVARIANT)
|
|
* m_psItemDefaults - Property Spec array (PROPSPEC)
|
|
* m_wpiItemDefaults - WIA Property Info array (WIA_PROPERTY_INFO)
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT CWIAScannerDevice::BuildTopItemProperties()
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::BuildTopItemProperties");
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
WIAPROPERTIES TopItemProperties;
|
|
memset(&TopItemProperties,0,sizeof(TopItemProperties));
|
|
|
|
// set host driver numeric values
|
|
TopItemProperties.NumInitialFormats = m_NumInitialFormats;
|
|
TopItemProperties.NumSupportedCompressionTypes = m_NumSupportedCompressionTypes;
|
|
TopItemProperties.NumSupportedDataTypes = m_NumSupportedDataTypes;
|
|
TopItemProperties.NumSupportedFormats = m_NumSupportedFormats;
|
|
TopItemProperties.NumSupportedIntents = m_NumSupportedIntents;
|
|
TopItemProperties.NumSupportedTYMED = m_NumSupportedTYMED;
|
|
TopItemProperties.NumSupportedResolutions = m_NumSupportedResolutions;
|
|
|
|
// set host driver allocated pointers
|
|
TopItemProperties.pInitialFormats = m_pInitialFormats;
|
|
TopItemProperties.pSupportedCompressionTypes = m_pSupportedCompressionTypes;
|
|
TopItemProperties.pSupportedDataTypes = m_pSupportedDataTypes;
|
|
TopItemProperties.pSupportedFormats = m_pSupportedFormats;
|
|
TopItemProperties.pSupportedIntents = m_pSupportedIntents;
|
|
TopItemProperties.pSupportedTYMED = m_pSupportedTYMED;
|
|
TopItemProperties.pSupportedResolutions = m_pSupportedResolutions;
|
|
TopItemProperties.bLegacyBWRestrictions = m_bLegacyBWRestriction;
|
|
|
|
hr = m_pScanAPI->BuildTopItemProperties(&TopItemProperties);
|
|
if(FAILED(hr)){
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildTopItemProperties, m_pScanAPI->BuildTopItemProperties failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
DeleteTopItemProperties();
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// assign pointers to members
|
|
//
|
|
|
|
m_NumItemProperties = TopItemProperties.NumItemProperties;
|
|
m_pszItemDefaults = TopItemProperties.pszItemDefaults;
|
|
m_piItemDefaults = TopItemProperties.piItemDefaults;
|
|
m_pvItemDefaults = TopItemProperties.pvItemDefaults;
|
|
m_psItemDefaults = TopItemProperties.psItemDefaults;
|
|
m_wpiItemDefaults = TopItemProperties.wpiItemDefaults;
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* BuildSupportedResolutions
|
|
*
|
|
* This helper initializes the supported resolution array
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT CWIAScannerDevice::BuildSupportedResolutions()
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::BuildSupportedResolutions");
|
|
|
|
HRESULT hr = S_OK;
|
|
if(NULL != m_pSupportedResolutions) {
|
|
|
|
//
|
|
// Supported intents have already been initialized,
|
|
// so return S_OK.
|
|
//
|
|
|
|
return hr;
|
|
}
|
|
m_NumSupportedResolutions = 6;
|
|
m_pSupportedResolutions = new LONG[m_NumSupportedResolutions];
|
|
if(m_pSupportedResolutions){
|
|
m_pSupportedResolutions[0] = 75;
|
|
m_pSupportedResolutions[1] = 100;
|
|
m_pSupportedResolutions[2] = 150;
|
|
m_pSupportedResolutions[3] = 200;
|
|
m_pSupportedResolutions[4] = 300;
|
|
m_pSupportedResolutions[5] = 600;
|
|
} else
|
|
hr = E_OUTOFMEMORY;
|
|
return hr;
|
|
}
|
|
/**************************************************************************\
|
|
* DeleteSupportedResolutionsArrayContents
|
|
*
|
|
* This helper deletes the supported resolutions array
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT CWIAScannerDevice::DeleteSupportedResolutionsArrayContents()
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::DeleteSupportedResolutionsArrayContents");
|
|
|
|
HRESULT hr = S_OK;
|
|
if(NULL != m_pSupportedResolutions)
|
|
delete [] m_pSupportedResolutions;
|
|
|
|
m_pSupportedResolutions = NULL;
|
|
m_NumSupportedResolutions = 0;
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* BuildSupportedIntents
|
|
*
|
|
* This helper initializes the supported intent array
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT CWIAScannerDevice::BuildSupportedIntents()
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::BuildSupportedIntents");
|
|
|
|
HRESULT hr = S_OK;
|
|
if(NULL != m_pSupportedIntents) {
|
|
|
|
//
|
|
// Supported intents have already been initialized,
|
|
// so return S_OK.
|
|
//
|
|
|
|
return hr;
|
|
}
|
|
m_NumSupportedIntents = 6;
|
|
m_pSupportedIntents = new LONG[m_NumSupportedIntents];
|
|
if(m_pSupportedIntents){
|
|
m_pSupportedIntents[0] = WIA_INTENT_NONE;
|
|
m_pSupportedIntents[1] = WIA_INTENT_IMAGE_TYPE_COLOR;
|
|
m_pSupportedIntents[2] = WIA_INTENT_IMAGE_TYPE_GRAYSCALE;
|
|
m_pSupportedIntents[3] = WIA_INTENT_IMAGE_TYPE_TEXT;
|
|
m_pSupportedIntents[4] = WIA_INTENT_MINIMIZE_SIZE;
|
|
m_pSupportedIntents[5] = WIA_INTENT_MAXIMIZE_QUALITY;
|
|
} else
|
|
hr = E_OUTOFMEMORY;
|
|
return hr;
|
|
}
|
|
/**************************************************************************\
|
|
* DeleteSupportedIntentsArrayContents
|
|
*
|
|
* This helper deletes the supported intent array
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT CWIAScannerDevice::DeleteSupportedIntentsArrayContents()
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::DeleteSupportedIntentsArrayContents");
|
|
|
|
HRESULT hr = S_OK;
|
|
if(NULL != m_pSupportedIntents)
|
|
delete [] m_pSupportedIntents;
|
|
|
|
m_pSupportedIntents = NULL;
|
|
m_NumSupportedIntents = 0;
|
|
return hr;
|
|
}
|
|
/**************************************************************************\
|
|
* BuildSupportedCompressions
|
|
*
|
|
* This helper initializes the supported compression types array
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT CWIAScannerDevice::BuildSupportedCompressions()
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::BuildSupportedCompressions");
|
|
|
|
HRESULT hr = S_OK;
|
|
if(NULL != m_pSupportedCompressionTypes) {
|
|
|
|
//
|
|
// Supported compression types have already been initialized,
|
|
// so return S_OK.
|
|
//
|
|
|
|
return hr;
|
|
}
|
|
|
|
m_NumSupportedCompressionTypes = 1;
|
|
m_pSupportedCompressionTypes = new LONG[m_NumSupportedCompressionTypes];
|
|
if(m_pSupportedCompressionTypes){
|
|
m_pSupportedCompressionTypes[0] = WIA_COMPRESSION_NONE;
|
|
} else
|
|
hr = E_OUTOFMEMORY;
|
|
return hr;
|
|
}
|
|
/**************************************************************************\
|
|
* DeleteSupportedCompressionsArrayContents
|
|
*
|
|
* This helper deletes the supported compression types array
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT CWIAScannerDevice::DeleteSupportedCompressionsArrayContents()
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::DeleteSupportedCompressionsArrayContents");
|
|
|
|
HRESULT hr = S_OK;
|
|
if (NULL != m_pSupportedCompressionTypes)
|
|
delete [] m_pSupportedCompressionTypes;
|
|
|
|
m_pSupportedCompressionTypes = NULL;
|
|
m_NumSupportedCompressionTypes = 0;
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* BuildSupportedPreviewModes
|
|
*
|
|
* This helper initializes the supported preview mode array
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 8/17/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT CWIAScannerDevice::BuildSupportedPreviewModes()
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::BuildSupportedPreviewModes");
|
|
|
|
HRESULT hr = S_OK;
|
|
if(NULL != m_pSupportedPreviewModes) {
|
|
|
|
//
|
|
// Supported preview modes have already been initialized,
|
|
// so return S_OK.
|
|
//
|
|
|
|
return hr;
|
|
}
|
|
|
|
m_NumSupportedPreviewModes = 2;
|
|
m_pSupportedPreviewModes = new LONG[m_NumSupportedPreviewModes];
|
|
if(m_pSupportedPreviewModes){
|
|
m_pSupportedPreviewModes[0] = WIA_FINAL_SCAN;
|
|
m_pSupportedPreviewModes[1] = WIA_PREVIEW_SCAN;
|
|
} else
|
|
hr = E_OUTOFMEMORY;
|
|
return hr;
|
|
}
|
|
/**************************************************************************\
|
|
* DeleteSupportedCompressionsArrayContents
|
|
*
|
|
* This helper deletes the supported compression types array
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 8/17/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT CWIAScannerDevice::DeleteSupportedPreviewModesArrayContents()
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::DeleteSupportedPreviewModesArrayContents");
|
|
|
|
HRESULT hr = S_OK;
|
|
if (NULL != m_pSupportedPreviewModes)
|
|
delete [] m_pSupportedPreviewModes;
|
|
|
|
m_pSupportedPreviewModes = NULL;
|
|
m_NumSupportedPreviewModes = 0;
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* BuildSupportedDataTypes
|
|
*
|
|
* This helper initializes the supported data types array
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT CWIAScannerDevice::BuildSupportedDataTypes()
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::BuildSupportedDataTypes");
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if(NULL != m_pSupportedDataTypes) {
|
|
|
|
//
|
|
// Supported data types have already been initialized,
|
|
// so return S_OK.
|
|
//
|
|
|
|
return hr;
|
|
}
|
|
|
|
if (m_bLegacyBWRestriction) {
|
|
m_NumSupportedDataTypes = NUM_DATA_TYPES_LEGACY;
|
|
} else {
|
|
m_NumSupportedDataTypes = NUM_DATA_TYPES_NONLEGACY;
|
|
}
|
|
m_pSupportedDataTypes = new LONG[m_NumSupportedDataTypes];
|
|
|
|
if(m_pSupportedDataTypes){
|
|
m_pSupportedDataTypes[0] = WIA_DATA_THRESHOLD;
|
|
m_pSupportedDataTypes[1] = WIA_DATA_GRAYSCALE;
|
|
|
|
//
|
|
// Add color support to non-legacy devices only
|
|
//
|
|
|
|
if (m_NumSupportedDataTypes == NUM_DATA_TYPES_NONLEGACY) {
|
|
m_pSupportedDataTypes[2] = WIA_DATA_COLOR;
|
|
}
|
|
} else
|
|
hr = E_OUTOFMEMORY;
|
|
return hr;
|
|
}
|
|
/**************************************************************************\
|
|
* DeleteSupportedDataTypesArrayContents
|
|
*
|
|
* This helper deletes the supported data types array
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT CWIAScannerDevice::DeleteSupportedDataTypesArrayContents()
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::DeleteSupportedDataTypesArrayContents");
|
|
|
|
HRESULT hr = S_OK;
|
|
if(NULL != m_pSupportedDataTypes)
|
|
delete [] m_pSupportedDataTypes;
|
|
|
|
m_pSupportedDataTypes = NULL;
|
|
m_NumSupportedDataTypes = 0;
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* BuildInitialFormats
|
|
*
|
|
* This helper initializes the initial format array
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT CWIAScannerDevice::BuildInitialFormats()
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::BuildInitialFormats");
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if(NULL != m_pInitialFormats) {
|
|
|
|
//
|
|
// Supported data types have already been initialized,
|
|
// so return S_OK.
|
|
//
|
|
|
|
return hr;
|
|
}
|
|
|
|
m_NumInitialFormats = 1;
|
|
m_pInitialFormats = new GUID[m_NumInitialFormats];
|
|
if(m_pInitialFormats){
|
|
m_pInitialFormats[0] = WiaImgFmt_MEMORYBMP;
|
|
} else
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
return hr;
|
|
}
|
|
/**************************************************************************\
|
|
* DeleteInitialFormatsArrayContents
|
|
*
|
|
* This helper deletes the initial format array
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT CWIAScannerDevice::DeleteInitialFormatsArrayContents()
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::DeleteInitialFormatsArrayContents");
|
|
|
|
HRESULT hr = S_OK;
|
|
if(NULL != m_pInitialFormats)
|
|
delete [] m_pInitialFormats;
|
|
|
|
m_pInitialFormats = NULL;
|
|
m_NumInitialFormats = 0;
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* BuildSupportedFormats
|
|
*
|
|
* This helper initializes the supported format array
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT CWIAScannerDevice::BuildSupportedFormats()
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::BuildSupportedFormats");
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if(NULL != m_pSupportedFormats) {
|
|
|
|
//
|
|
// Supported formats have already been initialized,
|
|
// so return S_OK.
|
|
//
|
|
|
|
return hr;
|
|
}
|
|
|
|
LONG lNumFileFormats = 0;
|
|
LONG lNumMemoryFormats = 0;
|
|
GUID *pFileFormats = NULL;
|
|
GUID *pMemoryFormats = NULL;
|
|
|
|
hr = m_pScanAPI->GetSupportedFileFormats(&pFileFormats, &lNumFileFormats);
|
|
if(SUCCEEDED(hr)){
|
|
hr = m_pScanAPI->GetSupportedMemoryFormats(&pMemoryFormats, &lNumMemoryFormats);
|
|
if (SUCCEEDED(hr)) {
|
|
m_NumSupportedFormats = lNumFileFormats + lNumMemoryFormats + 2;
|
|
m_pSupportedFormats = new WIA_FORMAT_INFO[m_NumSupportedFormats];
|
|
LONG lIndex = 0;
|
|
if (m_pSupportedFormats) {
|
|
|
|
// fill out file formats
|
|
m_pSupportedFormats[lIndex].guidFormatID = WiaImgFmt_BMP;
|
|
m_pSupportedFormats[lIndex].lTymed = TYMED_FILE;
|
|
lIndex++;
|
|
for(LONG lSrcIndex = 0;lSrcIndex < lNumFileFormats; lSrcIndex++){
|
|
m_pSupportedFormats[lIndex].guidFormatID = pFileFormats[lSrcIndex];
|
|
m_pSupportedFormats[lIndex].lTymed = TYMED_FILE;
|
|
lIndex ++;
|
|
}
|
|
|
|
//fill out memory formats
|
|
m_pSupportedFormats[lIndex].guidFormatID = WiaImgFmt_MEMORYBMP;
|
|
m_pSupportedFormats[lIndex].lTymed = TYMED_CALLBACK;
|
|
lIndex++;
|
|
for(lSrcIndex = 0;lSrcIndex < lNumMemoryFormats; lSrcIndex++){
|
|
m_pSupportedFormats[lIndex].guidFormatID = pMemoryFormats[lSrcIndex];
|
|
m_pSupportedFormats[lIndex].lTymed = TYMED_CALLBACK;
|
|
lIndex++;
|
|
}
|
|
} else{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
} else if(E_NOTIMPL == hr){
|
|
// do default processing of file formats
|
|
hr = DeleteSupportedFormatsArrayContents();
|
|
if (SUCCEEDED(hr)) {
|
|
m_NumSupportedFormats = 2;
|
|
|
|
m_pSupportedFormats = new WIA_FORMAT_INFO[m_NumSupportedFormats];
|
|
if (m_pSupportedFormats) {
|
|
m_pSupportedFormats[0].guidFormatID = WiaImgFmt_MEMORYBMP;
|
|
m_pSupportedFormats[0].lTymed = TYMED_CALLBACK;
|
|
m_pSupportedFormats[1].guidFormatID = WiaImgFmt_BMP;
|
|
m_pSupportedFormats[1].lTymed = TYMED_FILE;
|
|
} else
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
} else {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildSupportedFormats, GetSupportedFileFormats Failed "));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
/**************************************************************************\
|
|
* DeleteSupportedFormatsArrayContents
|
|
*
|
|
* This helper deletes the supported formats array
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT CWIAScannerDevice::DeleteSupportedFormatsArrayContents()
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::DeleteSupportedFormatsArrayContents");
|
|
|
|
HRESULT hr = S_OK;
|
|
if(NULL != m_pSupportedFormats)
|
|
delete [] m_pSupportedFormats;
|
|
|
|
m_pSupportedFormats = NULL;
|
|
m_NumSupportedFormats = 0;
|
|
return hr;
|
|
}
|
|
/**************************************************************************\
|
|
* BuildSupportedTYMED
|
|
*
|
|
* This helper initializes the supported TYMED array
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT CWIAScannerDevice::BuildSupportedTYMED()
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::BuildSupportedTYMED");
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if(NULL != m_pSupportedTYMED) {
|
|
|
|
//
|
|
// Supported TYMED have already been initialized,
|
|
// so return S_OK.
|
|
//
|
|
|
|
return hr;
|
|
}
|
|
|
|
hr = DeleteSupportedTYMEDArrayContents();
|
|
if (SUCCEEDED(hr)) {
|
|
m_NumSupportedTYMED = 2;
|
|
m_pSupportedTYMED = new LONG[m_NumSupportedTYMED];
|
|
if (m_pSupportedTYMED) {
|
|
m_pSupportedTYMED[0] = TYMED_FILE;
|
|
m_pSupportedTYMED[1] = TYMED_CALLBACK;
|
|
|
|
} else
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
return hr;
|
|
}
|
|
/**************************************************************************\
|
|
* DeleteSupportedTYMEDArrayContents
|
|
*
|
|
* This helper deletes the supported TYMED array
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT CWIAScannerDevice::DeleteSupportedTYMEDArrayContents()
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::DeleteSupportedTYMEDArrayContents");
|
|
|
|
HRESULT hr = S_OK;
|
|
if(NULL != m_pSupportedTYMED)
|
|
delete [] m_pSupportedTYMED;
|
|
|
|
m_pSupportedTYMED = NULL;
|
|
m_NumSupportedTYMED = 0;
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* BuildCapabilities
|
|
*
|
|
* This helper initializes the capabilities array
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT CWIAScannerDevice::BuildCapabilities()
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::BuildCapabilities");
|
|
|
|
HRESULT hr = S_OK;
|
|
if (NULL != m_pCapabilities) {
|
|
|
|
//
|
|
// Capabilities have already been initialized,
|
|
// so return S_OK.
|
|
//
|
|
|
|
return hr;
|
|
}
|
|
|
|
m_NumSupportedCommands = 0;
|
|
m_NumSupportedEvents = 0;
|
|
m_NumCapabilities = 0;
|
|
|
|
WIACAPABILITIES WIACaps;
|
|
memset(&WIACaps,0,sizeof(WIACaps));
|
|
WIACaps.pCapabilities = NULL; // set to NULL, to ask for number of
|
|
// capabilities
|
|
WIACaps.pNumSupportedCommands = &m_NumSupportedCommands;
|
|
WIACaps.pNumSupportedEvents = &m_NumSupportedEvents;
|
|
|
|
//
|
|
// ask for number of capabilities
|
|
//
|
|
|
|
hr = m_pScanAPI->BuildCapabilities(&WIACaps);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
LONG lDriverAddedEvents = m_NumSupportedEvents;
|
|
m_NumSupportedCommands = 1;
|
|
m_NumSupportedEvents = (lDriverAddedEvents + 2); // 2 required events (default events for all devices)
|
|
m_NumCapabilities = (m_NumSupportedCommands + m_NumSupportedEvents);
|
|
|
|
//
|
|
// allocate capabilities array memory
|
|
//
|
|
|
|
m_pCapabilities = new WIA_DEV_CAP_DRV[m_NumCapabilities];
|
|
if (m_pCapabilities) {
|
|
|
|
memset(&WIACaps,0,sizeof(WIACaps));
|
|
WIACaps.pCapabilities = m_pCapabilities;
|
|
WIACaps.pNumSupportedCommands = NULL;
|
|
WIACaps.pNumSupportedEvents = NULL;
|
|
|
|
//
|
|
// get capabilities from micro driver
|
|
//
|
|
|
|
hr = m_pScanAPI->BuildCapabilities(&WIACaps);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
LONG lStartIndex = lDriverAddedEvents;
|
|
|
|
//
|
|
// Initialize EVENTS
|
|
//
|
|
|
|
// WIA_EVENT_DEVICE_CONNECTED
|
|
GetOLESTRResourceString(IDS_EVENT_DEVICE_CONNECTED_NAME,&(m_pCapabilities[lStartIndex].wszName),TRUE);
|
|
GetOLESTRResourceString(IDS_EVENT_DEVICE_CONNECTED_DESC,&(m_pCapabilities[lStartIndex].wszDescription),TRUE);
|
|
m_pCapabilities[lStartIndex].guid = (GUID*)&WIA_EVENT_DEVICE_CONNECTED;
|
|
m_pCapabilities[lStartIndex].ulFlags = WIA_NOTIFICATION_EVENT;
|
|
m_pCapabilities[lStartIndex].wszIcon = WIA_ICON_DEVICE_CONNECTED;
|
|
|
|
lStartIndex++;
|
|
|
|
// WIA_EVENT_DEVICE_DISCONNECTED
|
|
GetOLESTRResourceString(IDS_EVENT_DEVICE_DISCONNECTED_NAME,&(m_pCapabilities[lStartIndex].wszName),TRUE);
|
|
GetOLESTRResourceString(IDS_EVENT_DEVICE_DISCONNECTED_DESC,&(m_pCapabilities[lStartIndex].wszDescription),TRUE);
|
|
m_pCapabilities[lStartIndex].guid = (GUID*)&WIA_EVENT_DEVICE_DISCONNECTED;
|
|
m_pCapabilities[lStartIndex].ulFlags = WIA_NOTIFICATION_EVENT;
|
|
m_pCapabilities[lStartIndex].wszIcon = WIA_ICON_DEVICE_DISCONNECTED;
|
|
|
|
lStartIndex++;
|
|
|
|
//
|
|
// Initialize COMMANDS
|
|
//
|
|
|
|
// WIA_CMD_SYNCHRONIZE
|
|
GetOLESTRResourceString(IDS_CMD_SYNCRONIZE_NAME,&(m_pCapabilities[lStartIndex].wszName),TRUE);
|
|
GetOLESTRResourceString(IDS_CMD_SYNCRONIZE_DESC,&(m_pCapabilities[lStartIndex].wszDescription),TRUE);
|
|
m_pCapabilities[lStartIndex].guid = (GUID*)&WIA_CMD_SYNCHRONIZE;
|
|
m_pCapabilities[lStartIndex].ulFlags = 0;
|
|
m_pCapabilities[lStartIndex].wszIcon = WIA_ICON_SYNCHRONIZE;
|
|
}
|
|
|
|
} else {
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* DeleteCapabilitiesArrayContents
|
|
*
|
|
* This helper deletes the capabilities array
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT CWIAScannerDevice::DeleteCapabilitiesArrayContents()
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::DeleteCapabilitiesArrayContents");
|
|
|
|
HRESULT hr = S_OK;
|
|
if(NULL != m_pCapabilities) {
|
|
for (LONG i = 0; i < m_NumCapabilities;i++) {
|
|
CoTaskMemFree(m_pCapabilities[i].wszName);
|
|
CoTaskMemFree(m_pCapabilities[i].wszDescription);
|
|
}
|
|
delete [] m_pCapabilities;
|
|
|
|
m_pCapabilities = NULL;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* GetBSTRResourceString
|
|
*
|
|
* This helper gets a BSTR from a resource location
|
|
*
|
|
* Arguments:
|
|
*
|
|
* lResourceID - Resource ID of the target BSTR value
|
|
* pBSTR - pointer to a BSTR value (caller must free this string)
|
|
* bLocal - TRUE - for local resources, FALSE - for wiaservc resources
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT CWIAScannerDevice::GetBSTRResourceString(LONG lResourceID,BSTR *pBSTR,BOOL bLocal)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::GetBSTRResourceString");
|
|
|
|
HRESULT hr = S_OK;
|
|
TCHAR szStringValue[255];
|
|
if(bLocal) {
|
|
|
|
//
|
|
// We are looking for a resource in our own private resource file
|
|
//
|
|
|
|
LoadString(g_hInst,lResourceID,szStringValue,255);
|
|
|
|
//
|
|
// NOTE: caller must free this allocated BSTR
|
|
//
|
|
|
|
#ifdef UNICODE
|
|
*pBSTR = SysAllocString(szStringValue);
|
|
#else
|
|
WCHAR wszStringValue[255];
|
|
|
|
//
|
|
// convert szStringValue from char* to unsigned short* (ANSI only)
|
|
//
|
|
|
|
MultiByteToWideChar(CP_ACP,
|
|
MB_PRECOMPOSED,
|
|
szStringValue,
|
|
lstrlenA(szStringValue)+1,
|
|
wszStringValue,
|
|
(sizeof(wszStringValue)/sizeof(WCHAR)));
|
|
|
|
*pBSTR = SysAllocString(wszStringValue);
|
|
#endif
|
|
|
|
} else {
|
|
|
|
//
|
|
// We are looking for a resource in the wiaservc's resource file
|
|
//
|
|
|
|
hr = E_NOTIMPL;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* GetOLESTRResourceString
|
|
*
|
|
* This helper gets a LPOLESTR from a resource location
|
|
*
|
|
* Arguments:
|
|
*
|
|
* lResourceID - Resource ID of the target BSTR value
|
|
* ppsz - pointer to a OLESTR value (caller must free this string)
|
|
* bLocal - TRUE - for local resources, FALSE - for wiaservc resources
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT CWIAScannerDevice::GetOLESTRResourceString(LONG lResourceID,LPOLESTR *ppsz,BOOL bLocal)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWIAScannerDevice::GetOLESTRResourceString");
|
|
|
|
HRESULT hr = S_OK;
|
|
TCHAR szStringValue[255];
|
|
if(bLocal) {
|
|
|
|
//
|
|
// We are looking for a resource in our own private resource file
|
|
//
|
|
|
|
LoadString(g_hInst,lResourceID,szStringValue,255);
|
|
|
|
//
|
|
// NOTE: caller must free this allocated BSTR
|
|
//
|
|
|
|
#ifdef UNICODE
|
|
*ppsz = NULL;
|
|
*ppsz = (LPOLESTR)CoTaskMemAlloc(sizeof(szStringValue));
|
|
if(*ppsz != NULL) {
|
|
wcscpy(*ppsz,szStringValue);
|
|
} else {
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
#else
|
|
WCHAR wszStringValue[255];
|
|
|
|
//
|
|
// convert szStringValue from char* to unsigned short* (ANSI only)
|
|
//
|
|
|
|
MultiByteToWideChar(CP_ACP,
|
|
MB_PRECOMPOSED,
|
|
szStringValue,
|
|
lstrlenA(szStringValue)+1,
|
|
wszStringValue,
|
|
(sizeof(wszStringValue)/sizeof(WCHAR)));
|
|
|
|
*ppsz = NULL;
|
|
*ppsz = (LPOLESTR)CoTaskMemAlloc(sizeof(wszStringValue));
|
|
if(*ppsz != NULL) {
|
|
wcscpy(*ppsz,wszStringValue);
|
|
} else {
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
#endif
|
|
|
|
} else {
|
|
|
|
//
|
|
// We are looking for a resource in the wiaservc's resource file
|
|
//
|
|
|
|
hr = E_NOTIMPL;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* VerticalFlip
|
|
*
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID CWIAScannerDevice::VerticalFlip(
|
|
PMINIDRIVERITEMCONTEXT pDrvItemContext,
|
|
PMINIDRV_TRANSFER_CONTEXT pDataTransferContext)
|
|
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL3,
|
|
"CWIAScannerDevice::VerticalFlip");
|
|
|
|
LONG iHeight = 0;
|
|
LONG iWidth = pDrvItemContext->lBytesPerScanLineRaw;
|
|
ULONG uiDepth = pDrvItemContext->lDepth;
|
|
LONG ScanLineWidth = pDrvItemContext->lBytesPerScanLine;
|
|
BITMAPINFO UNALIGNED *pbmi = NULL;
|
|
PBYTE pImageTop = NULL;
|
|
|
|
//
|
|
// find out if data is TYMED_FILE or TYMED_HGLOBAL
|
|
//
|
|
|
|
if (pDataTransferContext->tymed == TYMED_FILE) {
|
|
pbmi = (PBITMAPINFO)(pDataTransferContext->pTransferBuffer + sizeof(BITMAPFILEHEADER));
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// init memory pointer and height
|
|
//
|
|
|
|
pImageTop = pDataTransferContext->pTransferBuffer + pDataTransferContext->lHeaderSize;
|
|
|
|
#ifdef _64BIT_ALIGNMENT
|
|
BITMAPINFOHEADER UNALIGNED *pbmih = &pbmi->bmiHeader;
|
|
iHeight = pbmih->biHeight;
|
|
#else
|
|
iHeight = pbmi->bmiHeader.biHeight;
|
|
#endif
|
|
|
|
//
|
|
// try to allocate a temp scan line buffer
|
|
//
|
|
|
|
PBYTE pBuffer = (PBYTE)LocalAlloc(LPTR,ScanLineWidth);
|
|
|
|
if (pBuffer != NULL) {
|
|
|
|
LONG index = 0;
|
|
PBYTE pImageBottom = NULL;
|
|
|
|
pImageBottom = pImageTop + (iHeight-1) * ScanLineWidth;
|
|
for (index = 0;index < (iHeight/2);index++) {
|
|
memcpy(pBuffer,pImageTop,ScanLineWidth);
|
|
memcpy(pImageTop,pImageBottom,ScanLineWidth);
|
|
memcpy(pImageBottom,pBuffer,ScanLineWidth);
|
|
pImageTop += ScanLineWidth;
|
|
pImageBottom -= ScanLineWidth;
|
|
}
|
|
|
|
LocalFree(pBuffer);
|
|
} else {
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("VerticalFlip, LocalAlloc failed allocating %d bytes",ScanLineWidth));
|
|
}
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* SwapBuffer24
|
|
*
|
|
* Place RGB bytes in correct order for DIB format.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pBuffer - Pointer to the data buffer.
|
|
* lByteCount - Size of the data in bytes.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 7/18/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID CWIAScannerDevice::SwapBuffer24(PBYTE pBuffer, LONG lByteCount)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL3,
|
|
"CWIAScannerDevice::::SwapBuffer24");
|
|
for (LONG i = 0; i < lByteCount; i+= 3) {
|
|
BYTE bTemp = pBuffer[i];
|
|
pBuffer[i] = pBuffer[i + 2];
|
|
pBuffer[i + 2] = bTemp;
|
|
}
|
|
}
|
|
|