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.
 
 
 
 
 
 

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