/* Copyright (c) 1998-1999 Microsoft Corporation Module Name: collect.h Abstract: Author: */ #ifndef _MDHCP_COLLECTION_H_ #define _MDHCP_COLLECTION_H_ #include "mdhcp.h" #include "tapi3if.h" #include "resource.h" // main symbols #include // for CSafeComEnum EXTERN_C const IID LIBID_TAPI3Lib; //////////////////////////////////////////////////////////////////////// // CTapiIfCollection -- adapter from tapi3 code // Collection template for collections of IDispatch interfaces // //////////////////////////////////////////////////////////////////////// template class CTapiIfCollection : public CComDualImpl, public CComObjectRootEx, public CObjectSafeImpl { public: typedef CTapiIfCollection _CTapiCollectionBase; BEGIN_COM_MAP(_CTapiCollectionBase) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(ITCollection) COM_INTERFACE_ENTRY(IObjectSafety) COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM) END_COM_MAP() DECLARE_GET_CONTROLLING_UNKNOWN() private: int m_nSize; CComVariant * m_Var; IUnknown * m_pFTM; // Pointer to the free threaded marshaler. public: CTapiIfCollection(void) : m_nSize(0), m_Var(NULL), m_pFTM(NULL) { } // initialize HRESULT STDMETHODCALLTYPE Initialize( DWORD dwSize, T * pBegin, T * pEnd ) { int i; HRESULT hr; T * iter; LOG((MSP_TRACE, "CTapiIfCollection::Initialize - enter")); hr = CoCreateFreeThreadedMarshaler( GetControllingUnknown(), & m_pFTM ); if ( FAILED(hr) ) { LOG((MSP_ERROR, "CTapiIfCollection::Initialize: " "create FTM failed 0x%08x", hr)); return hr; } // create variant array m_nSize = dwSize; m_Var = new CComVariant[m_nSize]; if ( m_Var == NULL ) { LOG((MSP_ERROR, "CTapiIfCollection::Initialize: " "array creation failed - exit E_OUTOFMEMORY")); return E_OUTOFMEMORY; } i = 0; for (iter = pBegin; iter != pEnd; iter++) { // get IDispatch pointer IDispatch * pDisp = NULL; hr = (*iter)->QueryInterface(IID_IDispatch, (void**)&pDisp); if (hr != S_OK) { return hr; } // create a variant and add it to the collection CComVariant& var = m_Var[i]; VariantInit(&var); var.vt = VT_DISPATCH; var.pdispVal = pDisp; i++; } LOG((MSP_TRACE, "CTapiIfCollection::Initialize - exit")); return S_OK; } void FinalRelease() { LOG((MSP_TRACE, "CTapiIfCollection::FinalRelease - enter")); delete [] m_Var; if ( m_pFTM ) { m_pFTM->Release(); } LOG((MSP_TRACE, "CTapiIfCollection::FinalRelease - exit")); } STDMETHOD(get_Count)( long* retval ) { LOG((MSP_TRACE, "CTapiIfCollection::get_Count - enter")); if ( IsBadWritePtr(retval, sizeof(long) ) ) { LOG((MSP_ERROR, "CTapiIfCollection::get_Count - exit E_POINTER")); return E_POINTER; } *retval = m_nSize; LOG((MSP_TRACE, "CTapiIfCollection::get_Count - exit S_OK")); return S_OK; } STDMETHOD(get_Item)( long Index, VARIANT* retval ) { LOG((MSP_TRACE, "CTapiIfCollection::get_Item - enter")); if ( IsBadWritePtr(retval, sizeof(VARIANT) ) ) { LOG((MSP_ERROR, "CTapiIfCollection::get_Item - exit E_POINTER")); return E_POINTER; } VariantInit(retval); retval->vt = VT_UNKNOWN; retval->punkVal = NULL; // use 1-based index, VB like if ((Index < 1) || (Index > m_nSize)) { LOG((MSP_ERROR, "CTapiIfCollection::get_Item - exit E_INVALIDARG")); return E_INVALIDARG; } VariantCopy(retval, &m_Var[Index-1]); LOG((MSP_TRACE, "CTapiIfCollection::get_Item - exit S_OK")); return S_OK; } HRESULT STDMETHODCALLTYPE get__NewEnum( IUnknown** retval ) { HRESULT hr; LOG((MSP_TRACE, "CTapiIfCollection::new__Enum - enter")); if (retval == NULL) { return E_POINTER; } *retval = NULL; typedef CComObject > > enumvar; enumvar* p; // = new enumvar; hr = enumvar::CreateInstance( &p ); if ( FAILED(hr) ) { LOG((MSP_ERROR, "CTapiIfCollection::get__NewEnum: " "enum creation failed - exit 0x%08x", hr)); return hr; } hr = p->Init(&m_Var[0], &m_Var[m_nSize], NULL, AtlFlagCopy); if (SUCCEEDED(hr)) { hr = p->QueryInterface(IID_IEnumVARIANT, (void**)retval); } if (FAILED(hr)) { delete p; } LOG((MSP_TRACE, "CTapiIfCollection::new__Enum - exit")); return hr; } }; //////////////////////////////////////////////////////////////////////// // CTapiBstrCollection -- adapter from tapi3 code // Collection of BSTRs. //////////////////////////////////////////////////////////////////////// class CTapiBstrCollection : public CComObjectRootEx, public CComDualImpl, public CObjectSafeImpl { public: BEGIN_COM_MAP(CTapiBstrCollection) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(ITCollection) COM_INTERFACE_ENTRY(IObjectSafety) COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM) END_COM_MAP() DECLARE_GET_CONTROLLING_UNKNOWN() private: DWORD m_dwSize; CComVariant * m_Var; IUnknown * m_pFTM; // Pointer to the free threaded marshaler. public: CTapiBstrCollection(void) : m_dwSize(0), m_Var(NULL), m_pFTM(NULL) { } // initialize HRESULT STDMETHODCALLTYPE Initialize( DWORD dwSize, BSTR * pBegin, BSTR * pEnd ) { BSTR * i; HRESULT hr; DWORD dw = 0; LOG((MSP_TRACE, "CTapiBstrCollection::Initialize - enter")); hr = CoCreateFreeThreadedMarshaler( GetControllingUnknown(), & m_pFTM ); if ( FAILED(hr) ) { LOG((MSP_ERROR, "CTapiBstrCollection::Initialize: " "create FTM failed 0x%08x", hr)); return hr; } // create variant array m_dwSize = dwSize; m_Var = new CComVariant[m_dwSize]; if ( m_Var == NULL ) { LOG((MSP_ERROR, "CTapiBstrCollection::Initialize - exit E_OUTOFMEMORY")); return E_OUTOFMEMORY; } for (i = pBegin; i != pEnd; i++) { // create a variant and add it to the collection CComVariant& var = m_Var[dw]; var.vt = VT_BSTR; var.bstrVal = *i; dw++; } LOG((MSP_TRACE, "CTapiBstrCollection::Initialize - exit")); return S_OK; } STDMETHOD(get_Count)( long* retval ) { LOG((MSP_TRACE, "CTapiBstrCollection::get_Count - enter")); if ( IsBadWritePtr(retval, sizeof(long) ) ) { LOG((MSP_ERROR, "CTapiBstrCollection::get_Count - exit E_POINTER")); return E_POINTER; } *retval = m_dwSize; LOG((MSP_TRACE, "CTapiBstrCollection::get_Count - exit S_OK")); return S_OK; } STDMETHOD(get_Item)( long Index, VARIANT* retval ) { LOG((MSP_TRACE, "CTapiBstrCollection::get_Item - enter")); if ( IsBadWritePtr(retval, sizeof(VARIANT) ) ) { LOG((MSP_ERROR, "CTapiBstrCollection::get_Item - exit E_POINTER")); return E_POINTER; } VariantInit(retval); retval->vt = VT_BSTR; retval->bstrVal = NULL; // use 1-based index, VB like // ZoltanS: no problem with signed/unsigned, since // if Index < 0 then first clause is true, making it // irrelevant if the second clause is correct or not. if ((Index < 1) || ( (DWORD) Index > m_dwSize)) { LOG((MSP_ERROR, "CTapiBstrCollection::get_Item - exit E_INVALIDARG")); return E_INVALIDARG; } // // This copies the string, not just the pointer. // VariantCopy(retval, &m_Var[Index-1]); LOG((MSP_TRACE, "CTapiBstrCollection::get_Item - exit S_OK")); return S_OK; } HRESULT STDMETHODCALLTYPE get__NewEnum( IUnknown** retval ) { HRESULT hr; LOG((MSP_TRACE, "CTapiBstrCollection::get__NumEnum - enter")); if (retval == NULL) { return E_POINTER; } *retval = NULL; typedef CComObject > > enumvar; enumvar* p = new enumvar; if ( p == NULL ) { LOG((MSP_ERROR, "CTapiBstrCollection::get__NumEnum - exit E_OUTOFMEMORY")); return E_OUTOFMEMORY; } hr = p->Init(&m_Var[0], &m_Var[m_dwSize], NULL, AtlFlagCopy); if (SUCCEEDED(hr)) { hr = p->QueryInterface(IID_IEnumVARIANT, (void**)retval); } if (FAILED(hr)) { delete p; } LOG((MSP_TRACE, "CTapiBstrCollection::get__NewEnum - exit")); return hr; } void FinalRelease() { LOG((MSP_TRACE, "CTapiBstrCollection::FinalRelease() - enter")); delete [] m_Var; if ( m_pFTM ) { m_pFTM->Release(); } LOG((MSP_TRACE, "CTapiBstrCollection::FinalRelease() - exit")); } }; #endif // _MDHCP_COLLECTION_H_ // eof