urlmon: Added IInternetProtocolEx support to BindProtocol.
[wine/wine-gecko.git] / dlls / urlmon / bindprot.c
blob3b07809a01705d16e3a74a2c5a453425be9109ec
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);
412 TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
413 pOIBindInfo, grfPI, dwReserved);
415 if(This->protocol_handler != (IInternetProtocol*)PROTOCOLHANDLER(This)) {
416 FIXME("This->protocol_handler != PROTOCOLHANDLER(This)\n");
417 return E_FAIL;
420 return IInternetProtocolEx_Start(PROTOCOLHANDLER(This), szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved);
423 static HRESULT WINAPI BindProtocol_Continue(IInternetProtocolEx *iface, PROTOCOLDATA *pProtocolData)
425 BindProtocol *This = PROTOCOL_THIS(iface);
427 TRACE("(%p)->(%p)\n", This, pProtocolData);
429 return IInternetProtocol_Continue(This->protocol_handler, pProtocolData);
432 static HRESULT WINAPI BindProtocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason,
433 DWORD dwOptions)
435 BindProtocol *This = PROTOCOL_THIS(iface);
437 TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
439 return IInternetProtocol_Abort(This->protocol_handler, hrReason, dwOptions);
442 static HRESULT WINAPI BindProtocol_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
444 BindProtocol *This = PROTOCOL_THIS(iface);
446 TRACE("(%p)->(%08x)\n", This, dwOptions);
448 return IInternetProtocol_Terminate(This->protocol_handler, dwOptions);
451 static HRESULT WINAPI BindProtocol_Suspend(IInternetProtocolEx *iface)
453 BindProtocol *This = PROTOCOL_THIS(iface);
454 FIXME("(%p)\n", This);
455 return E_NOTIMPL;
458 static HRESULT WINAPI BindProtocol_Resume(IInternetProtocolEx *iface)
460 BindProtocol *This = PROTOCOL_THIS(iface);
461 FIXME("(%p)\n", This);
462 return E_NOTIMPL;
465 static HRESULT WINAPI BindProtocol_Read(IInternetProtocolEx *iface, void *pv,
466 ULONG cb, ULONG *pcbRead)
468 BindProtocol *This = PROTOCOL_THIS(iface);
470 TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
472 if(pcbRead)
473 *pcbRead = 0;
474 return IInternetProtocol_Read(This->protocol_handler, pv, cb, pcbRead);
477 static HRESULT WINAPI BindProtocol_Seek(IInternetProtocolEx *iface, LARGE_INTEGER dlibMove,
478 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
480 BindProtocol *This = PROTOCOL_THIS(iface);
481 FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
482 return E_NOTIMPL;
485 static HRESULT WINAPI BindProtocol_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
487 BindProtocol *This = PROTOCOL_THIS(iface);
489 TRACE("(%p)->(%08x)\n", This, dwOptions);
491 return IInternetProtocol_LockRequest(This->protocol_handler, dwOptions);
494 static HRESULT WINAPI BindProtocol_UnlockRequest(IInternetProtocolEx *iface)
496 BindProtocol *This = PROTOCOL_THIS(iface);
498 TRACE("(%p)\n", This);
500 return IInternetProtocol_UnlockRequest(This->protocol_handler);
503 static HRESULT WINAPI BindProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUri,
504 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
505 DWORD grfPI, HANDLE *dwReserved)
507 BindProtocol *This = PROTOCOL_THIS(iface);
509 TRACE("(%p)->(%p %p %p %08x %p)\n", This, pUri, pOIProtSink, pOIBindInfo, grfPI, dwReserved);
511 if(This->protocol_handler != (IInternetProtocol*)PROTOCOLHANDLER(This)) {
512 FIXME("This->protocol_handler != PROTOCOLHANDLER(This)\n");
513 return E_FAIL;
516 return IInternetProtocolEx_StartEx(PROTOCOLHANDLER(This), pUri, pOIProtSink, pOIBindInfo, grfPI, dwReserved);
519 void set_binding_sink(IInternetProtocol *bind_protocol, IInternetProtocolSink *sink, IInternetBindInfo *bind_info)
521 BindProtocol *This = PROTOCOL_THIS(bind_protocol);
522 IInternetProtocolSink *prev_sink;
523 IServiceProvider *service_provider = NULL;
525 if(sink)
526 IInternetProtocolSink_AddRef(sink);
527 prev_sink = InterlockedExchangePointer((void**)&This->protocol_sink, sink);
528 if(prev_sink)
529 IInternetProtocolSink_Release(prev_sink);
531 if(sink)
532 IInternetProtocolSink_QueryInterface(sink, &IID_IServiceProvider, (void**)&service_provider);
533 service_provider = InterlockedExchangePointer((void**)&This->service_provider, service_provider);
534 if(service_provider)
535 IServiceProvider_Release(service_provider);
537 if(bind_info)
538 IInternetBindInfo_AddRef(bind_info);
539 bind_info = InterlockedExchangePointer((void**)&This->bind_info, bind_info);
540 if(bind_info)
541 IInternetBindInfo_Release(bind_info);
544 IWinInetInfo *get_wininet_info(IInternetProtocol *bind_protocol)
546 BindProtocol *This = PROTOCOL_THIS(bind_protocol);
548 return This->wininet_info;
551 #undef PROTOCOL_THIS
553 static const IInternetProtocolExVtbl BindProtocolVtbl = {
554 BindProtocol_QueryInterface,
555 BindProtocol_AddRef,
556 BindProtocol_Release,
557 BindProtocol_Start,
558 BindProtocol_Continue,
559 BindProtocol_Abort,
560 BindProtocol_Terminate,
561 BindProtocol_Suspend,
562 BindProtocol_Resume,
563 BindProtocol_Read,
564 BindProtocol_Seek,
565 BindProtocol_LockRequest,
566 BindProtocol_UnlockRequest,
567 BindProtocol_StartEx
570 #define PROTOCOLHANDLER_THIS(iface) DEFINE_THIS(BindProtocol, IInternetProtocolHandler, iface)
572 static HRESULT WINAPI ProtocolHandler_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
574 ERR("should not be called\n");
575 return E_NOINTERFACE;
578 static ULONG WINAPI ProtocolHandler_AddRef(IInternetProtocolEx *iface)
580 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
581 return IInternetProtocolEx_AddRef(PROTOCOLEX(This));
584 static ULONG WINAPI ProtocolHandler_Release(IInternetProtocolEx *iface)
586 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
587 return IInternetProtocolEx_Release(PROTOCOLEX(This));
590 static HRESULT WINAPI ProtocolHandler_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
591 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
592 DWORD grfPI, HANDLE_PTR dwReserved)
594 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
595 IUri *uri;
596 HRESULT hres;
598 TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
599 pOIBindInfo, grfPI, dwReserved);
601 hres = CreateUri(szUrl, Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri);
602 if(FAILED(hres))
603 return hres;
605 hres = IInternetProtocolEx_StartEx(PROTOCOLHANDLER(This), uri, pOIProtSink, pOIBindInfo,
606 grfPI, (HANDLE*)dwReserved);
608 IUri_Release(uri);
609 return hres;
612 static HRESULT WINAPI ProtocolHandler_Continue(IInternetProtocolEx *iface, PROTOCOLDATA *pProtocolData)
614 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
615 HRESULT hres;
617 TRACE("(%p)->(%p)\n", This, pProtocolData);
619 hres = IInternetProtocol_Continue(This->protocol, pProtocolData);
621 heap_free(pProtocolData);
622 return hres;
625 static HRESULT WINAPI ProtocolHandler_Abort(IInternetProtocolEx *iface, HRESULT hrReason,
626 DWORD dwOptions)
628 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
630 TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
632 if(This->protocol && !This->reported_result)
633 return IInternetProtocol_Abort(This->protocol, hrReason, dwOptions);
635 return S_OK;
638 static HRESULT WINAPI ProtocolHandler_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
640 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
642 TRACE("(%p)->(%08x)\n", This, dwOptions);
644 if(!This->reported_result)
645 return E_FAIL;
647 IInternetProtocol_Terminate(This->protocol, 0);
649 if(This->filter_proxy) {
650 IInternetProtocol_Release(PROTOCOL(This->filter_proxy));
651 This->filter_proxy = NULL;
654 set_binding_sink((IInternetProtocol*)PROTOCOLEX(This), NULL, NULL);
656 if(This->bind_info) {
657 IInternetBindInfo_Release(This->bind_info);
658 This->bind_info = NULL;
661 return S_OK;
664 static HRESULT WINAPI ProtocolHandler_Suspend(IInternetProtocolEx *iface)
666 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
667 FIXME("(%p)\n", This);
668 return E_NOTIMPL;
671 static HRESULT WINAPI ProtocolHandler_Resume(IInternetProtocolEx *iface)
673 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
674 FIXME("(%p)\n", This);
675 return E_NOTIMPL;
678 static HRESULT WINAPI ProtocolHandler_Read(IInternetProtocolEx *iface, void *pv,
679 ULONG cb, ULONG *pcbRead)
681 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
682 ULONG read = 0;
683 HRESULT hres = S_OK;
685 TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
687 if(This->buf_size) {
688 read = min(cb, This->buf_size);
689 memcpy(pv, This->buf, read);
691 if(read == This->buf_size) {
692 heap_free(This->buf);
693 This->buf = NULL;
694 }else {
695 memmove(This->buf, This->buf+cb, This->buf_size-cb);
698 This->buf_size -= read;
701 if(read < cb) {
702 ULONG cread = 0;
704 hres = IInternetProtocol_Read(This->protocol, (BYTE*)pv+read, cb-read, &cread);
705 read += cread;
708 *pcbRead = read;
709 return hres;
712 static HRESULT WINAPI ProtocolHandler_Seek(IInternetProtocolEx *iface, LARGE_INTEGER dlibMove,
713 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
715 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
716 FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
717 return E_NOTIMPL;
720 static HRESULT WINAPI ProtocolHandler_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
722 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
724 TRACE("(%p)->(%08x)\n", This, dwOptions);
726 return IInternetProtocol_LockRequest(This->protocol, dwOptions);
729 static HRESULT WINAPI ProtocolHandler_UnlockRequest(IInternetProtocolEx *iface)
731 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
733 TRACE("(%p)\n", This);
735 return IInternetProtocol_UnlockRequest(This->protocol);
738 static HRESULT WINAPI ProtocolHandler_StartEx(IInternetProtocolEx *iface, IUri *pUri,
739 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
740 DWORD grfPI, HANDLE *dwReserved)
742 BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
743 IInternetProtocol *protocol = NULL;
744 IInternetProtocolEx *protocolex;
745 IInternetPriority *priority;
746 IServiceProvider *service_provider;
747 BOOL urlmon_protocol = FALSE;
748 CLSID clsid = IID_NULL;
749 LPOLESTR clsid_str;
750 HRESULT hres;
752 TRACE("(%p)->(%p %p %p %08x %p)\n", This, pUri, pOIProtSink, pOIBindInfo, grfPI, dwReserved);
754 if(!pUri || !pOIProtSink || !pOIBindInfo)
755 return E_INVALIDARG;
757 This->pi = grfPI;
759 IUri_AddRef(pUri);
760 This->uri = pUri;
762 hres = IInternetProtocolSink_QueryInterface(pOIProtSink, &IID_IServiceProvider,
763 (void**)&service_provider);
764 if(SUCCEEDED(hres)) {
765 /* FIXME: What's protocol CLSID here? */
766 IServiceProvider_QueryService(service_provider, &IID_IInternetProtocol,
767 &IID_IInternetProtocol, (void**)&protocol);
768 IServiceProvider_Release(service_provider);
771 if(!protocol) {
772 IClassFactory *cf;
773 IUnknown *unk;
774 BSTR raw_uri;
776 /* FIXME: Avoid GetRawUri here */
777 hres = IUri_GetRawUri(pUri, &raw_uri);
778 if(FAILED(hres))
779 return hres;
781 hres = get_protocol_handler(raw_uri, &clsid, &urlmon_protocol, &cf);
782 SysFreeString(raw_uri);
783 if(FAILED(hres))
784 return hres;
786 if(This->from_urlmon) {
787 hres = IClassFactory_CreateInstance(cf, NULL, &IID_IInternetProtocol, (void**)&protocol);
788 IClassFactory_Release(cf);
789 if(FAILED(hres))
790 return hres;
791 }else {
792 hres = IClassFactory_CreateInstance(cf, (IUnknown*)BINDINFO(This),
793 &IID_IUnknown, (void**)&unk);
794 IClassFactory_Release(cf);
795 if(FAILED(hres))
796 return hres;
798 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocol, (void**)&protocol);
799 IUnknown_Release(unk);
800 if(FAILED(hres))
801 return hres;
805 StringFromCLSID(&clsid, &clsid_str);
806 IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_PROTOCOLCLASSID, clsid_str);
807 CoTaskMemFree(clsid_str);
809 This->protocol = protocol;
811 if(urlmon_protocol)
812 IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&This->wininet_info);
814 set_binding_sink((IInternetProtocol*)PROTOCOLEX(This), pOIProtSink, pOIBindInfo);
816 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
817 if(SUCCEEDED(hres)) {
818 IInternetPriority_SetPriority(priority, This->priority);
819 IInternetPriority_Release(priority);
822 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolEx, (void**)&protocolex);
823 if(SUCCEEDED(hres)) {
824 hres = IInternetProtocolEx_StartEx(protocolex, pUri, PROTSINK(This), BINDINFO(This), 0, NULL);
825 IInternetProtocolEx_Release(protocolex);
826 }else {
827 BSTR display_uri;
829 hres = IUri_GetDisplayUri(pUri, &display_uri);
830 if(FAILED(hres))
831 return hres;
833 hres = IInternetProtocol_Start(protocol, display_uri, PROTSINK(This), BINDINFO(This), 0, 0);
834 SysFreeString(display_uri);
837 return hres;
840 #undef PROTOCOL_THIS
842 static const IInternetProtocolExVtbl InternetProtocolHandlerVtbl = {
843 ProtocolHandler_QueryInterface,
844 ProtocolHandler_AddRef,
845 ProtocolHandler_Release,
846 ProtocolHandler_Start,
847 ProtocolHandler_Continue,
848 ProtocolHandler_Abort,
849 ProtocolHandler_Terminate,
850 ProtocolHandler_Suspend,
851 ProtocolHandler_Resume,
852 ProtocolHandler_Read,
853 ProtocolHandler_Seek,
854 ProtocolHandler_LockRequest,
855 ProtocolHandler_UnlockRequest,
856 ProtocolHandler_StartEx
859 #define BINDINFO_THIS(iface) DEFINE_THIS(BindProtocol, InternetBindInfo, iface)
861 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface,
862 REFIID riid, void **ppv)
864 BindProtocol *This = BINDINFO_THIS(iface);
865 return IInternetProtocolEx_QueryInterface(PROTOCOLEX(This), riid, ppv);
868 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
870 BindProtocol *This = BINDINFO_THIS(iface);
871 return IInternetProtocolEx_AddRef(PROTOCOLEX(This));
874 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
876 BindProtocol *This = BINDINFO_THIS(iface);
877 return IInternetProtocolEx_Release(PROTOCOLEX(This));
880 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface,
881 DWORD *grfBINDF, BINDINFO *pbindinfo)
883 BindProtocol *This = BINDINFO_THIS(iface);
884 HRESULT hres;
886 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
888 hres = IInternetBindInfo_GetBindInfo(This->bind_info, grfBINDF, pbindinfo);
889 if(FAILED(hres)) {
890 WARN("GetBindInfo failed: %08x\n", hres);
891 return hres;
894 *grfBINDF |= BINDF_FROMURLMON;
895 return hres;
898 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface,
899 ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
901 BindProtocol *This = BINDINFO_THIS(iface);
903 TRACE("(%p)->(%d %p %d %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched);
905 return IInternetBindInfo_GetBindString(This->bind_info, ulStringType, ppwzStr, cEl, pcElFetched);
908 #undef BINDFO_THIS
910 static const IInternetBindInfoVtbl InternetBindInfoVtbl = {
911 BindInfo_QueryInterface,
912 BindInfo_AddRef,
913 BindInfo_Release,
914 BindInfo_GetBindInfo,
915 BindInfo_GetBindString
918 #define PRIORITY_THIS(iface) DEFINE_THIS(BindProtocol, InternetPriority, iface)
920 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
921 REFIID riid, void **ppv)
923 BindProtocol *This = PRIORITY_THIS(iface);
924 return IInternetProtocolEx_QueryInterface(PROTOCOLEX(This), riid, ppv);
927 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
929 BindProtocol *This = PRIORITY_THIS(iface);
930 return IInternetProtocolEx_AddRef(PROTOCOLEX(This));
933 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
935 BindProtocol *This = PRIORITY_THIS(iface);
936 return IInternetProtocolEx_Release(PROTOCOLEX(This));
939 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
941 BindProtocol *This = PRIORITY_THIS(iface);
943 TRACE("(%p)->(%d)\n", This, nPriority);
945 This->priority = nPriority;
946 return S_OK;
949 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
951 BindProtocol *This = PRIORITY_THIS(iface);
953 TRACE("(%p)->(%p)\n", This, pnPriority);
955 *pnPriority = This->priority;
956 return S_OK;
959 #undef PRIORITY_THIS
961 static const IInternetPriorityVtbl InternetPriorityVtbl = {
962 InternetPriority_QueryInterface,
963 InternetPriority_AddRef,
964 InternetPriority_Release,
965 InternetPriority_SetPriority,
966 InternetPriority_GetPriority
970 #define PROTSINK_THIS(iface) DEFINE_THIS(BindProtocol, IInternetProtocolSink, iface)
972 static HRESULT WINAPI BPInternetProtocolSink_QueryInterface(IInternetProtocolSink *iface,
973 REFIID riid, void **ppv)
975 BindProtocol *This = PROTSINK_THIS(iface);
976 return IInternetProtocolEx_QueryInterface(PROTOCOLEX(This), riid, ppv);
979 static ULONG WINAPI BPInternetProtocolSink_AddRef(IInternetProtocolSink *iface)
981 BindProtocol *This = PROTSINK_THIS(iface);
982 return IInternetProtocolEx_AddRef(PROTOCOLEX(This));
985 static ULONG WINAPI BPInternetProtocolSink_Release(IInternetProtocolSink *iface)
987 BindProtocol *This = PROTSINK_THIS(iface);
988 return IInternetProtocolEx_Release(PROTOCOLEX(This));
991 typedef struct {
992 task_header_t header;
993 PROTOCOLDATA *data;
994 } switch_task_t;
996 static void switch_proc(BindProtocol *bind, task_header_t *t)
998 switch_task_t *task = (switch_task_t*)t;
1000 IInternetProtocol_Continue(bind->protocol_handler, task->data);
1002 heap_free(task);
1005 static HRESULT WINAPI BPInternetProtocolSink_Switch(IInternetProtocolSink *iface,
1006 PROTOCOLDATA *pProtocolData)
1008 BindProtocol *This = PROTSINK_THIS(iface);
1009 PROTOCOLDATA *data;
1011 TRACE("(%p)->(%p)\n", This, pProtocolData);
1013 TRACE("flags %x state %x data %p cb %u\n", pProtocolData->grfFlags, pProtocolData->dwState,
1014 pProtocolData->pData, pProtocolData->cbData);
1016 data = heap_alloc(sizeof(PROTOCOLDATA));
1017 if(!data)
1018 return E_OUTOFMEMORY;
1019 memcpy(data, pProtocolData, sizeof(PROTOCOLDATA));
1021 if(!do_direct_notif(This)) {
1022 switch_task_t *task;
1024 task = heap_alloc(sizeof(switch_task_t));
1025 if(!task)
1026 return E_OUTOFMEMORY;
1028 task->data = data;
1030 push_task(This, &task->header, switch_proc);
1031 return S_OK;
1034 if(!This->protocol_sink) {
1035 IInternetProtocol_Continue(This->protocol_handler, data);
1036 return S_OK;
1039 return IInternetProtocolSink_Switch(This->protocol_sink, data);
1042 static void report_progress(BindProtocol *This, ULONG status_code, LPCWSTR status_text)
1044 switch(status_code) {
1045 case BINDSTATUS_FINDINGRESOURCE:
1046 case BINDSTATUS_CONNECTING:
1047 case BINDSTATUS_REDIRECTING:
1048 case BINDSTATUS_BEGINDOWNLOADDATA:
1049 case BINDSTATUS_SENDINGREQUEST:
1050 case BINDSTATUS_CACHEFILENAMEAVAILABLE:
1051 case BINDSTATUS_DIRECTBIND:
1052 case BINDSTATUS_ACCEPTRANGES:
1053 if(This->protocol_sink)
1054 IInternetProtocolSink_ReportProgress(This->protocol_sink, status_code, status_text);
1055 break;
1057 case BINDSTATUS_MIMETYPEAVAILABLE:
1058 mime_available(This, status_text, FALSE);
1059 break;
1061 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
1062 mime_available(This, status_text, TRUE);
1063 break;
1065 default:
1066 FIXME("unsupported ulStatusCode %u\n", status_code);
1070 typedef struct {
1071 task_header_t header;
1073 ULONG status_code;
1074 LPWSTR status_text;
1075 } on_progress_task_t;
1077 static void on_progress_proc(BindProtocol *This, task_header_t *t)
1079 on_progress_task_t *task = (on_progress_task_t*)t;
1081 report_progress(This, task->status_code, task->status_text);
1083 heap_free(task->status_text);
1084 heap_free(task);
1087 static HRESULT WINAPI BPInternetProtocolSink_ReportProgress(IInternetProtocolSink *iface,
1088 ULONG ulStatusCode, LPCWSTR szStatusText)
1090 BindProtocol *This = PROTSINK_THIS(iface);
1092 TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
1094 if(do_direct_notif(This)) {
1095 report_progress(This, ulStatusCode, szStatusText);
1096 }else {
1097 on_progress_task_t *task;
1099 task = heap_alloc(sizeof(on_progress_task_t));
1101 task->status_code = ulStatusCode;
1102 task->status_text = heap_strdupW(szStatusText);
1104 push_task(This, &task->header, on_progress_proc);
1107 return S_OK;
1110 static HRESULT report_data(BindProtocol *This, DWORD bscf, ULONG progress, ULONG progress_max)
1112 if(!This->protocol_sink)
1113 return S_OK;
1115 if((This->pi & PI_MIMEVERIFICATION) && !This->reported_mime) {
1116 BYTE buf[BUFFER_SIZE];
1117 DWORD read = 0;
1118 LPWSTR mime;
1119 HRESULT hres;
1121 do {
1122 read = 0;
1123 hres = IInternetProtocol_Read(This->protocol, buf,
1124 sizeof(buf)-This->buf_size, &read);
1125 if(FAILED(hres) && hres != E_PENDING)
1126 return hres;
1128 if(!This->buf) {
1129 This->buf = heap_alloc(BUFFER_SIZE);
1130 if(!This->buf)
1131 return E_OUTOFMEMORY;
1132 }else if(read + This->buf_size > BUFFER_SIZE) {
1133 BYTE *tmp;
1135 tmp = heap_realloc(This->buf, read+This->buf_size);
1136 if(!tmp)
1137 return E_OUTOFMEMORY;
1138 This->buf = tmp;
1141 memcpy(This->buf+This->buf_size, buf, read);
1142 This->buf_size += read;
1143 }while(This->buf_size < MIME_TEST_SIZE && hres == S_OK);
1145 if(This->buf_size < MIME_TEST_SIZE && hres != S_FALSE)
1146 return S_OK;
1148 bscf = BSCF_FIRSTDATANOTIFICATION;
1149 if(hres == S_FALSE)
1150 bscf |= BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE;
1152 if(!This->reported_mime) {
1153 BSTR raw_uri;
1155 hres = IUri_GetRawUri(This->uri, &raw_uri);
1156 if(FAILED(hres))
1157 return hres;
1159 hres = FindMimeFromData(NULL, raw_uri, This->buf, min(This->buf_size, MIME_TEST_SIZE),
1160 This->mime, 0, &mime, 0);
1161 SysFreeString(raw_uri);
1162 if(FAILED(hres))
1163 return hres;
1165 mime_available(This, mime, TRUE);
1166 CoTaskMemFree(mime);
1170 if(!This->protocol_sink)
1171 return S_OK;
1173 return IInternetProtocolSink_ReportData(This->protocol_sink, bscf, progress, progress_max);
1176 typedef struct {
1177 task_header_t header;
1178 DWORD bscf;
1179 ULONG progress;
1180 ULONG progress_max;
1181 } report_data_task_t;
1183 static void report_data_proc(BindProtocol *This, task_header_t *t)
1185 report_data_task_t *task = (report_data_task_t*)t;
1187 report_data(This, task->bscf, task->progress, task->progress_max);
1188 heap_free(task);
1191 static HRESULT WINAPI BPInternetProtocolSink_ReportData(IInternetProtocolSink *iface,
1192 DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax)
1194 BindProtocol *This = PROTSINK_THIS(iface);
1196 TRACE("(%p)->(%d %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
1198 if(!This->protocol_sink)
1199 return S_OK;
1201 if(!do_direct_notif(This)) {
1202 report_data_task_t *task;
1204 task = heap_alloc(sizeof(report_data_task_t));
1205 if(!task)
1206 return E_OUTOFMEMORY;
1208 task->bscf = grfBSCF;
1209 task->progress = ulProgress;
1210 task->progress_max = ulProgressMax;
1212 push_task(This, &task->header, report_data_proc);
1213 return S_OK;
1216 return report_data(This, grfBSCF, ulProgress, ulProgressMax);
1219 typedef struct {
1220 task_header_t header;
1222 HRESULT hres;
1223 DWORD err;
1224 LPWSTR str;
1225 } report_result_task_t;
1227 static void report_result_proc(BindProtocol *This, task_header_t *t)
1229 report_result_task_t *task = (report_result_task_t*)t;
1231 if(This->protocol_sink)
1232 IInternetProtocolSink_ReportResult(This->protocol_sink, task->hres, task->err, task->str);
1234 heap_free(task->str);
1235 heap_free(task);
1238 static HRESULT WINAPI BPInternetProtocolSink_ReportResult(IInternetProtocolSink *iface,
1239 HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
1241 BindProtocol *This = PROTSINK_THIS(iface);
1243 TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
1245 if(!This->protocol_sink)
1246 return E_FAIL;
1248 This->reported_result = TRUE;
1250 if(!do_direct_notif(This)) {
1251 report_result_task_t *task;
1253 task = heap_alloc(sizeof(report_result_task_t));
1254 if(!task)
1255 return E_OUTOFMEMORY;
1257 task->hres = hrResult;
1258 task->err = dwError;
1259 task->str = heap_strdupW(szResult);
1261 push_task(This, &task->header, report_result_proc);
1262 return S_OK;
1265 return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
1268 #undef PROTSINK_THIS
1270 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = {
1271 BPInternetProtocolSink_QueryInterface,
1272 BPInternetProtocolSink_AddRef,
1273 BPInternetProtocolSink_Release,
1274 BPInternetProtocolSink_Switch,
1275 BPInternetProtocolSink_ReportProgress,
1276 BPInternetProtocolSink_ReportData,
1277 BPInternetProtocolSink_ReportResult
1280 #define INETINFO_THIS(iface) DEFINE_THIS(BindProtocol, IWinInetHttpInfo, iface)
1282 static HRESULT WINAPI WinInetHttpInfo_QueryInterface(IWinInetHttpInfo *iface, REFIID riid, void **ppv)
1284 BindProtocol *This = INETINFO_THIS(iface);
1285 return IInternetProtocolEx_QueryInterface(PROTOCOLEX(This), riid, ppv);
1288 static ULONG WINAPI WinInetHttpInfo_AddRef(IWinInetHttpInfo *iface)
1290 BindProtocol *This = INETINFO_THIS(iface);
1291 return IInternetProtocolEx_AddRef(PROTOCOLEX(This));
1294 static ULONG WINAPI WinInetHttpInfo_Release(IWinInetHttpInfo *iface)
1296 BindProtocol *This = INETINFO_THIS(iface);
1297 return IInternetProtocolEx_Release(PROTOCOLEX(This));
1300 static HRESULT WINAPI WinInetHttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD dwOption,
1301 void *pBuffer, DWORD *pcbBuffer)
1303 BindProtocol *This = INETINFO_THIS(iface);
1304 FIXME("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer);
1305 return E_NOTIMPL;
1308 static HRESULT WINAPI WinInetHttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption,
1309 void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved)
1311 BindProtocol *This = INETINFO_THIS(iface);
1312 FIXME("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved);
1313 return E_NOTIMPL;
1316 #undef INETINFO_THIS
1318 static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = {
1319 WinInetHttpInfo_QueryInterface,
1320 WinInetHttpInfo_AddRef,
1321 WinInetHttpInfo_Release,
1322 WinInetHttpInfo_QueryOption,
1323 WinInetHttpInfo_QueryInfo
1326 #define SERVPROV_THIS(iface) DEFINE_THIS(BindProtocol, ServiceProvider, iface)
1328 static HRESULT WINAPI BPServiceProvider_QueryInterface(IServiceProvider *iface,
1329 REFIID riid, void **ppv)
1331 BindProtocol *This = SERVPROV_THIS(iface);
1332 return IInternetProtocolEx_QueryInterface(PROTOCOLEX(This), riid, ppv);
1335 static ULONG WINAPI BPServiceProvider_AddRef(IServiceProvider *iface)
1337 BindProtocol *This = SERVPROV_THIS(iface);
1338 return IInternetProtocolEx_AddRef(PROTOCOLEX(This));
1341 static ULONG WINAPI BPServiceProvider_Release(IServiceProvider *iface)
1343 BindProtocol *This = SERVPROV_THIS(iface);
1344 return IInternetProtocolEx_Release(PROTOCOLEX(This));
1347 static HRESULT WINAPI BPServiceProvider_QueryService(IServiceProvider *iface,
1348 REFGUID guidService, REFIID riid, void **ppv)
1350 BindProtocol *This = SERVPROV_THIS(iface);
1352 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
1354 if(!This->service_provider)
1355 return E_NOINTERFACE;
1357 return IServiceProvider_QueryService(This->service_provider, guidService, riid, ppv);
1360 #undef SERVPROV_THIS
1362 static const IServiceProviderVtbl ServiceProviderVtbl = {
1363 BPServiceProvider_QueryInterface,
1364 BPServiceProvider_AddRef,
1365 BPServiceProvider_Release,
1366 BPServiceProvider_QueryService
1369 HRESULT create_binding_protocol(LPCWSTR url, BOOL from_urlmon, IInternetProtocol **protocol)
1371 BindProtocol *ret = heap_alloc_zero(sizeof(BindProtocol));
1373 ret->lpIInternetProtocolExVtbl = &BindProtocolVtbl;
1374 ret->lpInternetBindInfoVtbl = &InternetBindInfoVtbl;
1375 ret->lpInternetPriorityVtbl = &InternetPriorityVtbl;
1376 ret->lpServiceProviderVtbl = &ServiceProviderVtbl;
1377 ret->lpIInternetProtocolSinkVtbl = &InternetProtocolSinkVtbl;
1378 ret->lpIInternetProtocolHandlerVtbl = &InternetProtocolHandlerVtbl;
1379 ret->lpIWinInetHttpInfoVtbl = &WinInetHttpInfoVtbl;
1381 ret->ref = 1;
1382 ret->from_urlmon = from_urlmon;
1383 ret->apartment_thread = GetCurrentThreadId();
1384 ret->notif_hwnd = get_notif_hwnd();
1385 ret->protocol_handler = (IInternetProtocol*)PROTOCOLHANDLER(ret);
1386 InitializeCriticalSection(&ret->section);
1388 URLMON_LockModule();
1390 *protocol = (IInternetProtocol*)PROTOCOLEX(ret);
1391 return S_OK;