/******************************************************************************* * * (C) COPYRIGHT MICROSOFT CORP., 1998 * * TITLE: IEnumWFI.Cpp * * VERSION: 2.1 * * AUTHOR: ByronC * * DATE: 20 Mar, 1998 * 08/10/1999 - Converted from IEnumWiaFormatInfo to IEnumWIA_FORMAT_INFO * * DESCRIPTION: * Implementation of IEnumWIA_FORMAT_INFO interface for * WIA device class driver server. * *******************************************************************************/ #include "precomp.h" #include "stiexe.h" #include "wiamindr.h" #include "coredbg.h" #include "ienumwfi.h" #include "helpers.h" /********************************************************************************\ * * AllocCopyWFI * * DESCRIPTION: * Allocates and copies an array of WIA_FORMAT_INFO structures. * * Arguments: * * ulCount - the number of elements to copy * pwfiIn - pointer to the WIA_FORMAT_INFO structures * * Return Value: * * Pointer to the newly created array. * History: * * 10/04/99 Original Version * \********************************************************************************/ WIA_FORMAT_INFO *AllocCopyWFI( ULONG ulCount, WIA_FORMAT_INFO *pwfiIn) { DBG_FN(::AllocCopyWFI); if (!ulCount) { return NULL; } WIA_FORMAT_INFO *pwfi = (WIA_FORMAT_INFO*) CoTaskMemAlloc(sizeof(WIA_FORMAT_INFO) * ulCount); if (pwfi) { for (ULONG i = 0; i < ulCount; i++) { // // Copy the structure // memcpy(&pwfi[i], &pwfiIn[i], sizeof(WIA_FORMAT_INFO)); } } else { DBG_ERR(("CEnumWiaFormatInfo : AllocCopyFe, unable to allocate WIA_FORMAT_INFO buffer")); } return pwfi; } /******************************************************************************* * * CEnumWiaFormatInfo * * DESCRIPTION: * CEnumWiaFormatInfo Constructor. * * History: * * 10/04/99 Original Version * \********************************************************************************/ CEnumWiaFormatInfo::CEnumWiaFormatInfo() { m_cRef = 0; m_iCur = 0; m_cFormatInfo = 0; m_pFormatInfo = NULL; m_pCWiaItem = NULL; } /********************************************************************************\ * * Initialize * * DESCRIPTION: * Sets up the enumerator. It makes a call down to the driver for the * information needed for the enumeration. * * Arguments: * * pWiaItem - A pointer to the calling item. * pWiaMiniDrv - A pointer to the corresponding mini driver * lFlags - flags * * Return Value: * * status * * History: * * 10/04/99 Original Version * \********************************************************************************/ HRESULT CEnumWiaFormatInfo::Initialize( CWiaItem *pWiaItem) { DBG_FN(CEnumWiaFormatInfo::Initialize); HRESULT hr = E_FAIL; WIA_FORMAT_INFO *pFormat; m_iCur = 0; m_cFormatInfo = 0; m_pCWiaItem = pWiaItem; // // Make call to driver. Driver returns an array of WIA_FORMAT_INFO. // LONG lFlags = 0; { LOCK_WIA_DEVICE _LWD(pWiaItem, &hr); if(SUCCEEDED(hr)) { hr = m_pCWiaItem->m_pActiveDevice->m_DrvWrapper.WIA_drvGetWiaFormatInfo((BYTE*)pWiaItem, lFlags, &m_cFormatInfo, &pFormat, &(pWiaItem->m_lLastDevErrVal)); } } if (SUCCEEDED(hr)) { // // Check that the count we get back is valid. Zero elements is supported. // if (m_cFormatInfo < 0) { m_cFormatInfo = 0; DBG_ERR(("CEnumWiaFormatInfo::Initialize, drvGetWiaFormatInfo returned invalid count")); return E_FAIL; } // // Check whether pointer received is valid // if (IsBadReadPtr(pFormat, sizeof(WIA_FORMAT_INFO)*m_cFormatInfo)) { DBG_ERR(("CEnumWiaFormatInfo::Initialize, drvGetWiaFormatInfo returned invalid pointer")); return E_POINTER; } // // Make a local copy in case minidriver goes away. // m_pFormatInfo = AllocCopyWFI(m_cFormatInfo, pFormat); } else { DBG_ERR(("CEnumWiaFormatInfo::Initialize, Error calling driver: drvGetWiaFormatInfo failed")); } return hr; } /********************************************************************************\ * * ~CEnumWiaFormatInfo * * DESCRIPTION: * * Destructor. Frees up the m_prgfe structure, if it was allocated * * History: * * 10/04/99 Original Version * \********************************************************************************/ CEnumWiaFormatInfo::~CEnumWiaFormatInfo() { DBG_FN(CEnumWiaFormatInfo::~CEnumWiaFormatInfo); if (NULL!=m_pFormatInfo) { // // Free our local copy of the device's WIA_FORMAT_INFOs // CoTaskMemFree(m_pFormatInfo); } m_cRef = 0; m_iCur = 0; m_cFormatInfo = 0; m_pFormatInfo = NULL; m_pCWiaItem = NULL; } /******************************************************************************* * * QueryInterface * AddRef * Release * * DESCRIPTION: * CEnumWiaFormatInfo IUnknown Interface. * * PARAMETERS: * *******************************************************************************/ HRESULT _stdcall CEnumWiaFormatInfo::QueryInterface(const IID& iid, void** ppv) { *ppv = NULL; if (iid == IID_IUnknown || iid == IID_IEnumWIA_FORMAT_INFO) { *ppv = (IEnumWIA_FORMAT_INFO*) this; } else { return E_NOINTERFACE; } AddRef(); return S_OK; } ULONG _stdcall CEnumWiaFormatInfo::AddRef() { InterlockedIncrement((long*) &m_cRef); return m_cRef; } ULONG _stdcall CEnumWiaFormatInfo::Release() { ULONG ulRefCount = m_cRef - 1; if (InterlockedDecrement((long*) &m_cRef) == 0) { delete this; return 0; } return ulRefCount; } /**************************************************************************\ * Next * * Device capability enumerator, this enumerator returns an array of * WIA_FORMAT_INFO structs. * Next_Proxy ensures that last parameter is non-NULL. * * Arguments: * * cwfi - number requested. * pwfi - WIA_FORMAT_INFO returned in this array * pcwfi - returned number of entries written. NULLs are * ignored. * * Return Value: * * Status * * History: * * 10/04/99 Original Version * \**************************************************************************/ HRESULT _stdcall CEnumWiaFormatInfo::Next( ULONG cwfi, WIA_FORMAT_INFO *pwfi, ULONG *pcwfi) { DBG_FN(CEnumWiaFormatInfo::Next); HRESULT hr; ULONG ulCount; ULONG cReturn = 0L; // // Parameter validation. // if (NULL == m_pFormatInfo) { return S_FALSE; } *pcwfi = 0L; // // Check if the current index indicates that we've already been through // all the elements. // if (m_iCur >= (ULONG)m_cFormatInfo) { return S_FALSE; } // // Check that the requested number of elements exist. If not, // set ulCount to the remaining number of elements. // if (cwfi > (m_cFormatInfo - m_iCur)) { ulCount = m_cFormatInfo - m_iCur; } else { ulCount = cwfi; } // // Copy the structres into the return // for (ULONG i = 0; i < ulCount; i++) { // // Make the copy // memcpy(&pwfi[i], &m_pFormatInfo[m_iCur++], sizeof(WIA_FORMAT_INFO)); } *pcwfi = ulCount; // // Return S_FALSE if we returned less elements than requested // if (ulCount < cwfi) { return S_FALSE; } return S_OK; } /**************************************************************************\ * Skip * * Skips WIA_FORMAT_INFOs in the enumeration. * * Arguments: * * celt - number of items to skip. * * Return Value: * * status * * History: * * 12/04/99 Original Version * \**************************************************************************/ HRESULT _stdcall CEnumWiaFormatInfo::Skip(ULONG cwfi) { DBG_FN(CEnumWiaFormatInfo::Skip); if ((((m_iCur + cwfi) >= (ULONG)m_cFormatInfo)) || (NULL == m_pFormatInfo)) { return S_FALSE; } m_iCur+= cwfi; return S_OK; } /**************************************************************************\ * EnumDC::Reset * * Resets the enumeration to the first element * * Arguments: * * * Return Value: * * status * * History: * * 16/03/99 Original Version * \**************************************************************************/ HRESULT _stdcall CEnumWiaFormatInfo::Reset(void) { DBG_FN(CEnumWiaFormatInfo::Reset); m_iCur = 0; return S_OK; } /**************************************************************************\ * Clone * * Creates another IEnumWIA_FORMAT_INFO enumeration object and returns an * interface pointer to it. * * Arguments: * * ppIEnum - Address that receives the new enumeration object * * Return Value: * * * History: * * 16/03/99 Original Version * \**************************************************************************/ HRESULT _stdcall CEnumWiaFormatInfo::Clone(IEnumWIA_FORMAT_INFO **ppIEnum) { DBG_FN(CEnumWiaFormatInfo::Clone); HRESULT hr; CEnumWiaFormatInfo *pClone; *ppIEnum = NULL; // // Create the clone // pClone = new CEnumWiaFormatInfo(); if (!pClone) { return E_OUTOFMEMORY; } hr = pClone->Initialize(m_pCWiaItem); if (SUCCEEDED(hr)) { pClone->AddRef(); pClone->m_iCur = m_iCur; *ppIEnum = pClone; } else { DBG_ERR(("CEnumWiaFormatInfo::Clone, Initialization failed")); delete pClone; } return hr; } /**************************************************************************\ * GetCount * * Returns the number of elements stored in this enumerator. * * Arguments: * * pcelt - address of ULONG where to put the number of elements. * * Return Value: * * Status - S_OK if successful * E_FAIL if failed * * History: * * 05/07/99 Original Version * \**************************************************************************/ HRESULT _stdcall CEnumWiaFormatInfo::GetCount(ULONG *pcelt) { DBG_FN(CEnumWiaFormatInfo::GetCount); *pcelt = 0; // // Check that we actually have a FORMAETC list and that the count // has a non-zero value. // if(m_cFormatInfo && m_pFormatInfo) { *pcelt = m_cFormatInfo; return S_OK; } return E_FAIL; }