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.

428 lines
11 KiB

  1. /*************************************************************************
  2. **
  3. ** OLE 2 Utility Code
  4. **
  5. ** enumfetc.c
  6. **
  7. ** This file contains a standard implementation of IEnumFormatEtc
  8. ** interface.
  9. ** This file is part of the OLE 2.0 User Interface support library.
  10. **
  11. ** (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
  12. **
  13. *************************************************************************/
  14. #define STRICT 1
  15. #include <win32.h>
  16. #include <shellapi.h>
  17. #include <ole2.h>
  18. #include "enumfetc.h"
  19. STDAPI_(void) OleStdFree(LPVOID pmem);
  20. STDAPI_(BOOL) OleStdCopyFormatEtc(LPFORMATETC petcDest, LPFORMATETC petcSrc);
  21. typedef struct tagOleStdEnumFmtEtc {
  22. IEnumFORMATETCVtbl FAR* lpVtbl;
  23. ULONG m_dwRefs; /* referance count */
  24. WORD m_wIndex; /* current index in list */
  25. WORD m_wCount; /* how many items in list */
  26. LPFORMATETC m_lpEtc; /* list of formatetc */
  27. } OLESTDENUMFMTETC, FAR* LPOLESTDENUMFMTETC;
  28. VOID OleStdEnumFmtEtc_Destroy(LPOLESTDENUMFMTETC pEtc);
  29. STDMETHODIMP OleStdEnumFmtEtc_QueryInterface(
  30. LPENUMFORMATETC lpThis, REFIID riid, LPVOID FAR* ppobj);
  31. STDMETHODIMP_(ULONG) OleStdEnumFmtEtc_AddRef(LPENUMFORMATETC lpThis);
  32. STDMETHODIMP_(ULONG) OleStdEnumFmtEtc_Release(LPENUMFORMATETC lpThis);
  33. STDMETHODIMP OleStdEnumFmtEtc_Next(LPENUMFORMATETC lpThis, ULONG celt,
  34. LPFORMATETC rgelt, ULONG FAR* pceltFetched);
  35. STDMETHODIMP OleStdEnumFmtEtc_Skip(LPENUMFORMATETC lpThis, ULONG celt);
  36. STDMETHODIMP OleStdEnumFmtEtc_Reset(LPENUMFORMATETC lpThis);
  37. STDMETHODIMP OleStdEnumFmtEtc_Clone(LPENUMFORMATETC lpThis,
  38. LPENUMFORMATETC FAR* ppenum);
  39. static IEnumFORMATETCVtbl g_EnumFORMATETCVtbl = {
  40. OleStdEnumFmtEtc_QueryInterface,
  41. OleStdEnumFmtEtc_AddRef,
  42. OleStdEnumFmtEtc_Release,
  43. OleStdEnumFmtEtc_Next,
  44. OleStdEnumFmtEtc_Skip,
  45. OleStdEnumFmtEtc_Reset,
  46. OleStdEnumFmtEtc_Clone,
  47. };
  48. /////////////////////////////////////////////////////////////////////////////
  49. STDAPI_(LPENUMFORMATETC)
  50. OleStdEnumFmtEtc_Create(WORD wCount, LPFORMATETC lpEtc)
  51. //----------------------------------------------------------------------------
  52. //
  53. //----------------------------------------------------------------------------
  54. {
  55. LPMALLOC lpMalloc=NULL;
  56. LPOLESTDENUMFMTETC lpEF=NULL;
  57. DWORD dwSize;
  58. WORD i;
  59. HRESULT hRes;
  60. hRes = CoGetMalloc(MEMCTX_TASK, &lpMalloc);
  61. if (hRes != NOERROR) {
  62. return NULL;
  63. }
  64. lpEF = (LPOLESTDENUMFMTETC)lpMalloc->lpVtbl->Alloc(lpMalloc,
  65. sizeof(OLESTDENUMFMTETC));
  66. if (lpEF == NULL) {
  67. goto errReturn;
  68. }
  69. lpEF->lpVtbl = &g_EnumFORMATETCVtbl;
  70. lpEF->m_dwRefs = 1;
  71. lpEF->m_wCount = wCount;
  72. lpEF->m_wIndex = 0;
  73. dwSize = sizeof(FORMATETC) * lpEF->m_wCount;
  74. lpEF->m_lpEtc = (LPFORMATETC)lpMalloc->lpVtbl->Alloc(lpMalloc, dwSize);
  75. if (lpEF->m_lpEtc == NULL) {
  76. goto errReturn;
  77. }
  78. for (i=0; i<wCount; i++) {
  79. OleStdCopyFormatEtc(
  80. (LPFORMATETC)&(lpEF->m_lpEtc[i]), (LPFORMATETC)&(lpEtc[i]));
  81. }
  82. return (LPENUMFORMATETC)lpEF;
  83. errReturn:
  84. if (lpEF != NULL) {
  85. lpMalloc->lpVtbl->Free(lpMalloc, lpEF);
  86. }
  87. if (lpMalloc != NULL) {
  88. lpMalloc->lpVtbl->Release(lpMalloc);
  89. }
  90. return NULL;
  91. } /* OleStdEnumFmtEtc_Create()
  92. */
  93. VOID
  94. OleStdEnumFmtEtc_Destroy(LPOLESTDENUMFMTETC lpEF)
  95. //----------------------------------------------------------------------------
  96. //
  97. //----------------------------------------------------------------------------
  98. {
  99. LPMALLOC lpMalloc=NULL;
  100. WORD i;
  101. if (lpEF != NULL) {
  102. if (CoGetMalloc(MEMCTX_TASK, &lpMalloc) == NOERROR) {
  103. /* OLE2NOTE: we MUST free any memory that was allocated for
  104. ** TARGETDEVICES contained within the FORMATETC elements.
  105. */
  106. for (i=0; i<lpEF->m_wCount; i++) {
  107. OleStdFree(lpEF->m_lpEtc[i].ptd);
  108. }
  109. if (lpEF->m_lpEtc != NULL) {
  110. lpMalloc->lpVtbl->Free(lpMalloc, lpEF->m_lpEtc);
  111. }
  112. lpMalloc->lpVtbl->Free(lpMalloc, lpEF);
  113. lpMalloc->lpVtbl->Release(lpMalloc);
  114. }
  115. }
  116. } /* OleStdEnumFmtEtc_Destroy()
  117. */
  118. STDMETHODIMP
  119. OleStdEnumFmtEtc_QueryInterface(
  120. LPENUMFORMATETC lpThis, REFIID riid, LPVOID FAR* ppobj)
  121. //----------------------------------------------------------------------------
  122. //
  123. //----------------------------------------------------------------------------
  124. {
  125. LPOLESTDENUMFMTETC lpEF = (LPOLESTDENUMFMTETC)lpThis;
  126. *ppobj = NULL;
  127. if (IsEqualIID(riid,&IID_IUnknown) || IsEqualIID(riid,&IID_IEnumFORMATETC)){
  128. *ppobj = (LPVOID)lpEF;
  129. }
  130. if (*ppobj == NULL) return ResultFromScode(S_FALSE);
  131. else{
  132. OleStdEnumFmtEtc_AddRef(lpThis);
  133. return NOERROR;
  134. }
  135. } /* OleStdEnumFmtEtc_QueryInterface()
  136. */
  137. STDMETHODIMP_(ULONG)
  138. OleStdEnumFmtEtc_AddRef(LPENUMFORMATETC lpThis)
  139. //----------------------------------------------------------------------------
  140. //
  141. //----------------------------------------------------------------------------
  142. {
  143. LPOLESTDENUMFMTETC lpEF = (LPOLESTDENUMFMTETC)lpThis;
  144. return lpEF->m_dwRefs++;
  145. } /* OleStdEnumFmtEtc_AddRef()
  146. */
  147. STDMETHODIMP_(ULONG)
  148. OleStdEnumFmtEtc_Release(LPENUMFORMATETC lpThis)
  149. //----------------------------------------------------------------------------
  150. //
  151. //----------------------------------------------------------------------------
  152. {
  153. LPOLESTDENUMFMTETC lpEF = (LPOLESTDENUMFMTETC)lpThis;
  154. DWORD dwRefs = --lpEF->m_dwRefs;
  155. if (dwRefs == 0)
  156. OleStdEnumFmtEtc_Destroy(lpEF);
  157. return dwRefs;
  158. } /* OleStdEnumFmtEtc_Release()
  159. */
  160. STDMETHODIMP
  161. OleStdEnumFmtEtc_Next(LPENUMFORMATETC lpThis, ULONG celt, LPFORMATETC rgelt,
  162. ULONG FAR* pceltFetched)
  163. //----------------------------------------------------------------------------
  164. //
  165. //----------------------------------------------------------------------------
  166. {
  167. LPOLESTDENUMFMTETC lpEF = (LPOLESTDENUMFMTETC)lpThis;
  168. ULONG i=0;
  169. WORD wOffset;
  170. if (rgelt == NULL) {
  171. return ResultFromScode(E_INVALIDARG);
  172. }
  173. while (i < celt) {
  174. wOffset = lpEF->m_wIndex + (WORD)i;
  175. if (wOffset < lpEF->m_wCount) {
  176. OleStdCopyFormatEtc(
  177. (LPFORMATETC)&(rgelt[i]), (LPFORMATETC)&(lpEF->m_lpEtc[wOffset]));
  178. lpEF->m_wIndex ++;
  179. i++;
  180. }else{
  181. break;
  182. }
  183. }
  184. if (pceltFetched != NULL) {
  185. *pceltFetched = i;
  186. }
  187. if (i != celt) {
  188. return ResultFromScode(S_FALSE);
  189. }
  190. return NOERROR;
  191. } /* OleStdEnumFmtEtc_Next()
  192. */
  193. STDMETHODIMP
  194. OleStdEnumFmtEtc_Skip(LPENUMFORMATETC lpThis, ULONG celt)
  195. //----------------------------------------------------------------------------
  196. //
  197. //----------------------------------------------------------------------------
  198. {
  199. LPOLESTDENUMFMTETC lpEF = (LPOLESTDENUMFMTETC)lpThis;
  200. ULONG i=0;
  201. WORD wOffset;
  202. while (i < celt) {
  203. wOffset = lpEF->m_wIndex + (WORD)i;
  204. if (wOffset < lpEF->m_wCount) {
  205. lpEF->m_wIndex ++;
  206. i++;
  207. }else{
  208. break;
  209. }
  210. }
  211. if (i != celt) {
  212. return ResultFromScode(S_FALSE);
  213. }
  214. return NOERROR;
  215. } /* OleStdEnumFmtEtc_Skip()
  216. */
  217. STDMETHODIMP
  218. OleStdEnumFmtEtc_Reset(LPENUMFORMATETC lpThis)
  219. //----------------------------------------------------------------------------
  220. //
  221. //----------------------------------------------------------------------------
  222. {
  223. LPOLESTDENUMFMTETC lpEF = (LPOLESTDENUMFMTETC)lpThis;
  224. lpEF->m_wIndex = 0;
  225. return NOERROR;
  226. } /* OleStdEnumFmtEtc_Reset()
  227. */
  228. STDMETHODIMP
  229. OleStdEnumFmtEtc_Clone(LPENUMFORMATETC lpThis, LPENUMFORMATETC FAR* ppenum)
  230. //----------------------------------------------------------------------------
  231. //
  232. //----------------------------------------------------------------------------
  233. {
  234. LPOLESTDENUMFMTETC lpEF = (LPOLESTDENUMFMTETC)lpThis;
  235. if (ppenum == NULL) {
  236. return ResultFromScode(E_INVALIDARG);
  237. }
  238. *ppenum = OleStdEnumFmtEtc_Create(lpEF->m_wCount, lpEF->m_lpEtc);
  239. return (*ppenum != NULL ? NOERROR : ResultFromScode(E_OUTOFMEMORY));
  240. } /* OleStdEnumFmtEtc_Clone()
  241. */
  242. /* OleStdMalloc
  243. ** ------------
  244. ** allocate memory using the currently active IMalloc* allocator
  245. */
  246. STDAPI_(LPVOID) OleStdMalloc(ULONG ulSize)
  247. {
  248. LPVOID pout;
  249. LPMALLOC pmalloc;
  250. if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != S_OK) {
  251. // OleDbgAssertSz(0, szAssertMemAlloc);
  252. return NULL;
  253. }
  254. pout = (LPVOID)pmalloc->lpVtbl->Alloc(pmalloc, ulSize);
  255. if (pmalloc != NULL) {
  256. ULONG refs = pmalloc->lpVtbl->Release(pmalloc);
  257. }
  258. return pout;
  259. }
  260. /*
  261. * OleStdCopyTargetDevice()
  262. *
  263. * Purpose:
  264. * duplicate a TARGETDEVICE struct. this function allocates memory for
  265. * the copy. the caller MUST free the allocated copy when done with it
  266. * using the standard allocator returned from CoGetMalloc.
  267. * (OleStdFree can be used to free the copy).
  268. *
  269. * Parameters:
  270. * ptdSrc pointer to source TARGETDEVICE
  271. *
  272. * Return Value:
  273. * pointer to allocated copy of ptdSrc
  274. * if ptdSrc==NULL then retuns NULL is returned.
  275. * if ptdSrc!=NULL and memory allocation fails, then NULL is returned
  276. */
  277. STDAPI_(DVTARGETDEVICE FAR*) OleStdCopyTargetDevice(DVTARGETDEVICE FAR* ptdSrc)
  278. {
  279. DVTARGETDEVICE FAR* ptdDest = NULL;
  280. if (ptdSrc == NULL) {
  281. return NULL;
  282. }
  283. if ((ptdDest = (DVTARGETDEVICE FAR*)OleStdMalloc(ptdSrc->tdSize)) != NULL) {
  284. hmemcpy(ptdDest, ptdSrc, (size_t)ptdSrc->tdSize);
  285. }
  286. return ptdDest;
  287. }
  288. /*
  289. * OleStdCopyFormatEtc()
  290. *
  291. * Purpose:
  292. * Copies the contents of a FORMATETC structure. this function takes
  293. * special care to copy correctly copying the pointer to the TARGETDEVICE
  294. * contained within the source FORMATETC structure.
  295. * if the source FORMATETC has a non-NULL TARGETDEVICE, then a copy
  296. * of the TARGETDEVICE will be allocated for the destination of the
  297. * FORMATETC (petcDest).
  298. *
  299. * OLE2NOTE: the caller MUST free the allocated copy of the TARGETDEVICE
  300. * within the destination FORMATETC when done with it
  301. * using the standard allocator returned from CoGetMalloc.
  302. * (OleStdFree can be used to free the copy).
  303. *
  304. * Parameters:
  305. * petcDest pointer to destination FORMATETC
  306. * petcSrc pointer to source FORMATETC
  307. *
  308. * Return Value:
  309. * pointer to allocated copy of ptdSrc; retuns NULL if not successful
  310. */
  311. STDAPI_(BOOL) OleStdCopyFormatEtc(LPFORMATETC petcDest, LPFORMATETC petcSrc)
  312. {
  313. if ((petcDest == NULL) || (petcSrc == NULL)) {
  314. return FALSE;
  315. }
  316. petcDest->cfFormat = petcSrc->cfFormat;
  317. petcDest->ptd = OleStdCopyTargetDevice(petcSrc->ptd);
  318. petcDest->dwAspect = petcSrc->dwAspect;
  319. petcDest->lindex = petcSrc->lindex;
  320. petcDest->tymed = petcSrc->tymed;
  321. return TRUE;
  322. }
  323. /* OleStdFree
  324. ** ----------
  325. ** free memory using the currently active IMalloc* allocator
  326. */
  327. STDAPI_(void) OleStdFree(LPVOID pmem)
  328. {
  329. LPMALLOC pmalloc;
  330. if (pmem == NULL)
  331. return;
  332. if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != S_OK) {
  333. // OleDbgAssertSz(0, szAssertMemAlloc);
  334. return;
  335. }
  336. pmalloc->lpVtbl->Free(pmalloc, pmem);
  337. if (pmalloc != NULL) {
  338. ULONG refs = pmalloc->lpVtbl->Release(pmalloc);
  339. }
  340. }