urlmon: Added BindProtocol::Switch implementation.
[wine/hacks.git] / dlls / urlmon / bindprot.c
blob8e6367319564d222ed0e572b9b271675f15ef77c
1 /*
2 * Copyright 2007 Jacek Caban for CodeWeavers
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.
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.
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
19 #include "urlmon_main.h"
20 #include "wine/debug.h"
22 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
24 typedef struct {
25 const IInternetProtocolVtbl *lpInternetProtocolVtbl;
26 const IInternetBindInfoVtbl *lpInternetBindInfoVtbl;
27 const IInternetPriorityVtbl *lpInternetPriorityVtbl;
28 const IServiceProviderVtbl *lpServiceProviderVtbl;
29 const IInternetProtocolSinkVtbl *lpInternetProtocolSinkVtbl;
31 LONG ref;
33 IInternetProtocol *protocol;
34 IInternetBindInfo *bind_info;
35 IInternetProtocolSink *protocol_sink;
36 IServiceProvider *service_provider;
38 LONG priority;
39 } BindProtocol;
41 #define PROTOCOL(x) ((IInternetProtocol*) &(x)->lpInternetProtocolVtbl)
42 #define BINDINFO(x) ((IInternetBindInfo*) &(x)->lpInternetBindInfoVtbl)
43 #define PRIORITY(x) ((IInternetPriority*) &(x)->lpInternetPriorityVtbl)
44 #define SERVPROV(x) ((IServiceProvider*) &(x)->lpServiceProviderVtbl)
45 #define PROTSINK(x) ((IInternetProtocolSink*) &(x)->lpInternetProtocolSinkVtbl)
47 #define PROTOCOL_THIS(iface) DEFINE_THIS(BindProtocol, InternetProtocol, iface)
49 static HRESULT WINAPI BindProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
51 BindProtocol *This = PROTOCOL_THIS(iface);
53 *ppv = NULL;
54 if(IsEqualGUID(&IID_IUnknown, riid)) {
55 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
56 *ppv = PROTOCOL(This);
57 }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
58 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
59 *ppv = PROTOCOL(This);
60 }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
61 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
62 *ppv = PROTOCOL(This);
63 }else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) {
64 TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This, ppv);
65 *ppv = BINDINFO(This);
66 }else if(IsEqualGUID(&IID_IInternetPriority, riid)) {
67 TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv);
68 *ppv = PRIORITY(This);
69 }else if(IsEqualGUID(&IID_IAuthenticate, riid)) {
70 FIXME("(%p)->(IID_IAuthenticate %p)\n", This, ppv);
71 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
72 TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
73 *ppv = SERVPROV(This);
74 }else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
75 TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
76 *ppv = PROTSINK(This);
79 if(*ppv) {
80 IInternetProtocol_AddRef(iface);
81 return S_OK;
84 WARN("not supported interface %s\n", debugstr_guid(riid));
85 return E_NOINTERFACE;
88 static ULONG WINAPI BindProtocol_AddRef(IInternetProtocol *iface)
90 BindProtocol *This = PROTOCOL_THIS(iface);
91 LONG ref = InterlockedIncrement(&This->ref);
92 TRACE("(%p) ref=%d\n", This, ref);
93 return ref;
96 static ULONG WINAPI BindProtocol_Release(IInternetProtocol *iface)
98 BindProtocol *This = PROTOCOL_THIS(iface);
99 LONG ref = InterlockedDecrement(&This->ref);
101 TRACE("(%p) ref=%d\n", This, ref);
103 if(!ref) {
104 if(This->protocol)
105 IInternetProtocol_Release(This->protocol);
106 if(This->bind_info)
107 IInternetBindInfo_Release(This->bind_info);
108 if(This->protocol_sink)
109 IInternetProtocolSink_Release(This->protocol_sink);
111 heap_free(This);
113 URLMON_UnlockModule();
116 return ref;
119 static HRESULT WINAPI BindProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
120 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
121 DWORD grfPI, DWORD dwReserved)
123 BindProtocol *This = PROTOCOL_THIS(iface);
124 IInternetProtocol *protocol = NULL;
125 IInternetPriority *priority;
126 IServiceProvider *service_provider;
127 CLSID clsid = IID_NULL;
128 LPOLESTR clsid_str;
129 HRESULT hres;
131 TRACE("(%p)->(%s %p %p %08x %d)\n", This, debugstr_w(szUrl), pOIProtSink,
132 pOIBindInfo, grfPI, dwReserved);
134 if(!szUrl || !pOIProtSink || !pOIBindInfo)
135 return E_INVALIDARG;
137 hres = IInternetProtocolSink_QueryInterface(pOIProtSink, &IID_IServiceProvider,
138 (void**)&service_provider);
139 if(SUCCEEDED(hres)) {
140 /* FIXME: What's protocol CLSID here? */
141 IServiceProvider_QueryService(service_provider, &IID_IInternetProtocol,
142 &IID_IInternetProtocol, (void**)&protocol);
143 IServiceProvider_Release(service_provider);
146 if(!protocol) {
147 IClassFactory *cf;
148 IUnknown *unk;
150 hres = get_protocol_handler(szUrl, &clsid, &cf);
151 if(FAILED(hres))
152 return hres;
154 hres = IClassFactory_CreateInstance(cf, (IUnknown*)BINDINFO(This),
155 &IID_IUnknown, (void**)&unk);
156 IClassFactory_Release(cf);
157 if(FAILED(hres))
158 return hres;
160 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocol, (void**)&protocol);
161 IUnknown_Release(unk);
162 if(FAILED(hres))
163 return hres;
166 StringFromCLSID(&clsid, &clsid_str);
167 IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_PROTOCOLCLASSID, clsid_str);
168 CoTaskMemFree(clsid_str);
170 This->protocol = protocol;
172 IInternetBindInfo_AddRef(pOIBindInfo);
173 This->bind_info = pOIBindInfo;
175 IInternetProtocolSink_AddRef(pOIProtSink);
176 This->protocol_sink = pOIProtSink;
178 IInternetProtocolSink_QueryInterface(pOIProtSink, &IID_IServiceProvider, (void**)&This->service_provider);
180 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
181 if(SUCCEEDED(hres)) {
182 IInternetPriority_SetPriority(priority, This->priority);
183 IInternetPriority_Release(priority);
186 return IInternetProtocol_Start(protocol, szUrl, PROTSINK(This), BINDINFO(This), 0, 0);
189 static HRESULT WINAPI BindProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
191 BindProtocol *This = PROTOCOL_THIS(iface);
192 FIXME("(%p)->(%p)\n", This, pProtocolData);
193 return E_NOTIMPL;
196 static HRESULT WINAPI BindProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
197 DWORD dwOptions)
199 BindProtocol *This = PROTOCOL_THIS(iface);
200 FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
201 return E_NOTIMPL;
204 static HRESULT WINAPI BindProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
206 BindProtocol *This = PROTOCOL_THIS(iface);
208 TRACE("(%p)->(%08x)\n", This, dwOptions);
210 IInternetProtocol_Terminate(This->protocol, 0);
211 return S_OK;
214 static HRESULT WINAPI BindProtocol_Suspend(IInternetProtocol *iface)
216 BindProtocol *This = PROTOCOL_THIS(iface);
217 FIXME("(%p)\n", This);
218 return E_NOTIMPL;
221 static HRESULT WINAPI BindProtocol_Resume(IInternetProtocol *iface)
223 BindProtocol *This = PROTOCOL_THIS(iface);
224 FIXME("(%p)\n", This);
225 return E_NOTIMPL;
228 static HRESULT WINAPI BindProtocol_Read(IInternetProtocol *iface, void *pv,
229 ULONG cb, ULONG *pcbRead)
231 BindProtocol *This = PROTOCOL_THIS(iface);
232 ULONG read = 0;
233 HRESULT hres;
235 TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
237 hres = IInternetProtocol_Read(This->protocol, pv, cb, &read);
239 *pcbRead = read;
240 return hres;
243 static HRESULT WINAPI BindProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
244 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
246 BindProtocol *This = PROTOCOL_THIS(iface);
247 FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
248 return E_NOTIMPL;
251 static HRESULT WINAPI BindProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
253 BindProtocol *This = PROTOCOL_THIS(iface);
254 FIXME("(%p)->(%08x)\n", This, dwOptions);
255 return E_NOTIMPL;
258 static HRESULT WINAPI BindProtocol_UnlockRequest(IInternetProtocol *iface)
260 BindProtocol *This = PROTOCOL_THIS(iface);
261 FIXME("(%p)\n", This);
262 return E_NOTIMPL;
265 #undef PROTOCOL_THIS
267 static const IInternetProtocolVtbl BindProtocolVtbl = {
268 BindProtocol_QueryInterface,
269 BindProtocol_AddRef,
270 BindProtocol_Release,
271 BindProtocol_Start,
272 BindProtocol_Continue,
273 BindProtocol_Abort,
274 BindProtocol_Terminate,
275 BindProtocol_Suspend,
276 BindProtocol_Resume,
277 BindProtocol_Read,
278 BindProtocol_Seek,
279 BindProtocol_LockRequest,
280 BindProtocol_UnlockRequest
283 #define BINDINFO_THIS(iface) DEFINE_THIS(BindProtocol, InternetBindInfo, iface)
285 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface,
286 REFIID riid, void **ppv)
288 BindProtocol *This = BINDINFO_THIS(iface);
289 return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
292 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
294 BindProtocol *This = BINDINFO_THIS(iface);
295 return IBinding_AddRef(PROTOCOL(This));
298 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
300 BindProtocol *This = BINDINFO_THIS(iface);
301 return IBinding_Release(PROTOCOL(This));
304 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface,
305 DWORD *grfBINDF, BINDINFO *pbindinfo)
307 BindProtocol *This = BINDINFO_THIS(iface);
308 HRESULT hres;
310 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
312 hres = IInternetBindInfo_GetBindInfo(This->bind_info, grfBINDF, pbindinfo);
313 if(FAILED(hres)) {
314 WARN("GetBindInfo failed: %08x\n", hres);
315 return hres;
318 *grfBINDF |= BINDF_FROMURLMON;
319 return hres;
322 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface,
323 ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
325 BindProtocol *This = BINDINFO_THIS(iface);
327 TRACE("(%p)->(%d %p %d %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched);
329 return IInternetBindInfo_GetBindString(This->bind_info, ulStringType, ppwzStr, cEl, pcElFetched);
332 #undef BINDFO_THIS
334 static const IInternetBindInfoVtbl InternetBindInfoVtbl = {
335 BindInfo_QueryInterface,
336 BindInfo_AddRef,
337 BindInfo_Release,
338 BindInfo_GetBindInfo,
339 BindInfo_GetBindString
342 #define PRIORITY_THIS(iface) DEFINE_THIS(BindProtocol, InternetPriority, iface)
344 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
345 REFIID riid, void **ppv)
347 BindProtocol *This = PRIORITY_THIS(iface);
348 return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
351 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
353 BindProtocol *This = PRIORITY_THIS(iface);
354 return IInternetProtocol_AddRef(PROTOCOL(This));
357 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
359 BindProtocol *This = PRIORITY_THIS(iface);
360 return IInternetProtocol_Release(PROTOCOL(This));
363 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
365 BindProtocol *This = PRIORITY_THIS(iface);
367 TRACE("(%p)->(%d)\n", This, nPriority);
369 This->priority = nPriority;
370 return S_OK;
373 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
375 BindProtocol *This = PRIORITY_THIS(iface);
377 TRACE("(%p)->(%p)\n", This, pnPriority);
379 *pnPriority = This->priority;
380 return S_OK;
383 #undef PRIORITY_THIS
385 static const IInternetPriorityVtbl InternetPriorityVtbl = {
386 InternetPriority_QueryInterface,
387 InternetPriority_AddRef,
388 InternetPriority_Release,
389 InternetPriority_SetPriority,
390 InternetPriority_GetPriority
394 #define PROTSINK_THIS(iface) DEFINE_THIS(BindProtocol, InternetProtocolSink, iface)
396 static HRESULT WINAPI InternetProtocolSink_QueryInterface(IInternetProtocolSink *iface,
397 REFIID riid, void **ppv)
399 BindProtocol *This = PROTSINK_THIS(iface);
400 return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
403 static ULONG WINAPI InternetProtocolSink_AddRef(IInternetProtocolSink *iface)
405 BindProtocol *This = PROTSINK_THIS(iface);
406 return IInternetProtocol_AddRef(PROTOCOL(This));
409 static ULONG WINAPI InternetProtocolSink_Release(IInternetProtocolSink *iface)
411 BindProtocol *This = PROTSINK_THIS(iface);
412 return IInternetProtocol_Release(PROTOCOL(This));
415 static HRESULT WINAPI InternetProtocolSink_Switch(IInternetProtocolSink *iface,
416 PROTOCOLDATA *pProtocolData)
418 BindProtocol *This = PROTSINK_THIS(iface);
420 TRACE("(%p)->(%p)\n", This, pProtocolData);
422 return IInternetProtocolSink_Switch(This->protocol_sink, pProtocolData);
425 static HRESULT WINAPI InternetProtocolSink_ReportProgress(IInternetProtocolSink *iface,
426 ULONG ulStatusCode, LPCWSTR szStatusText)
428 BindProtocol *This = PROTSINK_THIS(iface);
430 TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
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);
446 return E_NOTIMPL;
449 static HRESULT WINAPI InternetProtocolSink_ReportData(IInternetProtocolSink *iface,
450 DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax)
452 BindProtocol *This = PROTSINK_THIS(iface);
454 TRACE("(%p)->(%d %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
456 return IInternetProtocolSink_ReportData(This->protocol_sink, grfBSCF, ulProgress, ulProgressMax);
459 static HRESULT WINAPI InternetProtocolSink_ReportResult(IInternetProtocolSink *iface,
460 HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
462 BindProtocol *This = PROTSINK_THIS(iface);
464 TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
466 return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
469 #undef PROTSINK_THIS
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
481 #define SERVPROV_THIS(iface) DEFINE_THIS(BindProtocol, ServiceProvider, iface)
483 static HRESULT WINAPI BPServiceProvider_QueryInterface(IServiceProvider *iface,
484 REFIID riid, void **ppv)
486 BindProtocol *This = SERVPROV_THIS(iface);
487 return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
490 static ULONG WINAPI BPServiceProvider_AddRef(IServiceProvider *iface)
492 BindProtocol *This = SERVPROV_THIS(iface);
493 return IInternetProtocol_AddRef(PROTOCOL(This));
496 static ULONG WINAPI BPServiceProvider_Release(IServiceProvider *iface)
498 BindProtocol *This = SERVPROV_THIS(iface);
499 return IInternetProtocol_Release(PROTOCOL(This));
502 static HRESULT WINAPI BPServiceProvider_QueryService(IServiceProvider *iface,
503 REFGUID guidService, REFIID riid, void **ppv)
505 BindProtocol *This = SERVPROV_THIS(iface);
507 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
509 if(!This->service_provider)
510 return E_NOINTERFACE;
512 return IServiceProvider_QueryService(This->service_provider, guidService, riid, ppv);
515 #undef SERVPROV_THIS
517 static const IServiceProviderVtbl ServiceProviderVtbl = {
518 BPServiceProvider_QueryInterface,
519 BPServiceProvider_AddRef,
520 BPServiceProvider_Release,
521 BPServiceProvider_QueryService
524 HRESULT create_binding_protocol(LPCWSTR url, IInternetProtocol **protocol)
526 BindProtocol *ret = heap_alloc(sizeof(BindProtocol));
528 ret->lpInternetProtocolVtbl = &BindProtocolVtbl;
529 ret->lpInternetBindInfoVtbl = &InternetBindInfoVtbl;
530 ret->lpInternetPriorityVtbl = &InternetPriorityVtbl;
531 ret->lpServiceProviderVtbl = &ServiceProviderVtbl;
532 ret->lpInternetProtocolSinkVtbl = &InternetProtocolSinkVtbl;
534 ret->ref = 1;
535 ret->protocol = NULL;
536 ret->bind_info = NULL;
537 ret->protocol_sink = NULL;
538 ret->service_provider = NULL;
539 ret->priority = 0;
541 URLMON_LockModule();
543 *protocol = PROTOCOL(ret);
544 return S_OK;