Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

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;
}
}