410 lines
8.3 KiB
C
410 lines
8.3 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1997-2000 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
rndcoll.h
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Definitions for CRendezvous collection template class.
|
||
|
--*/
|
||
|
|
||
|
#ifndef __RENDCOLL_H
|
||
|
#define __RENDCOLL_H
|
||
|
|
||
|
#include "tapi3if.h"
|
||
|
#include "rndobjsf.h"
|
||
|
|
||
|
EXTERN_C const IID LIBID_TAPI3Lib;
|
||
|
|
||
|
template <class T>
|
||
|
class ATL_NO_VTABLE TInterfaceCollection :
|
||
|
public CComObjectRootEx<CComMultiThreadModel>,
|
||
|
public IDispatchImpl<ITCollection, &IID_ITCollection, &LIBID_TAPI3Lib>,
|
||
|
public CObjectSafeImpl
|
||
|
|
||
|
{
|
||
|
public:
|
||
|
TInterfaceCollection()
|
||
|
: m_Var(NULL), m_nSize(0), m_pFTM(NULL) {}
|
||
|
|
||
|
~TInterfaceCollection()
|
||
|
{
|
||
|
delete [] m_Var;
|
||
|
|
||
|
if ( m_pFTM )
|
||
|
{
|
||
|
m_pFTM->Release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
typedef TInterfaceCollection<T> _TCollection;
|
||
|
|
||
|
DECLARE_GET_CONTROLLING_UNKNOWN()
|
||
|
|
||
|
BEGIN_COM_MAP(_TCollection)
|
||
|
COM_INTERFACE_ENTRY(IDispatch)
|
||
|
COM_INTERFACE_ENTRY(ITCollection)
|
||
|
COM_INTERFACE_ENTRY(IObjectSafety)
|
||
|
COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM)
|
||
|
END_COM_MAP()
|
||
|
|
||
|
private:
|
||
|
// Array of Dispatch pointers.
|
||
|
CComVariant* m_Var ;
|
||
|
long m_nSize;
|
||
|
IUnknown * m_pFTM; // pointer to the free threaded marshaler
|
||
|
|
||
|
public:
|
||
|
|
||
|
HRESULT Initialize (long nSize, T* begin, T* end);
|
||
|
|
||
|
// ICollection methods
|
||
|
STDMETHOD (get_Count) (OUT long* retval);
|
||
|
STDMETHOD (get_Item) (IN long Index, OUT VARIANT* retval);
|
||
|
STDMETHOD (get__NewEnum)(IUnknown** retval);
|
||
|
};
|
||
|
|
||
|
template <class T>
|
||
|
HRESULT
|
||
|
TInterfaceCollection<T>::Initialize (long nSize, T* begin, T* end)
|
||
|
{
|
||
|
if ( nSize < 0 )
|
||
|
{
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT hr = CoCreateFreeThreadedMarshaler( GetControllingUnknown(),
|
||
|
& m_pFTM );
|
||
|
|
||
|
if ( FAILED(hr) )
|
||
|
{
|
||
|
LOG((MSP_INFO, "CTInterfaceCollection::Initialize - "
|
||
|
"create FTM returned 0x%08x; exit", hr));
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
if (NULL == (m_Var = new CComVariant[nSize]))
|
||
|
{
|
||
|
return E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
m_nSize = nSize;
|
||
|
|
||
|
DWORD i = 0;
|
||
|
|
||
|
for (T *iter = begin; iter != end; iter ++, i ++)
|
||
|
{
|
||
|
// get IDispatch pointer
|
||
|
IDispatch * pDisp;
|
||
|
|
||
|
hr = (*iter)->QueryInterface(IID_IDispatch, (void**)&pDisp);
|
||
|
if (S_OK != hr) return hr;
|
||
|
|
||
|
V_VT(&m_Var[i]) = VT_DISPATCH;
|
||
|
V_DISPATCH(&m_Var[i]) = pDisp;
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
template <class T>
|
||
|
STDMETHODIMP
|
||
|
TInterfaceCollection<T>::get_Count(OUT long* retval)
|
||
|
{
|
||
|
if ( IsBadWritePtr(retval, sizeof(long) ) )
|
||
|
{
|
||
|
return E_POINTER;
|
||
|
}
|
||
|
|
||
|
*retval = m_nSize;
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
template <class T>
|
||
|
STDMETHODIMP
|
||
|
TInterfaceCollection<T>::get_Item(IN long Index, OUT VARIANT* retval)
|
||
|
{
|
||
|
if ( IsBadWritePtr(retval, sizeof(VARIANT) ) )
|
||
|
{
|
||
|
return E_POINTER;
|
||
|
}
|
||
|
|
||
|
retval->vt = VT_UNKNOWN;
|
||
|
retval->punkVal = NULL;
|
||
|
|
||
|
// use 1-based index, VB like
|
||
|
if ((Index < 1) || (Index > m_nSize))
|
||
|
{
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
|
||
|
VariantCopy(retval, &m_Var[Index-1]);
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
template <class T>
|
||
|
STDMETHODIMP
|
||
|
TInterfaceCollection<T>::get__NewEnum(IUnknown** retval)
|
||
|
{
|
||
|
if ( IsBadWritePtr(retval, sizeof( IUnknown * ) ) )
|
||
|
{
|
||
|
return E_POINTER;
|
||
|
}
|
||
|
|
||
|
*retval = NULL;
|
||
|
|
||
|
typedef CComObject<CSafeComEnum<IEnumVARIANT,
|
||
|
&IID_IEnumVARIANT, VARIANT, _Copy<VARIANT> > > enumvar;
|
||
|
|
||
|
enumvar* p; // = new enumvar;
|
||
|
enumvar::CreateInstance( &p );
|
||
|
|
||
|
if (p == NULL)
|
||
|
{
|
||
|
return E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
HRESULT hr = p->Init(&m_Var[0], &m_Var[m_nSize], NULL, AtlFlagCopy);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = p->QueryInterface(IID_IEnumVARIANT, (void**)retval);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
delete p;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
class ATL_NO_VTABLE TBstrCollection :
|
||
|
public CComObjectRootEx<CComMultiThreadModel>,
|
||
|
public IDispatchImpl<ITCollection, &IID_ITCollection, &LIBID_TAPI3Lib>,
|
||
|
public CObjectSafeImpl
|
||
|
{
|
||
|
public:
|
||
|
TBstrCollection()
|
||
|
: m_Var(NULL), m_nSize(0), m_pFTM(NULL) {}
|
||
|
|
||
|
~TBstrCollection()
|
||
|
{
|
||
|
delete [] m_Var;
|
||
|
|
||
|
if ( m_pFTM )
|
||
|
{
|
||
|
m_pFTM->Release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DECLARE_GET_CONTROLLING_UNKNOWN()
|
||
|
|
||
|
BEGIN_COM_MAP(TBstrCollection)
|
||
|
COM_INTERFACE_ENTRY(IDispatch)
|
||
|
COM_INTERFACE_ENTRY(ITCollection)
|
||
|
COM_INTERFACE_ENTRY(IObjectSafety)
|
||
|
COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM)
|
||
|
END_COM_MAP()
|
||
|
|
||
|
private:
|
||
|
// Array of Dispatch pointers.
|
||
|
CComVariant* m_Var ;
|
||
|
long m_nSize;
|
||
|
IUnknown * m_pFTM; // pointer to the free threaded marshaler
|
||
|
|
||
|
public:
|
||
|
|
||
|
inline HRESULT Initialize (long nSize, BSTR* begin, BSTR* end, CComEnumFlags flags);
|
||
|
|
||
|
// ITCollection methods
|
||
|
inline STDMETHOD (get_Count) (OUT long* retval);
|
||
|
inline STDMETHOD (get_Item) (IN long Index, OUT VARIANT* retval);
|
||
|
inline STDMETHOD (get__NewEnum)(IUnknown** retval);
|
||
|
};
|
||
|
|
||
|
inline
|
||
|
HRESULT
|
||
|
TBstrCollection::Initialize (long nSize, BSTR * begin, BSTR * end, CComEnumFlags flags)
|
||
|
{
|
||
|
if ( nSize < 0 )
|
||
|
{
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
|
||
|
HRESULT hr = CoCreateFreeThreadedMarshaler( GetControllingUnknown(),
|
||
|
& m_pFTM );
|
||
|
|
||
|
if ( FAILED(hr) )
|
||
|
{
|
||
|
LOG((MSP_INFO, "TCollectionCollection::Initialize - "
|
||
|
"create FTM returned 0x%08x; exit", hr));
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
if (NULL == (m_Var = new CComVariant[nSize]))
|
||
|
{
|
||
|
return E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
m_nSize = nSize;
|
||
|
|
||
|
DWORD i = 0;
|
||
|
|
||
|
for (BSTR * iter = begin; iter != end; iter ++, i ++)
|
||
|
{
|
||
|
m_Var[i].vt = VT_BSTR;
|
||
|
switch (flags)
|
||
|
{
|
||
|
case AtlFlagNoCopy:
|
||
|
case AtlFlagTakeOwnership :
|
||
|
m_Var[i].bstrVal = (*iter);
|
||
|
break;
|
||
|
|
||
|
case AtlFlagCopy:
|
||
|
m_Var[i].bstrVal = SysAllocString(*iter);
|
||
|
if (m_Var[i].bstrVal == NULL)
|
||
|
{
|
||
|
return E_OUTOFMEMORY;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (AtlFlagTakeOwnership) delete begin;
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
STDMETHODIMP
|
||
|
TBstrCollection::get_Count(OUT long* retval)
|
||
|
{
|
||
|
if ( IsBadWritePtr(retval, sizeof(long) ) )
|
||
|
{
|
||
|
return E_POINTER;
|
||
|
}
|
||
|
|
||
|
*retval = m_nSize;
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
STDMETHODIMP
|
||
|
TBstrCollection::get_Item(IN long Index, OUT VARIANT* retval)
|
||
|
{
|
||
|
if ( IsBadWritePtr(retval, sizeof(VARIANT) ) )
|
||
|
{
|
||
|
return E_POINTER;
|
||
|
}
|
||
|
|
||
|
retval->vt = VT_UNKNOWN;
|
||
|
retval->punkVal = NULL;
|
||
|
|
||
|
// use 1-based index, VB like
|
||
|
if ((Index < 1) || (Index > m_nSize))
|
||
|
{
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
|
||
|
VariantCopy(retval, &m_Var[Index-1]);
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
STDMETHODIMP
|
||
|
TBstrCollection::get__NewEnum(IUnknown** retval)
|
||
|
{
|
||
|
if ( IsBadWritePtr(retval, sizeof( IUnknown * ) ) )
|
||
|
{
|
||
|
return E_POINTER;
|
||
|
}
|
||
|
|
||
|
*retval = NULL;
|
||
|
|
||
|
typedef CComObject<CSafeComEnum<IEnumVARIANT,
|
||
|
&IID_IEnumVARIANT, VARIANT, _Copy<VARIANT> > > enumvar;
|
||
|
|
||
|
enumvar* p; // = new enumvar;
|
||
|
enumvar::CreateInstance( &p );
|
||
|
|
||
|
if (p == NULL)
|
||
|
{
|
||
|
return E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
HRESULT hr = p->Init(&m_Var[0], &m_Var[m_nSize], NULL, AtlFlagCopy);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = p->QueryInterface(IID_IEnumVARIANT, (void**)retval);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
delete p;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
template <class T>
|
||
|
HRESULT CreateInterfaceCollection(
|
||
|
IN long nSize,
|
||
|
IN T * begin,
|
||
|
IN T * end,
|
||
|
OUT VARIANT * pVariant
|
||
|
)
|
||
|
{
|
||
|
// create the collection object
|
||
|
typedef TInterfaceCollection<T> CCollection;
|
||
|
|
||
|
CComObject<CCollection> * p;
|
||
|
HRESULT hr = CComObject<CCollection>::CreateInstance( &p );
|
||
|
|
||
|
if (NULL == p)
|
||
|
{
|
||
|
LOG((MSP_ERROR, "Could not create Collection object, %x",hr));
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
hr = p->Initialize(nSize, begin, end);
|
||
|
|
||
|
if (S_OK != hr)
|
||
|
{
|
||
|
LOG((MSP_ERROR, "Could not initialize Collection object, %x", hr));
|
||
|
delete p;
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
IDispatch *pDisp;
|
||
|
|
||
|
// get the IDispatch interface
|
||
|
hr = p->_InternalQueryInterface(IID_IDispatch, (void **)&pDisp);
|
||
|
|
||
|
if (S_OK != hr)
|
||
|
{
|
||
|
LOG((MSP_ERROR, "QI for IDispatch in CreateCollection, %x", hr));
|
||
|
delete p;
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// put it in the variant
|
||
|
VariantInit(pVariant);
|
||
|
V_VT(pVariant) = VT_DISPATCH;
|
||
|
V_DISPATCH(pVariant) = pDisp;
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
#endif
|