home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Internet 2000 May / MICD_2000_05.iso / CBuilder5 / INSTALL / DATA1.CAB / Program_Built_Files / Include / mspenum.h < prev    next >
C/C++ Source or Header  |  2000-02-01  |  4KB  |  155 lines

  1. /*
  2.  
  3.     Copyright (c) 1998-1999  Microsoft Corporation
  4.  
  5. */
  6.  
  7. #ifndef _MSPENUM_H_
  8. #pragma option push -b -a8 -pc -A- /*P_O_Push*/
  9. #define _MSPENUM_H_
  10.  
  11. //////////////////////////////////////////////////////////////////////////////
  12. //
  13. // CSafeComEnum
  14. //
  15. // All TAPI 3.0 system components and MSPs use the CSafeComEnum class instead
  16. // of ATL 2.1's CComEnum class when implementing enumerator objects that are
  17. // accessible to applications. This is needed for the following reasons:
  18. //
  19. // 1. CComEnum does not perform IsBadWritePtr checks on the pointer arguments
  20. //    to the enumerator methods. This allows the component exposing the
  21. //    enumerator to AV when called with invalid pointer arguments.
  22. //
  23. // 2. CComEnum does not support free thread marshaling, and therefore cannot
  24. //    be used from an apartment threaded application.
  25. //
  26. // Note: No debug tracing is done here, to facilitate use of this template
  27. // independent of the rest of the MSP Base Classes.
  28. //
  29. /////////////////////////////////////////////////////////////////////////////
  30.  
  31.  
  32. template <class Base, const IID* piid, class T, class Copy,
  33.           class ThreadModel = CComObjectThreadModel>
  34. class ATL_NO_VTABLE CSafeComEnum :
  35.         public CComEnumImpl<Base, piid, T, Copy>,
  36.         public CComObjectRootEx< ThreadModel >
  37. {
  38.     typedef CSafeComEnum<Base, piid, T, Copy, ThreadModel> ThisClass;
  39.     typedef CComEnumImpl<Base, piid, T, Copy>              BaseClass;
  40.  
  41.     STDMETHOD(Next)(ULONG celt, T* rgelt, ULONG* pceltFetched)
  42.     {
  43.         //
  44.         // Check if the return array is valid for as many elements as
  45.         // specified. No need to explicitly check if celt is zero here, as
  46.         // IsBadWritePtr(p, 0) is valid and returns 0.
  47.         // celt itself will be checked in the base class method.
  48.         //
  49.  
  50.         if ( IsBadWritePtr(rgelt, celt * sizeof(T) ) )
  51.         {
  52.             return E_POINTER;
  53.         }
  54.  
  55.         //
  56.         // Check if the return dword is bad, but if pceltFetched == NULL,
  57.         // this may still be a valid call. pceltFetched == NULL implies that
  58.         // celt should be equal to 1, but that will be checked in the
  59.         // base class method.
  60.         //
  61.  
  62.         if ( ( pceltFetched != NULL ) &&
  63.              IsBadWritePtr(pceltFetched, sizeof(ULONG) ) )
  64.         {
  65.             return E_POINTER;
  66.         }
  67.  
  68.         //
  69.         // Everything OK so far; proceed with base class method.
  70.         //
  71.  
  72.         return BaseClass::Next(celt, rgelt, pceltFetched);
  73.     }
  74.  
  75.     STDMETHOD(Clone)(Base** ppEnum)
  76.     {
  77.         //
  78.         // Check if the return pointer is valid.
  79.         //
  80.  
  81.         if ( IsBadWritePtr(ppEnum, sizeof(Base *) ) )
  82.         {
  83.             return E_POINTER;
  84.         }
  85.  
  86.         //
  87.         // Everything OK so far; proceed with base class method.
  88.         //
  89.  
  90.         return BaseClass::Clone(ppEnum);
  91.     }
  92.  
  93.     //
  94.     // We do not override Skip or Reset as they have no pointer arguments.
  95.     //
  96.  
  97.     //
  98.     // The rest of this class involves support for free thread marshaling.
  99.     //
  100.  
  101.     BEGIN_COM_MAP( ThisClass )
  102.  
  103.         COM_INTERFACE_ENTRY_IID( *piid, BaseClass )
  104.         COM_INTERFACE_ENTRY_AGGREGATE( IID_IMarshal, m_pFTM )
  105.  
  106.     END_COM_MAP()
  107.  
  108.     DECLARE_GET_CONTROLLING_UNKNOWN()
  109.  
  110.     HRESULT Init(T* begin, T* end, IUnknown* pUnk,
  111.             CComEnumFlags flags = AtlFlagNoCopy)
  112.     {
  113.         //
  114.         // We do not check the pointer arguments in this method because this
  115.         // method is not exposed to the application (it is not a COM interface
  116.         // method).
  117.         //
  118.         
  119.         HRESULT hr;
  120.  
  121.         IUnknown * pIU = GetControllingUnknown();
  122.  
  123.         hr = CoCreateFreeThreadedMarshaler( pIU, 
  124.                                             & m_pFTM );
  125.  
  126.         if ( FAILED(hr) )
  127.         {
  128.             return hr;
  129.         }
  130.  
  131.         return BaseClass::Init(begin, end, pUnk, flags);
  132.     }
  133.  
  134.     CSafeComEnum()
  135.     {
  136.         m_pFTM = NULL;
  137.     }
  138.  
  139.     void FinalRelease(void)
  140.     {
  141.         if ( m_pFTM )
  142.         {
  143.             m_pFTM->Release();
  144.         }
  145.  
  146.         CComObjectRootEx< ThreadModel >::FinalRelease();
  147.     }
  148.  
  149. protected:
  150.     IUnknown * m_pFTM; // pointer to free thread marshaler
  151. };
  152.  
  153. #pragma option pop /*P_O_Pop*/
  154. #endif // _MSPENUM_H_
  155.