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.

371 lines
8.0 KiB

  1. /*
  2. * enumfmte.cpp - EnumFormatEtc class implementation.
  3. *
  4. * Taken from URL code - essentially identical to DavidDi's original code
  5. *
  6. * Created: ChrisPi 9-11-95
  7. *
  8. */
  9. /* Headers
  10. **********/
  11. #include "precomp.h"
  12. #include "clrefcnt.hpp"
  13. #include "clenumft.hpp"
  14. /***************************** Private Functions *****************************/
  15. #ifdef DEBUG
  16. BOOL IsValidArrayOfFORMATETCs(CFORMATETC rgcfmtetc[],
  17. ULONG ulcFormats)
  18. {
  19. BOOL bResult = TRUE;
  20. ULONG ul;
  21. for (ul = 0; ul < ulcFormats; ul++)
  22. bResult = (EVAL(IS_VALID_STRUCT_PTR(&(rgcfmtetc[ul]), CFORMATETC)) &&
  23. bResult);
  24. return(bResult);
  25. }
  26. BOOL IsValidPCEnumFormatEtc(PCEnumFormatEtc pcefe)
  27. {
  28. return(IS_VALID_READ_PTR(pcefe, CEnumFormatEtc) &&
  29. EVAL(IsValidArrayOfFORMATETCs(pcefe->m_pfmtetc, pcefe->m_ulcFormats)) &&
  30. EVAL(pcefe->m_uliCurrent <= pcefe->m_ulcFormats) &&
  31. IS_VALID_STRUCT_PTR((PCRefCount)pcefe, CRefCount) &&
  32. IS_VALID_INTERFACE_PTR((PCIEnumFORMATETC)pcefe, IEnumFORMATETC));
  33. }
  34. #endif
  35. /********************************** Methods **********************************/
  36. EnumFormatEtc::EnumFormatEtc(CFORMATETC rgcfmtetc[], ULONG ulcFormats) :
  37. RefCount(NULL)
  38. {
  39. DebugEntry(EnumFormatEtc::EnumFormatEtc);
  40. // Don't validate this until after construction.
  41. ASSERT(IsValidArrayOfFORMATETCs(rgcfmtetc, ulcFormats));
  42. m_pfmtetc = new(FORMATETC[ulcFormats]);
  43. if (m_pfmtetc)
  44. {
  45. CopyMemory(m_pfmtetc, rgcfmtetc, ulcFormats * sizeof(rgcfmtetc[0]));
  46. m_ulcFormats = ulcFormats;
  47. }
  48. else
  49. m_ulcFormats = 0;
  50. m_uliCurrent = 0;
  51. ASSERT(IS_VALID_STRUCT_PTR(this, CEnumFormatEtc));
  52. DebugExitVOID(EnumFormatEtc::EnumFormatEtc);
  53. return;
  54. }
  55. EnumFormatEtc::~EnumFormatEtc(void)
  56. {
  57. DebugEntry(EnumFormatEtc::~EnumFormatEtc);
  58. ASSERT(IS_VALID_STRUCT_PTR(this, CEnumFormatEtc));
  59. if (m_pfmtetc)
  60. {
  61. delete m_pfmtetc;
  62. m_pfmtetc = NULL;
  63. }
  64. m_ulcFormats = 0;
  65. m_uliCurrent = 0;
  66. ASSERT(IS_VALID_STRUCT_PTR(this, CEnumFormatEtc));
  67. DebugExitVOID(EnumFormatEtc::~EnumFormatEtc);
  68. return;
  69. }
  70. ULONG STDMETHODCALLTYPE EnumFormatEtc::AddRef(void)
  71. {
  72. ULONG ulcRef;
  73. DebugEntry(EnumFormatEtc::AddRef);
  74. ASSERT(IS_VALID_STRUCT_PTR(this, CEnumFormatEtc));
  75. ulcRef = RefCount::AddRef();
  76. ASSERT(IS_VALID_STRUCT_PTR(this, CEnumFormatEtc));
  77. DebugExitULONG(EnumFormatEtc::AddRef, ulcRef);
  78. return(ulcRef);
  79. }
  80. ULONG STDMETHODCALLTYPE EnumFormatEtc::Release(void)
  81. {
  82. ULONG ulcRef;
  83. DebugEntry(EnumFormatEtc::Release);
  84. ASSERT(IS_VALID_STRUCT_PTR(this, CEnumFormatEtc));
  85. ulcRef = RefCount::Release();
  86. DebugExitULONG(EnumFormatEtc::Release, ulcRef);
  87. return(ulcRef);
  88. }
  89. HRESULT STDMETHODCALLTYPE EnumFormatEtc::QueryInterface(REFIID riid,
  90. PVOID *ppvObject)
  91. {
  92. HRESULT hr = S_OK;
  93. DebugEntry(EnumFormatEtc::QueryInterface);
  94. ASSERT(IS_VALID_STRUCT_PTR(this, CEnumFormatEtc));
  95. ASSERT(IsValidREFIID(riid));
  96. ASSERT(IS_VALID_WRITE_PTR(ppvObject, PVOID));
  97. if (riid == IID_IEnumFORMATETC)
  98. {
  99. *ppvObject = (PIEnumFORMATETC)this;
  100. ASSERT(IS_VALID_INTERFACE_PTR((PIEnumFORMATETC)*ppvObject, IEnumFORMATETC));
  101. TRACE_OUT(("EnumFormatEtc::QueryInterface(): Returning IEnumFORMATETC."));
  102. }
  103. else if (riid == IID_IUnknown)
  104. {
  105. *ppvObject = (PIUnknown)this;
  106. ASSERT(IS_VALID_INTERFACE_PTR((PIUnknown)*ppvObject, IUnknown));
  107. TRACE_OUT(("EnumFormatEtc::QueryInterface(): Returning IUnknown."));
  108. }
  109. else
  110. {
  111. *ppvObject = NULL;
  112. hr = E_NOINTERFACE;
  113. TRACE_OUT(("EnumFormatEtc::QueryInterface(): Called on unknown interface."));
  114. }
  115. if (hr == S_OK)
  116. AddRef();
  117. ASSERT(IS_VALID_STRUCT_PTR(this, CEnumFormatEtc));
  118. // removed by ChrisPi - CINTERFACE undeclared identifier
  119. //ASSERT(FAILED(hr) ||
  120. // IS_VALID_INTERFACE_PTR(*ppvObject, INTERFACE));
  121. DebugExitHRESULT(EnumFormatEtc::QueryInterface, hr);
  122. return(hr);
  123. }
  124. HRESULT STDMETHODCALLTYPE EnumFormatEtc::Next(ULONG ulcToFetch,
  125. PFORMATETC pfmtetc,
  126. PULONG pulcFetched)
  127. {
  128. HRESULT hr = S_FALSE;
  129. ULONG ulcFetched;
  130. DebugEntry(EnumFormatEtc::Next);
  131. ASSERT(IS_VALID_STRUCT_PTR(this, CEnumFormatEtc));
  132. if (m_uliCurrent < m_ulcFormats)
  133. {
  134. ULONG ulcCanFetch = m_ulcFormats - m_uliCurrent;
  135. ulcFetched = min(ulcCanFetch, ulcToFetch);
  136. CopyMemory(pfmtetc, &(m_pfmtetc[m_uliCurrent]),
  137. ulcFetched * sizeof(*pfmtetc));
  138. m_uliCurrent += ulcFetched;
  139. }
  140. else
  141. // End of the list.
  142. ulcFetched = 0;
  143. if (pulcFetched)
  144. *pulcFetched = ulcFetched;
  145. else
  146. ASSERT(ulcToFetch == 1);
  147. if (ulcFetched < ulcToFetch)
  148. hr = S_FALSE;
  149. else
  150. {
  151. ASSERT(ulcFetched == ulcToFetch);
  152. hr = S_OK;
  153. }
  154. TRACE_OUT(("EnumFormatEtc::Next(): Fetched %lu FORMATETCs.",
  155. ulcFetched));
  156. ASSERT(IS_VALID_STRUCT_PTR(this, CEnumFormatEtc));
  157. ASSERT((((hr == S_OK &&
  158. EVAL((! pulcFetched &&
  159. ulcToFetch == 1) ||
  160. *pulcFetched == ulcToFetch)) ||
  161. (hr == S_FALSE &&
  162. EVAL((! pulcFetched &&
  163. ulcToFetch == 1) ||
  164. *pulcFetched < ulcToFetch))) &&
  165. EVAL((! pulcFetched &&
  166. IS_VALID_STRUCT_PTR(pfmtetc, CFORMATETC)) ||
  167. IsValidArrayOfFORMATETCs(pfmtetc, *pulcFetched))) ||
  168. (FAILED(hr) &&
  169. EVAL((! pulcFetched &&
  170. ulcToFetch == 1) ||
  171. ! *pulcFetched)));
  172. DebugExitHRESULT(EnumFormatEtc::Next, hr);
  173. return(hr);
  174. }
  175. HRESULT STDMETHODCALLTYPE EnumFormatEtc::Skip(ULONG ulcToSkip)
  176. {
  177. HRESULT hr;
  178. DebugEntry(EnumFormatEtc::Skip);
  179. ASSERT(IS_VALID_STRUCT_PTR(this, CEnumFormatEtc));
  180. if (ulcToSkip <= m_ulcFormats - m_uliCurrent)
  181. {
  182. m_uliCurrent += ulcToSkip;
  183. hr = S_OK;
  184. TRACE_OUT(("EnumFormatEtc::Skip(): Skipped %lu FORMATETCs, as requested.",
  185. ulcToSkip));
  186. }
  187. else
  188. {
  189. TRACE_OUT(("EnumFormatEtc::Skip(): Skipped %lu of %lu FORMATETCs.",
  190. m_ulcFormats - m_uliCurrent,
  191. ulcToSkip));
  192. m_uliCurrent = m_ulcFormats;
  193. hr = S_FALSE;
  194. }
  195. ASSERT(IS_VALID_STRUCT_PTR(this, CEnumFormatEtc));
  196. ASSERT((hr == S_OK &&
  197. m_uliCurrent <= m_ulcFormats) ||
  198. (hr == S_FALSE &&
  199. m_uliCurrent == m_ulcFormats));
  200. DebugExitHRESULT(EnumFormatEtc::Skip, hr);
  201. return(hr);
  202. }
  203. HRESULT STDMETHODCALLTYPE EnumFormatEtc::Reset(void)
  204. {
  205. HRESULT hr;
  206. DebugEntry(EnumFormatEtc::Reset);
  207. ASSERT(IS_VALID_STRUCT_PTR(this, CEnumFormatEtc));
  208. m_uliCurrent = 0;
  209. hr = S_OK;
  210. ASSERT(IS_VALID_STRUCT_PTR(this, CEnumFormatEtc));
  211. ASSERT(hr == S_OK &&
  212. ! m_uliCurrent);
  213. DebugExitHRESULT(EnumFormatEtc::Reset, hr);
  214. return(hr);
  215. }
  216. HRESULT STDMETHODCALLTYPE EnumFormatEtc::Clone(PIEnumFORMATETC *ppiefe)
  217. {
  218. HRESULT hr;
  219. PEnumFormatEtc pefe;
  220. DebugEntry(EnumFormatEtc::Clone);
  221. ASSERT(IS_VALID_STRUCT_PTR(this, CEnumFormatEtc));
  222. pefe = new ::EnumFormatEtc(m_pfmtetc, m_ulcFormats);
  223. if (pefe)
  224. {
  225. hr = pefe->Status();
  226. if (hr == S_OK)
  227. {
  228. hr = pefe->Skip(m_uliCurrent);
  229. if (hr == S_OK)
  230. *ppiefe = pefe;
  231. else
  232. hr = E_UNEXPECTED;
  233. }
  234. if (hr != S_OK)
  235. {
  236. delete pefe;
  237. pefe = NULL;
  238. }
  239. }
  240. else
  241. hr = E_OUTOFMEMORY;
  242. ASSERT(IS_VALID_STRUCT_PTR(this, CEnumFormatEtc));
  243. ASSERT((hr == S_OK &&
  244. IS_VALID_INTERFACE_PTR(*ppiefe, IEnumFORMATETC)) ||
  245. (FAILED(hr) &&
  246. ! *ppiefe));
  247. DebugExitHRESULT(EnumFormatEtc::Clone, hr);
  248. return(hr);
  249. }
  250. HRESULT STDMETHODCALLTYPE EnumFormatEtc::Status(void)
  251. {
  252. HRESULT hr;
  253. DebugEntry(EnumFormatEtc::Status);
  254. ASSERT(IS_VALID_STRUCT_PTR(this, CEnumFormatEtc));
  255. hr = (m_pfmtetc ? S_OK : E_OUTOFMEMORY);
  256. ASSERT(IS_VALID_STRUCT_PTR(this, CEnumFormatEtc));
  257. DebugExitHRESULT(EnumFormatEtc::Status, hr);
  258. return(hr);
  259. }