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