msxml3/tests: Add a trailing '\n' to an ok() call.
[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 "urlmon_main.h"
20 #include "wine/debug.h"
21
22 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
23
24 typedef struct {
25     const IInternetProtocolVtbl *lpInternetProtocolVtbl;
26     const IInternetBindInfoVtbl *lpInternetBindInfoVtbl;
27     const IInternetPriorityVtbl *lpInternetPriorityVtbl;
28     const IServiceProviderVtbl  *lpServiceProviderVtbl;
29     const IInternetProtocolSinkVtbl *lpInternetProtocolSinkVtbl;
30
31     LONG ref;
32
33     IInternetProtocol *protocol;
34     IInternetBindInfo *bind_info;
35     IInternetProtocolSink *protocol_sink;
36     IServiceProvider *service_provider;
37
38     LONG priority;
39
40     BOOL reported_result;
41     BOOL from_urlmon;
42 } BindProtocol;
43
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)
49
50 #define PROTOCOL_THIS(iface) DEFINE_THIS(BindProtocol, InternetProtocol, iface)
51
52 static HRESULT WINAPI BindProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
53 {
54     BindProtocol *This = PROTOCOL_THIS(iface);
55
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);
80     }
81
82     if(*ppv) {
83         IInternetProtocol_AddRef(iface);
84         return S_OK;
85     }
86
87     WARN("not supported interface %s\n", debugstr_guid(riid));
88     return E_NOINTERFACE;
89 }
90
91 static ULONG WINAPI BindProtocol_AddRef(IInternetProtocol *iface)
92 {
93     BindProtocol *This = PROTOCOL_THIS(iface);
94     LONG ref = InterlockedIncrement(&This->ref);
95     TRACE("(%p) ref=%d\n", This, ref);
96     return ref;
97 }
98
99 static ULONG WINAPI BindProtocol_Release(IInternetProtocol *iface)
100 {
101     BindProtocol *This = PROTOCOL_THIS(iface);
102     LONG ref = InterlockedDecrement(&This->ref);
103
104     TRACE("(%p) ref=%d\n", This, ref);
105
106     if(!ref) {
107         if(This->protocol)
108             IInternetProtocol_Release(This->protocol);
109         if(This->bind_info)
110             IInternetBindInfo_Release(This->bind_info);
111
112         set_binding_sink(PROTOCOL(This), NULL);
113         heap_free(This);
114
115         URLMON_UnlockModule();
116     }
117
118     return ref;
119 }
120
121 static HRESULT WINAPI BindProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
122         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
123         DWORD grfPI, DWORD dwReserved)
124 {
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;
132
133     TRACE("(%p)->(%s %p %p %08x %d)\n", This, debugstr_w(szUrl), pOIProtSink,
134             pOIBindInfo, grfPI, dwReserved);
135
136     if(!szUrl || !pOIProtSink || !pOIBindInfo)
137         return E_INVALIDARG;
138
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);
146     }
147
148     if(!protocol) {
149         IClassFactory *cf;
150         IUnknown *unk;
151
152         hres = get_protocol_handler(szUrl, &clsid, &cf);
153         if(FAILED(hres))
154             return hres;
155
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;
167
168             hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocol, (void**)&protocol);
169             IUnknown_Release(unk);
170             if(FAILED(hres))
171                 return hres;
172         }
173     }
174
175     StringFromCLSID(&clsid, &clsid_str);
176     IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_PROTOCOLCLASSID, clsid_str);
177     CoTaskMemFree(clsid_str);
178
179     This->protocol = protocol;
180
181     IInternetBindInfo_AddRef(pOIBindInfo);
182     This->bind_info = pOIBindInfo;
183
184     set_binding_sink(PROTOCOL(This), pOIProtSink);
185
186     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
187     if(SUCCEEDED(hres)) {
188         IInternetPriority_SetPriority(priority, This->priority);
189         IInternetPriority_Release(priority);
190     }
191
192     return IInternetProtocol_Start(protocol, szUrl, PROTSINK(This), BINDINFO(This), 0, 0);
193 }
194
195 static HRESULT WINAPI BindProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
196 {
197     BindProtocol *This = PROTOCOL_THIS(iface);
198
199     TRACE("(%p)->(%p)\n", This, pProtocolData);
200
201     return IInternetProtocol_Continue(This->protocol, pProtocolData);
202 }
203
204 static HRESULT WINAPI BindProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
205         DWORD dwOptions)
206 {
207     BindProtocol *This = PROTOCOL_THIS(iface);
208     FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
209     return E_NOTIMPL;
210 }
211
212 static HRESULT WINAPI BindProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
213 {
214     BindProtocol *This = PROTOCOL_THIS(iface);
215
216     TRACE("(%p)->(%08x)\n", This, dwOptions);
217
218     if(!This->reported_result)
219         return E_FAIL;
220
221     IInternetProtocol_Terminate(This->protocol, 0);
222
223     set_binding_sink(PROTOCOL(This), NULL);
224
225     if(This->bind_info) {
226         IInternetBindInfo_Release(This->bind_info);
227         This->bind_info = NULL;
228     }
229
230     return S_OK;
231 }
232
233 static HRESULT WINAPI BindProtocol_Suspend(IInternetProtocol *iface)
234 {
235     BindProtocol *This = PROTOCOL_THIS(iface);
236     FIXME("(%p)\n", This);
237     return E_NOTIMPL;
238 }
239
240 static HRESULT WINAPI BindProtocol_Resume(IInternetProtocol *iface)
241 {
242     BindProtocol *This = PROTOCOL_THIS(iface);
243     FIXME("(%p)\n", This);
244     return E_NOTIMPL;
245 }
246
247 static HRESULT WINAPI BindProtocol_Read(IInternetProtocol *iface, void *pv,
248         ULONG cb, ULONG *pcbRead)
249 {
250     BindProtocol *This = PROTOCOL_THIS(iface);
251     ULONG read = 0;
252     HRESULT hres;
253
254     TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
255
256     hres = IInternetProtocol_Read(This->protocol, pv, cb, &read);
257
258     *pcbRead = read;
259     return hres;
260 }
261
262 static HRESULT WINAPI BindProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
263         DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
264 {
265     BindProtocol *This = PROTOCOL_THIS(iface);
266     FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
267     return E_NOTIMPL;
268 }
269
270 static HRESULT WINAPI BindProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
271 {
272     BindProtocol *This = PROTOCOL_THIS(iface);
273
274     TRACE("(%p)->(%08x)\n", This, dwOptions);
275
276     return IInternetProtocol_LockRequest(This->protocol, dwOptions);
277 }
278
279 static HRESULT WINAPI BindProtocol_UnlockRequest(IInternetProtocol *iface)
280 {
281     BindProtocol *This = PROTOCOL_THIS(iface);
282
283     TRACE("(%p)\n", This);
284
285     return IInternetProtocol_UnlockRequest(This->protocol);
286 }
287
288 void set_binding_sink(IInternetProtocol *bind_protocol, IInternetProtocolSink *sink)
289 {
290     BindProtocol *This = PROTOCOL_THIS(bind_protocol);
291     IInternetProtocolSink *prev_sink;
292     IServiceProvider *service_provider = NULL;
293
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);
299
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);
305 }
306
307 #undef PROTOCOL_THIS
308
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
323 };
324
325 #define BINDINFO_THIS(iface) DEFINE_THIS(BindProtocol, InternetBindInfo, iface)
326
327 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface,
328         REFIID riid, void **ppv)
329 {
330     BindProtocol *This = BINDINFO_THIS(iface);
331     return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
332 }
333
334 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
335 {
336     BindProtocol *This = BINDINFO_THIS(iface);
337     return IBinding_AddRef(PROTOCOL(This));
338 }
339
340 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
341 {
342     BindProtocol *This = BINDINFO_THIS(iface);
343     return IBinding_Release(PROTOCOL(This));
344 }
345
346 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface,
347         DWORD *grfBINDF, BINDINFO *pbindinfo)
348 {
349     BindProtocol *This = BINDINFO_THIS(iface);
350     HRESULT hres;
351
352     TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
353
354     hres = IInternetBindInfo_GetBindInfo(This->bind_info, grfBINDF, pbindinfo);
355     if(FAILED(hres)) {
356         WARN("GetBindInfo failed: %08x\n", hres);
357         return hres;
358     }
359
360     *grfBINDF |= BINDF_FROMURLMON;
361     return hres;
362 }
363
364 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface,
365         ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
366 {
367     BindProtocol *This = BINDINFO_THIS(iface);
368
369     TRACE("(%p)->(%d %p %d %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched);
370
371     return IInternetBindInfo_GetBindString(This->bind_info, ulStringType, ppwzStr, cEl, pcElFetched);
372 }
373
374 #undef BINDFO_THIS
375
376 static const IInternetBindInfoVtbl InternetBindInfoVtbl = {
377     BindInfo_QueryInterface,
378     BindInfo_AddRef,
379     BindInfo_Release,
380     BindInfo_GetBindInfo,
381     BindInfo_GetBindString
382 };
383
384 #define PRIORITY_THIS(iface) DEFINE_THIS(BindProtocol, InternetPriority, iface)
385
386 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
387         REFIID riid, void **ppv)
388 {
389     BindProtocol *This = PRIORITY_THIS(iface);
390     return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
391 }
392
393 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
394 {
395     BindProtocol *This = PRIORITY_THIS(iface);
396     return IInternetProtocol_AddRef(PROTOCOL(This));
397 }
398
399 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
400 {
401     BindProtocol *This = PRIORITY_THIS(iface);
402     return IInternetProtocol_Release(PROTOCOL(This));
403 }
404
405 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
406 {
407     BindProtocol *This = PRIORITY_THIS(iface);
408
409     TRACE("(%p)->(%d)\n", This, nPriority);
410
411     This->priority = nPriority;
412     return S_OK;
413 }
414
415 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
416 {
417     BindProtocol *This = PRIORITY_THIS(iface);
418
419     TRACE("(%p)->(%p)\n", This, pnPriority);
420
421     *pnPriority = This->priority;
422     return S_OK;
423 }
424
425 #undef PRIORITY_THIS
426
427 static const IInternetPriorityVtbl InternetPriorityVtbl = {
428     InternetPriority_QueryInterface,
429     InternetPriority_AddRef,
430     InternetPriority_Release,
431     InternetPriority_SetPriority,
432     InternetPriority_GetPriority
433
434 };
435
436 #define PROTSINK_THIS(iface) DEFINE_THIS(BindProtocol, InternetProtocolSink, iface)
437
438 static HRESULT WINAPI BPInternetProtocolSink_QueryInterface(IInternetProtocolSink *iface,
439         REFIID riid, void **ppv)
440 {
441     BindProtocol *This = PROTSINK_THIS(iface);
442     return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
443 }
444
445 static ULONG WINAPI BPInternetProtocolSink_AddRef(IInternetProtocolSink *iface)
446 {
447     BindProtocol *This = PROTSINK_THIS(iface);
448     return IInternetProtocol_AddRef(PROTOCOL(This));
449 }
450
451 static ULONG WINAPI BPInternetProtocolSink_Release(IInternetProtocolSink *iface)
452 {
453     BindProtocol *This = PROTSINK_THIS(iface);
454     return IInternetProtocol_Release(PROTOCOL(This));
455 }
456
457 static HRESULT WINAPI BPInternetProtocolSink_Switch(IInternetProtocolSink *iface,
458         PROTOCOLDATA *pProtocolData)
459 {
460     BindProtocol *This = PROTSINK_THIS(iface);
461
462     TRACE("(%p)->(%p)\n", This, pProtocolData);
463
464     TRACE("flags %x state %x data %p cb %u\n", pProtocolData->grfFlags, pProtocolData->dwState,
465           pProtocolData->pData, pProtocolData->cbData);
466
467     if(!This->protocol_sink) {
468         IInternetProtocol_Continue(This->protocol, pProtocolData);
469         return S_OK;
470     }
471
472     return IInternetProtocolSink_Switch(This->protocol_sink, pProtocolData);
473 }
474
475 static HRESULT WINAPI BPInternetProtocolSink_ReportProgress(IInternetProtocolSink *iface,
476         ULONG ulStatusCode, LPCWSTR szStatusText)
477 {
478     BindProtocol *This = PROTSINK_THIS(iface);
479
480     TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
481
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);
494
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);
503     }
504
505     return E_NOTIMPL;
506 }
507
508 static HRESULT WINAPI BPInternetProtocolSink_ReportData(IInternetProtocolSink *iface,
509         DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax)
510 {
511     BindProtocol *This = PROTSINK_THIS(iface);
512
513     TRACE("(%p)->(%d %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
514
515     if(!This->protocol_sink)
516         return S_OK;
517
518     return IInternetProtocolSink_ReportData(This->protocol_sink, grfBSCF, ulProgress, ulProgressMax);
519 }
520
521 static HRESULT WINAPI BPInternetProtocolSink_ReportResult(IInternetProtocolSink *iface,
522         HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
523 {
524     BindProtocol *This = PROTSINK_THIS(iface);
525
526     TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
527
528     if(!This->protocol_sink)
529         return E_FAIL;
530
531     This->reported_result = TRUE;
532
533     return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
534 }
535
536 #undef PROTSINK_THIS
537
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
546 };
547
548 #define SERVPROV_THIS(iface) DEFINE_THIS(BindProtocol, ServiceProvider, iface)
549
550 static HRESULT WINAPI BPServiceProvider_QueryInterface(IServiceProvider *iface,
551         REFIID riid, void **ppv)
552 {
553     BindProtocol *This = SERVPROV_THIS(iface);
554     return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
555 }
556
557 static ULONG WINAPI BPServiceProvider_AddRef(IServiceProvider *iface)
558 {
559     BindProtocol *This = SERVPROV_THIS(iface);
560     return IInternetProtocol_AddRef(PROTOCOL(This));
561 }
562
563 static ULONG WINAPI BPServiceProvider_Release(IServiceProvider *iface)
564 {
565     BindProtocol *This = SERVPROV_THIS(iface);
566     return IInternetProtocol_Release(PROTOCOL(This));
567 }
568
569 static HRESULT WINAPI BPServiceProvider_QueryService(IServiceProvider *iface,
570         REFGUID guidService, REFIID riid, void **ppv)
571 {
572     BindProtocol *This = SERVPROV_THIS(iface);
573
574     TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
575
576     if(!This->service_provider)
577         return E_NOINTERFACE;
578
579     return IServiceProvider_QueryService(This->service_provider, guidService, riid, ppv);
580 }
581
582 #undef SERVPROV_THIS
583
584 static const IServiceProviderVtbl ServiceProviderVtbl = {
585     BPServiceProvider_QueryInterface,
586     BPServiceProvider_AddRef,
587     BPServiceProvider_Release,
588     BPServiceProvider_QueryService
589 };
590
591 HRESULT create_binding_protocol(LPCWSTR url, BOOL from_urlmon, IInternetProtocol **protocol)
592 {
593     BindProtocol *ret = heap_alloc_zero(sizeof(BindProtocol));
594
595     ret->lpInternetProtocolVtbl = &BindProtocolVtbl;
596     ret->lpInternetBindInfoVtbl = &InternetBindInfoVtbl;
597     ret->lpInternetPriorityVtbl = &InternetPriorityVtbl;
598     ret->lpServiceProviderVtbl  = &ServiceProviderVtbl;
599     ret->lpInternetProtocolSinkVtbl = &InternetProtocolSinkVtbl;
600
601     ret->ref = 1;
602     ret->from_urlmon = from_urlmon;
603
604     URLMON_LockModule();
605
606     *protocol = PROTOCOL(ret);
607     return S_OK;
608 }