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.
 
 
 
 
 
 

3929 lines
148 KiB

#include "precomp.h"
// #define DEBUG_MEMXFER
#define PRIVATE_CAP_ARRAY_PADDING 64 // 64 bytes padding
const TCHAR WIA_STR[] = TEXT("WIA-");
const CHAR* FAMILY_NAME = "Twain Data Source On WIA";
CWiaDataSrc::CWiaDataSrc() :
m_dsState(DS_STATE_0),
m_hMemXferBits(NULL),
m_pMemXferBits(NULL),
m_pDevice(NULL),
m_pIWiaItems(NULL),
m_NumIWiaItems(0),
m_NextIWiaItemIndex(0),
m_NumCaps(0),
m_CapList(NULL),
m_hCachedImageData(NULL),
m_bCacheImage(FALSE)
{
SetTWAINState(DS_STATE_3);
memset(m_FileXferName,0,sizeof(m_FileXferName));
memset(&m_AppIdentity,0,sizeof(m_AppIdentity));
memset(&m_dsIdentity,0, sizeof(m_dsIdentity));
memset(&m_CurFrame, 0,sizeof(m_CurFrame));
memset(&m_CurImageLayout, 0,sizeof(m_CurImageLayout));
memset(&m_MemoryTransferInfo,0,sizeof(m_MemoryTransferInfo));
ResetMemXfer();
m_twStatus.ConditionCode = TWCC_SUCCESS;
m_CurImageLayout.DocumentNumber = 1;
m_CurImageLayout.PageNumber = 1;
m_CurImageLayout.FrameNumber = 1;
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;
m_pCurrentIWiaItem = NULL;
}
CWiaDataSrc::~CWiaDataSrc()
{
ResetMemXfer();
if (m_pDevice){
delete m_pDevice;
m_pDevice = NULL;
}
if (m_pIWiaItems){
delete [] m_pIWiaItems;
m_pIWiaItems = NULL;
}
}
TW_UINT16 CWiaDataSrc::IWiaDataSrc(LPCTSTR DeviceId)
{
if (!DeviceId) {
m_twStatus.ConditionCode = TWCC_BADVALUE;
return TWRC_FAILURE;
}
//
// Initialize m_dsIdentity. This is required because
// DG_CONTROL/DAT_IDENTITY/MSG_GET could be called
// before we are opened.
//
m_pDevice = new CWiaDevice;
if (!m_pDevice) {
m_twStatus.ConditionCode = TWCC_LOWMEMORY;
return TWRC_FAILURE;
}
TCHAR szTempString[MAX_PATH];
memset(szTempString,0,sizeof(szTempString));
HRESULT hr = S_OK;
hr = m_pDevice->Initialize(DeviceId);
if (FAILED(hr)) {
m_twStatus.ConditionCode = TWCC_LOWMEMORY;
delete m_pDevice;
m_pDevice = NULL;
DBG_ERR(("CWiaDataSrc::IWiaDataSrc(), WIA Device object Initialize failed"));
return TWRC_FAILURE;
}
//
// We don't need to attach a callback here because we will
// close the device after we are done with it.
//
if (SUCCEEDED(hr)) {
m_dsIdentity.Id = 0;
m_dsIdentity.Version.MajorNum = 1;
m_dsIdentity.Version.MinorNum = 0;
m_dsIdentity.Version.Language = TWLG_USA;
m_dsIdentity.Version.Country = TWCY_USA;
m_dsIdentity.ProtocolMajor = TWON_PROTOCOLMAJOR;
m_dsIdentity.ProtocolMinor = TWON_PROTOCOLMINOR;
m_dsIdentity.SupportedGroups = DG_CONTROL | DG_IMAGE;
lstrcpyA(m_dsIdentity.Version.Info,"26 June 2000");
//
// Use a specific product family name so that applications
// can differentiate between a data source on WIA and
// a *pure* TWAIN data source
//
lstrcpyA(m_dsIdentity.ProductFamily, FAMILY_NAME);
lstrcpyA(m_dsIdentity.ProductName, "UnknownProduct");
lstrcpyA(m_dsIdentity.Manufacturer, "UnknownMfg");
#ifdef UNICODE
//
// UNICODE specific
//
// This assumes that ProductName, FamilyName and Manufacturer
// are all in TW_STR32 (TWAIN data type for a string).
//
UINT Len = 0;
memset(szTempString,0,sizeof(szTempString));
hr = m_pDevice->GetDeviceDesc(szTempString,sizeof(szTempString),&Len);
if (SUCCEEDED(hr)) {
//
// Add "WIA-" to beginning of ProductName string, to separate
// TWAIN installed data sources, from WIA data sources
//
AddWIAPrefixToString(szTempString,sizeof(szTempString));
Len += lstrlen(WIA_STR); // add prefix size to length
//
// set ProductName in TW_IDENTITY structure
//
WideCharToMultiByte(CP_ACP, 0, szTempString, Len + 1,m_dsIdentity.ProductName,
(sizeof(m_dsIdentity.ProductName)/sizeof(m_dsIdentity.ProductName[0])),NULL, NULL);
Len = 0;
} else {
DBG_ERR(("CWiaDataSrc::IWiaDataSrc(), GetDeviceDesc failed"));
return TWRC_FAILURE;
}
memset(szTempString,0,sizeof(szTempString));
hr = m_pDevice->GetDeviceVendorName(szTempString,sizeof(szTempString),&Len);
if (SUCCEEDED(hr)) {
//
// set Manufacturer in TW_IDENTITY structure
//
WideCharToMultiByte(CP_ACP, 0, szTempString, Len + 1,m_dsIdentity.Manufacturer,
(sizeof(m_dsIdentity.Manufacturer)/sizeof(m_dsIdentity.Manufacturer[0])),NULL, NULL);
} else {
DBG_ERR(("CWiaDataSrc::IWiaDataSrc(), GetDeviceVendorName failed"));
return TWRC_FAILURE;
}
#else
//
// ANSI specific
//
memset(szTempString,0,sizeof(szTempString));
hr = m_pDevice->GetDeviceDesc(szTempString,sizeof(szTempString),NULL);
if (SUCCEEDED(hr) ) {
//
// Add "WIA-" to beginning of ProductName string, to separate
// TWAIN installed data sources, from WIA data sources
//
AddWIAPrefixToString(szTempString,sizeof(szTempString));
//
// set ProductName in TW_IDENTITY structure
//
strncpy(m_dsIdentity.ProductName,szTempString,sizeof(TW_STR32) - 1);
} else {
DBG_ERR(("CWiaDataSrc::IWiaDataSrc(),GetDeviceDesc failed"));
return TWRC_FAILURE;
}
memset(szTempString,0,sizeof(szTempString));
hr = m_pDevice->GetDeviceVendorName(szTempString,sizeof(szTempString),NULL);
if (SUCCEEDED(hr) ) {
//
// set Manufacturer in TW_IDENTITY structure
//
strncpy(m_dsIdentity.Manufacturer,szTempString,sizeof(TW_STR32) - 1);
} else {
DBG_ERR(("CWiaDataSrc::IWiaDataSrc(),GetDeviceVendorName failed"));
}
#endif
}
return(SUCCEEDED(hr)) ? TWRC_SUCCESS : TWRC_FAILURE;
}
TW_UINT16 CWiaDataSrc::AddWIAPrefixToString(LPTSTR szString,UINT uSize)
{
TCHAR szTempBuffer[512];
memset(szTempBuffer,0,sizeof(szTempBuffer));
_sntprintf(szTempBuffer,(sizeof(szTempBuffer)/sizeof(szTempBuffer[0])),TEXT("%s%s"),WIA_STR,szString);
szTempBuffer[(sizeof(szTempBuffer)/sizeof(szTempBuffer[0])) - 1] = 0;
//
// copy, and truncate New string to TWAIN's required
// restricted size.
//
memset(szString,0,uSize);
#ifdef UNICODE
wcsncpy(szString,szTempBuffer,(sizeof(TW_STR32) - 1));
#else
strncpy(szString,szTempBuffer,(sizeof(TW_STR32) - 1));
#endif
return TWRC_SUCCESS;
}
TW_UINT16 CWiaDataSrc::DSEntry(pTW_IDENTITY pOrigin,TW_UINT32 DG,TW_UINT16 DAT,
TW_UINT16 MSG,TW_MEMREF pData)
{
TWAIN_MSG twMsg;
twMsg.AppId = pOrigin;
twMsg.DG = DG;
twMsg.DAT = DAT;
twMsg.MSG = MSG;
twMsg.pData = pData;
TW_UINT16 twRc = TWRC_SUCCESS;
if (MSG_PROCESSEVENT == MSG) {
//
// Since we rely on WIA UI to provide the user interface and since
// the WIA UI is a modal dialog box(meaning it has its own
// messge loop), every event we receive here is not DS event.
//
//((TW_EVENT*)twMsg.pData)->TWMessage = MSG_NULL;
twRc = TWRC_NOTDSEVENT;
} else {
//
// Dispatch message based on group
//
switch (twMsg.DG) {
case DG_CONTROL:
twRc = DispatchControlMsg(&twMsg);
break;
case DG_IMAGE:
twRc = DispatchImageMsg(&twMsg);
break;
default:
m_twStatus.ConditionCode = TWCC_BADPROTOCOL;
twRc = TWRC_FAILURE;
break;
}
DBG_TRC(("Sent to TWAIN Application, DG = %X, DT = %X, MSG = %X, ( TWRC = %X, TWCC = %X)",DG,DAT,MSG,twRc,m_twStatus.ConditionCode));
}
return twRc;
}
#ifdef _USE_NONSPRINTF_CONVERSION
float CWiaDataSrc::Fix32ToFloat(TW_FIX32 fix32)
{
float ffloat = 0.0f;
//
// TWAIN spec implementation
//
ffloat = (float)fix32.Whole + (float)fix32.Frac / 65536.0f;
/*
//
// original implementation
//
int iexp = 1;
int frac = fix32.Frac;
while(frac/10 > 0){
iexp++;
frac = (frac/10);
}
ffloat = (float)fix32.Whole + (float) ( (float) fix32.Frac / (float) pow(10,iexp));
*/
return ffloat;
}
TW_FIX32 CWiaDataSrc::FloatToFix32(float ffloat)
{
TW_FIX32 fix32;
memset(&fix32,0,sizeof(fix32));
//
// TWAIN spec implementation
//
TW_INT32 value = (TW_INT32) (ffloat * 65536.0f + 0.5f);
fix32.Whole = (TW_INT16)(value >> 16);
fix32.Frac = (TW_UINT16)(value & 0x0000ffffL);
/*
//
// original implementation
//
fix32.Whole = (TW_INT16)ffloat;
//float fVal = -((float)fix32.Whole - ffloat);
float fVal = (ffloat - (float)fix32.Whole);
fVal = (fVal * 100000.0f);
fix32.Frac = (TW_UINT16)(fVal);
*/
return fix32;
}
#else // _USE_NONSPRINTF_CONVERSION
TW_FIX32 CWiaDataSrc::FloatToFix32(float f)
{
char fstr[64];
memset(fstr,0,sizeof(fstr));
char *p = NULL;
TW_FIX32 f32;
memset(&f32,0,sizeof(f32));
sprintf(fstr, "%f", f);
p = strchr(fstr, '.');
if (p != NULL) {
*p = '\0';
f32.Whole = (TW_INT16)atoi(fstr);
f32.Frac = (TW_UINT16)atoi(p + 1);
}
return f32;
}
float CWiaDataSrc::Fix32ToFloat(TW_FIX32 fix32)
{
// (full precision)
char fstr[64];
memset(fstr,0,sizeof(fstr));
float fReturnValue = 0.0f;
sprintf(fstr,"%d.%d",fix32.Whole,fix32.Frac);
sscanf(fstr,"%f",&fReturnValue);
// original (loses precision)
// fReturnValue = (float)fix32.Whole + (float)(fix32.Frac / 65536.0);
return fReturnValue;
}
#endif // _USE_NONSPRINTF_CONVERSION
void CWiaDataSrc::NotifyCloseReq()
{
DBG_FN_DS(CWiaDataSrc::NotifyCloseReq());
if(m_DSM.Notify(&m_dsIdentity, &m_AppIdentity,
(TW_UINT32)DG_CONTROL, DAT_NULL,MSG_CLOSEDSREQ, (TW_MEMREF)NULL)){
DBG_TRC(("CWiaDataSrc::NotifyCloseReq(), MSG_CLOSEDSREQ is sent to application"));
} else {
DBG_WRN(("CWiaDataSrc::NotifyCloseReq(), could not notify application for MSG_CLOSEDSREQ"));
}
}
void CWiaDataSrc::NotifyXferReady()
{
DBG_FN_DS(CWiaDataSrc::NotifyXferReady());
if (m_DSM.Notify(&m_dsIdentity,&m_AppIdentity,
(TW_UINT32)DG_CONTROL,DAT_NULL,MSG_XFERREADY,(TW_MEMREF)NULL)) {
DBG_TRC(("CWiaDataSrc::NotifyXferReady(), MSG_XFERREADY is sent to application"));
//
// transition to STATE_6
//
SetTWAINState(DS_STATE_6);
} else {
DBG_WRN(("CWiaDataSrc::NotifyXferReady(), could not notify application for MSG_XFERREADY"));
}
}
void CWiaDataSrc::ResetMemXfer()
{
DBG_FN_DS(CWiaDataSrc::ResetMemXfer());
if (IS_VALID_HANDLE(m_hMemXferBits)) {
if (m_pMemXferBits) {
if (GlobalUnlock(m_hMemXferBits)) {
m_pMemXferBits = NULL;
}
}
// Now free block always
GlobalFree(m_hMemXferBits);
}
m_hMemXferBits = NULL;
m_hCachedImageData = NULL;
m_LinesTransferred = 0;
}
TW_UINT16 CWiaDataSrc::DispatchControlMsg(PTWAIN_MSG ptwMsg)
{
TW_UINT16 twRc = TWRC_SUCCESS;
if (!ptwMsg) {
m_twStatus.ConditionCode = TWCC_BADPROTOCOL;
return TWRC_FAILURE;
}
switch (ptwMsg->DAT) {
case DAT_IDENTITY:
twRc = OnIdentityMsg(ptwMsg);
break;
case DAT_USERINTERFACE:
twRc = OnUserInterfaceMsg(ptwMsg);
break;
case DAT_CAPABILITY:
twRc = OnCapabilityMsg(ptwMsg);
break;
case DAT_STATUS:
twRc = OnStatusMsg(ptwMsg);
break;
case DAT_PENDINGXFERS:
twRc = OnPendingXfersMsg(ptwMsg);
break;
case DAT_SETUPMEMXFER:
twRc = OnSetupMemXferMsg(ptwMsg);
break;
case DAT_SETUPFILEXFER:
twRc = OnSetupFileXferMsg(ptwMsg);
break;
case DAT_XFERGROUP:
twRc = OnXferGroupMsg(ptwMsg);
break;
default:
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_BADPROTOCOL;
}
return twRc;
}
TW_UINT16 CWiaDataSrc::DispatchImageMsg(PTWAIN_MSG ptwMsg)
{
TW_UINT16 twRc = TWRC_SUCCESS;
if (!ptwMsg) {
m_twStatus.ConditionCode = TWCC_BADPROTOCOL;
return TWRC_FAILURE;
}
switch (ptwMsg->DAT) {
case DAT_IMAGEINFO:
twRc = OnImageInfoMsg(ptwMsg);
break;
case DAT_IMAGELAYOUT:
twRc = OnImageLayoutMsg(ptwMsg);
break;
case DAT_IMAGEMEMXFER:
twRc = OnImageMemXferMsg(ptwMsg);
break;
case DAT_IMAGENATIVEXFER:
twRc = OnImageNativeXferMsg(ptwMsg);
break;
case DAT_IMAGEFILEXFER:
twRc = OnImageFileXferMsg(ptwMsg);
break;
case DAT_PALETTE8:
twRc = OnPalette8Msg(ptwMsg);
break;
case DAT_GRAYRESPONSE:
twRc = OnGrayResponseMsg(ptwMsg);
break;
case DAT_RGBRESPONSE:
twRc = OnRGBResponseMsg(ptwMsg);
break;
case DAT_CIECOLOR:
twRc = OnCIEColorMsg(ptwMsg);;
break;
case DAT_JPEGCOMPRESSION:
twRc = OnJPEGCompressionMsg(ptwMsg);
break;
default:
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_BADPROTOCOL;
}
return twRc;
}
TW_UINT16 CWiaDataSrc::OnPalette8Msg(PTWAIN_MSG ptwMsg)
{
DBG_FN_DS(CWiaDataSrc::OnPalette8Msg());
TW_UINT16 twRc = TWRC_SUCCESS;
switch (GetTWAINState()) {
case DS_STATE_4:
case DS_STATE_5:
case DS_STATE_6:
case DS_STATE_7:
switch (ptwMsg->MSG) {
case MSG_GET:
// TWPA_RGB - color palette
// TWPA_GRAY - grayscale palette
// TWPA_CMY - CMY palette
((TW_PALETTE8 *)ptwMsg->pData)->NumColors = 0;
((TW_PALETTE8 *)ptwMsg->pData)->PaletteType = TWPA_RGB;
break;
case MSG_GETDEFAULT:
case MSG_RESET:
case MSG_SET:
break;
default:
m_twStatus.ConditionCode = TWCC_BADPROTOCOL;
twRc = TWRC_FAILURE;
DSError();
}
break;
default:
m_twStatus.ConditionCode = TWCC_SEQERROR;
twRc = TWRC_FAILURE;
DSError();
break;
}
return twRc;
}
TW_UINT16 CWiaDataSrc::OnSetupMemXferMsg(PTWAIN_MSG ptwMsg)
{
DBG_FN_DS(CWiaDataSrc::OnSetupMemXferMsg());
TW_UINT16 twRc = TWRC_SUCCESS;
TW_SETUPMEMXFER *pMemSetup = (TW_SETUPMEMXFER *)ptwMsg->pData;
switch (GetTWAINState()) {
case DS_STATE_4:
case DS_STATE_5:
case DS_STATE_6:
if (MSG_GET == ptwMsg->MSG) {
if (pMemSetup) {
pMemSetup->MinBufSize = MIN_MEMXFER_SIZE;
pMemSetup->MaxBufSize = MAX_MEMXFER_SIZE;
pMemSetup->Preferred = PREFERRED_MEMXFER_SIZE;
} else {
m_twStatus.ConditionCode = TWCC_BADVALUE;
twRc = TWRC_FAILURE;
}
} else {
m_twStatus.ConditionCode = TWCC_BADPROTOCOL;
twRc = TWRC_FAILURE;
DSError();
}
break;
default:
m_twStatus.ConditionCode = TWCC_SEQERROR;
twRc = TWRC_FAILURE;
DSError();
break;
}
return twRc;
}
TW_UINT16 CWiaDataSrc::OnSetupFileXferMsg(PTWAIN_MSG ptwMsg)
{
DBG_FN_DS(CWiaDataSrc::OnSetupFileXferMsg());
TW_UINT16 twRc = TWRC_SUCCESS;
CCap *pImageXferCap = NULL;
TW_SETUPFILEXFER *pFileXfer = NULL;
switch (GetTWAINState()) {
case DS_STATE_4:
case DS_STATE_5:
case DS_STATE_6:
pFileXfer = (TW_SETUPFILEXFER *)ptwMsg->pData;
pImageXferCap = FindCap(ICAP_IMAGEFILEFORMAT);
switch (ptwMsg->MSG) {
case MSG_GET:
case MSG_GETDEFAULT:
case MSG_GETCURRENT:
if (pImageXferCap) {
pFileXfer->Format = (TW_UINT16)pImageXferCap->GetCurrent();
pFileXfer->VRefNum = 0;
pFileXfer->FileName[0] = 0;
strcpy(pFileXfer->FileName, m_FileXferName);
} else {
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_BUMMER;
}
break;
case MSG_SET:
{
strcpy(m_FileXferName, pFileXfer->FileName);
pImageXferCap->SetCurrent((VOID*)&pFileXfer->Format);
}
break;
default:
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_BADPROTOCOL;
DSError();
break;
}
break;
default:
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_SEQERROR;
DSError();
break;
}
return twRc;
}
TW_UINT16 CWiaDataSrc::OnXferGroupMsg(PTWAIN_MSG ptwMsg)
{
DBG_FN_DS(CWiaDataSrc::OnXferGroupMsg());
TW_UINT16 twRc = TWRC_SUCCESS;
switch (GetTWAINState()) {
case DS_STATE_4:
case DS_STATE_5:
case DS_STATE_6:
switch (ptwMsg->MSG) {
case MSG_GET:
case MSG_GETDEFAULT:
case MSG_GETCURRENT:
case MSG_RESET:
*((TW_UINT16 *)ptwMsg->pData) = DG_IMAGE;
break;
case MSG_SET:
break;
default:
m_twStatus.ConditionCode = TWCC_BADPROTOCOL;
twRc = TWRC_FAILURE;
DSError();
break;
}
break;
default:
m_twStatus.ConditionCode = TWCC_SEQERROR;
twRc = TWRC_FAILURE;
DSError();
break;
}
return twRc;
}
TW_UINT16 CWiaDataSrc::OnImageInfoMsg(PTWAIN_MSG ptwMsg)
{
DBG_FN_DS(CWiaDataSrc::OnImageInfoMsg());
TW_UINT16 twRc = TWRC_FAILURE;
TW_IMAGEINFO *ptwImageInfo = NULL;
if (DS_STATE_6 == GetTWAINState()) {
if (MSG_GET == ptwMsg->MSG) {
ptwImageInfo = (TW_IMAGEINFO *)ptwMsg->pData;
HRESULT hr = S_OK;
hr = m_pDevice->GetImageInfo(m_pCurrentIWiaItem, &m_MemoryTransferInfo);
if (SUCCEEDED(hr)) {
ptwImageInfo->ImageWidth = (TW_INT32)m_MemoryTransferInfo.mtiWidthPixels;
ptwImageInfo->ImageLength = (TW_INT32)m_MemoryTransferInfo.mtiHeightPixels;
ptwImageInfo->BitsPerPixel = (TW_INT16)m_MemoryTransferInfo.mtiBitsPerPixel;
ptwImageInfo->SamplesPerPixel = (TW_INT16)m_MemoryTransferInfo.mtiNumChannels;
ptwImageInfo->Planar = (TW_BOOL)m_MemoryTransferInfo.mtiPlanar;
//
// adjust height for unknown length acquisitions
//
if(ptwImageInfo->ImageLength == 0){
DBG_WRN(("CWiaDataSrc::OnImageInfoMsg(), Possible unknown length device detected..checking cached height value"));
ptwImageInfo->ImageLength = m_ImageHeight;
if(ptwImageInfo->ImageLength == 0){
DBG_WRN(("CWiaDataSrc::OnImageInfoMsg(), no cached height available, defaulting to -1 (ICAP_UNDEFINEDIMAGESIZE support only)"));
ptwImageInfo->ImageLength = -1; // unknown page length (only valid if TWAIN applications support ICAP_UNDEFINEDIMAGESIZE)
} else {
DBG_TRC(("CWiaDataSrc::OnImageInfoMsg(), new height = %d",ptwImageInfo->ImageLength));
}
}
//
// set PixelType to corresponding TWAIN pixel type
//
switch(m_MemoryTransferInfo.mtiDataType) {
case WIA_DATA_THRESHOLD:
ptwImageInfo->PixelType = TWPT_BW;
break;
case WIA_DATA_GRAYSCALE:
ptwImageInfo->PixelType = TWPT_GRAY;
break;
case WIA_DATA_COLOR:
default:
ptwImageInfo->PixelType = TWPT_RGB;
break;
}
//
// set compression to NONE
//
ptwImageInfo->Compression = TWCP_NONE;
//
// Unit conversion.......
//
ptwImageInfo->XResolution = FloatToFix32((float)m_MemoryTransferInfo.mtiXResolution);
ptwImageInfo->YResolution = FloatToFix32((float)m_MemoryTransferInfo.mtiYResolution);
twRc = TWRC_SUCCESS;
} else {
m_twStatus.ConditionCode = TWCC_OPERATIONERROR;
twRc = TWRC_FAILURE;
}
if (TWRC_SUCCESS == twRc) {
DBG_TRC(("CWiaDataSrc::OnImageInfoMsg(), Reported Image Information from data source"));
DBG_TRC(("XResolution = %d.%d",ptwImageInfo->XResolution.Whole,ptwImageInfo->XResolution.Frac));
DBG_TRC(("YResolution = %d.%d",ptwImageInfo->YResolution.Whole,ptwImageInfo->YResolution.Frac));
DBG_TRC(("ImageWidth = %d",ptwImageInfo->ImageWidth));
DBG_TRC(("ImageLength = %d",ptwImageInfo->ImageLength));
DBG_TRC(("SamplesPerPixel = %d",ptwImageInfo->SamplesPerPixel));
memset(ptwImageInfo->BitsPerSample,0,sizeof(ptwImageInfo->BitsPerSample));
if (ptwImageInfo->BitsPerPixel < 24) {
ptwImageInfo->BitsPerSample[0] = ptwImageInfo->BitsPerPixel;
} else {
for (int i = 0; i < ptwImageInfo->SamplesPerPixel; i++) {
ptwImageInfo->BitsPerSample[i] = (ptwImageInfo->BitsPerPixel/ptwImageInfo->SamplesPerPixel);
}
}
// (bpp / spp) = bps
DBG_TRC(("BitsPerSample = [%d],[%d],[%d],[%d],[%d],[%d],[%d],[%d]",ptwImageInfo->BitsPerSample[0],
ptwImageInfo->BitsPerSample[1],
ptwImageInfo->BitsPerSample[2],
ptwImageInfo->BitsPerSample[3],
ptwImageInfo->BitsPerSample[4],
ptwImageInfo->BitsPerSample[5],
ptwImageInfo->BitsPerSample[6],
ptwImageInfo->BitsPerSample[7]));
DBG_TRC(("BitsPerPixel = %d",ptwImageInfo->BitsPerPixel));
DBG_TRC(("Planar = %d",ptwImageInfo->Planar));
DBG_TRC(("PixelType = %d",ptwImageInfo->PixelType));
DBG_TRC(("Compression = %d",ptwImageInfo->Compression));
}
} else {
m_twStatus.ConditionCode = TWCC_BADPROTOCOL;
twRc = TWRC_FAILURE;
}
} else {
m_twStatus.ConditionCode = TWCC_SEQERROR;
twRc = TWRC_FAILURE;
}
if (TWRC_SUCCESS != twRc) {
DSError();
}
return twRc;
}
TW_UINT16 CWiaDataSrc::OnImageLayoutMsg(PTWAIN_MSG ptwMsg)
{
m_twStatus.ConditionCode = TWCC_BUMMER;
return TWRC_FAILURE;
}
TW_UINT16 CWiaDataSrc::OnGrayResponseMsg(PTWAIN_MSG ptwMsg)
{
m_twStatus.ConditionCode = TWCC_BUMMER;
return TWRC_FAILURE;
}
TW_UINT16 CWiaDataSrc::OnRGBResponseMsg(PTWAIN_MSG ptwMsg)
{
m_twStatus.ConditionCode = TWCC_BUMMER;
return TWRC_FAILURE;
}
TW_UINT16 CWiaDataSrc::OnCIEColorMsg(PTWAIN_MSG ptwMsg)
{
m_twStatus.ConditionCode = TWCC_BUMMER;
return TWRC_FAILURE;
}
TW_UINT16 CWiaDataSrc::OnJPEGCompressionMsg(PTWAIN_MSG ptwMsg)
{
m_twStatus.ConditionCode = TWCC_BUMMER;
return TWRC_FAILURE;
}
TW_UINT16 CWiaDataSrc::OnIdentityMsg(PTWAIN_MSG ptwMsg)
{
DBG_FN_DS(CWiaDataSrc::OnIdentityMsg());
TW_UINT16 twRc = TWRC_SUCCESS;
if (ptwMsg) {
switch (ptwMsg->MSG) {
case MSG_OPENDS:
#ifdef DEBUG_ME
MessageBox(NULL,TEXT("MSG_OPENDS - Attach me to a debugger"),TEXT("Attach me to a debugger"),MB_OK);
#endif
twRc = OpenDS(ptwMsg);
break;
case MSG_CLOSEDS:
twRc = CloseDS(ptwMsg);
break;
case MSG_GET:
if (!IsBadWritePtr(ptwMsg->pData, sizeof(TW_IDENTITY))) {
*(TW_IDENTITY*)ptwMsg->pData = m_dsIdentity;
DBG_TRC(("CWiaDataSrc::OnIdentityMsg(), Reported TW_IDENTITY from data source"));
DBG_TRC(("Id = %d",m_dsIdentity.Id));
DBG_TRC(("Manufacturer = %s",m_dsIdentity.Manufacturer));
DBG_TRC(("ProductFamily = %s",m_dsIdentity.ProductFamily));
DBG_TRC(("ProductName = %s",m_dsIdentity.ProductName));
DBG_TRC(("ProtocolMajor = %d",m_dsIdentity.ProtocolMajor));
DBG_TRC(("ProtocolMinor = %d",m_dsIdentity.ProtocolMinor));
DBG_TRC(("SupportedGrps = %d",m_dsIdentity.SupportedGroups));
DBG_TRC(("Ver Country = %d",m_dsIdentity.Version.Country));
DBG_TRC(("Ver Info = %s",m_dsIdentity.Version.Info));
DBG_TRC(("Ver Language = %d",m_dsIdentity.Version.Language));
DBG_TRC(("Ver MajorNum = %d",m_dsIdentity.Version.MajorNum));
DBG_TRC(("Ver MinorNum = %d",m_dsIdentity.Version.MinorNum));
twRc = TWRC_SUCCESS;
} else {
twRc = TWCC_BADVALUE;
}
break;
default:
m_twStatus.ConditionCode = TWCC_BADPROTOCOL;
twRc = TWRC_FAILURE;
DSError();
break;
}
}
return twRc;
}
TW_UINT16 CWiaDataSrc::OnUserInterfaceMsg(PTWAIN_MSG ptwMsg)
{
DBG_FN_DS(CWiaDataSrc::OnUserInterfaceMsg());
TW_UINT16 twRc = TWRC_SUCCESS;
switch (ptwMsg->MSG) {
case MSG_ENABLEDS:
switch (GetTWAINState()) {
case DS_STATE_5:
case DS_STATE_6:
case DS_STATE_7:
m_twStatus.ConditionCode = TWCC_SEQERROR;
twRc = TWRC_FAILURE;
break;
default:
twRc = EnableDS((TW_USERINTERFACE*)ptwMsg->pData);
break;
}
break;
case MSG_DISABLEDS:
twRc = DisableDS((TW_USERINTERFACE*)ptwMsg->pData);
break;
default:
m_twStatus.ConditionCode = TWCC_BADPROTOCOL;
twRc = TWRC_FAILURE;
DSError();
break;
}
return twRc;
}
TW_UINT16 CWiaDataSrc::OnCapabilityMsg(PTWAIN_MSG ptwMsg)
{
DBG_FN_DS(CWiaDataSrc::OnCapabilityMsg());
TW_UINT16 twRc = TWRC_SUCCESS;
TW_UINT16 twCC = TWCC_SUCCESS;
TW_CAPABILITY *ptwCap = (TW_CAPABILITY *)ptwMsg->pData;
if (!ptwCap) {
m_twStatus.ConditionCode = TWCC_BADCAP;
return TWRC_FAILURE;
}
if (CAP_SUPPORTEDCAPS == ptwCap->Cap) {
switch(ptwMsg->MSG) {
case MSG_SET:
case MSG_RESET:
{
//
// MSG_SET, MSG_RESET shouldn't be able to be called on CAP_SUPPORTEDCAPS!!
//
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_CAPBADOPERATION;
return twRc;
}
default:
break;
}
//
// get number of PRIVATE TWAIN capabilities from WIA driver
// and add them to our CAP_SUPPORTEDCAPS list.
//
LONG lNumPrivateCaps = 0;
LONG *pPrivateCapArray = NULL;
lNumPrivateCaps = GetPrivateSupportedCapsFromWIADevice(&pPrivateCapArray);
ptwCap->ConType = TWON_ARRAY;
ptwCap->hContainer = GlobalAlloc(GHND, sizeof(TW_ARRAY) + sizeof(TW_UINT16) * (m_NumCaps + lNumPrivateCaps) );
if (ptwCap->hContainer) {
TW_ARRAY *pCapIdArray = (TW_ARRAY *) GlobalLock(ptwCap->hContainer);
if (pCapIdArray) {
TW_UINT32 i = 0;
pCapIdArray->ItemType = TWTY_UINT16;
TW_UINT16 *ItemList;
ItemList = (TW_UINT16 *)pCapIdArray->ItemList;
//
// fill in TWAIN compat layer's supported CAPS first
//
for (i = 0; i < m_NumCaps; i++) {
ItemList[i] = m_CapList[i].GetCapId();
}
//
// fill in WIA driver's private supported CAPS next
//
int PrivateCapIndex = 0;
for(i = m_NumCaps; i < (m_NumCaps + lNumPrivateCaps);i++){
ItemList[i] = (TW_UINT16)pPrivateCapArray[PrivateCapIndex];
DBG_TRC(("(%d) Private Capability ID reported = %x",(PrivateCapIndex + 1), ItemList[i]));
PrivateCapIndex++;
}
//
// finally set NumItems
//
pCapIdArray->NumItems = (m_NumCaps + lNumPrivateCaps);
GlobalUnlock(ptwCap->hContainer);
} else {
GlobalFree(ptwCap->hContainer);
ptwCap->hContainer = NULL;
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_LOWMEMORY;
}
} else {
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_LOWMEMORY;
}
//
// delete Private capability array, if it was allocated
//
if(pPrivateCapArray){
GlobalFree(pPrivateCapArray);
pPrivateCapArray = NULL;
}
return twRc;
}
CCap *pCap = FindCap(ptwCap->Cap);
if (!pCap) {
DBG_TRC(("Couldn't find the CCap object for CAP ID %x in TWAIN Compat layer CAP list, try WIA driver's private TWAIN cap list", ptwCap->Cap));
if (m_pDevice->TwainCapabilityPassThrough()) {
return OnPrivateCapabilityMsg(ptwMsg);
} else {
m_twStatus.ConditionCode = TWCC_BADCAP;
return TWRC_FAILURE;
}
}
switch (ptwMsg->MSG) {
case MSG_GET:
if(ptwCap->Cap == ICAP_IMAGEDATASET)
twCC = pCap->GetCurrent(ptwCap);
else
twCC = pCap->Get(ptwCap);
break;
case MSG_GETDEFAULT:
twCC = pCap->GetDefault(ptwCap);
break;
case MSG_GETCURRENT:
twCC = pCap->GetCurrent(ptwCap);
break;
case MSG_SET:
switch (GetTWAINState()) {
case DS_STATE_7:
twCC = TWCC_SEQERROR;
twRc = TWRC_FAILURE;
break;
default:
twCC = SetCapability(pCap, ptwCap);
break;
}
break;
case MSG_RESET:
switch (GetTWAINState()) {
case DS_STATE_5:
case DS_STATE_6:
case DS_STATE_7:
twCC = TWCC_SEQERROR;
twRc = TWRC_FAILURE;
break;
default:
{
// ptwCap->Cap,
// ptwCap->ConType,
// ptwCap->hContainer);
twCC = pCap->Reset();
//
// According to the TWAIN spec, a MSG_RESET can be sent down meaning more than just
// RESET!!! It is stated that it can mean GET_DEFAULT/CURRENT, and RESET in a single call.
// Applications choose to ignore the value returned if they don't care, But if they
// attempt to read the value as the DEFAULT/CURRENT value...it must be set correctly in the
// container.
//
//
// fill the container with the current value, after the
// RESET call.
//
twCC = pCap->GetCurrent(ptwCap);
// ptwCap->ConType);
}
break;
}
break;
default:
twCC = TWCC_BADPROTOCOL;
DSError();
break;
}
m_twStatus.ConditionCode = twCC;
if (TWCC_SUCCESS != twCC) {
twRc = TWRC_FAILURE;
}
return twRc;
}
TW_UINT16 CWiaDataSrc::OnPrivateCapabilityMsg(PTWAIN_MSG ptwMsg)
{
DBG_FN_DS(CWiaDataSrc::OnPrivateCapabilityMsg());
TW_UINT16 twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_BADCAP;
if (ptwMsg) {
if (ptwMsg->MSG == MSG_SET) {
TW_CAPABILITY *ptwCap = (TW_CAPABILITY *)ptwMsg->pData;
if (ptwCap) {
if ((NULL == ptwCap->hContainer)||(INVALID_HANDLE_VALUE == ptwCap->hContainer)) {
return twRc;
}
}
}
if (m_pCurrentIWiaItem) {
//
// Get the IWiaItemExtras Interface
//
IWiaItemExtras *pIWiaItemExtras = NULL;
HRESULT hr = m_pCurrentIWiaItem->QueryInterface(IID_IWiaItemExtras,(void **)&pIWiaItemExtras);
if (S_OK == hr) {
//
// we have an IWiaItemExtras Interface, so lets talk to the WIA device about
// the capability message
//
TW_CAPABILITY *ptwCap = (TW_CAPABILITY *)ptwMsg->pData;
if (ptwCap) {
//
// Initialize the common header
//
TWAIN_CAPABILITY twCap;
twCap.lSize = sizeof(twCap); // size of TWAIN_CAPABILITY structure
twCap.lMSG = ptwMsg->MSG; // TWAIN message
twCap.lCapID = ptwCap->Cap; // TWAIN capability ID
twCap.lConType = ptwCap->ConType; // TWAIN container type
twCap.lCC = TWCC_BADCAP; // TWAIN return code
twCap.lRC = TWRC_FAILURE; // TWAIN condition code
twCap.lDataSize= 0; // TWAIN capability data size
twCap.Data[0] = 0; // TWAIN capability data (first byte)
DBG_TRC(("== Private TWAIN_CAPABILITY data Header =="));
DBG_TRC(("twCap.lSize = %d", twCap.lSize));
DBG_TRC(("twCap.lMSG = %d", twCap.lMSG));
DBG_TRC(("twCap.lCapID = %x", twCap.lCapID));
DBG_TRC(("twCap.lConType = %d", twCap.lConType));
DBG_TRC(("twCap.lCC = %d", twCap.lCC));
DBG_TRC(("twCap.lRC = %d", twCap.lRC));
DWORD dwInDataSize = 0;
DWORD dwOutDataSize = 0;
DWORD dwContainerSize = 0;
DWORD dwActualOutDataSize = 0;
BYTE *pInData = NULL;
BYTE *pOutData = NULL;
BYTE *pContainerData = NULL;
TWAIN_CAPABILITY *pHeader = NULL;
//
// Depending on the Message type GET ot SET we do different things
//
//
// For a SET or RESET message, we just send the IN buffer, with an OUT buffer
// containing the header.
//
if ((ptwMsg->MSG == MSG_SET) ||
(ptwMsg->MSG == MSG_RESET)) {
dwContainerSize = 0;
if (ptwMsg->MSG == MSG_SET) {
//
// only check container size, when the TWAIN message is a MSG_SET
// MSG_RESET operations do not have containers attached.
//
dwContainerSize = (DWORD)GlobalSize(ptwCap->hContainer);
}
dwInDataSize = dwContainerSize + sizeof(twCap);
dwOutDataSize = sizeof(twCap);
dwActualOutDataSize = dwOutDataSize;
twCap.lDataSize = dwContainerSize;
DBG_TRC(("twCap.lDataSize = %d", twCap.lDataSize));
DBG_TRC(("== Processing MSG_SET or MSG_RESET Capability Message =="));
DBG_TRC(("dwInDataSize = %d",dwInDataSize));
DBG_TRC(("dwOutDataSize = %d",dwOutDataSize));
DBG_TRC(("dwActualOutDataSize = %d",dwActualOutDataSize));
DBG_TRC(("dwContainerSize = %d",dwContainerSize));
//
// allocate IN buffer and write TWAIN_CAPABILITY header
//
if (TWRC_SUCCESS == AllocatePrivateCapBuffer(&twCap,&pInData,dwInDataSize)) {
if (ptwMsg->MSG == MSG_SET) {
//
// copy TWAIN container data to IN buffer
//
if (TWRC_SUCCESS == CopyContainerToPrivateCapBuffer(pInData,ptwCap->hContainer)) {
//
// container data was copied to IN buffer
//
DBG_TRC(("Container data was successfully copied, we are processing a MSG_SET"));
} else {
//
// could not copy TWAIN container data into private capability IN buffer
//
DBG_ERR(("could not copy TWAIN container data into private capability IN buffer"));
if(pInData){
GlobalFree(pInData);
pInData = NULL;
}
return twRc; // return here, becuase we can not continue
}
} else {
//
// no container data needs to be copied
//
DBG_TRC(("No Container data was copied, because we are processing a MSG_RESET"));
}
//
// allocate OUT buffer and write TWAIN_CAPABILITY header
//
if (TWRC_SUCCESS == AllocatePrivateCapBuffer(&twCap,&pOutData,dwOutDataSize)) {
hr = pIWiaItemExtras->Escape(ESC_TWAIN_CAPABILITY,
pInData,
dwInDataSize,
pOutData,
dwOutDataSize,
&dwActualOutDataSize);
if (S_OK == hr) {
pHeader = (TWAIN_CAPABILITY*)pOutData;
DBG_TRC(("== Returned TWAIN_CAPABILITY data Header from WIA device =="));
DBG_TRC(("pHeader->lSize = %d", pHeader->lSize));
DBG_TRC(("pHeader->lMSG = %d", pHeader->lMSG));
DBG_TRC(("pHeader->lCapID = %x", pHeader->lCapID));
DBG_TRC(("pHeader->lConType = %d", pHeader->lConType));
DBG_TRC(("pHeader->lCC = %d", pHeader->lCC));
DBG_TRC(("pHeader->lRC = %d", pHeader->lRC));
DBG_TRC(("pHeader->lDataSize = %d", pHeader->lDataSize));
twRc = (TW_UINT16)pHeader->lRC;
m_twStatus.ConditionCode = (TW_UINT16)pHeader->lCC;
} else {
//
// pIWiaItemExtras->Escape call failed,
// a failure means that we do not respond with a success to the TWAIN application
//
DBG_ERR(("pIWiaItemExtras->Escape Failed"));
DBG_TRC(("Escape(code = %d, pInData = %p, dwInDataSize = %d, pOutData = %p, dwOutDataSize = %d,dwActualOutDataSize = %p)",
ESC_TWAIN_CAPABILITY,
pInData,
dwInDataSize,
pOutData,
dwOutDataSize,
&dwActualOutDataSize));
}
} else {
//
// could not allocate memory for private capability OUT buffer
//
DBG_ERR(("could not allocate memory for private capability OUT buffer"));
}
} else {
//
// could not allocate memory for private capability IN buffer
//
DBG_ERR(("could not allocate memory for private capability IN buffer"));
}
} else if ((ptwMsg->MSG == MSG_GET) ||
(ptwMsg->MSG == MSG_GETCURRENT) ||
(ptwMsg->MSG == MSG_GETDEFAULT)) {
dwContainerSize = 0;
dwInDataSize = sizeof(twCap);
dwOutDataSize = dwInDataSize;
dwActualOutDataSize = dwInDataSize;
twCap.lDataSize = dwContainerSize;
DBG_TRC(("twCap.lDataSize = %d", twCap.lDataSize));
DBG_TRC(("== Processing MSG_GET, MSG_GETCURRENT, or MSG_GETDEFAULT Capability Message =="));
DBG_TRC(("dwInDataSize = %d",dwInDataSize));
DBG_TRC(("dwOutDataSize = %d",dwOutDataSize));
DBG_TRC(("dwActualOutDataSize = %d",dwActualOutDataSize));
DBG_TRC(("dwContainerSize = %d",dwContainerSize));
//
// allocate IN buffer and write TWAIN_CAPABILITY header
//
if (TWRC_SUCCESS == AllocatePrivateCapBuffer(&twCap,&pInData,dwInDataSize)) {
//
// ask the WIA driver how large is the data, so
// we can allocate the proper OUT buffer
//
//
// allocate OUT buffer and write TWAIN_CAPABILITY header
//
if (TWRC_SUCCESS == AllocatePrivateCapBuffer(&twCap,&pOutData,dwOutDataSize)) {
hr = pIWiaItemExtras->Escape(ESC_TWAIN_CAPABILITY,
pInData,
dwInDataSize,
pOutData,
dwOutDataSize,
&dwActualOutDataSize);
if (S_OK == hr) {
//
// make sure that the returned data is large enough to
// contain a proper header.
//
if (dwActualOutDataSize == dwInDataSize) {
pHeader = (TWAIN_CAPABILITY*)pOutData;
DBG_TRC(("== Returned TWAIN_CAPABILITY data Header from WIA device =="));
DBG_TRC(("pHeader->lSize = %d", pHeader->lSize));
DBG_TRC(("pHeader->lMSG = %d", pHeader->lMSG));
DBG_TRC(("pHeader->lCapID = %x", pHeader->lCapID));
DBG_TRC(("pHeader->lConType = %d", pHeader->lConType));
DBG_TRC(("pHeader->lCC = %d", pHeader->lCC));
DBG_TRC(("pHeader->lRC = %d", pHeader->lRC));
DBG_TRC(("pHeader->lDataSize = %d", pHeader->lDataSize));
if (pHeader->lDataSize > 0) {
//
// update common header data size from information returned
// to create OUT buffer header
//
twCap.lDataSize = pHeader->lDataSize;
//
// set new out data size to (data + header) size
//
dwOutDataSize = (pHeader->lDataSize + sizeof(twCap));
//
// update InBuffer header data size from the common header
//
pHeader = (TWAIN_CAPABILITY*)pInData;
pHeader->lDataSize = twCap.lDataSize;
//
// free old out buffer, before allocating new one
//
if (pOutData) {
GlobalFree(pOutData);
pOutData = NULL;
}
//
// allocate OUT buffer and write TWAIN_CAPABILITY header
//
if (TWRC_SUCCESS == AllocatePrivateCapBuffer(&twCap,&pOutData,dwOutDataSize)) {
hr = pIWiaItemExtras->Escape(ESC_TWAIN_CAPABILITY,
pInData,
dwInDataSize,
pOutData,
dwOutDataSize,
&dwActualOutDataSize);
if (S_OK == hr) {
pHeader = (TWAIN_CAPABILITY*)pOutData;
DBG_TRC(("== Returned TWAIN_CAPABILITY data Header from WIA device =="));
DBG_TRC(("pHeader->lSize = %d", pHeader->lSize));
DBG_TRC(("pHeader->lMSG = %d", pHeader->lMSG));
DBG_TRC(("pHeader->lCapID = %x", pHeader->lCapID));
DBG_TRC(("pHeader->lConType = %d", pHeader->lConType));
DBG_TRC(("pHeader->lCC = %d", pHeader->lCC));
DBG_TRC(("pHeader->lRC = %d", pHeader->lRC));
DBG_TRC(("pHeader->lDataSize = %d", pHeader->lDataSize));
twRc = (TW_UINT16)pHeader->lRC;
m_twStatus.ConditionCode = (TW_UINT16)pHeader->lCC;
if (TWRC_SUCCESS == twRc) {
if (TWRC_SUCCESS == CopyPrivateCapBufferToContainer(&ptwCap->hContainer,pOutData,pHeader->lDataSize)) {
ptwCap->ConType = (TW_UINT16)pHeader->lConType;
} else {
//
// could not copy private capability buffer into TWAIN container data
//
DBG_ERR(("could not copy private capability buffer into TWAIN container data"));
}
} else {
//
// WIA driver failed the TWAIN capability request, by returning a TWAIN failure
// return code in the OUT header.
//
DBG_ERR(("WIA driver failed the TWAIN capability request, by returning a TWAIN failure return code in the OUT header."));
}
} else {
//
// pIWiaItemExtras->Escape call failed, (sending passthrough operation)
// a failure means that we do not respond with a success to the TWAIN application
//
DBG_ERR(("pIWiaItemExtras->Escape Failed (sending passthrough operation)"));
DBG_TRC(("Escape(code = %d, pInData = %p, dwInDataSize = %d, pOutData = %p, dwOutDataSize = %d,dwActualOutDataSize = %d)",
ESC_TWAIN_CAPABILITY,
pInData,
dwInDataSize,
pOutData,
dwOutDataSize,
dwActualOutDataSize));
}
} else {
//
// could not allocate memory for private capability OUT buffer
//
DBG_ERR(("could not allocate memory for private capability OUT buffer"));
}
} else {
//
// OUT buffer size returned from the WIA driver is too small to contain a
// proper header.
//
DBG_ERR(("OUT buffer size (%d) returned from the WIA driver is too small to contain data",pHeader->lDataSize));
}
} else {
//
// OUT buffer size returned from the WIA driver is too small to contain a
// proper header.
//
DBG_ERR(("OUT buffer size (%d) returned from the WIA driver is too small to contain a proper header",dwActualOutDataSize));
}
} else {
//
// pIWiaItemExtras->Escape call failed, (requesting OUT buffer size)
// a failure means that we do not respond with a success to the TWAIN application
//
DBG_ERR(("pIWiaItemExtras->Escape Failed (requesting OUT buffer size)"));
DBG_TRC(("Escape(code = %d, pInData = %p, dwInDataSize = %d, pOutData = %p, dwOutDataSize = %d,dwActualOutDataSize = %d)",
ESC_TWAIN_CAPABILITY,
pInData,
dwInDataSize,
pInData,
dwInDataSize,
dwActualOutDataSize));
}
} else {
//
// could not allocate memory for private capability OUT buffer
//
DBG_ERR(("could not allocate memory for private capability OUT buffer"));
}
} else {
//
// could not allocate memory for private capability IN buffer
//
DBG_ERR(("could not allocate memory for private capability IN buffer"));
}
}
//
// free IN buffer
//
if (pInData) {
GlobalFree(pInData);
pInData = NULL;
}
//
// free OUT buffer
//
if (pOutData) {
GlobalFree(pOutData);
pOutData = NULL;
}
} else {
//
// could not get TWAIN capability from TWAIN message
//
DBG_ERR(("could not get TWAIN capability from TWAIN message"));
}
//
// release IWiaItemExtras Interface
//
if (pIWiaItemExtras) {
pIWiaItemExtras->Release();
pIWiaItemExtras = NULL;
}
} else {
//
// QI for IWiaItemExtras Failed
//
DBG_ERR(("QueryInterface for IWiaItemExtras Failed"));
}
} else {
//
// no current item selected
//
DBG_ERR(("no current item selected for use"));
}
} else {
//
// imcoming TWAIN capability is NULL
//
DBG_ERR(("incoming TWAIN capability is NULL"));
}
return twRc;
}
TW_UINT16 CWiaDataSrc::AllocatePrivateCapBuffer(TWAIN_CAPABILITY *pHeader, BYTE** ppBuffer, DWORD dwSize)
{
DBG_FN_DS(CWiaDataSrc::AllocatePrivateCapBuffer());
if(dwSize < sizeof(TWAIN_CAPABILITY) || (!ppBuffer)|| (!pHeader)){
return TWRC_FAILURE;
}
*ppBuffer = (BYTE*)GlobalAlloc(GPTR,dwSize);
if(*ppBuffer){
memcpy(*ppBuffer, pHeader,sizeof(TWAIN_CAPABILITY));
} else {
return TWRC_FAILURE;
}
return TWRC_SUCCESS;
}
TW_UINT16 CWiaDataSrc::CopyContainerToPrivateCapBuffer(BYTE* pBuffer, HGLOBAL hContainer)
{
DBG_FN_DS(CWiaDataSrc::CopyContainerToPrivateCapBuffer());
if((!pBuffer)||(!hContainer)){
return TWRC_FAILURE;
}
DWORD dwContainerSize = (DWORD)GlobalSize(hContainer);
BYTE *pContainerBuffer = (BYTE*)GlobalLock(hContainer);
if(!pContainerBuffer){
return TWRC_FAILURE;
}
TWAIN_CAPABILITY *pHeader = (TWAIN_CAPABILITY*)pBuffer;
memcpy((BYTE*)pHeader->Data,pContainerBuffer,dwContainerSize);
//
// unlock handle before returning
//
GlobalUnlock(hContainer);
return TWRC_SUCCESS;
}
TW_UINT16 CWiaDataSrc::CopyPrivateCapBufferToContainer(HGLOBAL *phContainer, BYTE* pBuffer, DWORD dwSize)
{
DBG_FN_DS(CWiaDataSrc::CopyPrivateCapBufferToContainer());
if((!phContainer) || (!pBuffer) || (dwSize <= 0)){
return TWRC_FAILURE;
}
*phContainer = NULL;
*phContainer = (HGLOBAL)GlobalAlloc(GHND,dwSize);
if(!*phContainer){
return TWRC_FAILURE;
}
BYTE *pContainerBuffer = (BYTE*)GlobalLock(*phContainer);
if(!pContainerBuffer){
GlobalFree(*phContainer);
*phContainer = NULL;
return TWRC_FAILURE;
}
TWAIN_CAPABILITY *pHeader = (TWAIN_CAPABILITY*)pBuffer;
memcpy(pContainerBuffer,(BYTE*)pHeader->Data,dwSize);
//
// unlock handle before returning
//
GlobalUnlock(*phContainer);
return TWRC_SUCCESS;
}
TW_UINT16 CWiaDataSrc::SetCapability(CCap *pCap,TW_CAPABILITY *ptwCap)
{
DBG_FN_DS(CWiaDataSrc::SetCapability());
if (!pCap || !ptwCap) {
m_twStatus.ConditionCode = TWCC_BADCAP;
return TWRC_FAILURE;
}
return pCap->Set(ptwCap);
}
TW_UINT16 CWiaDataSrc::OnStatusMsg(PTWAIN_MSG ptwMsg)
{
DBG_FN_DS(CWiaDataSrc::OnStatusMsg());
TW_UINT16 twRc = TWRC_SUCCESS;
if (MSG_GET == ptwMsg->MSG) {
*((TW_STATUS*)ptwMsg->pData) = m_twStatus;
twRc = TWRC_SUCCESS;
} else {
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_BADPROTOCOL;
DSError();
}
return twRc;
}
TW_UINT16 CWiaDataSrc::OnPendingXfersMsg(PTWAIN_MSG ptwMsg)
{
m_twStatus.ConditionCode = TWCC_BUMMER;
return TWRC_FAILURE;
}
TW_UINT16 CWiaDataSrc::OnImageMemXferMsg(PTWAIN_MSG ptwMsg)
{
DBG_FN_DS(CWiaDataSrc::OnImageMemXferMsg());
TW_UINT16 twRc = TWRC_SUCCESS;
HRESULT hr = E_FAIL;
switch (GetTWAINState()) {
case DS_STATE_6:
case DS_STATE_7:
{
if (MSG_GET == ptwMsg->MSG) {
TW_IMAGEMEMXFER *pMemXfer = (TW_IMAGEMEMXFER *)ptwMsg->pData;
if ((m_hMemXferBits == NULL)) {
m_LinesTransferred = 0;
GUID guidFormat = GUID_NULL;
DBG_WRN(("Transferring %d bit data",m_MemoryTransferInfo.mtiBitsPerPixel));
if (m_MemoryTransferInfo.mtiBitsPerPixel > 32) {
//
// Load image into memory for memory transfer (hi-color images)
//
guidFormat = WiaImgFmt_RAWRGB;
} else {
//
// The TWAIN compatibility layer has the ability to transfer images
// 1,2,4,8,16,24 and 32 bit when using MEMORYBMP.
//
guidFormat = WiaImgFmt_MEMORYBMP;
}
twRc = TransferToMemory(guidFormat);
if (TWRC_SUCCESS != twRc) {
return twRc;
} else {
//
// transition to STATE_7
//
SetTWAINState(DS_STATE_7);
}
}
//
// turn off the Image caching flag
//
m_bCacheImage = FALSE;
//
// Lock down the memory and get the address to the bits
//
GetMemoryTransferBits((BYTE*)GlobalLock(m_hMemXferBits));
m_pMemXferBits = m_MemoryTransferInfo.mtipBits;
if (m_pMemXferBits) {
if(m_MemoryTransferInfo.mtiHeightPixels == 0){
m_MemoryTransferInfo.mtiHeightPixels = m_ImageHeight;
}
if(m_MemoryTransferInfo.mtiguidFormat == WiaImgFmt_MEMORYBMP){
//
// adjust the image information to report the actual information
// reported in the BITMAPINFO header.
//
//
// only change these values, if the current information does not
// match the image header. (always take the header's values)
//
if(m_MemoryTransferInfo.mtiHeightPixels != m_ImageHeight){
m_MemoryTransferInfo.mtiHeightPixels = m_ImageHeight;
}
if(m_MemoryTransferInfo.mtiWidthPixels != m_ImageWidth){
m_MemoryTransferInfo.mtiWidthPixels = m_ImageWidth;
}
}
DBG_TRC(("CWiaDataSrc::OnImageMemXferMsg(), Transferring (%d) of (%d) total lines of image data.",m_LinesTransferred,m_MemoryTransferInfo.mtiHeightPixels));
if (m_LinesTransferred >= (TW_UINT32)m_MemoryTransferInfo.mtiHeightPixels) {
//
// we have completed the transfer, or we are out
// of scan lines to copy..so return XFERDONE
//
//
// unlock memory before bailing
//
// Keep unlock and NULLing together
GlobalUnlock(m_hMemXferBits);
m_pMemXferBits = NULL;
ResetMemXfer();
m_twStatus.ConditionCode = TWCC_SUCCESS;
return TWRC_XFERDONE;
} else {
//
// looks like we are working with transfer data
//
BYTE * pAppBuffer = NULL;
if (pMemXfer->Memory.Flags & TWMF_HANDLE) {
DBG_TRC(("TWAIN Application wants to work with a HANDLE"));
//
// if the memory is a HANDLE, lock it first
//
pAppBuffer = (LPBYTE)GlobalLock(pMemXfer->Memory.TheMem);
} else if (pMemXfer->Memory.Flags & TWMF_POINTER) {
DBG_TRC(("TWAIN Application wants to work with a POINTER"));
//
// if the memory is a POINTER, then proceed
//
pAppBuffer = (LPBYTE)pMemXfer->Memory.TheMem;
} else {
DBG_TRC(("TWAIN Application gave us nothing to work with"));
//
// we have no memory, so set it to NULL
//
pAppBuffer = NULL;
}
//
// if (there is no Memory to write to), or
// (the app doesn't own the memory), or
// (the length is less than MIN_ ), or
// (the length is greater than MAX),
// return a FAILURE!, and a CC of BADVALUE
//
if (!pAppBuffer ||
!(pMemXfer->Memory.Flags & TWMF_APPOWNS) ||
pMemXfer->Memory.Length < MIN_MEMXFER_SIZE ||
pMemXfer->Memory.Length > MAX_MEMXFER_SIZE) {
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_BADVALUE;
} else {
//
// set memory Xfer values
//
UINT ScanlinesToCopy = 0;
pMemXfer->BytesPerRow = GetLineSize(&m_MemoryTransferInfo);
ScanlinesToCopy = min(pMemXfer->Memory.Length / pMemXfer->BytesPerRow,
(TW_UINT32)(m_MemoryTransferInfo.mtiHeightPixels - m_LinesTransferred));
pMemXfer->Compression = TWCP_NONE;
pMemXfer->Columns = m_MemoryTransferInfo.mtiWidthPixels;
pMemXfer->Rows = ScanlinesToCopy;
pMemXfer->XOffset = 0;
pMemXfer->YOffset = m_LinesTransferred;
pMemXfer->BytesWritten = pMemXfer->BytesPerRow * ScanlinesToCopy;
#ifdef DEBUG_MEMXFER
DBG_TRC(("CWiaDataSrc::OnImageMemXferMsg(), Reports TW_IMAGEMEMXFER"));
DBG_TRC(("pMemXfer->Compression = %d",pMemXfer->Compression));
DBG_TRC(("pMemXfer->Columns = %d",pMemXfer->Columns));
DBG_TRC(("pMemXfer->Rows = %d",pMemXfer->Rows));
DBG_TRC(("pMemXfer->XOffset = %d",pMemXfer->XOffset));
DBG_TRC(("pMemXfer->YOffset = %d",pMemXfer->YOffset));
DBG_TRC(("pMemXfer->BytesPerRow = %d",pMemXfer->BytesPerRow));
DBG_TRC(("pMemXfer->BytesWritten = %d",pMemXfer->BytesWritten));
DBG_TRC(("pAppBuffer = %p, m_pMemXferBits = %p",pAppBuffer,m_pMemXferBits));
#endif
//
// Transfer one-line strips in a loop to Application supplied buffer
//
LPBYTE pTo = pAppBuffer;
LPBYTE pFrom = m_pMemXferBits + m_LinesTransferred * GetLineSize(&m_MemoryTransferInfo);
for (UINT i=0;i < ScanlinesToCopy;i++ ) {
//
// swap color values, if needed
//
if (m_MemoryTransferInfo.mtiBitsPerPixel == 24) {
for (ULONG ulIndex = 0; ulIndex < pMemXfer->BytesPerRow; ulIndex+= 3) {
// 1 2 3
// RED-GREEN-BLUE
//
BYTE bFirst = pFrom[ulIndex];
pFrom[ulIndex] = pFrom[ulIndex+2];
pFrom[ulIndex+2] = bFirst;
}
}
/*
if(m_MemoryTransferInfo.mtiBitsPerPixel == 48){
for(j = 0; j < pMemXfer->BytesPerRow; j+=6){
// 1 2 1 2 1 2
// REDRED-GREENGREEN-BLUEBLUE
//
BYTE bFirst = pFrom[j];
BYTE bSecond = pFrom[j+1];
pFrom[j] = pFrom[j+4];
pFrom[j+1] = pFrom[j+5];
pFrom[j+4] = bFirst;
pFrom[j+5] = bSecond;
}
}
*/
//
// copy line to application supplied buffer
//
memcpy(pTo,pFrom,pMemXfer->BytesPerRow);
pFrom+=GetLineSize(&m_MemoryTransferInfo);
pTo+=pMemXfer->BytesPerRow;
}
//
// calculate lines transferred
//
m_LinesTransferred += ScanlinesToCopy;
if (m_LinesTransferred >= (TW_UINT32)m_MemoryTransferInfo.mtiHeightPixels) {
//
// we have completed the transfer, or we are out
// of scan lines to copy..so return XFERDONE
//
twRc = TWRC_XFERDONE;
m_twStatus.ConditionCode = TWCC_SUCCESS;
// Keep unlock and NULLing together
GlobalUnlock(m_hMemXferBits);
m_pMemXferBits = NULL;
ResetMemXfer();
//
// if we are working with an application provided HANDLE,
// GlobalUnlock it before continuing
//
if (pMemXfer->Memory.Flags & TWMF_HANDLE) {
GlobalUnlock(pMemXfer->Memory.TheMem);
}
return twRc;
}
//
// if we are working with an application provided HANDLE,
// GlobalUnlock it before continuing
//
if (pMemXfer->Memory.Flags & TWMF_HANDLE) {
GlobalUnlock(pMemXfer->Memory.TheMem);
}
}
}
//
// unlock buffer when finished
//
// Keep unlock and NULLing together
GlobalUnlock(m_hMemXferBits);
m_pMemXferBits = NULL;
} else {
//
// Could not lock down memory for transfer
//
m_twStatus.ConditionCode = TWCC_LOWMEMORY;
return TWRC_FAILURE;
}
} else {
//
// we recieved a message other than the expected MSG_GET
//
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_BADPROTOCOL;
}
}
break;
default:
{
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_SEQERROR;
return twRc;
break;
}
break;
}
//
// if we failed, report it properly
//
if (TWRC_FAILURE == twRc)
DSError();
return twRc;
}
TW_UINT16 CWiaDataSrc::OnImageFileXferMsg(PTWAIN_MSG ptwMsg)
{
DBG_FN_DS(CWiaDataSrc::OnImageFileXferMsg());
TW_UINT16 twRc = TWRC_SUCCESS;
if (MSG_GET == ptwMsg->MSG) {
GUID guidFileFormat = WiaImgFmt_BMP;
CCap *pCap = FindCap(ICAP_IMAGEFILEFORMAT);
if(pCap){
guidFileFormat = ICAP_IMAGEFILEFORMAT_TO_WIA_IPA_FORMAT((TW_UINT16)pCap->GetCurrent());
}
twRc = TransferToFile(guidFileFormat);
if(TWRC_XFERDONE == twRc) {
SetTWAINState(DS_STATE_7);
} else {
DBG_ERR(("CWiaDataSrc::OnImageFileXferMsg(), TransferToFile() failed"));
}
} else {
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_BADPROTOCOL;
}
if (TWRC_FAILURE == twRc){
DSError();
}
return twRc;
}
TW_UINT16 CWiaDataSrc::OnImageNativeXferMsg(PTWAIN_MSG ptwMsg)
{
DBG_FN_DS(CWiaDataSrc::OnImageNativeXferMsg());
TW_UINT16 twRc = TWRC_SUCCESS;
HGLOBAL hDIB = NULL;
switch (GetTWAINState()) {
case DS_STATE_6:
{
if (MSG_GET == ptwMsg->MSG) {
twRc = TransferToDIB(&hDIB);
if (TWRC_XFERDONE == twRc) {
SetTWAINState(DS_STATE_7);
*(TW_UINT32*)ptwMsg->pData = (TW_UINT32)(INT_PTR)hDIB;
} else {
DBG_ERR(("CWiaDataSrc::OnImageNativeXferMsg(), TransferToDIB() failed"));
}
} else {
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_BADPROTOCOL;
}
}
break;
default:
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_SEQERROR;
break;
}
if (TWRC_FAILURE == twRc){
DSError();
}
return twRc;
}
TW_UINT16 CWiaDataSrc::OpenDS(PTWAIN_MSG ptwMsg)
{
DBG_FN_DS(CWiaDataSrc::OpenDS());
TW_UINT16 twRc = TWRC_SUCCESS;
if (DS_STATE_3 == GetTWAINState()) {
//
// No multiple clients are allowed.
// This is enforced by making sure that our identity's id field
// has a value of 0.
if (m_dsIdentity.Id) {
m_twStatus.ConditionCode = TWCC_MAXCONNECTIONS;
twRc = TWRC_FAILURE;
} else {
//
// make a copy of the caller's identity
//
m_AppIdentity = *ptwMsg->AppId;
m_dsIdentity = *((TW_IDENTITY *)ptwMsg->pData);
HRESULT hr = S_OK;
hr = m_pDevice->Open(CWiaDataSrc::DeviceEventCallback,
(LPARAM)this);
if (FAILED(hr)) {
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_BUMMER;
}
}
} else {
m_twStatus.ConditionCode = TWCC_SEQERROR;
twRc = TWRC_FAILURE;
}
if (TWRC_SUCCESS == twRc) {
//
// transition to STATE_4
//
SetTWAINState(DS_STATE_4);
}
if (TWRC_SUCCESS != twRc) {
}
return twRc;
}
TW_UINT16 CWiaDataSrc::CloseDS(PTWAIN_MSG ptwMsg)
{
DBG_FN_DS(CWiaDataSrc::CloseDS());
TW_UINT16 twRc = TWRC_SUCCESS;
switch (GetTWAINState()) {
case DS_STATE_7:
case DS_STATE_6:
case DS_STATE_5:
case DS_STATE_4:
m_pDevice->Close();
//DBG_TRC(("Calling ResetMemXfer because CLOSEDS was called"));
ResetMemXfer();
//
// We are up for sale again.
//
m_AppIdentity.Id = 0;
//
// transition to STATE_3
//
SetTWAINState(DS_STATE_3);
if (m_pIWiaItems)
delete [] m_pIWiaItems;
m_pIWiaItems = NULL;
m_NumIWiaItems = 0;
m_NextIWiaItemIndex = 0;
break;
default:
m_twStatus.ConditionCode = TWCC_SEQERROR;
twRc = TWRC_FAILURE;
DSError();
break;
}
return twRc;
}
TW_UINT16 CWiaDataSrc::EnableDS(TW_USERINTERFACE *pUI)
{
return TWRC_FAILURE;
}
TW_UINT16 CWiaDataSrc::DisableDS(TW_USERINTERFACE *pUI)
{
DBG_FN_DS(CWiaDataSrc::DisableDS());
TW_UINT16 twRc = TWRC_SUCCESS;
switch (GetTWAINState()) {
case DS_STATE_5:
//
// transition to STATE_4
//
SetTWAINState(DS_STATE_4);
break;
default:
twRc = TWRC_FAILURE;
m_twStatus.ConditionCode = TWCC_SEQERROR;
DSError();
break;
}
return twRc;
}
TW_UINT16 CWiaDataSrc::CreateCapList(TW_UINT32 NumCaps,PCAPDATA pCapData)
{
DBG_FN_DS(CWiaDataSrc::CreateCapList());
if (!NumCaps || !pCapData)
return TWCC_BADVALUE;
TW_UINT16 twCc = TWCC_SUCCESS;
DestroyCapList();
m_CapList = new CCap[NumCaps];
if (m_CapList) {
for (m_NumCaps = 0; m_NumCaps < NumCaps; m_NumCaps++) {
twCc = m_CapList[m_NumCaps].ICap(&pCapData[m_NumCaps]);
if (TWCC_SUCCESS != twCc) {
break;
}
}
m_NumCaps = NumCaps;
} else {
twCc = TWCC_LOWMEMORY;
}
if (TWCC_SUCCESS != twCc && m_CapList) {
DestroyCapList();
}
return twCc;
}
TW_UINT16 CWiaDataSrc::DestroyCapList()
{
DBG_FN_DS(CWiaDataSrc::DestroyCapList());
if (m_CapList) {
delete [] m_CapList;
m_CapList = NULL;
}
m_NumCaps = 0;
return TWCC_SUCCESS;
}
CCap * CWiaDataSrc::FindCap(TW_UINT16 CapId)
{
TW_UINT32 ui32;
for (ui32 = 0; ui32 < m_NumCaps; ui32++) {
if (m_CapList[ui32].GetCapId() == CapId)
return &m_CapList[ui32];
}
return NULL;
}
void CWiaDataSrc::DSError()
{
DBG_FN_DS(CWiaDataSrc::DSError());
NotifyCloseReq();
}
HRESULT CALLBACK CWiaDataSrc::DeviceEventCallback(LONG lEvent,LPARAM lParam)
{
CWiaDataSrc *pDataSrc = NULL;
pDataSrc = (CWiaDataSrc *)lParam;
if (pDataSrc) {
pDataSrc->NotifyCloseReq();
return S_OK;
}
return E_FAIL;
}
DS_STATE CWiaDataSrc::SetTWAINState(DS_STATE NewTWAINState)
{
DBG_TRC(("(Transitioning From TWAIN STATE %d to TWAIN STATE %d)",m_dsState,NewTWAINState));
m_dsState = NewTWAINState;
return m_dsState;
}
DS_STATE CWiaDataSrc::GetTWAINState()
{
return m_dsState;
}
TW_UINT16 CWiaDataSrc::SetStatusTWCC(TW_UINT16 NewConditionCode)
{
m_twStatus.ConditionCode = NewConditionCode;
return NewConditionCode;
}
float CWiaDataSrc::ConvertToTWAINUnits(LONG lValue, LONG lResolution)
{
float fReturnValue = 0.0f;
CCap *pUnits = FindCap(ICAP_UNITS);
if(pUnits){
switch (pUnits->GetCurrent()) {
case TWUN_INCHES:
fReturnValue = (float)lValue / (float)lResolution;
break;
case TWUN_CENTIMETERS:
fReturnValue = (float)((lValue * 2.54) / (float)lResolution);
break;
case TWUN_PICAS:
fReturnValue = (float)((lValue * 6.00) / (float)lResolution);
break;
case TWUN_POINTS:
fReturnValue = (float)(((float)lValue * 72.0) / (float)lResolution);
break;
case TWUN_PIXELS:
default:
fReturnValue = (float)lValue;
break;
}
}
return fReturnValue;
}
LONG CWiaDataSrc::ConvertFromTWAINUnits(float fValue, LONG lResolution)
{
LONG lReturnValue = 0;
CCap *pUnits = FindCap(ICAP_UNITS);
if (pUnits) {
switch (pUnits->GetCurrent()) {
case TWUN_INCHES:
lReturnValue = (LONG)((float)fValue * (float)lResolution);
break;
case TWUN_CENTIMETERS:
lReturnValue = (LONG)(((float)fValue / 2.54) * (float)lResolution);
break;
case TWUN_PICAS:
lReturnValue = (LONG)(((float)fValue / 6.00) * (float)lResolution);
break;
case TWUN_POINTS:
lReturnValue = (LONG)(((float)fValue / 72.0) * (float)lResolution);
break;
case TWUN_PIXELS:
default:
lReturnValue = (LONG)fValue;
break;
}
}
return lReturnValue;
}
DWORD CWiaDataSrc::ReadTwainRegistryDWORDValue(LPTSTR szRegValue, DWORD dwDefault)
{
DBG_FN_DS(CWiaDataSrc::ReadTwainRegistryDWORDValue());
DWORD dwValue = 0;
DWORD dwType = REG_DWORD;
DWORD dwDataSize = sizeof(DWORD);
DWORD dwDisposition = REG_OPENED_EXISTING_KEY;
HKEY hTwainRootKey = NULL;
if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER,TWAIN_REG_KEY,0,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,
NULL,&hTwainRootKey,&dwDisposition)){
if(dwDisposition == REG_CREATED_NEW_KEY){
DBG_WRN(("CWiaDataSrc::ReadTwainRegistryDWORDValue(), Created Root Twain Registry Key"));
}
if (ERROR_SUCCESS == RegQueryValueEx(hTwainRootKey,szRegValue,NULL,&dwType,(BYTE*)&dwValue,&dwDataSize)) {
#ifdef UNICODE
DBG_TRC(("CWiaDataSrc::ReadTwainRegistryDWORDValue(), Reading %ws Registry Key Value = %d",szRegValue,dwValue));
#else
DBG_TRC(("CWiaDataSrc::ReadTwainRegistryDWORDValue(), Reading %s Registry Key Value = %d",szRegValue,dwValue));
#endif
} else {
// reset sizes, just for safety
dwType = REG_DWORD;
dwDataSize = sizeof(DWORD);
dwValue = dwDefault;
if(ERROR_SUCCESS == RegSetValueEx(hTwainRootKey,szRegValue,NULL,dwType,(BYTE*)&dwDefault,dwDataSize)){
#ifdef UNICODE
DBG_TRC(("CWiaDataSrc::ReadTwainRegistryDWORDValue(), Writing Default Value for %ws Registry Key Value = %d",szRegValue,dwDefault));
#else
DBG_TRC(("CWiaDataSrc::ReadTwainRegistryDWORDValue(), Writing Default Value for %s Registry Key Value = %d",szRegValue,dwDefault));
#endif
} else {
#ifdef UNICODE
DBG_TRC(("CWiaDataSrc::ReadTwainRegistryDWORDValue(), Error Reading %ws Registry Key Value",szRegValue));
#else
DBG_TRC(("CWiaDataSrc::ReadTwainRegistryDWORDValue(), Error Reading %s Registry Key Value",szRegValue));
#endif
}
}
RegCloseKey(hTwainRootKey);
hTwainRootKey = NULL;
} else {
DBG_ERR(("CWiaDataSrc::ReadTwainRegistryDWORDValue(), could not open Root TWAIN Registry Key"));
}
return dwValue;
}
LONG CWiaDataSrc::GetPrivateSupportedCapsFromWIADevice(LONG **ppCapArray)
{
DBG_FN_DS(CWiaDataSrc::GetPrivateSupportedCapsFromWIADevice());
if (!ppCapArray) {
DBG_ERR(("CWiaDataSrc::GetPrivateSupportedCapsFromWIADevice(), ppCapArray is NULL"));
return 0;
}
*ppCapArray = NULL;
LONG lNumPrivateCaps = 0;
if (m_pDevice) {
if (m_pDevice->TwainCapabilityPassThrough()) {
if (m_pCurrentIWiaItem) {
//
// Get the IWiaItemExtras Interface
//
IWiaItemExtras *pIWiaItemExtras = NULL;
HRESULT hr = m_pCurrentIWiaItem->QueryInterface(IID_IWiaItemExtras,(void **)&pIWiaItemExtras);
if (S_OK == hr) {
//
// set data sizes
//
DWORD dwInDataSize = 0;
DWORD dwOutDataSize = 0;
DWORD dwActualOutDataSize = 0;
BYTE *pInData = NULL;
BYTE *pOutData = NULL;
LONG lCapabilityDataSize = sizeof(LONG);
pOutData = (BYTE*)&lCapabilityDataSize;
pInData = (BYTE*)&lCapabilityDataSize;
dwActualOutDataSize = sizeof(LONG);
dwInDataSize = dwActualOutDataSize;
dwOutDataSize = dwActualOutDataSize;
//
// ask how many bytes are needed to store the private TWAIN capabilities the WIA driver supports
//
hr = pIWiaItemExtras->Escape(ESC_TWAIN_PRIVATE_SUPPORTED_CAPS,
pInData,
dwInDataSize,
pOutData,
dwOutDataSize,
&dwActualOutDataSize);
if (S_OK == hr) {
lCapabilityDataSize = (LONG)(*pOutData);
lNumPrivateCaps = (lCapabilityDataSize / sizeof(LONG));
DBG_TRC(("WIA device reported %d private TWAIN supported CAPS",lNumPrivateCaps));
if (lNumPrivateCaps > 0) {
//
// allocate an array of LONGs for the WIA driver to fill with
// CAP ids.
//
dwOutDataSize = (lCapabilityDataSize + PRIVATE_CAP_ARRAY_PADDING);
dwActualOutDataSize = dwOutDataSize;
*ppCapArray = (LONG*)GlobalAlloc(GPTR,dwOutDataSize);
if (*ppCapArray) {
pOutData = (BYTE*)*ppCapArray;
//
// ask the WIA driver to fill the array of LONGS
//
hr = pIWiaItemExtras->Escape(ESC_TWAIN_PRIVATE_SUPPORTED_CAPS,
pInData,
dwInDataSize,
pOutData,
dwOutDataSize,
&dwActualOutDataSize);
if (FAILED(hr)) {
//
// pIWiaItemExtras->Escape call failed,
// a failure means that there are no private supported capabilities
//
DBG_ERR(("pIWiaItemExtras->Escape Failed (sending a request for the cability array data)"));
DBG_TRC(("Escape(code = %d, pInData = %p, dwInDataSize = %d, pOutData = %p, dwOutDataSize = %d,dwActualOutDataSize = %d)",
ESC_TWAIN_PRIVATE_SUPPORTED_CAPS,
pInData,
dwInDataSize,
pOutData,
dwOutDataSize,
dwActualOutDataSize));
}
} else {
DBG_ERR(("could not allocate memory for private capability array of %d items (%d bytes - this includes padding)",lNumPrivateCaps,dwOutDataSize));
lNumPrivateCaps = 0;
*ppCapArray = NULL;
}
} else {
//
// no supported caps
//
DBG_TRC(("No private supported caps reported from WIA device"));
}
} else {
//
// pIWiaItemExtras->Escape call failed,
// a failure means that there are no private supported capabilities
//
DBG_ERR(("pIWiaItemExtras->Escape Failed (sending a request for the number of capabilities)"));
DBG_TRC(("Escape(code = %d, pInData = %p, dwInDataSize = %d, pOutData = %p, dwOutDataSize = %d,dwActualOutDataSize = %d)",
ESC_TWAIN_PRIVATE_SUPPORTED_CAPS,
pInData,
dwInDataSize,
pOutData,
dwOutDataSize,
dwActualOutDataSize));
}
//
// release IWiaItemExtras Interface
//
if (pIWiaItemExtras) {
pIWiaItemExtras->Release();
pIWiaItemExtras = NULL;
}
} else {
//
// QI for IWiaItemExtras Failed
//
DBG_ERR(("QueryInterface for IWiaItemExtras Failed"));
}
} else {
//
// no current item selected
//
DBG_ERR(("no current item selected for use"));
}
}
} else {
//
// m_pDevice is NULL
//
DBG_ERR(("CWiaDataSrc::GetPrivateSupportedCapsFromWIADevice(), m_pDevice is NULL"));
}
return lNumPrivateCaps;
}
TW_UINT16 CWiaDataSrc::TransferToFile(GUID guidFormatID)
{
DBG_FN_DS(CWiaDataSrc::TransferToFile());
TW_UINT16 twRc = TWRC_FAILURE;
HRESULT hr = E_FAIL;
CWiaDataCallback DataCallback;
CCap *pCap = NULL;
pCap = FindCap(CAP_INDICATORS);
if(pCap){
DataCallback.Initialize(NULL,pCap->GetCurrent());
} else {
DataCallback.Initialize(NULL,TRUE);
}
IWiaDataCallback *pIDataCB = NULL;
hr = DataCallback.QueryInterface(IID_IWiaDataCallback,(void **)&pIDataCB);
if (SUCCEEDED(hr)) {
hr = m_pDevice->LoadImageToDisk(m_pCurrentIWiaItem, m_FileXferName, guidFormatID, pIDataCB);
if (SUCCEEDED(hr)) {
twRc = TWRC_XFERDONE;
m_twStatus.ConditionCode = TWCC_SUCCESS;
}
pIDataCB->Release();
pIDataCB = NULL;
}
//
// check for a cancel, or out-of-paper error (scanners could return this)
//
if ((S_FALSE == hr) || (WIA_ERROR_PAPER_EMPTY == hr)) {
m_twStatus.ConditionCode = TWCC_SUCCESS;
if(WIA_ERROR_PAPER_EMPTY == hr) {
DBG_TRC(("CWiaDataSrc::TransferToFile(), WIA_ERROR_PAPER_EMPTY returned from source."));
}
//
// set XFERCOUNT
//
CCap *pxferCap = FindCap(CAP_XFERCOUNT);
if (pxferCap) {
pxferCap->SetCurrent((TW_UINT32)0);
}
//
// return a cancel to abort the transfer.
// Applications will most commonly delete the current
// image, and keep the previous images.
//
twRc = TWRC_CANCEL;
} else if (FAILED(hr)) {
m_twStatus.ConditionCode = TWCC_FROM_HRESULT(hr);
twRc = TWRC_FAILURE;
}
return twRc;
}
TW_UINT16 CWiaDataSrc::TransferToDIB(HGLOBAL *phDIB)
{
DBG_FN_DS(CWiaDataSrc::TransferToDIB());
TW_UINT16 twRc = TWRC_FAILURE;
HRESULT hr = E_FAIL;
CWiaDataCallback DataCallback;
CCap *pCap = NULL;
pCap = FindCap(CAP_INDICATORS);
if(pCap){
DataCallback.Initialize(NULL,pCap->GetCurrent());
} else {
DataCallback.Initialize(NULL,TRUE);
}
IWiaDataCallback *pIDataCB = NULL;
hr = DataCallback.QueryInterface(IID_IWiaDataCallback,(void **)&pIDataCB);
if (SUCCEEDED(hr)) {
hr = m_pDevice->LoadImage(m_pCurrentIWiaItem, WiaImgFmt_MEMORYBMP, pIDataCB); // memory bmp only
if (SUCCEEDED(hr)) {
if(SUCCEEDED(DataCallback.GetImage(phDIB, NULL))){
//
// DIB data (special case) - NATIVE TWAIN transfers are in DIB format always
// If we are acquiring DIB data, then we have to apply the
// height rules:
// positive = image is right side up
// negative = image is up side down
// zero = image has an unknown length (and assumed to be upside down)
if(FlipDIB(*phDIB)){
twRc = TWRC_XFERDONE;
m_ImageHeight = (TW_UINT32)DataCallback.GetImageHeight();
m_ImageWidth = (TW_UINT32)DataCallback.GetImageWidth();
}
}
}
pIDataCB->Release();
pIDataCB = NULL;
}
//
// check for a cancel, or out-of-paper error (scanners could return this)
//
if ((S_FALSE == hr) || (WIA_ERROR_PAPER_EMPTY == hr)) {
m_twStatus.ConditionCode = TWCC_SUCCESS;
if(WIA_ERROR_PAPER_EMPTY == hr) {
DBG_TRC(("CWiaDataSrc::TransferToDIB(), WIA_ERROR_PAPER_EMPTY returned from source."));
}
//
// set XFERCOUNT
//
CCap *pxferCap = FindCap(CAP_XFERCOUNT);
if (pxferCap) {
pxferCap->SetCurrent((TW_UINT32)0);
}
//
// return a cancel to abort the transfer.
// Applications will most commonly delete the current
// image, and keep the previous images.
//
twRc = TWRC_CANCEL;
} else if (FAILED(hr)) {
m_twStatus.ConditionCode = TWCC_FROM_HRESULT(hr);
twRc = TWRC_FAILURE;
}
return twRc;
}
TW_UINT16 CWiaDataSrc::TransferToMemory(GUID guidFormatID)
{
DBG_FN_DS(CWiaDataSrc::TransferToMemory());
//
// set WIA format in Transfer Information structure
//
m_MemoryTransferInfo.mtiguidFormat = guidFormatID;
TW_UINT16 twRc = TWRC_FAILURE;
HRESULT hr = E_FAIL;
CWiaDataCallback DataCallback;
CCap *pCap = NULL;
pCap = FindCap(CAP_INDICATORS);
if(pCap){
DataCallback.Initialize(NULL,pCap->GetCurrent());
} else {
DataCallback.Initialize(NULL,TRUE);
}
IWiaDataCallback *pIDataCB = NULL;
hr = DataCallback.QueryInterface(IID_IWiaDataCallback,(void **)&pIDataCB);
if (SUCCEEDED(hr)) {
hr = m_pDevice->LoadImage(m_pCurrentIWiaItem, guidFormatID, pIDataCB);
if (SUCCEEDED(hr)) {
if(SUCCEEDED(DataCallback.GetImage(&m_hMemXferBits, NULL))){
//
// check for DIB data (special case)
// If we are acquiring DIB data, then we have to apply the
// height rules:
// positive = image is right side up
// negative = image is up side down
// zero = image has an unknown length (and assumed to be upside down)
if(WiaImgFmt_MEMORYBMP == guidFormatID){
//
// for memory transfers we need to make sure that the image
// is upside down in memory, so the application can assemble
// the bands correctly.
//
FlipDIB(m_hMemXferBits, TRUE);
}
m_ImageHeight = (TW_UINT32)DataCallback.GetImageHeight();
m_ImageWidth = (TW_UINT32)DataCallback.GetImageWidth();
m_hCachedImageData = m_hMemXferBits;
twRc = TWRC_SUCCESS;
}
}
pIDataCB->Release();
pIDataCB = NULL;
}
//
// check for a cancel, or out-of-paper error (scanners could return this)
//
if ((S_FALSE == hr) || (WIA_ERROR_PAPER_EMPTY == hr)) {
m_twStatus.ConditionCode = TWCC_SUCCESS;
if(WIA_ERROR_PAPER_EMPTY == hr) {
DBG_TRC(("CWiaDataSrc::TransferToMemory(), WIA_ERROR_PAPER_EMPTY returned from source."));
}
//
// set XFERCOUNT
//
CCap *pxferCap = FindCap(CAP_XFERCOUNT);
if (pxferCap) {
pxferCap->SetCurrent((TW_UINT32)0);
}
//
// return a cancel to abort the transfer.
// Applications will most commonly delete the current
// image, and keep the previous images.
//
twRc = TWRC_CANCEL;
} else if (FAILED(hr)) {
m_twStatus.ConditionCode = TWCC_FROM_HRESULT(hr);
twRc = TWRC_FAILURE;
}
return twRc;
}
TW_UINT16 CWiaDataSrc::GetCachedImage(HGLOBAL *phImage)
{
DBG_FN_DS(CWiaDataSrc::GetCachedImage());
TW_UINT16 twRc = TWRC_FAILURE;
if(phImage){
if (m_hCachedImageData) {
*phImage = m_hCachedImageData;
//
// since we are giving out the cached data
// reset the cache handle to NULL;
//
m_hCachedImageData = NULL;
m_hMemXferBits = NULL;
twRc = TWRC_SUCCESS;
}
}
return twRc;
}
TW_UINT16 CWiaDataSrc::TransferToThumbnail(HGLOBAL *phThumbnail)
{
DBG_FN_DS(CWiaDataSrc::TransferToThumbnail());
TW_UINT16 twRc = TWRC_FAILURE;
HRESULT hr = E_FAIL;
hr = m_pDevice->LoadThumbnail(m_pCurrentIWiaItem,phThumbnail,NULL);
if (SUCCEEDED(hr)) {
twRc = TWRC_XFERDONE;
}
return twRc;
}
TW_UINT16 CWiaDataSrc::GetCommonSettings()
{
DBG_FN_DS(CWiaDataSrc::GetCommonSettings());
TW_UINT16 twRc = TWRC_FAILURE;
//
// Some TWAIN applications make the assumption that the TWAIN data source
// defaults to BMP/DIB data formats. This is on the basis that TWAIN
// spec minimal requirements are BMP/DIB. WIA minimal requirements are
// BMP/DIB. Set the current Format GUID to MEMORYBMP, and TYMED to
// TYMED_CALLBACK. This will set the WIA driver to transfer bitmap data
// by default. This does not limit the data types in any way. A high
// end application will properly read the valid TWAIN values and configure
// the device to do the correct thing.
//
//
// before configuring TWAIN valid values, set the WIA device to TYMED_CALLBACK, MEMORYBMP.
//
HRESULT hr = S_OK;
CWiahelper WIA;
hr = WIA.SetIWiaItem(m_pCurrentIWiaItem);
if (FAILED(hr)) {
DBG_ERR(("CWiaDataSrc::GetCommonSettings(), failed to set IWiaItem for property writing"));
return twRc;
}
hr = WIA.WritePropertyLong(WIA_IPA_TYMED,TYMED_CALLBACK);
if(FAILED(hr)){
DBG_ERR(("CWiaDataSrc::GetCommonSettings(), failed to set TYMED_CALLBACK as a default setting"));
return twRc;
}
hr = WIA.WritePropertyGUID(WIA_IPA_FORMAT,WiaImgFmt_MEMORYBMP);
if(FAILED(hr)){
DBG_ERR(("CWiaDataSrc::GetCommonSettings(), failed to set WiaImgFmt_MEMORYBMP as a default setting"));
return twRc;
}
if (TWRC_SUCCESS == GetPixelTypes()) {
if (TWRC_SUCCESS == GetCompressionTypes()) {
if (TWRC_SUCCESS == GetBitDepths()) {
if (TWRC_SUCCESS == GetImageFileFormats()) {
twRc = TWRC_SUCCESS;
} else {
DBG_ERR(("CWiaDataSrc::GetCommonSettings(), GetImageFileFormats()"));
}
} else {
DBG_ERR(("CWiaDataSrc::GetCommonSettings(), GetBitDepths() failed"));
}
} else {
DBG_ERR(("CWiaDataSrc::GetCommonSettings(), GetCompressionTypes() failed"));
}
} else {
DBG_ERR(("CWiaDataSrc::GetCommonSettings(), GetPixelTypes() failed"));
}
return twRc;
}
TW_UINT16 CWiaDataSrc::GetCommonDefaultSettings()
{
DBG_FN_DS(CWiaDataSrc::GetCommonDefaultSettings());
TW_UINT16 twRc = TWRC_FAILURE;
CCap *pCap = NULL;
TW_UINT16 CapDataArray[1];
pCap = FindCap(ICAP_PIXELTYPE);
if (pCap) {
CapDataArray[0] = TWPT_RGB;
twRc = pCap->Set(0,0,1,(BYTE*)CapDataArray);
if (TWRC_SUCCESS == twRc) {
pCap = FindCap(ICAP_COMPRESSION);
if (pCap) {
CapDataArray[0] = TWCP_NONE;
twRc = pCap->Set(0,0,1,(BYTE*)CapDataArray);
pCap = FindCap(ICAP_BITDEPTH);
if (pCap) {
CapDataArray[0] = 24;
twRc = pCap->Set(0,0,1,(BYTE*)CapDataArray);
if (TWRC_SUCCESS == twRc) {
pCap = FindCap(ICAP_IMAGEFILEFORMAT);
if (pCap) {
CapDataArray[0] = TWFF_BMP;
twRc = pCap->Set(0,0,1,(BYTE*)CapDataArray);
if (TWRC_SUCCESS == twRc) {
}
}
}
}
}
}
}
return twRc;
}
TW_UINT16 CWiaDataSrc::GetPixelTypes()
{
DBG_FN_DS(CWiaScannerDS::GetPixelTypes());
TW_UINT16 twRc = TWRC_FAILURE;
CCap *pCap = FindCap(ICAP_PIXELTYPE);
if (pCap) {
HRESULT hr = S_OK;
CWiahelper WIA;
hr = WIA.SetIWiaItem(m_pCurrentIWiaItem);
if (FAILED(hr)) {
DBG_ERR(("CWiaDataSrc::GetPixelTypes(), failed to set IWiaItem for property reading"));
return twRc;
}
TW_UINT32 ActualCount = 0;
TW_UINT32 CurrentIndex = 0;
TW_UINT32 DefaultIndex = 0;
TW_UINT16 *pPixelTypeArray = NULL;
//
// read current value, for default and current index settings
//
LONG lCurrentDataTypeValue = WIA_DATA_COLOR;
//
// read current WIA_IPA_DATATYPE setting
//
hr = WIA.ReadPropertyLong(WIA_IPA_DATATYPE,&lCurrentDataTypeValue);
if (SUCCEEDED(hr)) {
//
// read valid values for WIA_IPA_DATATYPE
//
PROPVARIANT pv;
memset(&pv,0,sizeof(pv));
LONG lAccessFlags = 0;
hr = WIA.ReadPropertyAttributes(WIA_IPA_DATATYPE,&lAccessFlags,&pv);
if (SUCCEEDED(hr)) {
if (lAccessFlags & WIA_PROP_LIST) {
//
// for each valid WIA value in the LIST, set a corresponding
// TWAIN value
//
pPixelTypeArray = new TW_UINT16[WIA_PROP_LIST_COUNT(&pv)];
if (pPixelTypeArray) {
memset(pPixelTypeArray,0,(sizeof(TW_UINT16)*WIA_PROP_LIST_COUNT(&pv)));
for (ULONG i = 0; i < WIA_PROP_LIST_COUNT(&pv);i++) {
switch (pv.caul.pElems[i+2]) {
case WIA_DATA_THRESHOLD:
pPixelTypeArray[ActualCount] = (TW_UINT16)TWPT_BW;
if (lCurrentDataTypeValue == WIA_DATA_THRESHOLD) {
CurrentIndex = ActualCount;
}
ActualCount++;
DBG_TRC(("WIA driver supports WIA_DATA_THERSHOLD -> TWPT_BW"));
break;
case WIA_DATA_GRAYSCALE:
pPixelTypeArray[ActualCount] = (TW_UINT16)TWPT_GRAY;
if (lCurrentDataTypeValue == WIA_DATA_GRAYSCALE) {
CurrentIndex = ActualCount;
}
ActualCount++;
DBG_TRC(("WIA driver supports WIA_DATA_GRAYSCALE -> TWPT_GRAY"));
break;
case WIA_DATA_COLOR:
pPixelTypeArray[ActualCount] = (TW_UINT16)TWPT_RGB;
if (lCurrentDataTypeValue == WIA_DATA_COLOR) {
CurrentIndex = ActualCount;
}
ActualCount++;
DBG_TRC(("WIA driver supports WIA_DATA_COLOR -> TWPT_RGB"));
break;
case WIA_DATA_DITHER:
case WIA_DATA_COLOR_THRESHOLD:
case WIA_DATA_COLOR_DITHER:
////////////////////////////////
// NO TWAIN -> WIA CONVERSION //
////////////////////////////////
//
// TWPT_PALETTE
// TWPT_CMY
// TWPT_CMYK
// TWPT_YUV
// TWPT_YUVK
// TWPT_CIEXYZ
default:
DBG_TRC(("WIA Data Type (%d) does not MAP to TWAIN a pixel type",pv.caul.pElems[i+2]));
break;
}
}
} else {
DBG_ERR(("CWiaDataSrc::GetPixelTypes(), failed to allocate Pixel Type Array Memory"));
}
} else {
//
// we only have 1 value, so make it the current, default and valid value.
//
pPixelTypeArray = new TW_UINT16[1];
if (pPixelTypeArray) {
memset(pPixelTypeArray,0,(sizeof(TW_UINT16)));
switch (lCurrentDataTypeValue) {
case WIA_DATA_THRESHOLD:
pPixelTypeArray[ActualCount] = (TW_UINT16)TWPT_BW;
if (lCurrentDataTypeValue == WIA_DATA_THRESHOLD) {
CurrentIndex = ActualCount;
}
ActualCount++;
DBG_TRC(("WIA driver supports WIA_DATA_THERSHOLD -> TWPT_BW"));
break;
case WIA_DATA_GRAYSCALE:
pPixelTypeArray[ActualCount] = (TW_UINT16)TWPT_GRAY;
if (lCurrentDataTypeValue == WIA_DATA_GRAYSCALE) {
CurrentIndex = ActualCount;
}
ActualCount++;
DBG_TRC(("WIA driver supports WIA_DATA_GRAYSCALE -> TWPT_GRAY"));
break;
case WIA_DATA_COLOR:
pPixelTypeArray[ActualCount] = (TW_UINT16)TWPT_RGB;
if (lCurrentDataTypeValue == WIA_DATA_COLOR) {
CurrentIndex = ActualCount;
}
ActualCount++;
DBG_TRC(("WIA driver supports WIA_DATA_COLOR -> TWPT_RGB"));
break;
case WIA_DATA_DITHER:
case WIA_DATA_COLOR_THRESHOLD:
case WIA_DATA_COLOR_DITHER:
////////////////////////////////
// NO TWAIN -> WIA CONVERSION //
////////////////////////////////
//
// TWPT_PALETTE
// TWPT_CMY
// TWPT_CMYK
// TWPT_YUV
// TWPT_YUVK
// TWPT_CIEXYZ
default:
DBG_TRC(("WIA Data Type (%d) does not MAP to TWAIN a pixel type",lCurrentDataTypeValue));
break;
}
} else {
DBG_ERR(("CWiaDataSrc::GetPixelTypes(), failed to allocate Pixel Type Array Memory"));
}
}
if (pPixelTypeArray) {
//
// default index is equal to current index, because we are stating that the WIA driver
// is a fresh start-up state.
//
DefaultIndex = CurrentIndex;
twRc = pCap->Set(DefaultIndex,CurrentIndex,ActualCount,(BYTE*)pPixelTypeArray,TRUE); // list
delete [] pPixelTypeArray;
pPixelTypeArray = NULL;
//twRc = TWRC_SUCCESS;
}
PropVariantClear(&pv);
} else {
DBG_ERR(("CWiaDataSrc::GetPixelTypes(), failed to read WIA_IPS_DATATYPE attributes"));
}
} else {
DBG_ERR(("CWiaDataSrc::GetPixelTypes(), failed to read WIA_IPS_DATATYPE current value"));
}
}
return twRc;
}
TW_UINT16 CWiaDataSrc::GetBitDepths()
{
DBG_FN_DS(CWiaScannerDS::GetBitDepths());
TW_UINT16 twRc = TWRC_FAILURE;
CCap *pCap = FindCap(ICAP_BITDEPTH);
if (pCap) {
HRESULT hr = S_OK;
CWiahelper WIA;
hr = WIA.SetIWiaItem(m_pCurrentIWiaItem);
if (FAILED(hr)) {
DBG_ERR(("CWiaDataSrc::GetBitDepths(), failed to set IWiaItem for property reading"));
return twRc;
}
TW_UINT32 ActualCount = 0;
TW_UINT32 CurrentIndex = 0;
TW_UINT32 DefaultIndex = 0;
TW_UINT16 BitDepthArray[MAX_BITDEPTHS];
memset(BitDepthArray,0,sizeof(BitDepthArray));
//
// read current value, for default and current index settings
//
LONG lCurrentDataTypeValue = WIA_DATA_COLOR;
LONG lCurrentBitDepthValue = 24;
//
// read current WIA_IPA_DATATYPE setting
//
hr = WIA.ReadPropertyLong(WIA_IPA_DATATYPE,&lCurrentDataTypeValue);
if (SUCCEEDED(hr)) {
//
// read current WIA_IPA_DEPTH setting
//
hr = WIA.ReadPropertyLong(WIA_IPA_DEPTH,&lCurrentBitDepthValue);
if (SUCCEEDED(hr)) {
PROPVARIANT pv;
memset(&pv,0,sizeof(pv));
LONG lAccessFlags = 0;
//
// read valid values for WIA_IPA_DATATYPE
//
hr = WIA.ReadPropertyAttributes(WIA_IPA_DATATYPE,&lAccessFlags,&pv);
if (SUCCEEDED(hr)) {
//
// for each valid value, set it to the current setting, and read
// the valid values for WIA_IPA_DEPTH.
//
if (lAccessFlags & WIA_PROP_LIST) {
//
// set the WIA_IPA_DATATYPE to each valid value in the LIST
//
for (ULONG i = 0; i < WIA_PROP_LIST_COUNT(&pv);i++) {
hr = WIA.WritePropertyLong(WIA_IPA_DATATYPE,(LONG)pv.caul.pElems[i+2]);
if (SUCCEEDED(hr)) {
//
// read valid values for WIA_IPA_DEPTH
//
lAccessFlags = 0;
PROPVARIANT pvDepth;
memset(&pvDepth,0,sizeof(pvDepth));
hr = WIA.ReadPropertyAttributes(WIA_IPA_DEPTH,&lAccessFlags,&pvDepth);
if (SUCCEEDED(hr)) {
LONG lBitDepth = 0;
if (lAccessFlags & WIA_PROP_LIST) {
//
// copy each valid value in the LIST to the array
//
for (ULONG ulIndex = 0; ulIndex < WIA_PROP_LIST_COUNT(&pvDepth);ulIndex++) {
lBitDepth = pvDepth.caul.pElems[ulIndex+2];
for (ULONG BitDepthArrayIndex = 0; BitDepthArrayIndex < MAX_BITDEPTHS; BitDepthArrayIndex++) {
if (BitDepthArray[BitDepthArrayIndex] == 0) {
//
// the current slot is (0) zero, so add the new bit depth value
//
BitDepthArray[BitDepthArrayIndex] = (TW_UINT16)lBitDepth;
DBG_TRC(("WIA driver supports %d bit depth",lBitDepth));
ActualCount++;
//
// exit the loop
//
BitDepthArrayIndex = MAX_BITDEPTHS;
} else if (BitDepthArray[BitDepthArrayIndex] == (TW_UINT16)lBitDepth) {
//
// bit depth is already in the list, so exit the loop
//
BitDepthArrayIndex = MAX_BITDEPTHS;
}
}
}
} else if (lAccessFlags & WIA_PROP_NONE) {
//
// read the current value for WIA_IPA_DEPTH
// and copy it to the array
//
hr = WIA.ReadPropertyLong(WIA_IPA_DEPTH,&lBitDepth);
if (SUCCEEDED(hr)) {
for (ULONG BitDepthArrayIndex = 0; BitDepthArrayIndex < MAX_BITDEPTHS; BitDepthArrayIndex++) {
if (BitDepthArray[BitDepthArrayIndex] == 0) {
//
// the current slot is (0) zero, so add the new bit depth value
//
BitDepthArray[BitDepthArrayIndex] = (TW_UINT16)lBitDepth;
DBG_TRC(("WIA driver supports %d bit depth",lBitDepth));
ActualCount++;
//
// exit the loop
//
BitDepthArrayIndex = MAX_BITDEPTHS;
} else if (BitDepthArray[BitDepthArrayIndex] == (TW_UINT16)lBitDepth) {
//
// bit depth is already in the list, so exit the loop
//
BitDepthArrayIndex = MAX_BITDEPTHS;
}
}
} else {
DBG_ERR(("CWiaDataSrc::GetBitDepths(), ReadPropertyLong(WIA_IPA_DEPTH) failed"));
}
}
//
// clean up the PROPVARIANT structure
//
PropVariantClear(&pvDepth);
}
} else {
DBG_ERR(("CWiaDataSrc::GetBitDepths(), WritePropertyLong(WIA_IPA_DATATYPE) failed"));
}
}
} else {
//
// we only have 1 value, so make it the current, default and valid value.
//
BitDepthArray[0] = (TW_UINT16)lCurrentBitDepthValue;
ActualCount = 1;
DBG_TRC(("WIA driver supports %d bit depth",lCurrentBitDepthValue));
}
//
// set the current values back
//
hr = WIA.WritePropertyLong(WIA_IPA_DATATYPE,lCurrentDataTypeValue);
if (SUCCEEDED(hr)) {
hr = WIA.WritePropertyLong(WIA_IPA_DEPTH,lCurrentBitDepthValue);
}
for (ULONG BitDepthArrayIndex = 0; BitDepthArrayIndex < MAX_BITDEPTHS; BitDepthArrayIndex++) {
if (BitDepthArray[BitDepthArrayIndex] == (TW_UINT16)lCurrentBitDepthValue) {
CurrentIndex = BitDepthArrayIndex;
BitDepthArrayIndex = MAX_BITDEPTHS;
}
}
//
// default index is equal to current index, because we are stating that the WIA driver
// is a fresh start-up state.
//
DefaultIndex = CurrentIndex;
twRc = pCap->Set(DefaultIndex,CurrentIndex,ActualCount,(BYTE*)BitDepthArray,TRUE); // list
//twRc = TWRC_SUCCESS;
PropVariantClear(&pv);
} else {
DBG_ERR(("CWiaDataSrc::GetBitDepths(), failed to read WIA_IPS_DATATYPE attributes"));
}
} else {
DBG_ERR(("CWiaDataSrc::GetBitDepths(), ReadPropertyLong(WIA_IPA_DEPTH) failed"));
}
} else {
DBG_ERR(("CWiaDataSrc::GetBitDepths(), ReadPropertyLong(WIA_IPA_DATATYPE) failed"));
}
}
return twRc;
}
TW_UINT16 CWiaDataSrc::GetImageFileFormats()
{
DBG_FN_DS(CWiaScannerDS::GetImageFileFormats());
TW_UINT16 twRc = TWRC_FAILURE;
CCap *pCap = FindCap(ICAP_IMAGEFILEFORMAT);
if (pCap) {
HRESULT hr = S_OK;
CWiahelper WIA;
hr = WIA.SetIWiaItem(m_pCurrentIWiaItem);
if (FAILED(hr)) {
DBG_ERR(("CWiaDataSrc::GetImageFileFormats(), failed to set IWiaItem for property reading"));
return twRc;
}
TW_UINT32 ActualCount = 0;
TW_UINT32 CurrentIndex = 0;
TW_UINT32 DefaultIndex = 0;
TW_UINT16 *pFileTypeArray = NULL;
IWiaDataTransfer *pIWiaDataTransfer = NULL;
TW_UINT32 TotalFileFormats = 0;
IEnumWIA_FORMAT_INFO *pIEnumWIA_FORMAT_INFO = NULL;
WIA_FORMAT_INFO pfe;
//
// read current value, for default and current index settings
//
GUID guidCurrentFileFormat = GUID_NULL;
hr = WIA.ReadPropertyGUID(WIA_IPA_FORMAT,&guidCurrentFileFormat);
if (SUCCEEDED(hr)) {
//
// collect valid values for image file format
//
hr = m_pCurrentIWiaItem->QueryInterface(IID_IWiaDataTransfer, (void **)&pIWiaDataTransfer);
if (S_OK == hr) {
hr = pIWiaDataTransfer->idtEnumWIA_FORMAT_INFO(&pIEnumWIA_FORMAT_INFO);
if (SUCCEEDED(hr)) {
//
// count supported FILE formats
//
do {
memset(&pfe,0,sizeof(pfe));
hr = pIEnumWIA_FORMAT_INFO->Next(1, &pfe, NULL);
if (hr == S_OK) {
if ((pfe.lTymed == TYMED_FILE) || (pfe.lTymed == TYMED_MULTIPAGE_FILE)) {
TotalFileFormats++;
}
}
} while (hr == S_OK);
//
// allocate supported FILE format array
//
pFileTypeArray = new TW_UINT16[TotalFileFormats];
if (pFileTypeArray) {
memset(pFileTypeArray,0,(sizeof(TW_UINT16) * TotalFileFormats));
//
// reset enuerator
//
hr = pIEnumWIA_FORMAT_INFO->Reset();
if (SUCCEEDED(hr)) {
do {
memset(&pfe,0,sizeof(pfe));
hr = pIEnumWIA_FORMAT_INFO->Next(1, &pfe, NULL);
if (hr == S_OK) {
if (pfe.lTymed == TYMED_MULTIPAGE_FILE) {
if (pfe.guidFormatID == WiaImgFmt_TIFF) {
pFileTypeArray[ActualCount] = (TW_UINT16)TWFF_TIFFMULTI;
if (guidCurrentFileFormat == WiaImgFmt_TIFF) {
CurrentIndex = ActualCount;
}
ActualCount++;
DBG_TRC(("WIA driver supports WiaImgFmt_TIFF (Multipage) -> TWFF_TIFFMULTI"));
}
}
if (pfe.lTymed == TYMED_FILE) {
if (pfe.guidFormatID == WiaImgFmt_BMP) {
pFileTypeArray[ActualCount] = (TW_UINT16)TWFF_BMP;
if (guidCurrentFileFormat == WiaImgFmt_BMP) {
CurrentIndex = ActualCount;
}
ActualCount++;
DBG_TRC(("WIA driver supports WiaImgFmt_BMP -> TWFF_BMP"));
} else if (pfe.guidFormatID == WiaImgFmt_JPEG) {
pFileTypeArray[ActualCount] = (TW_UINT16)TWFF_JFIF;
if (guidCurrentFileFormat == WiaImgFmt_JPEG) {
CurrentIndex = ActualCount;
}
ActualCount++;
DBG_TRC(("WIA driver supports WiaImgFmt_JPEG -> TWFF_JFIF"));
} else if (pfe.guidFormatID == WiaImgFmt_TIFF) {
pFileTypeArray[ActualCount] = (TW_UINT16)TWFF_TIFF;
if (guidCurrentFileFormat == WiaImgFmt_TIFF) {
CurrentIndex = ActualCount;
}
ActualCount++;
DBG_TRC(("WIA driver supports WiaImgFmt_TIFF -> TWFF_TIFF"));
} else if (pfe.guidFormatID == WiaImgFmt_PICT) {
pFileTypeArray[ActualCount] = (TW_UINT16)TWFF_PICT;
if (guidCurrentFileFormat == WiaImgFmt_PICT) {
CurrentIndex = ActualCount;
}
ActualCount++;
DBG_TRC(("WIA driver supports WiaImgFmt_PICT -> TWFF_PICT"));
} else if (pfe.guidFormatID == WiaImgFmt_PNG) {
pFileTypeArray[ActualCount] = (TW_UINT16)TWFF_PNG;
if (guidCurrentFileFormat == WiaImgFmt_PNG) {
CurrentIndex = ActualCount;
}
ActualCount++;
DBG_TRC(("WIA driver supports WiaImgFmt_PNG -> WiaImgFmt_PNG"));
} else if (pfe.guidFormatID == WiaImgFmt_EXIF) {
pFileTypeArray[ActualCount] = (TW_UINT16)TWFF_EXIF;
if (guidCurrentFileFormat == WiaImgFmt_EXIF) {
CurrentIndex = ActualCount;
}
ActualCount++;
DBG_TRC(("WIA driver supports WiaImgFmt_EXIF -> TWFF_EXIF"));
} else if (pfe.guidFormatID == WiaImgFmt_FLASHPIX) {
pFileTypeArray[ActualCount] = (TW_UINT16)TWFF_FPX;
if (guidCurrentFileFormat == WiaImgFmt_FLASHPIX) {
CurrentIndex = ActualCount;
}
ActualCount++;
DBG_TRC(("WIA driver supports WiaImgFmt_FLASHPIX -> TWFF_FPX"));
} else if (pfe.guidFormatID == WiaImgFmt_UNDEFINED) {
DBG_TRC(("WIA File Format WiaImgFmt_UNDEFINED does not MAP to TWAIN a file format"));
} else if (pfe.guidFormatID == WiaImgFmt_EMF) {
DBG_TRC(("WIA File Format WiaImgFmt_EMF does not MAP to TWAIN a file format"));
} else if (pfe.guidFormatID == WiaImgFmt_WMF) {
DBG_TRC(("WIA File Format WiaImgFmt_WMF does not MAP to TWAIN a file format"));
} else if (pfe.guidFormatID == WiaImgFmt_GIF) {
DBG_TRC(("WIA File Format WiaImgFmt_GIF does not MAP to TWAIN a file format"));
} else if (pfe.guidFormatID == WiaImgFmt_PHOTOCD) {
DBG_TRC(("WIA File Format WiaImgFmt_PHOTOCD does not MAP to TWAIN a file format"));
} else if (pfe.guidFormatID == WiaImgFmt_ICO) {
DBG_TRC(("WIA File Format WiaImgFmt_ICO does not MAP to TWAIN a file format"));
} else if (pfe.guidFormatID == WiaImgFmt_CIFF) {
DBG_TRC(("WIA File Format WiaImgFmt_CIFF does not MAP to TWAIN a file format"));
} else if (pfe.guidFormatID == WiaImgFmt_JPEG2K) {
DBG_TRC(("WIA File Format WiaImgFmt_JPEG2K does not MAP to TWAIN a file format"));
} else if (pfe.guidFormatID == WiaImgFmt_JPEG2KX) {
DBG_TRC(("WIA File Format WiaImgFmt_JPEG2KX does not MAP to TWAIN a file format"));
} else {
}
////////////////////////////////
// NO TWAIN -> WIA CONVERSION //
////////////////////////////////
//
// TWFF_XBM
// TWFF_SPIFF
}
}
} while (hr == S_OK);
}
if (pFileTypeArray) {
//
// default index is equal to current index, because we are stating that the WIA driver
// is a fresh start-up state.
//
DefaultIndex = CurrentIndex;
twRc = pCap->Set(DefaultIndex,CurrentIndex,ActualCount,(BYTE*)pFileTypeArray,TRUE); // list
delete [] pFileTypeArray;
pFileTypeArray = NULL;
//twRc = TWRC_SUCCESS;
}
}
pIEnumWIA_FORMAT_INFO->Release();
pIEnumWIA_FORMAT_INFO = NULL;
} else {
DBG_ERR(("CWiaDataSrc::GetImageFileFormats(), pIWiaDataTransfer->idtEnumWIA_FORMAT_INFO() failed to enumerate supported file formats"));
}
pIWiaDataTransfer->Release();
pIWiaDataTransfer = NULL;
} else {
DBG_ERR(("CWiaDataSrc::GetImageFileFormats(), QueryInterface(IID_IWiaDataTransfer) failed"));
}
}
}
return twRc;
}
TW_UINT16 CWiaDataSrc::GetCompressionTypes()
{
DBG_FN_DS(CWiaScannerDS::GetCompressionTypes());
TW_UINT16 twRc = TWRC_FAILURE;
CCap *pCap = FindCap(ICAP_COMPRESSION);
if (pCap) {
#ifdef SUPPORT_COMPRESSION_TYPES
HRESULT hr = S_OK;
CWiahelper WIA;
hr = WIA.SetIWiaItem(m_pCurrentIWiaItem);
if (FAILED(hr)) {
DBG_ERR(("CWiaDataSrc::GetCompressionTypes(), failed to set IWiaItem for property reading"));
return twRc;
}
TW_UINT32 ActualCount = 0;
TW_UINT32 CurrentIndex = 0;
TW_UINT32 DefaultIndex = 0;
TW_UINT16 *pCompressionTypeArray = NULL;
//
// read current value, for default and current index settings
//
LONG lCurrentCompressionTypeValue = WIA_COMPRESSION_NONE;
hr = WIA.ReadPropertyLong(WIA_IPA_COMPRESSION,&lCurrentCompressionTypeValue);
if (SUCCEEDED(hr)) {
PROPVARIANT pv;
memset(&pv,0,sizeof(pv));
LONG lAccessFlags = 0;
hr = WIA.ReadPropertyAttributes(WIA_IPA_COMPRESSION,&lAccessFlags,&pv);
if (SUCCEEDED(hr)) {
//
// collect valid values for compression type
//
if (lAccessFlags & WIA_PROP_LIST) {
pCompressionTypeArray = new TW_UINT16[WIA_PROP_LIST_COUNT(&pv)];
if (pCompressionTypeArray) {
memset(pCompressionTypeArray,0,(sizeof(TW_UINT16)*WIA_PROP_LIST_COUNT(&pv)));
for (ULONG i = 0; i < WIA_PROP_LIST_COUNT(&pv);i++) {
switch (pv.caul.pElems[i+2]) {
case WIA_COMPRESSION_NONE:
pCompressionTypeArray[ActualCount] = (TW_UINT16)TWCP_NONE;
if (lCurrentCompressionTypeValue == WIA_COMPRESSION_NONE) {
CurrentIndex = ActualCount;
}
ActualCount++;
DBG_TRC(("WIA driver supports WIA_COMPRESSION_NONE -> TWCP_NONE"));
break;
case WIA_COMPRESSION_G3:
pCompressionTypeArray[ActualCount] = (TW_UINT16)TWCP_GROUP31D;
if (lCurrentCompressionTypeValue == WIA_COMPRESSION_G3) {
CurrentIndex = ActualCount;
}
ActualCount++;
DBG_TRC(("WIA driver supports WIA_COMPRESSION_G3 -> TWCP_GROUP31D"));
break;
case WIA_COMPRESSION_G4:
pCompressionTypeArray[ActualCount] = (TW_UINT16)TWCP_GROUP4;
if (lCurrentCompressionTypeValue == WIA_COMPRESSION_G4) {
CurrentIndex = ActualCount;
}
ActualCount++;
DBG_TRC(("WIA driver supports WIA_COMPRESSION_G4 -> TWCP_GROUP4"));
break;
case WIA_COMPRESSION_JPEG:
pCompressionTypeArray[ActualCount] = (TW_UINT16)TWCP_JPEG;
if (lCurrentCompressionTypeValue == WIA_COMPRESSION_JPEG) {
CurrentIndex = ActualCount;
}
ActualCount++;
DBG_TRC(("WIA driver supports WIA_COMPRESSION_JPEG -> TWCP_JPEG"));
break;
case WIA_COMPRESSION_BI_RLE4:
pCompressionTypeArray[ActualCount] = (TW_UINT16)TWCP_RLE4;
if (lCurrentCompressionTypeValue == WIA_COMPRESSION_BI_RLE4) {
CurrentIndex = ActualCount;
}
ActualCount++;
DBG_TRC(("WIA driver supports WIA_COMPRESSION_BI_RLE4 -> TWCP_RLE4"));
break;
case WIA_COMPRESSION_BI_RLE8:
pCompressionTypeArray[ActualCount] = (TW_UINT16)TWCP_RLE8;
if (lCurrentCompressionTypeValue == WIA_COMPRESSION_BI_RLE8) {
CurrentIndex = ActualCount;
}
ActualCount++;
DBG_TRC(("WIA driver supports WIA_COMPRESSION_BI_RLE8 -> TWCP_RLE8"));
break;
////////////////////////////////
// NO TWAIN -> WIA CONVERSION //
////////////////////////////////
//
// TWCP_PACKBITS
// TWCP_GROUP31D
// TWCP_GROUP31DEOL
// TWCP_GROUP32D
//
//
// TWCP_LZW
// TWCP_JBIG
default:
DBG_TRC(("WIA Compression Type (%d) does not MAP to TWAIN a compression type",pv.caul.pElems[i+2]));
break;
}
}
} else {
DBG_ERR(("CWiaDataSrc::GetCompressionTypes(), failed to allocate Compression Type Array Memory"));
}
} else {
//
// current value becomes the only valid value
//
CurrentIndex = 0;
ActualCount = 1;
pCompressionTypeArray = new TW_UINT16[1];
if (pCompressionTypeArray) {
switch (lCurrentCompressionTypeValue) {
case WIA_COMPRESSION_NONE:
pCompressionTypeArray[0] = (TW_UINT16)TWCP_NONE;
DBG_TRC(("WIA driver supports WIA_COMPRESSION_NONE -> TWCP_NONE"));
break;
case WIA_COMPRESSION_G3:
pCompressionTypeArray[0] = (TW_UINT16)TWCP_GROUP31D;
DBG_TRC(("WIA driver supports WIA_COMPRESSION_G3 -> TWCP_GROUP31D"));
break;
case WIA_COMPRESSION_G4:
pCompressionTypeArray[0] = (TW_UINT16)TWCP_GROUP4;
DBG_TRC(("WIA driver supports WIA_COMPRESSION_G4 -> TWCP_GROUP4"));
break;
case WIA_COMPRESSION_JPEG:
pCompressionTypeArray[0] = (TW_UINT16)TWCP_JPEG;
DBG_TRC(("WIA driver supports WIA_COMPRESSION_JPEG -> TWCP_JPEG"));
break;
case WIA_COMPRESSION_BI_RLE4:
pCompressionTypeArray[0] = (TW_UINT16)TWCP_RLE4;
DBG_TRC(("WIA driver supports WIA_COMPRESSION_BI_RLE4 -> TWCP_RLE4"));
break;
case WIA_COMPRESSION_BI_RLE8:
pCompressionTypeArray[0] = (TW_UINT16)TWCP_RLE8;
DBG_TRC(("WIA driver supports WIA_COMPRESSION_BI_RLE8 -> TWCP_RLE8"));
break;
////////////////////////////////
// NO TWAIN -> WIA CONVERSION //
////////////////////////////////
//
// TWCP_PACKBITS
// TWCP_GROUP31D
// TWCP_GROUP31DEOL
// TWCP_GROUP32D
//
//
// TWCP_LZW
// TWCP_JBIG
default:
DBG_TRC(("WIA Compression Type (%d) does not MAP to TWAIN a compression type",lCurrentCompressionTypeValue));
break;
}
}
}
if (pCompressionTypeArray) {
//
// default index is equal to current index, because we are stating that the WIA driver
// is a fresh start-up state.
//
DefaultIndex = CurrentIndex;
twRc = pCap->Set(DefaultIndex,CurrentIndex,ActualCount,(BYTE*)pCompressionTypeArray,TRUE); // list
delete [] pCompressionTypeArray;
pCompressionTypeArray = NULL;
//twRc = TWRC_SUCCESS;
}
PropVariantClear(&pv);
} else {
DBG_ERR(("CWiaDataSrc::GetCompressionTypes(), failed to read WIA_IPA_COMPRESSION attributes"));
}
} else {
DBG_ERR(("CWiaDataSrc::GetCompressionTypes(), failed to read WIA_IPA_COMPRESSION current value"));
}
#else // SUPPORT_COMPRESSION_TYPES
//
// support only TWCP_NONE (no Compression)
//
TW_UINT16 CapDataArray[1];
CapDataArray[0] = TWCP_NONE;
twRc = pCap->Set(0,0,1,(BYTE*)CapDataArray);
#endif // SUPPORT_COMPRESSION_TYPES
}
return twRc;
}
TW_UINT16 CWiaDataSrc::SetCommonSettings(CCap *pCap)
{
DBG_FN_DS(CWiaScannerDS::SetCommonSettings());
HRESULT hr = S_OK;
LONG lValue = 0;
CWiahelper WIA;
IWiaItem *pIRootItem = NULL;
hr = WIA.SetIWiaItem(m_pCurrentIWiaItem);
if (FAILED(hr)) {
DBG_ERR(("CWiaDataSrc::SetCommonSettings(), 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 ICAP_PIXELTYPE:
DBG_TRC(("CWiaDataSrc::SetCommonSettings(ICAP_PIXELTYPE)"));
switch (pCap->GetCurrent()) {
case TWPT_BW:
DBG_TRC(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_DATATYPE to WIA_DATA_THRESHOLD"));
hr = WIA.WritePropertyLong(WIA_IPA_DATATYPE,WIA_DATA_THRESHOLD);
if(FAILED(hr)){
DBG_ERR(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_DATATYPE to WIA_DATA_THRESHOLD failed"));
}
break;
case TWPT_GRAY:
DBG_TRC(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_DATATYPE to WIA_DATA_GRAYSCALE"));
hr = WIA.WritePropertyLong(WIA_IPA_DATATYPE,WIA_DATA_GRAYSCALE);
if(FAILED(hr)){
DBG_ERR(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_DATATYPE to WIA_DATA_GRAYSCALE failed"));
}
break;
case TWPT_RGB:
DBG_TRC(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_DATATYPE to WIA_DATA_COLOR"));
hr = WIA.WritePropertyLong(WIA_IPA_DATATYPE,WIA_DATA_COLOR);
if(FAILED(hr)){
DBG_ERR(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_DATATYPE to WIA_DATA_COLOR failed"));
}
break;
case TWPT_PALETTE:
case TWPT_CMY:
case TWPT_CMYK:
case TWPT_YUV:
case TWPT_YUVK:
case TWPT_CIEXYZ:
default:
DBG_WRN(("CWiaDataSrc::SetCommonSettings(), An unsupported ICAP_PIXELTYPE (%d) was sent to this data source",(LONG)pCap->GetCurrent()));
break;
}
break;
case ICAP_BITDEPTH:
DBG_TRC(("CWiaDataSrc::SetCommonSettings(ICAP_BITDEPTH)"));
lValue = (LONG)pCap->GetCurrent();
DBG_TRC(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_BITDEPTH to %d",lValue));
hr = WIA.WritePropertyLong(WIA_IPA_DEPTH,lValue);
if(FAILED(hr)){
DBG_ERR(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_BITDEPTH to %d failed",lValue));
}
break;
case ICAP_IMAGEFILEFORMAT:
{
DBG_TRC(("CWiaDataSrc::SetCommonSettings(ICAP_IMAGEFILEFORMAT)"));
lValue = (LONG)pCap->GetCurrent();
LONG lTymed = TYMED_FILE;
if (lValue == TWFF_TIFFMULTI) {
DBG_TRC(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_TYMED to TYMED_MULTIPAGE_FILE"));
lTymed = TYMED_MULTIPAGE_FILE;
} else {
DBG_TRC(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_TYMED to TYMED_FILE"));
}
hr = WIA.WritePropertyLong(WIA_IPA_TYMED,lTymed);
GUID guidFormat = GUID_NULL;
if (SUCCEEDED(hr)) {
switch (lValue) {
case TWFF_TIFFMULTI:
case TWFF_TIFF:
guidFormat = WiaImgFmt_TIFF;
DBG_TRC(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_FORMAT to WiaImgFmt_TIFF"));
break;
case TWFF_PICT:
guidFormat = WiaImgFmt_PICT;
DBG_TRC(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_FORMAT to WiaImgFmt_PICT"));
break;
case TWFF_BMP:
guidFormat = WiaImgFmt_BMP;
DBG_TRC(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_FORMAT to WiaImgFmt_BMP"));
break;
case TWFF_JFIF:
guidFormat = WiaImgFmt_JPEG;
DBG_TRC(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_FORMAT to WiaImgFmt_JPEG"));
break;
case TWFF_FPX:
guidFormat = WiaImgFmt_FLASHPIX;
DBG_TRC(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_FORMAT to WiaImgFmt_FLASHPIX"));
break;
case TWFF_PNG:
guidFormat = WiaImgFmt_PNG;
DBG_TRC(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_FORMAT to WiaImgFmt_PNG"));
break;
case TWFF_EXIF:
guidFormat = WiaImgFmt_EXIF;
DBG_TRC(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_FORMAT to WiaImgFmt_EXIF"));
break;
case TWFF_SPIFF:
case TWFF_XBM:
default:
break;
}
hr = WIA.WritePropertyGUID(WIA_IPA_FORMAT,guidFormat);
if (FAILED(hr)) {
DBG_ERR(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_FORMAT to %d failed",lValue));
}
} else {
DBG_ERR(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_TYMED to %d failed",lTymed));
}
}
break;
case ICAP_COMPRESSION:
{
DBG_TRC(("CWiaDataSrc::SetCommonSettings(ICAP_COMPRESSION)"));
lValue = (LONG)pCap->GetCurrent();
LONG lCompression = WIA_COMPRESSION_NONE;
switch (lValue) {
case TWCP_NONE:
lCompression = WIA_COMPRESSION_NONE;
DBG_TRC(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_COMPRESSION to WIA_COMPRESSION_NONE"));
break;
case TWCP_GROUP4:
lCompression = WIA_COMPRESSION_G4;
DBG_TRC(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_COMPRESSION to WIA_COMPRESSION_G4"));
break;
case TWCP_JPEG:
lCompression = WIA_COMPRESSION_JPEG;
DBG_TRC(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_COMPRESSION to WIA_COMPRESSION_JPEG"));
break;
case TWCP_RLE4:
lCompression = WIA_COMPRESSION_BI_RLE4;
DBG_TRC(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_COMPRESSION to WIA_COMPRESSION_BI_RLE4"));
break;
case TWCP_RLE8:
lCompression = WIA_COMPRESSION_BI_RLE8;
DBG_TRC(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_COMPRESSION to WIA_COMPRESSION_BI_RLE8"));
break;
case TWCP_GROUP31D:
case TWCP_GROUP31DEOL:
case TWCP_GROUP32D:
lCompression = WIA_COMPRESSION_G3;
DBG_TRC(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_COMPRESSION to WIA_COMPRESSION_G3"));
break;
case TWCP_LZW:
case TWCP_JBIG:
case TWCP_PACKBITS:
default:
break;
}
hr = WIA.WritePropertyLong(WIA_IPA_COMPRESSION,lCompression);
if(FAILED(hr)){
DBG_ERR(("CWiaDataSrc::SetCommonSettings(), Setting WIA_IPA_COMPRESSION to %d failed",lCompression));
}
}
break;
default:
DBG_TRC(("CWiaDataSrc::SetCommonSettings(), data source is not setting CAPID = %x to WIA device (it is not needed)",pCap->GetCapId()));
break;
}
if (SUCCEEDED(hr)) {
DBG_TRC(("CWiaDataSrc::SetCommonSettings(), Settings were successfully sent to WIA device"));
} else {
DBG_ERR(("CWiaDataSrc::SetCommonSettings(), Settings were unsuccessfully sent to WIA device"));
return TWRC_FAILURE;
}
return TWRC_SUCCESS;
}
TW_UINT16 CWiaDataSrc::GetMemoryTransferBits(BYTE* pImageData)
{
DBG_FN_DS(CWiaScannerDS::GetMemoryTransferBits());
if(!pImageData){
return TWRC_FAILURE;
}
BYTE *pBits = pImageData;
if (m_MemoryTransferInfo.mtiguidFormat == WiaImgFmt_MEMORYBMP) {
BITMAPINFOHEADER* pbmh = (BITMAPINFOHEADER*)pImageData;
if (pbmh) {
pBits += sizeof(BITMAPINFOHEADER) + (pbmh->biClrUsed * sizeof(RGBQUAD));
}
}
m_MemoryTransferInfo.mtipBits = pBits;
return TWRC_SUCCESS;
}