|
|
/*******************************************************************************
* * (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; }
|