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.
1110 lines
35 KiB
1110 lines
35 KiB
/*******************************************************************************
|
|
*
|
|
* (C) COPYRIGHT 2001, MICROSOFT CORP.
|
|
*
|
|
* TITLE: Child.cpp
|
|
*
|
|
* VERSION: 1.0
|
|
*
|
|
* DATE: 15 Nov, 2000
|
|
*
|
|
* DESCRIPTION:
|
|
* This file implements the helper methods for IWiaMiniDrv for child items.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#include "pch.h"
|
|
|
|
// extern FORMAT_INFO *g_FormatInfo;
|
|
// extern UINT g_NumFormatInfo;
|
|
|
|
/**************************************************************************\
|
|
* BuildChildItemProperties
|
|
*
|
|
* This helper creates the properties for a child item.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pWiasContext - WIA service context
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT CWiaCameraDevice::BuildChildItemProperties(
|
|
BYTE *pWiasContext
|
|
)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWiaCameraDevice::BuildChildItemProperties");
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
BOOL bBitmap;
|
|
FORMAT_INFO *pFormatInfo;
|
|
LONG pTymedArray[] = { TYMED_FILE, TYMED_CALLBACK };
|
|
GUID *pFormatArray = NULL;
|
|
|
|
BSTR bstrFileExt = NULL;
|
|
|
|
|
|
//
|
|
// Get the driver item context
|
|
//
|
|
ITEM_CONTEXT *pItemCtx;
|
|
hr = GetDrvItemContext(pWiasContext, &pItemCtx);
|
|
if (FAILED(hr))
|
|
{
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildChildItemProperties, GetDrvItemContext failed"));
|
|
return hr;
|
|
}
|
|
|
|
ITEM_INFO *pItemInfo = pItemCtx->ItemHandle;
|
|
|
|
//
|
|
// Set up properties that are used for all item types
|
|
//
|
|
CWiauPropertyList ItemProps;
|
|
|
|
const INT NUM_ITEM_PROPS = 21;
|
|
hr = ItemProps.Init(NUM_ITEM_PROPS);
|
|
if (FAILED(hr))
|
|
{
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildChildItemProperties, iten prop Init failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
|
|
INT index;
|
|
|
|
//
|
|
// WIA_IPA_ITEM_TIME
|
|
//
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPA_ITEM_TIME, WIA_IPA_ITEM_TIME_STR,
|
|
WIA_PROP_READ, WIA_PROP_NONE);
|
|
if (FAILED(hr)) goto failure;
|
|
|
|
ItemProps.SetCurrentValue(index, &pItemInfo->Time);
|
|
|
|
//
|
|
// WIA_IPA_ACCESS_RIGHTS
|
|
//
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPA_ACCESS_RIGHTS, WIA_IPA_ACCESS_RIGHTS_STR,
|
|
WIA_PROP_READ, WIA_PROP_FLAG);
|
|
if (FAILED(hr)) goto failure;
|
|
|
|
//
|
|
// If device supports changing the read-only status, item access rights is r/w
|
|
//
|
|
LONG AccessRights;
|
|
if (pItemInfo->bReadOnly)
|
|
AccessRights = WIA_ITEM_READ;
|
|
else
|
|
AccessRights = WIA_ITEM_RD;
|
|
|
|
if (pItemInfo->bCanSetReadOnly)
|
|
{
|
|
ItemProps.SetAccessSubType(index, WIA_PROP_RW, WIA_PROP_FLAG);
|
|
ItemProps.SetValidValues(index, AccessRights, AccessRights, WIA_ITEM_RD);
|
|
}
|
|
else
|
|
{
|
|
ItemProps.SetCurrentValue(index, AccessRights);
|
|
}
|
|
|
|
//
|
|
// Set up non-folder properties
|
|
//
|
|
if (!(pItemInfo->bIsFolder))
|
|
{
|
|
//
|
|
// WIA_IPA_PREFERRED_FORMAT
|
|
//
|
|
pFormatInfo = FormatCode2FormatInfo(pItemInfo->Format);
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPA_PREFERRED_FORMAT, WIA_IPA_PREFERRED_FORMAT_STR,
|
|
WIA_PROP_READ, WIA_PROP_NONE);
|
|
if (FAILED(hr)) goto failure;
|
|
ItemProps.SetCurrentValue(index, &(pFormatInfo->FormatGuid));
|
|
|
|
bBitmap = IsEqualGUID(WiaImgFmt_BMP, pFormatInfo->FormatGuid);
|
|
|
|
//
|
|
// WIA_IPA_FILENAME_EXTENSION
|
|
//
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPA_FILENAME_EXTENSION, WIA_IPA_FILENAME_EXTENSION_STR,
|
|
WIA_PROP_READ, WIA_PROP_NONE);
|
|
if (FAILED(hr)) goto failure;
|
|
if( pFormatInfo->ExtensionString[0] )
|
|
{
|
|
bstrFileExt = SysAllocString(pFormatInfo->ExtensionString);
|
|
}
|
|
else // unknown file extension, get it from filename
|
|
{
|
|
WCHAR *pwcsTemp = wcsrchr(pItemInfo->pName, L'.');
|
|
if( pwcsTemp )
|
|
{
|
|
bstrFileExt = SysAllocString(pwcsTemp+1);
|
|
}
|
|
else
|
|
{
|
|
bstrFileExt = SysAllocString(pFormatInfo->ExtensionString);
|
|
}
|
|
}
|
|
ItemProps.SetCurrentValue(index, bstrFileExt);
|
|
|
|
//
|
|
// WIA_IPA_TYMED
|
|
//
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPA_TYMED, WIA_IPA_TYMED_STR,
|
|
WIA_PROP_RW, WIA_PROP_LIST);
|
|
if (FAILED(hr)) goto failure;
|
|
ItemProps.SetValidValues(index, TYMED_FILE, TYMED_FILE,
|
|
sizeof(pTymedArray) / sizeof(pTymedArray[0]), pTymedArray);
|
|
|
|
//
|
|
// WIA_IPA_FORMAT
|
|
//
|
|
// First call drvGetWiaFormatInfo to get the valid formats
|
|
//
|
|
int NumFormats = 0;
|
|
GUID *pFormatArray = NULL;
|
|
hr = GetValidFormats(pWiasContext, TYMED_FILE, &NumFormats, &pFormatArray);
|
|
if (FAILED(hr) || NumFormats == 0)
|
|
{
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildChildItemProperties, GetValidFormats failed"));
|
|
goto failure;
|
|
}
|
|
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPA_FORMAT, WIA_IPA_FORMAT_STR,
|
|
WIA_PROP_RW, WIA_PROP_LIST);
|
|
if (FAILED(hr)) goto failure;
|
|
ItemProps.SetValidValues(index, &(pFormatInfo->FormatGuid), &(pFormatInfo->FormatGuid),
|
|
NumFormats, &pFormatArray);
|
|
|
|
//
|
|
// WIA_IPA_COMPRESSION
|
|
//
|
|
// This property is mainly used by scanners. Set to no compression.
|
|
//
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPA_COMPRESSION, WIA_IPA_COMPRESSION_STR,
|
|
WIA_PROP_READ, WIA_PROP_NONE);
|
|
if (FAILED(hr)) goto failure;
|
|
ItemProps.SetCurrentValue(index, (LONG) WIA_COMPRESSION_NONE);
|
|
|
|
//
|
|
// WIA_IPA_ITEM_SIZE
|
|
//
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPA_ITEM_SIZE, WIA_IPA_ITEM_SIZE_STR,
|
|
WIA_PROP_READ, WIA_PROP_NONE);
|
|
if (FAILED(hr)) goto failure;
|
|
|
|
ItemProps.SetCurrentValue(index, pItemInfo->Size);
|
|
|
|
//
|
|
// WIA_IPA_MIN_BUFFER_SIZE
|
|
//
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPA_MIN_BUFFER_SIZE, WIA_IPA_MIN_BUFFER_SIZE_STR,
|
|
WIA_PROP_READ, WIA_PROP_NONE);
|
|
if (FAILED(hr)) goto failure;
|
|
|
|
LONG minBufSize;
|
|
if (!bBitmap && pItemInfo->Size > 0)
|
|
minBufSize = min(MIN_BUFFER_SIZE, pItemInfo->Size);
|
|
else
|
|
minBufSize = MIN_BUFFER_SIZE;
|
|
ItemProps.SetCurrentValue(index, minBufSize);
|
|
|
|
}
|
|
|
|
//
|
|
// Set up the image-only properties
|
|
//
|
|
if (m_FormatInfo[pItemInfo->Format].ItemType == ITEMTYPE_IMAGE)
|
|
{
|
|
//
|
|
// WIA_IPA_DATATYPE
|
|
//
|
|
// This property is mainly used by scanners. Set to color since most camera
|
|
// images will be color.
|
|
//
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPA_DATATYPE, WIA_IPA_DATATYPE_STR,
|
|
WIA_PROP_READ, WIA_PROP_NONE);
|
|
if (FAILED(hr)) goto failure;
|
|
ItemProps.SetCurrentValue(index, (LONG) WIA_DATA_COLOR);
|
|
|
|
//
|
|
// WIA_IPA_PLANAR
|
|
//
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPA_PLANAR, WIA_IPA_PLANAR_STR,
|
|
WIA_PROP_READ, WIA_PROP_NONE);
|
|
if (FAILED(hr)) goto failure;
|
|
ItemProps.SetCurrentValue(index, (LONG) WIA_PACKED_PIXEL);
|
|
|
|
//
|
|
// WIA_IPA_DEPTH
|
|
//
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPA_DEPTH, WIA_IPA_DEPTH_STR,
|
|
WIA_PROP_READ, WIA_PROP_NONE);
|
|
if (FAILED(hr)) goto failure;
|
|
ItemProps.SetCurrentValue(index, pItemInfo->Depth);
|
|
|
|
//
|
|
// WIA_IPA_CHANNELS_PER_PIXEL
|
|
//
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPA_CHANNELS_PER_PIXEL, WIA_IPA_CHANNELS_PER_PIXEL_STR,
|
|
WIA_PROP_READ, WIA_PROP_NONE);
|
|
if (FAILED(hr)) goto failure;
|
|
ItemProps.SetCurrentValue(index, pItemInfo->Channels);
|
|
|
|
//
|
|
// WIA_IPA_BITS_PER_CHANNEL
|
|
//
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPA_BITS_PER_CHANNEL, WIA_IPA_BITS_PER_CHANNEL_STR,
|
|
WIA_PROP_READ, WIA_PROP_NONE);
|
|
if (FAILED(hr)) goto failure;
|
|
ItemProps.SetCurrentValue(index, pItemInfo->BitsPerChannel);
|
|
|
|
|
|
//
|
|
// WIA_IPA_PIXELS_PER_LINE
|
|
//
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPA_PIXELS_PER_LINE, WIA_IPA_PIXELS_PER_LINE_STR,
|
|
WIA_PROP_READ, WIA_PROP_NONE);
|
|
if (FAILED(hr)) goto failure;
|
|
ItemProps.SetCurrentValue(index, pItemInfo->Width);
|
|
|
|
//
|
|
// WIA_IPA_BYTES_PER_LINE
|
|
//
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPA_BYTES_PER_LINE, WIA_IPA_BYTES_PER_LINE_STR,
|
|
WIA_PROP_READ, WIA_PROP_NONE);
|
|
if (FAILED(hr)) goto failure;
|
|
|
|
if (bBitmap)
|
|
ItemProps.SetCurrentValue(index, pItemInfo->Width * 3);
|
|
else
|
|
ItemProps.SetCurrentValue(index, (LONG) 0);
|
|
|
|
//
|
|
// WIA_IPA_NUMBER_OF_LINES
|
|
//
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPA_NUMBER_OF_LINES, WIA_IPA_NUMBER_OF_LINES_STR,
|
|
WIA_PROP_READ, WIA_PROP_NONE);
|
|
if (FAILED(hr)) goto failure;
|
|
ItemProps.SetCurrentValue(index, pItemInfo->Height);
|
|
|
|
|
|
//
|
|
// WIA_IPC_THUMBNAIL
|
|
//
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPC_THUMBNAIL, WIA_IPC_THUMBNAIL_STR,
|
|
WIA_PROP_READ, WIA_PROP_NONE);
|
|
if (FAILED(hr)) goto failure;
|
|
ItemProps.SetCurrentValue(index, (BYTE *) NULL, 0);
|
|
|
|
//
|
|
// WIA_IPC_THUMB_WIDTH
|
|
//
|
|
// This field is probably zero until the thumbnail is read in, but set it anyway
|
|
//
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPC_THUMB_WIDTH, WIA_IPC_THUMB_WIDTH_STR,
|
|
WIA_PROP_READ, WIA_PROP_NONE);
|
|
if (FAILED(hr)) goto failure;
|
|
ItemProps.SetCurrentValue(index, pItemInfo->ThumbWidth);
|
|
|
|
//
|
|
// WIA_IPC_THUMB_HEIGHT
|
|
//
|
|
// This field is probably zero until the thumbnail is read in, but set it anyway
|
|
//
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPC_THUMB_HEIGHT, WIA_IPC_THUMB_HEIGHT_STR,
|
|
WIA_PROP_READ, WIA_PROP_NONE);
|
|
if (FAILED(hr)) goto failure;
|
|
ItemProps.SetCurrentValue(index, pItemInfo->ThumbHeight);
|
|
|
|
//
|
|
// WIA_IPC_SEQUENCE
|
|
//
|
|
if (pItemInfo->SequenceNum > 0)
|
|
{
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPC_SEQUENCE, WIA_IPC_SEQUENCE_STR,
|
|
WIA_PROP_READ, WIA_PROP_NONE);
|
|
if (FAILED(hr)) goto failure;
|
|
ItemProps.SetCurrentValue(index, pItemInfo->SequenceNum);
|
|
}
|
|
}
|
|
|
|
// For video
|
|
#if 1
|
|
if( ( pItemInfo->Format < (FORMAT_CODE)m_NumFormatInfo) &&
|
|
(ITEMTYPE_VIDEO == m_FormatInfo[pItemInfo->Format].ItemType) )
|
|
{
|
|
//
|
|
// WIA_IPC_THUMBNAIL
|
|
//
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPC_THUMBNAIL, WIA_IPC_THUMBNAIL_STR,
|
|
WIA_PROP_READ, WIA_PROP_NONE);
|
|
if (FAILED(hr)) goto failure;
|
|
ItemProps.SetCurrentValue(index, (BYTE *) NULL, 0);
|
|
|
|
//
|
|
// WIA_IPC_THUMB_WIDTH
|
|
//
|
|
// This field is probably zero until the thumbnail is read in, but set it anyway
|
|
//
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPC_THUMB_WIDTH, WIA_IPC_THUMB_WIDTH_STR,
|
|
WIA_PROP_READ, WIA_PROP_NONE);
|
|
if (FAILED(hr)) goto failure;
|
|
ItemProps.SetCurrentValue(index, pItemInfo->ThumbWidth);
|
|
|
|
//
|
|
// WIA_IPC_THUMB_HEIGHT
|
|
//
|
|
// This field is probably zero until the thumbnail is read in, but set it anyway
|
|
//
|
|
hr = ItemProps.DefineProperty(&index, WIA_IPC_THUMB_HEIGHT, WIA_IPC_THUMB_HEIGHT_STR,
|
|
WIA_PROP_READ, WIA_PROP_NONE);
|
|
if (FAILED(hr)) goto failure;
|
|
ItemProps.SetCurrentValue(index, pItemInfo->ThumbHeight);
|
|
}
|
|
#endif
|
|
//
|
|
// Last step: send all the properties to WIA
|
|
//
|
|
hr = ItemProps.SendToWia(pWiasContext);
|
|
if (FAILED(hr))
|
|
{
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildChildItemProperties, SendToWia failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
}
|
|
|
|
// Nb: hr is used for routine return code - careful to not overwrite it from here till return statement
|
|
|
|
if (bstrFileExt) {
|
|
SysFreeString(bstrFileExt);
|
|
bstrFileExt = NULL;
|
|
}
|
|
|
|
if (pFormatArray)
|
|
delete []pFormatArray;
|
|
|
|
return hr;
|
|
|
|
//
|
|
// Any failures from DefineProperty will end up here
|
|
//
|
|
failure:
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildChildItemProperties, DefineProperty failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
|
|
if (bstrFileExt) {
|
|
SysFreeString(bstrFileExt);
|
|
bstrFileExt = NULL;
|
|
}
|
|
|
|
if (pFormatArray)
|
|
delete []pFormatArray;
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* GetValidFormats
|
|
*
|
|
* Calls drvGetWiaFormatInfo and makes a list of valid formats given
|
|
* a tymed value. Caller is responsible for freeing the format array.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pWiasContext - WIA service context
|
|
* TymedValue - tymed value to search for
|
|
* pNumFormats - pointer to value to receive number of formats
|
|
* ppFormatArray - pointer to a pointer location to receive array address
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT
|
|
CWiaCameraDevice::GetValidFormats(
|
|
BYTE *pWiasContext,
|
|
LONG TymedValue,
|
|
int *pNumFormats,
|
|
GUID **ppFormatArray
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!ppFormatArray || !pNumFormats)
|
|
{
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetValidFormats, invalid arg"));
|
|
return E_INVALIDARG;
|
|
}
|
|
*ppFormatArray = NULL;
|
|
*pNumFormats = 0;
|
|
|
|
LONG NumFi = 0;
|
|
WIA_FORMAT_INFO *pFiArray = NULL;
|
|
LONG lErrVal = 0;
|
|
hr = drvGetWiaFormatInfo(pWiasContext, 0, &NumFi, &pFiArray, &lErrVal);
|
|
if (FAILED(hr))
|
|
{
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetValidFormats, drvGetWiaFormatInfo failed"));
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// This will allocate more spots than necessary, but pNumFormats will be set correctly
|
|
//
|
|
GUID *pFA = new GUID[NumFi];
|
|
|
|
if( !pFA )
|
|
return E_OUTOFMEMORY;
|
|
|
|
for (int count = 0; count < NumFi; count++)
|
|
{
|
|
if (pFiArray[count].lTymed == TymedValue)
|
|
{
|
|
pFA[*pNumFormats] = pFiArray[count].guidFormatID;
|
|
(*pNumFormats)++;
|
|
}
|
|
}
|
|
|
|
*ppFormatArray = pFA;
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* ReadChildItemProperties
|
|
*
|
|
* Update the properties for the child items.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pWiasContext - WIA service context
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT
|
|
CWiaCameraDevice::ReadChildItemProperties(
|
|
BYTE *pWiasContext,
|
|
LONG NumPropSpecs,
|
|
const PROPSPEC *pPropSpecs
|
|
)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWiaCameraDevice::ReadChildItemProperties");
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!NumPropSpecs || !pPropSpecs)
|
|
{
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ReadChildItemProperties, invalid arg"));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// Get the driver item context
|
|
//
|
|
ITEM_CONTEXT *pItemCtx;
|
|
hr = GetDrvItemContext(pWiasContext, &pItemCtx);
|
|
if (FAILED(hr))
|
|
{
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildChildItemProperties, GetDrvItemContext failed"));
|
|
return hr;
|
|
}
|
|
|
|
ITEM_INFO *pItemInfo = pItemCtx->ItemHandle;
|
|
|
|
//
|
|
// The only child property on a camera that could change is the item time
|
|
//
|
|
if (wiauPropInPropSpec(NumPropSpecs, pPropSpecs, WIA_IPA_ITEM_TIME))
|
|
{
|
|
PROPVARIANT propVar;
|
|
PROPSPEC propSpec;
|
|
propVar.vt = VT_VECTOR | VT_UI2;
|
|
propVar.caui.cElems = sizeof(SYSTEMTIME) / sizeof(WORD);
|
|
propVar.caui.pElems = (WORD *) &pItemInfo->Time;
|
|
propSpec.ulKind = PRSPEC_PROPID;
|
|
propSpec.propid = WIA_IPA_ITEM_TIME;
|
|
hr = wiasWriteMultiple(pWiasContext, 1, &propSpec, &propVar );
|
|
if (FAILED(hr))
|
|
{
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ReadChildItemProperties, wiasWriteMultiple failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// For images & video, update the thumbnail properties if requested
|
|
//
|
|
ULONG uItemType;
|
|
|
|
uItemType = m_FormatInfo[pItemInfo->Format].ItemType;
|
|
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, ("ReadChildItemProperties, File %S, Type =%d", pItemInfo->pName, uItemType));
|
|
|
|
PROPSPEC propSpecs[9];
|
|
PROPVARIANT propVars[9];
|
|
UINT nNumProps;
|
|
|
|
// The following is needed because we delayed parsing these properties until read
|
|
if( uItemType == ITEMTYPE_IMAGE || uItemType == ITEMTYPE_VIDEO )
|
|
{
|
|
//
|
|
// Get the thumbnail if requested to update any of the thumbnail properties and
|
|
// the thumbnail is not already cached.
|
|
//
|
|
PROPID propsToUpdate[] = {
|
|
WIA_IPA_DEPTH,
|
|
WIA_IPA_CHANNELS_PER_PIXEL,
|
|
WIA_IPA_BITS_PER_CHANNEL,
|
|
WIA_IPA_PIXELS_PER_LINE,
|
|
WIA_IPA_BYTES_PER_LINE,
|
|
WIA_IPA_NUMBER_OF_LINES,
|
|
WIA_IPC_THUMB_WIDTH,
|
|
WIA_IPC_THUMB_HEIGHT,
|
|
WIA_IPC_THUMBNAIL
|
|
};
|
|
|
|
if (wiauPropsInPropSpec(NumPropSpecs, pPropSpecs, sizeof(propsToUpdate) / sizeof(PROPID), propsToUpdate))
|
|
{
|
|
|
|
if (!pItemCtx->pThumb)
|
|
{
|
|
hr = CacheThumbnail(pItemCtx, uItemType);
|
|
if (FAILED(hr))
|
|
{
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ReadChildItemProperties, CacheThumbnail failed"));
|
|
pItemInfo->ThumbWidth = 0;
|
|
pItemInfo->ThumbHeight = 0;
|
|
pItemCtx->ThumbSize = 0;
|
|
pItemCtx->pThumb = NULL;
|
|
// return hr;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Update the related thumbnail properties. Update the thumb width and height in case
|
|
// the device didn't report them in the ObjectInfo structure (they are optional there).
|
|
//
|
|
propSpecs[0].ulKind = PRSPEC_PROPID;
|
|
propSpecs[0].propid = WIA_IPC_THUMB_WIDTH;
|
|
propVars[0].vt = VT_I4;
|
|
propVars[0].lVal = pItemInfo->ThumbWidth;
|
|
|
|
propSpecs[1].ulKind = PRSPEC_PROPID;
|
|
propSpecs[1].propid = WIA_IPC_THUMB_HEIGHT;
|
|
propVars[1].vt = VT_I4;
|
|
propVars[1].lVal = pItemInfo->ThumbHeight;
|
|
|
|
propSpecs[2].ulKind = PRSPEC_PROPID;
|
|
propSpecs[2].propid = WIA_IPC_THUMBNAIL;
|
|
propVars[2].vt = VT_VECTOR | VT_UI1;
|
|
propVars[2].caub.cElems = pItemCtx->ThumbSize;
|
|
propVars[2].caub.pElems = pItemCtx->pThumb;
|
|
|
|
if( uItemType == ITEMTYPE_IMAGE )
|
|
{
|
|
propSpecs[3].ulKind = PRSPEC_PROPID;
|
|
propSpecs[3].propid = WIA_IPA_DEPTH;
|
|
propVars[3].vt = VT_I4;
|
|
propVars[3].lVal = pItemInfo->Depth;
|
|
|
|
propSpecs[4].ulKind = PRSPEC_PROPID;
|
|
propSpecs[4].propid = WIA_IPA_CHANNELS_PER_PIXEL;
|
|
propVars[4].vt = VT_I4;
|
|
propVars[4].lVal = pItemInfo->Channels;
|
|
|
|
propSpecs[5].ulKind = PRSPEC_PROPID;
|
|
propSpecs[5].propid = WIA_IPA_BITS_PER_CHANNEL;
|
|
propVars[5].vt = VT_I4;
|
|
propVars[5].lVal = pItemInfo->BitsPerChannel;
|
|
|
|
propSpecs[6].ulKind = PRSPEC_PROPID;
|
|
propSpecs[6].propid = WIA_IPA_PIXELS_PER_LINE;
|
|
propVars[6].vt = VT_I4;
|
|
propVars[6].lVal = pItemInfo->Width;
|
|
|
|
propSpecs[7].ulKind = PRSPEC_PROPID;
|
|
propSpecs[7].propid = WIA_IPA_BYTES_PER_LINE;
|
|
propVars[7].vt = VT_I4;
|
|
propVars[7].lVal = (pItemInfo->Width * pItemInfo->Depth) >> 3;
|
|
|
|
propSpecs[8].ulKind = PRSPEC_PROPID;
|
|
propSpecs[8].propid = WIA_IPA_NUMBER_OF_LINES;
|
|
propVars[8].vt = VT_I4;
|
|
propVars[8].lVal = pItemInfo->Height;
|
|
|
|
nNumProps = 9;
|
|
} else {
|
|
nNumProps = 3;
|
|
}
|
|
|
|
hr = wiasWriteMultiple(pWiasContext, nNumProps, propSpecs, propVars);
|
|
if (FAILED(hr))
|
|
{
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ReadChildItemProperties, wiasWriteMultiple for size properties failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
}
|
|
} // end of IF wiauPropsInProp
|
|
|
|
} // end of IF Image or Video
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// This function caches the thumbnail into the given ITEM_CONTEXT
|
|
//
|
|
// Input:
|
|
// pItemCtx -- the designated ITEM_CONTEXT
|
|
//
|
|
HRESULT
|
|
CWiaCameraDevice::CacheThumbnail(ITEM_CONTEXT *pItemCtx, ULONG uItemType)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWiaCameraDevice::CacheThumbnail");
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Local variables
|
|
//
|
|
ITEM_INFO *pItemInfo = NULL;
|
|
BYTE *pDest = NULL;
|
|
INT iThumbSize = 0;
|
|
BYTE *pNativeThumb = NULL;
|
|
BOOL bGotNativeThumbnail=TRUE;
|
|
BMP_IMAGE_INFO BmpImageInfo;
|
|
INT iSize=0;
|
|
|
|
//
|
|
// Check arguments
|
|
//
|
|
if (!pItemCtx)
|
|
{
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CacheThumbnail, invalid arg"));
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Make sure thumbnail isn't already created
|
|
//
|
|
if (pItemCtx->pThumb)
|
|
{
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CacheThumbnail, thumbnail is already cached"));
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Get the thumbnail from the camera in it's native format
|
|
//
|
|
pItemInfo = pItemCtx->ItemHandle;
|
|
pItemInfo->ThumbWidth = 0;
|
|
pItemInfo->ThumbHeight = 0;
|
|
pItemCtx->ThumbSize = 0;
|
|
pItemCtx->pThumb = NULL;
|
|
|
|
|
|
pDest=NULL;
|
|
iSize=0;
|
|
|
|
if( uItemType == ITEMTYPE_VIDEO )
|
|
{
|
|
hr = m_pDevice->CreateVideoThumbnail(pItemInfo, &iSize, &pDest, &BmpImageInfo);
|
|
}
|
|
else
|
|
{
|
|
hr = m_pDevice->CreateThumbnail(pItemInfo, &iSize, &pDest, &BmpImageInfo);
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CacheThumbnail, CreateThumbnail failed"));
|
|
goto Cleanup;
|
|
}
|
|
|
|
pItemInfo->ThumbWidth = BmpImageInfo.Width;
|
|
pItemInfo->ThumbHeight = BmpImageInfo.Height;
|
|
// pItemInfo->ThumbFormat = TYPE_BMP;
|
|
|
|
//
|
|
// Cache the buffer returned from ConvertToBmp in the driver item context. Set pDest
|
|
// to NULL, so it won't be freed below.
|
|
//
|
|
pItemCtx->ThumbSize = iSize;
|
|
pItemCtx->pThumb = pDest;
|
|
pDest = NULL;
|
|
|
|
|
|
Cleanup:
|
|
if (pNativeThumb) {
|
|
delete []pNativeThumb;
|
|
pNativeThumb = NULL;
|
|
}
|
|
|
|
if (pDest) {
|
|
delete []pDest;
|
|
pDest = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// This function transfers native data to the application without translating it.
|
|
//
|
|
HRESULT
|
|
CWiaCameraDevice::AcquireData(
|
|
ITEM_CONTEXT *pItemCtx,
|
|
PMINIDRV_TRANSFER_CONTEXT pmdtc,
|
|
BYTE *pBuf,
|
|
LONG lBufSize,
|
|
BOOL bConverting
|
|
)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWiaCameraDevice::AcquireData");
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
BYTE *pCur = NULL;
|
|
LONG lState = STATE_FIRST;
|
|
LONG lPercentComplete = 0;
|
|
LONG lTotalToRead = pItemCtx->ItemHandle->Size;
|
|
LONG lOffset = 0;
|
|
DWORD dwBytesToRead = 0;
|
|
BOOL bFileTransfer = pmdtc->tymed & TYMED_FILE;
|
|
LONG lMessage = 0;
|
|
LONG lStatus = 0;
|
|
|
|
//
|
|
// If pBuf is non-null use that as the buffer, otherwise use the buffer
|
|
// and size in pmdtc
|
|
//
|
|
if (pBuf)
|
|
{
|
|
pCur = pBuf;
|
|
dwBytesToRead = lBufSize;
|
|
}
|
|
else
|
|
{
|
|
pCur = pmdtc->pTransferBuffer;
|
|
dwBytesToRead = pmdtc->lBufferSize;
|
|
}
|
|
|
|
//
|
|
// If the transfer size is the entire item, split it into approximately
|
|
// 10 equal transfers in order to show progress to the app
|
|
//
|
|
if (dwBytesToRead == (DWORD) lTotalToRead)
|
|
{
|
|
dwBytesToRead = (lTotalToRead / 10 + 3) & ~0x3;
|
|
}
|
|
|
|
//
|
|
// Set up parameters for the callback function
|
|
//
|
|
if (bConverting)
|
|
{
|
|
lMessage = IT_MSG_STATUS;
|
|
lStatus = IT_STATUS_TRANSFER_FROM_DEVICE;
|
|
}
|
|
else if (bFileTransfer)
|
|
{
|
|
lMessage = IT_MSG_STATUS;
|
|
lStatus = IT_STATUS_TRANSFER_TO_CLIENT;
|
|
}
|
|
else // e.g. memory transfer
|
|
{
|
|
lMessage = IT_MSG_DATA;
|
|
lStatus = IT_STATUS_TRANSFER_TO_CLIENT;
|
|
}
|
|
|
|
//
|
|
// Read data until finished
|
|
//
|
|
while (lOffset < lTotalToRead)
|
|
{
|
|
//
|
|
// If this is the last read, adjust the amount of data to read
|
|
// and the state
|
|
//
|
|
if (dwBytesToRead >= (DWORD) (lTotalToRead - lOffset))
|
|
{
|
|
dwBytesToRead = (lTotalToRead - lOffset);
|
|
lState |= STATE_LAST;
|
|
}
|
|
|
|
//
|
|
// Get the data from the camera
|
|
//
|
|
hr = m_pDevice->GetItemData(pItemCtx->ItemHandle, lState, pCur, dwBytesToRead);
|
|
if (FAILED(hr))
|
|
{
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("AcquireData, GetItemData failed"));
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Calculate the percent complete for the callback function. If converting,
|
|
// report the percent complete as TRANSFER_PERCENT of the actual. From
|
|
// TRANSFER_PERCENT to 100% will be reported during format conversion.
|
|
//
|
|
if (bConverting)
|
|
lPercentComplete = (lOffset + dwBytesToRead) * TRANSFER_PERCENT / lTotalToRead;
|
|
else
|
|
lPercentComplete = (lOffset + dwBytesToRead) * 100 / lTotalToRead;
|
|
|
|
|
|
//
|
|
// Call the callback function to send status and/or data to the app
|
|
//
|
|
hr = pmdtc->pIWiaMiniDrvCallBack->
|
|
MiniDrvCallback(lMessage, lStatus, lPercentComplete,
|
|
lOffset, dwBytesToRead, pmdtc, 0);
|
|
if (FAILED(hr))
|
|
{
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("AcquireData, callback failed"));
|
|
goto Cleanup;
|
|
}
|
|
if (hr == S_FALSE)
|
|
{
|
|
//
|
|
// Transfer is being cancelled by the app
|
|
//
|
|
WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("AcquireData, transfer cancelled"));
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Increment buffer pointer only if converting or this is a
|
|
// file transfer
|
|
//
|
|
if (bConverting || bFileTransfer)
|
|
{
|
|
pCur += dwBytesToRead;
|
|
}
|
|
|
|
//
|
|
// For a memory transfer not using a buffer allocated by the minidriver,
|
|
// update the buffer pointer and size from the transfer context in case
|
|
// of double buffering
|
|
//
|
|
else if (!pBuf)
|
|
{
|
|
pCur = pmdtc->pTransferBuffer;
|
|
// dwBytesToRead = pmdtc->lBufferSize;
|
|
}
|
|
|
|
//
|
|
// Adjust variables for the next iteration
|
|
//
|
|
lOffset += dwBytesToRead;
|
|
lState &= ~STATE_FIRST;
|
|
}
|
|
|
|
//
|
|
// For file transfers, write the data to file
|
|
//
|
|
if (!pBuf && bFileTransfer)
|
|
{
|
|
//
|
|
// Call WIA to write the data to the file
|
|
//
|
|
hr = wiasWriteBufToFile(0, pmdtc);
|
|
if (FAILED(hr))
|
|
{
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("AcquireData, wiasWriteBufToFile failed"));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
//
|
|
// If the transfer wasn't completed, send cancel to the device
|
|
//
|
|
if (!(lState & STATE_LAST))
|
|
{
|
|
lState = STATE_CANCEL;
|
|
m_pDevice->GetItemData(pItemCtx->ItemHandle, lState, NULL, 0);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// This function translates native data to BMP and sends the data to the app
|
|
//
|
|
HRESULT
|
|
CWiaCameraDevice::Convert(
|
|
BYTE *pWiasContext,
|
|
ITEM_CONTEXT *pItemCtx,
|
|
PMINIDRV_TRANSFER_CONTEXT pmdtc,
|
|
BYTE *pNativeImage,
|
|
LONG lNativeSize
|
|
)
|
|
{
|
|
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
|
|
WIALOG_NO_RESOURCE_ID,
|
|
WIALOG_LEVEL1,
|
|
"CWiaCameraDevice::Convert");
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Locals
|
|
//
|
|
LONG lMsg = 0; // Parameter to the callback function
|
|
LONG lPercentComplete = 0; // Parameter to the callback function
|
|
BOOL bUseAppBuffer = FALSE; // Indicates whether to transfer directly into the app's buffer
|
|
BYTE *pBmpBuffer = NULL; // Buffer used to hold converted image
|
|
INT iBmpBufferSize = 0; // Size of the converted image buffer
|
|
LONG lBytesToCopy = 0;
|
|
LONG lOffset = 0;
|
|
BYTE *pCurrent = NULL;
|
|
BMP_IMAGE_INFO BmpImageInfo;
|
|
SKIP_AMOUNT iSkipAmt = SKIP_OFF;
|
|
|
|
//
|
|
// Check arguments
|
|
//
|
|
if (!pNativeImage)
|
|
{
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("Convert, invalid arg"));
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// The msg to send to the app via the callback depends on whether
|
|
// this is a file or callback transfer
|
|
//
|
|
lMsg = ((pmdtc->tymed & TYMED_FILE) ? IT_MSG_STATUS : IT_MSG_DATA);
|
|
|
|
//
|
|
// If the class driver allocated a buffer and the buffer is large
|
|
// enough, convert directly into that buffer. Otherwise, pass NULL
|
|
// to the ConvertToBmp function so that it will allocate a buffer.
|
|
//
|
|
if (pmdtc->bClassDrvAllocBuf &&
|
|
pmdtc->lBufferSize >= pmdtc->lItemSize) {
|
|
|
|
bUseAppBuffer = TRUE;
|
|
pBmpBuffer = pmdtc->pTransferBuffer;
|
|
iBmpBufferSize = pmdtc->lBufferSize;
|
|
}
|
|
|
|
//
|
|
// Convert the image to BMP. Skip the BMP file header if the app asked
|
|
// for a "memory bitmap" (aka DIB).
|
|
//
|
|
memset(&BmpImageInfo, 0, sizeof(BmpImageInfo));
|
|
if (IsEqualGUID(pmdtc->guidFormatID, WiaImgFmt_MEMORYBMP)) {
|
|
iSkipAmt = SKIP_FILEHDR;
|
|
}
|
|
hr = m_Converter.ConvertToBmp(pNativeImage, lNativeSize, &pBmpBuffer,
|
|
&iBmpBufferSize, &BmpImageInfo, iSkipAmt);
|
|
if (FAILED(hr))
|
|
{
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("Convert, ConvertToBmp failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Send the data to the app. If the class driver allocated the buffer,
|
|
// but it was too small, send the data back one chunk at a time.
|
|
// Otherwise send all the data back at once.
|
|
//
|
|
if (pmdtc->bClassDrvAllocBuf &&
|
|
pmdtc->lBufferSize < BmpImageInfo.Size) {
|
|
|
|
pCurrent = pBmpBuffer;
|
|
|
|
while (lOffset < BmpImageInfo.Size)
|
|
{
|
|
lBytesToCopy = BmpImageInfo.Size - lOffset;
|
|
if (lBytesToCopy > pmdtc->lBufferSize) {
|
|
|
|
lBytesToCopy = pmdtc->lBufferSize;
|
|
|
|
//
|
|
// Calculate how much of the data has been sent back so far. Report percentages to
|
|
// the app between TRANSFER_PERCENT and 100 percent. Make sure it is never larger
|
|
// than 99 until the end.
|
|
//
|
|
lPercentComplete = TRANSFER_PERCENT + ((100 - TRANSFER_PERCENT) * lOffset) / pmdtc->lItemSize;
|
|
if (lPercentComplete > 99) {
|
|
lPercentComplete = 99;
|
|
}
|
|
}
|
|
|
|
//
|
|
// This will complete the transfer, so set the percentage to 100
|
|
else {
|
|
lPercentComplete = 100;
|
|
}
|
|
|
|
memcpy(pmdtc->pTransferBuffer, pCurrent, lBytesToCopy);
|
|
|
|
//
|
|
// Call the application's callback transfer to report status and/or transfer data
|
|
//
|
|
hr = pmdtc->pIWiaMiniDrvCallBack->MiniDrvCallback(lMsg, IT_STATUS_TRANSFER_TO_CLIENT,
|
|
lPercentComplete, lOffset, lBytesToCopy, pmdtc, 0);
|
|
if (FAILED(hr))
|
|
{
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("Convert, sending data to app failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
goto Cleanup;
|
|
}
|
|
if (hr == S_FALSE)
|
|
{
|
|
WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("Convert, transfer cancelled"));
|
|
hr = S_FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
pCurrent += lBytesToCopy;
|
|
lOffset += lBytesToCopy;
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
//
|
|
// Send the data to the app in one big chunk
|
|
//
|
|
pmdtc->pTransferBuffer = pBmpBuffer;
|
|
hr = pmdtc->pIWiaMiniDrvCallBack->MiniDrvCallback(lMsg, IT_STATUS_TRANSFER_TO_CLIENT,
|
|
100, 0, BmpImageInfo.Size, pmdtc, 0);
|
|
if (FAILED(hr))
|
|
{
|
|
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("Convert, sending data to app failed"));
|
|
WIAS_LHRESULT(m_pIWiaLog, hr);
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
if (!bUseAppBuffer) {
|
|
if (pBmpBuffer) {
|
|
delete []pBmpBuffer;
|
|
pBmpBuffer = NULL;
|
|
iBmpBufferSize = 0;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|