urlmon: Release previously set URI in BindProtocol::StartEx.
[wine.git] / dlls / urlmon / bindprot.c
bloba4399ab93f3b53f24caa65333640b41f7e786e02
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 void (*task_proc_t)(BindProtocol*,task_header_t*);
26 struct _task_header_t {
27 task_proc_t proc;
28 task_header_t *next;
31 #define BUFFER_SIZE 2048
32 #define MIME_TEST_SIZE 255
34 #define WM_MK_CONTINUE (WM_USER+101)
35 #define WM_MK_RELEASE (WM_USER+102)
37 static void process_tasks(BindProtocol *This)
39 task_header_t *task;
41 while(1) {
42 EnterCriticalSection(&This->section);
44 task = This->task_queue_head;
45 if(task) {
46 This->task_queue_head = task->next;
47 if(!This->task_queue_head)
48 This->task_queue_tail = NULL;
51 LeaveCriticalSection(&This->section);
53 if(!task)
54 break;
56 This->continue_call++;
57 task->proc(This, task);
58 This->continue_call--;
62 static LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
64 switch(msg) {
65 case WM_MK_CONTINUE: {
66 BindProtocol *This = (BindProtocol*)lParam;
68 process_tasks(This);
70 IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
71 return 0;
73 case WM_MK_RELEASE: {
74 tls_data_t *data = get_tls_data();
76 if(!--data->notif_hwnd_cnt) {
77 DestroyWindow(hwnd);
78 data->notif_hwnd = NULL;
83 return DefWindowProcW(hwnd, msg, wParam, lParam);
86 static const WCHAR wszURLMonikerNotificationWindow[] =
87 {'U','R','L',' ','M','o','n','i','k','e','r',' ',
88 'N','o','t','i','f','i','c','a','t','i','o','n',' ','W','i','n','d','o','w',0};
90 static ATOM notif_wnd_class;
92 static BOOL WINAPI register_notif_wnd_class(INIT_ONCE *once, void *param, void **context)
94 static WNDCLASSEXW wndclass = {
95 sizeof(wndclass), 0, notif_wnd_proc, 0, 0,
96 NULL, NULL, NULL, NULL, NULL,
97 wszURLMonikerNotificationWindow, NULL
100 wndclass.hInstance = hProxyDll;
101 notif_wnd_class = RegisterClassExW(&wndclass);
102 return TRUE;
105 void unregister_notif_wnd_class(void)
107 if(notif_wnd_class)
108 UnregisterClassW(MAKEINTRESOURCEW(notif_wnd_class), hProxyDll);
111 HWND get_notif_hwnd(void)
113 tls_data_t *tls_data;
115 static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
117 tls_data = get_tls_data();
118 if(!tls_data)
119 return NULL;
121 if(tls_data->notif_hwnd_cnt) {
122 tls_data->notif_hwnd_cnt++;
123 return tls_data->notif_hwnd;
126 InitOnceExecuteOnce(&init_once, register_notif_wnd_class, NULL, NULL);
127 if(!notif_wnd_class)
128 return NULL;
130 tls_data->notif_hwnd = CreateWindowExW(0, MAKEINTRESOURCEW(notif_wnd_class),
131 wszURLMonikerNotificationWindow, 0, 0, 0, 0, 0, HWND_MESSAGE,
132 NULL, hProxyDll, NULL);
133 if(tls_data->notif_hwnd)
134 tls_data->notif_hwnd_cnt++;
136 TRACE("hwnd = %p\n", tls_data->notif_hwnd);
138 return tls_data->notif_hwnd;
141 void release_notif_hwnd(HWND hwnd)
143 tls_data_t *data = get_tls_data();
145 if(!data)
146 return;
148 if(data->notif_hwnd != hwnd) {
149 PostMessageW(data->notif_hwnd, WM_MK_RELEASE, 0, 0);
150 return;
153 if(!--data->notif_hwnd_cnt) {
154 DestroyWindow(data->notif_hwnd);
155 data->notif_hwnd = NULL;
159 static void push_task(BindProtocol *This, task_header_t *task, task_proc_t proc)
161 BOOL do_post = FALSE;
163 task->proc = proc;
164 task->next = NULL;
166 EnterCriticalSection(&This->section);
168 if(This->task_queue_tail) {
169 This->task_queue_tail->next = task;
170 This->task_queue_tail = task;
171 }else {
172 This->task_queue_tail = This->task_queue_head = task;
173 do_post = !This->continue_call;
176 LeaveCriticalSection(&This->section);
178 if(do_post) {
179 IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
180 PostMessageW(This->notif_hwnd, WM_MK_CONTINUE, 0, (LPARAM)This);
184 static inline BOOL is_apartment_thread(BindProtocol *This)
186 return This->apartment_thread == GetCurrentThreadId();
189 static inline BOOL do_direct_notif(BindProtocol *This)
191 return !(This->pi & PI_APARTMENTTHREADED) || (is_apartment_thread(This) && !This->continue_call);
194 static HRESULT handle_mime_filter(BindProtocol *This, IInternetProtocol *mime_filter)
196 PROTOCOLFILTERDATA filter_data = { sizeof(PROTOCOLFILTERDATA), NULL, NULL, NULL, 0 };
197 HRESULT hres;
199 hres = IInternetProtocol_QueryInterface(mime_filter, &IID_IInternetProtocolSink, (void**)&This->protocol_sink_handler);
200 if(FAILED(hres)) {
201 This->protocol_sink_handler = &This->default_protocol_handler.IInternetProtocolSink_iface;
202 return hres;
205 IInternetProtocol_AddRef(mime_filter);
206 This->protocol_handler = mime_filter;
208 filter_data.pProtocol = &This->default_protocol_handler.IInternetProtocol_iface;
209 hres = IInternetProtocol_Start(mime_filter, This->mime, &This->default_protocol_handler.IInternetProtocolSink_iface,
210 &This->IInternetBindInfo_iface, PI_FILTER_MODE|PI_FORCE_ASYNC,
211 (HANDLE_PTR)&filter_data);
212 if(FAILED(hres)) {
213 IInternetProtocolSink_Release(This->protocol_sink_handler);
214 IInternetProtocol_Release(This->protocol_handler);
215 This->protocol_sink_handler = &This->default_protocol_handler.IInternetProtocolSink_iface;
216 This->protocol_handler = &This->default_protocol_handler.IInternetProtocol_iface;
217 return hres;
220 /* NOTE: IE9 calls it on the new protocol_sink. It doesn't make sense so it seems to be a bug there. */
221 IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_LOADINGMIMEHANDLER, NULL);
223 return S_OK;
226 static void mime_available(BindProtocol *This, LPCWSTR mime, BOOL verified)
228 IInternetProtocol *mime_filter;
229 HRESULT hres;
231 heap_free(This->mime);
232 This->mime = heap_strdupW(mime);
234 if(This->protocol_handler==&This->default_protocol_handler.IInternetProtocol_iface
235 && (mime_filter = get_mime_filter(mime))) {
236 TRACE("Got mime filter for %s\n", debugstr_w(mime));
238 hres = handle_mime_filter(This, mime_filter);
239 IInternetProtocol_Release(mime_filter);
240 if(FAILED(hres))
241 FIXME("MIME filter failed: %08x\n", hres);
244 if(This->reported_mime || verified || !(This->pi & PI_MIMEVERIFICATION)) {
245 This->reported_mime = TRUE;
246 IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, mime);
250 static inline BindProtocol *impl_from_IInternetProtocolEx(IInternetProtocolEx *iface)
252 return CONTAINING_RECORD(iface, BindProtocol, IInternetProtocolEx_iface);
255 static HRESULT WINAPI BindProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
257 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
259 *ppv = NULL;
260 if(IsEqualGUID(&IID_IUnknown, riid)) {
261 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
262 *ppv = &This->IInternetProtocolEx_iface;
263 }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
264 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
265 *ppv = &This->IInternetProtocolEx_iface;
266 }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
267 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
268 *ppv = &This->IInternetProtocolEx_iface;
269 }else if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) {
270 TRACE("(%p)->(IID_IInternetProtocolEx %p)\n", This, ppv);
271 *ppv = &This->IInternetProtocolEx_iface;
272 }else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) {
273 TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This, ppv);
274 *ppv = &This->IInternetBindInfo_iface;
275 }else if(IsEqualGUID(&IID_IInternetPriority, riid)) {
276 TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv);
277 *ppv = &This->IInternetPriority_iface;
278 }else if(IsEqualGUID(&IID_IAuthenticate, riid)) {
279 FIXME("(%p)->(IID_IAuthenticate %p)\n", This, ppv);
280 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
281 TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
282 *ppv = &This->IServiceProvider_iface;
283 }else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
284 TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
285 *ppv = &This->IInternetProtocolSink_iface;
286 }else if(IsEqualGUID(&IID_IWinInetInfo, riid)) {
287 TRACE("(%p)->(IID_IWinInetInfo %p)\n", This, ppv);
289 if(This->protocol) {
290 IWinInetInfo *inet_info;
291 HRESULT hres;
293 hres = IInternetProtocol_QueryInterface(This->protocol, &IID_IWinInetInfo, (void**)&inet_info);
294 if(SUCCEEDED(hres)) {
295 *ppv = &This->IWinInetHttpInfo_iface;
296 IWinInetInfo_Release(inet_info);
299 }else if(IsEqualGUID(&IID_IWinInetHttpInfo, riid)) {
300 TRACE("(%p)->(IID_IWinInetHttpInfo %p)\n", This, ppv);
302 if(This->protocol) {
303 IWinInetHttpInfo *http_info;
304 HRESULT hres;
306 hres = IInternetProtocol_QueryInterface(This->protocol, &IID_IWinInetHttpInfo, (void**)&http_info);
307 if(SUCCEEDED(hres)) {
308 *ppv = &This->IWinInetHttpInfo_iface;
309 IWinInetHttpInfo_Release(http_info);
312 }else {
313 WARN("not supported interface %s\n", debugstr_guid(riid));
316 if(!*ppv)
317 return E_NOINTERFACE;
319 IUnknown_AddRef((IUnknown*)*ppv);
320 return S_OK;
323 static ULONG WINAPI BindProtocol_AddRef(IInternetProtocolEx *iface)
325 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
326 LONG ref = InterlockedIncrement(&This->ref);
327 TRACE("(%p) ref=%d\n", This, ref);
328 return ref;
331 static ULONG WINAPI BindProtocol_Release(IInternetProtocolEx *iface)
333 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
334 LONG ref = InterlockedDecrement(&This->ref);
336 TRACE("(%p) ref=%d\n", This, ref);
338 if(!ref) {
339 if(This->wininet_info)
340 IWinInetInfo_Release(This->wininet_info);
341 if(This->wininet_http_info)
342 IWinInetHttpInfo_Release(This->wininet_http_info);
343 if(This->protocol)
344 IInternetProtocol_Release(This->protocol);
345 if(This->bind_info)
346 IInternetBindInfo_Release(This->bind_info);
347 if(This->protocol_handler && This->protocol_handler != &This->default_protocol_handler.IInternetProtocol_iface)
348 IInternetProtocol_Release(This->protocol_handler);
349 if(This->protocol_sink_handler &&
350 This->protocol_sink_handler != &This->default_protocol_handler.IInternetProtocolSink_iface)
351 IInternetProtocolSink_Release(This->protocol_sink_handler);
352 if(This->uri)
353 IUri_Release(This->uri);
354 SysFreeString(This->display_uri);
356 set_binding_sink(This, NULL, NULL);
358 if(This->notif_hwnd)
359 release_notif_hwnd(This->notif_hwnd);
360 This->section.DebugInfo->Spare[0] = 0;
361 DeleteCriticalSection(&This->section);
363 heap_free(This->mime);
364 heap_free(This);
366 URLMON_UnlockModule();
369 return ref;
372 static HRESULT WINAPI BindProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
373 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
374 DWORD grfPI, HANDLE_PTR dwReserved)
376 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
377 IUri *uri;
378 HRESULT hres;
380 TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
381 pOIBindInfo, grfPI, dwReserved);
383 hres = CreateUri(szUrl, Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri);
384 if(FAILED(hres))
385 return hres;
387 hres = IInternetProtocolEx_StartEx(&This->IInternetProtocolEx_iface, uri, pOIProtSink,
388 pOIBindInfo, grfPI, (HANDLE*)dwReserved);
390 IUri_Release(uri);
391 return hres;
394 static HRESULT WINAPI BindProtocol_Continue(IInternetProtocolEx *iface, PROTOCOLDATA *pProtocolData)
396 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
398 TRACE("(%p)->(%p)\n", This, pProtocolData);
400 return IInternetProtocol_Continue(This->protocol_handler, pProtocolData);
403 static HRESULT WINAPI BindProtocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason,
404 DWORD dwOptions)
406 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
408 TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
410 return IInternetProtocol_Abort(This->protocol_handler, hrReason, dwOptions);
413 static HRESULT WINAPI BindProtocol_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
415 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
417 TRACE("(%p)->(%08x)\n", This, dwOptions);
419 return IInternetProtocol_Terminate(This->protocol_handler, dwOptions);
422 static HRESULT WINAPI BindProtocol_Suspend(IInternetProtocolEx *iface)
424 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
425 FIXME("(%p)\n", This);
426 return E_NOTIMPL;
429 static HRESULT WINAPI BindProtocol_Resume(IInternetProtocolEx *iface)
431 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
432 FIXME("(%p)\n", This);
433 return E_NOTIMPL;
436 static HRESULT WINAPI BindProtocol_Read(IInternetProtocolEx *iface, void *pv,
437 ULONG cb, ULONG *pcbRead)
439 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
441 TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
443 if(pcbRead)
444 *pcbRead = 0;
445 return IInternetProtocol_Read(This->protocol_handler, pv, cb, pcbRead);
448 static HRESULT WINAPI BindProtocol_Seek(IInternetProtocolEx *iface, LARGE_INTEGER dlibMove,
449 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
451 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
452 FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
453 return E_NOTIMPL;
456 static HRESULT WINAPI BindProtocol_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
458 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
460 TRACE("(%p)->(%08x)\n", This, dwOptions);
462 return IInternetProtocol_LockRequest(This->protocol_handler, dwOptions);
465 static HRESULT WINAPI BindProtocol_UnlockRequest(IInternetProtocolEx *iface)
467 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
469 TRACE("(%p)\n", This);
471 return IInternetProtocol_UnlockRequest(This->protocol_handler);
474 static HRESULT WINAPI BindProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUri,
475 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
476 DWORD grfPI, HANDLE *dwReserved)
478 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
479 IInternetProtocol *protocol = NULL;
480 IInternetProtocolEx *protocolex;
481 IInternetPriority *priority;
482 IServiceProvider *service_provider;
483 BOOL urlmon_protocol = FALSE;
484 CLSID clsid = IID_NULL;
485 LPOLESTR clsid_str;
486 HRESULT hres;
488 TRACE("(%p)->(%p %p %p %08x %p)\n", This, pUri, pOIProtSink, pOIBindInfo, grfPI, dwReserved);
490 if(!pUri || !pOIProtSink || !pOIBindInfo)
491 return E_INVALIDARG;
493 This->pi = grfPI;
495 if(This->uri) {
496 if(This->display_uri)
497 SysFreeString(This->display_uri);
498 IUri_Release(This->uri);
500 IUri_AddRef(pUri);
501 This->uri = pUri;
503 hres = IInternetProtocolSink_QueryInterface(pOIProtSink, &IID_IServiceProvider,
504 (void**)&service_provider);
505 if(SUCCEEDED(hres)) {
506 /* FIXME: What's protocol CLSID here? */
507 IServiceProvider_QueryService(service_provider, &IID_IInternetProtocol,
508 &IID_IInternetProtocol, (void**)&protocol);
509 IServiceProvider_Release(service_provider);
512 if(!protocol) {
513 IClassFactory *cf;
514 IUnknown *unk;
516 hres = get_protocol_handler(pUri, &clsid, &urlmon_protocol, &cf);
517 if(FAILED(hres))
518 return hres;
520 if(This->from_urlmon) {
521 hres = IClassFactory_CreateInstance(cf, NULL, &IID_IInternetProtocol, (void**)&protocol);
522 IClassFactory_Release(cf);
523 if(FAILED(hres))
524 return hres;
525 }else {
526 hres = IClassFactory_CreateInstance(cf, (IUnknown*)&This->IInternetBindInfo_iface,
527 &IID_IUnknown, (void**)&unk);
528 IClassFactory_Release(cf);
529 if(FAILED(hres))
530 return hres;
532 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocol, (void**)&protocol);
533 IUnknown_Release(unk);
534 if(FAILED(hres))
535 return hres;
539 StringFromCLSID(&clsid, &clsid_str);
540 IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_PROTOCOLCLASSID, clsid_str);
541 CoTaskMemFree(clsid_str);
543 This->protocol = protocol;
545 if(urlmon_protocol) {
546 IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&This->wininet_info);
547 IInternetProtocol_QueryInterface(protocol, &IID_IWinInetHttpInfo, (void**)&This->wininet_http_info);
550 set_binding_sink(This, pOIProtSink, pOIBindInfo);
552 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
553 if(SUCCEEDED(hres)) {
554 IInternetPriority_SetPriority(priority, This->priority);
555 IInternetPriority_Release(priority);
558 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolEx, (void**)&protocolex);
559 if(SUCCEEDED(hres)) {
560 hres = IInternetProtocolEx_StartEx(protocolex, pUri, &This->IInternetProtocolSink_iface,
561 &This->IInternetBindInfo_iface, 0, NULL);
562 IInternetProtocolEx_Release(protocolex);
563 }else {
564 hres = IUri_GetDisplayUri(pUri, &This->display_uri);
565 if(FAILED(hres))
566 return hres;
568 hres = IInternetProtocol_Start(protocol, This->display_uri, &This->IInternetProtocolSink_iface,
569 &This->IInternetBindInfo_iface, 0, 0);
572 if(SUCCEEDED(hres))
573 process_tasks(This);
574 return hres;
577 void set_binding_sink(BindProtocol *This, IInternetProtocolSink *sink, IInternetBindInfo *bind_info)
579 IInternetProtocolSink *prev_sink;
580 IServiceProvider *service_provider = NULL;
582 if(sink)
583 IInternetProtocolSink_AddRef(sink);
584 prev_sink = InterlockedExchangePointer((void**)&This->protocol_sink, sink);
585 if(prev_sink)
586 IInternetProtocolSink_Release(prev_sink);
588 if(sink)
589 IInternetProtocolSink_QueryInterface(sink, &IID_IServiceProvider, (void**)&service_provider);
590 service_provider = InterlockedExchangePointer((void**)&This->service_provider, service_provider);
591 if(service_provider)
592 IServiceProvider_Release(service_provider);
594 if(bind_info)
595 IInternetBindInfo_AddRef(bind_info);
596 bind_info = InterlockedExchangePointer((void**)&This->bind_info, bind_info);
597 if(bind_info)
598 IInternetBindInfo_Release(bind_info);
601 static const IInternetProtocolExVtbl BindProtocolVtbl = {
602 BindProtocol_QueryInterface,
603 BindProtocol_AddRef,
604 BindProtocol_Release,
605 BindProtocol_Start,
606 BindProtocol_Continue,
607 BindProtocol_Abort,
608 BindProtocol_Terminate,
609 BindProtocol_Suspend,
610 BindProtocol_Resume,
611 BindProtocol_Read,
612 BindProtocol_Seek,
613 BindProtocol_LockRequest,
614 BindProtocol_UnlockRequest,
615 BindProtocol_StartEx
618 static inline BindProtocol *impl_from_IInternetProtocol(IInternetProtocol *iface)
620 return CONTAINING_RECORD(iface, BindProtocol, default_protocol_handler.IInternetProtocol_iface);
623 static HRESULT WINAPI ProtocolHandler_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
625 BindProtocol *This = impl_from_IInternetProtocol(iface);
627 *ppv = NULL;
628 if(IsEqualGUID(&IID_IUnknown, riid)) {
629 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
630 *ppv = &This->default_protocol_handler.IInternetProtocol_iface;
631 }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
632 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
633 *ppv = &This->default_protocol_handler.IInternetProtocol_iface;
634 }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
635 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
636 *ppv = &This->default_protocol_handler.IInternetProtocol_iface;
637 }else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
638 TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
639 *ppv = &This->default_protocol_handler.IInternetProtocolSink_iface;
642 if(*ppv) {
643 IInternetProtocol_AddRef(iface);
644 return S_OK;
647 WARN("not supported interface %s\n", debugstr_guid(riid));
648 return E_NOINTERFACE;
651 static ULONG WINAPI ProtocolHandler_AddRef(IInternetProtocol *iface)
653 BindProtocol *This = impl_from_IInternetProtocol(iface);
654 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
657 static ULONG WINAPI ProtocolHandler_Release(IInternetProtocol *iface)
659 BindProtocol *This = impl_from_IInternetProtocol(iface);
660 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
663 static HRESULT WINAPI ProtocolHandler_Start(IInternetProtocol *iface, LPCWSTR szUrl,
664 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
665 DWORD grfPI, HANDLE_PTR dwReserved)
667 ERR("Should not be called\n");
668 return E_NOTIMPL;
671 static HRESULT WINAPI ProtocolHandler_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
673 BindProtocol *This = impl_from_IInternetProtocol(iface);
674 HRESULT hres;
676 TRACE("(%p)->(%p)\n", This, pProtocolData);
678 hres = IInternetProtocol_Continue(This->protocol, pProtocolData);
680 heap_free(pProtocolData);
681 return hres;
684 static HRESULT WINAPI ProtocolHandler_Abort(IInternetProtocol *iface, HRESULT hrReason,
685 DWORD dwOptions)
687 BindProtocol *This = impl_from_IInternetProtocol(iface);
689 TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
691 if(This->protocol && !This->reported_result)
692 return IInternetProtocol_Abort(This->protocol, hrReason, dwOptions);
694 return S_OK;
697 static HRESULT WINAPI ProtocolHandler_Terminate(IInternetProtocol *iface, DWORD dwOptions)
699 BindProtocol *This = impl_from_IInternetProtocol(iface);
701 TRACE("(%p)->(%08x)\n", This, dwOptions);
703 if(!This->reported_result)
704 return E_FAIL;
706 /* This may get released in Terminate call. */
707 IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
709 IInternetProtocol_Terminate(This->protocol, 0);
711 set_binding_sink(This, NULL, NULL);
713 if(This->bind_info) {
714 IInternetBindInfo_Release(This->bind_info);
715 This->bind_info = NULL;
718 IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
719 return S_OK;
722 static HRESULT WINAPI ProtocolHandler_Suspend(IInternetProtocol *iface)
724 BindProtocol *This = impl_from_IInternetProtocol(iface);
725 FIXME("(%p)\n", This);
726 return E_NOTIMPL;
729 static HRESULT WINAPI ProtocolHandler_Resume(IInternetProtocol *iface)
731 BindProtocol *This = impl_from_IInternetProtocol(iface);
732 FIXME("(%p)\n", This);
733 return E_NOTIMPL;
736 static HRESULT WINAPI ProtocolHandler_Read(IInternetProtocol *iface, void *pv,
737 ULONG cb, ULONG *pcbRead)
739 BindProtocol *This = impl_from_IInternetProtocol(iface);
740 ULONG read = 0;
741 HRESULT hres = S_OK;
743 TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
745 if(This->buf_size) {
746 read = min(cb, This->buf_size);
747 memcpy(pv, This->buf, read);
749 if(read == This->buf_size) {
750 heap_free(This->buf);
751 This->buf = NULL;
752 }else {
753 memmove(This->buf, This->buf+cb, This->buf_size-cb);
756 This->buf_size -= read;
759 if(read < cb) {
760 ULONG cread = 0;
762 if(is_apartment_thread(This))
763 This->continue_call++;
764 hres = IInternetProtocol_Read(This->protocol, (BYTE*)pv+read, cb-read, &cread);
765 if(is_apartment_thread(This))
766 This->continue_call--;
767 read += cread;
770 *pcbRead = read;
771 return hres;
774 static HRESULT WINAPI ProtocolHandler_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
775 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
777 BindProtocol *This = impl_from_IInternetProtocol(iface);
778 FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
779 return E_NOTIMPL;
782 static HRESULT WINAPI ProtocolHandler_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
784 BindProtocol *This = impl_from_IInternetProtocol(iface);
786 TRACE("(%p)->(%08x)\n", This, dwOptions);
788 return IInternetProtocol_LockRequest(This->protocol, dwOptions);
791 static HRESULT WINAPI ProtocolHandler_UnlockRequest(IInternetProtocol *iface)
793 BindProtocol *This = impl_from_IInternetProtocol(iface);
795 TRACE("(%p)\n", This);
797 return IInternetProtocol_UnlockRequest(This->protocol);
800 static const IInternetProtocolVtbl InternetProtocolHandlerVtbl = {
801 ProtocolHandler_QueryInterface,
802 ProtocolHandler_AddRef,
803 ProtocolHandler_Release,
804 ProtocolHandler_Start,
805 ProtocolHandler_Continue,
806 ProtocolHandler_Abort,
807 ProtocolHandler_Terminate,
808 ProtocolHandler_Suspend,
809 ProtocolHandler_Resume,
810 ProtocolHandler_Read,
811 ProtocolHandler_Seek,
812 ProtocolHandler_LockRequest,
813 ProtocolHandler_UnlockRequest
816 static inline BindProtocol *impl_from_IInternetProtocolSinkHandler(IInternetProtocolSink *iface)
818 return CONTAINING_RECORD(iface, BindProtocol, default_protocol_handler.IInternetProtocolSink_iface);
821 static HRESULT WINAPI ProtocolSinkHandler_QueryInterface(IInternetProtocolSink *iface,
822 REFIID riid, void **ppvObject)
824 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
825 return IInternetProtocol_QueryInterface(&This->default_protocol_handler.IInternetProtocol_iface,
826 riid, ppvObject);
829 static ULONG WINAPI ProtocolSinkHandler_AddRef(IInternetProtocolSink *iface)
831 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
832 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
835 static ULONG WINAPI ProtocolSinkHandler_Release(IInternetProtocolSink *iface)
837 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
838 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
841 static HRESULT WINAPI ProtocolSinkHandler_Switch(IInternetProtocolSink *iface,
842 PROTOCOLDATA *pProtocolData)
844 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
846 TRACE("(%p)->(%p)\n", This, pProtocolData);
848 if(!This->protocol_sink) {
849 IInternetProtocol_Continue(This->protocol_handler, pProtocolData);
850 return S_OK;
853 return IInternetProtocolSink_Switch(This->protocol_sink, pProtocolData);
856 static HRESULT WINAPI ProtocolSinkHandler_ReportProgress(IInternetProtocolSink *iface,
857 ULONG status_code, LPCWSTR status_text)
859 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
861 TRACE("(%p)->(%s %s)\n", This, debugstr_bindstatus(status_code), debugstr_w(status_text));
863 if(!This->protocol_sink)
864 return S_OK;
866 switch(status_code) {
867 case BINDSTATUS_FINDINGRESOURCE:
868 case BINDSTATUS_CONNECTING:
869 case BINDSTATUS_REDIRECTING:
870 case BINDSTATUS_SENDINGREQUEST:
871 case BINDSTATUS_CACHEFILENAMEAVAILABLE:
872 case BINDSTATUS_DIRECTBIND:
873 case BINDSTATUS_ACCEPTRANGES:
874 case BINDSTATUS_DECODING:
875 IInternetProtocolSink_ReportProgress(This->protocol_sink, status_code, status_text);
876 break;
878 case BINDSTATUS_BEGINDOWNLOADDATA:
879 IInternetProtocolSink_ReportData(This->protocol_sink, This->bscf, This->progress, This->progress_max);
880 break;
882 case BINDSTATUS_MIMETYPEAVAILABLE:
883 mime_available(This, status_text, FALSE);
884 break;
886 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
887 mime_available(This, status_text, TRUE);
888 break;
890 default:
891 FIXME("unsupported ulStatusCode %u\n", status_code);
894 return S_OK;
897 static HRESULT WINAPI ProtocolSinkHandler_ReportData(IInternetProtocolSink *iface,
898 DWORD bscf, ULONG progress, ULONG progress_max)
900 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
902 TRACE("(%p)->(%x %u %u)\n", This, bscf, progress, progress_max);
904 This->bscf = bscf;
905 This->progress = progress;
906 This->progress_max = progress_max;
908 if(!This->protocol_sink)
909 return S_OK;
911 if((This->pi & PI_MIMEVERIFICATION) && !This->reported_mime) {
912 BYTE buf[BUFFER_SIZE];
913 DWORD read = 0;
914 LPWSTR mime;
915 HRESULT hres;
917 do {
918 read = 0;
919 if(is_apartment_thread(This))
920 This->continue_call++;
921 hres = IInternetProtocol_Read(This->protocol, buf,
922 sizeof(buf)-This->buf_size, &read);
923 if(is_apartment_thread(This))
924 This->continue_call--;
925 if(FAILED(hres) && hres != E_PENDING)
926 return hres;
928 if(!This->buf) {
929 This->buf = heap_alloc(BUFFER_SIZE);
930 if(!This->buf)
931 return E_OUTOFMEMORY;
932 }else if(read + This->buf_size > BUFFER_SIZE) {
933 BYTE *tmp;
935 tmp = heap_realloc(This->buf, read+This->buf_size);
936 if(!tmp)
937 return E_OUTOFMEMORY;
938 This->buf = tmp;
941 memcpy(This->buf+This->buf_size, buf, read);
942 This->buf_size += read;
943 }while(This->buf_size < MIME_TEST_SIZE && hres == S_OK);
945 if(This->buf_size < MIME_TEST_SIZE && hres != S_FALSE)
946 return S_OK;
948 bscf = BSCF_FIRSTDATANOTIFICATION;
949 if(hres == S_FALSE)
950 bscf |= BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE;
952 if(!This->reported_mime) {
953 BSTR raw_uri;
955 hres = IUri_GetRawUri(This->uri, &raw_uri);
956 if(FAILED(hres))
957 return hres;
959 hres = FindMimeFromData(NULL, raw_uri, This->buf, min(This->buf_size, MIME_TEST_SIZE),
960 This->mime, 0, &mime, 0);
961 SysFreeString(raw_uri);
962 if(FAILED(hres))
963 return hres;
965 heap_free(This->mime);
966 This->mime = heap_strdupW(mime);
967 CoTaskMemFree(mime);
968 This->reported_mime = TRUE;
969 if(This->protocol_sink)
970 IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, This->mime);
974 if(!This->protocol_sink)
975 return S_OK;
977 return IInternetProtocolSink_ReportData(This->protocol_sink, bscf, progress, progress_max);
980 static HRESULT WINAPI ProtocolSinkHandler_ReportResult(IInternetProtocolSink *iface,
981 HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
983 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
985 TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
987 if(This->protocol_sink)
988 return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
989 return S_OK;
992 static const IInternetProtocolSinkVtbl InternetProtocolSinkHandlerVtbl = {
993 ProtocolSinkHandler_QueryInterface,
994 ProtocolSinkHandler_AddRef,
995 ProtocolSinkHandler_Release,
996 ProtocolSinkHandler_Switch,
997 ProtocolSinkHandler_ReportProgress,
998 ProtocolSinkHandler_ReportData,
999 ProtocolSinkHandler_ReportResult
1002 static inline BindProtocol *impl_from_IInternetBindInfo(IInternetBindInfo *iface)
1004 return CONTAINING_RECORD(iface, BindProtocol, IInternetBindInfo_iface);
1007 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface,
1008 REFIID riid, void **ppv)
1010 BindProtocol *This = impl_from_IInternetBindInfo(iface);
1011 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
1014 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
1016 BindProtocol *This = impl_from_IInternetBindInfo(iface);
1017 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
1020 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
1022 BindProtocol *This = impl_from_IInternetBindInfo(iface);
1023 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
1026 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface,
1027 DWORD *grfBINDF, BINDINFO *pbindinfo)
1029 BindProtocol *This = impl_from_IInternetBindInfo(iface);
1030 HRESULT hres;
1032 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
1034 hres = IInternetBindInfo_GetBindInfo(This->bind_info, grfBINDF, pbindinfo);
1035 if(FAILED(hres)) {
1036 WARN("GetBindInfo failed: %08x\n", hres);
1037 return hres;
1040 *grfBINDF |= BINDF_FROMURLMON;
1041 return hres;
1044 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface,
1045 ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
1047 BindProtocol *This = impl_from_IInternetBindInfo(iface);
1049 TRACE("(%p)->(%d %p %d %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched);
1051 return IInternetBindInfo_GetBindString(This->bind_info, ulStringType, ppwzStr, cEl, pcElFetched);
1054 static const IInternetBindInfoVtbl InternetBindInfoVtbl = {
1055 BindInfo_QueryInterface,
1056 BindInfo_AddRef,
1057 BindInfo_Release,
1058 BindInfo_GetBindInfo,
1059 BindInfo_GetBindString
1062 static inline BindProtocol *impl_from_IInternetPriority(IInternetPriority *iface)
1064 return CONTAINING_RECORD(iface, BindProtocol, IInternetPriority_iface);
1067 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
1068 REFIID riid, void **ppv)
1070 BindProtocol *This = impl_from_IInternetPriority(iface);
1071 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
1074 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
1076 BindProtocol *This = impl_from_IInternetPriority(iface);
1077 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
1080 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
1082 BindProtocol *This = impl_from_IInternetPriority(iface);
1083 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
1086 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
1088 BindProtocol *This = impl_from_IInternetPriority(iface);
1090 TRACE("(%p)->(%d)\n", This, nPriority);
1092 This->priority = nPriority;
1093 return S_OK;
1096 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
1098 BindProtocol *This = impl_from_IInternetPriority(iface);
1100 TRACE("(%p)->(%p)\n", This, pnPriority);
1102 *pnPriority = This->priority;
1103 return S_OK;
1106 static const IInternetPriorityVtbl InternetPriorityVtbl = {
1107 InternetPriority_QueryInterface,
1108 InternetPriority_AddRef,
1109 InternetPriority_Release,
1110 InternetPriority_SetPriority,
1111 InternetPriority_GetPriority
1115 static inline BindProtocol *impl_from_IInternetProtocolSink(IInternetProtocolSink *iface)
1117 return CONTAINING_RECORD(iface, BindProtocol, IInternetProtocolSink_iface);
1120 static HRESULT WINAPI BPInternetProtocolSink_QueryInterface(IInternetProtocolSink *iface,
1121 REFIID riid, void **ppv)
1123 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1124 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
1127 static ULONG WINAPI BPInternetProtocolSink_AddRef(IInternetProtocolSink *iface)
1129 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1130 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
1133 static ULONG WINAPI BPInternetProtocolSink_Release(IInternetProtocolSink *iface)
1135 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1136 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
1139 typedef struct {
1140 task_header_t header;
1141 PROTOCOLDATA *data;
1142 } switch_task_t;
1144 static void switch_proc(BindProtocol *bind, task_header_t *t)
1146 switch_task_t *task = (switch_task_t*)t;
1148 IInternetProtocol_Continue(bind->protocol_handler, task->data);
1150 heap_free(task);
1153 static HRESULT WINAPI BPInternetProtocolSink_Switch(IInternetProtocolSink *iface,
1154 PROTOCOLDATA *pProtocolData)
1156 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1157 PROTOCOLDATA *data;
1159 TRACE("(%p)->(%p)\n", This, pProtocolData);
1161 TRACE("flags %x state %x data %p cb %u\n", pProtocolData->grfFlags, pProtocolData->dwState,
1162 pProtocolData->pData, pProtocolData->cbData);
1164 data = heap_alloc(sizeof(PROTOCOLDATA));
1165 if(!data)
1166 return E_OUTOFMEMORY;
1167 memcpy(data, pProtocolData, sizeof(PROTOCOLDATA));
1169 if((This->pi&PI_APARTMENTTHREADED && pProtocolData->grfFlags&PI_FORCE_ASYNC)
1170 || !do_direct_notif(This)) {
1171 switch_task_t *task;
1173 task = heap_alloc(sizeof(switch_task_t));
1174 if(!task)
1176 heap_free(data);
1177 return E_OUTOFMEMORY;
1180 task->data = data;
1182 push_task(This, &task->header, switch_proc);
1183 return S_OK;
1186 return IInternetProtocolSink_Switch(This->protocol_sink_handler, data);
1189 typedef struct {
1190 task_header_t header;
1192 ULONG status_code;
1193 LPWSTR status_text;
1194 } on_progress_task_t;
1196 static void on_progress_proc(BindProtocol *This, task_header_t *t)
1198 on_progress_task_t *task = (on_progress_task_t*)t;
1200 IInternetProtocolSink_ReportProgress(This->protocol_sink_handler, task->status_code, task->status_text);
1202 heap_free(task->status_text);
1203 heap_free(task);
1206 static HRESULT WINAPI BPInternetProtocolSink_ReportProgress(IInternetProtocolSink *iface,
1207 ULONG ulStatusCode, LPCWSTR szStatusText)
1209 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1211 TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
1213 if(do_direct_notif(This)) {
1214 IInternetProtocolSink_ReportProgress(This->protocol_sink_handler, ulStatusCode, szStatusText);
1215 }else {
1216 on_progress_task_t *task;
1218 task = heap_alloc(sizeof(on_progress_task_t));
1220 task->status_code = ulStatusCode;
1221 task->status_text = heap_strdupW(szStatusText);
1223 push_task(This, &task->header, on_progress_proc);
1226 return S_OK;
1229 typedef struct {
1230 task_header_t header;
1231 DWORD bscf;
1232 ULONG progress;
1233 ULONG progress_max;
1234 } report_data_task_t;
1236 static void report_data_proc(BindProtocol *This, task_header_t *t)
1238 report_data_task_t *task = (report_data_task_t*)t;
1240 IInternetProtocolSink_ReportData(This->protocol_sink_handler,
1241 task->bscf, task->progress, task->progress_max);
1243 heap_free(task);
1246 static HRESULT WINAPI BPInternetProtocolSink_ReportData(IInternetProtocolSink *iface,
1247 DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax)
1249 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1251 TRACE("(%p)->(%x %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
1253 if(!This->protocol_sink)
1254 return S_OK;
1256 if(!do_direct_notif(This)) {
1257 report_data_task_t *task;
1259 task = heap_alloc(sizeof(report_data_task_t));
1260 if(!task)
1261 return E_OUTOFMEMORY;
1263 task->bscf = grfBSCF;
1264 task->progress = ulProgress;
1265 task->progress_max = ulProgressMax;
1267 push_task(This, &task->header, report_data_proc);
1268 return S_OK;
1271 return IInternetProtocolSink_ReportData(This->protocol_sink_handler,
1272 grfBSCF, ulProgress, ulProgressMax);
1275 typedef struct {
1276 task_header_t header;
1278 HRESULT hres;
1279 DWORD err;
1280 LPWSTR str;
1281 } report_result_task_t;
1283 static void report_result_proc(BindProtocol *This, task_header_t *t)
1285 report_result_task_t *task = (report_result_task_t*)t;
1287 IInternetProtocolSink_ReportResult(This->protocol_sink_handler, task->hres, task->err, task->str);
1289 heap_free(task->str);
1290 heap_free(task);
1293 static HRESULT WINAPI BPInternetProtocolSink_ReportResult(IInternetProtocolSink *iface,
1294 HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
1296 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1298 TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
1300 if(!This->protocol_sink)
1301 return E_FAIL;
1302 This->reported_result = TRUE;
1304 if(!do_direct_notif(This)) {
1305 report_result_task_t *task;
1307 task = heap_alloc(sizeof(report_result_task_t));
1308 if(!task)
1309 return E_OUTOFMEMORY;
1311 task->hres = hrResult;
1312 task->err = dwError;
1313 task->str = heap_strdupW(szResult);
1315 push_task(This, &task->header, report_result_proc);
1316 return S_OK;
1319 return IInternetProtocolSink_ReportResult(This->protocol_sink_handler, hrResult, dwError, szResult);
1322 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = {
1323 BPInternetProtocolSink_QueryInterface,
1324 BPInternetProtocolSink_AddRef,
1325 BPInternetProtocolSink_Release,
1326 BPInternetProtocolSink_Switch,
1327 BPInternetProtocolSink_ReportProgress,
1328 BPInternetProtocolSink_ReportData,
1329 BPInternetProtocolSink_ReportResult
1332 static inline BindProtocol *impl_from_IWinInetHttpInfo(IWinInetHttpInfo *iface)
1334 return CONTAINING_RECORD(iface, BindProtocol, IWinInetHttpInfo_iface);
1337 static HRESULT WINAPI WinInetHttpInfo_QueryInterface(IWinInetHttpInfo *iface, REFIID riid, void **ppv)
1339 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1340 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
1343 static ULONG WINAPI WinInetHttpInfo_AddRef(IWinInetHttpInfo *iface)
1345 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1346 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
1349 static ULONG WINAPI WinInetHttpInfo_Release(IWinInetHttpInfo *iface)
1351 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1352 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
1355 static HRESULT WINAPI WinInetHttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD dwOption,
1356 void *pBuffer, DWORD *pcbBuffer)
1358 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1359 FIXME("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer);
1360 return E_NOTIMPL;
1363 static HRESULT WINAPI WinInetHttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption,
1364 void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved)
1366 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1367 FIXME("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved);
1368 return E_NOTIMPL;
1371 static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = {
1372 WinInetHttpInfo_QueryInterface,
1373 WinInetHttpInfo_AddRef,
1374 WinInetHttpInfo_Release,
1375 WinInetHttpInfo_QueryOption,
1376 WinInetHttpInfo_QueryInfo
1379 static inline BindProtocol *impl_from_IServiceProvider(IServiceProvider *iface)
1381 return CONTAINING_RECORD(iface, BindProtocol, IServiceProvider_iface);
1384 static HRESULT WINAPI BPServiceProvider_QueryInterface(IServiceProvider *iface,
1385 REFIID riid, void **ppv)
1387 BindProtocol *This = impl_from_IServiceProvider(iface);
1388 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
1391 static ULONG WINAPI BPServiceProvider_AddRef(IServiceProvider *iface)
1393 BindProtocol *This = impl_from_IServiceProvider(iface);
1394 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
1397 static ULONG WINAPI BPServiceProvider_Release(IServiceProvider *iface)
1399 BindProtocol *This = impl_from_IServiceProvider(iface);
1400 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
1403 static HRESULT WINAPI BPServiceProvider_QueryService(IServiceProvider *iface,
1404 REFGUID guidService, REFIID riid, void **ppv)
1406 BindProtocol *This = impl_from_IServiceProvider(iface);
1408 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
1410 if(!This->service_provider)
1411 return E_NOINTERFACE;
1413 return IServiceProvider_QueryService(This->service_provider, guidService, riid, ppv);
1416 static const IServiceProviderVtbl ServiceProviderVtbl = {
1417 BPServiceProvider_QueryInterface,
1418 BPServiceProvider_AddRef,
1419 BPServiceProvider_Release,
1420 BPServiceProvider_QueryService
1423 HRESULT create_binding_protocol(BOOL from_urlmon, BindProtocol **protocol)
1425 BindProtocol *ret = heap_alloc_zero(sizeof(BindProtocol));
1427 ret->IInternetProtocolEx_iface.lpVtbl = &BindProtocolVtbl;
1428 ret->IInternetBindInfo_iface.lpVtbl = &InternetBindInfoVtbl;
1429 ret->IInternetPriority_iface.lpVtbl = &InternetPriorityVtbl;
1430 ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
1431 ret->IInternetProtocolSink_iface.lpVtbl = &InternetProtocolSinkVtbl;
1432 ret->IWinInetHttpInfo_iface.lpVtbl = &WinInetHttpInfoVtbl;
1434 ret->default_protocol_handler.IInternetProtocol_iface.lpVtbl = &InternetProtocolHandlerVtbl;
1435 ret->default_protocol_handler.IInternetProtocolSink_iface.lpVtbl = &InternetProtocolSinkHandlerVtbl;
1437 ret->ref = 1;
1438 ret->from_urlmon = from_urlmon;
1439 ret->apartment_thread = GetCurrentThreadId();
1440 ret->notif_hwnd = get_notif_hwnd();
1441 ret->protocol_handler = &ret->default_protocol_handler.IInternetProtocol_iface;
1442 ret->protocol_sink_handler = &ret->default_protocol_handler.IInternetProtocolSink_iface;
1443 InitializeCriticalSection(&ret->section);
1444 ret->section.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BindProtocol.section");
1446 URLMON_LockModule();
1448 *protocol = ret;
1449 return S_OK;