Sync with trunk head (part 1 of 2)
[reactos.git] / dll / win32 / urlmon / bindprot.c
1 /*
2 * Copyright 2007-2009 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 BindProtocol BindProtocol;
25
26 struct _task_header_t;
27
28 typedef void (*task_proc_t)(BindProtocol*,struct _task_header_t*);
29
30 typedef struct _task_header_t {
31 task_proc_t proc;
32 struct _task_header_t *next;
33 } task_header_t;
34
35 struct BindProtocol {
36 const IInternetProtocolVtbl *lpIInternetProtocolVtbl;
37 const IInternetBindInfoVtbl *lpInternetBindInfoVtbl;
38 const IInternetPriorityVtbl *lpInternetPriorityVtbl;
39 const IServiceProviderVtbl *lpServiceProviderVtbl;
40 const IInternetProtocolSinkVtbl *lpIInternetProtocolSinkVtbl;
41 const IWinInetHttpInfoVtbl *lpIWinInetHttpInfoVtbl;
42
43 const IInternetProtocolVtbl *lpIInternetProtocolHandlerVtbl;
44
45 LONG ref;
46
47 IInternetProtocol *protocol;
48 IInternetProtocol *protocol_handler;
49 IInternetBindInfo *bind_info;
50 IInternetProtocolSink *protocol_sink;
51 IServiceProvider *service_provider;
52 IWinInetInfo *wininet_info;
53
54 LONG priority;
55
56 BOOL reported_result;
57 BOOL reported_mime;
58 BOOL from_urlmon;
59 DWORD pi;
60
61 DWORD apartment_thread;
62 HWND notif_hwnd;
63 DWORD continue_call;
64
65 CRITICAL_SECTION section;
66 task_header_t *task_queue_head, *task_queue_tail;
67
68 BYTE *buf;
69 DWORD buf_size;
70 LPWSTR mime;
71 LPWSTR url;
72 ProtocolProxy *filter_proxy;
73 };
74
75 #define BINDINFO(x) ((IInternetBindInfo*) &(x)->lpInternetBindInfoVtbl)
76 #define PRIORITY(x) ((IInternetPriority*) &(x)->lpInternetPriorityVtbl)
77 #define HTTPINFO(x) ((IWinInetHttpInfo*) &(x)->lpIWinInetHttpInfoVtbl)
78 #define SERVPROV(x) ((IServiceProvider*) &(x)->lpServiceProviderVtbl)
79
80 #define PROTOCOLHANDLER(x) ((IInternetProtocol*) &(x)->lpIInternetProtocolHandlerVtbl)
81
82 #define BUFFER_SIZE 2048
83 #define MIME_TEST_SIZE 255
84
85 #define WM_MK_CONTINUE (WM_USER+101)
86 #define WM_MK_RELEASE (WM_USER+102)
87
88 static LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
89 {
90 switch(msg) {
91 case WM_MK_CONTINUE: {
92 BindProtocol *This = (BindProtocol*)lParam;
93 task_header_t *task;
94
95 while(1) {
96 EnterCriticalSection(&This->section);
97
98 task = This->task_queue_head;
99 if(task) {
100 This->task_queue_head = task->next;
101 if(!This->task_queue_head)
102 This->task_queue_tail = NULL;
103 }
104
105 LeaveCriticalSection(&This->section);
106
107 if(!task)
108 break;
109
110 This->continue_call++;
111 task->proc(This, task);
112 This->continue_call--;
113 }
114
115 IInternetProtocol_Release(PROTOCOL(This));
116 return 0;
117 }
118 case WM_MK_RELEASE: {
119 tls_data_t *data = get_tls_data();
120
121 if(!--data->notif_hwnd_cnt) {
122 DestroyWindow(hwnd);
123 data->notif_hwnd = NULL;
124 }
125 }
126 }
127
128 return DefWindowProcW(hwnd, msg, wParam, lParam);
129 }
130
131 HWND get_notif_hwnd(void)
132 {
133 static ATOM wnd_class = 0;
134 tls_data_t *tls_data;
135
136 static const WCHAR wszURLMonikerNotificationWindow[] =
137 {'U','R','L',' ','M','o','n','i','k','e','r',' ',
138 'N','o','t','i','f','i','c','a','t','i','o','n',' ','W','i','n','d','o','w',0};
139
140 tls_data = get_tls_data();
141 if(!tls_data)
142 return NULL;
143
144 if(tls_data->notif_hwnd_cnt) {
145 tls_data->notif_hwnd_cnt++;
146 return tls_data->notif_hwnd;
147 }
148
149 if(!wnd_class) {
150 static WNDCLASSEXW wndclass = {
151 sizeof(wndclass), 0,
152 notif_wnd_proc, 0, 0,
153 NULL, NULL, NULL, NULL, NULL,
154 wszURLMonikerNotificationWindow,
155 NULL
156 };
157
158 wndclass.hInstance = hProxyDll;
159
160 wnd_class = RegisterClassExW(&wndclass);
161 if (!wnd_class && GetLastError() == ERROR_CLASS_ALREADY_EXISTS)
162 wnd_class = 1;
163 }
164
165 tls_data->notif_hwnd = CreateWindowExW(0, wszURLMonikerNotificationWindow,
166 wszURLMonikerNotificationWindow, 0, 0, 0, 0, 0, HWND_MESSAGE,
167 NULL, hProxyDll, NULL);
168 if(tls_data->notif_hwnd)
169 tls_data->notif_hwnd_cnt++;
170
171 TRACE("hwnd = %p\n", tls_data->notif_hwnd);
172
173 return tls_data->notif_hwnd;
174 }
175
176 void release_notif_hwnd(HWND hwnd)
177 {
178 tls_data_t *data = get_tls_data();
179
180 if(!data)
181 return;
182
183 if(data->notif_hwnd != hwnd) {
184 PostMessageW(data->notif_hwnd, WM_MK_RELEASE, 0, 0);
185 return;
186 }
187
188 if(!--data->notif_hwnd_cnt) {
189 DestroyWindow(data->notif_hwnd);
190 data->notif_hwnd = NULL;
191 }
192 }
193
194 static void push_task(BindProtocol *This, task_header_t *task, task_proc_t proc)
195 {
196 BOOL do_post = FALSE;
197
198 task->proc = proc;
199 task->next = NULL;
200
201 EnterCriticalSection(&This->section);
202
203 if(This->task_queue_tail) {
204 This->task_queue_tail->next = task;
205 This->task_queue_tail = task;
206 }else {
207 This->task_queue_tail = This->task_queue_head = task;
208 do_post = !This->continue_call;
209 }
210
211 LeaveCriticalSection(&This->section);
212
213 if(do_post) {
214 IInternetProtocol_AddRef(PROTOCOL(This));
215 PostMessageW(This->notif_hwnd, WM_MK_CONTINUE, 0, (LPARAM)This);
216 }
217 }
218
219 static inline BOOL do_direct_notif(BindProtocol *This)
220 {
221 return !(This->pi & PI_APARTMENTTHREADED) || (This->apartment_thread == GetCurrentThreadId() && !This->continue_call);
222 }
223
224 static HRESULT handle_mime_filter(BindProtocol *This, IInternetProtocol *mime_filter, LPCWSTR mime)
225 {
226 PROTOCOLFILTERDATA filter_data = { sizeof(PROTOCOLFILTERDATA), NULL, NULL, NULL, 0 };
227 IInternetProtocolSink *protocol_sink, *old_sink;
228 ProtocolProxy *filter_proxy;
229 HRESULT hres;
230
231 hres = IInternetProtocol_QueryInterface(mime_filter, &IID_IInternetProtocolSink, (void**)&protocol_sink);
232 if(FAILED(hres))
233 return hres;
234
235 hres = create_protocol_proxy(PROTOCOLHANDLER(This), This->protocol_sink, &filter_proxy);
236 if(FAILED(hres)) {
237 IInternetProtocolSink_Release(protocol_sink);
238 return hres;
239 }
240
241 old_sink = This->protocol_sink;
242 This->protocol_sink = protocol_sink;
243 This->filter_proxy = filter_proxy;
244
245 IInternetProtocol_AddRef(mime_filter);
246 This->protocol_handler = mime_filter;
247
248 filter_data.pProtocol = PROTOCOL(filter_proxy);
249 hres = IInternetProtocol_Start(mime_filter, mime, PROTSINK(filter_proxy), BINDINFO(This),
250 PI_FILTER_MODE|PI_FORCE_ASYNC, (HANDLE_PTR)&filter_data);
251 if(FAILED(hres)) {
252 IInternetProtocolSink_Release(old_sink);
253 return hres;
254 }
255
256 IInternetProtocolSink_ReportProgress(old_sink, BINDSTATUS_LOADINGMIMEHANDLER, NULL);
257 IInternetProtocolSink_Release(old_sink);
258
259 This->pi &= ~PI_MIMEVERIFICATION; /* FIXME: more tests */
260 return S_OK;
261 }
262
263 static void mime_available(BindProtocol *This, LPCWSTR mime, BOOL verified)
264 {
265 IInternetProtocol *mime_filter;
266 HRESULT hres;
267
268 heap_free(This->mime);
269 This->mime = NULL;
270
271 mime_filter = get_mime_filter(mime);
272 if(mime_filter) {
273 TRACE("Got mime filter for %s\n", debugstr_w(mime));
274
275 hres = handle_mime_filter(This, mime_filter, mime);
276 IInternetProtocol_Release(mime_filter);
277 if(FAILED(hres))
278 FIXME("MIME filter failed: %08x\n", hres);
279 }else {
280 This->mime = heap_strdupW(mime);
281
282 if(verified || !(This->pi & PI_MIMEVERIFICATION)) {
283 This->reported_mime = TRUE;
284
285 if(This->protocol_sink)
286 IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, mime);
287 }
288 }
289 }
290
291 #define PROTOCOL_THIS(iface) DEFINE_THIS(BindProtocol, IInternetProtocol, iface)
292
293 static HRESULT WINAPI BindProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
294 {
295 BindProtocol *This = PROTOCOL_THIS(iface);
296
297 *ppv = NULL;
298 if(IsEqualGUID(&IID_IUnknown, riid)) {
299 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
300 *ppv = PROTOCOL(This);
301 }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
302 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
303 *ppv = PROTOCOL(This);
304 }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
305 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
306 *ppv = PROTOCOL(This);
307 }else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) {
308 TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This, ppv);
309 *ppv = BINDINFO(This);
310 }else if(IsEqualGUID(&IID_IInternetPriority, riid)) {
311 TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv);
312 *ppv = PRIORITY(This);
313 }else if(IsEqualGUID(&IID_IAuthenticate, riid)) {
314 FIXME("(%p)->(IID_IAuthenticate %p)\n", This, ppv);
315 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
316 TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
317 *ppv = SERVPROV(This);
318 }else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
319 TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
320 *ppv = PROTSINK(This);
321 }else if(IsEqualGUID(&IID_IWinInetInfo, riid)) {
322 TRACE("(%p)->(IID_IWinInetInfo %p)\n", This, ppv);
323
324 if(This->protocol) {
325 IWinInetInfo *inet_info;
326 HRESULT hres;
327
328 hres = IInternetProtocol_QueryInterface(This->protocol, &IID_IWinInetInfo, (void**)&inet_info);
329 if(SUCCEEDED(hres)) {
330 *ppv = HTTPINFO(This);
331 IWinInetInfo_Release(inet_info);
332 }
333 }
334 }else if(IsEqualGUID(&IID_IWinInetHttpInfo, riid)) {
335 TRACE("(%p)->(IID_IWinInetHttpInfo %p)\n", This, ppv);
336
337 if(This->protocol) {
338 IWinInetHttpInfo *http_info;
339 HRESULT hres;
340
341 hres = IInternetProtocol_QueryInterface(This->protocol, &IID_IWinInetHttpInfo, (void**)&http_info);
342 if(SUCCEEDED(hres)) {
343 *ppv = HTTPINFO(This);
344 IWinInetHttpInfo_Release(http_info);
345 }
346 }
347 }else {
348 WARN("not supported interface %s\n", debugstr_guid(riid));
349 }
350
351 if(!*ppv)
352 return E_NOINTERFACE;
353
354 IUnknown_AddRef((IUnknown*)*ppv);
355 return S_OK;
356 }
357
358 static ULONG WINAPI BindProtocol_AddRef(IInternetProtocol *iface)
359 {
360 BindProtocol *This = PROTOCOL_THIS(iface);
361 LONG ref = InterlockedIncrement(&This->ref);
362 TRACE("(%p) ref=%d\n", This, ref);
363 return ref;
364 }
365
366 static ULONG WINAPI BindProtocol_Release(IInternetProtocol *iface)
367 {
368 BindProtocol *This = PROTOCOL_THIS(iface);
369 LONG ref = InterlockedDecrement(&This->ref);
370
371 TRACE("(%p) ref=%d\n", This, ref);
372
373 if(!ref) {
374 if(This->wininet_info)
375 IWinInetInfo_Release(This->wininet_info);
376 if(This->protocol)
377 IInternetProtocol_Release(This->protocol);
378 if(This->bind_info)
379 IInternetBindInfo_Release(This->bind_info);
380 if(This->protocol_handler && This->protocol_handler != PROTOCOLHANDLER(This))
381 IInternetProtocol_Release(This->protocol_handler);
382 if(This->filter_proxy)
383 IInternetProtocol_Release(PROTOCOL(This->filter_proxy));
384
385 set_binding_sink(PROTOCOL(This), NULL);
386
387 if(This->notif_hwnd)
388 release_notif_hwnd(This->notif_hwnd);
389 DeleteCriticalSection(&This->section);
390
391 heap_free(This->mime);
392 heap_free(This->url);
393 heap_free(This);
394
395 URLMON_UnlockModule();
396 }
397
398 return ref;
399 }
400
401 static HRESULT WINAPI BindProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
402 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
403 DWORD grfPI, HANDLE_PTR dwReserved)
404 {
405 BindProtocol *This = PROTOCOL_THIS(iface);
406
407 TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
408 pOIBindInfo, grfPI, dwReserved);
409
410 return IInternetProtocol_Start(This->protocol_handler, szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved);
411 }
412
413 static HRESULT WINAPI BindProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
414 {
415 BindProtocol *This = PROTOCOL_THIS(iface);
416
417 TRACE("(%p)->(%p)\n", This, pProtocolData);
418
419 return IInternetProtocol_Continue(This->protocol_handler, pProtocolData);
420 }
421
422 static HRESULT WINAPI BindProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
423 DWORD dwOptions)
424 {
425 BindProtocol *This = PROTOCOL_THIS(iface);
426 FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
427 return E_NOTIMPL;
428 }
429
430 static HRESULT WINAPI BindProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
431 {
432 BindProtocol *This = PROTOCOL_THIS(iface);
433
434 TRACE("(%p)->(%08x)\n", This, dwOptions);
435
436 return IInternetProtocol_Terminate(This->protocol_handler, dwOptions);
437 }
438
439 static HRESULT WINAPI BindProtocol_Suspend(IInternetProtocol *iface)
440 {
441 BindProtocol *This = PROTOCOL_THIS(iface);
442 FIXME("(%p)\n", This);
443 return E_NOTIMPL;
444 }
445
446 static HRESULT WINAPI BindProtocol_Resume(IInternetProtocol *iface)
447 {
448 BindProtocol *This = PROTOCOL_THIS(iface);
449 FIXME("(%p)\n", This);
450 return E_NOTIMPL;
451 }
452
453 static HRESULT WINAPI BindProtocol_Read(IInternetProtocol *iface, void *pv,
454 ULONG cb, ULONG *pcbRead)
455 {
456 BindProtocol *This = PROTOCOL_THIS(iface);
457
458 TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
459
460 if(pcbRead)
461 *pcbRead = 0;
462 return IInternetProtocol_Read(This->protocol_handler, pv, cb, pcbRead);
463 }
464
465 static HRESULT WINAPI BindProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
466 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
467 {
468 BindProtocol *This = PROTOCOL_THIS(iface);
469 FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
470 return E_NOTIMPL;
471 }
472
473 static HRESULT WINAPI BindProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
474 {
475 BindProtocol *This = PROTOCOL_THIS(iface);
476
477 TRACE("(%p)->(%08x)\n", This, dwOptions);
478
479 return IInternetProtocol_LockRequest(This->protocol_handler, dwOptions);
480 }
481
482 static HRESULT WINAPI BindProtocol_UnlockRequest(IInternetProtocol *iface)
483 {
484 BindProtocol *This = PROTOCOL_THIS(iface);
485
486 TRACE("(%p)\n", This);
487
488 return IInternetProtocol_UnlockRequest(This->protocol_handler);
489 }
490
491 void set_binding_sink(IInternetProtocol *bind_protocol, IInternetProtocolSink *sink)
492 {
493 BindProtocol *This = PROTOCOL_THIS(bind_protocol);
494 IInternetProtocolSink *prev_sink;
495 IServiceProvider *service_provider = NULL;
496
497 if(sink)
498 IInternetProtocolSink_AddRef(sink);
499 prev_sink = InterlockedExchangePointer((void**)&This->protocol_sink, sink);
500 if(prev_sink)
501 IInternetProtocolSink_Release(prev_sink);
502
503 if(sink)
504 IInternetProtocolSink_QueryInterface(sink, &IID_IServiceProvider, (void**)&service_provider);
505 service_provider = InterlockedExchangePointer((void**)&This->service_provider, service_provider);
506 if(service_provider)
507 IServiceProvider_Release(service_provider);
508 }
509
510 IWinInetInfo *get_wininet_info(IInternetProtocol *bind_protocol)
511 {
512 BindProtocol *This = PROTOCOL_THIS(bind_protocol);
513
514 return This->wininet_info;
515 }
516
517 #undef PROTOCOL_THIS
518
519 static const IInternetProtocolVtbl BindProtocolVtbl = {
520 BindProtocol_QueryInterface,
521 BindProtocol_AddRef,
522 BindProtocol_Release,
523 BindProtocol_Start,
524 BindProtocol_Continue,
525 BindProtocol_Abort,
526 BindProtocol_Terminate,
527 BindProtocol_Suspend,
528 BindProtocol_Resume,
529 BindProtocol_Read,
530 BindProtocol_Seek,
531 BindProtocol_LockRequest,
532 BindProtocol_UnlockRequest
533 };
534
535 #define PROTOCOLHANDLER_THIS(iface) DEFINE_THIS(BindProtocol, IInternetProtocolHandler, iface)
536
537 static HRESULT WINAPI ProtocolHandler_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
538 {
539 ERR("should not be called\n");
540 return E_NOINTERFACE;
541 }
542
543 static ULONG WINAPI ProtocolHandler_AddRef(IInternetProtocol *iface)
544 {
545 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
546 return IInternetProtocol_AddRef(PROTOCOL(This));
547 }
548
549 static ULONG WINAPI ProtocolHandler_Release(IInternetProtocol *iface)
550 {
551 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
552 return IInternetProtocol_Release(PROTOCOL(This));
553 }
554
555 static HRESULT WINAPI ProtocolHandler_Start(IInternetProtocol *iface, LPCWSTR szUrl,
556 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
557 DWORD grfPI, HANDLE_PTR dwReserved)
558 {
559 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
560 IInternetProtocol *protocol = NULL;
561 IInternetPriority *priority;
562 IServiceProvider *service_provider;
563 BOOL urlmon_protocol = FALSE;
564 CLSID clsid = IID_NULL;
565 LPOLESTR clsid_str;
566 HRESULT hres;
567
568 TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
569 pOIBindInfo, grfPI, dwReserved);
570
571 if(!szUrl || !pOIProtSink || !pOIBindInfo)
572 return E_INVALIDARG;
573
574 This->pi = grfPI;
575 This->url = heap_strdupW(szUrl);
576
577 hres = IInternetProtocolSink_QueryInterface(pOIProtSink, &IID_IServiceProvider,
578 (void**)&service_provider);
579 if(SUCCEEDED(hres)) {
580 /* FIXME: What's protocol CLSID here? */
581 IServiceProvider_QueryService(service_provider, &IID_IInternetProtocol,
582 &IID_IInternetProtocol, (void**)&protocol);
583 IServiceProvider_Release(service_provider);
584 }
585
586 if(!protocol) {
587 IClassFactory *cf;
588 IUnknown *unk;
589
590 hres = get_protocol_handler(szUrl, &clsid, &urlmon_protocol, &cf);
591 if(FAILED(hres))
592 return hres;
593
594 if(This->from_urlmon) {
595 hres = IClassFactory_CreateInstance(cf, NULL, &IID_IInternetProtocol, (void**)&protocol);
596 IClassFactory_Release(cf);
597 if(FAILED(hres))
598 return hres;
599 }else {
600 hres = IClassFactory_CreateInstance(cf, (IUnknown*)BINDINFO(This),
601 &IID_IUnknown, (void**)&unk);
602 IClassFactory_Release(cf);
603 if(FAILED(hres))
604 return hres;
605
606 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocol, (void**)&protocol);
607 IUnknown_Release(unk);
608 if(FAILED(hres))
609 return hres;
610 }
611 }
612
613 StringFromCLSID(&clsid, &clsid_str);
614 IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_PROTOCOLCLASSID, clsid_str);
615 CoTaskMemFree(clsid_str);
616
617 This->protocol = protocol;
618
619 if(urlmon_protocol)
620 IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&This->wininet_info);
621
622 IInternetBindInfo_AddRef(pOIBindInfo);
623 This->bind_info = pOIBindInfo;
624
625 set_binding_sink(PROTOCOL(This), pOIProtSink);
626
627 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
628 if(SUCCEEDED(hres)) {
629 IInternetPriority_SetPriority(priority, This->priority);
630 IInternetPriority_Release(priority);
631 }
632
633 return IInternetProtocol_Start(protocol, szUrl, PROTSINK(This), BINDINFO(This), 0, 0);
634 }
635
636 static HRESULT WINAPI ProtocolHandler_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
637 {
638 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
639 HRESULT hres;
640
641 TRACE("(%p)->(%p)\n", This, pProtocolData);
642
643 hres = IInternetProtocol_Continue(This->protocol, pProtocolData);
644
645 heap_free(pProtocolData);
646 return hres;
647 }
648
649 static HRESULT WINAPI ProtocolHandler_Abort(IInternetProtocol *iface, HRESULT hrReason,
650 DWORD dwOptions)
651 {
652 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
653 FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
654 return E_NOTIMPL;
655 }
656
657 static HRESULT WINAPI ProtocolHandler_Terminate(IInternetProtocol *iface, DWORD dwOptions)
658 {
659 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
660
661 TRACE("(%p)->(%08x)\n", This, dwOptions);
662
663 if(!This->reported_result)
664 return E_FAIL;
665
666 IInternetProtocol_Terminate(This->protocol, 0);
667
668 if(This->filter_proxy) {
669 IInternetProtocol_Release(PROTOCOL(This->filter_proxy));
670 This->filter_proxy = NULL;
671 }
672
673 set_binding_sink(PROTOCOL(This), NULL);
674
675 if(This->bind_info) {
676 IInternetBindInfo_Release(This->bind_info);
677 This->bind_info = NULL;
678 }
679
680 return S_OK;
681 }
682
683 static HRESULT WINAPI ProtocolHandler_Suspend(IInternetProtocol *iface)
684 {
685 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
686 FIXME("(%p)\n", This);
687 return E_NOTIMPL;
688 }
689
690 static HRESULT WINAPI ProtocolHandler_Resume(IInternetProtocol *iface)
691 {
692 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
693 FIXME("(%p)\n", This);
694 return E_NOTIMPL;
695 }
696
697 static HRESULT WINAPI ProtocolHandler_Read(IInternetProtocol *iface, void *pv,
698 ULONG cb, ULONG *pcbRead)
699 {
700 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
701 ULONG read = 0;
702 HRESULT hres = S_OK;
703
704 TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
705
706 if(This->buf_size) {
707 read = min(cb, This->buf_size);
708 memcpy(pv, This->buf, read);
709
710 if(read == This->buf_size) {
711 heap_free(This->buf);
712 This->buf = NULL;
713 }else {
714 memmove(This->buf, This->buf+cb, This->buf_size-cb);
715 }
716
717 This->buf_size -= read;
718 }
719
720 if(read < cb) {
721 ULONG cread = 0;
722
723 hres = IInternetProtocol_Read(This->protocol, (BYTE*)pv+read, cb-read, &cread);
724 read += cread;
725 }
726
727 *pcbRead = read;
728 return hres;
729 }
730
731 static HRESULT WINAPI ProtocolHandler_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
732 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
733 {
734 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
735 FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
736 return E_NOTIMPL;
737 }
738
739 static HRESULT WINAPI ProtocolHandler_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
740 {
741 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
742
743 TRACE("(%p)->(%08x)\n", This, dwOptions);
744
745 return IInternetProtocol_LockRequest(This->protocol, dwOptions);
746 }
747
748 static HRESULT WINAPI ProtocolHandler_UnlockRequest(IInternetProtocol *iface)
749 {
750 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
751
752 TRACE("(%p)\n", This);
753
754 return IInternetProtocol_UnlockRequest(This->protocol);
755 }
756
757 #undef PROTOCOL_THIS
758
759 static const IInternetProtocolVtbl InternetProtocolHandlerVtbl = {
760 ProtocolHandler_QueryInterface,
761 ProtocolHandler_AddRef,
762 ProtocolHandler_Release,
763 ProtocolHandler_Start,
764 ProtocolHandler_Continue,
765 ProtocolHandler_Abort,
766 ProtocolHandler_Terminate,
767 ProtocolHandler_Suspend,
768 ProtocolHandler_Resume,
769 ProtocolHandler_Read,
770 ProtocolHandler_Seek,
771 ProtocolHandler_LockRequest,
772 ProtocolHandler_UnlockRequest
773 };
774
775 #define BINDINFO_THIS(iface) DEFINE_THIS(BindProtocol, InternetBindInfo, iface)
776
777 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface,
778 REFIID riid, void **ppv)
779 {
780 BindProtocol *This = BINDINFO_THIS(iface);
781 return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
782 }
783
784 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
785 {
786 BindProtocol *This = BINDINFO_THIS(iface);
787 return IBinding_AddRef(PROTOCOL(This));
788 }
789
790 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
791 {
792 BindProtocol *This = BINDINFO_THIS(iface);
793 return IBinding_Release(PROTOCOL(This));
794 }
795
796 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface,
797 DWORD *grfBINDF, BINDINFO *pbindinfo)
798 {
799 BindProtocol *This = BINDINFO_THIS(iface);
800 HRESULT hres;
801
802 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
803
804 hres = IInternetBindInfo_GetBindInfo(This->bind_info, grfBINDF, pbindinfo);
805 if(FAILED(hres)) {
806 WARN("GetBindInfo failed: %08x\n", hres);
807 return hres;
808 }
809
810 *grfBINDF |= BINDF_FROMURLMON;
811 return hres;
812 }
813
814 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface,
815 ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
816 {
817 BindProtocol *This = BINDINFO_THIS(iface);
818
819 TRACE("(%p)->(%d %p %d %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched);
820
821 return IInternetBindInfo_GetBindString(This->bind_info, ulStringType, ppwzStr, cEl, pcElFetched);
822 }
823
824 #undef BINDFO_THIS
825
826 static const IInternetBindInfoVtbl InternetBindInfoVtbl = {
827 BindInfo_QueryInterface,
828 BindInfo_AddRef,
829 BindInfo_Release,
830 BindInfo_GetBindInfo,
831 BindInfo_GetBindString
832 };
833
834 #define PRIORITY_THIS(iface) DEFINE_THIS(BindProtocol, InternetPriority, iface)
835
836 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
837 REFIID riid, void **ppv)
838 {
839 BindProtocol *This = PRIORITY_THIS(iface);
840 return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
841 }
842
843 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
844 {
845 BindProtocol *This = PRIORITY_THIS(iface);
846 return IInternetProtocol_AddRef(PROTOCOL(This));
847 }
848
849 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
850 {
851 BindProtocol *This = PRIORITY_THIS(iface);
852 return IInternetProtocol_Release(PROTOCOL(This));
853 }
854
855 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
856 {
857 BindProtocol *This = PRIORITY_THIS(iface);
858
859 TRACE("(%p)->(%d)\n", This, nPriority);
860
861 This->priority = nPriority;
862 return S_OK;
863 }
864
865 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
866 {
867 BindProtocol *This = PRIORITY_THIS(iface);
868
869 TRACE("(%p)->(%p)\n", This, pnPriority);
870
871 *pnPriority = This->priority;
872 return S_OK;
873 }
874
875 #undef PRIORITY_THIS
876
877 static const IInternetPriorityVtbl InternetPriorityVtbl = {
878 InternetPriority_QueryInterface,
879 InternetPriority_AddRef,
880 InternetPriority_Release,
881 InternetPriority_SetPriority,
882 InternetPriority_GetPriority
883
884 };
885
886 #define PROTSINK_THIS(iface) DEFINE_THIS(BindProtocol, IInternetProtocolSink, iface)
887
888 static HRESULT WINAPI BPInternetProtocolSink_QueryInterface(IInternetProtocolSink *iface,
889 REFIID riid, void **ppv)
890 {
891 BindProtocol *This = PROTSINK_THIS(iface);
892 return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
893 }
894
895 static ULONG WINAPI BPInternetProtocolSink_AddRef(IInternetProtocolSink *iface)
896 {
897 BindProtocol *This = PROTSINK_THIS(iface);
898 return IInternetProtocol_AddRef(PROTOCOL(This));
899 }
900
901 static ULONG WINAPI BPInternetProtocolSink_Release(IInternetProtocolSink *iface)
902 {
903 BindProtocol *This = PROTSINK_THIS(iface);
904 return IInternetProtocol_Release(PROTOCOL(This));
905 }
906
907 typedef struct {
908 task_header_t header;
909 PROTOCOLDATA *data;
910 } switch_task_t;
911
912 static void switch_proc(BindProtocol *bind, task_header_t *t)
913 {
914 switch_task_t *task = (switch_task_t*)t;
915
916 IInternetProtocol_Continue(bind->protocol_handler, task->data);
917
918 heap_free(task);
919 }
920
921 static HRESULT WINAPI BPInternetProtocolSink_Switch(IInternetProtocolSink *iface,
922 PROTOCOLDATA *pProtocolData)
923 {
924 BindProtocol *This = PROTSINK_THIS(iface);
925 PROTOCOLDATA *data;
926
927 TRACE("(%p)->(%p)\n", This, pProtocolData);
928
929 TRACE("flags %x state %x data %p cb %u\n", pProtocolData->grfFlags, pProtocolData->dwState,
930 pProtocolData->pData, pProtocolData->cbData);
931
932 data = heap_alloc(sizeof(PROTOCOLDATA));
933 if(!data)
934 return E_OUTOFMEMORY;
935 memcpy(data, pProtocolData, sizeof(PROTOCOLDATA));
936
937 if(!do_direct_notif(This)) {
938 switch_task_t *task;
939
940 task = heap_alloc(sizeof(switch_task_t));
941 if(!task)
942 return E_OUTOFMEMORY;
943
944 task->data = data;
945
946 push_task(This, &task->header, switch_proc);
947 return S_OK;
948 }
949
950 if(!This->protocol_sink) {
951 IInternetProtocol_Continue(This->protocol_handler, data);
952 return S_OK;
953 }
954
955 return IInternetProtocolSink_Switch(This->protocol_sink, data);
956 }
957
958 static void report_progress(BindProtocol *This, ULONG status_code, LPCWSTR status_text)
959 {
960 switch(status_code) {
961 case BINDSTATUS_FINDINGRESOURCE:
962 case BINDSTATUS_CONNECTING:
963 case BINDSTATUS_REDIRECTING:
964 case BINDSTATUS_BEGINDOWNLOADDATA:
965 case BINDSTATUS_SENDINGREQUEST:
966 case BINDSTATUS_CACHEFILENAMEAVAILABLE:
967 case BINDSTATUS_DIRECTBIND:
968 case BINDSTATUS_ACCEPTRANGES:
969 if(This->protocol_sink)
970 IInternetProtocolSink_ReportProgress(This->protocol_sink, status_code, status_text);
971 break;
972
973 case BINDSTATUS_MIMETYPEAVAILABLE:
974 mime_available(This, status_text, FALSE);
975 break;
976
977 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
978 mime_available(This, status_text, TRUE);
979 break;
980
981 default:
982 FIXME("unsupported ulStatusCode %u\n", status_code);
983 }
984 }
985
986 typedef struct {
987 task_header_t header;
988
989 ULONG status_code;
990 LPWSTR status_text;
991 } on_progress_task_t;
992
993 static void on_progress_proc(BindProtocol *This, task_header_t *t)
994 {
995 on_progress_task_t *task = (on_progress_task_t*)t;
996
997 report_progress(This, task->status_code, task->status_text);
998
999 heap_free(task->status_text);
1000 heap_free(task);
1001 }
1002
1003 static HRESULT WINAPI BPInternetProtocolSink_ReportProgress(IInternetProtocolSink *iface,
1004 ULONG ulStatusCode, LPCWSTR szStatusText)
1005 {
1006 BindProtocol *This = PROTSINK_THIS(iface);
1007
1008 TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
1009
1010 if(do_direct_notif(This)) {
1011 report_progress(This, ulStatusCode, szStatusText);
1012 }else {
1013 on_progress_task_t *task;
1014
1015 task = heap_alloc(sizeof(on_progress_task_t));
1016
1017 task->status_code = ulStatusCode;
1018 task->status_text = heap_strdupW(szStatusText);
1019
1020 push_task(This, &task->header, on_progress_proc);
1021 }
1022
1023 return S_OK;
1024 }
1025
1026 static HRESULT report_data(BindProtocol *This, DWORD bscf, ULONG progress, ULONG progress_max)
1027 {
1028 if(!This->protocol_sink)
1029 return S_OK;
1030
1031 if((This->pi & PI_MIMEVERIFICATION) && !This->reported_mime) {
1032 BYTE buf[BUFFER_SIZE];
1033 DWORD read = 0;
1034 LPWSTR mime;
1035 HRESULT hres;
1036
1037 do {
1038 read = 0;
1039 hres = IInternetProtocol_Read(This->protocol, buf,
1040 sizeof(buf)-This->buf_size, &read);
1041 if(FAILED(hres) && hres != E_PENDING)
1042 return hres;
1043
1044 if(!This->buf) {
1045 This->buf = heap_alloc(BUFFER_SIZE);
1046 if(!This->buf)
1047 return E_OUTOFMEMORY;
1048 }else if(read + This->buf_size > BUFFER_SIZE) {
1049 BYTE *tmp;
1050
1051 tmp = heap_realloc(This->buf, read+This->buf_size);
1052 if(!tmp)
1053 return E_OUTOFMEMORY;
1054 This->buf = tmp;
1055 }
1056
1057 memcpy(This->buf+This->buf_size, buf, read);
1058 This->buf_size += read;
1059 }while(This->buf_size < MIME_TEST_SIZE && hres == S_OK);
1060
1061 if(This->buf_size < MIME_TEST_SIZE && hres != S_FALSE)
1062 return S_OK;
1063
1064 bscf = BSCF_FIRSTDATANOTIFICATION;
1065 if(hres == S_FALSE)
1066 bscf |= BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE;
1067
1068 if(!This->reported_mime) {
1069 hres = FindMimeFromData(NULL, This->url, This->buf, min(This->buf_size, MIME_TEST_SIZE),
1070 This->mime, 0, &mime, 0);
1071 if(FAILED(hres))
1072 return hres;
1073
1074 mime_available(This, mime, TRUE);
1075 CoTaskMemFree(mime);
1076 }
1077 }
1078
1079 if(!This->protocol_sink)
1080 return S_OK;
1081
1082 return IInternetProtocolSink_ReportData(This->protocol_sink, bscf, progress, progress_max);
1083 }
1084
1085 typedef struct {
1086 task_header_t header;
1087 DWORD bscf;
1088 ULONG progress;
1089 ULONG progress_max;
1090 } report_data_task_t;
1091
1092 static void report_data_proc(BindProtocol *This, task_header_t *t)
1093 {
1094 report_data_task_t *task = (report_data_task_t*)t;
1095
1096 report_data(This, task->bscf, task->progress, task->progress_max);
1097 heap_free(task);
1098 }
1099
1100 static HRESULT WINAPI BPInternetProtocolSink_ReportData(IInternetProtocolSink *iface,
1101 DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax)
1102 {
1103 BindProtocol *This = PROTSINK_THIS(iface);
1104
1105 TRACE("(%p)->(%d %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
1106
1107 if(!This->protocol_sink)
1108 return S_OK;
1109
1110 if(!do_direct_notif(This)) {
1111 report_data_task_t *task;
1112
1113 task = heap_alloc(sizeof(report_data_task_t));
1114 if(!task)
1115 return E_OUTOFMEMORY;
1116
1117 task->bscf = grfBSCF;
1118 task->progress = ulProgress;
1119 task->progress_max = ulProgressMax;
1120
1121 push_task(This, &task->header, report_data_proc);
1122 return S_OK;
1123 }
1124
1125 return report_data(This, grfBSCF, ulProgress, ulProgressMax);
1126 }
1127
1128 typedef struct {
1129 task_header_t header;
1130
1131 HRESULT hres;
1132 DWORD err;
1133 LPWSTR str;
1134 } report_result_task_t;
1135
1136 static void report_result_proc(BindProtocol *This, task_header_t *t)
1137 {
1138 report_result_task_t *task = (report_result_task_t*)t;
1139
1140 if(This->protocol_sink)
1141 IInternetProtocolSink_ReportResult(This->protocol_sink, task->hres, task->err, task->str);
1142
1143 heap_free(task->str);
1144 heap_free(task);
1145 }
1146
1147 static HRESULT WINAPI BPInternetProtocolSink_ReportResult(IInternetProtocolSink *iface,
1148 HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
1149 {
1150 BindProtocol *This = PROTSINK_THIS(iface);
1151
1152 TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
1153
1154 if(!This->protocol_sink)
1155 return E_FAIL;
1156
1157 This->reported_result = TRUE;
1158
1159 if(!do_direct_notif(This)) {
1160 report_result_task_t *task;
1161
1162 task = heap_alloc(sizeof(report_result_task_t));
1163 if(!task)
1164 return E_OUTOFMEMORY;
1165
1166 task->hres = hrResult;
1167 task->err = dwError;
1168 task->str = heap_strdupW(szResult);
1169
1170 push_task(This, &task->header, report_result_proc);
1171 return S_OK;
1172 }
1173
1174 return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
1175 }
1176
1177 #undef PROTSINK_THIS
1178
1179 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = {
1180 BPInternetProtocolSink_QueryInterface,
1181 BPInternetProtocolSink_AddRef,
1182 BPInternetProtocolSink_Release,
1183 BPInternetProtocolSink_Switch,
1184 BPInternetProtocolSink_ReportProgress,
1185 BPInternetProtocolSink_ReportData,
1186 BPInternetProtocolSink_ReportResult
1187 };
1188
1189 #define INETINFO_THIS(iface) DEFINE_THIS(BindProtocol, IWinInetHttpInfo, iface)
1190
1191 static HRESULT WINAPI WinInetHttpInfo_QueryInterface(IWinInetHttpInfo *iface, REFIID riid, void **ppv)
1192 {
1193 BindProtocol *This = INETINFO_THIS(iface);
1194 return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
1195 }
1196
1197 static ULONG WINAPI WinInetHttpInfo_AddRef(IWinInetHttpInfo *iface)
1198 {
1199 BindProtocol *This = INETINFO_THIS(iface);
1200 return IInternetProtocol_AddRef(PROTOCOL(This));
1201 }
1202
1203 static ULONG WINAPI WinInetHttpInfo_Release(IWinInetHttpInfo *iface)
1204 {
1205 BindProtocol *This = INETINFO_THIS(iface);
1206 return IInternetProtocol_Release(PROTOCOL(This));
1207 }
1208
1209 static HRESULT WINAPI WinInetHttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD dwOption,
1210 void *pBuffer, DWORD *pcbBuffer)
1211 {
1212 BindProtocol *This = INETINFO_THIS(iface);
1213 FIXME("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer);
1214 return E_NOTIMPL;
1215 }
1216
1217 static HRESULT WINAPI WinInetHttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption,
1218 void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved)
1219 {
1220 BindProtocol *This = INETINFO_THIS(iface);
1221 FIXME("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved);
1222 return E_NOTIMPL;
1223 }
1224
1225 #undef INETINFO_THIS
1226
1227 static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = {
1228 WinInetHttpInfo_QueryInterface,
1229 WinInetHttpInfo_AddRef,
1230 WinInetHttpInfo_Release,
1231 WinInetHttpInfo_QueryOption,
1232 WinInetHttpInfo_QueryInfo
1233 };
1234
1235 #define SERVPROV_THIS(iface) DEFINE_THIS(BindProtocol, ServiceProvider, iface)
1236
1237 static HRESULT WINAPI BPServiceProvider_QueryInterface(IServiceProvider *iface,
1238 REFIID riid, void **ppv)
1239 {
1240 BindProtocol *This = SERVPROV_THIS(iface);
1241 return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
1242 }
1243
1244 static ULONG WINAPI BPServiceProvider_AddRef(IServiceProvider *iface)
1245 {
1246 BindProtocol *This = SERVPROV_THIS(iface);
1247 return IInternetProtocol_AddRef(PROTOCOL(This));
1248 }
1249
1250 static ULONG WINAPI BPServiceProvider_Release(IServiceProvider *iface)
1251 {
1252 BindProtocol *This = SERVPROV_THIS(iface);
1253 return IInternetProtocol_Release(PROTOCOL(This));
1254 }
1255
1256 static HRESULT WINAPI BPServiceProvider_QueryService(IServiceProvider *iface,
1257 REFGUID guidService, REFIID riid, void **ppv)
1258 {
1259 BindProtocol *This = SERVPROV_THIS(iface);
1260
1261 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
1262
1263 if(!This->service_provider)
1264 return E_NOINTERFACE;
1265
1266 return IServiceProvider_QueryService(This->service_provider, guidService, riid, ppv);
1267 }
1268
1269 #undef SERVPROV_THIS
1270
1271 static const IServiceProviderVtbl ServiceProviderVtbl = {
1272 BPServiceProvider_QueryInterface,
1273 BPServiceProvider_AddRef,
1274 BPServiceProvider_Release,
1275 BPServiceProvider_QueryService
1276 };
1277
1278 HRESULT create_binding_protocol(LPCWSTR url, BOOL from_urlmon, IInternetProtocol **protocol)
1279 {
1280 BindProtocol *ret = heap_alloc_zero(sizeof(BindProtocol));
1281
1282 ret->lpIInternetProtocolVtbl = &BindProtocolVtbl;
1283 ret->lpInternetBindInfoVtbl = &InternetBindInfoVtbl;
1284 ret->lpInternetPriorityVtbl = &InternetPriorityVtbl;
1285 ret->lpServiceProviderVtbl = &ServiceProviderVtbl;
1286 ret->lpIInternetProtocolSinkVtbl = &InternetProtocolSinkVtbl;
1287 ret->lpIInternetProtocolHandlerVtbl = &InternetProtocolHandlerVtbl;
1288 ret->lpIWinInetHttpInfoVtbl = &WinInetHttpInfoVtbl;
1289
1290 ret->ref = 1;
1291 ret->from_urlmon = from_urlmon;
1292 ret->apartment_thread = GetCurrentThreadId();
1293 ret->notif_hwnd = get_notif_hwnd();
1294 ret->protocol_handler = PROTOCOLHANDLER(ret);
1295 InitializeCriticalSection(&ret->section);
1296
1297 URLMON_LockModule();
1298
1299 *protocol = PROTOCOL(ret);
1300 return S_OK;
1301 }