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.
1899 lines
55 KiB
1899 lines
55 KiB
/*******************************************************************************
|
|
*
|
|
* (C) COPYRIGHT 2000, MICROSOFT CORP.
|
|
*
|
|
* TITLE: IWiaMiniDrv.cpp
|
|
*
|
|
* VERSION: 1.0
|
|
*
|
|
* DATE: 18 July, 2000
|
|
*
|
|
* DESCRIPTION:
|
|
* Implementation of the WIA sample camera 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"
|
|
|
|
#ifndef INITGUID
|
|
#include <initguid.h>
|
|
#endif
|
|
|
|
//
|
|
// A few extra format GUIDs
|
|
//
|
|
DEFINE_GUID(GUID_NULL, 0,0,0,0,0,0,0,0,0,0,0);
|
|
DEFINE_GUID(FMT_NOTHING, 0x81a566e7,0x8620,0x4fba,0xbc,0x8e,0xb2,0x7c,0x17,0xad,0x9e,0xfd);
|
|
|
|
/**************************************************************************\
|
|
* 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)
|
|
{
|
|
DBG_FN("CWiaCameraDevice::drvInitializeWia");
|
|
|
|
if (!ppIUnknownInner || !pIUnknownOuter)
|
|
{
|
|
// optional arguments, may be NULLs
|
|
}
|
|
|
|
if (!pWiasContext || !bstrDeviceID || !bstrRootFullItemName ||
|
|
!pStiDevice || !ppIDrvItemRoot || !plDevErrVal)
|
|
{
|
|
wiauDbgError("drvInitializeWia", "invalid arguments");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
*plDevErrVal = 0;
|
|
|
|
//
|
|
// Locals
|
|
//
|
|
MCAM_ITEM_INFO *pItem = NULL;
|
|
|
|
wiauDbgTrace("drvInitializeWia", "device ID: %S", bstrDeviceID);
|
|
|
|
*ppIDrvItemRoot = NULL;
|
|
if (ppIUnknownInner)
|
|
{
|
|
*ppIUnknownInner = NULL;
|
|
}
|
|
|
|
//
|
|
// Count the number of apps connected so that resources can be
|
|
// freed when it reaches zero
|
|
//
|
|
m_iConnectedApps++;;
|
|
|
|
wiauDbgTrace("drvInitializeWia", "Number of connected apps is now %d", m_iConnectedApps);
|
|
|
|
if (m_iConnectedApps == 1)
|
|
{
|
|
//
|
|
// Save STI device interface for calling locking functions
|
|
//
|
|
m_pStiDevice = (IStiDevice *)pStiDevice;
|
|
|
|
//
|
|
// Cache the device ID
|
|
//
|
|
m_bstrDeviceID = SysAllocString(bstrDeviceID);
|
|
REQUIRE_ALLOC(m_bstrDeviceID, hr, "drvInitializeWia");
|
|
|
|
//
|
|
// Cache the root item name
|
|
//
|
|
m_bstrRootFullItemName = SysAllocString(bstrRootFullItemName);
|
|
REQUIRE_ALLOC(m_bstrRootFullItemName, hr, "drvInitializeWia");
|
|
|
|
//
|
|
// For devices connected to ports that can be shared (e.g. USB),
|
|
// open the device and initialize access to the camera
|
|
//
|
|
if (!m_pDeviceInfo->bExclusivePort) {
|
|
hr = m_pDevice->Open(m_pDeviceInfo, m_wszPortName);
|
|
REQUIRE_SUCCESS(hr, "Initialize", "Open failed");
|
|
}
|
|
|
|
//
|
|
// Get information from the device
|
|
//
|
|
hr = m_pDevice->GetDeviceInfo(m_pDeviceInfo, &pItem);
|
|
REQUIRE_SUCCESS(hr, "drvInitializeWia", "GetDeviceInfo failed");
|
|
|
|
//
|
|
// Build the capabilities array
|
|
//
|
|
hr = BuildCapabilities();
|
|
REQUIRE_SUCCESS(hr, "drvInitializeWia", "BuildCapabilities failed");
|
|
|
|
//
|
|
// Build the device item tree
|
|
//
|
|
hr = BuildItemTree(pItem);
|
|
REQUIRE_SUCCESS(hr, "drvInitializeWia", "BuildItemTree failed");
|
|
|
|
}
|
|
|
|
*ppIDrvItemRoot = m_pRootItem;
|
|
|
|
Cleanup:
|
|
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)
|
|
{
|
|
DBG_FN("CWiaCameraDevice::drvUnInitializeWia");
|
|
|
|
if (!pWiasContext)
|
|
{
|
|
wiauDbgError("drvUnInitializeWia", "invalid arguments");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
m_iConnectedApps--;
|
|
|
|
if (m_iConnectedApps == 0)
|
|
{
|
|
hr = FreeResources();
|
|
if (FAILED(hr))
|
|
wiauDbgErrorHr(hr, "drvUnInitializeWia", "FreeResources failed, continuing...");
|
|
|
|
//
|
|
// Do not delete the device object here, because GetStatus may still be called later.
|
|
//
|
|
}
|
|
|
|
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)
|
|
{
|
|
DBG_FN("CWiaCameraDevice::drvInitItemProperties");
|
|
|
|
if (!pWiasContext || !plDevErrVal)
|
|
{
|
|
wiauDbgError("drvInitItemProperties", "invalid arguments");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
*plDevErrVal = 0;
|
|
|
|
LONG lItemType;
|
|
hr = wiasGetItemType(pWiasContext, &lItemType);
|
|
REQUIRE_SUCCESS(hr, "drvInitItemProperties", "wiasGetItemType failed");
|
|
|
|
if (lItemType & WiaItemTypeRoot) {
|
|
|
|
//
|
|
// Build root item properties, initializing global
|
|
// structures with their default and valid values
|
|
//
|
|
hr = BuildRootItemProperties(pWiasContext);
|
|
REQUIRE_SUCCESS(hr, "drvInitItemProperties", "BuildRootItemProperties failed");
|
|
}
|
|
|
|
else {
|
|
|
|
//
|
|
// Build child item properties, initializing global
|
|
// structures with their default and valid values
|
|
//
|
|
hr = BuildChildItemProperties(pWiasContext);
|
|
REQUIRE_SUCCESS(hr, "drvInitItemProperties", "BuildChildItemProperties failed");
|
|
}
|
|
|
|
Cleanup:
|
|
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)
|
|
{
|
|
DBG_FN("CWiaCameraDevice::drvLockWiaDevice");
|
|
|
|
if (!plDevErrVal)
|
|
{
|
|
wiauDbgError("drvLockWiaDevice", "invalid arguments");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
*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)
|
|
{
|
|
DBG_FN("CWiaCameraDevice::drvUnLockWiaDevice");
|
|
|
|
if (!pWiasContext || !plDevErrVal)
|
|
{
|
|
wiauDbgError("drvUnLockWiaDevice", "invalid arguments");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
*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)
|
|
{
|
|
DBG_FN("CWiaCameraDevice::drvFreeDrvItemContext");
|
|
|
|
if (!pSpecContext || !plDevErrVal)
|
|
{
|
|
wiauDbgError("drvFreeDrvItemContext", "invalid arguments");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
*plDevErrVal = 0;
|
|
|
|
ITEM_CONTEXT *pItemCtx = (ITEM_CONTEXT *) pSpecContext;
|
|
|
|
if (pItemCtx)
|
|
{
|
|
if (pItemCtx->pItemInfo) {
|
|
hr = m_pDevice->FreeItemInfo(m_pDeviceInfo, pItemCtx->pItemInfo);
|
|
if (FAILED(hr))
|
|
wiauDbgErrorHr(hr, "drvFreeDrvItemContext", "FreeItemInfo failed");
|
|
}
|
|
pItemCtx->pItemInfo = NULL;
|
|
|
|
if (pItemCtx->pFormatInfo)
|
|
{
|
|
delete []pItemCtx->pFormatInfo;
|
|
pItemCtx->pFormatInfo = NULL;
|
|
}
|
|
pItemCtx->lNumFormatInfo = 0;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* 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)
|
|
{
|
|
DBG_FN("CWiaCameraDevice::drvReadItemProperties");
|
|
|
|
if (!pWiasContext || !pPropSpec || !plDevErrVal)
|
|
{
|
|
wiauDbgError("drvReadItemProperties", "invalid arguments");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
*plDevErrVal = 0;
|
|
|
|
LONG lItemType;
|
|
hr = wiasGetItemType(pWiasContext, &lItemType);
|
|
REQUIRE_SUCCESS(hr, "drvReadItemProperties", "wiasGetItemType failed");
|
|
|
|
if (lItemType & WiaItemTypeRoot) {
|
|
|
|
//
|
|
// Build root item properties, initializing global
|
|
// structures with their default and valid values
|
|
//
|
|
hr = ReadRootItemProperties(pWiasContext, nPropSpec, pPropSpec);
|
|
REQUIRE_SUCCESS(hr, "drvReadItemProperties", "ReadRootItemProperties failed");
|
|
}
|
|
|
|
else {
|
|
|
|
//
|
|
// Build child item properties, initializing global
|
|
// structures with their default and valid values
|
|
//
|
|
hr = ReadChildItemProperties(pWiasContext, nPropSpec, pPropSpec);
|
|
REQUIRE_SUCCESS(hr, "drvReadItemProperties", "ReadChildItemProperties failed");
|
|
}
|
|
|
|
Cleanup:
|
|
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)
|
|
{
|
|
DBG_FN("CWiaCameraDevice::drvWriteItemProperties");
|
|
|
|
if (!pWiasContext || !pmdtc || !plDevErrVal)
|
|
{
|
|
wiauDbgError("drvWriteItemProperties", "invalid arguments");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
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)
|
|
{
|
|
DBG_FN("CWiaCameraDevice::drvAcquireItemData");
|
|
|
|
if (!pWiasContext || !plDevErrVal || !pmdtc)
|
|
{
|
|
wiauDbgError("drvAcquireItemData", "invalid arguments");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
*plDevErrVal = 0;
|
|
|
|
//
|
|
// Locals
|
|
//
|
|
BYTE *pTempBuf = NULL;
|
|
LONG lBufSize = 0;
|
|
ITEM_CONTEXT *pItemCtx = NULL;
|
|
BOOL bConvert = FALSE;
|
|
|
|
//
|
|
// Get item context
|
|
//
|
|
hr = wiauGetDrvItemContext(pWiasContext, (VOID **) &pItemCtx);
|
|
REQUIRE_SUCCESS(hr, "drvAcquireItemData", "wiauGetDrvItemContext failed");
|
|
|
|
//
|
|
// If the format requested is BMP or DIB, and the image is not already in BMP
|
|
// format, convert it
|
|
//
|
|
bConvert = (IsEqualGUID(pmdtc->guidFormatID, WiaImgFmt_BMP) ||
|
|
IsEqualGUID(pmdtc->guidFormatID, WiaImgFmt_MEMORYBMP)) &&
|
|
!IsEqualGUID(*(pItemCtx->pItemInfo->pguidFormat), WiaImgFmt_BMP);
|
|
|
|
//
|
|
// 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->pItemInfo->lSize;
|
|
pTempBuf = new BYTE[lBufSize];
|
|
REQUIRE_ALLOC(pTempBuf, hr, "drvAcquireItemData");
|
|
}
|
|
|
|
//
|
|
// Acquire the data from the device
|
|
//
|
|
hr = AcquireData(pItemCtx, pmdtc, pTempBuf, lBufSize, bConvert);
|
|
REQUIRE_SUCCESS(hr, "drvAcquireItemData", "AcquireData failed");
|
|
if (hr == S_FALSE)
|
|
{
|
|
wiauDbgWarning("drvAcquireItemData", "Transfer cancelled");
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Now convert the data to BMP, if necessary
|
|
//
|
|
if (bConvert)
|
|
{
|
|
hr = Convert(pWiasContext, pItemCtx, pmdtc, pTempBuf, lBufSize);
|
|
REQUIRE_SUCCESS(hr, "drvAcquireItemData", "Convert failed");
|
|
}
|
|
|
|
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)
|
|
{
|
|
DBG_FN("CWiaCameraDevice::drvGetWiaFormatInfo");
|
|
|
|
if (!pWiasContext || !pcelt || !ppwfi || !plDevErrVal)
|
|
{
|
|
wiauDbgError("drvGetWiaFormatInfo", "invalid arguments");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
*plDevErrVal = 0;
|
|
|
|
//
|
|
// Locals
|
|
//
|
|
IWiaDrvItem *pWiaDrvItem = NULL;
|
|
ITEM_CONTEXT *pItemCtx = NULL;
|
|
const GUID *pguidFormat = NULL;
|
|
BOOL bAddBmp = FALSE;
|
|
|
|
*pcelt = 0;
|
|
*ppwfi = NULL;
|
|
|
|
hr = wiauGetDrvItemContext(pWiasContext, (VOID **) &pItemCtx, &pWiaDrvItem);
|
|
REQUIRE_SUCCESS(hr, "drvGetWiaFormatInfo", "wiauGetDrvItemContext failed");
|
|
|
|
if (!pItemCtx->pFormatInfo)
|
|
{
|
|
//
|
|
// The format info list is not intialized. Do it now.
|
|
//
|
|
LONG ItemType;
|
|
DWORD ui32;
|
|
|
|
hr = wiasGetItemType(pWiasContext, &ItemType);
|
|
REQUIRE_SUCCESS(hr, "drvGetWiaFormatInfo", "wiasGetItemType");
|
|
|
|
if ((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];
|
|
REQUIRE_ALLOC(pItemCtx->pFormatInfo, hr, "drvGetWiaFormatInfo");
|
|
|
|
pItemCtx->lNumFormatInfo = 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;
|
|
}
|
|
|
|
else if (ItemType & WiaItemTypeFile)
|
|
{
|
|
//
|
|
// Create the supported format for the item, based on the format stored in the
|
|
// ObjectInfo structure.
|
|
//
|
|
if (!pItemCtx->pItemInfo)
|
|
{
|
|
wiauDbgError("drvGetWiaFormatInfo", "Item info pointer in context is null");
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
|
|
pguidFormat = pItemCtx->pItemInfo->pguidFormat;
|
|
|
|
//
|
|
// If the format of the item is supported by the converter utility, add the
|
|
// BMP types to the format array, since this driver can convert those to BMP
|
|
//
|
|
bAddBmp = m_Converter.IsFormatSupported(pguidFormat);
|
|
|
|
ULONG NumWfi = bAddBmp ? 2 : 1;
|
|
|
|
//
|
|
// Allocate two entries for each format, one for file transfer and one for callback
|
|
//
|
|
WIA_FORMAT_INFO *pwfi = new WIA_FORMAT_INFO[2 * NumWfi];
|
|
REQUIRE_ALLOC(pwfi, hr, "drvGetWiaFormatInfo");
|
|
|
|
pwfi[0].guidFormatID = *pguidFormat;
|
|
pwfi[0].lTymed = TYMED_FILE;
|
|
pwfi[1].guidFormatID = *pguidFormat;
|
|
pwfi[1].lTymed = TYMED_CALLBACK;
|
|
|
|
//
|
|
// Add the BMP entries when appropriate
|
|
//
|
|
if (bAddBmp)
|
|
{
|
|
pwfi[2].guidFormatID = WiaImgFmt_BMP;
|
|
pwfi[2].lTymed = TYMED_FILE;
|
|
pwfi[3].guidFormatID = WiaImgFmt_MEMORYBMP;
|
|
pwfi[3].lTymed = TYMED_CALLBACK;
|
|
}
|
|
|
|
pItemCtx->lNumFormatInfo = 2 * NumWfi;
|
|
pItemCtx->pFormatInfo = pwfi;
|
|
}
|
|
}
|
|
|
|
*pcelt = pItemCtx->lNumFormatInfo;
|
|
*ppwfi = pItemCtx->pFormatInfo;
|
|
|
|
Cleanup:
|
|
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)
|
|
{
|
|
DBG_FN("CWiaCameraDevice::drvValidateItemProperties");
|
|
|
|
if (!pWiasContext || !pPropSpec || !plDevErrVal)
|
|
{
|
|
wiauDbgError("drvValidateItemProperties", "invalid arguments");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
*plDevErrVal = 0;
|
|
|
|
//
|
|
// Locals
|
|
//
|
|
LONG lItemType = 0;
|
|
ITEM_CONTEXT *pItemCtx = NULL;
|
|
MCAM_ITEM_INFO *pItemInfo = NULL;
|
|
BOOL bFormatUpdated = FALSE;
|
|
LONG lRights = 0;
|
|
BOOL bReadOnly = 0;
|
|
|
|
//
|
|
// Have the service validate against the valid values for each property
|
|
//
|
|
hr = wiasValidateItemProperties(pWiasContext, nPropSpec, pPropSpec);
|
|
REQUIRE_SUCCESS(hr, "drvValidateItemProperties", "wiasValidateItemProperties failed");
|
|
|
|
//
|
|
// Get the item type
|
|
//
|
|
hr = wiasGetItemType(pWiasContext, &lItemType);
|
|
REQUIRE_SUCCESS(hr, "drvValidateItemProperties", "wiasGetItemType");
|
|
|
|
//
|
|
// Validate root item properties
|
|
//
|
|
if (lItemType & WiaItemTypeRoot) {
|
|
|
|
//
|
|
// None yet
|
|
//
|
|
}
|
|
|
|
//
|
|
// Validate child item properties
|
|
//
|
|
else {
|
|
|
|
//
|
|
// Get the driver item context and item info pointer
|
|
//
|
|
hr = wiauGetDrvItemContext(pWiasContext, (VOID **) &pItemCtx);
|
|
REQUIRE_SUCCESS(hr, "drvGetWiaFormatInfo", "wiauGetDrvItemContext failed");
|
|
|
|
pItemInfo = pItemCtx->pItemInfo;
|
|
|
|
//
|
|
// See if access rights were changed
|
|
//
|
|
if (wiauPropInPropSpec(nPropSpec, pPropSpec, WIA_IPA_ACCESS_RIGHTS))
|
|
{
|
|
hr = wiasReadPropLong(pWiasContext, WIA_IPA_ACCESS_RIGHTS, &lRights, NULL, TRUE);
|
|
REQUIRE_SUCCESS(hr, "drvValidateItemProperties", "wiasReadPropLong failed");
|
|
|
|
bReadOnly = (lRights == WIA_ITEM_READ);
|
|
hr = m_pDevice->SetItemProt(m_pDeviceInfo, pItemInfo, bReadOnly);
|
|
REQUIRE_SUCCESS(hr, "drvValidateItemProperties", "SetItemProt failed");
|
|
pItemInfo->bReadOnly = bReadOnly;
|
|
}
|
|
|
|
//
|
|
// 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);
|
|
REQUIRE_SUCCESS(hr, "drvValidateItemProperties", "wiasCreatePropContext failed");
|
|
|
|
//
|
|
// Use the WIA Service to update the valid values
|
|
// for format. It will pull the values from the
|
|
// structure returned by drvGetWiaFormatInfo, using the
|
|
// new value for tymed.
|
|
//
|
|
hr = wiasUpdateValidFormat(pWiasContext, &Context, (IWiaMiniDrv*) this);
|
|
REQUIRE_SUCCESS(hr, "drvGetWiaFormatInfo", "wiasUpdateValidFormat failed");
|
|
|
|
//
|
|
// Free the property context
|
|
//
|
|
hr = wiasFreePropContext(&Context);
|
|
REQUIRE_SUCCESS(hr, "drvGetWiaFormatInfo", "wiasFreePropContext failed");
|
|
|
|
//
|
|
// The format may have changed, so update the properties
|
|
// dependent on format
|
|
//
|
|
bFormatUpdated = TRUE;
|
|
}
|
|
|
|
//
|
|
// If the format was changed, just update the item size
|
|
//
|
|
if (bFormatUpdated || wiauPropInPropSpec(nPropSpec, pPropSpec, WIA_IPA_FORMAT))
|
|
{
|
|
//
|
|
// Update the affected item properties
|
|
//
|
|
hr = wiauSetImageItemSize(pWiasContext, pItemInfo->lWidth, pItemInfo->lHeight,
|
|
pItemInfo->lDepth, pItemInfo->lSize, pItemInfo->wszExt);
|
|
REQUIRE_SUCCESS(hr, "drvGetWiaFormatInfo", "wiauSetImageItemSize failed");
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
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)
|
|
{
|
|
DBG_FN("CWiaCameraDevice::drvDeleteItem");
|
|
|
|
if (!pWiasContext || !plDevErrVal)
|
|
{
|
|
wiauDbgError("drvDeleteItem", "invalid arguments");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
*plDevErrVal = 0;
|
|
|
|
//
|
|
// Locals
|
|
//
|
|
ITEM_CONTEXT *pItemCtx = NULL;
|
|
IWiaDrvItem *pDrvItem = NULL;
|
|
BSTR bstrFullName = NULL;
|
|
|
|
hr = wiauGetDrvItemContext(pWiasContext, (VOID **) &pItemCtx, &pDrvItem);
|
|
REQUIRE_SUCCESS(hr, "drvDeleteItem", "wiauGetDrvItemContext failed");
|
|
|
|
hr = m_pDevice->DeleteItem(m_pDeviceInfo, pItemCtx->pItemInfo);
|
|
REQUIRE_SUCCESS(hr, "drvDeleteItem", "DeleteItem failed");
|
|
|
|
//
|
|
// Get the item's full name
|
|
//
|
|
hr = pDrvItem->GetFullItemName(&bstrFullName);
|
|
REQUIRE_SUCCESS(hr, "drvDeleteItem", "GetFullItemName failed");
|
|
|
|
//
|
|
// Queue an "item deleted" event
|
|
//
|
|
hr = wiasQueueEvent(m_bstrDeviceID, &WIA_EVENT_ITEM_DELETED, bstrFullName);
|
|
REQUIRE_SUCCESS(hr, "drvDeleteItem", "wiasQueueEvent failed");
|
|
|
|
Cleanup:
|
|
if (bstrFullName)
|
|
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)
|
|
{
|
|
DBG_FN("CWiaCameraDevice::DrvNotifyPnpEvent");
|
|
if (!pEventGUID)
|
|
{
|
|
wiauDbgError("drvNotifyPnpEvent", "invalid arguments");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
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)
|
|
{
|
|
DBG_FN("CWiaCameraDevice::drvGetCapabilites");
|
|
|
|
if (!pWiasContext)
|
|
{
|
|
//
|
|
// The WIA service may pass in a NULL for the pWiasContext. This is expected
|
|
// because there is a case where no item was created at the time the event was fired.
|
|
//
|
|
}
|
|
|
|
if (!pcelt || !ppCapabilities || !plDevErrVal)
|
|
{
|
|
wiauDbgError("drvGetCapabilities", "invalid arguments");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
*plDevErrVal = 0;
|
|
|
|
//
|
|
// Return values depend on the passed flags. Flags specify whether we should return
|
|
// commands, events, or both.
|
|
//
|
|
if (ulFlags & (WIA_DEVICE_COMMANDS | WIA_DEVICE_EVENTS)) {
|
|
|
|
//
|
|
// Return both events and commands
|
|
//
|
|
*pcelt = m_lNumCapabilities;
|
|
*ppCapabilities = m_pCapabilities;
|
|
}
|
|
else if (ulFlags & WIA_DEVICE_COMMANDS) {
|
|
|
|
//
|
|
// Return commands only
|
|
//
|
|
*pcelt = m_lNumSupportedCommands;
|
|
*ppCapabilities = &m_pCapabilities[m_lNumSupportedEvents];
|
|
}
|
|
else if (ulFlags & WIA_DEVICE_EVENTS) {
|
|
|
|
//
|
|
// Return events only
|
|
//
|
|
*pcelt = m_lNumSupportedEvents;
|
|
*ppCapabilities = m_pCapabilities;
|
|
}
|
|
|
|
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)
|
|
{
|
|
DBG_FN("CWiaCameraDevice::drvDeviceCommand");
|
|
|
|
if (!pWiasContext || !plCommand || !ppWiaDrvItem || !plDevErrVal)
|
|
{
|
|
wiauDbgError("drvDeviceCommand", "invalid arguments");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
*plDevErrVal = 0;
|
|
|
|
//
|
|
// Locals
|
|
//
|
|
MCAM_ITEM_INFO *pItem = NULL;
|
|
|
|
//
|
|
// Check which command was issued
|
|
//
|
|
|
|
if (*plCommand == WIA_CMD_SYNCHRONIZE) {
|
|
|
|
//
|
|
// SYNCHRONIZE - Re-build the item tree, if the device needs it.
|
|
//
|
|
if (m_pDeviceInfo->bSyncNeeded)
|
|
{
|
|
hr = m_pDevice->StopEvents(m_pDeviceInfo);
|
|
REQUIRE_SUCCESS(hr, "drvDeviceCommand", "StopEvents failed");
|
|
|
|
hr = DeleteItemTree(WiaItemTypeDisconnected);
|
|
REQUIRE_SUCCESS(hr, "drvDeviceCommand", "DeleteItemTree failed");
|
|
|
|
hr = m_pDevice->GetDeviceInfo(m_pDeviceInfo, &pItem);
|
|
REQUIRE_SUCCESS(hr, "drvDeviceCommand", "GetDeviceInfo failed");
|
|
|
|
hr = BuildItemTree(pItem);
|
|
REQUIRE_SUCCESS(hr, "drvDeviceCommand", "BuildItemTree failed");
|
|
}
|
|
}
|
|
|
|
#if DEADCODE
|
|
|
|
//
|
|
// Not implemented yet
|
|
//
|
|
else if (*plCommand == WIA_CMD_TAKE_PICTURE) {
|
|
|
|
//
|
|
// TAKE_PICTURE - Command the camera to capture a new image.
|
|
//
|
|
hr = m_pDevice->TakePicture(&pItem);
|
|
REQUIRE_SUCCESS(hr, "drvDeviceCommand", "TakePicture failed");
|
|
|
|
hr = AddObject(pItem);
|
|
REQUIRE_SUCCESS(hr, "drvDeviceCommand", "AddObject failed");
|
|
|
|
hr = LinkToParent(pItem);
|
|
REQUIRE_SUCCESS(hr, "drvDeviceCommand", "LinkToParent failed");
|
|
}
|
|
#endif
|
|
|
|
else {
|
|
wiauDbgWarning("drvDeviceCommand", "Unknown command 0x%08x", *plCommand);
|
|
hr = E_NOTIMPL;
|
|
goto Cleanup;
|
|
}
|
|
|
|
Cleanup:
|
|
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)
|
|
{
|
|
DBG_FN("CWiaCameraDevice::drvAnalyzeItem");
|
|
|
|
if (!pWiasContext || !plDevErrVal)
|
|
{
|
|
wiauDbgError("drvAnalyzeItem", "invalid arguments");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
*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)
|
|
{
|
|
DBG_FN("CWiaCameraDevice::drvGetDeviceErrorStr");
|
|
|
|
if (!ppszDevErrStr || !plDevErr)
|
|
{
|
|
wiauDbgError("drvGetDeviceErrorStr", "invalid arguments");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
*plDevErr = 0;
|
|
|
|
//
|
|
// Map device errors to a string appropriate for showing to the user
|
|
//
|
|
|
|
switch (lDevErrVal) {
|
|
case 0:
|
|
*ppszDevErrStr = NULL;
|
|
break;
|
|
|
|
default:
|
|
*ppszDevErrStr = NULL;
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* P R I V A T E M E T H O D S
|
|
*
|
|
*******************************************************************************/
|
|
|
|
/**************************************************************************\
|
|
* FreeResources
|
|
*
|
|
* Cleans up all of the resources held by the driver.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT
|
|
CWiaCameraDevice::FreeResources()
|
|
{
|
|
DBG_FN("CWiaCameraDevice::FreeResources");
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
wiauDbgTrace("FreeResources", "Connected apps is now zero, freeing resources...");
|
|
|
|
hr = m_pDevice->StopEvents(m_pDeviceInfo);
|
|
if (FAILED(hr))
|
|
wiauDbgErrorHr(hr, "FreeResources", "StopEvents failed");
|
|
|
|
// Destroy the driver item tree
|
|
hr = DeleteItemTree(WiaItemTypeDisconnected);
|
|
if (FAILED(hr))
|
|
wiauDbgErrorHr(hr, "FreeResources", "UnlinkItemTree failed");
|
|
|
|
// Delete allocated arrays
|
|
DeleteCapabilitiesArrayContents();
|
|
|
|
//
|
|
// For devices connected to ports that can be shared (e.g. USB),
|
|
// close the device
|
|
//
|
|
if (m_pDeviceInfo && !m_pDeviceInfo->bExclusivePort) {
|
|
hr = m_pDevice->Close(m_pDeviceInfo);
|
|
if (FAILED(hr))
|
|
wiauDbgErrorHr(hr, "FreeResources", "Close failed");
|
|
}
|
|
|
|
// Free the storage for the device ID
|
|
if (m_bstrDeviceID) {
|
|
SysFreeString(m_bstrDeviceID);
|
|
m_bstrDeviceID = NULL;
|
|
}
|
|
|
|
// Free the storage for the root item name
|
|
if (m_bstrRootFullItemName) {
|
|
SysFreeString(m_bstrRootFullItemName);
|
|
m_bstrRootFullItemName = NULL;
|
|
}
|
|
|
|
/*
|
|
// 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;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* DeleteItemTree
|
|
*
|
|
* Call device manager to unlink and release our reference to
|
|
* all items in the driver item tree.
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT
|
|
CWiaCameraDevice::DeleteItemTree(LONG lReason)
|
|
{
|
|
DBG_FN("CWiaCameraDevice::DeleteItemTree");
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// If no tree, return.
|
|
//
|
|
|
|
if (!m_pRootItem)
|
|
goto Cleanup;
|
|
|
|
//
|
|
// Call device manager to unlink the driver item tree.
|
|
//
|
|
hr = m_pRootItem->UnlinkItemTree(lReason);
|
|
REQUIRE_SUCCESS(hr, "DeleteItemTree", "UnlinkItemTree failed");
|
|
|
|
m_pRootItem->Release();
|
|
m_pRootItem = NULL;
|
|
|
|
Cleanup:
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* BuildItemTree
|
|
*
|
|
* The device uses the WIA Service functions to build up a tree of
|
|
* device items.
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT
|
|
CWiaCameraDevice::BuildItemTree(MCAM_ITEM_INFO *pItem)
|
|
{
|
|
DBG_FN("CWiaCameraDevice::BuildItemTree");
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Locals
|
|
//
|
|
BSTR bstrRoot = NULL;
|
|
ITEM_CONTEXT *pItemCtx = NULL;
|
|
MCAM_ITEM_INFO *pCurItem = NULL;
|
|
|
|
//
|
|
// Make sure the item tree doesn't already exist
|
|
//
|
|
if (m_pRootItem)
|
|
{
|
|
wiauDbgError("BuildItemTree", "Item tree already exists");
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Create the root item name
|
|
//
|
|
bstrRoot = SysAllocString(L"Root");
|
|
REQUIRE_ALLOC(bstrRoot, hr, "BuildItemTree");
|
|
|
|
//
|
|
// Create the root item
|
|
//
|
|
hr = wiasCreateDrvItem(WiaItemTypeFolder | WiaItemTypeDevice | WiaItemTypeRoot,
|
|
bstrRoot,
|
|
m_bstrRootFullItemName,
|
|
(IWiaMiniDrv *)this,
|
|
sizeof(ITEM_CONTEXT),
|
|
(BYTE **) &pItemCtx,
|
|
&m_pRootItem);
|
|
REQUIRE_SUCCESS(hr, "BuildItemTree", "wiasCreateDrvItem failed");
|
|
|
|
//
|
|
// Initialize item context fields for the root
|
|
//
|
|
memset(pItemCtx, 0, sizeof(ITEM_CONTEXT));
|
|
|
|
//
|
|
// Create a driver item for each item on the camera
|
|
//
|
|
pCurItem = pItem;
|
|
while (pCurItem) {
|
|
|
|
hr = AddObject(pCurItem);
|
|
REQUIRE_SUCCESS(hr, "BuildItemTree", "AddObject failed");
|
|
|
|
pCurItem = pCurItem->pNext;
|
|
}
|
|
|
|
//
|
|
// Link each item to its parent
|
|
//
|
|
pCurItem = pItem;
|
|
while (pCurItem) {
|
|
|
|
hr = LinkToParent(pCurItem);
|
|
REQUIRE_SUCCESS(hr, "BuildItemTree", "LinkToParent failed");
|
|
|
|
pCurItem = pCurItem->pNext;
|
|
}
|
|
|
|
Cleanup:
|
|
if (bstrRoot)
|
|
SysFreeString(bstrRoot);
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* AddObject
|
|
*
|
|
* Helper function to add an item to the driver item tree
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pItemInfo - Pointer to the item info structure
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT CWiaCameraDevice::AddObject(MCAM_ITEM_INFO *pItemInfo)
|
|
{
|
|
DBG_FN("CWiaCameraDevice::AddObject");
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Locals
|
|
//
|
|
LONG lItemType = 0;
|
|
BSTR bstrItemFullName = NULL;
|
|
BSTR bstrItemName = NULL;
|
|
WCHAR wszTemp[MAX_PATH];
|
|
IWiaDrvItem *pItem = NULL;
|
|
ITEM_CONTEXT *pItemCtx = NULL;
|
|
|
|
REQUIRE_ARGS(!pItemInfo, hr, "AddObject");
|
|
|
|
//
|
|
// Create the item's full name
|
|
//
|
|
hr = ConstructFullName(pItemInfo, wszTemp, sizeof(wszTemp) / sizeof(wszTemp[0]));
|
|
REQUIRE_SUCCESS(hr, "AddObject", "ConstructFullName failed");
|
|
|
|
wiauDbgTrace("AddObject", "Adding item %S", wszTemp);
|
|
|
|
bstrItemFullName = SysAllocString(wszTemp);
|
|
REQUIRE_ALLOC(bstrItemFullName, hr, "AddObject");
|
|
|
|
bstrItemName = SysAllocString(pItemInfo->pwszName);
|
|
REQUIRE_ALLOC(bstrItemName, hr, "AddObject");
|
|
|
|
//
|
|
// Make sure there is no filename extension in the name
|
|
//
|
|
if (wcschr(bstrItemFullName, L'.'))
|
|
{
|
|
wiauDbgError("AddObject", "Item names must not contain filename extensions");
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Set the item's type
|
|
//
|
|
switch (pItemInfo->iType) {
|
|
case WiaMCamTypeFolder:
|
|
lItemType = ITEMTYPE_FOLDER;
|
|
break;
|
|
case WiaMCamTypeImage:
|
|
lItemType = ITEMTYPE_IMAGE;
|
|
break;
|
|
case WiaMCamTypeAudio:
|
|
lItemType = ITEMTYPE_AUDIO;
|
|
break;
|
|
case WiaMCamTypeVideo:
|
|
lItemType = ITEMTYPE_VIDEO;
|
|
break;
|
|
default:
|
|
lItemType = ITEMTYPE_FILE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// See if the item has attachments
|
|
//
|
|
if (pItemInfo->bHasAttachments)
|
|
lItemType |= WiaItemTypeHasAttachments;
|
|
|
|
//
|
|
// Create the driver item
|
|
//
|
|
hr = wiasCreateDrvItem(lItemType,
|
|
bstrItemName,
|
|
bstrItemFullName,
|
|
(IWiaMiniDrv *)this,
|
|
sizeof(ITEM_CONTEXT),
|
|
(BYTE **) &pItemCtx,
|
|
&pItem);
|
|
|
|
REQUIRE_SUCCESS(hr, "AddObject", "wiasCreateDrvItem failed");
|
|
|
|
//
|
|
// Fill in the driver item context. Wait until the thumbnail is requested before
|
|
// reading it in.
|
|
//
|
|
memset(pItemCtx, 0, sizeof(ITEM_CONTEXT));
|
|
pItemCtx->pItemInfo = pItemInfo;
|
|
|
|
//
|
|
// Put a pointer to the driver item in the item info structure
|
|
//
|
|
pItemInfo->pDrvItem = pItem;
|
|
|
|
Cleanup:
|
|
if (bstrItemFullName)
|
|
SysFreeString(bstrItemFullName);
|
|
|
|
if (bstrItemName)
|
|
SysFreeString(bstrItemName);
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* ConstructFullName
|
|
*
|
|
* Helper function for creating the item's full name
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pItemInfo - Pointer to the item info structure
|
|
* pwszFullName - Pointer to area to construct name
|
|
* cchFullNameSize - size (in characters) of buffer provided in pwszFullName
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT CWiaCameraDevice::ConstructFullName(MCAM_ITEM_INFO *pItemInfo,
|
|
WCHAR *pwszFullName,
|
|
INT cchFullNameSize)
|
|
{
|
|
DBG_FN("CWiaCameraDevice::ConstructFullName");
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!pItemInfo)
|
|
{
|
|
wiauDbgError("ConstructFullName", "pItemInfo arg is NULL");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (pItemInfo->pParent)
|
|
{
|
|
hr = ConstructFullName(pItemInfo->pParent, pwszFullName, cchFullNameSize);
|
|
}
|
|
else
|
|
{
|
|
if (lstrlenW(m_bstrRootFullItemName) < cchFullNameSize)
|
|
{
|
|
lstrcpyW(pwszFullName, m_bstrRootFullItemName);
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr) && pItemInfo->pwszName)
|
|
{
|
|
//
|
|
// Verify that buffer is big enough to accommodate both strings + "\" + terminating zero
|
|
//
|
|
if (lstrlenW(pwszFullName) + lstrlenW(pItemInfo->pwszName) + 2 <= cchFullNameSize)
|
|
{
|
|
lstrcatW(pwszFullName, L"\\");
|
|
lstrcatW(pwszFullName, pItemInfo->pwszName);
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL; // buffer is not big enough
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* LinkToParent
|
|
*
|
|
* Helper function to link an item to its parent in the item tree
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pItemInfo - Pointer to the item info structure
|
|
* bQueueEvent - Indicates whether to queue an WIA event
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT CWiaCameraDevice::LinkToParent(MCAM_ITEM_INFO *pItemInfo, BOOL bQueueEvent)
|
|
{
|
|
DBG_FN("CWiaCameraDevice::LinkToParent");
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Locals
|
|
//
|
|
IWiaDrvItem *pParentDrvItem = NULL;
|
|
IWiaDrvItem *pItem = NULL;
|
|
BSTR bstrItemFullName = NULL;
|
|
|
|
REQUIRE_ARGS(!pItemInfo, hr, "LinkToParent");
|
|
|
|
//
|
|
// Retrieve the driver item and make sure it's not null
|
|
//
|
|
pItem = pItemInfo->pDrvItem;
|
|
if (!pItem) {
|
|
wiauDbgError("LinkToParent", "Driver item pointer is null");
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Find the item's parent driver item object
|
|
//
|
|
if (pItemInfo->pParent) {
|
|
pParentDrvItem = pItemInfo->pParent->pDrvItem;
|
|
}
|
|
else {
|
|
//
|
|
// If the parent pointer is null, use the root as the parent
|
|
//
|
|
pParentDrvItem = m_pRootItem;
|
|
}
|
|
|
|
//
|
|
// The driver item should exist for the parent, but just make sure
|
|
//
|
|
if (!pParentDrvItem) {
|
|
wiauDbgError("LinkToParent", "Parent driver item is null");
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Place the item under it's parent
|
|
//
|
|
hr = pItem->AddItemToFolder(pParentDrvItem);
|
|
REQUIRE_SUCCESS(hr, "LinkToParent", "AddItemToFolder failed");
|
|
|
|
//
|
|
// The minidriver doesn't need the driver item pointer any more, so release it.
|
|
// The service will still keep a reference until the item is deleted.
|
|
//
|
|
pItem->Release();
|
|
|
|
//
|
|
// Post an item added event, if requested
|
|
//
|
|
if (bQueueEvent)
|
|
{
|
|
hr = pItem->GetFullItemName(&bstrItemFullName);
|
|
REQUIRE_SUCCESS(hr, "LinkToParent", "GetFullItemName failed");
|
|
|
|
hr = wiasQueueEvent(m_bstrDeviceID, &WIA_EVENT_ITEM_CREATED, bstrItemFullName);
|
|
REQUIRE_SUCCESS(hr, "LinkToParent", "wiasQueueEvent failed");
|
|
}
|
|
|
|
Cleanup:
|
|
if (bstrItemFullName)
|
|
SysFreeString(bstrItemFullName);
|
|
|
|
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 with CoTaskMemFree)
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT CWiaCameraDevice::GetOLESTRResourceString(LONG lResourceID, LPOLESTR *ppsz)
|
|
{
|
|
DBG_FN("GetOLESTRResourceString");
|
|
if (!ppsz)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
TCHAR tszStringValue[255];
|
|
|
|
if (LoadString(g_hInst, lResourceID, tszStringValue, 255) == 0)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
goto Cleanup;
|
|
}
|
|
|
|
#ifdef UNICODE
|
|
//
|
|
// just allocate memory and copy string
|
|
//
|
|
*ppsz = NULL;
|
|
*ppsz = (LPOLESTR)CoTaskMemAlloc(sizeof(tszStringValue));
|
|
if (*ppsz != NULL)
|
|
{
|
|
wcscpy(*ppsz, tszStringValue);
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
#else
|
|
WCHAR wszStringValue[255];
|
|
|
|
//
|
|
// convert szStringValue from char* to unsigned short* (ANSI only)
|
|
//
|
|
if (!MultiByteToWideChar(CP_ACP,
|
|
MB_PRECOMPOSED,
|
|
tszStringValue,
|
|
lstrlenA(tszStringValue)+1,
|
|
wszStringValue,
|
|
(sizeof(wszStringValue)/sizeof(wszStringValue[0]))))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
goto Cleanup;
|
|
}
|
|
|
|
*ppsz = NULL;
|
|
*ppsz = (LPOLESTR)CoTaskMemAlloc(sizeof(wszStringValue));
|
|
if (*ppsz != NULL)
|
|
{
|
|
wcscpy(*ppsz,wszStringValue);
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
#endif
|
|
|
|
Cleanup:
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* BuildCapabilities
|
|
*
|
|
* This helper initializes the capabilities array
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT CWiaCameraDevice::BuildCapabilities()
|
|
{
|
|
DBG_FN("BuildCapabilities");
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_pCapabilities != NULL) {
|
|
|
|
//
|
|
// Capabilities have already been initialized,
|
|
// so return S_OK.
|
|
//
|
|
|
|
return hr;
|
|
}
|
|
|
|
m_lNumSupportedCommands = 1;
|
|
m_lNumSupportedEvents = 3;
|
|
m_lNumCapabilities = (m_lNumSupportedCommands + m_lNumSupportedEvents);
|
|
|
|
|
|
m_pCapabilities = new WIA_DEV_CAP_DRV[m_lNumCapabilities];
|
|
REQUIRE_ALLOC(m_pCapabilities, hr, "BuildCapabilities");
|
|
|
|
//
|
|
// Initialize EVENTS
|
|
//
|
|
|
|
//
|
|
// WIA_EVENT_DEVICE_CONNECTED
|
|
//
|
|
hr = GetOLESTRResourceString(IDS_EVENT_DEVICE_CONNECTED_NAME, &m_pCapabilities[0].wszName);
|
|
REQUIRE_SUCCESS(hr, "BuildCapabilities", "GetOLESTRResourceString failed");
|
|
|
|
hr = GetOLESTRResourceString(IDS_EVENT_DEVICE_CONNECTED_DESC, &m_pCapabilities[0].wszDescription);
|
|
REQUIRE_SUCCESS(hr, "BuildCapabilities", "GetOLESTRResourceString failed");
|
|
|
|
m_pCapabilities[0].guid = (GUID*)&WIA_EVENT_DEVICE_CONNECTED;
|
|
m_pCapabilities[0].ulFlags = WIA_NOTIFICATION_EVENT;
|
|
m_pCapabilities[0].wszIcon = WIA_ICON_DEVICE_CONNECTED;
|
|
|
|
//
|
|
// WIA_EVENT_DEVICE_DISCONNECTED
|
|
//
|
|
hr = GetOLESTRResourceString(IDS_EVENT_DEVICE_DISCONNECTED_NAME, &m_pCapabilities[1].wszName);
|
|
REQUIRE_SUCCESS(hr, "BuildCapabilities", "GetOLESTRResourceString failed");
|
|
|
|
hr = GetOLESTRResourceString(IDS_EVENT_DEVICE_DISCONNECTED_DESC, &m_pCapabilities[1].wszDescription);
|
|
REQUIRE_SUCCESS(hr, "BuildCapabilities", "GetOLESTRResourceString failed");
|
|
|
|
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
|
|
//
|
|
hr = GetOLESTRResourceString(IDS_EVENT_ITEM_DELETED_NAME, &m_pCapabilities[2].wszName);
|
|
REQUIRE_SUCCESS(hr, "BuildCapabilities", "GetOLESTRResourceString failed");
|
|
|
|
hr = GetOLESTRResourceString(IDS_EVENT_ITEM_DELETED_DESC, &m_pCapabilities[2].wszDescription);
|
|
REQUIRE_SUCCESS(hr, "BuildCapabilities", "GetOLESTRResourceString failed");
|
|
|
|
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
|
|
//
|
|
hr = GetOLESTRResourceString(IDS_CMD_SYNCRONIZE_NAME, &m_pCapabilities[3].wszName);
|
|
REQUIRE_SUCCESS(hr, "BuildCapabilities", "GetOLESTRResourceString failed");
|
|
|
|
hr = GetOLESTRResourceString(IDS_CMD_SYNCRONIZE_DESC, &m_pCapabilities[3].wszDescription);
|
|
REQUIRE_SUCCESS(hr, "BuildCapabilities", "GetOLESTRResourceString failed");
|
|
|
|
m_pCapabilities[3].guid = (GUID*)&WIA_CMD_SYNCHRONIZE;
|
|
m_pCapabilities[3].ulFlags = 0;
|
|
m_pCapabilities[3].wszIcon = WIA_ICON_SYNCHRONIZE;
|
|
|
|
Cleanup:
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* DeleteCapabilitiesArrayContents
|
|
*
|
|
* This helper deletes the capabilities array
|
|
*
|
|
* Arguments:
|
|
*
|
|
* none
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT CWiaCameraDevice::DeleteCapabilitiesArrayContents()
|
|
{
|
|
DBG_FN("DeleteCapabilitiesArrayContents");
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_pCapabilities) {
|
|
for (LONG i = 0; i < m_lNumCapabilities; i++)
|
|
{
|
|
CoTaskMemFree(m_pCapabilities[i].wszName);
|
|
CoTaskMemFree(m_pCapabilities[i].wszDescription);
|
|
}
|
|
|
|
delete []m_pCapabilities;
|
|
m_pCapabilities = NULL;
|
|
}
|
|
|
|
m_lNumSupportedCommands = 0;
|
|
m_lNumSupportedEvents = 0;
|
|
m_lNumCapabilities = 0;
|
|
|
|
return hr;
|
|
}
|
|
|
|
|