Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

409 lines
8.3 KiB

/*++
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