Jacek Caban | 1aad808 | 2005-09-02 12:17:29 +0000 | [diff] [blame] | 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 |
Jonathan Ernst | 360a3f9 | 2006-05-18 14:49:52 +0200 | [diff] [blame] | 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
Jacek Caban | 1aad808 | 2005-09-02 12:17:29 +0000 | [diff] [blame] | 17 | */ |
| 18 | |
| 19 | #include <stdarg.h> |
| 20 | |
| 21 | #define COBJMACROS |
| 22 | |
| 23 | #include "windef.h" |
| 24 | #include "winbase.h" |
| 25 | #include "winuser.h" |
| 26 | #include "ole2.h" |
| 27 | #include "urlmon.h" |
| 28 | #include "urlmon_main.h" |
| 29 | |
| 30 | #include "wine/debug.h" |
| 31 | |
| 32 | WINE_DEFAULT_DEBUG_CHANNEL(urlmon); |
| 33 | |
Jacek Caban | 74138a0 | 2005-09-03 15:03:06 +0000 | [diff] [blame] | 34 | static WCHAR wszEnumFORMATETC[] = {'_','E','n','u','m','F','O','R','M','A','T','E','T','C','_',0}; |
| 35 | |
Jacek Caban | 1aad808 | 2005-09-02 12:17:29 +0000 | [diff] [blame] | 36 | typedef struct { |
| 37 | const IEnumFORMATETCVtbl *lpEnumFORMATETCVtbl; |
| 38 | |
| 39 | FORMATETC *fetc; |
| 40 | UINT fetc_cnt; |
| 41 | UINT it; |
| 42 | |
| 43 | LONG ref; |
| 44 | } EnumFORMATETC; |
| 45 | |
| 46 | static IEnumFORMATETC *EnumFORMATETC_Create(UINT cfmtetc, FORMATETC *rgfmtetc, UINT it); |
| 47 | |
| 48 | #define ENUMF_THIS(iface) ICOM_THIS_MULTI(EnumFORMATETC, lpEnumFORMATETCVtbl, iface) |
| 49 | |
| 50 | static HRESULT WINAPI EnumFORMATETC_QueryInterface(IEnumFORMATETC *iface, REFIID riid, void **ppv) |
| 51 | { |
| 52 | TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv); |
| 53 | |
| 54 | *ppv = NULL; |
| 55 | |
| 56 | if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IEnumFORMATETC, riid)) { |
| 57 | *ppv = iface; |
| 58 | return S_OK; |
| 59 | } |
| 60 | |
| 61 | WARN("not supported interface %s\n", debugstr_guid(riid)); |
| 62 | return E_NOINTERFACE; |
| 63 | } |
| 64 | |
| 65 | static ULONG WINAPI EnumFORMATETC_AddRef(IEnumFORMATETC *iface) |
| 66 | { |
| 67 | ENUMF_THIS(iface); |
| 68 | LONG ref = InterlockedIncrement(&This->ref); |
Jacek Caban | 7e340f8 | 2006-10-05 23:49:11 +0200 | [diff] [blame] | 69 | TRACE("(%p) ref=%d\n", This, ref); |
Jacek Caban | 1aad808 | 2005-09-02 12:17:29 +0000 | [diff] [blame] | 70 | return ref; |
| 71 | } |
| 72 | |
| 73 | static ULONG WINAPI EnumFORMATETC_Release(IEnumFORMATETC *iface) |
| 74 | { |
| 75 | ENUMF_THIS(iface); |
| 76 | LONG ref = InterlockedDecrement(&This->ref); |
| 77 | |
Jacek Caban | 7e340f8 | 2006-10-05 23:49:11 +0200 | [diff] [blame] | 78 | TRACE("(%p) ref=%d\n", This, ref); |
Jacek Caban | 1aad808 | 2005-09-02 12:17:29 +0000 | [diff] [blame] | 79 | |
| 80 | if(!ref) { |
| 81 | HeapFree(GetProcessHeap(), 0, This->fetc); |
| 82 | HeapFree(GetProcessHeap(), 0, This); |
| 83 | |
| 84 | URLMON_UnlockModule(); |
| 85 | } |
| 86 | |
| 87 | return ref; |
| 88 | } |
| 89 | |
| 90 | static HRESULT WINAPI EnumFORMATETC_Next(IEnumFORMATETC *iface, ULONG celt, |
| 91 | FORMATETC *rgelt, ULONG *pceltFetched) |
| 92 | { |
| 93 | ENUMF_THIS(iface); |
| 94 | ULONG cnt; |
| 95 | |
Jacek Caban | 7e340f8 | 2006-10-05 23:49:11 +0200 | [diff] [blame] | 96 | TRACE("(%p)->(%d %p %p)\n", This, celt, rgelt, pceltFetched); |
Jacek Caban | 1aad808 | 2005-09-02 12:17:29 +0000 | [diff] [blame] | 97 | |
| 98 | if(!rgelt) |
| 99 | return E_INVALIDARG; |
| 100 | |
| 101 | if(This->it >= This->fetc_cnt || !celt) { |
| 102 | if(pceltFetched) |
| 103 | *pceltFetched = 0; |
| 104 | return celt ? S_FALSE : S_OK; |
| 105 | } |
| 106 | |
| 107 | cnt = This->fetc_cnt-This->it > celt ? celt : This->fetc_cnt-This->it; |
| 108 | |
| 109 | memcpy(rgelt, This->fetc+This->it, cnt*sizeof(FORMATETC)); |
| 110 | This->it += cnt; |
| 111 | |
| 112 | if(pceltFetched) |
| 113 | *pceltFetched = cnt; |
| 114 | |
| 115 | return cnt == celt ? S_OK : S_FALSE; |
| 116 | } |
| 117 | |
| 118 | static HRESULT WINAPI EnumFORMATETC_Skip(IEnumFORMATETC *iface, ULONG celt) |
| 119 | { |
| 120 | ENUMF_THIS(iface); |
| 121 | |
Jacek Caban | 7e340f8 | 2006-10-05 23:49:11 +0200 | [diff] [blame] | 122 | TRACE("(%p)->(%d)\n", This, celt); |
Jacek Caban | 1aad808 | 2005-09-02 12:17:29 +0000 | [diff] [blame] | 123 | |
| 124 | This->it += celt; |
| 125 | return This->it > This->fetc_cnt ? S_FALSE : S_OK; |
| 126 | } |
| 127 | |
| 128 | static HRESULT WINAPI EnumFORMATETC_Reset(IEnumFORMATETC *iface) |
| 129 | { |
| 130 | ENUMF_THIS(iface); |
| 131 | |
| 132 | TRACE("(%p)\n", This); |
| 133 | |
| 134 | This->it = 0; |
| 135 | return S_OK; |
| 136 | } |
| 137 | |
| 138 | static HRESULT WINAPI EnumFORMATETC_Clone(IEnumFORMATETC *iface, IEnumFORMATETC **ppenum) |
| 139 | { |
| 140 | ENUMF_THIS(iface); |
| 141 | |
| 142 | TRACE("(%p)->(%p)\n", This, ppenum); |
| 143 | |
| 144 | if(!ppenum) |
| 145 | return E_INVALIDARG; |
| 146 | |
| 147 | *ppenum = EnumFORMATETC_Create(This->fetc_cnt, This->fetc, This->it); |
| 148 | return S_OK; |
| 149 | } |
| 150 | |
| 151 | static const IEnumFORMATETCVtbl EnumFORMATETCVtbl = { |
| 152 | EnumFORMATETC_QueryInterface, |
| 153 | EnumFORMATETC_AddRef, |
| 154 | EnumFORMATETC_Release, |
| 155 | EnumFORMATETC_Next, |
| 156 | EnumFORMATETC_Skip, |
| 157 | EnumFORMATETC_Reset, |
| 158 | EnumFORMATETC_Clone |
| 159 | }; |
| 160 | |
| 161 | static IEnumFORMATETC *EnumFORMATETC_Create(UINT cfmtetc, FORMATETC *rgfmtetc, UINT it) |
| 162 | { |
| 163 | EnumFORMATETC *ret = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumFORMATETC)); |
| 164 | |
| 165 | URLMON_LockModule(); |
| 166 | |
| 167 | ret->lpEnumFORMATETCVtbl = &EnumFORMATETCVtbl; |
| 168 | ret->ref = 1; |
| 169 | ret->it = it; |
| 170 | ret->fetc_cnt = cfmtetc; |
| 171 | |
| 172 | ret->fetc = HeapAlloc(GetProcessHeap(), 0, cfmtetc*sizeof(FORMATETC)); |
| 173 | memcpy(ret->fetc, rgfmtetc, cfmtetc*sizeof(FORMATETC)); |
| 174 | |
| 175 | return (IEnumFORMATETC*)ret; |
| 176 | } |
| 177 | |
| 178 | /********************************************************** |
| 179 | * CreateFormatEnumerator (urlmon.@) |
| 180 | */ |
| 181 | HRESULT WINAPI CreateFormatEnumerator(UINT cfmtetc, FORMATETC *rgfmtetc, |
| 182 | IEnumFORMATETC** ppenumfmtetc) |
| 183 | { |
| 184 | TRACE("(%d %p %p)\n", cfmtetc, rgfmtetc, ppenumfmtetc); |
| 185 | |
| 186 | if(!ppenumfmtetc) |
| 187 | return E_INVALIDARG; |
| 188 | if(!cfmtetc) |
| 189 | return E_FAIL; |
| 190 | |
| 191 | *ppenumfmtetc = EnumFORMATETC_Create(cfmtetc, rgfmtetc, 0); |
| 192 | return S_OK; |
| 193 | } |
Jacek Caban | 74138a0 | 2005-09-03 15:03:06 +0000 | [diff] [blame] | 194 | |
| 195 | /********************************************************** |
| 196 | * RegisterFormatEnumerator (urlmon.@) |
| 197 | */ |
| 198 | HRESULT WINAPI RegisterFormatEnumerator(LPBC pBC, IEnumFORMATETC *pEFetc, DWORD reserved) |
| 199 | { |
Jacek Caban | 7e340f8 | 2006-10-05 23:49:11 +0200 | [diff] [blame] | 200 | TRACE("(%p %p %d)\n", pBC, pEFetc, reserved); |
Jacek Caban | 74138a0 | 2005-09-03 15:03:06 +0000 | [diff] [blame] | 201 | |
| 202 | if(reserved) |
| 203 | WARN("reserved != 0\n"); |
| 204 | |
| 205 | if(!pBC || !pEFetc) |
| 206 | return E_INVALIDARG; |
| 207 | |
| 208 | return IBindCtx_RegisterObjectParam(pBC, wszEnumFORMATETC, (IUnknown*)pEFetc); |
| 209 | } |
| 210 | |
| 211 | /********************************************************** |
| 212 | * RevokeFormatEnumerator (urlmon.@) |
| 213 | */ |
| 214 | HRESULT WINAPI RevokeFormatEnumerator(LPBC pbc, IEnumFORMATETC *pEFetc) |
| 215 | { |
| 216 | TRACE("(%p %p)\n", pbc, pEFetc); |
| 217 | |
| 218 | if(!pbc) |
| 219 | return E_INVALIDARG; |
| 220 | |
| 221 | return IBindCtx_RevokeObjectParam(pbc, wszEnumFORMATETC); |
| 222 | } |