rpcrt4: Free the memory for a registered interface that is in use and when WaitForCal...
[wine.git] / dlls / urlmon / bindprot.c
blob81dfabf214afae7df2f0c64f640fd1d06abc82cd
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;
40 BOOL reported_result;
41 BOOL from_urlmon;
42 } BindProtocol;
44 #define PROTOCOL(x) ((IInternetProtocol*) &(x)->lpInternetProtocolVtbl)
45 #define BINDINFO(x) ((IInternetBindInfo*) &(x)->lpInternetBindInfoVtbl)
46 #define PRIORITY(x) ((IInternetPriority*) &(x)->lpInternetPriorityVtbl)
47 #define SERVPROV(x) ((IServiceProvider*) &(x)->lpServiceProviderVtbl)
48 #define PROTSINK(x) ((IInternetProtocolSink*) &(x)->lpInternetProtocolSinkVtbl)
50 #define PROTOCOL_THIS(iface) DEFINE_THIS(BindProtocol, InternetProtocol, iface)
52 static HRESULT WINAPI BindProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
54 BindProtocol *This = PROTOCOL_THIS(iface);
56 *ppv = NULL;
57 if(IsEqualGUID(&IID_IUnknown, riid)) {
58 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
59 *ppv = PROTOCOL(This);
60 }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
61 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
62 *ppv = PROTOCOL(This);
63 }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
64 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
65 *ppv = PROTOCOL(This);
66 }else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) {
67 TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This, ppv);
68 *ppv = BINDINFO(This);
69 }else if(IsEqualGUID(&IID_IInternetPriority, riid)) {
70 TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv);
71 *ppv = PRIORITY(This);
72 }else if(IsEqualGUID(&IID_IAuthenticate, riid)) {
73 FIXME("(%p)->(IID_IAuthenticate %p)\n", This, ppv);
74 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
75 TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
76 *ppv = SERVPROV(This);
77 }else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
78 TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
79 *ppv = PROTSINK(This);
82 if(*ppv) {
83 IInternetProtocol_AddRef(iface);
84 return S_OK;
87 WARN("not supported interface %s\n", debugstr_guid(riid));
88 return E_NOINTERFACE;
91 static ULONG WINAPI BindProtocol_AddRef(IInternetProtocol *iface)
93 BindProtocol *This = PROTOCOL_THIS(iface);
94 LONG ref = InterlockedIncrement(&This->ref);
95 TRACE("(%p) ref=%d\n", This, ref);
96 return ref;
99 static ULONG WINAPI BindProtocol_Release(IInternetProtocol *iface)
101 BindProtocol *This = PROTOCOL_THIS(iface);
102 LONG ref = InterlockedDecrement(&This->ref);
104 TRACE("(%p) ref=%d\n", This, ref);
106 if(!ref) {
107 if(This->protocol)
108 IInternetProtocol_Release(This->protocol);
109 if(This->bind_info)
110 IInternetBindInfo_Release(This->bind_info);
112 set_binding_sink(PROTOCOL(This), NULL);
113 heap_free(This);
115 URLMON_UnlockModule();
118 return ref;
121 static HRESULT WINAPI BindProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
122 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
123 DWORD grfPI, DWORD dwReserved)
125 BindProtocol *This = PROTOCOL_THIS(iface);
126 IInternetProtocol *protocol = NULL;
127 IInternetPriority *priority;
128 IServiceProvider *service_provider;
129 CLSID clsid = IID_NULL;
130 LPOLESTR clsid_str;
131 HRESULT hres;
133 TRACE("(%p)->(%s %p %p %08x %d)\n", This, debugstr_w(szUrl), pOIProtSink,
134 pOIBindInfo, grfPI, dwReserved);
136 if(!szUrl || !pOIProtSink || !pOIBindInfo)
137 return E_INVALIDARG;
139 hres = IInternetProtocolSink_QueryInterface(pOIProtSink, &IID_IServiceProvider,
140 (void**)&service_provider);
141 if(SUCCEEDED(hres)) {
142 /* FIXME: What's protocol CLSID here? */
143 IServiceProvider_QueryService(service_provider, &IID_IInternetProtocol,
144 &IID_IInternetProtocol, (void**)&protocol);
145 IServiceProvider_Release(service_provider);
148 if(!protocol) {
149 IClassFactory *cf;
150 IUnknown *unk;
152 hres = get_protocol_handler(szUrl, &clsid, &cf);
153 if(FAILED(hres))
154 return hres;
156 if(This->from_urlmon) {
157 hres = IClassFactory_CreateInstance(cf, NULL, &IID_IInternetProtocol, (void**)&protocol);
158 IClassFactory_Release(cf);
159 if(FAILED(hres))
160 return hres;
161 }else {
162 hres = IClassFactory_CreateInstance(cf, (IUnknown*)BINDINFO(This),
163 &IID_IUnknown, (void**)&unk);
164 IClassFactory_Release(cf);
165 if(FAILED(hres))
166 return hres;
168 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocol, (void**)&protocol);
169 IUnknown_Release(unk);
170 if(FAILED(hres))
171 return hres;
175 StringFromCLSID(&clsid, &clsid_str);
176 IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_PROTOCOLCLASSID, clsid_str);
177 CoTaskMemFree(clsid_str);
179 This->protocol = protocol;
181 IInternetBindInfo_AddRef(pOIBindInfo);
182 This->bind_info = pOIBindInfo;
184 set_binding_sink(PROTOCOL(This), pOIProtSink);
186 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
187 if(SUCCEEDED(hres)) {
188 IInternetPriority_SetPriority(priority, This->priority);
189 IInternetPriority_Release(priority);
192 return IInternetProtocol_Start(protocol, szUrl, PROTSINK(This), BINDINFO(This), 0, 0);
195 static HRESULT WINAPI BindProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
197 BindProtocol *This = PROTOCOL_THIS(iface);
199 TRACE("(%p)->(%p)\n", This, pProtocolData);
201 return IInternetProtocol_Continue(This->protocol, pProtocolData);
204 static HRESULT WINAPI BindProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
205 DWORD dwOptions)
207 BindProtocol *This = PROTOCOL_THIS(iface);
208 FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
209 return E_NOTIMPL;
212 static HRESULT WINAPI BindProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
214 BindProtocol *This = PROTOCOL_THIS(iface);
216 TRACE("(%p)->(%08x)\n", This, dwOptions);
218 if(!This->reported_result)
219 return E_FAIL;
221 IInternetProtocol_Terminate(This->protocol, 0);
223 set_binding_sink(PROTOCOL(This), NULL);
225 if(This->bind_info) {
226 IInternetBindInfo_Release(This->bind_info);
227 This->bind_info = NULL;
230 return S_OK;
233 static HRESULT WINAPI BindProtocol_Suspend(IInternetProtocol *iface)
235 BindProtocol *This = PROTOCOL_THIS(iface);
236 FIXME("(%p)\n", This);
237 return E_NOTIMPL;
240 static HRESULT WINAPI BindProtocol_Resume(IInternetProtocol *iface)
242 BindProtocol *This = PROTOCOL_THIS(iface);
243 FIXME("(%p)\n", This);
244 return E_NOTIMPL;
247 static HRESULT WINAPI BindProtocol_Read(IInternetProtocol *iface, void *pv,
248 ULONG cb, ULONG *pcbRead)
250 BindProtocol *This = PROTOCOL_THIS(iface);
251 ULONG read = 0;
252 HRESULT hres;
254 TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
256 hres = IInternetProtocol_Read(This->protocol, pv, cb, &read);
258 *pcbRead = read;
259 return hres;
262 static HRESULT WINAPI BindProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
263 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
265 BindProtocol *This = PROTOCOL_THIS(iface);
266 FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
267 return E_NOTIMPL;
270 static HRESULT WINAPI BindProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
272 BindProtocol *This = PROTOCOL_THIS(iface);
274 TRACE("(%p)->(%08x)\n", This, dwOptions);
276 return IInternetProtocol_LockRequest(This->protocol, dwOptions);
279 static HRESULT WINAPI BindProtocol_UnlockRequest(IInternetProtocol *iface)
281 BindProtocol *This = PROTOCOL_THIS(iface);
283 TRACE("(%p)\n", This);
285 return IInternetProtocol_UnlockRequest(This->protocol);
288 void set_binding_sink(IInternetProtocol *bind_protocol, IInternetProtocolSink *sink)
290 BindProtocol *This = PROTOCOL_THIS(bind_protocol);
291 IInternetProtocolSink *prev_sink;
292 IServiceProvider *service_provider = NULL;
294 if(sink)
295 IInternetProtocolSink_AddRef(sink);
296 prev_sink = InterlockedExchangePointer((void**)&This->protocol_sink, sink);
297 if(prev_sink)
298 IInternetProtocolSink_Release(prev_sink);
300 if(sink)
301 IInternetProtocolSink_QueryInterface(sink, &IID_IServiceProvider, (void**)&service_provider);
302 service_provider = InterlockedExchangePointer((void**)&This->service_provider, service_provider);
303 if(service_provider)
304 IServiceProvider_Release(service_provider);
307 #undef PROTOCOL_THIS
309 static const IInternetProtocolVtbl BindProtocolVtbl = {
310 BindProtocol_QueryInterface,
311 BindProtocol_AddRef,
312 BindProtocol_Release,
313 BindProtocol_Start,
314 BindProtocol_Continue,
315 BindProtocol_Abort,
316 BindProtocol_Terminate,
317 BindProtocol_Suspend,
318 BindProtocol_Resume,
319 BindProtocol_Read,
320 BindProtocol_Seek,
321 BindProtocol_LockRequest,
322 BindProtocol_UnlockRequest
325 #define BINDINFO_THIS(iface) DEFINE_THIS(BindProtocol, InternetBindInfo, iface)
327 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface,
328 REFIID riid, void **ppv)
330 BindProtocol *This = BINDINFO_THIS(iface);
331 return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
334 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
336 BindProtocol *This = BINDINFO_THIS(iface);
337 return IBinding_AddRef(PROTOCOL(This));
340 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
342 BindProtocol *This = BINDINFO_THIS(iface);
343 return IBinding_Release(PROTOCOL(This));
346 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface,
347 DWORD *grfBINDF, BINDINFO *pbindinfo)
349 BindProtocol *This = BINDINFO_THIS(iface);
350 HRESULT hres;
352 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
354 hres = IInternetBindInfo_GetBindInfo(This->bind_info, grfBINDF, pbindinfo);
355 if(FAILED(hres)) {
356 WARN("GetBindInfo failed: %08x\n", hres);
357 return hres;
360 *grfBINDF |= BINDF_FROMURLMON;
361 return hres;
364 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface,
365 ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
367 BindProtocol *This = BINDINFO_THIS(iface);
369 TRACE("(%p)->(%d %p %d %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched);
371 return IInternetBindInfo_GetBindString(This->bind_info, ulStringType, ppwzStr, cEl, pcElFetched);
374 #undef BINDFO_THIS
376 static const IInternetBindInfoVtbl InternetBindInfoVtbl = {
377 BindInfo_QueryInterface,
378 BindInfo_AddRef,
379 BindInfo_Release,
380 BindInfo_GetBindInfo,
381 BindInfo_GetBindString
384 #define PRIORITY_THIS(iface) DEFINE_THIS(BindProtocol, InternetPriority, iface)
386 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
387 REFIID riid, void **ppv)
389 BindProtocol *This = PRIORITY_THIS(iface);
390 return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
393 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
395 BindProtocol *This = PRIORITY_THIS(iface);
396 return IInternetProtocol_AddRef(PROTOCOL(This));
399 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
401 BindProtocol *This = PRIORITY_THIS(iface);
402 return IInternetProtocol_Release(PROTOCOL(This));
405 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
407 BindProtocol *This = PRIORITY_THIS(iface);
409 TRACE("(%p)->(%d)\n", This, nPriority);
411 This->priority = nPriority;
412 return S_OK;
415 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
417 BindProtocol *This = PRIORITY_THIS(iface);
419 TRACE("(%p)->(%p)\n", This, pnPriority);
421 *pnPriority = This->priority;
422 return S_OK;
425 #undef PRIORITY_THIS
427 static const IInternetPriorityVtbl InternetPriorityVtbl = {
428 InternetPriority_QueryInterface,
429 InternetPriority_AddRef,
430 InternetPriority_Release,
431 InternetPriority_SetPriority,
432 InternetPriority_GetPriority
436 #define PROTSINK_THIS(iface) DEFINE_THIS(BindProtocol, InternetProtocolSink, iface)
438 static HRESULT WINAPI BPInternetProtocolSink_QueryInterface(IInternetProtocolSink *iface,
439 REFIID riid, void **ppv)
441 BindProtocol *This = PROTSINK_THIS(iface);
442 return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
445 static ULONG WINAPI BPInternetProtocolSink_AddRef(IInternetProtocolSink *iface)
447 BindProtocol *This = PROTSINK_THIS(iface);
448 return IInternetProtocol_AddRef(PROTOCOL(This));
451 static ULONG WINAPI BPInternetProtocolSink_Release(IInternetProtocolSink *iface)
453 BindProtocol *This = PROTSINK_THIS(iface);
454 return IInternetProtocol_Release(PROTOCOL(This));
457 static HRESULT WINAPI BPInternetProtocolSink_Switch(IInternetProtocolSink *iface,
458 PROTOCOLDATA *pProtocolData)
460 BindProtocol *This = PROTSINK_THIS(iface);
462 TRACE("(%p)->(%p)\n", This, pProtocolData);
464 TRACE("flags %x state %x data %p cb %u\n", pProtocolData->grfFlags, pProtocolData->dwState,
465 pProtocolData->pData, pProtocolData->cbData);
467 if(!This->protocol_sink) {
468 IInternetProtocol_Continue(This->protocol, pProtocolData);
469 return S_OK;
472 return IInternetProtocolSink_Switch(This->protocol_sink, pProtocolData);
475 static HRESULT WINAPI BPInternetProtocolSink_ReportProgress(IInternetProtocolSink *iface,
476 ULONG ulStatusCode, LPCWSTR szStatusText)
478 BindProtocol *This = PROTSINK_THIS(iface);
480 TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
482 switch(ulStatusCode) {
483 case BINDSTATUS_FINDINGRESOURCE:
484 case BINDSTATUS_CONNECTING:
485 case BINDSTATUS_BEGINDOWNLOADDATA:
486 case BINDSTATUS_SENDINGREQUEST:
487 case BINDSTATUS_CACHEFILENAMEAVAILABLE:
488 case BINDSTATUS_DIRECTBIND:
489 case BINDSTATUS_MIMETYPEAVAILABLE:
490 if(!This->protocol_sink)
491 return S_OK;
492 return IInternetProtocolSink_ReportProgress(This->protocol_sink,
493 ulStatusCode, szStatusText);
495 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
496 if(!This->protocol_sink)
497 return S_OK;
498 return IInternetProtocolSink_ReportProgress(This->protocol_sink,
499 This->from_urlmon ? BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE : BINDSTATUS_MIMETYPEAVAILABLE,
500 szStatusText);
501 default:
502 FIXME("unsupported ulStatusCode %u\n", ulStatusCode);
505 return E_NOTIMPL;
508 static HRESULT WINAPI BPInternetProtocolSink_ReportData(IInternetProtocolSink *iface,
509 DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax)
511 BindProtocol *This = PROTSINK_THIS(iface);
513 TRACE("(%p)->(%d %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
515 if(!This->protocol_sink)
516 return S_OK;
518 return IInternetProtocolSink_ReportData(This->protocol_sink, grfBSCF, ulProgress, ulProgressMax);
521 static HRESULT WINAPI BPInternetProtocolSink_ReportResult(IInternetProtocolSink *iface,
522 HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
524 BindProtocol *This = PROTSINK_THIS(iface);
526 TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
528 if(!This->protocol_sink)
529 return E_FAIL;
531 This->reported_result = TRUE;
533 return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
536 #undef PROTSINK_THIS
538 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = {
539 BPInternetProtocolSink_QueryInterface,
540 BPInternetProtocolSink_AddRef,
541 BPInternetProtocolSink_Release,
542 BPInternetProtocolSink_Switch,
543 BPInternetProtocolSink_ReportProgress,
544 BPInternetProtocolSink_ReportData,
545 BPInternetProtocolSink_ReportResult
548 #define SERVPROV_THIS(iface) DEFINE_THIS(BindProtocol, ServiceProvider, iface)
550 static HRESULT WINAPI BPServiceProvider_QueryInterface(IServiceProvider *iface,
551 REFIID riid, void **ppv)
553 BindProtocol *This = SERVPROV_THIS(iface);
554 return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
557 static ULONG WINAPI BPServiceProvider_AddRef(IServiceProvider *iface)
559 BindProtocol *This = SERVPROV_THIS(iface);
560 return IInternetProtocol_AddRef(PROTOCOL(This));
563 static ULONG WINAPI BPServiceProvider_Release(IServiceProvider *iface)
565 BindProtocol *This = SERVPROV_THIS(iface);
566 return IInternetProtocol_Release(PROTOCOL(This));
569 static HRESULT WINAPI BPServiceProvider_QueryService(IServiceProvider *iface,
570 REFGUID guidService, REFIID riid, void **ppv)
572 BindProtocol *This = SERVPROV_THIS(iface);
574 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
576 if(!This->service_provider)
577 return E_NOINTERFACE;
579 return IServiceProvider_QueryService(This->service_provider, guidService, riid, ppv);
582 #undef SERVPROV_THIS
584 static const IServiceProviderVtbl ServiceProviderVtbl = {
585 BPServiceProvider_QueryInterface,
586 BPServiceProvider_AddRef,
587 BPServiceProvider_Release,
588 BPServiceProvider_QueryService
591 HRESULT create_binding_protocol(LPCWSTR url, BOOL from_urlmon, IInternetProtocol **protocol)
593 BindProtocol *ret = heap_alloc_zero(sizeof(BindProtocol));
595 ret->lpInternetProtocolVtbl = &BindProtocolVtbl;
596 ret->lpInternetBindInfoVtbl = &InternetBindInfoVtbl;
597 ret->lpInternetPriorityVtbl = &InternetPriorityVtbl;
598 ret->lpServiceProviderVtbl = &ServiceProviderVtbl;
599 ret->lpInternetProtocolSinkVtbl = &InternetProtocolSinkVtbl;
601 ret->ref = 1;
602 ret->from_urlmon = from_urlmon;
604 URLMON_LockModule();
606 *protocol = PROTOCOL(ret);
607 return S_OK;