1 /* 2 * Copyright 2005 Jacek Caban 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19 #include "urlmon_main.h" 20 #include "wine/debug.h" 21 22 WINE_DEFAULT_DEBUG_CHANNEL(urlmon); 23 24 static WCHAR wszEnumFORMATETC[] = {'_','E','n','u','m','F','O','R','M','A','T','E','T','C','_',0}; 25 26 typedef struct { 27 IEnumFORMATETC IEnumFORMATETC_iface; 28 29 FORMATETC *fetc; 30 UINT fetc_cnt; 31 UINT it; 32 33 LONG ref; 34 } EnumFORMATETC; 35 36 static inline EnumFORMATETC *impl_from_IEnumFORMATETC(IEnumFORMATETC *iface) 37 { 38 return CONTAINING_RECORD(iface, EnumFORMATETC, IEnumFORMATETC_iface); 39 } 40 41 static IEnumFORMATETC *EnumFORMATETC_Create(UINT cfmtetc, const FORMATETC *rgfmtetc, UINT it); 42 43 static HRESULT WINAPI EnumFORMATETC_QueryInterface(IEnumFORMATETC *iface, REFIID riid, void **ppv) 44 { 45 EnumFORMATETC *This = impl_from_IEnumFORMATETC(iface); 46 47 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); 48 49 *ppv = NULL; 50 51 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IEnumFORMATETC, riid)) { 52 IEnumFORMATETC_AddRef(iface); 53 *ppv = iface; 54 return S_OK; 55 } 56 57 WARN("not supported interface %s\n", debugstr_guid(riid)); 58 return E_NOINTERFACE; 59 } 60 61 static ULONG WINAPI EnumFORMATETC_AddRef(IEnumFORMATETC *iface) 62 { 63 EnumFORMATETC *This = impl_from_IEnumFORMATETC(iface); 64 LONG ref = InterlockedIncrement(&This->ref); 65 TRACE("(%p) ref=%d\n", This, ref); 66 return ref; 67 } 68 69 static ULONG WINAPI EnumFORMATETC_Release(IEnumFORMATETC *iface) 70 { 71 EnumFORMATETC *This = impl_from_IEnumFORMATETC(iface); 72 LONG ref = InterlockedDecrement(&This->ref); 73 74 TRACE("(%p) ref=%d\n", This, ref); 75 76 if(!ref) { 77 heap_free(This->fetc); 78 heap_free(This); 79 80 URLMON_UnlockModule(); 81 } 82 83 return ref; 84 } 85 86 static HRESULT WINAPI EnumFORMATETC_Next(IEnumFORMATETC *iface, ULONG celt, 87 FORMATETC *rgelt, ULONG *pceltFetched) 88 { 89 EnumFORMATETC *This = impl_from_IEnumFORMATETC(iface); 90 ULONG cnt; 91 92 TRACE("(%p)->(%d %p %p)\n", This, celt, rgelt, pceltFetched); 93 94 if(!rgelt) 95 return E_INVALIDARG; 96 97 if(This->it >= This->fetc_cnt || !celt) { 98 if(pceltFetched) 99 *pceltFetched = 0; 100 return celt ? S_FALSE : S_OK; 101 } 102 103 cnt = This->fetc_cnt-This->it > celt ? celt : This->fetc_cnt-This->it; 104 105 memcpy(rgelt, This->fetc+This->it, cnt*sizeof(FORMATETC)); 106 This->it += cnt; 107 108 if(pceltFetched) 109 *pceltFetched = cnt; 110 111 return cnt == celt ? S_OK : S_FALSE; 112 } 113 114 static HRESULT WINAPI EnumFORMATETC_Skip(IEnumFORMATETC *iface, ULONG celt) 115 { 116 EnumFORMATETC *This = impl_from_IEnumFORMATETC(iface); 117 118 TRACE("(%p)->(%d)\n", This, celt); 119 120 This->it += celt; 121 return This->it > This->fetc_cnt ? S_FALSE : S_OK; 122 } 123 124 static HRESULT WINAPI EnumFORMATETC_Reset(IEnumFORMATETC *iface) 125 { 126 EnumFORMATETC *This = impl_from_IEnumFORMATETC(iface); 127 128 TRACE("(%p)\n", This); 129 130 This->it = 0; 131 return S_OK; 132 } 133 134 static HRESULT WINAPI EnumFORMATETC_Clone(IEnumFORMATETC *iface, IEnumFORMATETC **ppenum) 135 { 136 EnumFORMATETC *This = impl_from_IEnumFORMATETC(iface); 137 138 TRACE("(%p)->(%p)\n", This, ppenum); 139 140 if(!ppenum) 141 return E_INVALIDARG; 142 143 *ppenum = EnumFORMATETC_Create(This->fetc_cnt, This->fetc, This->it); 144 return S_OK; 145 } 146 147 static const IEnumFORMATETCVtbl EnumFORMATETCVtbl = { 148 EnumFORMATETC_QueryInterface, 149 EnumFORMATETC_AddRef, 150 EnumFORMATETC_Release, 151 EnumFORMATETC_Next, 152 EnumFORMATETC_Skip, 153 EnumFORMATETC_Reset, 154 EnumFORMATETC_Clone 155 }; 156 157 static IEnumFORMATETC *EnumFORMATETC_Create(UINT cfmtetc, const FORMATETC *rgfmtetc, UINT it) 158 { 159 EnumFORMATETC *ret = heap_alloc(sizeof(EnumFORMATETC)); 160 161 URLMON_LockModule(); 162 163 ret->IEnumFORMATETC_iface.lpVtbl = &EnumFORMATETCVtbl; 164 ret->ref = 1; 165 ret->it = it; 166 ret->fetc_cnt = cfmtetc; 167 168 ret->fetc = heap_alloc(cfmtetc*sizeof(FORMATETC)); 169 memcpy(ret->fetc, rgfmtetc, cfmtetc*sizeof(FORMATETC)); 170 171 return &ret->IEnumFORMATETC_iface; 172 } 173 174 /********************************************************** 175 * CreateFormatEnumerator (urlmon.@) 176 */ 177 HRESULT WINAPI CreateFormatEnumerator(UINT cfmtetc, FORMATETC *rgfmtetc, 178 IEnumFORMATETC** ppenumfmtetc) 179 { 180 TRACE("(%d %p %p)\n", cfmtetc, rgfmtetc, ppenumfmtetc); 181 182 if(!ppenumfmtetc) 183 return E_INVALIDARG; 184 if(!cfmtetc) 185 return E_FAIL; 186 187 *ppenumfmtetc = EnumFORMATETC_Create(cfmtetc, rgfmtetc, 0); 188 return S_OK; 189 } 190 191 /********************************************************** 192 * RegisterFormatEnumerator (urlmon.@) 193 */ 194 HRESULT WINAPI RegisterFormatEnumerator(LPBC pBC, IEnumFORMATETC *pEFetc, DWORD reserved) 195 { 196 TRACE("(%p %p %d)\n", pBC, pEFetc, reserved); 197 198 if(reserved) 199 WARN("reserved != 0\n"); 200 201 if(!pBC || !pEFetc) 202 return E_INVALIDARG; 203 204 return IBindCtx_RegisterObjectParam(pBC, wszEnumFORMATETC, (IUnknown*)pEFetc); 205 } 206 207 /********************************************************** 208 * RevokeFormatEnumerator (urlmon.@) 209 */ 210 HRESULT WINAPI RevokeFormatEnumerator(LPBC pbc, IEnumFORMATETC *pEFetc) 211 { 212 TRACE("(%p %p)\n", pbc, pEFetc); 213 214 if(!pbc) 215 return E_INVALIDARG; 216 217 return IBindCtx_RevokeObjectParam(pbc, wszEnumFORMATETC); 218 } 219