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.
 
 
 
 
 
 

1659 lines
62 KiB

#include "precomp.h"
//
// values that the WIA/TWAIN data source provides for capability negotation
//
TW_UINT16 g_ScannerUnits[] = {TWUN_INCHES,TWUN_PIXELS};
TW_UINT16 g_ScannerBitOrder[] = {TWBO_MSBFIRST};
TW_UINT16 g_ScannerXferMech[] = {TWSX_NATIVE, TWSX_FILE, TWSX_MEMORY};
TW_UINT16 g_ScannerPixelFlavor[] = {TWPF_CHOCOLATE,TWPF_VANILLA};
const TW_UINT32 NUM_SCANNERCAPDATA = 29;
const TW_UINT32 NUM_SCANNERCAPDATA_NO_FEEDER_DETECTED = 26;
CAPDATA SCANNER_CAPDATA[NUM_SCANNERCAPDATA] =
{
//
// Every source must support all five DG_CONTROL / DAT_CAPABILITY operations on:
//
{CAP_XFERCOUNT, TWTY_INT16, TWON_ONEVALUE,
sizeof(TW_INT16), 0, 0, -1, 0, 1, NULL, NULL
},
//
// Every source must support DG_CONTROL / DAT_CAPABILITY, MSG_GET on:
//
{CAP_SUPPORTEDCAPS, TWTY_UINT16, TWON_ARRAY,
sizeof(TW_UINT16), 0, 0, 0, 0, 0, NULL, NULL
},
{CAP_UICONTROLLABLE, TWTY_BOOL, TWON_ONEVALUE,
sizeof(TW_BOOL), TRUE, TRUE, TRUE, TRUE, 0, NULL, NULL
},
//
// Sources that supply image information must support DG_CONTROL / DAT_CAPABILITY /
// MSG_GET, MSG_GETCURRENT, and MSG_GETDEFAULT on:
//
{ICAP_COMPRESSION, TWTY_UINT16, TWON_ENUMERATION,
sizeof(TW_UINT16), 0, 0, 0, 0, 0, NULL, NULL
},
{ICAP_PLANARCHUNKY, TWTY_UINT16, TWON_ONEVALUE,
sizeof(TW_UINT16), TWPC_CHUNKY, TWPC_CHUNKY, TWPC_CHUNKY, TWPC_PLANAR, 0, NULL, NULL
},
{ICAP_PHYSICALHEIGHT, TWTY_FIX32, TWON_ONEVALUE,
sizeof(TW_FIX32), 0, 0, 0, 0, 0, NULL, NULL
},
{ICAP_PHYSICALWIDTH, TWTY_FIX32, TWON_ONEVALUE,
sizeof(TW_FIX32), 0, 0, 0, 0, 0, NULL, NULL
},
{ICAP_PIXELFLAVOR, TWTY_UINT16, TWON_ENUMERATION,
sizeof(TW_UINT16), 0, 0, 0, 1, 0, g_ScannerPixelFlavor, NULL
},
//
// Sources that supply image information must support DG_CONTROL / DAT_CAPABILITY /
// MSG_GET, MSG_GETCURRENT, MSG_GETDEFAULT, MSG_RESET, and MSG_SET on:
//
{ICAP_BITDEPTH, TWTY_UINT16, TWON_ENUMERATION,
sizeof(TW_UINT16), 0, 0, 0, 0, 0, NULL, NULL
},
{ICAP_BITORDER, TWTY_UINT16, TWON_ENUMERATION,
sizeof(TW_UINT16), 0, 0, 0, 0, 0, g_ScannerBitOrder, NULL
},
{ICAP_PIXELTYPE, TWTY_UINT16, TWON_ENUMERATION,
sizeof(TW_UINT16), 0, 0, 0, 0, 0, NULL, NULL
},
{ICAP_UNITS, TWTY_UINT16, TWON_ENUMERATION,
sizeof(TW_UINT16), 0, 0, 0, 1, 0, g_ScannerUnits, NULL
},
{ICAP_XFERMECH, TWTY_UINT16, TWON_ENUMERATION,
sizeof(TW_UINT16), 0, 0, 0, 2, 0, g_ScannerXferMech, NULL
},
{ICAP_XRESOLUTION, TWTY_FIX32, TWON_RANGE,
sizeof(TW_FIX32), 100, 100, 75, 1200, 1, NULL, NULL
},
{ICAP_YRESOLUTION, TWTY_FIX32, TWON_RANGE,
sizeof(TW_FIX32), 100, 100, 75, 1200, 1, NULL, NULL
},
//
// The following capabilities are provided for application compatiblity only.
//
{ICAP_IMAGEFILEFORMAT, TWTY_UINT16, TWON_ENUMERATION,
sizeof(TW_UINT16), 0, 0, 0, 0, 0, NULL, NULL
},
{CAP_INDICATORS, TWTY_BOOL, TWON_ONEVALUE,
sizeof(TW_BOOL), TRUE, TRUE, TRUE, TRUE, 0, NULL, NULL
},
{CAP_ENABLEDSUIONLY, TWTY_BOOL, TWON_ONEVALUE,
sizeof(TW_BOOL), FALSE, FALSE, FALSE, FALSE, 0, NULL, NULL
},
{CAP_DEVICEONLINE, TWTY_BOOL, TWON_ONEVALUE,
sizeof(TW_UINT16), TRUE, TRUE, TRUE, TRUE, 0, NULL, NULL
},
{ICAP_XNATIVERESOLUTION, TWTY_FIX32, TWON_ONEVALUE,
sizeof(TW_FIX32), 0, 0, 0, 0, 0, NULL, NULL
},
{ICAP_YNATIVERESOLUTION, TWTY_FIX32, TWON_ONEVALUE,
sizeof(TW_FIX32), 0, 0, 0, 0, 0, NULL, NULL
},
{ICAP_BRIGHTNESS, TWTY_FIX32, TWON_RANGE,
sizeof(TW_FIX32), 0, 0, -1000, 1000, 1, NULL, NULL
},
{ICAP_CONTRAST, TWTY_FIX32, TWON_RANGE,
sizeof(TW_FIX32), 0, 0, -1000, 1000, 1, NULL, NULL
},
{ICAP_XSCALING, TWTY_FIX32, TWON_RANGE,
sizeof(TW_FIX32), 1, 1, 1, 1, 1, NULL, NULL
},
{ICAP_YSCALING, TWTY_FIX32, TWON_RANGE,
sizeof(TW_FIX32), 1, 1, 1, 1, 1, NULL, NULL
},
{ICAP_THRESHOLD, TWTY_FIX32, TWON_RANGE,
sizeof(TW_FIX32), 128, 128, 0, 255, 1, NULL, NULL
},
//
// All sources must implement the advertised features supplied by their devices.
// The following properties are supplied for TWAIN protocol only, this source
// supports document feeders (if they are detected).
//
{CAP_FEEDERENABLED, TWTY_BOOL, TWON_ONEVALUE,
sizeof(TW_BOOL), FALSE, FALSE, FALSE, TRUE, 0, NULL, NULL
},
{CAP_FEEDERLOADED, TWTY_BOOL, TWON_ONEVALUE,
sizeof(TW_BOOL), FALSE, FALSE, FALSE, TRUE, 0, NULL, NULL
},
{CAP_AUTOFEED, TWTY_BOOL, TWON_ONEVALUE,
sizeof(TW_BOOL), FALSE, FALSE, FALSE, TRUE, 0, NULL, NULL
}
};
TW_UINT16 CWiaScannerDS::OpenDS(PTWAIN_MSG ptwMsg)
{
DBG_FN_DS(CWiaScannerDS::OpenDS());
m_bUnknownPageLength = FALSE;
m_bCacheImage = FALSE;
m_bEnforceUIMode = FALSE;
m_bUnknownPageLengthMultiPageOverRide = FALSE;
if (ReadTwainRegistryDWORDValue(DWORD_REGVALUE_ENABLE_MULTIPAGE_SCROLLFED,
DWORD_REGVALUE_ENABLE_MULTIPAGE_SCROLLFED_ON) == DWORD_REGVALUE_ENABLE_MULTIPAGE_SCROLLFED_ON) {
m_bUnknownPageLengthMultiPageOverRide = TRUE;
}
TW_UINT16 twRc = TWRC_FAILURE;
HRESULT hr = S_OK;
twRc = CWiaDataSrc::OpenDS(ptwMsg);
if (TWRC_SUCCESS != twRc)
return twRc;
BASIC_INFO BasicInfo;
memset(&BasicInfo,0,sizeof(BasicInfo));
BasicInfo.Size = sizeof(BasicInfo);
hr = m_pDevice->GetBasicScannerInfo(&BasicInfo);
if(FAILED(hr)){
DBG_ERR(("CWiaScannerDS::OpenDS(), GetBasicScannerInfo() failed"));
return TWRC_FAILURE;
}
DBG_TRC(("CWiaScannerDS::OpenDS(), Reported Basic Scanner Information from WIA device"));
DBG_TRC(("BasicInfo.Size = %d",BasicInfo.Size));
DBG_TRC(("BasicInfo.xBedSize = %d",BasicInfo.xBedSize));
DBG_TRC(("BasicInfo.yBedSize = %d",BasicInfo.yBedSize));
DBG_TRC(("BasicInfo.xOpticalRes = %d",BasicInfo.xOpticalRes));
DBG_TRC(("BasicInfo.yOpticalRes = %d",BasicInfo.yOpticalRes));
DBG_TRC(("BasicInfo.FeederCaps = %d",BasicInfo.FeederCaps));
//
// Update cap based on information we got
//
CCap * pCap = NULL;
TW_UINT32 Value = 0;
TW_FIX32 fix32;
memset(&fix32,0,sizeof(fix32));
//
// Cache the scanner document handling capability
//
m_FeederCaps = BasicInfo.FeederCaps;
//
// create capability list
//
if(m_FeederCaps > 0){
twRc = CreateCapList(NUM_SCANNERCAPDATA, SCANNER_CAPDATA);
} else {
twRc = CreateCapList(NUM_SCANNERCAPDATA_NO_FEEDER_DETECTED, SCANNER_CAPDATA);
}
if (TWCC_SUCCESS != twRc) {
m_twStatus.ConditionCode = twRc;
return TWRC_FAILURE;
}
if (m_FeederCaps > 0) {
//
// we have a scanner that has feeder capabilities
//
pCap = NULL;
pCap = FindCap(CAP_FEEDERENABLED);
if (pCap) {
DBG_TRC(("Setting feeder enabled to TRUE, because we have a document feeder"));
twRc = pCap->Set(FALSE, FALSE, TRUE, TRUE);
}
pCap = NULL;
pCap = FindCap(CAP_FEEDERLOADED);
if (pCap) {
DBG_TRC(("Setting feeder loaded to TRUE, because we have a document feeder and assume it is loaded"));
twRc = pCap->Set(TRUE, TRUE, TRUE, TRUE);
}
}
//
// Update the cached frame.
//
m_CurFrame.Left.Whole = m_CurFrame.Top.Whole = 0;
m_CurFrame.Left.Frac = m_CurFrame.Top.Frac = 0;
pCap = FindCap(ICAP_XNATIVERESOLUTION);
if (pCap) {
twRc = pCap->Set(BasicInfo.xOpticalRes, BasicInfo.xOpticalRes,
BasicInfo.xOpticalRes, BasicInfo.xOpticalRes);
}
pCap = NULL;
pCap = FindCap(ICAP_YNATIVERESOLUTION);
if (pCap) {
twRc = pCap->Set(BasicInfo.yOpticalRes, BasicInfo.yOpticalRes,
BasicInfo.yOpticalRes, BasicInfo.yOpticalRes);
}
pCap = NULL;
pCap = FindCap(ICAP_PHYSICALHEIGHT);
if (pCap) {
// bed size is in 1000th inches (we default to inches, so calculate the size correctly..)
fix32 = FloatToFix32((FLOAT)(BasicInfo.yBedSize / 1000.00));
memcpy(&Value, &fix32, sizeof(TW_UINT32));
twRc = pCap->Set(Value, Value, Value, Value);
m_CurFrame.Bottom = fix32;
}
pCap = NULL;
pCap = FindCap(ICAP_PHYSICALWIDTH);
if (pCap) {
// bed size is in 1000th inches (we default to inches, so calculate the size correctly..)
fix32 = FloatToFix32((FLOAT)(BasicInfo.xBedSize / 1000.00));
memcpy(&Value, &fix32, sizeof(TW_UINT32));
twRc = pCap->Set(Value, Value, Value, Value);
m_CurFrame.Right = fix32;
}
//
// By TWAIN standard, capability negotiations come before
// data source enabling. For this reason, we have to
// trigger the device have those information ready for us.
//
hr = m_pDevice->AcquireImages(NULL, FALSE);
if (SUCCEEDED(hr)) {
hr = m_pDevice->EnumAcquiredImage(0, &m_pCurrentIWiaItem);
if (SUCCEEDED(hr)) {
twRc = GetCommonSettings();
if(TWRC_SUCCESS == twRc){
twRc = GetSettings();
}
}
}
return twRc;
}
TW_UINT16 CWiaScannerDS::OnImageLayoutMsg(PTWAIN_MSG ptwMsg)
{
DBG_FN_DS(CWiaScannerDS::OnImageLayoutMsg());
TW_UINT16 twRc = TWRC_SUCCESS;
TW_IMAGELAYOUT *pLayout = (TW_IMAGELAYOUT*)ptwMsg->pData;
switch (ptwMsg->MSG) {
case MSG_GET:
case MSG_GETDEFAULT:
case MSG_GETCURRENT:
switch (GetTWAINState()) {
case DS_STATE_7:
m_twStatus.ConditionCode = TWCC_SEQERROR;
twRc = TWRC_FAILURE;
break;
default:
{
GetImageLayout(&m_CurImageLayout);
pLayout->DocumentNumber = m_CurImageLayout.DocumentNumber;
pLayout->PageNumber = m_CurImageLayout.PageNumber;
pLayout->FrameNumber = m_CurImageLayout.FrameNumber;
pLayout->Frame.Top.Whole = m_CurImageLayout.Frame.Top.Whole;
pLayout->Frame.Top.Frac = m_CurImageLayout.Frame.Top.Frac;
pLayout->Frame.Left.Whole = m_CurImageLayout.Frame.Left.Whole;
pLayout->Frame.Left.Frac = m_CurImageLayout.Frame.Left.Frac;
pLayout->Frame.Right.Whole = m_CurImageLayout.Frame.Right.Whole;
pLayout->Frame.Right.Frac = m_CurImageLayout.Frame.Right.Frac;
pLayout->Frame.Bottom.Whole = m_CurImageLayout.Frame.Bottom.Whole;
pLayout->Frame.Bottom.Frac = m_CurImageLayout.Frame.Bottom.Frac;
//pLayout->Frame = m_CurFrame; // BETTER BE IN CORRECT UNITS!!!!
}
break;
}
break;
case MSG_SET:
switch (GetTWAINState()) {
case DS_STATE_5:
case DS_STATE_6:
case DS_STATE_7:
m_twStatus.ConditionCode = TWCC_SEQERROR;
twRc = TWRC_FAILURE;
break;
default:
// do actual MSG_SET here..
{
DBG_TRC(("CWiaScannerDS::OnImageLayoutMsg(), MSG_SET TW_IMAGELAYOUT to set from Application"));
DBG_TRC(("DocumentNumber = %d",pLayout->DocumentNumber));
DBG_TRC(("PageNumber = %d",pLayout->PageNumber));
DBG_TRC(("FrameNumber = %d",pLayout->FrameNumber));
DBG_TRC(("Frame.Top.Whole = %d",pLayout->Frame.Top.Whole));
DBG_TRC(("Frame.Top.Frac = %d",pLayout->Frame.Top.Frac));
DBG_TRC(("Frame.Left.Whole = %d",pLayout->Frame.Left.Whole));
DBG_TRC(("Frame.Left.Frac = %d",pLayout->Frame.Left.Frac));
DBG_TRC(("Frame.Right.Whole = %d",pLayout->Frame.Right.Whole));
DBG_TRC(("Frame.Right.Frac = %d",pLayout->Frame.Right.Frac));
DBG_TRC(("Frame.Bottom.Whole = %d",pLayout->Frame.Bottom.Whole));
DBG_TRC(("Frame.Bottom.Frac = %d",pLayout->Frame.Bottom.Frac));
//
// perform a really rough validation check on FRAME values.
// validate possible incorrect settings by an application.
//
CCap *pXCap = FindCap(ICAP_PHYSICALWIDTH);
TW_INT16 MaxWidthWhole = 8;
if(pXCap){
MaxWidthWhole = (TW_INT16)pXCap->GetCurrent();
}
if(pLayout->Frame.Right.Whole > MaxWidthWhole) {
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_BADVALUE;
DBG_TRC(("Frame.Right.Whole Value (%d) is greater than MAX Right value (%d)",pLayout->Frame.Right.Whole,MaxWidthWhole));
}
CCap *pYCap = FindCap(ICAP_PHYSICALHEIGHT);
TW_INT16 MaxHeightWhole = 11;
if(pYCap){
MaxHeightWhole = (TW_INT16)pYCap->GetCurrent();
}
if(pLayout->Frame.Bottom.Whole > MaxHeightWhole) {
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_BADVALUE;
DBG_TRC(("Frame.Bottom.Whole Value (%d) is greater than MAX Bottom value (%d)",pLayout->Frame.Bottom.Whole,MaxHeightWhole));
}
if (twRc == TWRC_SUCCESS) {
//
// save SET values to ImageLayout member
//
m_CurImageLayout.DocumentNumber = pLayout->DocumentNumber;
m_CurImageLayout.PageNumber = pLayout->PageNumber;
m_CurImageLayout.FrameNumber = pLayout->FrameNumber;
m_CurImageLayout.Frame.Top.Whole = pLayout->Frame.Top.Whole;
m_CurImageLayout.Frame.Top.Frac = pLayout->Frame.Top.Frac;
m_CurImageLayout.Frame.Left.Whole = pLayout->Frame.Left.Whole;
m_CurImageLayout.Frame.Left.Frac = pLayout->Frame.Left.Frac;
m_CurImageLayout.Frame.Right.Whole = pLayout->Frame.Right.Whole;
m_CurImageLayout.Frame.Right.Frac = pLayout->Frame.Right.Frac;
m_CurImageLayout.Frame.Bottom.Whole = pLayout->Frame.Bottom.Whole;
m_CurImageLayout.Frame.Bottom.Frac = pLayout->Frame.Bottom.Frac;
twRc = SetImageLayout(pLayout);
}
}
break;
}
break;
case MSG_RESET:
switch (GetTWAINState()) {
case DS_STATE_5:
case DS_STATE_6:
case DS_STATE_7:
m_twStatus.ConditionCode = TWCC_SEQERROR;
twRc = TWRC_FAILURE;
break;
default:
// do actual MSG_RESET here..
{
#ifdef DEBUG
DBG_TRC(("\n\nMSG_RESET - ImageLayout DocNum = %d, PgNum = %d, FrameNum = %d",
pLayout->DocumentNumber,
pLayout->PageNumber,
pLayout->FrameNumber));
DBG_TRC(("Frame Values\n Top = %d.%d\nLeft = %d.%d\nRight = %d.%d\nBottom = %d.%d",
pLayout->Frame.Top.Whole,
pLayout->Frame.Top.Frac,
pLayout->Frame.Left.Whole,
pLayout->Frame.Left.Frac,
pLayout->Frame.Right.Whole,
pLayout->Frame.Right.Frac,
pLayout->Frame.Bottom.Whole,
pLayout->Frame.Bottom.Frac));
#endif
m_CurImageLayout.Frame.Top.Whole = 0;
m_CurImageLayout.Frame.Top.Frac = 0;
m_CurImageLayout.Frame.Left.Whole = 0;
m_CurImageLayout.Frame.Left.Frac = 0;
m_CurImageLayout.Frame.Right.Whole = 8;
m_CurImageLayout.Frame.Right.Frac = 5;
m_CurImageLayout.Frame.Bottom.Whole = 11;
m_CurImageLayout.Frame.Bottom.Frac = 0;
}
break;
}
break;
default:
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_BADPROTOCOL;
DSError();
break;
}
return twRc;
}
TW_UINT16 CWiaScannerDS::CloseDS(PTWAIN_MSG ptwMsg)
{
DBG_FN_DS(CWiaScannerDS::CloseDS());
DestroyCapList();
return CWiaDataSrc::CloseDS(ptwMsg);
}
TW_UINT16 CWiaScannerDS::EnableDS(TW_USERINTERFACE *pUI)
{
DBG_FN_DS(CWiaScannerDS::EnableDS());
TW_UINT16 twRc = TWRC_FAILURE;
m_bUnknownPageLength = FALSE;
if (DS_STATE_4 == GetTWAINState()) {
HRESULT hr = S_OK;
if(pUI->ShowUI){
DBG_TRC(("CWiaScannerDS::EnableDS(), TWAIN UI MODE"));
m_pDevice->FreeAcquiredImages();
m_pCurrentIWiaItem = NULL;
} else {
DBG_TRC(("CWiaScannerDS::EnableDS(), TWAIN UI-LESS MODE"));
m_pDevice->FreeAcquiredImages();
m_pCurrentIWiaItem = NULL;
}
hr = m_pDevice->AcquireImages(HWND (pUI->ShowUI ? pUI->hParent : NULL),pUI->ShowUI);
if (S_OK == hr) {
twRc = TWRC_SUCCESS;
LONG lNumImages = 0;
m_pDevice->GetNumAcquiredImages(&lNumImages);
if (lNumImages) {
m_NumIWiaItems = (TW_UINT32)lNumImages;
m_pIWiaItems = new (IWiaItem *[m_NumIWiaItems]);
if (m_pIWiaItems) {
hr = m_pDevice->GetAcquiredImageList(lNumImages, m_pIWiaItems, NULL);
if (FAILED(hr)) {
delete [] m_pIWiaItems;
m_pIWiaItems = NULL;
m_NumIWiaItems = 0;
m_NextIWiaItemIndex = 0;
m_twStatus.ConditionCode = TWCC_BUMMER;
twRc = TWRC_FAILURE;
}
} else {
m_NumIWiaItems = 0;
m_twStatus.ConditionCode = TWCC_LOWMEMORY;
twRc = TWRC_FAILURE;
}
}
} else if(S_FALSE == hr) {
return TWRC_CANCEL;
} else {
m_twStatus.ConditionCode = TWCC_OPERATIONERROR;
twRc = TWRC_FAILURE;
}
if (TWRC_SUCCESS == twRc) {
if (m_NumIWiaItems) {
m_pCurrentIWiaItem = m_pIWiaItems[0];
m_NextIWiaItemIndex = 1;
//
// Special case the devices that can acquire with an unknown page length setting.
// WIA devices will be missing the YExtent property, or it will be set to 0.
// TRUE will be returned from IsUnknownPageLengthDevice() if it this functionality
// is supported.
// Since TWAIN does not support unknown page lengths very well, we are required to
// cache the page data, and image settings.
// Note: unknown page length devices will be limited to DIB/BMP data types.
// This will allow the TWAIN compatibility layer to calculate the
// missing image information from the transferred data size.
//
if(IsUnknownPageLengthDevice()){
twRc = TransferToMemory(WiaImgFmt_MEMORYBMP);
if(TWRC_SUCCESS != twRc){
return twRc;
}
m_bUnknownPageLength = TRUE;
m_bCacheImage = TRUE;
}
//
// transition to STATE_5
//
SetTWAINState(DS_STATE_5);
NotifyXferReady();
twRc = TWRC_SUCCESS;
} else {
NotifyCloseReq();
//
// transition to STATE_5
//
SetTWAINState(DS_STATE_5);
twRc = TWRC_SUCCESS;
}
}
}
return twRc;
}
TW_UINT16 CWiaScannerDS::SetCapability(CCap *pCap,TW_CAPABILITY *ptwCap)
{
TW_UINT16 twRc = TWRC_SUCCESS;
//
// Use base class's function for now
//
twRc = CWiaDataSrc::SetCapability(pCap, ptwCap);
if (twRc == TWRC_SUCCESS) {
twRc = CWiaDataSrc::SetCommonSettings(pCap);
if(twRc == TWRC_SUCCESS){
twRc = SetSettings(pCap);
}
}
return twRc;
}
TW_UINT16 CWiaScannerDS::TransferToFile(GUID guidFormatID)
{
TW_UINT16 twRc = TWRC_FAILURE;
CCap *pPendingXfers = FindCap(CAP_XFERCOUNT);
if(pPendingXfers){
if(IsFeederEnabled()){
DBG_TRC(("CWiaScannerDS::TransferToFile(), Scanner device is set to FEEDER mode for transfer"));
pPendingXfers->SetCurrent((TW_UINT32)32767);
} else {
DBG_TRC(("CWiaScannerDS::TransferToFile(), Scanner device is set to FLATBED mode for transfer"));
pPendingXfers->SetCurrent((TW_UINT32)0);
}
}
if (m_bCacheImage) {
m_bCacheImage = FALSE;
//
// acquire a cached image
//
HGLOBAL hDIB = NULL;
twRc = CWiaDataSrc::GetCachedImage(&hDIB);
if(TWRC_SUCCESS == twRc){
//
// cached data is always upside down orientation
// because it was acquired using the TransferToMemory()
// API. Call FlipDIB() to correct the image's orientation
// and to adjust any negative heights that may exist.
//
FlipDIB(hDIB,TRUE);
twRc = WriteDIBToFile(m_FileXferName, hDIB);
GlobalFree(hDIB);
hDIB = NULL;
}
} else {
//
// acquire a real image
//
twRc = CWiaDataSrc::TransferToFile(guidFormatID);
}
return twRc;
}
TW_UINT16 CWiaScannerDS::TransferToDIB(HGLOBAL *phDIB)
{
TW_UINT16 twRc = TWRC_FAILURE;
CCap *pPendingXfers = FindCap(CAP_XFERCOUNT);
if(pPendingXfers){
if(IsFeederEnabled()){
DBG_TRC(("CWiaScannerDS::TransferToDIB(), Scanner device is set to FEEDER mode for transfer"));
pPendingXfers->SetCurrent((TW_UINT32)32767);
} else {
DBG_TRC(("CWiaScannerDS::TransferToDIB(), Scanner device is set to FLATBED mode for transfer"));
pPendingXfers->SetCurrent((TW_UINT32)0);
}
}
if (m_bCacheImage) {
m_bCacheImage = FALSE;
//
// acquire a cached image
//
twRc = CWiaDataSrc::GetCachedImage(phDIB);
if(TWRC_SUCCESS == twRc){
//
// cached data is always upside down orientation
// because it was acquired using the TransferToMemory()
// API. Call FlipDIB() to correct the image's orientation
// and to adjust any negative heights that may exist.
//
FlipDIB(*phDIB,TRUE);
twRc = TWRC_XFERDONE;
}
} else {
//
// acquire a real image
//
twRc = CWiaDataSrc::TransferToDIB(phDIB);
}
return twRc;
}
TW_UINT16 CWiaScannerDS::TransferToMemory(GUID guidFormatID)
{
TW_UINT16 twRc = TWRC_FAILURE;
CCap *pPendingXfers = FindCap(CAP_XFERCOUNT);
if(pPendingXfers){
if(IsFeederEnabled()){
DBG_TRC(("CWiaScannerDS::TransferToMemory(), Scanner device is set to FEEDER mode for transfer"));
pPendingXfers->SetCurrent((TW_UINT32)32767);
} else {
DBG_TRC(("CWiaScannerDS::TransferToMemory(), Scanner device is set to FLATBED mode for transfer"));
pPendingXfers->SetCurrent((TW_UINT32)0);
}
}
if (m_bCacheImage) {
m_bCacheImage = FALSE;
//
// acquire a cached image
//
//
// cached data is already in the correct form to just pass
// back because it was originally acquired using the TransferToMemory()
// API.
//
twRc = CWiaDataSrc::GetCachedImage(&m_hMemXferBits);
if(TWRC_FAILURE == twRc){
DBG_ERR(("CWiaDataSrc::GetCachedImage(), failed to return cached data"));
}
} else {
//
// acquire a real image
//
twRc = CWiaDataSrc::TransferToMemory(guidFormatID);
if(TWRC_FAILURE == twRc){
DBG_ERR(("CWiaDataSrc::TransferToMemory(), failed to return data"));
}
}
return twRc;
}
TW_UINT16 CWiaScannerDS::OnPendingXfersMsg(PTWAIN_MSG ptwMsg)
{
DBG_FN_DS(CWiaScannerDS::OnPendingXfersMsg());
TW_UINT16 twRc = TWRC_SUCCESS;
CCap *pXferCount;
pXferCount = FindCap(CAP_XFERCOUNT);
if (!pXferCount) {
m_twStatus.ConditionCode = TWCC_BUMMER;
return TWRC_FAILURE;
}
twRc = TWRC_SUCCESS;
switch (ptwMsg->MSG) {
case MSG_GET:
switch (GetTWAINState()) {
case DS_STATE_4:
case DS_STATE_5:
case DS_STATE_6:
case DS_STATE_7:
if(m_bUnknownPageLength){
if(m_bUnknownPageLengthMultiPageOverRide){
((TW_PENDINGXFERS *)ptwMsg->pData)->Count = (TW_INT16)pXferCount->GetCurrent();
DBG_TRC(("CWiaScannerDS::OnPendingXfersMsg(), MSG_GET returning %d (unknown page length device detected) MULTI-PAGE enabled",((TW_PENDINGXFERS *)ptwMsg->pData)->Count));
} else {
DBG_WRN(("CWiaScannerDS::OnPendingXfersMsg(), MSG_GET returning 0 (unknown page length device detected)"));
((TW_PENDINGXFERS *)ptwMsg->pData)->Count = 0; // force 1 page only
}
} else {
((TW_PENDINGXFERS *)ptwMsg->pData)->Count = (TW_INT16)pXferCount->GetCurrent();
DBG_TRC(("CWiaScannerDS::OnPendingXfersMsg(), MSG_GET returning %d",((TW_PENDINGXFERS *)ptwMsg->pData)->Count));
}
break;
default:
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_SEQERROR;
DSError();
break;
}
break;
case MSG_ENDXFER:
if (DS_STATE_6 == GetTWAINState() || DS_STATE_7 == GetTWAINState()) {
ResetMemXfer();
TW_INT32 Count = 0;
if (m_bUnknownPageLength) {
if(m_bUnknownPageLengthMultiPageOverRide){
DBG_WRN(("CWiaScannerDS::OnPendingXfersMsg(), MSG_ENDXFER (unknown page length device detected) MULTI-PAGE enabled"));
//
// check to see if we are in FEEDER mode
//
if (IsFeederEnabled()) {
//
// check for documents
//
if (IsFeederEmpty()) {
Count = 0;
} else {
Count = pXferCount->GetCurrent();
}
} else {
//
// we must be in FLATBED mode, so force a single page transfer
//
Count = 0;
}
} else {
DBG_WRN(("CWiaScannerDS::OnPendingXfersMsg(), MSG_ENDXFER returning 0 (unknown page length device detected)"));
Count = 0; // force a single page transfer only
}
} else {
//
// check to see if we are in FEEDER mode
//
if (IsFeederEnabled()) {
//
// check for documents
//
if (IsFeederEmpty()) {
Count = 0;
} else {
Count = pXferCount->GetCurrent();
}
} else {
//
// we must be in FLATBED mode, so force a single page transfer
//
Count = 0;
}
}
if(Count == 32767){
DBG_TRC(("CWiaScannerDS::OnPendingXfersMsg(), MSG_ENDXFER, -1 or (32767) (feeder may have more documents)"));
} else if (Count > 0){
Count--;
} else {
Count = 0;
}
((TW_PENDINGXFERS*)ptwMsg->pData)->Count = (SHORT)Count;
pXferCount->SetCurrent((TW_UINT32)Count);
if (Count == 0) {
DBG_TRC(("CWiaScannerDS::OnPendingXfersMsg(), MSG_ENDXFER, no more pages to transfer"));
//
// Transition to STATE_5
//
SetTWAINState(DS_STATE_5);
NotifyCloseReq();
} else if(Count == 32767){
DBG_TRC(("CWiaScannerDS::OnPendingXfersMsg(), MSG_ENDXFER, more pages to transfer"));
//
// Transition to STATE_6
//
SetTWAINState(DS_STATE_6);
}
} else {
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_SEQERROR;
DSError();
}
break;
case MSG_RESET:
if (DS_STATE_6 == GetTWAINState()) {
//
// Transition to STATE_5
//
SetTWAINState(DS_STATE_5);
((TW_PENDINGXFERS*)ptwMsg->pData)->Count = 0;
ResetMemXfer();
pXferCount->SetCurrent((TW_UINT32)0);
} else {
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_SEQERROR;
DSError();
}
break;
default:
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_BADPROTOCOL;
DSError();
break;
}
return twRc;
}
TW_UINT16 CWiaScannerDS::SetImageLayout(TW_IMAGELAYOUT *pImageLayout)
{
DBG_FN_DS(CWiaScannerDS::SetImageLayout());
HRESULT hr = S_OK;
LONG lXPos = 0;
LONG lYPos = 0;
LONG lXExtent = 0;
LONG lYExtent = 0;
LONG lXRes = 0;
LONG lYRes = 0;
BOOL bCheckStatus = FALSE;
CWiahelper WIA;
hr = WIA.SetIWiaItem(m_pCurrentIWiaItem);
if (FAILED(hr)) {
DBG_ERR(("CWiaScannerDS::SetImageLayout(), failed to set IWiaItem for property reading"));
}
hr = WIA.ReadPropertyLong(WIA_IPS_XPOS,&lXPos);
if(FAILED(hr)){
DBG_ERR(("CWiaScannerDS::SetImageLayout(), failed to read WIA_IPS_XPOS"));
return TWRC_FAILURE;
}
hr = WIA.ReadPropertyLong(WIA_IPS_YPOS,&lYPos);
if(FAILED(hr)){
DBG_ERR(("CWiaScannerDS::SetImageLayout(), failed to read WIA_IPS_YPOS"));
return TWRC_FAILURE;
}
hr = WIA.ReadPropertyLong(WIA_IPS_XEXTENT,&lXExtent);
if(FAILED(hr)){
DBG_ERR(("CWiaScannerDS::SetImageLayout(), failed to read WIA_IPS_XEXTENT"));
return TWRC_FAILURE;
}
hr = WIA.ReadPropertyLong(WIA_IPS_YEXTENT,&lYExtent);
if(FAILED(hr)){
DBG_ERR(("CWiaScannerDS::SetImageLayout(), failed to read WIA_IPS_YEXTENT"));
return TWRC_FAILURE;
}
hr = WIA.ReadPropertyLong(WIA_IPS_XRES,&lXRes);
if(FAILED(hr)){
DBG_ERR(("CWiaScannerDS::SetImageLayout(), failed to read WIA_IPS_XRES"));
return TWRC_FAILURE;
}
hr = WIA.ReadPropertyLong(WIA_IPS_YRES,&lYRes);
if(FAILED(hr)){
DBG_ERR(("CWiaScannerDS::SetImageLayout(), failed to read WIA_IPS_YRES"));
return TWRC_FAILURE;
}
//
// read the current values of the device
//
if (SUCCEEDED(hr)) {
DBG_TRC(("==============================================================================="));
DBG_TRC(("CWiaScannerDS::SetImageLayout(), WIA extents from device at %d dpi(x), %d dpi(y)",lXRes,lYRes));
DBG_TRC(("CWiaScannerDS::SetImageLayout(), Current X Position = %d",lXPos));
DBG_TRC(("CWiaScannerDS::SetImageLayout(), Current Y Position = %d",lYPos));
DBG_TRC(("CWiaScannerDS::SetImageLayout(), Current X Extent = %d",lXExtent));
DBG_TRC(("CWiaScannerDS::SetImageLayout(), Current Y Extent = %d",lYExtent));
DBG_TRC(("==============================================================================="));
DBG_TRC(("CWiaScannerDS::SetImageLayout(),TWAIN extents to convert.."));
DBG_TRC(("CWiaScannerDS::SetImageLayout(),TWAIN X Position = %f",Fix32ToFloat(pImageLayout->Frame.Left)));
DBG_TRC(("CWiaScannerDS::SetImageLayout(),TWAIN Y Position = %f",Fix32ToFloat(pImageLayout->Frame.Top)));
DBG_TRC(("CWiaScannerDS::SetImageLayout(),TWAIN X Extent = %f",Fix32ToFloat(pImageLayout->Frame.Right)));
DBG_TRC(("CWiaScannerDS::SetImageLayout(),TWAIN Y Extent = %f",Fix32ToFloat(pImageLayout->Frame.Bottom)));
DBG_TRC(("==============================================================================="));
lXPos = ConvertFromTWAINUnits(Fix32ToFloat(pImageLayout->Frame.Left),lXRes);
lYPos = ConvertFromTWAINUnits(Fix32ToFloat(pImageLayout->Frame.Top),lYRes);
lXExtent = ConvertFromTWAINUnits(Fix32ToFloat(pImageLayout->Frame.Right),lXRes);
lYExtent = ConvertFromTWAINUnits(Fix32ToFloat(pImageLayout->Frame.Bottom),lYRes);
DBG_TRC(("TWAIN -> WIA extent conversion at %d dpi(x), %d dpi(y)",lXRes,lYRes));
DBG_TRC(("CWiaScannerDS::SetImageLayout(), New X Position = %d",lXPos));
DBG_TRC(("CWiaScannerDS::SetImageLayout(), New Y Position = %d",lYPos));
DBG_TRC(("CWiaScannerDS::SetImageLayout(), New X Extent = %d",lXExtent));
DBG_TRC(("CWiaScannerDS::SetImageLayout(), New Y Extent = %d",lYExtent));
DBG_TRC(("==============================================================================="));
if (!m_bUnknownPageLength) {
//
// note: A failure to write the properties, isn't a large issue here, because
// TWAIN UI-LESS mode expects clipping. They will reread properties
// for application's validation section. All capabilities are validated
// against their valid values, before setting here.
//
//
// Write extents first, because TWAIN expects Height/Width settings to validate
// the new Pos settings.
//
hr = WIA.WritePropertyLong(WIA_IPS_XEXTENT,lXExtent);
if (FAILED(hr)) {
DBG_ERR(("CWiaScannerDS::SetImageLayout(), failed to write WIA_IPS_XEXTENT"));
bCheckStatus = TRUE;
}
hr = WIA.WritePropertyLong(WIA_IPS_YEXTENT,lYExtent);
if (FAILED(hr)) {
DBG_ERR(("CWiaScannerDS::SetImageLayout(), failed to write WIA_IPS_YEXTENT"));
bCheckStatus = TRUE;
}
//
// Write position settings...(top-of-page offsets)
//
hr = WIA.WritePropertyLong(WIA_IPS_XPOS,lXPos);
if (FAILED(hr)) {
DBG_ERR(("CWiaScannerDS::SetImageLayout(), failed to write WIA_IPS_XPOS"));
bCheckStatus = TRUE;
}
hr = WIA.WritePropertyLong(WIA_IPS_YPOS,lYPos);
if (FAILED(hr)) {
DBG_ERR(("CWiaScannerDS::SetImageLayout(), failed to write WIA_IPS_YPOS"));
bCheckStatus = TRUE;
}
if (bCheckStatus) {
DBG_TRC(("CWiaScannerDS::SetImageLayout(), some settings could not be set exactly, so return TWRC_CHECKSTATUS"));
//return TWRC_CHECKSTATUS;
}
} else {
DBG_WRN(("CWiaScannerDS::SetImageLayout(), ImageLayout is does not make since when using a UnknownPageLength Device"));
//return TWRC_CHECKSTATUS;
}
} else {
return TWRC_FAILURE;
}
//
// Always return TWRC_CHECKSTATUS because we may have rounding errors.
// According to the TWAIN spec, a return of TWRC_CHECKSTATUS tells the
// calling application that we successfully set the settings, but there
// may have been some changes (clipping etc.) So the Calling application
// is required to requery for our current settings.
//
//
// call GetImageLayout to update our TWAIN capabilities to match our new WIA settings.
//
GetImageLayout(&m_CurImageLayout);
return TWRC_CHECKSTATUS; //return TWRC_SUCCESS;
}
TW_UINT16 CWiaScannerDS::GetImageLayout(TW_IMAGELAYOUT *pImageLayout)
{
DBG_FN_DS(CWiaScannerDS::GetImageLayout());
HRESULT hr = S_OK;
LONG lXPos = 0;
LONG lYPos = 0;
LONG lXExtent = 0;
LONG lYExtent = 0;
LONG lXRes = 0;
LONG lYRes = 0;
CWiahelper WIA;
hr = WIA.SetIWiaItem(m_pCurrentIWiaItem);
if (FAILED(hr)) {
DBG_ERR(("CWiaScannerDS::GetImageLayout(), failed to set IWiaItem for property reading"));
}
hr = WIA.ReadPropertyLong(WIA_IPS_XPOS,&lXPos);
if(FAILED(hr)){
DBG_ERR(("CWiaScannerDS::GetImageLayout(), failed to read WIA_IPS_XPOS"));
return TWRC_FAILURE;
}
hr = WIA.ReadPropertyLong(WIA_IPS_YPOS,&lYPos);
if(FAILED(hr)){
DBG_ERR(("CWiaScannerDS::GetImageLayout(), failed to read WIA_IPS_YPOS"));
return TWRC_FAILURE;
}
hr = WIA.ReadPropertyLong(WIA_IPS_XEXTENT,&lXExtent);
if(FAILED(hr)){
DBG_ERR(("CWiaScannerDS::GetImageLayout(), failed to read WIA_IPS_XEXTENT"));
return TWRC_FAILURE;
}
hr = WIA.ReadPropertyLong(WIA_IPS_YEXTENT,&lYExtent);
if(FAILED(hr)){
DBG_ERR(("CWiaScannerDS::GetImageLayout(), failed to read WIA_IPS_YEXTENT"));
return TWRC_FAILURE;
}
hr = WIA.ReadPropertyLong(WIA_IPS_XRES,&lXRes);
if(FAILED(hr)){
DBG_ERR(("CWiaScannerDS::GetImageLayout(), failed to read WIA_IPS_XRES"));
return TWRC_FAILURE;
}
hr = WIA.ReadPropertyLong(WIA_IPS_YRES,&lYRes);
if(FAILED(hr)){
DBG_ERR(("CWiaScannerDS::GetImageLayout(), failed to read WIA_IPS_YRES"));
return TWRC_FAILURE;
}
if (SUCCEEDED(hr)) {
if(lXRes <= 0){
DBG_ERR(("CWiaScannerDS::GetImageLayout(), WIA_IPS_XRES returned an invalid value (%d)",lXRes));
return TWRC_FAILURE;
}
if(lYRes <= 0){
DBG_ERR(("CWiaScannerDS::GetImageLayout(), WIA_IPS_YRES returned an invalid value (%d)",lYRes));
return TWRC_FAILURE;
}
pImageLayout->Frame.Top = FloatToFix32((float)((float)lYPos/(float)lYRes));
pImageLayout->Frame.Left = FloatToFix32((float)((float)lXPos/(float)lXRes));
pImageLayout->Frame.Right = FloatToFix32((float)((float)lXExtent/(float)lXRes));
pImageLayout->Frame.Bottom = FloatToFix32((float)((float)lYExtent/(float)lYRes));
} else {
return TWRC_FAILURE;
}
if(m_bUnknownPageLength){
DBG_WRN(("CWiaScannerDS::GetImageLayout(), ImageLayout is does not make since when using a UnknownPageLength Device"));
return TWRC_CHECKSTATUS;
}
return TWRC_SUCCESS;
}
TW_UINT16 CWiaScannerDS::GetResolutions()
{
DBG_FN_DS(CWiaScannerDS::GetResolutions());
HRESULT hr = S_OK;
CWiahelper WIA;
hr = WIA.SetIWiaItem(m_pCurrentIWiaItem);
if (FAILED(hr)) {
DBG_ERR(("CWiaScannerDS::GetResolutions(), failed to set IWiaItem for property reading"));
return TWRC_FAILURE;
}
TW_UINT16 twRc = TWRC_FAILURE;
TW_RANGE twOptionalYRange;
memset(&twOptionalYRange,0,sizeof(twOptionalYRange));
TW_UINT32 *pOptionalYResArray = NULL;
TW_UINT32 OptionalYResNumValues = 0;
BOOL bOptionalYResRange = FALSE;
PROPVARIANT pv;
memset(&pv,0,sizeof(pv));
LONG lAccessFlags = 0;
hr = WIA.ReadPropertyAttributes(WIA_IPS_XRES,&lAccessFlags,&pv);
if (SUCCEEDED(hr)) {
//
// collect valid values for X resolutions
//
CCap *pCap = FindCap(ICAP_XRESOLUTION);
if (pCap) {
if (lAccessFlags & WIA_PROP_RANGE) {
twRc = pCap->Set((TW_UINT32)pv.caul.pElems[WIA_RANGE_NOM],
(TW_UINT32)pv.caul.pElems[WIA_RANGE_NOM],
(TW_UINT32)pv.caul.pElems[WIA_RANGE_MIN],
(TW_UINT32)pv.caul.pElems[WIA_RANGE_MAX],
(TW_UINT32)pv.caul.pElems[WIA_RANGE_STEP]); // range
//
// save X resolution values in RANGE form (just in case the Y
// resolution is WIA_PROP_NONE)
//
twOptionalYRange.ItemType = TWTY_UINT32;
twOptionalYRange.CurrentValue = (TW_UINT32)pv.caul.pElems[WIA_RANGE_NOM];
twOptionalYRange.DefaultValue = (TW_UINT32)pv.caul.pElems[WIA_RANGE_NOM];
twOptionalYRange.MinValue = (TW_UINT32)pv.caul.pElems[WIA_RANGE_MIN];
twOptionalYRange.MaxValue = (TW_UINT32)pv.caul.pElems[WIA_RANGE_MAX];
twOptionalYRange.StepSize = (TW_UINT32)pv.caul.pElems[WIA_RANGE_STEP];
bOptionalYResRange = TRUE;
} else if (lAccessFlags & WIA_PROP_LIST) {
TW_UINT32 *pResArray = new TW_UINT32[WIA_PROP_LIST_COUNT(&pv)];
if (pResArray) {
memset(pResArray,0,(sizeof(TW_UINT32)*WIA_PROP_LIST_COUNT(&pv)));
pOptionalYResArray = new TW_UINT32[WIA_PROP_LIST_COUNT(&pv)];
if (pOptionalYResArray) {
memset(pOptionalYResArray,0,(sizeof(TW_UINT32)*WIA_PROP_LIST_COUNT(&pv)));
for (ULONG i = 0; i < WIA_PROP_LIST_COUNT(&pv);i++) {
pResArray[i] = (TW_UINT32)pv.caul.pElems[i+2];
//
// save the X resolution values in LIST form (just in case the Y
// resolution is WIA_PROP_NONE)
//
pOptionalYResArray[i] = (TW_UINT32)pv.caul.pElems[i+2];
}
//
// save the number of X resolutions saved
//
OptionalYResNumValues = (TW_UINT32)WIA_PROP_LIST_COUNT(&pv);
twRc = pCap->Set(0,0,WIA_PROP_LIST_COUNT(&pv),(BYTE*)pResArray,TRUE); // list
} else {
DBG_ERR(("CWiaScannerDS::GetResolutions(), failed to allocate optional Y Resolution Array Memory"));
twRc = TWRC_FAILURE;
}
delete [] pResArray;
pResArray = NULL;
} else {
DBG_ERR(("CWiaScannerDS::GetResolutions(), failed to allocate X Resolution Array Memory"));
twRc = TWRC_FAILURE;
}
} else if (lAccessFlags & WIA_PROP_NONE) {
//
// we are a "real" WIA_PROP_NONE value
//
LONG lCurrentValue = 0;
hr = WIA.ReadPropertyLong(WIA_IPS_XRES,&lCurrentValue);
if (SUCCEEDED(hr)) {
TW_UINT32 OneValueArray[1];
OneValueArray[0] = (TW_UINT32)lCurrentValue;
twRc = pCap->Set(0,0,1,(BYTE*)OneValueArray,TRUE); // list
} else {
DBG_ERR(("CWiaScannerDS::GetResolutions(), failed to read X Resolution current value"));
twRc = TWRC_FAILURE;
}
}
}
PropVariantClear(&pv);
} else {
DBG_ERR(("CWiaScannerDS::GetResolutions(), failed to read WIA_IPS_XRES attributes"));
twRc = TWRC_FAILURE;
}
if (TWRC_SUCCESS == twRc) {
memset(&pv,0,sizeof(pv));
lAccessFlags = 0;
hr = WIA.ReadPropertyAttributes(WIA_IPS_YRES,&lAccessFlags,&pv);
if (SUCCEEDED(hr)) {
//
// collect valid values for Y resolutions
//
CCap *pCap = FindCap(ICAP_YRESOLUTION);
if (pCap) {
if (lAccessFlags & WIA_PROP_RANGE) {
twRc = pCap->Set((TW_UINT32)pv.caul.pElems[WIA_RANGE_NOM],
(TW_UINT32)pv.caul.pElems[WIA_RANGE_NOM],
(TW_UINT32)pv.caul.pElems[WIA_RANGE_MIN],
(TW_UINT32)pv.caul.pElems[WIA_RANGE_MAX],
(TW_UINT32)pv.caul.pElems[WIA_RANGE_STEP]); // range
} else if (lAccessFlags & WIA_PROP_LIST) {
TW_UINT32 *pResArray = new TW_UINT32[WIA_PROP_LIST_COUNT(&pv)];
if (pResArray) {
memset(pResArray,0,(sizeof(TW_UINT32)*WIA_PROP_LIST_COUNT(&pv)));
for (ULONG i = 0; i < WIA_PROP_LIST_COUNT(&pv);i++) {
pResArray[i] = (TW_UINT32)pv.caul.pElems[i+2];
}
twRc = pCap->Set(0,0,WIA_PROP_LIST_COUNT(&pv),(BYTE*)pResArray,TRUE); // list
delete [] pResArray;
pResArray = NULL;
} else {
DBG_ERR(("CWiaScannerDS::GetResolutions(), failed to allocate Y Resolution Array Memory"));
twRc = TWRC_FAILURE;
}
} else if (lAccessFlags & WIA_PROP_NONE) {
if (pOptionalYResArray) {
//
// if we have an optional array allocated, then X Resolution must be in
// array form, so match it.
//
twRc = pCap->Set(0,0,OptionalYResNumValues,(BYTE*)pOptionalYResArray,TRUE); // list
} else if (bOptionalYResRange) {
//
// if the RANGE flag is set to TRUE, then X Resolution must be in range form, so match it.
//
twRc = pCap->Set(twOptionalYRange.DefaultValue,
twOptionalYRange.CurrentValue,
twOptionalYRange.MinValue,
twOptionalYRange.MaxValue,
twOptionalYRange.StepSize); // range
} else {
//
// we are a "real" WIA_PROP_NONE value
//
LONG lCurrentValue = 0;
hr = WIA.ReadPropertyLong(WIA_IPS_YRES,&lCurrentValue);
if (SUCCEEDED(hr)) {
TW_UINT32 OneValueArray[1];
OneValueArray[0] = (TW_UINT32)lCurrentValue;
twRc = pCap->Set(0,0,1,(BYTE*)OneValueArray,TRUE); // list
} else {
DBG_ERR(("CWiaScannerDS::GetResolutions(), failed to read Y Resolution current value"));
twRc = TWRC_FAILURE;
}
}
}
}
PropVariantClear(&pv);
} else {
DBG_ERR(("CWiaScannerDS::GetResolutions(), failed to read WIA_IPS_YRES attributes"));
twRc = TWRC_FAILURE;
}
}
if (pOptionalYResArray) {
delete [] pOptionalYResArray;
pOptionalYResArray = NULL;
}
return twRc;
}
TW_UINT16 CWiaScannerDS::GetSettings()
{
DBG_FN_DS(CWiaScannerDS::GetSettings());
TW_UINT16 twRc = TWRC_SUCCESS;
twRc = GetImageLayout(&m_CurImageLayout);
if (TWRC_SUCCESS == twRc) {
twRc = GetResolutions();
}
return twRc;
}
TW_UINT16 CWiaScannerDS::SetSettings(CCap *pCap)
{
DBG_FN_DS(CWiaScannerDS::SetSettings());
HRESULT hr = S_OK;
LONG lValue = 0;
CWiahelper WIA;
IWiaItem *pIRootItem = NULL;
hr = WIA.SetIWiaItem(m_pCurrentIWiaItem);
if (FAILED(hr)) {
DBG_ERR(("CWiaScannerDS::SetSettings(), failed to set IWiaItem for property reading"));
}
//
// determine if it is a Capability that the device really needs to know
// about.
//
switch (pCap->GetCapId()) {
case CAP_FEEDERENABLED:
DBG_TRC(("CWiaScannerDS::SetCommonSettings(CAP_FEEDERENABLED)"));
lValue = (LONG)pCap->GetCurrent();
if(lValue){
DBG_TRC(("CWiaScannerDS::SetSettings(), Setting FEEDER mode"));
lValue = FEEDER;
} else {
DBG_TRC(("CWiaScannerDS::SetSettings(), Setting FLATBED mode Enabled"));
lValue = FLATBED;
}
hr = m_pCurrentIWiaItem->GetRootItem(&pIRootItem);
if(S_OK == hr){
hr = WIA.SetIWiaItem(pIRootItem);
if(SUCCEEDED(hr)){
//
// read current document handling select setting
//
LONG lCurrentDocumentHandlingSelect = 0;
hr = WIA.ReadPropertyLong(WIA_DPS_DOCUMENT_HANDLING_SELECT,&lCurrentDocumentHandlingSelect);
if(lValue == FEEDER){
lCurrentDocumentHandlingSelect &= ~FLATBED;
} else {
lCurrentDocumentHandlingSelect &= ~FEEDER;
}
//
// add the intended settings, and write them to the WIA device
//
lValue = lValue | lCurrentDocumentHandlingSelect;
hr = WIA.WritePropertyLong(WIA_DPS_DOCUMENT_HANDLING_SELECT,lValue);
if(SUCCEEDED(hr)){
//
// adjust ICAP_PHYSICALWIDTH and ICAP_PHYSICALHEIGHT
//
LONG lWidth = 0;
LONG lHeight = 0;
TW_UINT32 Value = 0;
CCap* pPhysicalCap = NULL;
TW_FIX32 fix32;
memset(&fix32,0,sizeof(fix32));
if(lValue & FEEDER){
//
// read current horizontal sheet feeder size
//
hr = WIA.ReadPropertyLong(WIA_DPS_HORIZONTAL_SHEET_FEED_SIZE,&lWidth);
} else {
//
// read current horizontal bed size
//
hr = WIA.ReadPropertyLong(WIA_DPS_HORIZONTAL_BED_SIZE,&lWidth);
}
if(SUCCEEDED(hr)){
//
// find the TWAIN capability ICAP_PHYSICALWIDTH
//
pPhysicalCap = FindCap(ICAP_PHYSICALWIDTH);
if(pPhysicalCap){
//
// set the current value, by reading the current setting from
// the WIA property WIA_DPS_HORIZONTAL_SHEET_FEED_SIZE and
// dividing by 1000.0 (because WIA units are in 1/1000th of
// an inch)
//
memset(&fix32,0,sizeof(fix32));
fix32 = FloatToFix32((FLOAT)(lWidth / 1000.00));
memcpy(&Value, &fix32, sizeof(TW_UINT32));
if(TWRC_SUCCESS == pPhysicalCap->Set(Value, Value, Value, Value)){
//
// if setting the new ICAP_PHYSICALWIDTH was successful, continue
// and attempt to set the ICAP_PHYSICALHEIGHT
//
if(lValue & FEEDER){
//
// read current vertical sheet feeder size
//
hr = WIA.ReadPropertyLong(WIA_DPS_VERTICAL_SHEET_FEED_SIZE,&lHeight);
} else {
//
// read current vertical bed size
//
hr = WIA.ReadPropertyLong(WIA_DPS_VERTICAL_BED_SIZE,&lHeight);
}
if (S_OK == hr){
//
// if the setting was successful, continue to attempt to set
// ICAP_PHYSICALHEIGHT setting.
//
pPhysicalCap = FindCap(ICAP_PHYSICALHEIGHT);
if (pPhysicalCap){
//
// set the current value, by reading the current setting from
// the WIA property WIA_DPS_VERTICAL_SHEET_FEED_SIZE and
// dividing by 1000.0 (because WIA units are in 1/1000th of
// an inch)
//
memset(&fix32,0,sizeof(fix32));
fix32 = FloatToFix32((FLOAT)(lHeight / 1000.00));
memcpy(&Value, &fix32, sizeof(TW_UINT32));
if (TWRC_SUCCESS != pPhysicalCap->Set(Value, Value, Value, Value)){
DBG_WRN(("CWiaScannerDS::SetSettings(), could not update TWAIN ICAP_PHYSICALHEIGHT settings"));
}
}
} else {
//
// allow this to pass, because we are either dealing with a "unknown length"
// device and it can not tell us the height, or the driver can not give us this
// value at this time.. (this is OK, because this setting is not fully needed for
// proper data transfers.) Worst case scenerio: The TWAIN compat layer will
// report the same height as the flatbed for the new ICAP_PHYSICALHEIGHT value.
//
hr = S_OK;
}
}
} else {
DBG_ERR(("CWiaScannerDS::SetSettings(), could not find ICAP_PHYSICALHEIGHT capability"));
}
} else {
DBG_ERR(("CWiaScannerDS::SetSettings(), failed to read physical sheet feeder size settings"));
}
}
}
pIRootItem->Release();
}
break;
case ICAP_XRESOLUTION:
DBG_TRC(("CWiaScannerDS::SetCommonSettings(ICAP_XRESOLUTION)"));
lValue = (LONG)pCap->GetCurrent();
DBG_TRC(("CWiaScannerDS::SetSettings(), Setting X Resolution to %d",lValue));
hr = WIA.WritePropertyLong(WIA_IPS_XRES,lValue);
break;
case ICAP_YRESOLUTION:
DBG_TRC(("CWiaScannerDS::SetCommonSettings(ICAP_YRESOLUTION)"));
lValue = (LONG)pCap->GetCurrent();
DBG_TRC(("CWiaScannerDS::SetSettings(), Setting Y Resolution to %d",lValue));
hr = WIA.WritePropertyLong(WIA_IPS_YRES,lValue);
break;
case ICAP_BRIGHTNESS:
DBG_TRC(("CWiaScannerDS::SetCommonSettings(ICAP_BRIGHTNESS)"));
lValue = (LONG)pCap->GetCurrent();
// to do: convert -1000 to 1000 range value in the range specified by the WIA driver
// and set that to lValue.
DBG_TRC(("CWiaScannerDS::SetSettings(), Setting WIA_IPS_BRIGHTNESS to %d",lValue));
break;
case ICAP_CONTRAST:
DBG_TRC(("CWiaScannerDS::SetCommonSettings(ICAP_CONTRAST)"));
lValue = (LONG)pCap->GetCurrent();
// to do: convert -1000 to 1000 range value in the range specified by the WIA driver
// and set that to lValue.
DBG_TRC(("CWiaScannerDS::SetSettings(), Setting WIA_IPS_CONTRAST to %d",lValue));
break;
default:
DBG_TRC(("CWiaScannerDS::SetSettings(), data source is not setting CAPID = %x to WIA device (it is not needed)",pCap->GetCapId()));
break;
}
if (SUCCEEDED(hr)) {
DBG_TRC(("CWiaScannerDS::SetSettings(), Settings were successfully sent to WIA device"));
} else {
DBG_ERR(("CWiaScannerDS::SetSettings(), Settings were unsuccessfully sent to WIA device"));
return TWRC_FAILURE;
}
return TWRC_SUCCESS;
}
BOOL CWiaScannerDS::IsUnknownPageLengthDevice()
{
DBG_FN_DS(CWiaScannerDS::IsUnknownPageLengthDevice());
HRESULT hr = S_OK;
BOOL bIsUnknownPageLengthDevice = FALSE;
CWiahelper WIA;
hr = WIA.SetIWiaItem(m_pCurrentIWiaItem);
if(FAILED(hr)){
DBG_ERR(("CWiaScannerDS::IsUnknownPageLengthDevice(), failed to set IWiaItem for property reading"));
return FALSE;
}
LONG lYExtent = 0;
hr = WIA.ReadPropertyLong(WIA_IPS_YEXTENT,&lYExtent);
if(FAILED(hr)){
DBG_ERR(("CWiaScannerDS::IsUnknownPageLengthDevice(), failed to read WIA_IPS_YEXTENT"));
}
if(SUCCEEDED(hr)){
if(S_FALSE == hr){ // property does not exist, so we have to support this feature
bIsUnknownPageLengthDevice = TRUE;
} else if(S_OK == hr){ // property exists, (need more information, so check the current value)
if(lYExtent == 0){ // property is set to 0, which means unknown page length is supported
bIsUnknownPageLengthDevice = TRUE;
}
}
}
if(bIsUnknownPageLengthDevice){
DBG_TRC(("CWiaScannerDS::IsUnknownPageLengthDevice(), device is set to do unknown page length"));
} else {
DBG_TRC(("CWiaScannerDS::IsUnknownPageLengthDevice(), device is not set to do unknown page length"));
}
return bIsUnknownPageLengthDevice;
}
BOOL CWiaScannerDS::IsFeederEnabled()
{
DBG_FN_DS(CWiaScannerDS::IsFeederEnabled());
HRESULT hr = S_OK;
BOOL bIsFeederEnabled = FALSE;
LONG lDocumentHandlingSelect = 0;
CWiahelper WIA;
IWiaItem *pIRootItem = NULL;
hr = m_pCurrentIWiaItem->GetRootItem(&pIRootItem);
if (SUCCEEDED(hr)) {
if (NULL != pIRootItem) {
hr = WIA.SetIWiaItem(pIRootItem);
if (FAILED(hr)) {
DBG_ERR(("CWiaScannerDS::IsFeederEnabled(), failed to set IWiaItem for property reading"));
}
if (SUCCEEDED(hr)) {
hr = WIA.ReadPropertyLong(WIA_DPS_DOCUMENT_HANDLING_SELECT,&lDocumentHandlingSelect);
if (FAILED(hr)) {
DBG_ERR(("CWiaScannerDS::IsFeederEnabled(), failed to read WIA_DPS_DOCUMENT_HANDLING_SELECT"));
}
if (S_OK == hr) {
if ((lDocumentHandlingSelect & FEEDER) == FEEDER) {
bIsFeederEnabled = TRUE;
}
} else if (S_FALSE == hr) {
DBG_WRN(("CWiaScannerDS::IsFeederEnabled(), WIA_DPS_DOCUMENT_HANDLING_SELECT was not found...defaulting to FLATBED"));
}
}
pIRootItem->Release();
pIRootItem = NULL;
}
} else {
DBG_ERR(("CWiaScannerDS::IsFeederEnabled(), failed to get ROOT IWiaItem from current IWiaItem"));
}
return bIsFeederEnabled;
}
BOOL CWiaScannerDS::IsFeederEmpty()
{
DBG_FN_DS(CWiaScannerDS::IsFeederEmpty());
HRESULT hr = S_OK;
BOOL bIsFeederEmpty = TRUE;
LONG lDocumentHandlingStatus = 0;
CWiahelper WIA;
IWiaItem *pIRootItem = NULL;
hr = m_pCurrentIWiaItem->GetRootItem(&pIRootItem);
if (SUCCEEDED(hr)) {
if (NULL != pIRootItem) {
hr = WIA.SetIWiaItem(pIRootItem);
if (FAILED(hr)) {
DBG_ERR(("CWiaScannerDS::IsFeederEmpty(), failed to set IWiaItem for property reading"));
}
if (SUCCEEDED(hr)) {
hr = WIA.ReadPropertyLong(WIA_DPS_DOCUMENT_HANDLING_STATUS,&lDocumentHandlingStatus);
if (FAILED(hr)) {
DBG_ERR(("CWiaScannerDS::IsFeederEmpty(), failed to read WIA_DPS_DOCUMENT_HANDLING_STATUS"));
}
if (S_OK == hr) {
if (lDocumentHandlingStatus & FEED_READY) {
bIsFeederEmpty = FALSE;
}
} else if (S_FALSE == hr) {
DBG_WRN(("CWiaScannerDS::IsFeederEmpty(), WIA_DPS_DOCUMENT_HANDLING_STATUS was not found"));
}
}
pIRootItem->Release();
pIRootItem = NULL;
}
} else {
DBG_ERR(("CWiaScannerDS::IsFeederEmpty(), failed to get ROOT IWiaItem from current IWiaItem"));
}
return bIsFeederEmpty;
}