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.
1278 lines
45 KiB
1278 lines
45 KiB
#include "precomp.h"
|
|
|
|
const ULONG DEFAULT_BUFFER_SIZE = 65535;
|
|
IMessageFilter * g_pOldOleMessageFilter = NULL;
|
|
|
|
HRESULT CWiaDevice::Initialize(LPCTSTR DeviceId)
|
|
{
|
|
DBG_FN_WIADEV(CWiaDevice::Initialize());
|
|
HRESULT hr = S_OK;
|
|
HRESULT Temphr = S_OK;
|
|
|
|
if (!DeviceId) {
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// copy the deviceID string into the member variable for later use.
|
|
//
|
|
|
|
if(!lstrcpyn(m_szDeviceID,DeviceId, ((sizeof(m_szDeviceID)/sizeof(m_szDeviceID[0])) - 1))) {
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
//
|
|
// we have a device ID, so now find it in the device enumeration, and
|
|
// fill the needed values for TW_IDENTITY
|
|
//
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
IWiaDevMgr *pIWiaDevMgr = NULL;
|
|
|
|
hr = CoCreateInstance(CLSID_WiaDevMgr, NULL,CLSCTX_LOCAL_SERVER,IID_IWiaDevMgr,(void **)&pIWiaDevMgr);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// create a WIA DEV info enumerator
|
|
//
|
|
|
|
IEnumWIA_DEV_INFO *pWiaEnumDevInfo = NULL;
|
|
hr = pIWiaDevMgr->EnumDeviceInfo(0,&pWiaEnumDevInfo);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
do {
|
|
|
|
IWiaPropertyStorage *pIWiaPropStg = NULL;
|
|
hr = pWiaEnumDevInfo->Next(1,&pIWiaPropStg, NULL);
|
|
if (hr == S_OK) {
|
|
|
|
PROPSPEC PropSpec[4];
|
|
PROPVARIANT PropVar[4];
|
|
|
|
memset(PropVar,0,sizeof(PropVar));
|
|
|
|
// Device ID (used for searching)
|
|
PropSpec[0].ulKind = PRSPEC_PROPID;
|
|
PropSpec[0].propid = WIA_DIP_DEV_ID;
|
|
|
|
// Device Name
|
|
PropSpec[1].ulKind = PRSPEC_PROPID;
|
|
PropSpec[1].propid = WIA_DIP_DEV_NAME;
|
|
|
|
// Device Description
|
|
PropSpec[2].ulKind = PRSPEC_PROPID;
|
|
PropSpec[2].propid = WIA_DIP_DEV_DESC;
|
|
|
|
// Device Vendor Description
|
|
PropSpec[3].ulKind = PRSPEC_PROPID;
|
|
PropSpec[3].propid = WIA_DIP_VEND_DESC;
|
|
|
|
hr = pIWiaPropStg->ReadMultiple(sizeof(PropSpec)/sizeof(PROPSPEC),
|
|
PropSpec,
|
|
PropVar);
|
|
|
|
if (hr == S_OK) {
|
|
|
|
DBG_TRC(("CWiaDevice::Initialize(), Reported Device Information from WIA device"));
|
|
DBG_TRC(("Device ID = %ws",PropVar[0].bstrVal));
|
|
DBG_TRC(("Device Name = %ws",PropVar[1].bstrVal));
|
|
DBG_TRC(("Device Desc = %ws",PropVar[2].bstrVal));
|
|
DBG_TRC(("Device Vendor Desc = %ws",PropVar[3].bstrVal));
|
|
|
|
#ifdef UNICODE
|
|
//
|
|
// compare Device IDs to find the correct device
|
|
//
|
|
|
|
DBG_TRC(("comparing Device ID [in] = %ws, to Device ID [read] = %ws",m_szDeviceID,PropVar[0].bstrVal));
|
|
|
|
if (lstrcmpi(m_szDeviceID,PropVar[0].bstrVal) == 0) {
|
|
|
|
//
|
|
// copy the device name
|
|
//
|
|
|
|
if(!lstrcpyn(m_szDeviceName,PropVar[1].bstrVal,((sizeof(m_szDeviceName)/sizeof(m_szDeviceName[0])) - 1))) {
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
} else {
|
|
|
|
//
|
|
// copy the device description
|
|
//
|
|
|
|
if(!lstrcpyn(m_szDeviceDesc,PropVar[2].bstrVal,((sizeof(m_szDeviceDesc)/sizeof(m_szDeviceDesc[0])) - 1))){
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
} else {
|
|
|
|
//
|
|
// copy the device vendor description
|
|
//
|
|
|
|
if(!lstrcpyn(m_szDeviceVendorDesc,PropVar[3].bstrVal,((sizeof(m_szDeviceVendorDesc)/sizeof(m_szDeviceVendorDesc[0])) - 1))) {
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
|
|
TCHAR szTempString[MAX_PATH];
|
|
memset(szTempString,0,sizeof(szTempString));
|
|
|
|
LONG lLength = 0;
|
|
lLength = WideCharToMultiByte(CP_ACP,0,PropVar[0].bstrVal,
|
|
lstrlenW(PropVar[0].bstrVal),
|
|
szTempString,
|
|
(sizeof(szTempString)/sizeof(CHAR)),
|
|
NULL,NULL);
|
|
|
|
if (!lLength) {
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
} else {
|
|
|
|
//
|
|
// compare Device IDs to find the correct device
|
|
//
|
|
|
|
DBG_TRC(("comparing Device ID [in] = %s, to Device ID [read] = %s",m_szDeviceID,szTempString));
|
|
|
|
if (lstrcmpi(m_szDeviceID,szTempString) == 0) {
|
|
|
|
// convert and copy Device Name
|
|
memset(szTempString,0,sizeof(szTempString));
|
|
lLength = WideCharToMultiByte(CP_ACP,0,PropVar[1].bstrVal,
|
|
lstrlenW(PropVar[1].bstrVal),
|
|
szTempString,
|
|
(sizeof(szTempString)/sizeof(CHAR)),
|
|
NULL,NULL);
|
|
|
|
if (!lLength) {
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
} else {
|
|
|
|
if (!lstrcpyn(m_szDeviceName,szTempString,((sizeof(m_szDeviceName)/sizeof(m_szDeviceName[0])) - 1))) {
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
} else {
|
|
|
|
// convert and copy Device Description
|
|
memset(szTempString,0,sizeof(szTempString));
|
|
lLength = WideCharToMultiByte(CP_ACP,0,PropVar[2].bstrVal,
|
|
lstrlenW(PropVar[2].bstrVal),
|
|
szTempString,
|
|
(sizeof(szTempString)/sizeof(CHAR)),
|
|
NULL,NULL);
|
|
|
|
if (!lLength) {
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
} else {
|
|
|
|
if(!lstrcpyn(m_szDeviceDesc,szTempString,((sizeof(m_szDeviceDesc)/sizeof(m_szDeviceDesc[0])) - 1))){
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
} else {
|
|
|
|
// convert and copy Device Vendor Description
|
|
memset(szTempString,0,sizeof(szTempString));
|
|
lLength = WideCharToMultiByte(CP_ACP,0,
|
|
PropVar[3].bstrVal,
|
|
lstrlenW(PropVar[3].bstrVal),
|
|
szTempString,
|
|
(sizeof(szTempString)/sizeof(CHAR)),
|
|
NULL,NULL);
|
|
if (!lLength) {
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
} else {
|
|
|
|
if (!lstrcpyn(m_szDeviceVendorDesc,szTempString,((sizeof(m_szDeviceVendorDesc)/sizeof(m_szDeviceVendorDesc[0])) - 1))) {
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
} else {
|
|
|
|
//
|
|
// Set hr to S_FALSE, to signal that we are finished with
|
|
// the device enumeration
|
|
//
|
|
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// free property variant array
|
|
//
|
|
|
|
FreePropVariantArray(sizeof(PropSpec)/sizeof(PROPSPEC),PropVar);
|
|
|
|
//
|
|
// release Property Storage
|
|
//
|
|
|
|
if(pIWiaPropStg) {
|
|
pIWiaPropStg->Release();
|
|
pIWiaPropStg = NULL;
|
|
}
|
|
|
|
}
|
|
}
|
|
} while (hr == S_OK);
|
|
|
|
//
|
|
// release WIA device Enumerator
|
|
//
|
|
|
|
if(pWiaEnumDevInfo) {
|
|
pWiaEnumDevInfo->Release();
|
|
}
|
|
}
|
|
|
|
//
|
|
// release WIA device manager
|
|
//
|
|
|
|
if(pIWiaDevMgr) {
|
|
pIWiaDevMgr->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
if(S_FALSE == hr){
|
|
|
|
//
|
|
// set this to OK, because enumeration termination could set hr to S_FALSE
|
|
//
|
|
|
|
hr = S_OK;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWiaDevice::Open( PFNDEVICEEVENTCALLBACK pCallback, LPARAM lParam)
|
|
{
|
|
DBG_FN_WIADEV(CWiaDevice::Open());
|
|
HRESULT hr = S_OK;
|
|
IWiaDevMgr *pIWiaDevMgr = NULL;
|
|
BSTR bstrDeviceId = NULL;
|
|
|
|
hr = CoCreateInstance(CLSID_WiaDevMgr, NULL,CLSCTX_LOCAL_SERVER,IID_IWiaDevMgr,
|
|
(void **)&pIWiaDevMgr);
|
|
if (S_OK == hr) {
|
|
|
|
#ifdef UNICODE
|
|
bstrDeviceId = SysAllocString(m_szDeviceID);
|
|
#else
|
|
WCHAR DeviceIdW[MAX_PATH];
|
|
MultiByteToWideChar(CP_ACP, 0, m_szDeviceID, -1,DeviceIdW, (sizeof(DeviceIdW) / sizeof(DeviceIdW[0])));
|
|
bstrDeviceId = SysAllocString(DeviceIdW);
|
|
#endif
|
|
|
|
if (bstrDeviceId) {
|
|
hr = pIWiaDevMgr->CreateDevice(bstrDeviceId,&m_pRootItem);
|
|
SysFreeString(bstrDeviceId);
|
|
} else {
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
pIWiaDevMgr->Release();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWiaDevice::Close()
|
|
{
|
|
DBG_FN_WIADEV(CWiaDevice::Close());
|
|
HRESULT hr = S_OK;
|
|
FreeAcquiredImages();
|
|
|
|
if (m_pRootItem) {
|
|
m_pRootItem->Release();
|
|
m_pRootItem = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWiaDevice::GetDeviceName(LPTSTR Name,UINT NameSize,UINT *pActualSize)
|
|
{
|
|
DBG_FN_WIADEV(CWiaDevice::GetDeviceName());
|
|
HRESULT hr = S_OK;
|
|
memset(Name,0,NameSize);
|
|
lstrcpyn(Name,m_szDeviceName,NameSize-1);
|
|
if(pActualSize){
|
|
*pActualSize = 0;
|
|
*pActualSize = lstrlen(Name);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWiaDevice::GetDeviceDesc(LPTSTR Desc,UINT DescSize,UINT *pActualSize)
|
|
{
|
|
DBG_FN_WIADEV(CWiaDevice::GetDeviceDesc());
|
|
HRESULT hr = S_OK;
|
|
memset(Desc,0,DescSize);
|
|
lstrcpyn(Desc,m_szDeviceDesc,DescSize-1);
|
|
if(pActualSize){
|
|
*pActualSize = 0;
|
|
*pActualSize = lstrlen(Desc);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWiaDevice::GetDeviceVendorName(LPTSTR Name,UINT NameSize,UINT *pActualSize)
|
|
{
|
|
DBG_FN_WIADEV(CWiaDevice::GetDeviceVendorName);
|
|
HRESULT hr = S_OK;
|
|
memset(Name,0,NameSize);
|
|
lstrcpyn(Name,m_szDeviceVendorDesc,NameSize-1);
|
|
if(pActualSize){
|
|
*pActualSize = 0;
|
|
*pActualSize = lstrlen(Name);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWiaDevice::AcquireImages(HWND hwndOwner,BOOL ShowUI)
|
|
{
|
|
DBG_FN_WIADEV(CWiaDevice::AcquireImages());
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!m_NumImageItems) {
|
|
|
|
//
|
|
// If we have not done so, do it.
|
|
//
|
|
|
|
if (ShowUI) {
|
|
DBG_TRC(("CWiaDevice::AcquireImages(), called for UI mode Initialization"));
|
|
|
|
//
|
|
// We will present the acquistion UI, use the default
|
|
// dialog to do it. The dialog is modal.
|
|
// It will return an array of (IWiaItem *) with each item
|
|
// represent a image(camera) or scan head(scanner).
|
|
// For a camera item, a call to LoadImage will load the image
|
|
// it represents; for a scanner item, a call to LoadImage
|
|
// will trigger scanning.
|
|
//
|
|
|
|
hr = m_pRootItem->DeviceDlg(hwndOwner,
|
|
// WIA_DEVICE_DIALOG_USE_COMMON_UI,// flags - removed because it was forcing Common UI
|
|
0, // flags
|
|
WIA_INTENT_MINIMIZE_SIZE, // intent
|
|
&m_NumImageItems, // item count
|
|
&m_ImageItemArray); // item array
|
|
|
|
DBG_TRC(("CWiaDevice::AcquireImages(),Number of images from DeviceDlg to Transfer = %d",m_NumImageItems));
|
|
} else {
|
|
DBG_TRC(("CWiaDevice::AcquireImages(), called for UI-LESS mode Initialization"));
|
|
DBG_TRC(("or...DS needs information for CAPABILITY initialization"));
|
|
|
|
//
|
|
// Non-UI mode, every item with
|
|
// ItemType == (WiaItemTypeImage | WiaItemTypeFile) is a data acquire
|
|
// item. Here we go through two passes:
|
|
// - The first pass determines how many items are available.
|
|
// - The second pass allocates buffer and retrieves all the items
|
|
// into that buffer
|
|
//
|
|
|
|
IEnumWiaItem *pEnum = NULL;
|
|
hr = m_pRootItem->EnumChildItems(&pEnum);
|
|
if (S_OK == hr) {
|
|
DWORD Count = 0;
|
|
pEnum->Reset();
|
|
IWiaItem *pIWiaItem = NULL;
|
|
while (SUCCEEDED(hr) && S_OK == pEnum->Next(1, &pIWiaItem, &Count)) {
|
|
hr = CollectImageItems(pIWiaItem, NULL, 0, &Count);
|
|
if (SUCCEEDED(hr)) {
|
|
m_NumImageItems += Count;
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
// Second pass .....
|
|
|
|
//
|
|
// m_NumImageItems has the number of image items
|
|
// Allocate buffer to hold all the image items
|
|
//
|
|
m_ImageItemArray = (IWiaItem**)CoTaskMemAlloc((sizeof(IWiaItem*) * m_NumImageItems));
|
|
if (m_ImageItemArray) {
|
|
IWiaItem **ppIWiaItems = NULL;
|
|
DWORD BufferSize = 0;
|
|
ppIWiaItems = m_ImageItemArray;
|
|
BufferSize = m_NumImageItems;
|
|
pEnum->Reset();
|
|
while (SUCCEEDED(hr) && S_OK == pEnum->Next(1, &pIWiaItem, &Count)) {
|
|
hr = CollectImageItems(pIWiaItem, ppIWiaItems,BufferSize, &Count);
|
|
if (SUCCEEDED(hr)) {
|
|
// advance the buffer
|
|
ppIWiaItems += Count;
|
|
// adjust the buffer size
|
|
BufferSize -= Count;
|
|
}
|
|
}
|
|
|
|
if (FAILED(hr)) {
|
|
m_NumImageItems -= BufferSize;
|
|
FreeAcquiredImages();
|
|
}
|
|
|
|
} else {
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWiaDevice::CollectImageItems(IWiaItem *pStartItem,IWiaItem **ItemList,
|
|
DWORD ItemListSize, DWORD *pCount)
|
|
{
|
|
DBG_FN_WIADEV(CWiaDevice::CollectImageItems());
|
|
HRESULT hr = S_OK;
|
|
DWORD Count = 0;
|
|
|
|
if (!pStartItem || (ItemListSize && !ItemList))
|
|
return E_INVALIDARG;
|
|
|
|
if (pStartItem) {
|
|
LONG ItemType = 0;
|
|
hr = pStartItem->GetItemType(&ItemType);
|
|
if (SUCCEEDED(hr)) {
|
|
if (ItemType & WiaItemTypeImage) {
|
|
|
|
//
|
|
// Count this is as an image item even though
|
|
// we may not have buffer to put it.
|
|
//
|
|
|
|
Count++;
|
|
|
|
if (ItemList && ItemListSize) {
|
|
|
|
//
|
|
// AddRef since will call Release on each item
|
|
// we ever receive
|
|
//
|
|
|
|
pStartItem->AddRef();
|
|
*ItemList = pStartItem;
|
|
ItemListSize--;
|
|
}
|
|
}
|
|
IEnumWiaItem *pEnum = NULL;
|
|
hr = pStartItem->EnumChildItems(&pEnum);
|
|
if (SUCCEEDED(hr)) {
|
|
IWiaItem *pChildItem = NULL;
|
|
DWORD ChildrenCount = 0;
|
|
pEnum->Reset();
|
|
while (SUCCEEDED(hr) && S_OK == pEnum->Next(1, &pChildItem, &ChildrenCount)) {
|
|
hr = CollectImageItems(pChildItem,&ItemList[Count],ItemListSize,&ChildrenCount);
|
|
if (SUCCEEDED(hr)) {
|
|
Count += ChildrenCount;
|
|
if (ItemListSize > ChildrenCount) {
|
|
ItemListSize -= ChildrenCount;
|
|
} else {
|
|
ItemListSize = 0;
|
|
ItemList = NULL;
|
|
}
|
|
}
|
|
}
|
|
pEnum->Release();
|
|
} else {
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
pStartItem->Release();
|
|
}
|
|
if (pCount)
|
|
*pCount = Count;
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWiaDevice::FreeAcquiredImages()
|
|
{
|
|
DBG_FN_WIADEV(CWiaDevice::FreeAcquiredImages());
|
|
HRESULT hr = S_OK;
|
|
if (m_ImageItemArray) {
|
|
DBG_TRC(("CWiaDevice::FreeAcquiredImages(), Freeing %d IWiaItems",m_NumImageItems));
|
|
for(LONG lItemIndex = 0; lItemIndex < m_NumImageItems; lItemIndex++){
|
|
if(NULL != m_ImageItemArray[lItemIndex]){
|
|
DBG_TRC(("CWiaDevice::FreeAcquiredImages(), Free IWiaItem (%d)",m_ImageItemArray[lItemIndex]));
|
|
m_ImageItemArray[lItemIndex]->Release();
|
|
m_ImageItemArray[lItemIndex] = NULL;
|
|
DBG_TRC(("CWiaDevice::FreeAcquiredImages(), Finished Freeing IWiaItem (%d)",lItemIndex));
|
|
}
|
|
}
|
|
CoTaskMemFree(m_ImageItemArray);
|
|
m_ImageItemArray = NULL;
|
|
m_NumImageItems = 0;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWiaDevice::GetNumAcquiredImages(LONG *pNumImages)
|
|
{
|
|
DBG_FN_WIADEV(CWiaDevice::GetNumAcquiredImages());
|
|
HRESULT hr = S_OK;
|
|
if (!pNumImages){
|
|
return E_INVALIDARG;
|
|
}
|
|
*pNumImages = m_NumImageItems;
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWiaDevice::GetAcquiredImageList(LONG lBufferSize,IWiaItem **ppIWiaItem,LONG *plActualSize)
|
|
{
|
|
DBG_FN_WIADEV(CWiaDevice::GetAcquiredImageList());
|
|
HRESULT hr = S_OK;
|
|
|
|
if (lBufferSize && !ppIWiaItem) {
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
if (lBufferSize >= m_NumImageItems) {
|
|
for (lBufferSize = 0; lBufferSize < m_NumImageItems; lBufferSize++) {
|
|
ppIWiaItem[lBufferSize] = m_ImageItemArray[lBufferSize];
|
|
}
|
|
} else {
|
|
hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
|
|
}
|
|
if (plActualSize) {
|
|
*plActualSize = m_NumImageItems;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWiaDevice::EnumAcquiredImage(DWORD Index,IWiaItem **ppIWiaItem)
|
|
{
|
|
DBG_FN_WIADEV(CWiaDevice::EnumAcquiredImages);
|
|
HRESULT hr = S_OK;
|
|
if (!ppIWiaItem) {
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
if (Index < (DWORD)m_NumImageItems) {
|
|
*ppIWiaItem = m_ImageItemArray[Index];
|
|
hr = S_OK;
|
|
} else {
|
|
hr = HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWiaDevice::GetImageInfo(IWiaItem *pIWiaItem,PMEMORY_TRANSFER_INFO pImageInfo)
|
|
{
|
|
DBG_FN_WIADEV(CWiaDevice::GetImageInfo());
|
|
if (!pIWiaItem || !pImageInfo)
|
|
return E_INVALIDARG;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
CWiahelper WIA;
|
|
hr = WIA.SetIWiaItem(pIWiaItem);
|
|
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetImageInfo(), failed to set IWiaItem for property reading"));
|
|
return hr;
|
|
}
|
|
|
|
hr = WIA.ReadPropertyLong(WIA_IPA_DATATYPE,&pImageInfo->mtiDataType);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPA_DATATYPE"));
|
|
return hr;
|
|
}
|
|
|
|
#ifdef SUPPORT_COMPRESSION_TYPES
|
|
|
|
hr = WIA.ReadPropertyLong(WIA_IPA_COMPRESSION,&pImageInfo->mtiCompression);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPA_COMPRESSION"));
|
|
return hr;
|
|
}
|
|
|
|
#else // SUPPORT_COMPRESSION_TYPES
|
|
|
|
pImageInfo->mtiCompression = WIA_COMPRESSION_NONE;
|
|
|
|
#endif // SUPPORT_COMPRESSION_TYPES
|
|
|
|
hr = WIA.ReadPropertyLong(WIA_IPA_CHANNELS_PER_PIXEL,&pImageInfo->mtiNumChannels);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPA_CHANNELS_PER_PIXEL"));
|
|
return hr;
|
|
}
|
|
|
|
hr = WIA.ReadPropertyLong(WIA_IPA_BITS_PER_CHANNEL,&pImageInfo->mtiBitsPerChannel[0]);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPA_BITS_PER_CHANNEL"));
|
|
return hr;
|
|
}
|
|
|
|
for(LONG i = 0; i<pImageInfo->mtiNumChannels; i++){
|
|
pImageInfo->mtiBitsPerChannel[i] = pImageInfo->mtiBitsPerChannel[0];
|
|
}
|
|
|
|
hr = WIA.ReadPropertyLong(WIA_IPA_PIXELS_PER_LINE,&pImageInfo->mtiWidthPixels);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPA_PIXELS_PER_LINE"));
|
|
return hr;
|
|
}
|
|
|
|
hr = WIA.ReadPropertyLong(WIA_IPA_BYTES_PER_LINE,&pImageInfo->mtiBytesPerLine);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPA_BYTES_PER_LINE"));
|
|
return hr;
|
|
}
|
|
|
|
hr = WIA.ReadPropertyLong(WIA_IPA_PLANAR,&pImageInfo->mtiPlanar);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPA_PLANAR"));
|
|
return hr;
|
|
}
|
|
|
|
hr = WIA.ReadPropertyLong(WIA_IPA_NUMBER_OF_LINES,&pImageInfo->mtiHeightPixels);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPA_NUMBER_OF_LINES"));
|
|
return hr;
|
|
}
|
|
|
|
hr = WIA.ReadPropertyLong(WIA_IPA_DEPTH,&pImageInfo->mtiBitsPerPixel);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPA_DEPTH"));
|
|
return hr;
|
|
}
|
|
|
|
hr = WIA.ReadPropertyLong(WIA_IPS_XRES,&pImageInfo->mtiXResolution);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPS_XRES"));
|
|
return hr;
|
|
} else if (S_FALSE == hr) {
|
|
DBG_WRN(("CWiaDevice::GetImageInfo(), S_FALSE was returned from reading X Resolution, defaulting to 300 dpi (dummy value)"));
|
|
// set default
|
|
pImageInfo->mtiXResolution = 300;
|
|
}
|
|
|
|
hr = WIA.ReadPropertyLong(WIA_IPS_YRES,&pImageInfo->mtiYResolution);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPS_YRES"));
|
|
return hr;
|
|
} else if (S_FALSE == hr) {
|
|
DBG_WRN(("CWiaDevice::GetImageInfo(), S_FALSE was returned from reading Y Resolution, defaulting to 300 dpi (dummy value)"));
|
|
// set default
|
|
pImageInfo->mtiYResolution = 300;
|
|
}
|
|
|
|
hr = WIA.ReadPropertyGUID(WIA_IPA_FORMAT,&pImageInfo->mtiguidFormat);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetImageInfo(), failed to read WIA_IPA_FORMAT"));
|
|
return hr;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWiaDevice::GetThumbnailImageInfo(IWiaItem *pIWiaItem,PMEMORY_TRANSFER_INFO pImageInfo)
|
|
{
|
|
DBG_FN_WIADEV(CWiaDevice::GetThumbnailImageInfo());
|
|
if (!pIWiaItem || !pImageInfo)
|
|
return E_INVALIDARG;
|
|
|
|
HRESULT hr = S_OK;
|
|
CWiahelper WIA;
|
|
hr = WIA.SetIWiaItem(pIWiaItem);
|
|
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetThumbnailImageInfo(), failed to set IWiaItem for property reading"));
|
|
return hr;
|
|
}
|
|
|
|
hr = WIA.ReadPropertyLong(WIA_IPC_THUMB_WIDTH,&pImageInfo->mtiWidthPixels);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetThumbnailImageInfo(), failed to read WIA_IPC_THUMB_WIDTH"));
|
|
return hr;
|
|
}
|
|
|
|
hr = WIA.ReadPropertyLong(WIA_IPC_THUMB_HEIGHT,&pImageInfo->mtiHeightPixels);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetThumbnailImageInfo(), failed to read WIA_IPC_THUMB_HEIGHT"));
|
|
return hr;
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Thumbnail is always in 24bits color in DIB format without
|
|
// BITMAPINFO header.
|
|
//
|
|
|
|
pImageInfo->mtiNumChannels = 3;
|
|
pImageInfo->mtiBitsPerChannel[0] = 8;
|
|
pImageInfo->mtiBitsPerChannel[1] = 8;
|
|
pImageInfo->mtiBitsPerChannel[2] = 8;
|
|
pImageInfo->mtiBitsPerPixel = 24;
|
|
pImageInfo->mtiPlanar = FALSE;
|
|
pImageInfo->mtiBytesPerLine = (pImageInfo->mtiWidthPixels * 24/8 + 3) / 4;
|
|
pImageInfo->mtiCompression = WIA_COMPRESSION_NONE;
|
|
pImageInfo->mtiXResolution = 75;
|
|
pImageInfo->mtiYResolution = 75;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWiaDevice::GetImageRect(IWiaItem *pIWiaItem,LPRECT pRect)
|
|
{
|
|
DBG_FN_WIADEV(CWiaDevice::GetImageRect());
|
|
if (!pRect || !pIWiaItem)
|
|
return E_INVALIDARG;
|
|
|
|
HRESULT hr = S_OK;
|
|
LONG lXPos = 0;
|
|
LONG lYPos = 0;
|
|
LONG lXExtent = 0;
|
|
LONG lYExtent = 0;
|
|
|
|
CWiahelper WIA;
|
|
hr = WIA.SetIWiaItem(pIWiaItem);
|
|
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetImageRect(), failed to set IWiaItem for property reading"));
|
|
return hr;
|
|
}
|
|
|
|
hr = WIA.ReadPropertyLong(WIA_IPS_XPOS,&lXPos);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetImageRect(), failed to read WIA_IPS_XPOS"));
|
|
return hr;
|
|
}
|
|
hr = WIA.ReadPropertyLong(WIA_IPS_YPOS,&lYPos);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetImageRect(), failed to read WIA_IPS_YPOS"));
|
|
return hr;
|
|
}
|
|
hr = WIA.ReadPropertyLong(WIA_IPS_XEXTENT,&lXExtent);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetImageRect(), failed to read WIA_IPS_XEXTENT"));
|
|
return hr;
|
|
}
|
|
hr = WIA.ReadPropertyLong(WIA_IPS_YEXTENT,&lYExtent);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetImageRect(), failed to read WIA_IPS_YEXTENT"));
|
|
return hr;
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
pRect->left = lXPos;
|
|
pRect->right = lXExtent + lXPos - 1;
|
|
pRect->top = lYPos;
|
|
pRect->bottom = lYExtent + lYPos - 1;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWiaDevice::GetThumbnailRect(IWiaItem *pIWiaItem,LPRECT pRect)
|
|
{
|
|
DBG_FN_WIADEV(CWiaDevice::GetThumbnailRect());
|
|
if (!pIWiaItem || !pRect)
|
|
return E_INVALIDARG;
|
|
|
|
HRESULT hr = S_OK;
|
|
LONG lWidth = 0;
|
|
LONG lHeight = 0;
|
|
CWiahelper WIA;
|
|
hr = WIA.SetIWiaItem(pIWiaItem);
|
|
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetThumbnailRect(), failed to set IWiaItem for property reading"));
|
|
return hr;
|
|
}
|
|
|
|
hr = WIA.ReadPropertyLong(WIA_IPC_THUMB_WIDTH,&lWidth);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetThumbnailRect(), failed to read WIA_IPC_THUMB_WIDTH"));
|
|
return hr;
|
|
}
|
|
|
|
hr = WIA.ReadPropertyLong(WIA_IPC_THUMB_HEIGHT,&lHeight);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetThumbnailRect(), failed to read WIA_IPC_THUMB_HEIGHT"));
|
|
return hr;
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
pRect->left = 0;
|
|
pRect->top = 0;
|
|
pRect->right = lWidth - 1;
|
|
pRect->bottom = lHeight - 1;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWiaDevice::LoadImage(IWiaItem *pIWiaItem,GUID guidFormatID,IWiaDataCallback *pIDataCB)
|
|
{
|
|
DBG_FN_WIADEV(CWiaDevice::LoadImage());
|
|
HRESULT hr = S_OK;
|
|
if (!pIWiaItem || !pIDataCB) {
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
CWiahelper WIA;
|
|
hr = WIA.SetIWiaItem(pIWiaItem);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::LoadImage(), failed to set IWiaItem for property writing"));
|
|
return hr;
|
|
}
|
|
|
|
IWiaDataTransfer *pDataTransfer = NULL;
|
|
hr = pIWiaItem->QueryInterface(IID_IWiaDataTransfer,(void**)&pDataTransfer);
|
|
if (S_OK == hr) {
|
|
|
|
//
|
|
// write TYMED
|
|
//
|
|
|
|
hr = WIA.WritePropertyLong(WIA_IPA_TYMED,TYMED_CALLBACK);
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaDevice::LoadImage(), failed to write WIA_IPA_TYMED"));
|
|
|
|
//
|
|
// release IWiaDataTransfer Interface, (we are bailing early)
|
|
//
|
|
|
|
pDataTransfer->Release();
|
|
pDataTransfer = NULL;
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// write format
|
|
//
|
|
|
|
hr = WIA.WritePropertyGUID(WIA_IPA_FORMAT, guidFormatID);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::LoadImage(), failed to write WIA_IPA_FORMAT"));
|
|
|
|
//
|
|
// release IWiaDataTransfer Interface, (we are bailing early)
|
|
//
|
|
|
|
pDataTransfer->Release();
|
|
pDataTransfer = NULL;
|
|
return hr;
|
|
}
|
|
|
|
|
|
LONG BufferSize = DEFAULT_BUFFER_SIZE;
|
|
hr = WIA.ReadPropertyLong(WIA_IPA_MIN_BUFFER_SIZE, &BufferSize);
|
|
if (FAILED(hr)) {
|
|
DBG_WRN(("CWiaDevice::LoadImage(), failed to read WIA_IPA_MIN_BUFFER_SIZE, (defaulting to %d)",DEFAULT_BUFFER_SIZE));
|
|
BufferSize = DEFAULT_BUFFER_SIZE;
|
|
}
|
|
|
|
//
|
|
// Before we do the blocking call, we need to temporarily disable
|
|
// the registered IMessageFilter (if any). We do this primarily
|
|
// for MFC based apps, as in some situations they can put up
|
|
// the "Server Busy" dialog when things are fine -- it's just
|
|
// taking a while to scan, etc. Unfortunately, we can't detect
|
|
// if it's MFC's IMessageFilter we're disabling. Apps can actually
|
|
// do interesting work in IMessageFilter, but it's not likely. This
|
|
// is a risk we're taking by nuking the message filter for the duration
|
|
// of the transfer.
|
|
//
|
|
|
|
// Nb: Note we ignore result of this call. It is generally harmless, but asserting it
|
|
// may be useful
|
|
|
|
g_pOldOleMessageFilter = NULL;
|
|
HRESULT hr_ServerBusyFix = S_OK;
|
|
hr_ServerBusyFix = ::CoRegisterMessageFilter( NULL, &g_pOldOleMessageFilter );
|
|
if(FAILED(hr_ServerBusyFix)){
|
|
DBG_WRN(("CWiaDevice::LoadImage(), failed to (Saving IMessageFilter) CoRegisterMessageFilter..(Server Busy code fix)"));
|
|
}
|
|
|
|
WIA_DATA_TRANSFER_INFO wiadtInfo;
|
|
memset(&wiadtInfo,0,sizeof(wiadtInfo));
|
|
wiadtInfo.ulSize = sizeof(wiadtInfo);
|
|
wiadtInfo.ulBufferSize = BufferSize * 4;
|
|
|
|
//
|
|
// acquire data from the IWiaItem
|
|
//
|
|
|
|
hr = pDataTransfer->idtGetBandedData(&wiadtInfo, pIDataCB);
|
|
|
|
//
|
|
// Restore the old IMessageFilter if there was one
|
|
//
|
|
|
|
if (g_pOldOleMessageFilter) {
|
|
hr_ServerBusyFix = ::CoRegisterMessageFilter( g_pOldOleMessageFilter, NULL );
|
|
if(FAILED(hr_ServerBusyFix)){
|
|
DBG_WRN(("CWiaDevice::LoadImage(), failed to (Restoring IMessageFilter) CoRegisterMessageFilter..(Server Busy code fix)"));
|
|
}
|
|
g_pOldOleMessageFilter = NULL;
|
|
}
|
|
|
|
//
|
|
// release IWiaDataTransfer Interface
|
|
//
|
|
|
|
pDataTransfer->Release();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWiaDevice::LoadImageToDisk(IWiaItem *pIWiaItem,CHAR *pFileName, GUID guidFormatID,IWiaDataCallback *pIDataCB)
|
|
{
|
|
DBG_FN_WIADEV(CWiaDevice::LoadImage());
|
|
HRESULT hr = S_OK;
|
|
if (!pIWiaItem || !pIDataCB || !pFileName) {
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
CWiahelper WIA;
|
|
hr = WIA.SetIWiaItem(pIWiaItem);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::LoadImageToDisk(), failed to set IWiaItem for property writing"));
|
|
return hr;
|
|
}
|
|
|
|
IWiaDataTransfer *pDataTransfer = NULL;
|
|
hr = pIWiaItem->QueryInterface(IID_IWiaDataTransfer,(void**)&pDataTransfer);
|
|
if (S_OK == hr) {
|
|
|
|
//
|
|
// write TYMED
|
|
//
|
|
|
|
hr = WIA.WritePropertyLong(WIA_IPA_TYMED,TYMED_FILE);
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaDevice::LoadImageToDisk(), failed to write WIA_IPA_TYMED"));
|
|
|
|
//
|
|
// release IWiaDataTransfer Interface, (we are bailing early)
|
|
//
|
|
|
|
pDataTransfer->Release();
|
|
pDataTransfer = NULL;
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// write format
|
|
//
|
|
|
|
hr = WIA.WritePropertyGUID(WIA_IPA_FORMAT, guidFormatID);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::LoadImageToDisk(), failed to write WIA_IPA_FORMAT"));
|
|
|
|
//
|
|
// release IWiaDataTransfer Interface, (we are bailing early)
|
|
//
|
|
|
|
pDataTransfer->Release();
|
|
pDataTransfer = NULL;
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Before we do the blocking call, we need to temporarily disable
|
|
// the registered IMessageFilter (if any). We do this primarily
|
|
// for MFC based apps, as in some situations they can put up
|
|
// the "Server Busy" dialog when things are fine -- it's just
|
|
// taking a while to scan, etc. Unfortunately, we can't detect
|
|
// if it's MFC's IMessageFilter we're disabling. Apps can actually
|
|
// do interesting work in IMessageFilter, but it's not likely. This
|
|
// is a risk we're taking by nuking the message filter for the duration
|
|
// of the transfer.
|
|
//
|
|
|
|
// Nb: Note we ignore result of this call. It is generally harmless, but asserting it
|
|
// may be useful
|
|
|
|
g_pOldOleMessageFilter = NULL;
|
|
HRESULT hr_ServerBusyFix = S_OK;
|
|
hr_ServerBusyFix = ::CoRegisterMessageFilter( NULL, &g_pOldOleMessageFilter );
|
|
if(FAILED(hr_ServerBusyFix)){
|
|
DBG_WRN(("CWiaDevice::LoadImageToDisk(), failed to (Saving IMessageFilter) CoRegisterMessageFilter..(Server Busy code fix)"));
|
|
}
|
|
|
|
//
|
|
// load the StgMedium
|
|
//
|
|
|
|
WCHAR wszFileName[MAX_PATH];
|
|
memset(wszFileName,0,sizeof(wszFileName));
|
|
MultiByteToWideChar(CP_ACP, 0,pFileName,-1,wszFileName,(sizeof(wszFileName)/sizeof(wszFileName[0])));
|
|
|
|
STGMEDIUM StgMedium;
|
|
memset(&StgMedium,0,sizeof(StgMedium));
|
|
|
|
StgMedium.tymed = TYMED_FILE;
|
|
StgMedium.pUnkForRelease = NULL;
|
|
StgMedium.hGlobal = NULL;
|
|
StgMedium.lpszFileName = wszFileName;
|
|
|
|
//
|
|
// acquire data from the IWiaItem
|
|
//
|
|
|
|
hr = pDataTransfer->idtGetData(&StgMedium, pIDataCB);
|
|
|
|
//
|
|
// Restore the old IMessageFilter if there was one
|
|
//
|
|
|
|
if (g_pOldOleMessageFilter) {
|
|
hr_ServerBusyFix = ::CoRegisterMessageFilter( g_pOldOleMessageFilter, NULL );
|
|
if(FAILED(hr_ServerBusyFix)){
|
|
DBG_WRN(("CWiaDevice::LoadImageToDisk(), failed to (Restoring IMessageFilter) CoRegisterMessageFilter..(Server Busy code fix)"));
|
|
}
|
|
g_pOldOleMessageFilter = NULL;
|
|
}
|
|
|
|
//
|
|
// release IWiaDataTransfer Interface
|
|
//
|
|
|
|
pDataTransfer->Release();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWiaDevice::GetBasicScannerInfo(PBASIC_INFO pBasicInfo)
|
|
{
|
|
if (!pBasicInfo || pBasicInfo->Size < sizeof(BASIC_INFO))
|
|
return E_INVALIDARG;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
LONG lDocumentHandlingCapabilites = 0;
|
|
LONG lHorizontalBedSize = 0;
|
|
LONG lVerticalBedSize = 0;
|
|
LONG lXOpticalResolution = 0;
|
|
LONG lYOpticalResolution = 0;
|
|
|
|
pBasicInfo->FeederCaps = 0;
|
|
pBasicInfo->xBedSize = 0;
|
|
pBasicInfo->xOpticalRes = 0;
|
|
pBasicInfo->yOpticalRes = 0;
|
|
pBasicInfo->yBedSize = 0;
|
|
|
|
CWiahelper WIA;
|
|
hr = WIA.SetIWiaItem(m_pRootItem);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetBasicScannerInfo(), failed to set IWiaItem for property reading"));
|
|
return hr;
|
|
}
|
|
|
|
hr = WIA.ReadPropertyLong(WIA_DPS_DOCUMENT_HANDLING_CAPABILITIES,&lDocumentHandlingCapabilites);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetBasicScannerInfo(), failed to read WIA_DPS_DOCUMENT_HANDLING_CAPABILITIES"));
|
|
return hr;
|
|
}
|
|
|
|
pBasicInfo->FeederCaps = (TW_UINT32)lDocumentHandlingCapabilites;
|
|
|
|
hr = WIA.ReadPropertyLong(WIA_DPS_OPTICAL_XRES,&lXOpticalResolution);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetBasicScannerInfo(), failed to read WIA_DPS_OPTICAL_XRES"));
|
|
return hr;
|
|
}
|
|
|
|
|
|
pBasicInfo->xOpticalRes = (TW_UINT32)lXOpticalResolution;
|
|
|
|
hr = WIA.ReadPropertyLong(WIA_DPS_OPTICAL_YRES,&lYOpticalResolution);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetBasicScannerInfo(), failed to read WIA_DPS_OPTICAL_YRES"));
|
|
return hr;
|
|
}
|
|
|
|
pBasicInfo->yOpticalRes = (TW_UINT32)lYOpticalResolution;
|
|
|
|
hr = WIA.ReadPropertyLong(WIA_DPS_HORIZONTAL_BED_SIZE,&lHorizontalBedSize);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetBasicScannerInfo(), failed to read WIA_DPS_HORIZONTAL_BED_SIZE"));
|
|
return hr;
|
|
} else if(S_FALSE == hr){
|
|
DBG_WRN(("CWiaDevice::GetBasicScannerInfo(), WIA_DPS_HORIZONTAL_BED_SIZE property not found"));
|
|
hr = WIA.ReadPropertyLong(WIA_DPS_HORIZONTAL_SHEET_FEED_SIZE,&lHorizontalBedSize);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetBasicScannerInfo(), failed to read WIA_DPS_HORIZONTAL_SHEET_FEED_SIZE"));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
pBasicInfo->xBedSize = lHorizontalBedSize;
|
|
|
|
hr = WIA.ReadPropertyLong(WIA_DPS_VERTICAL_BED_SIZE,&lVerticalBedSize);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetBasicScannerInfo(), failed to read WIA_DPS_VERTICAL_BED_SIZE"));
|
|
return hr;
|
|
} else if(S_FALSE == hr){
|
|
DBG_WRN(("CWiaDevice::GetBasicScannerInfo(), WIA_DPS_VERTICAL_BED_SIZE property not found"));
|
|
hr = WIA.ReadPropertyLong(WIA_DPS_VERTICAL_SHEET_FEED_SIZE,&lVerticalBedSize);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::GetBasicScannerInfo(), failed to read WIA_DPS_VERTICAL_SHEET_FEED_SIZE"));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
pBasicInfo->yBedSize = lVerticalBedSize;
|
|
|
|
return hr;
|
|
}
|
|
|
|
BOOL CWiaDevice::TwainCapabilityPassThrough()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
LONG lRootItemFlags = 0;
|
|
|
|
CWiahelper WIA;
|
|
hr = WIA.SetIWiaItem(m_pRootItem);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::TwainCapabilityPassThrough(), failed to set IWiaItem for property reading"));
|
|
return FALSE;
|
|
}
|
|
|
|
hr = WIA.ReadPropertyLong(WIA_IPA_ITEM_FLAGS,&lRootItemFlags);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::TwainCapabilityPassThrough(), failed to read WIA_IPA_ITEM_FLAGS"));
|
|
return FALSE;
|
|
}
|
|
|
|
return (lRootItemFlags & WiaItemTypeTwainCapabilityPassThrough);
|
|
}
|
|
|
|
HRESULT CWiaDevice::LoadThumbnail(IWiaItem *pIWiaItem,HGLOBAL *phThumbnail,ULONG *pThumbnailSize)
|
|
{
|
|
DBG_FN_WIADEV(CWiaDevice::LoadThumbnail());
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!phThumbnail || !pIWiaItem)
|
|
return E_INVALIDARG;
|
|
|
|
*phThumbnail = NULL;
|
|
HGLOBAL hThumbnail = NULL;
|
|
|
|
CWiahelper WIA;
|
|
hr = WIA.SetIWiaItem(pIWiaItem);
|
|
if(FAILED(hr)){
|
|
DBG_ERR(("CWiaDevice::LoadThumbnail(), failed to set IWiaItem for property writing"));
|
|
return hr;
|
|
}
|
|
|
|
LONG ThumbWidth = 0;
|
|
LONG ThumbHeight = 0;
|
|
hr = WIA.ReadPropertyLong(WIA_IPC_THUMB_WIDTH, &ThumbWidth);
|
|
if (SUCCEEDED(hr)) {
|
|
hr = WIA.ReadPropertyLong(WIA_IPC_THUMB_HEIGHT, &ThumbHeight);
|
|
if (SUCCEEDED(hr)) {
|
|
LONG lDataSize = 0;
|
|
BYTE* pThumbData = NULL;
|
|
hr = WIA.ReadPropertyData(WIA_IPC_THUMBNAIL,&pThumbData,&lDataSize);
|
|
if (SUCCEEDED(hr)) {
|
|
hThumbnail = NULL;
|
|
hThumbnail = GlobalAlloc(GHND, (lDataSize + sizeof(BITMAPINFOHEADER)));
|
|
if (hThumbnail) {
|
|
BITMAPINFOHEADER *pbmih = NULL;
|
|
pbmih = (BITMAPINFOHEADER*)GlobalLock(hThumbnail);
|
|
if (pbmih) {
|
|
|
|
DBG_TRC(("CWiaDevice::LoadThumbnail(), Reported thumbnail information"));
|
|
DBG_TRC(("Width = %d",ThumbWidth));
|
|
DBG_TRC(("Height = %d",ThumbHeight));
|
|
DBG_TRC(("Data Size = %d",lDataSize));
|
|
|
|
//
|
|
// Initialize the BITMAPINFOHEADER
|
|
//
|
|
|
|
pbmih->biSize = sizeof(BITMAPINFOHEADER);
|
|
pbmih->biWidth = ThumbWidth;
|
|
pbmih->biHeight = ThumbHeight;
|
|
pbmih->biPlanes = 1;
|
|
pbmih->biBitCount = 24;
|
|
pbmih->biCompression = BI_RGB;
|
|
pbmih->biSizeImage = lDataSize;
|
|
pbmih->biXPelsPerMeter = 0;
|
|
pbmih->biYPelsPerMeter = 0;
|
|
pbmih->biClrUsed = 0;
|
|
pbmih->biClrImportant = 0;
|
|
|
|
//
|
|
// Copy the bits. The bits buffer is right after
|
|
// the header.
|
|
//
|
|
|
|
BYTE *pDst = (BYTE*)pbmih;
|
|
pDst = pDst + sizeof(BITMAPINFOHEADER);
|
|
memcpy(pDst, pThumbData,lDataSize);
|
|
GlobalUnlock(hThumbnail);
|
|
*phThumbnail = hThumbnail;
|
|
|
|
if (pThumbnailSize){
|
|
*pThumbnailSize = (lDataSize + sizeof(BITMAPINFOHEADER));
|
|
}
|
|
} else {
|
|
GlobalFree(hThumbnail);
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
} else {
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
//
|
|
// free any temporary buffers
|
|
//
|
|
|
|
if (pThumbData) {
|
|
DBG_TRC(("CWiaDevice::LoadThumbnail(), freeing temporary thumbnail buffer"));
|
|
GlobalFree(pThumbData);
|
|
pThumbData = NULL;
|
|
DBG_TRC(("CWiaDevice::LoadThumbnail(), finished freeing temporary thumbnail buffer"));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// CWiaEventCallback object implementation
|
|
//
|
|
|
|
HRESULT CWiaEventCallback::ImageEventCallback(const GUID *pEventGuid,BSTR bstrEventDescription,
|
|
BSTR bstrDeviceId,BSTR bstrDeviceDescription,
|
|
DWORD dwDeviceType,BSTR bstrFullItemName,
|
|
ULONG *pulEventType,ULONG ulReserved)
|
|
{
|
|
DBG_FN_WIADEV(CWiaEventCallback::ImageEventCallback);
|
|
//
|
|
// translate WIA event guid to event code.
|
|
// Note that we do not verify device id here because
|
|
// we will not receive events not meant for the device this
|
|
// object was created for.
|
|
//
|
|
|
|
if (m_pfnCallback && WIA_EVENT_DEVICE_DISCONNECTED == *pEventGuid) {
|
|
return(*m_pfnCallback)(0, m_CallbackParam);
|
|
}
|
|
return S_OK;
|
|
}
|