1/**
2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the mingw-w64 runtime package.
4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
5 */
6#ifndef _MSPENUM_H_
7#define _MSPENUM_H_
8
9#ifdef __cplusplus
10
11template <class Base,const IID *piid,class T,class Copy,class ThreadModel = CComObjectThreadModel>
12class ATL_NO_VTABLE CSafeComEnum : public CComEnumImpl<Base,piid,T,Copy>,public CComObjectRootEx< ThreadModel >
13{
14  typedef CSafeComEnum<Base,piid,T,Copy,ThreadModel> ThisClass;
15  typedef CComEnumImpl<Base,piid,T,Copy> BaseClass;
16  STDMETHOD(Next)(ULONG celt,T *rgelt,ULONG *pceltFetched) {
17    if(IsBadWritePtr(rgelt,celt *sizeof(T))) return E_POINTER;
18    if((pceltFetched!=NULL) && IsBadWritePtr(pceltFetched,sizeof(ULONG))) return E_POINTER;
19    return BaseClass::Next(celt,rgelt,pceltFetched);
20  }
21  STDMETHOD(Clone)(Base **ppEnum) {
22    if(IsBadWritePtr(ppEnum,sizeof(Base *))) return E_POINTER;
23    return BaseClass::Clone(ppEnum);
24  }
25  BEGIN_COM_MAP(ThisClass)
26    COM_INTERFACE_ENTRY_IID(*piid,BaseClass)
27    COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal,m_pFTM)
28  END_COM_MAP()
29  DECLARE_GET_CONTROLLING_UNKNOWN()
30  HRESULT Init(T *begin,T *end,IUnknown *pUnk,CComEnumFlags flags = AtlFlagNoCopy) {
31    HRESULT hr;
32    IUnknown *pIU = GetControllingUnknown();
33    hr = CoCreateFreeThreadedMarshaler(pIU,& m_pFTM);
34    if(FAILED(hr)) return hr;
35    return BaseClass::Init(begin,end,pUnk,flags);
36  }
37  CSafeComEnum() { m_pFTM = NULL; }
38  void FinalRelease(void) {
39    if(m_pFTM) {
40      m_pFTM->Release();
41    }
42    CComObjectRootEx< ThreadModel >::FinalRelease();
43  }
44protected:
45  IUnknown *m_pFTM;
46};
47
48#endif /* __cplusplus */
49
50#endif
51
52