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.

152 lines
4.0 KiB

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