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);
25 const IInternetProtocolVtbl *lpInternetProtocolVtbl;
26 const IInternetBindInfoVtbl *lpInternetBindInfoVtbl;
27 const IInternetPriorityVtbl *lpInternetPriorityVtbl;
28 const IServiceProviderVtbl *lpServiceProviderVtbl;
29 const IInternetProtocolSinkVtbl *lpInternetProtocolSinkVtbl;
33 IInternetProtocol *protocol;
34 IInternetBindInfo *bind_info;
35 IInternetProtocolSink *protocol_sink;
36 IServiceProvider *service_provider;
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);
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);
80 IInternetProtocol_AddRef(iface);
84 WARN("not supported interface %s\n", debugstr_guid(riid));
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);
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);
105 IInternetProtocol_Release(This->protocol);
107 IInternetBindInfo_Release(This->bind_info);
109 set_binding_sink(PROTOCOL(This), NULL);
112 URLMON_UnlockModule();
118 static HRESULT WINAPI BindProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
119 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
120 DWORD grfPI, DWORD dwReserved)
122 BindProtocol *This = PROTOCOL_THIS(iface);
123 IInternetProtocol *protocol = NULL;
124 IInternetPriority *priority;
125 IServiceProvider *service_provider;
126 CLSID clsid = IID_NULL;
130 TRACE("(%p)->(%s %p %p %08x %d)\n", This, debugstr_w(szUrl), pOIProtSink,
131 pOIBindInfo, grfPI, dwReserved);
133 if(!szUrl || !pOIProtSink || !pOIBindInfo)
136 hres = IInternetProtocolSink_QueryInterface(pOIProtSink, &IID_IServiceProvider,
137 (void**)&service_provider);
138 if(SUCCEEDED(hres)) {
139 /* FIXME: What's protocol CLSID here? */
140 IServiceProvider_QueryService(service_provider, &IID_IInternetProtocol,
141 &IID_IInternetProtocol, (void**)&protocol);
142 IServiceProvider_Release(service_provider);
149 hres = get_protocol_handler(szUrl, &clsid, &cf);
153 hres = IClassFactory_CreateInstance(cf, (IUnknown*)BINDINFO(This),
154 &IID_IUnknown, (void**)&unk);
155 IClassFactory_Release(cf);
159 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocol, (void**)&protocol);
160 IUnknown_Release(unk);
165 StringFromCLSID(&clsid, &clsid_str);
166 IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_PROTOCOLCLASSID, clsid_str);
167 CoTaskMemFree(clsid_str);
169 This->protocol = protocol;
171 IInternetBindInfo_AddRef(pOIBindInfo);
172 This->bind_info = pOIBindInfo;
174 set_binding_sink(PROTOCOL(This), pOIProtSink);
176 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
177 if(SUCCEEDED(hres)) {
178 IInternetPriority_SetPriority(priority, This->priority);
179 IInternetPriority_Release(priority);
182 return IInternetProtocol_Start(protocol, szUrl, PROTSINK(This), BINDINFO(This), 0, 0);
185 static HRESULT WINAPI BindProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
187 BindProtocol *This = PROTOCOL_THIS(iface);
189 TRACE("(%p)->(%p)\n", This, pProtocolData);
191 return IInternetProtocol_Continue(This->protocol, pProtocolData);
194 static HRESULT WINAPI BindProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
197 BindProtocol *This = PROTOCOL_THIS(iface);
198 FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
202 static HRESULT WINAPI BindProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
204 BindProtocol *This = PROTOCOL_THIS(iface);
206 TRACE("(%p)->(%08x)\n", This, dwOptions);
208 IInternetProtocol_Terminate(This->protocol, 0);
212 static HRESULT WINAPI BindProtocol_Suspend(IInternetProtocol *iface)
214 BindProtocol *This = PROTOCOL_THIS(iface);
215 FIXME("(%p)\n", This);
219 static HRESULT WINAPI BindProtocol_Resume(IInternetProtocol *iface)
221 BindProtocol *This = PROTOCOL_THIS(iface);
222 FIXME("(%p)\n", This);
226 static HRESULT WINAPI BindProtocol_Read(IInternetProtocol *iface, void *pv,
227 ULONG cb, ULONG *pcbRead)
229 BindProtocol *This = PROTOCOL_THIS(iface);
233 TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
235 hres = IInternetProtocol_Read(This->protocol, pv, cb, &read);
241 static HRESULT WINAPI BindProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
242 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
244 BindProtocol *This = PROTOCOL_THIS(iface);
245 FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
249 static HRESULT WINAPI BindProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
251 BindProtocol *This = PROTOCOL_THIS(iface);
253 TRACE("(%p)->(%08x)\n", This, dwOptions);
255 return IInternetProtocol_LockRequest(This->protocol, dwOptions);
258 static HRESULT WINAPI BindProtocol_UnlockRequest(IInternetProtocol *iface)
260 BindProtocol *This = PROTOCOL_THIS(iface);
262 TRACE("(%p)\n", This);
264 return IInternetProtocol_UnlockRequest(This->protocol);
267 void set_binding_sink(IInternetProtocol *bind_protocol, IInternetProtocolSink *sink)
269 BindProtocol *This = PROTOCOL_THIS(bind_protocol);
270 IInternetProtocolSink *prev_sink;
271 IServiceProvider *service_provider = NULL;
274 IInternetProtocolSink_AddRef(sink);
275 prev_sink = InterlockedExchangePointer((void**)&This->protocol_sink, sink);
277 IInternetProtocolSink_Release(prev_sink);
280 IInternetProtocolSink_QueryInterface(sink, &IID_IServiceProvider, (void**)&service_provider);
281 service_provider = InterlockedExchangePointer((void**)&This->service_provider, service_provider);
283 IServiceProvider_Release(service_provider);
288 static const IInternetProtocolVtbl BindProtocolVtbl = {
289 BindProtocol_QueryInterface,
291 BindProtocol_Release,
293 BindProtocol_Continue,
295 BindProtocol_Terminate,
296 BindProtocol_Suspend,
300 BindProtocol_LockRequest,
301 BindProtocol_UnlockRequest
304 #define BINDINFO_THIS(iface) DEFINE_THIS(BindProtocol, InternetBindInfo, iface)
306 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface,
307 REFIID riid, void **ppv)
309 BindProtocol *This = BINDINFO_THIS(iface);
310 return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
313 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
315 BindProtocol *This = BINDINFO_THIS(iface);
316 return IBinding_AddRef(PROTOCOL(This));
319 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
321 BindProtocol *This = BINDINFO_THIS(iface);
322 return IBinding_Release(PROTOCOL(This));
325 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface,
326 DWORD *grfBINDF, BINDINFO *pbindinfo)
328 BindProtocol *This = BINDINFO_THIS(iface);
331 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
333 hres = IInternetBindInfo_GetBindInfo(This->bind_info, grfBINDF, pbindinfo);
335 WARN("GetBindInfo failed: %08x\n", hres);
339 *grfBINDF |= BINDF_FROMURLMON;
343 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface,
344 ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
346 BindProtocol *This = BINDINFO_THIS(iface);
348 TRACE("(%p)->(%d %p %d %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched);
350 return IInternetBindInfo_GetBindString(This->bind_info, ulStringType, ppwzStr, cEl, pcElFetched);
355 static const IInternetBindInfoVtbl InternetBindInfoVtbl = {
356 BindInfo_QueryInterface,
359 BindInfo_GetBindInfo,
360 BindInfo_GetBindString
363 #define PRIORITY_THIS(iface) DEFINE_THIS(BindProtocol, InternetPriority, iface)
365 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
366 REFIID riid, void **ppv)
368 BindProtocol *This = PRIORITY_THIS(iface);
369 return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
372 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
374 BindProtocol *This = PRIORITY_THIS(iface);
375 return IInternetProtocol_AddRef(PROTOCOL(This));
378 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
380 BindProtocol *This = PRIORITY_THIS(iface);
381 return IInternetProtocol_Release(PROTOCOL(This));
384 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
386 BindProtocol *This = PRIORITY_THIS(iface);
388 TRACE("(%p)->(%d)\n", This, nPriority);
390 This->priority = nPriority;
394 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
396 BindProtocol *This = PRIORITY_THIS(iface);
398 TRACE("(%p)->(%p)\n", This, pnPriority);
400 *pnPriority = This->priority;
406 static const IInternetPriorityVtbl InternetPriorityVtbl = {
407 InternetPriority_QueryInterface,
408 InternetPriority_AddRef,
409 InternetPriority_Release,
410 InternetPriority_SetPriority,
411 InternetPriority_GetPriority
415 #define PROTSINK_THIS(iface) DEFINE_THIS(BindProtocol, InternetProtocolSink, iface)
417 static HRESULT WINAPI BPInternetProtocolSink_QueryInterface(IInternetProtocolSink *iface,
418 REFIID riid, void **ppv)
420 BindProtocol *This = PROTSINK_THIS(iface);
421 return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
424 static ULONG WINAPI BPInternetProtocolSink_AddRef(IInternetProtocolSink *iface)
426 BindProtocol *This = PROTSINK_THIS(iface);
427 return IInternetProtocol_AddRef(PROTOCOL(This));
430 static ULONG WINAPI BPInternetProtocolSink_Release(IInternetProtocolSink *iface)
432 BindProtocol *This = PROTSINK_THIS(iface);
433 return IInternetProtocol_Release(PROTOCOL(This));
436 static HRESULT WINAPI BPInternetProtocolSink_Switch(IInternetProtocolSink *iface,
437 PROTOCOLDATA *pProtocolData)
439 BindProtocol *This = PROTSINK_THIS(iface);
441 TRACE("(%p)->(%p)\n", This, pProtocolData);
443 return IInternetProtocolSink_Switch(This->protocol_sink, pProtocolData);
446 static HRESULT WINAPI BPInternetProtocolSink_ReportProgress(IInternetProtocolSink *iface,
447 ULONG ulStatusCode, LPCWSTR szStatusText)
449 BindProtocol *This = PROTSINK_THIS(iface);
451 TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
453 switch(ulStatusCode) {
454 case BINDSTATUS_FINDINGRESOURCE:
455 case BINDSTATUS_CONNECTING:
456 case BINDSTATUS_SENDINGREQUEST:
457 case BINDSTATUS_CACHEFILENAMEAVAILABLE:
458 return IInternetProtocolSink_ReportProgress(This->protocol_sink,
459 ulStatusCode, szStatusText);
460 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
461 case BINDSTATUS_MIMETYPEAVAILABLE:
462 return IInternetProtocolSink_ReportProgress(This->protocol_sink,
463 BINDSTATUS_MIMETYPEAVAILABLE, szStatusText);
465 FIXME("unsupported ulStatusCode %u\n", ulStatusCode);
471 static HRESULT WINAPI BPInternetProtocolSink_ReportData(IInternetProtocolSink *iface,
472 DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax)
474 BindProtocol *This = PROTSINK_THIS(iface);
476 TRACE("(%p)->(%d %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
478 return IInternetProtocolSink_ReportData(This->protocol_sink, grfBSCF, ulProgress, ulProgressMax);
481 static HRESULT WINAPI BPInternetProtocolSink_ReportResult(IInternetProtocolSink *iface,
482 HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
484 BindProtocol *This = PROTSINK_THIS(iface);
486 TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
488 return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
493 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = {
494 BPInternetProtocolSink_QueryInterface,
495 BPInternetProtocolSink_AddRef,
496 BPInternetProtocolSink_Release,
497 BPInternetProtocolSink_Switch,
498 BPInternetProtocolSink_ReportProgress,
499 BPInternetProtocolSink_ReportData,
500 BPInternetProtocolSink_ReportResult
503 #define SERVPROV_THIS(iface) DEFINE_THIS(BindProtocol, ServiceProvider, iface)
505 static HRESULT WINAPI BPServiceProvider_QueryInterface(IServiceProvider *iface,
506 REFIID riid, void **ppv)
508 BindProtocol *This = SERVPROV_THIS(iface);
509 return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
512 static ULONG WINAPI BPServiceProvider_AddRef(IServiceProvider *iface)
514 BindProtocol *This = SERVPROV_THIS(iface);
515 return IInternetProtocol_AddRef(PROTOCOL(This));
518 static ULONG WINAPI BPServiceProvider_Release(IServiceProvider *iface)
520 BindProtocol *This = SERVPROV_THIS(iface);
521 return IInternetProtocol_Release(PROTOCOL(This));
524 static HRESULT WINAPI BPServiceProvider_QueryService(IServiceProvider *iface,
525 REFGUID guidService, REFIID riid, void **ppv)
527 BindProtocol *This = SERVPROV_THIS(iface);
529 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
531 if(!This->service_provider)
532 return E_NOINTERFACE;
534 return IServiceProvider_QueryService(This->service_provider, guidService, riid, ppv);
539 static const IServiceProviderVtbl ServiceProviderVtbl = {
540 BPServiceProvider_QueryInterface,
541 BPServiceProvider_AddRef,
542 BPServiceProvider_Release,
543 BPServiceProvider_QueryService
546 HRESULT create_binding_protocol(LPCWSTR url, IInternetProtocol **protocol)
548 BindProtocol *ret = heap_alloc_zero(sizeof(BindProtocol));
550 ret->lpInternetProtocolVtbl = &BindProtocolVtbl;
551 ret->lpInternetBindInfoVtbl = &InternetBindInfoVtbl;
552 ret->lpInternetPriorityVtbl = &InternetPriorityVtbl;
553 ret->lpServiceProviderVtbl = &ServiceProviderVtbl;
554 ret->lpInternetProtocolSinkVtbl = &InternetProtocolSinkVtbl;
560 *protocol = PROTOCOL(ret);