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.

367 lines
8.0 KiB

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