gdi32: Add a stub for CancelDC.
[wine] / dlls / urlmon / bindprot.c
1 /*
2  * Copyright 2007 Jacek Caban for CodeWeavers
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 typedef struct {
35     const IInternetProtocolVtbl *lpInternetProtocolVtbl;
36     const IInternetBindInfoVtbl *lpInternetBindInfoVtbl;
37     const IInternetPriorityVtbl *lpInternetPriorityVtbl;
38     const IInternetProtocolSinkVtbl *lpInternetProtocolSinkVtbl;
39
40     LONG ref;
41
42     IInternetProtocol *protocol;
43     IInternetBindInfo *bind_info;
44     IInternetProtocolSink *protocol_sink;
45
46     LONG priority;
47 } BindProtocol;
48
49 #define PROTOCOL(x)  ((IInternetProtocol*) &(x)->lpInternetProtocolVtbl)
50 #define BINDINFO(x)  ((IInternetBindInfo*) &(x)->lpInternetBindInfoVtbl)
51 #define PRIORITY(x)  ((IInternetPriority*) &(x)->lpInternetPriorityVtbl)
52 #define PROTSINK(x)  ((IInternetProtocolSink*) &(x)->lpInternetProtocolSinkVtbl)
53
54 #define PROTOCOL_THIS(iface) DEFINE_THIS(BindProtocol, InternetProtocol, iface)
55
56 static HRESULT WINAPI BindProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
57 {
58     BindProtocol *This = PROTOCOL_THIS(iface);
59
60     *ppv = NULL;
61     if(IsEqualGUID(&IID_IUnknown, riid)) {
62         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
63         *ppv = PROTOCOL(This);
64     }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
65         TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
66         *ppv = PROTOCOL(This);
67     }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
68         TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
69         *ppv = PROTOCOL(This);
70     }else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) {
71         TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This, ppv);
72         *ppv = BINDINFO(This);
73     }else if(IsEqualGUID(&IID_IInternetPriority, riid)) {
74         TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv);
75         *ppv = PRIORITY(This);
76     }else if(IsEqualGUID(&IID_IAuthenticate, riid)) {
77         FIXME("(%p)->(IID_IAuthenticate %p)\n", This, ppv);
78     }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
79         FIXME("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
80     }else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
81         TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
82         *ppv = PROTSINK(This);
83     }
84
85     if(*ppv) {
86         IInternetProtocol_AddRef(iface);
87         return S_OK;
88     }
89
90     WARN("not supported interface %s\n", debugstr_guid(riid));
91     return E_NOINTERFACE;
92 }
93
94 static ULONG WINAPI BindProtocol_AddRef(IInternetProtocol *iface)
95 {
96     BindProtocol *This = PROTOCOL_THIS(iface);
97     LONG ref = InterlockedIncrement(&This->ref);
98     TRACE("(%p) ref=%d\n", This, ref);
99     return ref;
100 }
101
102 static ULONG WINAPI BindProtocol_Release(IInternetProtocol *iface)
103 {
104     BindProtocol *This = PROTOCOL_THIS(iface);
105     LONG ref = InterlockedDecrement(&This->ref);
106
107     TRACE("(%p) ref=%d\n", This, ref);
108
109     if(!ref) {
110         if(This->protocol)
111             IInternetProtocol_Release(This->protocol);
112         if(This->bind_info)
113             IInternetBindInfo_Release(This->bind_info);
114         if(This->protocol_sink)
115             IInternetProtocolSink_Release(This->protocol_sink);
116
117         HeapFree(GetProcessHeap(), 0, This);
118
119         URLMON_UnlockModule();
120     }
121
122     return ref;
123 }
124
125 static HRESULT WINAPI BindProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
126         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
127         DWORD grfPI, DWORD dwReserved)
128 {
129     BindProtocol *This = PROTOCOL_THIS(iface);
130     IInternetProtocol *protocol = NULL;
131     IInternetPriority *priority;
132     IServiceProvider *service_provider;
133     CLSID clsid = IID_NULL;
134     LPOLESTR clsid_str;
135     HRESULT hres;
136
137     TRACE("(%p)->(%s %p %p %08x %d)\n", This, debugstr_w(szUrl), pOIProtSink,
138             pOIBindInfo, grfPI, dwReserved);
139
140     if(!szUrl || !pOIProtSink || !pOIBindInfo)
141         return E_INVALIDARG;
142
143     hres = IInternetProtocolSink_QueryInterface(pOIProtSink, &IID_IServiceProvider,
144                                                 (void**)&service_provider);
145     if(SUCCEEDED(hres)) {
146         /* FIXME: What's protocol CLSID here? */
147         IServiceProvider_QueryService(service_provider, &IID_IInternetProtocol,
148                                       &IID_IInternetProtocol, (void**)&protocol);
149         IServiceProvider_Release(service_provider);
150     }
151
152     if(!protocol) {
153         IClassFactory *cf;
154         IUnknown *unk;
155
156         hres = get_protocol_handler(szUrl, &clsid, &cf);
157         if(FAILED(hres))
158             return hres;
159
160         hres = IClassFactory_CreateInstance(cf, (IUnknown*)BINDINFO(This),
161                 &IID_IUnknown, (void**)&unk);
162         IClassFactory_Release(cf);
163         if(FAILED(hres))
164             return hres;
165
166         hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocol, (void**)&protocol);
167         IUnknown_Release(unk);
168         if(FAILED(hres))
169             return hres;
170     }
171
172     StringFromCLSID(&clsid, &clsid_str);
173     IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_PROTOCOLCLASSID, clsid_str);
174     CoTaskMemFree(clsid_str);
175
176     This->protocol = protocol;
177
178     IInternetBindInfo_AddRef(pOIBindInfo);
179     This->bind_info = pOIBindInfo;
180
181     IInternetProtocolSink_AddRef(pOIProtSink);
182     This->protocol_sink = pOIProtSink;
183
184     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
185     if(SUCCEEDED(hres)) {
186         IInternetPriority_SetPriority(priority, This->priority);
187         IInternetPriority_Release(priority);
188     }
189
190     return IInternetProtocol_Start(protocol, szUrl, PROTSINK(This), BINDINFO(This), 0, 0);
191 }
192
193 static HRESULT WINAPI BindProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
194 {
195     BindProtocol *This = PROTOCOL_THIS(iface);
196     FIXME("(%p)->(%p)\n", This, pProtocolData);
197     return E_NOTIMPL;
198 }
199
200 static HRESULT WINAPI BindProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
201         DWORD dwOptions)
202 {
203     BindProtocol *This = PROTOCOL_THIS(iface);
204     FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
205     return E_NOTIMPL;
206 }
207
208 static HRESULT WINAPI BindProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
209 {
210     BindProtocol *This = PROTOCOL_THIS(iface);
211
212     TRACE("(%p)->(%08x)\n", This, dwOptions);
213
214     IInternetProtocol_Terminate(This->protocol, 0);
215     return S_OK;
216 }
217
218 static HRESULT WINAPI BindProtocol_Suspend(IInternetProtocol *iface)
219 {
220     BindProtocol *This = PROTOCOL_THIS(iface);
221     FIXME("(%p)\n", This);
222     return E_NOTIMPL;
223 }
224
225 static HRESULT WINAPI BindProtocol_Resume(IInternetProtocol *iface)
226 {
227     BindProtocol *This = PROTOCOL_THIS(iface);
228     FIXME("(%p)\n", This);
229     return E_NOTIMPL;
230 }
231
232 static HRESULT WINAPI BindProtocol_Read(IInternetProtocol *iface, void *pv,
233         ULONG cb, ULONG *pcbRead)
234 {
235     BindProtocol *This = PROTOCOL_THIS(iface);
236     ULONG read = 0;
237     HRESULT hres;
238
239     TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
240
241     hres = IInternetProtocol_Read(This->protocol, pv, cb, &read);
242
243     *pcbRead = read;
244     return hres;
245 }
246
247 static HRESULT WINAPI BindProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
248         DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
249 {
250     BindProtocol *This = PROTOCOL_THIS(iface);
251     FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
252     return E_NOTIMPL;
253 }
254
255 static HRESULT WINAPI BindProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
256 {
257     BindProtocol *This = PROTOCOL_THIS(iface);
258     FIXME("(%p)->(%08x)\n", This, dwOptions);
259     return E_NOTIMPL;
260 }
261
262 static HRESULT WINAPI BindProtocol_UnlockRequest(IInternetProtocol *iface)
263 {
264     BindProtocol *This = PROTOCOL_THIS(iface);
265     FIXME("(%p)\n", This);
266     return E_NOTIMPL;
267 }
268
269 #undef PROTOCOL_THIS
270
271 static const IInternetProtocolVtbl BindProtocolVtbl = {
272     BindProtocol_QueryInterface,
273     BindProtocol_AddRef,
274     BindProtocol_Release,
275     BindProtocol_Start,
276     BindProtocol_Continue,
277     BindProtocol_Abort,
278     BindProtocol_Terminate,
279     BindProtocol_Suspend,
280     BindProtocol_Resume,
281     BindProtocol_Read,
282     BindProtocol_Seek,
283     BindProtocol_LockRequest,
284     BindProtocol_UnlockRequest
285 };
286
287 #define BINDINFO_THIS(iface) DEFINE_THIS(BindProtocol, InternetBindInfo, iface)
288
289 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface,
290         REFIID riid, void **ppv)
291 {
292     BindProtocol *This = BINDINFO_THIS(iface);
293     return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
294 }
295
296 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
297 {
298     BindProtocol *This = BINDINFO_THIS(iface);
299     return IBinding_AddRef(PROTOCOL(This));
300 }
301
302 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
303 {
304     BindProtocol *This = BINDINFO_THIS(iface);
305     return IBinding_Release(PROTOCOL(This));
306 }
307
308 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface,
309         DWORD *grfBINDF, BINDINFO *pbindinfo)
310 {
311     BindProtocol *This = BINDINFO_THIS(iface);
312     HRESULT hres;
313
314     TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
315
316     hres = IInternetBindInfo_GetBindInfo(This->bind_info, grfBINDF, pbindinfo);
317     if(FAILED(hres)) {
318         WARN("GetBindInfo failed: %08x\n", hres);
319         return hres;
320     }
321
322     *grfBINDF |= BINDF_FROMURLMON;
323     return hres;
324 }
325
326 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface,
327         ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
328 {
329     BindProtocol *This = BINDINFO_THIS(iface);
330     FIXME("(%p)->(%d %p %d %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched);
331     return E_NOTIMPL;
332 }
333
334 #undef BINDFO_THIS
335
336 static const IInternetBindInfoVtbl InternetBindInfoVtbl = {
337     BindInfo_QueryInterface,
338     BindInfo_AddRef,
339     BindInfo_Release,
340     BindInfo_GetBindInfo,
341     BindInfo_GetBindString
342 };
343
344 #define PRIORITY_THIS(iface) DEFINE_THIS(BindProtocol, InternetPriority, iface)
345
346 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
347         REFIID riid, void **ppv)
348 {
349     BindProtocol *This = PRIORITY_THIS(iface);
350     return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
351 }
352
353 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
354 {
355     BindProtocol *This = PRIORITY_THIS(iface);
356     return IInternetProtocol_AddRef(PROTOCOL(This));
357 }
358
359 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
360 {
361     BindProtocol *This = PRIORITY_THIS(iface);
362     return IInternetProtocol_Release(PROTOCOL(This));
363 }
364
365 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
366 {
367     BindProtocol *This = PRIORITY_THIS(iface);
368
369     TRACE("(%p)->(%d)\n", This, nPriority);
370
371     This->priority = nPriority;
372     return S_OK;
373 }
374
375 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
376 {
377     BindProtocol *This = PRIORITY_THIS(iface);
378
379     TRACE("(%p)->(%p)\n", This, pnPriority);
380
381     *pnPriority = This->priority;
382     return S_OK;
383 }
384
385 #undef PRIORITY_THIS
386
387 static const IInternetPriorityVtbl InternetPriorityVtbl = {
388     InternetPriority_QueryInterface,
389     InternetPriority_AddRef,
390     InternetPriority_Release,
391     InternetPriority_SetPriority,
392     InternetPriority_GetPriority
393
394 };
395
396 #define PROTSINK_THIS(iface) DEFINE_THIS(BindProtocol, InternetProtocolSink, iface)
397
398 static HRESULT WINAPI InternetProtocolSink_QueryInterface(IInternetProtocolSink *iface,
399         REFIID riid, void **ppv)
400 {
401     BindProtocol *This = PROTSINK_THIS(iface);
402     return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
403 }
404
405 static ULONG WINAPI InternetProtocolSink_AddRef(IInternetProtocolSink *iface)
406 {
407     BindProtocol *This = PROTSINK_THIS(iface);
408     return IInternetProtocol_AddRef(PROTOCOL(This));
409 }
410
411 static ULONG WINAPI InternetProtocolSink_Release(IInternetProtocolSink *iface)
412 {
413     BindProtocol *This = PROTSINK_THIS(iface);
414     return IInternetProtocol_Release(PROTOCOL(This));
415 }
416
417 static HRESULT WINAPI InternetProtocolSink_Switch(IInternetProtocolSink *iface,
418         PROTOCOLDATA *pProtocolData)
419 {
420     BindProtocol *This = PROTSINK_THIS(iface);
421     FIXME("(%p)->(%p)\n", This, pProtocolData);
422     return E_NOTIMPL;
423 }
424
425 static HRESULT WINAPI InternetProtocolSink_ReportProgress(IInternetProtocolSink *iface,
426         ULONG ulStatusCode, LPCWSTR szStatusText)
427 {
428     BindProtocol *This = PROTSINK_THIS(iface);
429
430     TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
431
432     switch(ulStatusCode) {
433     case BINDSTATUS_SENDINGREQUEST:
434         return IInternetProtocolSink_ReportProgress(This->protocol_sink,
435                 ulStatusCode, NULL);
436     case BINDSTATUS_CACHEFILENAMEAVAILABLE:
437         return IInternetProtocolSink_ReportProgress(This->protocol_sink,
438                 ulStatusCode, szStatusText);
439     case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
440         return IInternetProtocolSink_ReportProgress(This->protocol_sink,
441                 BINDSTATUS_MIMETYPEAVAILABLE, szStatusText);
442     default:
443         FIXME("unsupported ulStatusCode %u\n", ulStatusCode);
444     }
445
446     return E_NOTIMPL;
447 }
448
449 static HRESULT WINAPI InternetProtocolSink_ReportData(IInternetProtocolSink *iface,
450         DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax)
451 {
452     BindProtocol *This = PROTSINK_THIS(iface);
453
454     TRACE("(%p)->(%d %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
455
456     return S_OK;
457 }
458
459 static HRESULT WINAPI InternetProtocolSink_ReportResult(IInternetProtocolSink *iface,
460         HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
461 {
462     BindProtocol *This = PROTSINK_THIS(iface);
463
464     TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
465
466     return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
467 }
468
469 #undef PROTSINK_THIS
470
471 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = {
472     InternetProtocolSink_QueryInterface,
473     InternetProtocolSink_AddRef,
474     InternetProtocolSink_Release,
475     InternetProtocolSink_Switch,
476     InternetProtocolSink_ReportProgress,
477     InternetProtocolSink_ReportData,
478     InternetProtocolSink_ReportResult
479 };
480
481 HRESULT create_binding_protocol(LPCWSTR url, IInternetProtocol **protocol)
482 {
483     BindProtocol *ret = HeapAlloc(GetProcessHeap(), 0, sizeof(BindProtocol));
484
485     ret->lpInternetProtocolVtbl = &BindProtocolVtbl;
486     ret->lpInternetBindInfoVtbl = &InternetBindInfoVtbl;
487     ret->lpInternetPriorityVtbl = &InternetPriorityVtbl;
488     ret->lpInternetProtocolSinkVtbl = &InternetProtocolSinkVtbl;
489
490     ret->ref = 1;
491     ret->protocol = NULL;
492     ret->bind_info = NULL;
493     ret->protocol_sink = NULL;
494     ret->priority = 0;
495
496     *protocol = PROTOCOL(ret);
497     return S_OK;
498 }