urlmon: Don't forward Start call to protocol handler in BindProtocol.
[wine/wine-gecko.git] / dlls / urlmon / bindprot.c
blob956b6a53491d824fa06f88a79ee7666f524fe664
1 /*
2 * Copyright 2007-2009 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 BindProtocol BindProtocol;
26 struct _task_header_t;
28 typedef void (*task_proc_t)(BindProtocol*,struct _task_header_t*);
30 typedef struct _task_header_t {
31 task_proc_t proc;
32 struct _task_header_t *next;
33 } task_header_t;
35 struct BindProtocol {
36 const IInternetProtocolExVtbl *lpIInternetProtocolExVtbl;
37 const IInternetBindInfoVtbl *lpInternetBindInfoVtbl;
38 const IInternetPriorityVtbl *lpInternetPriorityVtbl;
39 const IServiceProviderVtbl *lpServiceProviderVtbl;
40 const IInternetProtocolSinkVtbl *lpIInternetProtocolSinkVtbl;
41 const IWinInetHttpInfoVtbl *lpIWinInetHttpInfoVtbl;
43 const IInternetProtocolExVtbl *lpIInternetProtocolHandlerVtbl;
45 LONG ref;
47 IInternetProtocol *protocol;
48 IInternetProtocol *protocol_handler;
49 IInternetBindInfo *bind_info;
50 IInternetProtocolSink *protocol_sink;
51 IServiceProvider *service_provider;
52 IWinInetInfo *wininet_info;
54 LONG priority;
56 BOOL reported_result;
57 BOOL reported_mime;
58 BOOL from_urlmon;
59 DWORD pi;
61 DWORD apartment_thread;
62 HWND notif_hwnd;
63 DWORD continue_call;
65 CRITICAL_SECTION section;
66 task_header_t *task_queue_head, *task_queue_tail;
68 BYTE *buf;
69 DWORD buf_size;
70 LPWSTR mime;
71 IUri *uri;
72 ProtocolProxy *filter_proxy;
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 #define PROTOCOLEX(x) ((IInternetProtocolEx*) &(x)->lpIInternetProtocolExVtbl)
81 #define PROTOCOLHANDLER(x) ((IInternetProtocolEx*) &(x)->lpIInternetProtocolHandlerVtbl)
83 #define BUFFER_SIZE 2048
84 #define MIME_TEST_SIZE 255
86 #define WM_MK_CONTINUE (WM_USER+101)
87 #define WM_MK_RELEASE (WM_USER+102)
89 static LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
91 switch(msg) {
92 case WM_MK_CONTINUE: {
93 BindProtocol *This = (BindProtocol*)lParam;
94 task_header_t *task;
96 while(1) {
97 EnterCriticalSection(&This->section);
99 task = This->task_queue_head;
100 if(task) {
101 This->task_queue_head = task->next;
102 if(!This->task_queue_head)
103 This->task_queue_tail = NULL;
106 LeaveCriticalSection(&This->section);
108 if(!task)
109 break;
111 This->continue_call++;
112 task->proc(This, task);
113 This->continue_call--;
116 IInternetProtocolEx_Release(PROTOCOLEX(This));
117 return 0;
119 case WM_MK_RELEASE: {
120 tls_data_t *data = get_tls_data();
122 if(!--data->notif_hwnd_cnt) {
123 DestroyWindow(hwnd);
124 data->notif_hwnd = NULL;
129 return DefWindowProcW(hwnd, msg, wParam, lParam);
132 HWND get_notif_hwnd(void)
134 static ATOM wnd_class = 0;
135 tls_data_t *tls_data;
137 static const WCHAR wszURLMonikerNotificationWindow[] =
138 {'U','R','L',' ','M','o','n','i','k','e','r',' ',
139 'N','o','t','i','f','i','c','a','t','i','o','n',' ','W','i','n','d','o','w',0};
141 tls_data = get_tls_data();
142 if(!tls_data)
143 return NULL;
145 if(tls_data->notif_hwnd_cnt) {
146 tls_data->notif_hwnd_cnt++;
147 return tls_data->notif_hwnd;
150 if(!wnd_class) {
151 static WNDCLASSEXW wndclass = {
152 sizeof(wndclass), 0,
153 notif_wnd_proc, 0, 0,
154 NULL, NULL, NULL, NULL, NULL,
155 wszURLMonikerNotificationWindow,
156 NULL
159 wndclass.hInstance = hProxyDll;
161 wnd_class = RegisterClassExW(&wndclass);
162 if (!wnd_class && GetLastError() == ERROR_CLASS_ALREADY_EXISTS)
163 wnd_class = 1;
166 tls_data->notif_hwnd = CreateWindowExW(0, wszURLMonikerNotificationWindow,
167 wszURLMonikerNotificationWindow, 0, 0, 0, 0, 0, HWND_MESSAGE,
168 NULL, hProxyDll, NULL);
169 if(tls_data->notif_hwnd)
170 tls_data->notif_hwnd_cnt++;
172 TRACE("hwnd = %p\n", tls_data->notif_hwnd);
174 return tls_data->notif_hwnd;
177 void release_notif_hwnd(HWND hwnd)
179 tls_data_t *data = get_tls_data();
181 if(!data)
182 return;
184 if(data->notif_hwnd != hwnd) {
185 PostMessageW(data->notif_hwnd, WM_MK_RELEASE, 0, 0);
186 return;
189 if(!--data->notif_hwnd_cnt) {
190 DestroyWindow(data->notif_hwnd);
191 data->notif_hwnd = NULL;
195 static void push_task(BindProtocol *This, task_header_t *task, task_proc_t proc)
197 BOOL do_post = FALSE;
199 task->proc = proc;
200 task->next = NULL;
202 EnterCriticalSection(&This->section);
204 if(This->task_queue_tail) {
205 This->task_queue_tail->next = task;
206 This->task_queue_tail = task;
207 }else {
208 This->task_queue_tail = This->task_queue_head = task;
209 do_post = !This->continue_call;
212 LeaveCriticalSection(&This->section);
214 if(do_post) {
215 IInternetProtocolEx_AddRef(PROTOCOLEX(This));
216 PostMessageW(This->notif_hwnd, WM_MK_CONTINUE, 0, (LPARAM)This);
220 static inline BOOL do_direct_notif(BindProtocol *This)
222 return !(This->pi & PI_APARTMENTTHREADED) || (This->apartment_thread == GetCurrentThreadId() && !This->continue_call);
225 static HRESULT handle_mime_filter(BindProtocol *This, IInternetProtocol *mime_filter, LPCWSTR mime)
227 PROTOCOLFILTERDATA filter_data = { sizeof(PROTOCOLFILTERDATA), NULL, NULL, NULL, 0 };
228 IInternetProtocolSink *protocol_sink, *old_sink;
229 ProtocolProxy *filter_proxy;
230 HRESULT hres;
232 hres = IInternetProtocol_QueryInterface(mime_filter, &IID_IInternetProtocolSink, (void**)&protocol_sink);
233 if(FAILED(hres))
234 return hres;
236 hres = create_protocol_proxy((IInternetProtocol*)PROTOCOLHANDLER(This), This->protocol_sink, &filter_proxy);
237 if(FAILED(hres)) {
238 IInternetProtocolSink_Release(protocol_sink);
239 return hres;
242 old_sink = This->protocol_sink;
243 This->protocol_sink = protocol_sink;
244 This->filter_proxy = filter_proxy;
246 IInternetProtocol_AddRef(mime_filter);
247 This->protocol_handler = mime_filter;
249 filter_data.pProtocol = PROTOCOL(filter_proxy);
250 hres = IInternetProtocol_Start(mime_filter, mime, PROTSINK(filter_proxy), BINDINFO(This),
251 PI_FILTER_MODE|PI_FORCE_ASYNC, (HANDLE_PTR)&filter_data);
252 if(FAILED(hres)) {
253 IInternetProtocolSink_Release(old_sink);
254 return hres;
257 IInternetProtocolSink_ReportProgress(old_sink, BINDSTATUS_LOADINGMIMEHANDLER, NULL);
258 IInternetProtocolSink_Release(old_sink);
260 This->pi &= ~PI_MIMEVERIFICATION; /* FIXME: more tests */
261 return S_OK;
264 static void mime_available(BindProtocol *This, LPCWSTR mime, BOOL verified)
266 IInternetProtocol *mime_filter;
267 HRESULT hres;
269 heap_free(This->mime);
270 This->mime = NULL;
272 mime_filter = get_mime_filter(mime);
273 if(mime_filter) {
274 TRACE("Got mime filter for %s\n", debugstr_w(mime));
276 hres = handle_mime_filter(This, mime_filter, mime);
277 IInternetProtocol_Release(mime_filter);
278 if(FAILED(hres))
279 FIXME("MIME filter failed: %08x\n", hres);
280 }else {
281 This->mime = heap_strdupW(mime);
283 if(verified || !(This->pi & PI_MIMEVERIFICATION)) {
284 This->reported_mime = TRUE;
286 if(This->protocol_sink)
287 IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, mime);
292 #define PROTOCOL_THIS(iface) DEFINE_THIS(BindProtocol, IInternetProtocolEx, iface)
294 static HRESULT WINAPI BindProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
296 BindProtocol *This = PROTOCOL_THIS(iface);
298 *ppv = NULL;
299 if(IsEqualGUID(&IID_IUnknown, riid)) {
300 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
301 *ppv = PROTOCOLEX(This);
302 }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
303 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
304 *ppv = PROTOCOLEX(This);
305 }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
306 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
307 *ppv = PROTOCOLEX(This);
308 }else if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) {
309 TRACE("(%p)->(IID_IInternetProtocolEx %p)\n", This, ppv);
310 *ppv = PROTOCOLEX(This);
311 }else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) {
312 TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This, ppv);
313 *ppv = BINDINFO(This);
314 }else if(IsEqualGUID(&IID_IInternetPriority, riid)) {
315 TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv);
316 *ppv = PRIORITY(This);
317 }else if(IsEqualGUID(&IID_IAuthenticate, riid)) {
318 FIXME("(%p)->(IID_IAuthenticate %p)\n", This, ppv);
319 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
320 TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
321 *ppv = SERVPROV(This);
322 }else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
323 TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
324 *ppv = PROTSINK(This);
325 }else if(IsEqualGUID(&IID_IWinInetInfo, riid)) {
326 TRACE("(%p)->(IID_IWinInetInfo %p)\n", This, ppv);
328 if(This->protocol) {
329 IWinInetInfo *inet_info;
330 HRESULT hres;
332 hres = IInternetProtocol_QueryInterface(This->protocol, &IID_IWinInetInfo, (void**)&inet_info);
333 if(SUCCEEDED(hres)) {
334 *ppv = HTTPINFO(This);
335 IWinInetInfo_Release(inet_info);
338 }else if(IsEqualGUID(&IID_IWinInetHttpInfo, riid)) {
339 TRACE("(%p)->(IID_IWinInetHttpInfo %p)\n", This, ppv);
341 if(This->protocol) {
342 IWinInetHttpInfo *http_info;
343 HRESULT hres;
345 hres = IInternetProtocol_QueryInterface(This->protocol, &IID_IWinInetHttpInfo, (void**)&http_info);
346 if(SUCCEEDED(hres)) {
347 *ppv = HTTPINFO(This);
348 IWinInetHttpInfo_Release(http_info);
351 }else {
352 WARN("not supported interface %s\n", debugstr_guid(riid));
355 if(!*ppv)
356 return E_NOINTERFACE;
358 IUnknown_AddRef((IUnknown*)*ppv);
359 return S_OK;
362 static ULONG WINAPI BindProtocol_AddRef(IInternetProtocolEx *iface)
364 BindProtocol *This = PROTOCOL_THIS(iface);
365 LONG ref = InterlockedIncrement(&This->ref);
366 TRACE("(%p) ref=%d\n", This, ref);
367 return ref;
370 static ULONG WINAPI BindProtocol_Release(IInternetProtocolEx *iface)
372 BindProtocol *This = PROTOCOL_THIS(iface);
373 LONG ref = InterlockedDecrement(&This->ref);
375 TRACE("(%p) ref=%d\n", This, ref);
377 if(!ref) {
378 if(This->wininet_info)
379 IWinInetInfo_Release(This->wininet_info);
380 if(This->protocol)
381 IInternetProtocol_Release(This->protocol);
382 if(This->bind_info)
383 IInternetBindInfo_Release(This->bind_info);
384 if(This->protocol_handler && This->protocol_handler != (IInternetProtocol*)PROTOCOLHANDLER(This))
385 IInternetProtocol_Release(This->protocol_handler);
386 if(This->filter_proxy)
387 IInternetProtocol_Release(PROTOCOL(This->filter_proxy));
388 if(This->uri)
389 IUri_Release(This->uri);
391 set_binding_sink((IInternetProtocol*)PROTOCOLEX(This), NULL, NULL);
393 if(This->notif_hwnd)
394 release_notif_hwnd(This->notif_hwnd);
395 DeleteCriticalSection(&This->section);
397 heap_free(This->mime);
398 heap_free(This);
400 URLMON_UnlockModule();
403 return ref;
406 static HRESULT WINAPI BindProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
407 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
408 DWORD grfPI, HANDLE_PTR dwReserved)
410 BindProtocol *This = PROTOCOL_THIS(iface);
411 IUri *uri;
412 HRESULT hres;
414 TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
415 pOIBindInfo, grfPI, dwReserved);
417 hres = CreateUri(szUrl, Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri);
418 if(FAILED(hres))
419 return hres;
421 hres = IInternetProtocolEx_StartEx(PROTOCOLEX(This), uri, pOIProtSink, pOIBindInfo,
422 grfPI, (HANDLE*)dwReserved);
424 IUri_Release(uri);
425 return hres;
428 static HRESULT WINAPI BindProtocol_Continue(IInternetProtocolEx *iface, PROTOCOLDATA *pProtocolData)
430 BindProtocol *This = PROTOCOL_THIS(iface);
432 TRACE("(%p)->(%p)\n", This, pProtocolData);
434 return IInternetProtocol_Continue(This->protocol_handler, pProtocolData);
437 static HRESULT WINAPI BindProtocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason,
438 DWORD dwOptions)
440 BindProtocol *This = PROTOCOL_THIS(iface);
442 TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
444 return IInternetProtocol_Abort(This->protocol_handler, hrReason, dwOptions);
447 static HRESULT WINAPI BindProtocol_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
449 BindProtocol *This = PROTOCOL_THIS(iface);
451 TRACE("(%p)->(%08x)\n", This, dwOptions);
453 return IInternetProtocol_Terminate(This->protocol_handler, dwOptions);
456 static HRESULT WINAPI BindProtocol_Suspend(IInternetProtocolEx *iface)
458 BindProtocol *This = PROTOCOL_THIS(iface);
459 FIXME("(%p)\n", This);
460 return E_NOTIMPL;
463 static HRESULT WINAPI BindProtocol_Resume(IInternetProtocolEx *iface)
465 BindProtocol *This = PROTOCOL_THIS(iface);
466 FIXME("(%p)\n", This);
467 return E_NOTIMPL;
470 static HRESULT WINAPI BindProtocol_Read(IInternetProtocolEx *iface, void *pv,
471 ULONG cb, ULONG *pcbRead)
473 BindProtocol *This = PROTOCOL_THIS(iface);
475 TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
477 if(pcbRead)
478 *pcbRead = 0;
479 return IInternetProtocol_Read(This->protocol_handler, pv, cb, pcbRead);
482 static HRESULT WINAPI BindProtocol_Seek(IInternetProtocolEx *iface, LARGE_INTEGER dlibMove,
483 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
485 BindProtocol *This = PROTOCOL_THIS(iface);
486 FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
487 return E_NOTIMPL;
490 static HRESULT WINAPI BindProtocol_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
492 BindProtocol *This = PROTOCOL_THIS(iface);
494 TRACE("(%p)->(%08x)\n", This, dwOptions);
496 return IInternetProtocol_LockRequest(This->protocol_handler, dwOptions);
499 static HRESULT WINAPI BindProtocol_UnlockRequest(IInternetProtocolEx *iface)
501 BindProtocol *This = PROTOCOL_THIS(iface);
503 TRACE("(%p)\n", This);
505 return IInternetProtocol_UnlockRequest(This->protocol_handler);
508 static HRESULT WINAPI BindProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUri,
509 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
510 DWORD grfPI, HANDLE *dwReserved)
512 BindProtocol *This = PROTOCOL_THIS(iface);
514 TRACE("(%p)->(%p %p %p %08x %p)\n", This, pUri, pOIProtSink, pOIBindInfo, grfPI, dwReserved);
516 if(This->protocol_handler != (IInternetProtocol*)PROTOCOLHANDLER(This)) {
517 FIXME("This->protocol_handler != PROTOCOLHANDLER(This)\n");
518 return E_FAIL;
521 return IInternetProtocolEx_StartEx(PROTOCOLHANDLER(This), pUri, pOIProtSink, pOIBindInfo, grfPI, dwReserved);
524 void set_binding_sink(IInternetProtocol *bind_protocol, IInternetProtocolSink *sink, IInternetBindInfo *bind_info)
526 BindProtocol *This = PROTOCOL_THIS(bind_protocol);
527 IInternetProtocolSink *prev_sink;
528 IServiceProvider *service_provider = NULL;
530 if(sink)
531 IInternetProtocolSink_AddRef(sink);
532 prev_sink = InterlockedExchangePointer((void**)&This->protocol_sink, sink);
533 if(prev_sink)
534 IInternetProtocolSink_Release(prev_sink);
536 if(sink)
537 IInternetProtocolSink_QueryInterface(sink, &IID_IServiceProvider, (void**)&service_provider);
538 service_provider = InterlockedExchangePointer((void**)&This->service_provider, service_provider);
539 if(service_provider)
540 IServiceProvider_Release(service_provider);
542 if(bind_info)
543 IInternetBindInfo_AddRef(bind_info);
544 bind_info = InterlockedExchangePointer((void**)&This->bind_info, bind_info);
545 if(bind_info)
546 IInternetBindInfo_Release(bind_info);
549 IWinInetInfo *get_wininet_info(IInternetProtocol *bind_protocol)
551 BindProtocol *This = PROTOCOL_THIS(bind_protocol);
553 return This->wininet_info;
556 #undef PROTOCOL_THIS
558 static const IInternetProtocolExVtbl BindProtocolVtbl = {
559 BindProtocol_QueryInterface,
560 BindProtocol_AddRef,
561 BindProtocol_Release,
562 BindProtocol_Start,
563 BindProtocol_Continue,
564 BindProtocol_Abort,
565 BindProtocol_Terminate,
566 BindProtocol_Suspend,
567 BindProtocol_Resume,
568 BindProtocol_Read,
569 BindProtocol_Seek,
570 BindProtocol_LockRequest,
571 BindProtocol_UnlockRequest,
572 BindProtocol_StartEx
575 #define PROTOCOLHANDLER_THIS(iface) DEFINE_THIS(BindProtocol, IInternetProtocolHandler, iface)
577 static HRESULT WINAPI ProtocolHandler_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
579 ERR("should not be called\n");
580 return E_NOINTERFACE;
583 static ULONG WINAPI ProtocolHandler_AddRef(IInternetProtocolEx *iface)
585 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
586 return IInternetProtocolEx_AddRef(PROTOCOLEX(This));
589 static ULONG WINAPI ProtocolHandler_Release(IInternetProtocolEx *iface)
591 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
592 return IInternetProtocolEx_Release(PROTOCOLEX(This));
595 static HRESULT WINAPI ProtocolHandler_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
596 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
597 DWORD grfPI, HANDLE_PTR dwReserved)
599 ERR("Should not be called\n");
600 return E_NOTIMPL;
603 static HRESULT WINAPI ProtocolHandler_Continue(IInternetProtocolEx *iface, PROTOCOLDATA *pProtocolData)
605 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
606 HRESULT hres;
608 TRACE("(%p)->(%p)\n", This, pProtocolData);
610 hres = IInternetProtocol_Continue(This->protocol, pProtocolData);
612 heap_free(pProtocolData);
613 return hres;
616 static HRESULT WINAPI ProtocolHandler_Abort(IInternetProtocolEx *iface, HRESULT hrReason,
617 DWORD dwOptions)
619 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
621 TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
623 if(This->protocol && !This->reported_result)
624 return IInternetProtocol_Abort(This->protocol, hrReason, dwOptions);
626 return S_OK;
629 static HRESULT WINAPI ProtocolHandler_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
631 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
633 TRACE("(%p)->(%08x)\n", This, dwOptions);
635 if(!This->reported_result)
636 return E_FAIL;
638 IInternetProtocol_Terminate(This->protocol, 0);
640 if(This->filter_proxy) {
641 IInternetProtocol_Release(PROTOCOL(This->filter_proxy));
642 This->filter_proxy = NULL;
645 set_binding_sink((IInternetProtocol*)PROTOCOLEX(This), NULL, NULL);
647 if(This->bind_info) {
648 IInternetBindInfo_Release(This->bind_info);
649 This->bind_info = NULL;
652 return S_OK;
655 static HRESULT WINAPI ProtocolHandler_Suspend(IInternetProtocolEx *iface)
657 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
658 FIXME("(%p)\n", This);
659 return E_NOTIMPL;
662 static HRESULT WINAPI ProtocolHandler_Resume(IInternetProtocolEx *iface)
664 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
665 FIXME("(%p)\n", This);
666 return E_NOTIMPL;
669 static HRESULT WINAPI ProtocolHandler_Read(IInternetProtocolEx *iface, void *pv,
670 ULONG cb, ULONG *pcbRead)
672 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
673 ULONG read = 0;
674 HRESULT hres = S_OK;
676 TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
678 if(This->buf_size) {
679 read = min(cb, This->buf_size);
680 memcpy(pv, This->buf, read);
682 if(read == This->buf_size) {
683 heap_free(This->buf);
684 This->buf = NULL;
685 }else {
686 memmove(This->buf, This->buf+cb, This->buf_size-cb);
689 This->buf_size -= read;
692 if(read < cb) {
693 ULONG cread = 0;
695 hres = IInternetProtocol_Read(This->protocol, (BYTE*)pv+read, cb-read, &cread);
696 read += cread;
699 *pcbRead = read;
700 return hres;
703 static HRESULT WINAPI ProtocolHandler_Seek(IInternetProtocolEx *iface, LARGE_INTEGER dlibMove,
704 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
706 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
707 FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
708 return E_NOTIMPL;
711 static HRESULT WINAPI ProtocolHandler_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
713 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
715 TRACE("(%p)->(%08x)\n", This, dwOptions);
717 return IInternetProtocol_LockRequest(This->protocol, dwOptions);
720 static HRESULT WINAPI ProtocolHandler_UnlockRequest(IInternetProtocolEx *iface)
722 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
724 TRACE("(%p)\n", This);
726 return IInternetProtocol_UnlockRequest(This->protocol);
729 static HRESULT WINAPI ProtocolHandler_StartEx(IInternetProtocolEx *iface, IUri *pUri,
730 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
731 DWORD grfPI, HANDLE *dwReserved)
733 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
734 IInternetProtocol *protocol = NULL;
735 IInternetProtocolEx *protocolex;
736 IInternetPriority *priority;
737 IServiceProvider *service_provider;
738 BOOL urlmon_protocol = FALSE;
739 CLSID clsid = IID_NULL;
740 LPOLESTR clsid_str;
741 HRESULT hres;
743 TRACE("(%p)->(%p %p %p %08x %p)\n", This, pUri, pOIProtSink, pOIBindInfo, grfPI, dwReserved);
745 if(!pUri || !pOIProtSink || !pOIBindInfo)
746 return E_INVALIDARG;
748 This->pi = grfPI;
750 IUri_AddRef(pUri);
751 This->uri = pUri;
753 hres = IInternetProtocolSink_QueryInterface(pOIProtSink, &IID_IServiceProvider,
754 (void**)&service_provider);
755 if(SUCCEEDED(hres)) {
756 /* FIXME: What's protocol CLSID here? */
757 IServiceProvider_QueryService(service_provider, &IID_IInternetProtocol,
758 &IID_IInternetProtocol, (void**)&protocol);
759 IServiceProvider_Release(service_provider);
762 if(!protocol) {
763 IClassFactory *cf;
764 IUnknown *unk;
765 BSTR raw_uri;
767 /* FIXME: Avoid GetRawUri here */
768 hres = IUri_GetRawUri(pUri, &raw_uri);
769 if(FAILED(hres))
770 return hres;
772 hres = get_protocol_handler(raw_uri, &clsid, &urlmon_protocol, &cf);
773 SysFreeString(raw_uri);
774 if(FAILED(hres))
775 return hres;
777 if(This->from_urlmon) {
778 hres = IClassFactory_CreateInstance(cf, NULL, &IID_IInternetProtocol, (void**)&protocol);
779 IClassFactory_Release(cf);
780 if(FAILED(hres))
781 return hres;
782 }else {
783 hres = IClassFactory_CreateInstance(cf, (IUnknown*)BINDINFO(This),
784 &IID_IUnknown, (void**)&unk);
785 IClassFactory_Release(cf);
786 if(FAILED(hres))
787 return hres;
789 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocol, (void**)&protocol);
790 IUnknown_Release(unk);
791 if(FAILED(hres))
792 return hres;
796 StringFromCLSID(&clsid, &clsid_str);
797 IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_PROTOCOLCLASSID, clsid_str);
798 CoTaskMemFree(clsid_str);
800 This->protocol = protocol;
802 if(urlmon_protocol)
803 IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&This->wininet_info);
805 set_binding_sink((IInternetProtocol*)PROTOCOLEX(This), pOIProtSink, pOIBindInfo);
807 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
808 if(SUCCEEDED(hres)) {
809 IInternetPriority_SetPriority(priority, This->priority);
810 IInternetPriority_Release(priority);
813 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolEx, (void**)&protocolex);
814 if(SUCCEEDED(hres)) {
815 hres = IInternetProtocolEx_StartEx(protocolex, pUri, PROTSINK(This), BINDINFO(This), 0, NULL);
816 IInternetProtocolEx_Release(protocolex);
817 }else {
818 BSTR display_uri;
820 hres = IUri_GetDisplayUri(pUri, &display_uri);
821 if(FAILED(hres))
822 return hres;
824 hres = IInternetProtocol_Start(protocol, display_uri, PROTSINK(This), BINDINFO(This), 0, 0);
825 SysFreeString(display_uri);
828 return hres;
831 #undef PROTOCOL_THIS
833 static const IInternetProtocolExVtbl InternetProtocolHandlerVtbl = {
834 ProtocolHandler_QueryInterface,
835 ProtocolHandler_AddRef,
836 ProtocolHandler_Release,
837 ProtocolHandler_Start,
838 ProtocolHandler_Continue,
839 ProtocolHandler_Abort,
840 ProtocolHandler_Terminate,
841 ProtocolHandler_Suspend,
842 ProtocolHandler_Resume,
843 ProtocolHandler_Read,
844 ProtocolHandler_Seek,
845 ProtocolHandler_LockRequest,
846 ProtocolHandler_UnlockRequest,
847 ProtocolHandler_StartEx
850 #define BINDINFO_THIS(iface) DEFINE_THIS(BindProtocol, InternetBindInfo, iface)
852 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface,
853 REFIID riid, void **ppv)
855 BindProtocol *This = BINDINFO_THIS(iface);
856 return IInternetProtocolEx_QueryInterface(PROTOCOLEX(This), riid, ppv);
859 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
861 BindProtocol *This = BINDINFO_THIS(iface);
862 return IInternetProtocolEx_AddRef(PROTOCOLEX(This));
865 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
867 BindProtocol *This = BINDINFO_THIS(iface);
868 return IInternetProtocolEx_Release(PROTOCOLEX(This));
871 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface,
872 DWORD *grfBINDF, BINDINFO *pbindinfo)
874 BindProtocol *This = BINDINFO_THIS(iface);
875 HRESULT hres;
877 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
879 hres = IInternetBindInfo_GetBindInfo(This->bind_info, grfBINDF, pbindinfo);
880 if(FAILED(hres)) {
881 WARN("GetBindInfo failed: %08x\n", hres);
882 return hres;
885 *grfBINDF |= BINDF_FROMURLMON;
886 return hres;
889 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface,
890 ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
892 BindProtocol *This = BINDINFO_THIS(iface);
894 TRACE("(%p)->(%d %p %d %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched);
896 return IInternetBindInfo_GetBindString(This->bind_info, ulStringType, ppwzStr, cEl, pcElFetched);
899 #undef BINDFO_THIS
901 static const IInternetBindInfoVtbl InternetBindInfoVtbl = {
902 BindInfo_QueryInterface,
903 BindInfo_AddRef,
904 BindInfo_Release,
905 BindInfo_GetBindInfo,
906 BindInfo_GetBindString
909 #define PRIORITY_THIS(iface) DEFINE_THIS(BindProtocol, InternetPriority, iface)
911 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
912 REFIID riid, void **ppv)
914 BindProtocol *This = PRIORITY_THIS(iface);
915 return IInternetProtocolEx_QueryInterface(PROTOCOLEX(This), riid, ppv);
918 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
920 BindProtocol *This = PRIORITY_THIS(iface);
921 return IInternetProtocolEx_AddRef(PROTOCOLEX(This));
924 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
926 BindProtocol *This = PRIORITY_THIS(iface);
927 return IInternetProtocolEx_Release(PROTOCOLEX(This));
930 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
932 BindProtocol *This = PRIORITY_THIS(iface);
934 TRACE("(%p)->(%d)\n", This, nPriority);
936 This->priority = nPriority;
937 return S_OK;
940 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
942 BindProtocol *This = PRIORITY_THIS(iface);
944 TRACE("(%p)->(%p)\n", This, pnPriority);
946 *pnPriority = This->priority;
947 return S_OK;
950 #undef PRIORITY_THIS
952 static const IInternetPriorityVtbl InternetPriorityVtbl = {
953 InternetPriority_QueryInterface,
954 InternetPriority_AddRef,
955 InternetPriority_Release,
956 InternetPriority_SetPriority,
957 InternetPriority_GetPriority
961 #define PROTSINK_THIS(iface) DEFINE_THIS(BindProtocol, IInternetProtocolSink, iface)
963 static HRESULT WINAPI BPInternetProtocolSink_QueryInterface(IInternetProtocolSink *iface,
964 REFIID riid, void **ppv)
966 BindProtocol *This = PROTSINK_THIS(iface);
967 return IInternetProtocolEx_QueryInterface(PROTOCOLEX(This), riid, ppv);
970 static ULONG WINAPI BPInternetProtocolSink_AddRef(IInternetProtocolSink *iface)
972 BindProtocol *This = PROTSINK_THIS(iface);
973 return IInternetProtocolEx_AddRef(PROTOCOLEX(This));
976 static ULONG WINAPI BPInternetProtocolSink_Release(IInternetProtocolSink *iface)
978 BindProtocol *This = PROTSINK_THIS(iface);
979 return IInternetProtocolEx_Release(PROTOCOLEX(This));
982 typedef struct {
983 task_header_t header;
984 PROTOCOLDATA *data;
985 } switch_task_t;
987 static void switch_proc(BindProtocol *bind, task_header_t *t)
989 switch_task_t *task = (switch_task_t*)t;
991 IInternetProtocol_Continue(bind->protocol_handler, task->data);
993 heap_free(task);
996 static HRESULT WINAPI BPInternetProtocolSink_Switch(IInternetProtocolSink *iface,
997 PROTOCOLDATA *pProtocolData)
999 BindProtocol *This = PROTSINK_THIS(iface);
1000 PROTOCOLDATA *data;
1002 TRACE("(%p)->(%p)\n", This, pProtocolData);
1004 TRACE("flags %x state %x data %p cb %u\n", pProtocolData->grfFlags, pProtocolData->dwState,
1005 pProtocolData->pData, pProtocolData->cbData);
1007 data = heap_alloc(sizeof(PROTOCOLDATA));
1008 if(!data)
1009 return E_OUTOFMEMORY;
1010 memcpy(data, pProtocolData, sizeof(PROTOCOLDATA));
1012 if(!do_direct_notif(This)) {
1013 switch_task_t *task;
1015 task = heap_alloc(sizeof(switch_task_t));
1016 if(!task)
1017 return E_OUTOFMEMORY;
1019 task->data = data;
1021 push_task(This, &task->header, switch_proc);
1022 return S_OK;
1025 if(!This->protocol_sink) {
1026 IInternetProtocol_Continue(This->protocol_handler, data);
1027 return S_OK;
1030 return IInternetProtocolSink_Switch(This->protocol_sink, data);
1033 static void report_progress(BindProtocol *This, ULONG status_code, LPCWSTR status_text)
1035 switch(status_code) {
1036 case BINDSTATUS_FINDINGRESOURCE:
1037 case BINDSTATUS_CONNECTING:
1038 case BINDSTATUS_REDIRECTING:
1039 case BINDSTATUS_BEGINDOWNLOADDATA:
1040 case BINDSTATUS_SENDINGREQUEST:
1041 case BINDSTATUS_CACHEFILENAMEAVAILABLE:
1042 case BINDSTATUS_DIRECTBIND:
1043 case BINDSTATUS_ACCEPTRANGES:
1044 if(This->protocol_sink)
1045 IInternetProtocolSink_ReportProgress(This->protocol_sink, status_code, status_text);
1046 break;
1048 case BINDSTATUS_MIMETYPEAVAILABLE:
1049 mime_available(This, status_text, FALSE);
1050 break;
1052 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
1053 mime_available(This, status_text, TRUE);
1054 break;
1056 default:
1057 FIXME("unsupported ulStatusCode %u\n", status_code);
1061 typedef struct {
1062 task_header_t header;
1064 ULONG status_code;
1065 LPWSTR status_text;
1066 } on_progress_task_t;
1068 static void on_progress_proc(BindProtocol *This, task_header_t *t)
1070 on_progress_task_t *task = (on_progress_task_t*)t;
1072 report_progress(This, task->status_code, task->status_text);
1074 heap_free(task->status_text);
1075 heap_free(task);
1078 static HRESULT WINAPI BPInternetProtocolSink_ReportProgress(IInternetProtocolSink *iface,
1079 ULONG ulStatusCode, LPCWSTR szStatusText)
1081 BindProtocol *This = PROTSINK_THIS(iface);
1083 TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
1085 if(do_direct_notif(This)) {
1086 report_progress(This, ulStatusCode, szStatusText);
1087 }else {
1088 on_progress_task_t *task;
1090 task = heap_alloc(sizeof(on_progress_task_t));
1092 task->status_code = ulStatusCode;
1093 task->status_text = heap_strdupW(szStatusText);
1095 push_task(This, &task->header, on_progress_proc);
1098 return S_OK;
1101 static HRESULT report_data(BindProtocol *This, DWORD bscf, ULONG progress, ULONG progress_max)
1103 if(!This->protocol_sink)
1104 return S_OK;
1106 if((This->pi & PI_MIMEVERIFICATION) && !This->reported_mime) {
1107 BYTE buf[BUFFER_SIZE];
1108 DWORD read = 0;
1109 LPWSTR mime;
1110 HRESULT hres;
1112 do {
1113 read = 0;
1114 hres = IInternetProtocol_Read(This->protocol, buf,
1115 sizeof(buf)-This->buf_size, &read);
1116 if(FAILED(hres) && hres != E_PENDING)
1117 return hres;
1119 if(!This->buf) {
1120 This->buf = heap_alloc(BUFFER_SIZE);
1121 if(!This->buf)
1122 return E_OUTOFMEMORY;
1123 }else if(read + This->buf_size > BUFFER_SIZE) {
1124 BYTE *tmp;
1126 tmp = heap_realloc(This->buf, read+This->buf_size);
1127 if(!tmp)
1128 return E_OUTOFMEMORY;
1129 This->buf = tmp;
1132 memcpy(This->buf+This->buf_size, buf, read);
1133 This->buf_size += read;
1134 }while(This->buf_size < MIME_TEST_SIZE && hres == S_OK);
1136 if(This->buf_size < MIME_TEST_SIZE && hres != S_FALSE)
1137 return S_OK;
1139 bscf = BSCF_FIRSTDATANOTIFICATION;
1140 if(hres == S_FALSE)
1141 bscf |= BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE;
1143 if(!This->reported_mime) {
1144 BSTR raw_uri;
1146 hres = IUri_GetRawUri(This->uri, &raw_uri);
1147 if(FAILED(hres))
1148 return hres;
1150 hres = FindMimeFromData(NULL, raw_uri, This->buf, min(This->buf_size, MIME_TEST_SIZE),
1151 This->mime, 0, &mime, 0);
1152 SysFreeString(raw_uri);
1153 if(FAILED(hres))
1154 return hres;
1156 mime_available(This, mime, TRUE);
1157 CoTaskMemFree(mime);
1161 if(!This->protocol_sink)
1162 return S_OK;
1164 return IInternetProtocolSink_ReportData(This->protocol_sink, bscf, progress, progress_max);
1167 typedef struct {
1168 task_header_t header;
1169 DWORD bscf;
1170 ULONG progress;
1171 ULONG progress_max;
1172 } report_data_task_t;
1174 static void report_data_proc(BindProtocol *This, task_header_t *t)
1176 report_data_task_t *task = (report_data_task_t*)t;
1178 report_data(This, task->bscf, task->progress, task->progress_max);
1179 heap_free(task);
1182 static HRESULT WINAPI BPInternetProtocolSink_ReportData(IInternetProtocolSink *iface,
1183 DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax)
1185 BindProtocol *This = PROTSINK_THIS(iface);
1187 TRACE("(%p)->(%d %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
1189 if(!This->protocol_sink)
1190 return S_OK;
1192 if(!do_direct_notif(This)) {
1193 report_data_task_t *task;
1195 task = heap_alloc(sizeof(report_data_task_t));
1196 if(!task)
1197 return E_OUTOFMEMORY;
1199 task->bscf = grfBSCF;
1200 task->progress = ulProgress;
1201 task->progress_max = ulProgressMax;
1203 push_task(This, &task->header, report_data_proc);
1204 return S_OK;
1207 return report_data(This, grfBSCF, ulProgress, ulProgressMax);
1210 typedef struct {
1211 task_header_t header;
1213 HRESULT hres;
1214 DWORD err;
1215 LPWSTR str;
1216 } report_result_task_t;
1218 static void report_result_proc(BindProtocol *This, task_header_t *t)
1220 report_result_task_t *task = (report_result_task_t*)t;
1222 if(This->protocol_sink)
1223 IInternetProtocolSink_ReportResult(This->protocol_sink, task->hres, task->err, task->str);
1225 heap_free(task->str);
1226 heap_free(task);
1229 static HRESULT WINAPI BPInternetProtocolSink_ReportResult(IInternetProtocolSink *iface,
1230 HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
1232 BindProtocol *This = PROTSINK_THIS(iface);
1234 TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
1236 if(!This->protocol_sink)
1237 return E_FAIL;
1239 This->reported_result = TRUE;
1241 if(!do_direct_notif(This)) {
1242 report_result_task_t *task;
1244 task = heap_alloc(sizeof(report_result_task_t));
1245 if(!task)
1246 return E_OUTOFMEMORY;
1248 task->hres = hrResult;
1249 task->err = dwError;
1250 task->str = heap_strdupW(szResult);
1252 push_task(This, &task->header, report_result_proc);
1253 return S_OK;
1256 return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
1259 #undef PROTSINK_THIS
1261 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = {
1262 BPInternetProtocolSink_QueryInterface,
1263 BPInternetProtocolSink_AddRef,
1264 BPInternetProtocolSink_Release,
1265 BPInternetProtocolSink_Switch,
1266 BPInternetProtocolSink_ReportProgress,
1267 BPInternetProtocolSink_ReportData,
1268 BPInternetProtocolSink_ReportResult
1271 #define INETINFO_THIS(iface) DEFINE_THIS(BindProtocol, IWinInetHttpInfo, iface)
1273 static HRESULT WINAPI WinInetHttpInfo_QueryInterface(IWinInetHttpInfo *iface, REFIID riid, void **ppv)
1275 BindProtocol *This = INETINFO_THIS(iface);
1276 return IInternetProtocolEx_QueryInterface(PROTOCOLEX(This), riid, ppv);
1279 static ULONG WINAPI WinInetHttpInfo_AddRef(IWinInetHttpInfo *iface)
1281 BindProtocol *This = INETINFO_THIS(iface);
1282 return IInternetProtocolEx_AddRef(PROTOCOLEX(This));
1285 static ULONG WINAPI WinInetHttpInfo_Release(IWinInetHttpInfo *iface)
1287 BindProtocol *This = INETINFO_THIS(iface);
1288 return IInternetProtocolEx_Release(PROTOCOLEX(This));
1291 static HRESULT WINAPI WinInetHttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD dwOption,
1292 void *pBuffer, DWORD *pcbBuffer)
1294 BindProtocol *This = INETINFO_THIS(iface);
1295 FIXME("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer);
1296 return E_NOTIMPL;
1299 static HRESULT WINAPI WinInetHttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption,
1300 void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved)
1302 BindProtocol *This = INETINFO_THIS(iface);
1303 FIXME("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved);
1304 return E_NOTIMPL;
1307 #undef INETINFO_THIS
1309 static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = {
1310 WinInetHttpInfo_QueryInterface,
1311 WinInetHttpInfo_AddRef,
1312 WinInetHttpInfo_Release,
1313 WinInetHttpInfo_QueryOption,
1314 WinInetHttpInfo_QueryInfo
1317 #define SERVPROV_THIS(iface) DEFINE_THIS(BindProtocol, ServiceProvider, iface)
1319 static HRESULT WINAPI BPServiceProvider_QueryInterface(IServiceProvider *iface,
1320 REFIID riid, void **ppv)
1322 BindProtocol *This = SERVPROV_THIS(iface);
1323 return IInternetProtocolEx_QueryInterface(PROTOCOLEX(This), riid, ppv);
1326 static ULONG WINAPI BPServiceProvider_AddRef(IServiceProvider *iface)
1328 BindProtocol *This = SERVPROV_THIS(iface);
1329 return IInternetProtocolEx_AddRef(PROTOCOLEX(This));
1332 static ULONG WINAPI BPServiceProvider_Release(IServiceProvider *iface)
1334 BindProtocol *This = SERVPROV_THIS(iface);
1335 return IInternetProtocolEx_Release(PROTOCOLEX(This));
1338 static HRESULT WINAPI BPServiceProvider_QueryService(IServiceProvider *iface,
1339 REFGUID guidService, REFIID riid, void **ppv)
1341 BindProtocol *This = SERVPROV_THIS(iface);
1343 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
1345 if(!This->service_provider)
1346 return E_NOINTERFACE;
1348 return IServiceProvider_QueryService(This->service_provider, guidService, riid, ppv);
1351 #undef SERVPROV_THIS
1353 static const IServiceProviderVtbl ServiceProviderVtbl = {
1354 BPServiceProvider_QueryInterface,
1355 BPServiceProvider_AddRef,
1356 BPServiceProvider_Release,
1357 BPServiceProvider_QueryService
1360 HRESULT create_binding_protocol(LPCWSTR url, BOOL from_urlmon, IInternetProtocol **protocol)
1362 BindProtocol *ret = heap_alloc_zero(sizeof(BindProtocol));
1364 ret->lpIInternetProtocolExVtbl = &BindProtocolVtbl;
1365 ret->lpInternetBindInfoVtbl = &InternetBindInfoVtbl;
1366 ret->lpInternetPriorityVtbl = &InternetPriorityVtbl;
1367 ret->lpServiceProviderVtbl = &ServiceProviderVtbl;
1368 ret->lpIInternetProtocolSinkVtbl = &InternetProtocolSinkVtbl;
1369 ret->lpIInternetProtocolHandlerVtbl = &InternetProtocolHandlerVtbl;
1370 ret->lpIWinInetHttpInfoVtbl = &WinInetHttpInfoVtbl;
1372 ret->ref = 1;
1373 ret->from_urlmon = from_urlmon;
1374 ret->apartment_thread = GetCurrentThreadId();
1375 ret->notif_hwnd = get_notif_hwnd();
1376 ret->protocol_handler = (IInternetProtocol*)PROTOCOLHANDLER(ret);
1377 InitializeCriticalSection(&ret->section);
1379 URLMON_LockModule();
1381 *protocol = (IInternetProtocol*)PROTOCOLEX(ret);
1382 return S_OK;