urlmon: Fix PROTOCOLDATA message passing in IInternetProtocolSink interface of Binding.
[wine] / dlls / urlmon / format.c
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 <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
34 static WCHAR wszEnumFORMATETC[] = {'_','E','n','u','m','F','O','R','M','A','T','E','T','C','_',0};
35
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, const 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);
69     TRACE("(%p) ref=%d\n", This, ref);
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
78     TRACE("(%p) ref=%d\n", This, ref);
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
96     TRACE("(%p)->(%d %p %p)\n", This, celt, rgelt, pceltFetched);
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
122     TRACE("(%p)->(%d)\n", This, celt);
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, const 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 }
194
195 /**********************************************************
196  *      RegisterFormatEnumerator (urlmon.@)
197  */
198 HRESULT WINAPI RegisterFormatEnumerator(LPBC pBC, IEnumFORMATETC *pEFetc, DWORD reserved)
199 {
200     TRACE("(%p %p %d)\n", pBC, pEFetc, reserved);
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 }