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.
 
 
 
 
 
 

2406 lines
73 KiB

/*******************************************************************************
*
* (C) COPYRIGHT 2001, MICROSOFT CORP.
*
* TITLE: IWiaMiniDrv.cpp
*
* VERSION: 1.0
*
* DATE: 15 Nov, 2000
*
* DESCRIPTION:
* Implementation of the WIA File System Device driver IWiaMiniDrv methods. This file
* contains 3 sections. The first is the WIA minidriver entry points, all
* starting with "drv". The next section is public help methods. The last
* section is private helper methods.
*
*******************************************************************************/
#include "pch.h"
//
// This structure is a convenient way to map between the FORMAT_CODEs and info
// useful for WIA, such as the format GUIDs and item types. These need to
// correspond to the constants defined in FakeCam.h.
//
// FORMAT_INFO *g_FormatInfo;
// extern UINT g_NumFormatInfo=0;
// The following are utility functions for populate the g_FormatInfo array
LONG GetTypeInfoFromRegistry(HKEY *phKeyExt, WCHAR *wcsKeyName, GUID *pFormatGuid)
{
if( !pFormatGuid )
{
return ITEMTYPE_FILE; // In this case, no info from Registry about file type.
}
HKEY hKeyCur;
const int c_nMaxValueLength = 64;
DWORD dwRet = RegOpenKeyExW(*phKeyExt, wcsKeyName, 0, KEY_READ | KEY_QUERY_VALUE, &hKeyCur);
if( dwRet != ERROR_SUCCESS )
{
return ITEMTYPE_FILE;
}
WCHAR wcsValueName[c_nMaxValueLength] = L"Generic";
WCHAR wcsData[MAX_PATH];
DWORD dwType = REG_SZ;
DWORD dwSize = MAX_PATH;
dwRet = RegQueryValueExW(hKeyCur,
wcsValueName, NULL, &dwType, (LPBYTE)wcsData, &dwSize );
DWORD dwItemType = ITEMTYPE_FILE;
if( ERROR_SUCCESS == dwRet )
{
if( CSTR_EQUAL == CompareStringW(LOCALE_SYSTEM_DEFAULT,
NORM_IGNORECASE, L"image", 5, wcsData, 5) )
{
dwItemType = ITEMTYPE_IMAGE;
}
else if ( CSTR_EQUAL == CompareStringW(LOCALE_SYSTEM_DEFAULT,
NORM_IGNORECASE, L"audio", 5, wcsData, 5) )
{
dwItemType = ITEMTYPE_AUDIO;
}
else if ( CSTR_EQUAL == CompareStringW(LOCALE_SYSTEM_DEFAULT,
NORM_IGNORECASE, L"video", 5, wcsData, 5) )
{
dwItemType = ITEMTYPE_VIDEO;
}
else
{
dwItemType = ITEMTYPE_FILE;
}
}
StringCchCopyW(wcsValueName, c_nMaxValueLength, L"FormatGUID");
dwType = REG_SZ;
dwSize = MAX_PATH;
dwRet = RegQueryValueExW(hKeyCur,
wcsValueName,
NULL,
&dwType,
(LPBYTE)wcsData,
&dwSize );
if( ERROR_SUCCESS == dwRet )
{
wcsData[dwSize]=0;
if( NOERROR != CLSIDFromString(wcsData, pFormatGuid))
{
CopyMemory(pFormatGuid, (CONST VOID *)&WiaImgFmt_UNDEFINED, sizeof(GUID));
}
}
else
{
CopyMemory(pFormatGuid, (CONST VOID *)&WiaImgFmt_UNDEFINED, sizeof(GUID));
}
RegCloseKey(hKeyCur);
return dwItemType;
}
DWORD CWiaCameraDevice::PopulateFormatInfo(void)
{
HKEY hKeyExt = NULL;
DWORD dwRet, dwCurAllocation = 32;
DWORD dwIndex=0, dwIndexBase=0, dwKeyNameSize=32;
m_FormatInfo = (FORMAT_INFO *)CoTaskMemAlloc(sizeof(FORMAT_INFO)*dwCurAllocation);
if( !m_FormatInfo )
{
dwRet = ERROR_OUTOFMEMORY;
goto Exit;
}
m_FormatInfo[0].FormatGuid = WiaImgFmt_UNDEFINED;
m_FormatInfo[0].ItemType = ITEMTYPE_FILE;
m_FormatInfo[0].ExtensionString[0] = L'\0';
dwIndexBase=1;
dwIndex=0;
dwRet = RegOpenKeyExW(HKEY_CLASSES_ROOT,
L"CLSID\\{D2923B86-15F1-46FF-A19A-DE825F919576}\\SupportedExtension",
0, KEY_READ | KEY_QUERY_VALUE, &hKeyExt);
if( ERROR_SUCCESS != dwRet ) // No Key exist
{
goto Compilation;
}
WCHAR wcsKeyName[32], *pExt;
FILETIME ftLWT;
dwRet = RegEnumKeyExW(hKeyExt, dwIndex, wcsKeyName, &dwKeyNameSize, NULL, NULL, NULL, &ftLWT);
if( ERROR_SUCCESS != dwRet ) // No key exist
{
goto Compilation;
}
while ( dwRet == ERROR_SUCCESS )
{
pExt = (wcsKeyName[0]==L'.'?(&wcsKeyName[1]):(&wcsKeyName[0])); // remove the dot
pExt[MAXEXTENSIONSTRINGLENGTH-1] = NULL; // Truncate to avoid overrun
// Set values in FORMAT_INFO structure
StringCchCopyW(m_FormatInfo[dwIndex+dwIndexBase].ExtensionString, MAXEXTENSIONSTRINGLENGTH, pExt);
m_FormatInfo[dwIndex+dwIndexBase].ItemType = GetTypeInfoFromRegistry(&hKeyExt, wcsKeyName, &(m_FormatInfo[dwIndex+dwIndexBase].FormatGuid));
dwIndex++;
if( dwIndex+dwIndexBase > dwCurAllocation-1 ) // need allocate more memory
{
dwCurAllocation += 32;
m_FormatInfo = (FORMAT_INFO *)CoTaskMemRealloc(m_FormatInfo, sizeof(FORMAT_INFO)*dwCurAllocation);
if( !m_FormatInfo )
{
dwRet = ERROR_OUTOFMEMORY;
dwIndex --;
goto Exit;
}
}
dwKeyNameSize=32;
dwRet = RegEnumKeyExW(hKeyExt, dwIndex, wcsKeyName, &dwKeyNameSize, NULL, NULL, NULL, &ftLWT);
}
if(dwRet == ERROR_NO_MORE_ITEMS )
{
dwRet = ERROR_SUCCESS;
goto Exit;
}
Compilation: // Compile a fixed list of formats when error occurs
dwIndex=dwIndexBase=0;
dwRet = ERROR_SUCCESS;
DEFAULT_FORMAT_INFO g_DefaultFormats[] =
{
{ (GUID *)&WiaImgFmt_UNDEFINED, ITEMTYPE_FILE, L"" }, // Unknown
{ (GUID *)&WiaImgFmt_JPEG, ITEMTYPE_IMAGE, L"JPG" }, // JPEG or EXIF
{ (GUID *)&WiaImgFmt_TIFF, ITEMTYPE_IMAGE, L"TIF" }, // TIFF
{ (GUID *)&WiaImgFmt_BMP, ITEMTYPE_IMAGE, L"BMP" }, // BMP
{ (GUID *)&WiaImgFmt_GIF, ITEMTYPE_IMAGE, L"GIF" }, // GIF
{ NULL, 0, NULL }
};
while( g_DefaultFormats[dwIndex].pFormatGuid )
{
m_FormatInfo[dwIndex].FormatGuid = *g_DefaultFormats[dwIndex].pFormatGuid;
m_FormatInfo[dwIndex].ItemType = g_DefaultFormats[dwIndex].ItemType;
StringCchCopyW(m_FormatInfo[dwIndex].ExtensionString, MAXEXTENSIONSTRINGLENGTH, g_DefaultFormats[dwIndex].ExtensionString);
dwIndex++;
}
Exit:
m_NumFormatInfo = dwIndex+dwIndexBase;
if (hKeyExt != NULL ) {
RegCloseKey(hKeyExt);
hKeyExt = NULL;
}
return dwRet;
}
void CWiaCameraDevice::UnPopulateFormatInfo(void)
{
CoTaskMemFree(m_FormatInfo);
}
/**************************************************************************\
* CWiaCameraDevice::drvInitializeWia
*
* Initialize the WIA mini driver. This function will be called each time an
* application creates a device. The first time through, the driver item tree
* will be created and other initialization will be done.
*
* Arguments:
*
* pWiasContext - Pointer to the WIA item, unused.
* lFlags - Operation flags, unused.
* bstrDeviceID - Device ID.
* bstrRootFullItemName - Full item name.
* pIPropStg - Device info. properties.
* pStiDevice - STI device interface.
* pIUnknownOuter - Outer unknown interface.
* ppIDrvItemRoot - Pointer to returned root item.
* ppIUnknownInner - Pointer to returned inner unknown.
* plDevErrVal - Pointer to the device error value.
*
\**************************************************************************/
HRESULT CWiaCameraDevice::drvInitializeWia(
BYTE *pWiasContext,
LONG lFlags,
BSTR bstrDeviceID,
BSTR bstrRootFullItemName,
IUnknown *pStiDevice,
IUnknown *pIUnknownOuter,
IWiaDrvItem **ppIDrvItemRoot,
IUnknown **ppIUnknownInner,
LONG *plDevErrVal)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL1,
"CWiaCameraDevice::drvInitializeWia");
HRESULT hr = S_OK;
*plDevErrVal = 0;
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,("drvInitializeWia, device ID: %ws", bstrDeviceID));
*ppIDrvItemRoot = NULL;
*ppIUnknownInner = NULL;
m_ConnectedApps++;;
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvInitializeWia, number of connected apps is now %d", m_ConnectedApps));
if (m_ConnectedApps == 1)
{
if (ERROR_SUCCESS != PopulateFormatInfo() ) {
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitializeWia, unable to populate FormatInfo array"));
return E_OUTOFMEMORY;
}
//
// Save STI device interface for calling locking functions
//
m_pStiDevice = (IStiDevice *)pStiDevice;
//
// Cache the device ID
//
m_bstrDeviceID = SysAllocString(bstrDeviceID);
if (!m_bstrDeviceID) {
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitializeWia, unable to allocate device ID string"));
return E_OUTOFMEMORY;
}
//
// Cache the root item name
//
m_bstrRootFullItemName = SysAllocString(bstrRootFullItemName);
if (!m_bstrRootFullItemName) {
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitializeWia, unable to allocate root item name"));
return E_OUTOFMEMORY;
}
if( m_pDevice )
{
m_pDevice->m_FormatInfo = m_FormatInfo;
m_pDevice->m_NumFormatInfo = m_NumFormatInfo;
}
else
{
return (HRESULT_FROM_WIN32(ERROR_INVALID_ACCESS));
}
//
// Get information from the device
//
hr = m_pDevice->GetDeviceInfo(&m_DeviceInfo);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitializeWia, GetDeviceInfo failed"));
return hr;
}
//
// Build the capabilities array
//
hr = BuildCapabilities();
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitializeWia, BuildCapabilities failed"));
return hr;
}
//
// Build the device item tree
//
hr = BuildItemTree();
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitializeWia, BuildItemTree failed"));
return hr;
}
}
*ppIDrvItemRoot = m_pRootItem;
return hr;
}
/**************************************************************************\
* CWiaCameraDevice::drvUnInitializeWia
*
* Gets called when a client connection is going away.
*
* Arguments:
*
* pWiasContext - Pointer to the WIA Root item context of the client's
* item tree.
*
\**************************************************************************/
HRESULT CWiaCameraDevice::drvUnInitializeWia(BYTE *pWiasContext)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL1,
"CWiaCameraDevice::drvUnInitializeWia");
HRESULT hr = S_OK;
m_ConnectedApps--;
if (m_ConnectedApps == 0)
{
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("drvUnInitializeWia, connected apps is zero, freeing resources..."));
// Destroy the driver item tree
hr = DeleteItemTree(WiaItemTypeDisconnected);
if (FAILED(hr))
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvUnInitializeWia, UnlinkItemTree failed"));
// Delete allocated arrays
DeleteCapabilitiesArrayContents();
// Free the device info structure
m_pDevice->FreeDeviceInfo(&m_DeviceInfo);
// Free the item handle map
m_HandleItemMap.RemoveAll();
// Free the storage for the device ID
if (m_bstrDeviceID) {
SysFreeString(m_bstrDeviceID);
}
// Free the storage for the root item name
if (m_bstrRootFullItemName) {
SysFreeString(m_bstrRootFullItemName);
}
UnPopulateFormatInfo();
//
// Do not delete the device here, because GetStatus may still be called later
//
/*
// Kill notification thread if it exists.
SetNotificationHandle(NULL);
// Close event for syncronization of notifications shutdown.
if (m_hShutdownEvent && (m_hShutdownEvent != INVALID_HANDLE_VALUE)) {
CloseHandle(m_hShutdownEvent);
m_hShutdownEvent = NULL;
}
//
// WIA member destruction
//
// Cleanup the WIA event sink.
if (m_pIWiaEventCallback) {
m_pIWiaEventCallback->Release();
m_pIWiaEventCallback = NULL;
}
*/
}
return hr;
}
/**************************************************************************\
* CWiaCameraDevice::drvInitItemProperties
*
* Initialize the device item properties. Called during item
* initialization. This is called by the WIA Class driver
* after the item tree has been built. It is called once for every
* item in the tree. For the root item, just set the properties already
* set up in drvInitializeWia. For child items, access the camera for
* information about the item and for images also get the thumbnail.
*
* Arguments:
*
* pWiasContext - Pointer to WIA item.
* lFlags - Operation flags, unused.
* plDevErrVal - Pointer to the device error value.
*
*
\**************************************************************************/
HRESULT CWiaCameraDevice::drvInitItemProperties(
BYTE *pWiasContext,
LONG lFlags,
LONG *plDevErrVal)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL1,
"CWiaCameraDevice::drvInitItemProperties");
HRESULT hr = S_OK;
*plDevErrVal = 0;
LONG lItemType;
hr = wiasGetItemType(pWiasContext, &lItemType);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitItemProperties, wiasGetItemType failed"));
WIAS_LHRESULT(m_pIWiaLog, hr);
return hr;
}
if (lItemType & WiaItemTypeRoot) {
//
// Build root item properties, initializing global
// structures with their default and valid values
//
hr = BuildRootItemProperties(pWiasContext);
} else {
//
// Build child item properties, initializing global
// structures with their default and valid values
//
hr = BuildChildItemProperties(pWiasContext);
}
return hr;
}
/**************************************************************************\
* CWiaCameraDevice::drvLockWiaDevice
*
* Lock access to the device.
*
* Arguments:
*
* pWiasContext - unused, can be NULL
* lFlags - Operation flags, unused.
* plDevErrVal - Pointer to the device error value.
*
*
\**************************************************************************/
HRESULT CWiaCameraDevice::drvLockWiaDevice(
BYTE *pWiasContext,
LONG lFlags,
LONG *plDevErrVal)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL1,
"CWiaCameraDevice::drvLockWiaDevice");
*plDevErrVal = 0;
return m_pStiDevice->LockDevice(100);
}
/**************************************************************************\
* CWiaCameraDevice::drvUnLockWiaDevice
*
* Unlock access to the device.
*
* Arguments:
*
* pWiasContext - Pointer to the WIA item, unused.
* lFlags - Operation flags, unused.
* plDevErrVal - Pointer to the device error value.
*
\**************************************************************************/
HRESULT CWiaCameraDevice::drvUnLockWiaDevice(
BYTE *pWiasContext,
LONG lFlags,
LONG *plDevErrVal)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL1,
"CWiaCameraDevice::drvUnLockWiaDevice");
*plDevErrVal = 0;
return m_pStiDevice->UnLockDevice();
}
/**************************************************************************\
* CWiaCameraDevice::drvFreeDrvItemContext
*
* Free any device specific context.
*
* Arguments:
*
* lFlags - Operation flags, unused.
* pDevSpecContext - Pointer to device specific context.
* plDevErrVal - Pointer to the device error value.
*
\**************************************************************************/
HRESULT CWiaCameraDevice::drvFreeDrvItemContext(
LONG lFlags,
BYTE *pSpecContext,
LONG *plDevErrVal)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL1,
"CWiaCameraDevice::drvFreeDrvItemContext");
*plDevErrVal = 0;
ITEM_CONTEXT *pItemCtx = (ITEM_CONTEXT *) pSpecContext;
if (pItemCtx)
{
if (!m_HandleItemMap.Remove(pItemCtx->ItemHandle))
WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvFreeDrvItemContext, remove on handle item map failed"));
if (pItemCtx->ItemHandle)
m_pDevice->FreeItemInfo(pItemCtx->ItemHandle);
pItemCtx->ItemHandle = NULL;
if (pItemCtx->pFormatInfo)
{
delete []pItemCtx->pFormatInfo;
pItemCtx->pFormatInfo = NULL;
}
pItemCtx->NumFormatInfo = 0;
if (pItemCtx->pThumb)
{
delete []pItemCtx->pThumb;
pItemCtx->pThumb = NULL;
}
pItemCtx->ThumbSize = 0;
}
return S_OK;
}
/**************************************************************************\
* CWiaCameraDevice::drvReadItemProperties
*
* Read the device item properties. When a client application tries to
* read a WIA Item's properties, the WIA Class driver will first notify
* the driver by calling this method.
*
* Arguments:
*
* pWiasContext - wia item
* lFlags - Operation flags, unused.
* nPropSpec - Number of elements in pPropSpec.
* pPropSpec - Pointer to property specification, showing which properties
* the application wants to read.
* plDevErrVal - Pointer to the device error value.
*
\**************************************************************************/
HRESULT CWiaCameraDevice::drvReadItemProperties(
BYTE *pWiasContext,
LONG lFlags,
ULONG nPropSpec,
const PROPSPEC *pPropSpec,
LONG *plDevErrVal)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL1,
"CWiaCameraDevice::drvReadItemProperties");
HRESULT hr = S_OK;
*plDevErrVal = 0;
LONG lItemType;
hr = wiasGetItemType(pWiasContext, &lItemType);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvReadItemProperties, wiasGetItemType failed"));
WIAS_LHRESULT(m_pIWiaLog, hr);
return hr;
}
if (lItemType & WiaItemTypeRoot) {
//
// Build root item properties, initializing global
// structures with their default and valid values
//
hr = ReadRootItemProperties(pWiasContext, nPropSpec, pPropSpec);
} else {
//
// Build child item properties, initializing global
// structures with their default and valid values
//
hr = ReadChildItemProperties(pWiasContext, nPropSpec, pPropSpec);
}
return hr;
}
/**************************************************************************\
* CWiaCameraDevice::drvWriteItemProperties
*
* Write the device item properties to the hardware. This is called by the
* WIA Class driver prior to drvAcquireItemData when the client requests
* a data transfer.
*
* Arguments:
*
* pWiasContext - Pointer to WIA item.
* lFlags - Operation flags, unused.
* pmdtc - Pointer to mini driver context. On entry, only the
* portion of the mini driver context which is derived
* from the item properties is filled in.
* plDevErrVal - Pointer to the device error value.
*
\**************************************************************************/
HRESULT CWiaCameraDevice::drvWriteItemProperties(
BYTE *pWiasContext,
LONG lFlags,
PMINIDRV_TRANSFER_CONTEXT pmdtc,
LONG *plDevErrVal)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL1,
"CWiaCameraDevice::drvWriteItemProperties");
HRESULT hr = S_OK;
//
// This function doesn't need to do anything, because all of the camera
// properties are written in drvValidateItemProperties
//
*plDevErrVal = 0;
return hr;
}
/**************************************************************************\
* CWiaCameraDevice::drvAcquireItemData
*
* Transfer data from a mini driver item to device manger.
*
* Arguments:
*
* pWiasContext - Pointer to the WIA item.
* lFlags - Operation flags, unused.
* pmdtc - Pointer to mini driver context. On entry, only the
* portion of the mini driver context which is derived
* from the item properties is filled in.
* plDevErrVal - Pointer to the device error value.
*
\**************************************************************************/
HRESULT CWiaCameraDevice::drvAcquireItemData(
BYTE *pWiasContext,
LONG lFlags,
PMINIDRV_TRANSFER_CONTEXT pmdtc,
LONG *plDevErrVal)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL1,
"CWiaCameraDevice::drvAcquireItemData");
HRESULT hr = S_OK;
plDevErrVal = 0;
//
// Locals
//
BYTE *pTempBuf = NULL;
LONG lBufSize = 0;
//
// Get item context
//
ITEM_CONTEXT *pItemCtx = NULL;
hr = GetDrvItemContext(pWiasContext, &pItemCtx);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, GetDrvItemContext"));
return hr;
}
//
// If the format requested is BMP or DIB, and the image is not already in BMP
// format, convert it
//
BOOL bConvert = (IsEqualGUID(pmdtc->guidFormatID, WiaImgFmt_BMP) && !(IsEqualGUID(m_FormatInfo[pItemCtx->ItemHandle->Format].FormatGuid, WiaImgFmt_BMP)) ) ||
(IsEqualGUID(pmdtc->guidFormatID, WiaImgFmt_MEMORYBMP) && !(IsEqualGUID(m_FormatInfo[pItemCtx->ItemHandle->Format].FormatGuid, WiaImgFmt_MEMORYBMP)) );
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL1,("drvAcquireItemData, FormatCode=%d, bConvert=%d", pItemCtx->ItemHandle->Format, bConvert));
//
// If the class driver did not allocate the transfer buffer or the image is being
// converted to DIB or BMP, allocate a temporary buffer.
//
if (bConvert || !pmdtc->bClassDrvAllocBuf) {
lBufSize = pItemCtx->ItemHandle->Size;
pTempBuf = new BYTE[lBufSize];
if (!pTempBuf)
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, buffer allocation failed"));
hr = E_FAIL;
goto Cleanup;
}
}
//
// Acquire the data from the device
//
hr = AcquireData(pItemCtx, pmdtc, pTempBuf, lBufSize, bConvert);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, AcquireData failed"));
goto Cleanup;
}
if (hr == S_FALSE)
{
WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, transfer cancelled"));
goto Cleanup;
}
//
// Now convert the data to BMP, if necessary
//
if (bConvert)
{
hr = Convert(pWiasContext, pItemCtx, pmdtc, pTempBuf, lBufSize);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, Convert failed"));
goto Cleanup;
}
}
Cleanup:
if (pTempBuf)
{
delete []pTempBuf;
pTempBuf = NULL;
lBufSize = 0;
}
return hr;
}
/**************************************************************************\
* CWiaCameraDevice::drvGetWiaFormatInfo
*
* Returns an array of WIA_FORMAT_INFO structs, which specify the format
* and media type pairs that are supported.
*
* Arguments:
*
* pWiasContext - Pointer to the WIA item context, unused.
* lFlags - Operation flags, unused.
* pcelt - Pointer to returned number of elements in
* returned WIA_FORMAT_INFO array.
* ppwfi - Pointer to returned WIA_FORMAT_INFO array.
* plDevErrVal - Pointer to the device error value.
*
\**************************************************************************/
HRESULT CWiaCameraDevice::drvGetWiaFormatInfo(
BYTE *pWiasContext,
LONG lFlags,
LONG *pcelt,
WIA_FORMAT_INFO **ppwfi,
LONG *plDevErrVal)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL1,
"CWiaCameraDevice::drvGetWiaFormatInfo");
HRESULT hr = S_OK;
*plDevErrVal = 0;
*pcelt = 0;
*ppwfi = NULL;
IWiaDrvItem *pWiaDrvItem;
hr = wiasGetDrvItem(pWiasContext, &pWiaDrvItem);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvGetWiaFormatInfo, wiasGetDrvItem failed"));
return hr;
}
ITEM_CONTEXT *pItemCtx = NULL;
hr = pWiaDrvItem->GetDeviceSpecContext((BYTE **) &pItemCtx);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvGetWiaFormatInfo, GetDeviceSpecContext failed"));
return hr;
}
if (!pItemCtx)
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvGetWiaFormatInfo, item context is null"));
return E_FAIL;
}
FORMAT_CODE FormatCode;
WIA_FORMAT_INFO *pwfi;
if (!pItemCtx->pFormatInfo)
{
//
// The format info list is not intialized. Do it now.
//
LONG ItemType;
DWORD ui32;
hr = wiasGetItemType(pWiasContext, &ItemType);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvGetWiaFormatInfo, wiasGetItemType failed"));
WIAS_LHRESULT(m_pIWiaLog, hr);
return hr;
}
if ((ItemType&WiaItemTypeFile)&&(ItemType&WiaItemTypeImage) )
{
//
// Create the supported format for the item, based on the format stored in the
// ObjectInfo structure.
//
if (!pItemCtx->ItemHandle)
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvGetWiaFormatInfo, ItemHandle is not initialized"));
return E_FAIL;
}
//
// If the format is not BMP, add the BMP types to the format array,
// since this driver must support converting those to BMP
//
FormatCode = pItemCtx->ItemHandle->Format;
BOOL bIsBmp = (IsEqualGUID(m_FormatInfo[FormatCode].FormatGuid, WiaImgFmt_BMP)) ||
(IsEqualGUID(m_FormatInfo[FormatCode].FormatGuid, WiaImgFmt_MEMORYBMP));
ULONG NumWfi = bIsBmp ? 1 : 2;
//
// Allocate two entries for each format, one for file transfer and one for callback
//
pwfi = new WIA_FORMAT_INFO[2 * NumWfi];
if (!pwfi)
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvGetWiaFormatInfo, memory allocation failed"));
return E_OUTOFMEMORY;
}
pwfi[0].guidFormatID = WiaImgFmt_BMP;
pwfi[0].lTymed = TYMED_FILE;
pwfi[1].guidFormatID = WiaImgFmt_MEMORYBMP;
pwfi[1].lTymed = TYMED_CALLBACK;
FORMAT_INFO *pFormatInfo = FormatCode2FormatInfo(FormatCode);
//
// Add entries when appropriate
//
if (!bIsBmp)
{
pwfi[2].guidFormatID = pFormatInfo->FormatGuid;
pwfi[2].lTymed = TYMED_FILE;
pwfi[3].guidFormatID = pFormatInfo->FormatGuid;
pwfi[3].lTymed = TYMED_CALLBACK;
}
pItemCtx->NumFormatInfo = 2 * NumWfi;
pItemCtx->pFormatInfo = pwfi;
}
else if (ItemType & WiaItemTypeFile) {
if (!pItemCtx->ItemHandle)
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvGetWiaFormatInfo, ItemHandle is not initialized"));
return E_FAIL;
}
FormatCode = pItemCtx->ItemHandle->Format;
//
// Allocate two entries for each format, one for file transfer and one for callback
//
pwfi = new WIA_FORMAT_INFO[2];
if (!pwfi)
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvGetWiaFormatInfo, memory allocation failed"));
return E_OUTOFMEMORY;
}
FORMAT_INFO *pFormatInfo = FormatCode2FormatInfo(FormatCode);
if( !pFormatInfo )
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvGetWiaFormatInfo, FormatCode2FormatInfo failed"));
return E_FAIL;
}
pwfi[0].guidFormatID = pFormatInfo->FormatGuid;
pwfi[0].lTymed = TYMED_FILE;
pwfi[1].guidFormatID = pFormatInfo->FormatGuid;
pwfi[1].lTymed = TYMED_CALLBACK;
//
// Add entries when appropriate
//
pItemCtx->NumFormatInfo = 2;
pItemCtx->pFormatInfo = pwfi;
}
else
// ((ItemType & WiaItemTypeFolder) || (ItemType & WiaItemTypeRoot))
{
//
// Folders and the root don't really need format info, but some apps may fail
// without it. Create a fake list just in case.
//
pItemCtx->pFormatInfo = new WIA_FORMAT_INFO[2];
if (!pItemCtx->pFormatInfo)
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvGetWiaFormatInfo, memory allocation failed"));
return E_OUTOFMEMORY;
}
pItemCtx->NumFormatInfo = 2;
pItemCtx->pFormatInfo[0].lTymed = TYMED_FILE;
pItemCtx->pFormatInfo[0].guidFormatID = FMT_NOTHING;
pItemCtx->pFormatInfo[1].lTymed = TYMED_CALLBACK;
pItemCtx->pFormatInfo[1].guidFormatID = FMT_NOTHING;
}
} // end of IF
*pcelt = pItemCtx->NumFormatInfo;
*ppwfi = pItemCtx->pFormatInfo;
return hr;
}
/**************************************************************************\
* CWiaCameraDevice::drvValidateItemProperties
*
* Validate the device item properties. It is called when changes are made
* to an item's properties. Driver should not only check that the values
* are valid, but must update any valid values that may change as a result.
* If an a property is not being written by the application, and it's value
* is invalid, then "fold" it to a new value, else fail validation (because
* the application is setting the property to an invalid value).
*
* Arguments:
*
* pWiasContext - Pointer to the WIA item, unused.
* lFlags - Operation flags, unused.
* nPropSpec - The number of properties that are being written
* pPropSpec - An array of PropSpecs identifying the properties that
* are being written.
* plDevErrVal - Pointer to the device error value.
*
***************************************************************************/
HRESULT CWiaCameraDevice::drvValidateItemProperties(
BYTE *pWiasContext,
LONG lFlags,
ULONG nPropSpec,
const PROPSPEC *pPropSpec,
LONG *plDevErrVal)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL1,
"CWiaCameraDevice::drvValidateItemProperties");
HRESULT hr = S_OK;
*plDevErrVal = 0;
//
// Have the service validate against the valid values for each property
//
hr = wiasValidateItemProperties(pWiasContext, nPropSpec, pPropSpec);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvValidateItemProperties, wiasValidateItemProperties failed"));
return hr;
}
//
// Get the item type
//
LONG lItemType = 0;
hr = wiasGetItemType(pWiasContext, &lItemType);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvValidateItemProperties, wiasGetItemType failed"));
return hr;
}
//
// Validate root item properties
//
if (lItemType & WiaItemTypeRoot) {
//
// None yet
//
}
//
// Validate child item properties
//
else {
//
// If tymed property was changed, update format and item size
//
if (wiauPropInPropSpec(nPropSpec, pPropSpec, WIA_IPA_TYMED))
{
//
// Create a property context needed by some WIA Service
// functions used below.
//
WIA_PROPERTY_CONTEXT Context;
hr = wiasCreatePropContext(nPropSpec,
(PROPSPEC*)pPropSpec,
0,
NULL,
&Context);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvValidateItemProperties, wiasCreatePropContext failed"));
return hr;
}
//
// Use the WIA Service to update the valid values
// for format. It will pull the values from the
// structure returnd by drvGetWiaFormatInfo, using the
// new value for tymed.
//
hr = wiasUpdateValidFormat(pWiasContext, &Context, (IWiaMiniDrv*) this);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvValidateItemProperties, wiasUpdateValidFormat failed"));
return hr;
}
//
// Free the property context
//
hr = wiasFreePropContext(&Context);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvValidateItemProperties, wiasFreePropContext failed"));
return hr;
}
//
// Update the item size
//
hr = SetItemSize(pWiasContext);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvValidateItemProperties, SetItemSize failed"));
return hr;
}
}
//
// If the format was changed, just update the item size
//
else if (wiauPropInPropSpec(nPropSpec, pPropSpec, WIA_IPA_FORMAT))
{
//
// Update the item size
//
hr = SetItemSize(pWiasContext);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvValidateItemProperties, SetItemSize failed"));
return hr;
}
}
//
// Unconditionally update WIA_IPA_FILE_EXTENSION to match the current format
//
ITEM_CONTEXT *pItemCtx;
hr = GetDrvItemContext(pWiasContext, &pItemCtx);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvValidateItemProperties, GetDrvItemContext failed"));
return hr;
}
BSTR bstrFileExt = NULL;
ITEM_INFO *pItemInfo = pItemCtx->ItemHandle;
FORMAT_INFO *pFormatInfo = NULL;
if (pItemInfo)
{
pFormatInfo = FormatCode2FormatInfo(pItemInfo->Format);
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);
}
}
}
hr = wiasWritePropStr(pWiasContext, WIA_IPA_FILENAME_EXTENSION, bstrFileExt);
if (bstrFileExt)
{
SysFreeString(bstrFileExt);
bstrFileExt = NULL;
}
}
return hr;
}
/**************************************************************************\
* CWiaCameraDevice::drvDeleteItem
*
* Delete an item from the device.
*
* Arguments:
*
* pWiasContext - Indicates the item to delete.
* lFlags - Operation flags, unused.
* plDevErrVal - Pointer to the device error value.
*
\**************************************************************************/
HRESULT CWiaCameraDevice::drvDeleteItem(
BYTE *pWiasContext,
LONG lFlags,
LONG *plDevErrVal)
{
plDevErrVal = 0;
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL1,
"CWiaCameraDevice::drvDeleteItem");
HRESULT hr = S_OK;
ITEM_CONTEXT *pItemCtx = NULL;
IWiaDrvItem *pDrvItem;
hr = GetDrvItemContext(pWiasContext, &pItemCtx, &pDrvItem);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvDeleteItem, GetDrvItemContext failed"));
return hr;
}
hr = m_pDevice->DeleteItem(pItemCtx->ItemHandle);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvDeleteItem, delete item failed"));
return hr;
}
//
// Get the item's full name
//
BSTR bstrFullName;
hr = pDrvItem->GetFullItemName(&bstrFullName);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvDeleteItem, GetFullItemName failed"));
WIAS_LHRESULT(m_pIWiaLog, hr);
return hr;
}
//
// Queue an "item deleted" event
//
hr = wiasQueueEvent(m_bstrDeviceID,
&WIA_EVENT_ITEM_DELETED,
bstrFullName);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvDeleteItem, wiasQueueEvent failed"));
WIAS_LHRESULT(m_pIWiaLog, hr);
// Continue to free the string and return hr
}
SysFreeString(bstrFullName);
return hr;
}
/**************************************************************************\
* CWiaCameraDevice::drvNotifyPnpEvent
*
* Pnp Event received by device manager. This is called when a Pnp event
* is received for this device.
*
* Arguments:
*
*
*
\**************************************************************************/
HRESULT CWiaCameraDevice::drvNotifyPnpEvent(
const GUID *pEventGUID,
BSTR bstrDeviceID,
ULONG ulReserved)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL1,
"CWiaCameraDevice::DrvNotifyPnpEvent");
HRESULT hr = S_OK;
return hr;
}
/**************************************************************************\
* CWiaCameraDevice::drvGetCapabilities
*
* Get supported device commands and events as an array of WIA_DEV_CAPS.
*
* Arguments:
*
* pWiasContext - Pointer to the WIA item, unused.
* lFlags - Operation flags.
* pcelt - Pointer to returned number of elements in
* returned GUID array.
* ppCapabilities - Pointer to returned GUID array.
* plDevErrVal - Pointer to the device error value.
*
\**************************************************************************/
HRESULT CWiaCameraDevice::drvGetCapabilities(
BYTE *pWiasContext,
LONG ulFlags,
LONG *pcelt,
WIA_DEV_CAP_DRV **ppCapabilities,
LONG *plDevErrVal)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL1,
"CWiaCameraDevice::drvGetCapabilites");
*plDevErrVal = 0;
if( !m_pCapabilities )
{
HRESULT hr = BuildCapabilities();
if( hr != S_OK )
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvGetCapabilities, BuildCapabilities failed"));
return (hr);
}
}
//
// Return values depend on the passed flags. Flags specify whether we should return
// commands, events, or both.
//
switch (ulFlags) {
case WIA_DEVICE_COMMANDS:
//
// report commands only
//
*pcelt = m_NumSupportedCommands;
*ppCapabilities = &m_pCapabilities[m_NumSupportedEvents];
break;
case WIA_DEVICE_EVENTS:
//
// report events only
//
*pcelt = m_NumSupportedEvents;
*ppCapabilities = m_pCapabilities;
break;
case (WIA_DEVICE_COMMANDS | WIA_DEVICE_EVENTS):
//
// report both events and commands
//
*pcelt = m_NumCapabilities;
*ppCapabilities = m_pCapabilities;
break;
default:
//
// invalid request
//
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvGetCapabilities, invalid flags"));
return E_INVALIDARG;
}
return S_OK;
}
/**************************************************************************\
* CWiaCameraDevice::drvDeviceCommand
*
* Issue a command to the device.
*
* Arguments:
*
* pWiasContext - Pointer to the WIA item.
* lFlags - Operation flags, unused.
* plCommand - Pointer to command GUID.
* ppWiaDrvItem - Optional pointer to returned item, unused.
* plDevErrVal - Pointer to the device error value.
*
\**************************************************************************/
HRESULT CWiaCameraDevice::drvDeviceCommand(
BYTE *pWiasContext,
LONG lFlags,
const GUID *plCommand,
IWiaDrvItem **ppWiaDrvItem,
LONG *plDevErrVal)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL1,
"CWiaCameraDevice::drvDeviceCommand");
*plDevErrVal = 0;
HRESULT hr = S_OK;
//
// Check which command was issued
//
if (*plCommand == WIA_CMD_SYNCHRONIZE) {
//
// SYNCHRONIZE - Re-build the item tree, if the device needs it.
//
if (m_DeviceInfo.bSyncNeeded)
{
hr = DeleteItemTree(WiaItemTypeDisconnected);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvDeviceCommand, DeleteItemTree failed"));
return hr;
}
m_pDevice->FreeDeviceInfo(&m_DeviceInfo);
memset(&m_DeviceInfo, 0, sizeof(m_DeviceInfo));
hr = m_pDevice->GetDeviceInfo(&m_DeviceInfo);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvDeviceCommand, GetDeviceInfo failed"));
return hr;
}
hr = BuildItemTree();
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvDeviceCommand, BuildItemTree failed"));
return hr;
}
}
}
#if DEADCODE
//
// Not implemented yet
//
else if (*plCommand == WIA_CMD_TAKE_PICTURE) {
//
// TAKE_PICTURE - Command the camera to capture a new image.
//
ITEM_HANDLE NewImage = 0;
hr = m_pDevice->TakePicture(&NewImage);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvDeviceCommand, take picture failed"));
return hr;
}
// ISSUE-10/17/2000-davepar Create a new driver item for the new image
}
#endif
else {
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvDeviceCommand, unknown command"));
hr = E_NOTIMPL;
}
return hr;
}
/**************************************************************************\
* CWiaCameraDevice::drvAnalyzeItem
*
* This device does not support image analysis, so return E_NOTIMPL.
*
* Arguments:
*
* pWiasContext - Pointer to the device item to be analyzed.
* lFlags - Operation flags.
* plDevErrVal - Pointer to the device error value.
*
\**************************************************************************/
HRESULT CWiaCameraDevice::drvAnalyzeItem(
BYTE *pWiasContext,
LONG lFlags,
LONG *plDevErrVal)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL1,
"CWiaCameraDevice::drvAnalyzeItem");
*plDevErrVal = 0;
return E_NOTIMPL;
}
/**************************************************************************\
* CWiaCameraDevice::drvGetDeviceErrorStr
*
* Map a device error value to a string.
*
* Arguments:
*
* lFlags - Operation flags, unused.
* lDevErrVal - Device error value.
* ppszDevErrStr - Pointer to returned error string.
* plDevErrVal - Pointer to the device error value.
*
\**************************************************************************/
HRESULT CWiaCameraDevice::drvGetDeviceErrorStr(
LONG lFlags,
LONG lDevErrVal,
LPOLESTR *ppszDevErrStr,
LONG *plDevErr)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL1,
"CWiaCameraDevice::drvGetDeviceErrorStr");
HRESULT hr = S_OK;
*plDevErr = 0;
//
// Map device errors to a string appropriate for showing to the user
//
// ISSUE-10/17/2000-davepar These should be read from the resource file
switch (lDevErrVal) {
case 0:
*ppszDevErrStr = L"No Error";
break;
default:
*ppszDevErrStr = L"Device Error, Unknown Error";
hr = E_FAIL;
}
return hr;
}
/**************************************************************************\
* SetItemSize
*
* Calulate the new item size, and write the new Item Size property value.
*
* Arguments:
*
* pWiasContext - item
*
\**************************************************************************/
HRESULT CWiaCameraDevice::SetItemSize(BYTE *pWiasContext)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"CWiaCameraDevice::SetItemSize");
HRESULT hr = S_OK;
LONG lItemSize = 0;
LONG lWidthInBytes = 0;
GUID guidFormatID = GUID_NULL;
LONG lNumProperties = 2;
PROPVARIANT pv[2];
PROPSPEC ps[2] = {{PRSPEC_PROPID, WIA_IPA_ITEM_SIZE},
{PRSPEC_PROPID, WIA_IPA_BYTES_PER_LINE}};
//
// Get the driver item context
//
ITEM_CONTEXT *pItemCtx = NULL;
hr = GetDrvItemContext(pWiasContext, &pItemCtx);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetItemSize, GetDrvItemContext failed"));
return hr;
}
//
// Read the format GUID
//
hr = wiasReadPropGuid(pWiasContext, WIA_IPA_FORMAT, &guidFormatID, NULL, TRUE);
if (FAILED(hr)) {
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetItemSize, ReadPropLong WIA_IPA_FORMAT error"));
return hr;
}
if (IsEqualCLSID(guidFormatID, WiaImgFmt_BMP) ||
IsEqualCLSID(guidFormatID, WiaImgFmt_MEMORYBMP))
{
if( !(pItemCtx->ItemHandle->Width) ||
!(pItemCtx->ItemHandle->Depth) ||
!(pItemCtx->ItemHandle->Height) )
{ // Since we are going to use these, make sure they are filled in
LONG lNumPropToRead = 3;
PROPSPEC pPropsToRead[3] = { {PRSPEC_PROPID, WIA_IPA_DEPTH},
{PRSPEC_PROPID, WIA_IPA_NUMBER_OF_LINES},
{PRSPEC_PROPID, WIA_IPA_PIXELS_PER_LINE} };
hr = ReadChildItemProperties(pWiasContext, lNumPropToRead, pPropsToRead);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetItemSize, ReadItemProperties failed"));
return hr;
}
}
lItemSize = sizeof(BITMAPINFOHEADER);
//
// if this is a file, add file header to size
//
if (IsEqualCLSID(guidFormatID, WiaImgFmt_BMP))
{
lItemSize += sizeof(BITMAPFILEHEADER);
}
//
// Calculate number of bytes per line, width must be
// aligned to 4 byte boundary.
//
lWidthInBytes = ((pItemCtx->ItemHandle->Width * pItemCtx->ItemHandle->Depth + 31) & ~31) / 8;
//
// Calculate image size
//
lItemSize += lWidthInBytes * pItemCtx->ItemHandle->Height;
}
else
{
lItemSize = pItemCtx->ItemHandle->Size;
lWidthInBytes = 0;
}
//
// Initialize propvar's. Then write the values. Don't need to call
// PropVariantClear when done, since there are only LONG values.
//
for (int i = 0; i < lNumProperties; i++) {
PropVariantInit(&pv[i]);
pv[i].vt = VT_I4;
}
pv[0].lVal = lItemSize;
pv[1].lVal = lWidthInBytes;
//
// Write WIA_IPA_ITEM_SIZE and WIA_IPA_BYTES_PER_LINE property values
//
hr = wiasWriteMultiple(pWiasContext, lNumProperties, ps, pv);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetItemSize, wiasWriteMultiple failed"));
return hr;
}
return hr;
}
/*******************************************************************************
*
* P R I V A T E M E T H O D S
*
*******************************************************************************/
/**************************************************************************\
* DeleteItemTree
*
* Call device manager to unlink and release our reference to
* all items in the driver item tree.
*
* Arguments:
*
*
*
\**************************************************************************/
HRESULT
CWiaCameraDevice::DeleteItemTree(LONG lReason)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"CWiaCameraDevice::DeleteItemTree");
HRESULT hr = S_OK;
//
// If no tree, return.
//
if (!m_pRootItem) {
return S_OK;
}
//
// Call device manager to unlink the driver item tree.
//
hr = m_pRootItem->UnlinkItemTree(lReason);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("DeleteItemTree, UnlinkItemTree failed"));
return hr;
}
m_pRootItem->Release();
m_pRootItem = NULL;
return hr;
}
/**************************************************************************\
* BuildItemTree
*
* The device uses the WIA Service functions to build up a tree of
* device items.
*
* Arguments:
*
*
*
\**************************************************************************/
HRESULT
CWiaCameraDevice::BuildItemTree()
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"CWiaCameraDevice::BuildItemTree");
HRESULT hr = S_OK;
//
// Make sure the item tree doesn't already exist
//
if (m_pRootItem)
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildItemTree, item tree already exists"));
return E_FAIL;
}
//
// Create the root item name
//
BSTR bstrRoot = SysAllocString(L"Root");
if (!bstrRoot)
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildItemTree, SysAllocString failed"));
hr = E_OUTOFMEMORY;
}
//
// Create the root item
//
ITEM_CONTEXT *pItemCtx = NULL;
hr = wiasCreateDrvItem(WiaItemTypeFolder | WiaItemTypeDevice | WiaItemTypeRoot,
bstrRoot,
m_bstrRootFullItemName,
(IWiaMiniDrv *)this,
sizeof(ITEM_CONTEXT),
(BYTE **) &pItemCtx,
&m_pRootItem);
SysFreeString(bstrRoot);
if (FAILED(hr)) {
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildItemTree, wiasCreateDrvItem failed"));
return hr;
}
//
// Initialize item context fields for the root
//
memset(pItemCtx, 0, sizeof(ITEM_CONTEXT));
pItemCtx->ItemHandle = ROOT_ITEM_HANDLE;
//
// Put the root item in the handle map
//
m_HandleItemMap.Add(ROOT_ITEM_HANDLE, m_pRootItem);
//
// Get the list of items from the camera
//
ITEM_HANDLE *pItemArray = new ITEM_HANDLE[m_DeviceInfo.TotalItems];
if (!pItemArray)
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildItemTree, memory allocation failed"));
return E_OUTOFMEMORY;
}
m_pDevice->GetItemList(pItemArray);
//
// Create a driver item for each item on the camera
//
for (int count = 0; count < m_DeviceInfo.TotalItems; count++)
{
hr = AddObject(pItemArray[count]);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildItemTree, AddObject failed"));
return hr;
}
}
return hr;
}
/**************************************************************************\
* AddObject
*
* Helper function to add an object to the tree
*
* Arguments:
*
* pItemHandle - Pointer to the item handle
*
\**************************************************************************/
HRESULT CWiaCameraDevice::AddObject(ITEM_HANDLE ItemHandle, BOOL bQueueEvent)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL1,
"CWiaCameraDevice::AddObject");
HRESULT hr = S_OK;
LONG ExtraFlags = 0;
//
// Get information about the item from the camera
//
ITEM_INFO *pItemInfo = ItemHandle;
if (!pItemInfo)
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("AddObject, invalid arg"));
return E_INVALIDARG;
}
//
// Look up the item's parent in the map
//
IWiaDrvItem *pParent = NULL;
pParent = m_HandleItemMap.Lookup(pItemInfo->Parent);
//
// If a parent wasn't found, just use the root as the parent
//
if (!pParent)
{
pParent = m_pRootItem;
}
#ifdef CHECK_DOT_IN_FILENAME
//
// Make sure there is no filename extension in the name
//
if (wcschr(pItemInfo->pName, L'.'))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("AddObject, item name=%S", pItemInfo->pName));
return E_FAIL;
}
#endif
//
// Create the item's full name
//
BSTR bstrItemFullName = NULL;
BSTR bstrParentName = NULL;
hr = pParent->GetFullItemName(&bstrParentName);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("AddObject, GetFullItemName failed"));
return hr;
}
WCHAR wcsName[MAX_PATH];
StringCchPrintfW(wcsName, MAX_PATH, L"%s\\%s", bstrParentName, pItemInfo->pName);
bstrItemFullName = SysAllocString(wcsName);
if (!bstrItemFullName)
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("AddObject, SysAllocString failed"));
return E_OUTOFMEMORY;
}
//
// Look up information about the item's format
//
LONG lItemType=0;
//
// See if the item has attachments
//
if (pItemInfo->bHasAttachments)
ExtraFlags |= WiaItemTypeHasAttachments;
if( pItemInfo->bIsFolder)
{
lItemType = ITEMTYPE_FOLDER;
}
else
{
lItemType = m_FormatInfo[pItemInfo->Format].ItemType;
}
//
// Create the driver item
//
IWiaDrvItem *pItem = NULL;
ITEM_CONTEXT *pItemCtx = NULL;
hr = wiasCreateDrvItem(lItemType | ExtraFlags,
pItemInfo->pName,
bstrItemFullName,
(IWiaMiniDrv *)this,
sizeof(ITEM_CONTEXT),
(BYTE **) &pItemCtx,
&pItem);
SysFreeString(bstrParentName);
if (FAILED(hr) || !pItem || !pItemCtx)
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("AddObject, wiasCreateDrvItem failed"));
return hr;
}
//
// Fill in the driver item context. Wait until the thumbnail is requested before
// reading it in.
//
memset(pItemCtx, 0, sizeof(ITEM_CONTEXT));
pItemCtx->ItemHandle = ItemHandle;
//
// Place the new item under it's parent
//
hr = pItem->AddItemToFolder(pParent);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("AddObject, AddItemToFolder failed"));
WIAS_LHRESULT(m_pIWiaLog, hr);
return hr;
}
//
// Add the item to the item handle/driver item map
//
if (!m_HandleItemMap.Add(ItemHandle, pItem))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("AddObject, handle item map Add failed"));
return E_OUTOFMEMORY;
}
//
// Eventhough, there is still a reference to the item in the handle/item map, release
// it here, because there isn't a convenient place to do it later
//
pItem->Release();
//
// Post an item added event, if requested
//
if (bQueueEvent)
{
hr = wiasQueueEvent(m_bstrDeviceID, &WIA_EVENT_ITEM_CREATED, bstrItemFullName);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("AddObject, wiasQueueEvent failed"));
WIAS_LHRESULT(m_pIWiaLog, hr);
return hr;
}
}
SysFreeString(bstrItemFullName);
return hr;
}
/**************************************************************************\
* BuildCapabilities
*
* This helper initializes the capabilities array
*
* Arguments:
*
* none
*
\**************************************************************************/
HRESULT CWiaCameraDevice::BuildCapabilities()
{
HRESULT hr = S_OK;
if(NULL != m_pCapabilities) {
//
// Capabilities have already been initialized,
// so return S_OK.
//
return hr;
}
m_NumSupportedCommands = 1;
m_NumSupportedEvents = 3;
m_NumCapabilities = (m_NumSupportedCommands + m_NumSupportedEvents);
m_pCapabilities = new WIA_DEV_CAP_DRV[m_NumCapabilities];
if (m_pCapabilities) {
//
// Initialize EVENTS
//
// WIA_EVENT_DEVICE_CONNECTED
GetOLESTRResourceString(IDS_EVENT_DEVICE_CONNECTED_NAME,&(m_pCapabilities[0].wszName),TRUE);
GetOLESTRResourceString(IDS_EVENT_DEVICE_CONNECTED_DESC,&(m_pCapabilities[0].wszDescription),TRUE);
m_pCapabilities[0].guid = (GUID*)&WIA_EVENT_DEVICE_CONNECTED;
m_pCapabilities[0].ulFlags = WIA_NOTIFICATION_EVENT | WIA_ACTION_EVENT;
m_pCapabilities[0].wszIcon = WIA_ICON_DEVICE_CONNECTED;
// WIA_EVENT_DEVICE_DISCONNECTED
GetOLESTRResourceString(IDS_EVENT_DEVICE_DISCONNECTED_NAME,&(m_pCapabilities[1].wszName),TRUE);
GetOLESTRResourceString(IDS_EVENT_DEVICE_DISCONNECTED_DESC,&(m_pCapabilities[1].wszDescription),TRUE);
m_pCapabilities[1].guid = (GUID*)&WIA_EVENT_DEVICE_DISCONNECTED;
m_pCapabilities[1].ulFlags = WIA_NOTIFICATION_EVENT;
m_pCapabilities[1].wszIcon = WIA_ICON_DEVICE_DISCONNECTED;
// WIA_EVENT_ITEM_DELETED
GetOLESTRResourceString(IDS_EVENT_ITEM_DELETED_NAME,&(m_pCapabilities[2].wszName),TRUE);
GetOLESTRResourceString(IDS_EVENT_ITEM_DELETED_DESC,&(m_pCapabilities[2].wszDescription),TRUE);
m_pCapabilities[2].guid = (GUID*)&WIA_EVENT_ITEM_DELETED;
m_pCapabilities[2].ulFlags = WIA_NOTIFICATION_EVENT;
m_pCapabilities[2].wszIcon = WIA_ICON_ITEM_DELETED;
//
// Initialize COMMANDS
//
// WIA_CMD_SYNCHRONIZE
GetOLESTRResourceString(IDS_CMD_SYNCRONIZE_NAME,&(m_pCapabilities[3].wszName),TRUE);
GetOLESTRResourceString(IDS_CMD_SYNCRONIZE_DESC,&(m_pCapabilities[3].wszDescription),TRUE);
m_pCapabilities[3].guid = (GUID*)&WIA_CMD_SYNCHRONIZE;
m_pCapabilities[3].ulFlags = 0;
m_pCapabilities[3].wszIcon = WIA_ICON_SYNCHRONIZE;
// ISSUE-10/17/2000-davepar Add TakePicture if the camera supports it
}
else {
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildCapabilities, memory allocation failed"));
hr = E_OUTOFMEMORY;
}
return hr;
}
/**************************************************************************\
* DeleteCapabilitiesArrayContents
*
* This helper deletes the capabilities array
*
* Arguments:
*
* none
*
\**************************************************************************/
HRESULT CWiaCameraDevice::DeleteCapabilitiesArrayContents()
{
HRESULT hr = S_OK;
if (m_pCapabilities) {
for (LONG i = 0; i < m_NumCapabilities; i++) {
CoTaskMemFree(m_pCapabilities[i].wszName);
CoTaskMemFree(m_pCapabilities[i].wszDescription);
}
delete []m_pCapabilities;
m_pCapabilities = NULL;
}
m_NumSupportedCommands = 0;
m_NumSupportedEvents = 0;
m_NumCapabilities = 0;
return hr;
}
/**************************************************************************\
* GetBSTRResourceString
*
* This helper gets a BSTR from a resource location
*
* Arguments:
*
* lResourceID - Resource ID of the target BSTR value
* pBSTR - pointer to a BSTR value (caller must free this string)
* bLocal - TRUE - for local resources, FALSE - for wiaservc resources
*
\**************************************************************************/
HRESULT CWiaCameraDevice::GetBSTRResourceString(LONG lResourceID, BSTR *pBSTR, BOOL bLocal)
{
HRESULT hr = S_OK;
TCHAR szStringValue[MAX_PATH];
if (bLocal) {
//
// We are looking for a resource in our own private resource file
//
LoadString(g_hInst, lResourceID, szStringValue, MAX_PATH);
//
// NOTE: caller must free this allocated BSTR
//
#ifdef UNICODE
*pBSTR = SysAllocString(szStringValue);
#else
WCHAR wszStringValue[MAX_PATH];
//
// convert szStringValue from char* to unsigned short* (ANSI only)
//
MultiByteToWideChar(CP_ACP,
MB_PRECOMPOSED,
szStringValue,
lstrlenA(szStringValue)+1,
wszStringValue,
ARRAYSIZE(wszStringValue));
*pBSTR = SysAllocString(wszStringValue);
#endif
if (!*pBSTR) {
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetBSTRResourceString, SysAllocString failed"));
return E_OUTOFMEMORY;
}
} else {
//
// We are looking for a resource in the wiaservc's resource file
//
hr = E_NOTIMPL;
}
return hr;
}
/**************************************************************************\
* GetOLESTRResourceString
*
* This helper gets a LPOLESTR from a resource location
*
* Arguments:
*
* lResourceID - Resource ID of the target BSTR value
* ppsz - pointer to a OLESTR value (caller must free this string)
* bLocal - TRUE - for local resources, FALSE - for wiaservc resources
*
\**************************************************************************/
HRESULT CWiaCameraDevice::GetOLESTRResourceString(LONG lResourceID,LPOLESTR *ppsz,BOOL bLocal)
{
HRESULT hr = S_OK;
const int c_nMaxCharPerString = 255;
TCHAR szStringValue[c_nMaxCharPerString];
if(bLocal) {
//
// We are looking for a resource in our own private resource file
//
LoadString(g_hInst,lResourceID,szStringValue,255);
//
// NOTE: caller must free this allocated BSTR
//
#ifdef UNICODE
*ppsz = NULL;
*ppsz = (LPOLESTR)CoTaskMemAlloc(sizeof(szStringValue));
if(*ppsz != NULL) {
StringCchCopyW(*ppsz, c_nMaxCharPerString, szStringValue);
} else {
return E_OUTOFMEMORY;
}
#else
WCHAR wszStringValue[c_nMaxCharPerString];
//
// convert szStringValue from char* to unsigned short* (ANSI only)
//
MultiByteToWideChar(CP_ACP,
MB_PRECOMPOSED,
szStringValue,
lstrlenA(szStringValue)+1,
wszStringValue,
ARRAYSIZE(wszStringValue));
*ppsz = NULL;
*ppsz = (LPOLESTR)CoTaskMemAlloc(sizeof(wszStringValue));
if(*ppsz != NULL) {
StringCchCopyW(*ppsz, c_nMaxCharPerString, wszStringValue);
} else {
return E_OUTOFMEMORY;
}
#endif
} else {
//
// We are looking for a resource in the wiaservc's resource file
//
hr = E_NOTIMPL;
}
return hr;
}
/**************************************************************************\
* VerticalFlip
*
*
*
* Arguments:
*
*
*
\**************************************************************************/
VOID CWiaCameraDevice::VerticalFlip(
ITEM_CONTEXT *pItemCtx,
PMINIDRV_TRANSFER_CONTEXT pDataTransferContext
)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"CWiaCameraDevice::VerticalFlip");
HRESULT hr = S_OK;
LONG iHeight;
LONG iWidth = pItemCtx->ItemHandle->Width;
ULONG uiDepth = pItemCtx->ItemHandle->Depth;
LONG ScanLineWidth = iWidth * uiDepth / 8;
PBITMAPINFO pbmi = NULL;
PBYTE pImageTop = NULL;
//
// find out if data is TYMED_FILE or TYMED_HGLOBAL
//
if (pDataTransferContext->tymed == TYMED_FILE) {
pbmi = (PBITMAPINFO)(pDataTransferContext->pTransferBuffer + sizeof(BITMAPFILEHEADER));
} else if (pDataTransferContext->tymed == TYMED_HGLOBAL) {
pbmi = (PBITMAPINFO)(pDataTransferContext->pTransferBuffer);
} else {
return;
}
//
// init memory pointer and height
//
pImageTop = &pDataTransferContext->pTransferBuffer[0] + pDataTransferContext->lHeaderSize;
iHeight = pbmi->bmiHeader.biHeight;
//
// try to allocat a temp scan line buffer
//
PBYTE pBuffer = (PBYTE)LocalAlloc(LPTR,ScanLineWidth);
if (pBuffer != NULL) {
LONG index;
PBYTE pImageBottom;
pImageBottom = pImageTop + (iHeight-1) * ScanLineWidth;
for (index = 0;index < (iHeight/2);index++) {
memcpy(pBuffer,pImageTop,ScanLineWidth);
memcpy(pImageTop,pImageBottom,ScanLineWidth);
memcpy(pImageBottom,pBuffer,ScanLineWidth);
pImageTop += ScanLineWidth;
pImageBottom -= ScanLineWidth;
}
LocalFree(pBuffer);
}
}
/**************************************************************************\
* FormatCode2FormatInfo
*
* This helper function looks up information about an item's format based
* on the format code.
*
* Arguments:
*
* ItemType - the item's type
*
\**************************************************************************/
FORMAT_INFO *CWiaCameraDevice::FormatCode2FormatInfo(FORMAT_CODE FormatCode)
{
if (FormatCode > (LONG)m_NumFormatInfo)
FormatCode = 0;
if (FormatCode < 0)
FormatCode = 0;
return &m_FormatInfo[FormatCode];
}
/**************************************************************************\
* GetDrvItemContext
*
* This helper function gets the driver item context.
*
* Arguments:
*
* pWiasContext - service context
* ppItemCtx - pointer to pointer to item context
*
\**************************************************************************/
HRESULT CWiaCameraDevice::GetDrvItemContext(BYTE *pWiasContext, ITEM_CONTEXT **ppItemCtx,
IWiaDrvItem **ppDrvItem)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL1,
"CWiaCameraDevice::GetDrvItemContext");
HRESULT hr = S_OK;
if (!pWiasContext || !ppItemCtx)
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetDrvItemContext, invalid arg"));
return E_INVALIDARG;
}
IWiaDrvItem *pWiaDrvItem;
hr = wiasGetDrvItem(pWiasContext, &pWiaDrvItem);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetDrvItemContext, wiasGetDrvItem failed"));
WIAS_LHRESULT(m_pIWiaLog, hr);
return hr;
}
*ppItemCtx = NULL;
hr = pWiaDrvItem->GetDeviceSpecContext((BYTE **) ppItemCtx);
if (FAILED(hr))
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetDrvItemContext, GetDeviceSpecContext failed"));
WIAS_LHRESULT(m_pIWiaLog, hr);
return hr;
}
if (!*ppItemCtx)
{
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetDrvItemContext, item context is null"));
return E_FAIL;
}
if (ppDrvItem)
{
*ppDrvItem = pWiaDrvItem;
}
return hr;
}