mshtml: Don't call CP event sinks on detached documents.
[wine.git] / dlls / urlmon / bindprot.c
blob8deccda1bffdfb13ce1b4b12d9d963bd3ca2bc1a
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 HWND get_notif_hwnd(void)
88 static ATOM wnd_class = 0;
89 tls_data_t *tls_data;
91 static const WCHAR wszURLMonikerNotificationWindow[] =
92 {'U','R','L',' ','M','o','n','i','k','e','r',' ',
93 'N','o','t','i','f','i','c','a','t','i','o','n',' ','W','i','n','d','o','w',0};
95 tls_data = get_tls_data();
96 if(!tls_data)
97 return NULL;
99 if(tls_data->notif_hwnd_cnt) {
100 tls_data->notif_hwnd_cnt++;
101 return tls_data->notif_hwnd;
104 if(!wnd_class) {
105 static WNDCLASSEXW wndclass = {
106 sizeof(wndclass), 0,
107 notif_wnd_proc, 0, 0,
108 NULL, NULL, NULL, NULL, NULL,
109 wszURLMonikerNotificationWindow,
110 NULL
113 wndclass.hInstance = hProxyDll;
115 wnd_class = RegisterClassExW(&wndclass);
116 if (!wnd_class && GetLastError() == ERROR_CLASS_ALREADY_EXISTS)
117 wnd_class = 1;
120 tls_data->notif_hwnd = CreateWindowExW(0, wszURLMonikerNotificationWindow,
121 wszURLMonikerNotificationWindow, 0, 0, 0, 0, 0, HWND_MESSAGE,
122 NULL, hProxyDll, NULL);
123 if(tls_data->notif_hwnd)
124 tls_data->notif_hwnd_cnt++;
126 TRACE("hwnd = %p\n", tls_data->notif_hwnd);
128 return tls_data->notif_hwnd;
131 void release_notif_hwnd(HWND hwnd)
133 tls_data_t *data = get_tls_data();
135 if(!data)
136 return;
138 if(data->notif_hwnd != hwnd) {
139 PostMessageW(data->notif_hwnd, WM_MK_RELEASE, 0, 0);
140 return;
143 if(!--data->notif_hwnd_cnt) {
144 DestroyWindow(data->notif_hwnd);
145 data->notif_hwnd = NULL;
149 static void push_task(BindProtocol *This, task_header_t *task, task_proc_t proc)
151 BOOL do_post = FALSE;
153 task->proc = proc;
154 task->next = NULL;
156 EnterCriticalSection(&This->section);
158 if(This->task_queue_tail) {
159 This->task_queue_tail->next = task;
160 This->task_queue_tail = task;
161 }else {
162 This->task_queue_tail = This->task_queue_head = task;
163 do_post = !This->continue_call;
166 LeaveCriticalSection(&This->section);
168 if(do_post) {
169 IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
170 PostMessageW(This->notif_hwnd, WM_MK_CONTINUE, 0, (LPARAM)This);
174 static inline BOOL is_apartment_thread(BindProtocol *This)
176 return This->apartment_thread == GetCurrentThreadId();
179 static inline BOOL do_direct_notif(BindProtocol *This)
181 return !(This->pi & PI_APARTMENTTHREADED) || (is_apartment_thread(This) && !This->continue_call);
184 static HRESULT handle_mime_filter(BindProtocol *This, IInternetProtocol *mime_filter)
186 PROTOCOLFILTERDATA filter_data = { sizeof(PROTOCOLFILTERDATA), NULL, NULL, NULL, 0 };
187 HRESULT hres;
189 hres = IInternetProtocol_QueryInterface(mime_filter, &IID_IInternetProtocolSink, (void**)&This->protocol_sink_handler);
190 if(FAILED(hres)) {
191 This->protocol_sink_handler = &This->default_protocol_handler.IInternetProtocolSink_iface;
192 return hres;
195 IInternetProtocol_AddRef(mime_filter);
196 This->protocol_handler = mime_filter;
198 filter_data.pProtocol = &This->default_protocol_handler.IInternetProtocol_iface;
199 hres = IInternetProtocol_Start(mime_filter, This->mime, &This->default_protocol_handler.IInternetProtocolSink_iface,
200 &This->IInternetBindInfo_iface, PI_FILTER_MODE|PI_FORCE_ASYNC,
201 (HANDLE_PTR)&filter_data);
202 if(FAILED(hres)) {
203 IInternetProtocolSink_Release(This->protocol_sink_handler);
204 IInternetProtocol_Release(This->protocol_handler);
205 This->protocol_sink_handler = &This->default_protocol_handler.IInternetProtocolSink_iface;
206 This->protocol_handler = &This->default_protocol_handler.IInternetProtocol_iface;
207 return hres;
210 /* NOTE: IE9 calls it on the new protocol_sink. It doesn't make sense to is seems to be a bug there. */
211 IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_LOADINGMIMEHANDLER, NULL);
213 return S_OK;
216 static void mime_available(BindProtocol *This, LPCWSTR mime, BOOL verified)
218 IInternetProtocol *mime_filter;
219 HRESULT hres;
221 heap_free(This->mime);
222 This->mime = heap_strdupW(mime);
224 if(This->protocol_handler==&This->default_protocol_handler.IInternetProtocol_iface
225 && (mime_filter = get_mime_filter(mime))) {
226 TRACE("Got mime filter for %s\n", debugstr_w(mime));
228 hres = handle_mime_filter(This, mime_filter);
229 IInternetProtocol_Release(mime_filter);
230 if(FAILED(hres))
231 FIXME("MIME filter failed: %08x\n", hres);
234 if(This->reported_mime || verified || !(This->pi & PI_MIMEVERIFICATION)) {
235 This->reported_mime = TRUE;
236 IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, mime);
240 static inline BindProtocol *impl_from_IInternetProtocolEx(IInternetProtocolEx *iface)
242 return CONTAINING_RECORD(iface, BindProtocol, IInternetProtocolEx_iface);
245 static HRESULT WINAPI BindProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
247 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
249 *ppv = NULL;
250 if(IsEqualGUID(&IID_IUnknown, riid)) {
251 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
252 *ppv = &This->IInternetProtocolEx_iface;
253 }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
254 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
255 *ppv = &This->IInternetProtocolEx_iface;
256 }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
257 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
258 *ppv = &This->IInternetProtocolEx_iface;
259 }else if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) {
260 TRACE("(%p)->(IID_IInternetProtocolEx %p)\n", This, ppv);
261 *ppv = &This->IInternetProtocolEx_iface;
262 }else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) {
263 TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This, ppv);
264 *ppv = &This->IInternetBindInfo_iface;
265 }else if(IsEqualGUID(&IID_IInternetPriority, riid)) {
266 TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv);
267 *ppv = &This->IInternetPriority_iface;
268 }else if(IsEqualGUID(&IID_IAuthenticate, riid)) {
269 FIXME("(%p)->(IID_IAuthenticate %p)\n", This, ppv);
270 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
271 TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
272 *ppv = &This->IServiceProvider_iface;
273 }else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
274 TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
275 *ppv = &This->IInternetProtocolSink_iface;
276 }else if(IsEqualGUID(&IID_IWinInetInfo, riid)) {
277 TRACE("(%p)->(IID_IWinInetInfo %p)\n", This, ppv);
279 if(This->protocol) {
280 IWinInetInfo *inet_info;
281 HRESULT hres;
283 hres = IInternetProtocol_QueryInterface(This->protocol, &IID_IWinInetInfo, (void**)&inet_info);
284 if(SUCCEEDED(hres)) {
285 *ppv = &This->IWinInetHttpInfo_iface;
286 IWinInetInfo_Release(inet_info);
289 }else if(IsEqualGUID(&IID_IWinInetHttpInfo, riid)) {
290 TRACE("(%p)->(IID_IWinInetHttpInfo %p)\n", This, ppv);
292 if(This->protocol) {
293 IWinInetHttpInfo *http_info;
294 HRESULT hres;
296 hres = IInternetProtocol_QueryInterface(This->protocol, &IID_IWinInetHttpInfo, (void**)&http_info);
297 if(SUCCEEDED(hres)) {
298 *ppv = &This->IWinInetHttpInfo_iface;
299 IWinInetHttpInfo_Release(http_info);
302 }else {
303 WARN("not supported interface %s\n", debugstr_guid(riid));
306 if(!*ppv)
307 return E_NOINTERFACE;
309 IUnknown_AddRef((IUnknown*)*ppv);
310 return S_OK;
313 static ULONG WINAPI BindProtocol_AddRef(IInternetProtocolEx *iface)
315 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
316 LONG ref = InterlockedIncrement(&This->ref);
317 TRACE("(%p) ref=%d\n", This, ref);
318 return ref;
321 static ULONG WINAPI BindProtocol_Release(IInternetProtocolEx *iface)
323 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
324 LONG ref = InterlockedDecrement(&This->ref);
326 TRACE("(%p) ref=%d\n", This, ref);
328 if(!ref) {
329 if(This->wininet_info)
330 IWinInetInfo_Release(This->wininet_info);
331 if(This->wininet_http_info)
332 IWinInetHttpInfo_Release(This->wininet_http_info);
333 if(This->protocol)
334 IInternetProtocol_Release(This->protocol);
335 if(This->bind_info)
336 IInternetBindInfo_Release(This->bind_info);
337 if(This->protocol_handler && This->protocol_handler != &This->default_protocol_handler.IInternetProtocol_iface)
338 IInternetProtocol_Release(This->protocol_handler);
339 if(This->protocol_sink_handler &&
340 This->protocol_sink_handler != &This->default_protocol_handler.IInternetProtocolSink_iface)
341 IInternetProtocolSink_Release(This->protocol_sink_handler);
342 if(This->uri)
343 IUri_Release(This->uri);
344 SysFreeString(This->display_uri);
346 set_binding_sink(This, NULL, NULL);
348 if(This->notif_hwnd)
349 release_notif_hwnd(This->notif_hwnd);
350 This->section.DebugInfo->Spare[0] = 0;
351 DeleteCriticalSection(&This->section);
353 heap_free(This->mime);
354 heap_free(This);
356 URLMON_UnlockModule();
359 return ref;
362 static HRESULT WINAPI BindProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
363 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
364 DWORD grfPI, HANDLE_PTR dwReserved)
366 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
367 IUri *uri;
368 HRESULT hres;
370 TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
371 pOIBindInfo, grfPI, dwReserved);
373 hres = CreateUri(szUrl, Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri);
374 if(FAILED(hres))
375 return hres;
377 hres = IInternetProtocolEx_StartEx(&This->IInternetProtocolEx_iface, uri, pOIProtSink,
378 pOIBindInfo, grfPI, (HANDLE*)dwReserved);
380 IUri_Release(uri);
381 return hres;
384 static HRESULT WINAPI BindProtocol_Continue(IInternetProtocolEx *iface, PROTOCOLDATA *pProtocolData)
386 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
388 TRACE("(%p)->(%p)\n", This, pProtocolData);
390 return IInternetProtocol_Continue(This->protocol_handler, pProtocolData);
393 static HRESULT WINAPI BindProtocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason,
394 DWORD dwOptions)
396 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
398 TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
400 return IInternetProtocol_Abort(This->protocol_handler, hrReason, dwOptions);
403 static HRESULT WINAPI BindProtocol_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
405 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
407 TRACE("(%p)->(%08x)\n", This, dwOptions);
409 return IInternetProtocol_Terminate(This->protocol_handler, dwOptions);
412 static HRESULT WINAPI BindProtocol_Suspend(IInternetProtocolEx *iface)
414 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
415 FIXME("(%p)\n", This);
416 return E_NOTIMPL;
419 static HRESULT WINAPI BindProtocol_Resume(IInternetProtocolEx *iface)
421 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
422 FIXME("(%p)\n", This);
423 return E_NOTIMPL;
426 static HRESULT WINAPI BindProtocol_Read(IInternetProtocolEx *iface, void *pv,
427 ULONG cb, ULONG *pcbRead)
429 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
431 TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
433 if(pcbRead)
434 *pcbRead = 0;
435 return IInternetProtocol_Read(This->protocol_handler, pv, cb, pcbRead);
438 static HRESULT WINAPI BindProtocol_Seek(IInternetProtocolEx *iface, LARGE_INTEGER dlibMove,
439 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
441 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
442 FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
443 return E_NOTIMPL;
446 static HRESULT WINAPI BindProtocol_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
448 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
450 TRACE("(%p)->(%08x)\n", This, dwOptions);
452 return IInternetProtocol_LockRequest(This->protocol_handler, dwOptions);
455 static HRESULT WINAPI BindProtocol_UnlockRequest(IInternetProtocolEx *iface)
457 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
459 TRACE("(%p)\n", This);
461 return IInternetProtocol_UnlockRequest(This->protocol_handler);
464 static HRESULT WINAPI BindProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUri,
465 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
466 DWORD grfPI, HANDLE *dwReserved)
468 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
469 IInternetProtocol *protocol = NULL;
470 IInternetProtocolEx *protocolex;
471 IInternetPriority *priority;
472 IServiceProvider *service_provider;
473 BOOL urlmon_protocol = FALSE;
474 CLSID clsid = IID_NULL;
475 LPOLESTR clsid_str;
476 HRESULT hres;
478 TRACE("(%p)->(%p %p %p %08x %p)\n", This, pUri, pOIProtSink, pOIBindInfo, grfPI, dwReserved);
480 if(!pUri || !pOIProtSink || !pOIBindInfo)
481 return E_INVALIDARG;
483 This->pi = grfPI;
485 IUri_AddRef(pUri);
486 This->uri = pUri;
488 hres = IInternetProtocolSink_QueryInterface(pOIProtSink, &IID_IServiceProvider,
489 (void**)&service_provider);
490 if(SUCCEEDED(hres)) {
491 /* FIXME: What's protocol CLSID here? */
492 IServiceProvider_QueryService(service_provider, &IID_IInternetProtocol,
493 &IID_IInternetProtocol, (void**)&protocol);
494 IServiceProvider_Release(service_provider);
497 if(!protocol) {
498 IClassFactory *cf;
499 IUnknown *unk;
501 hres = get_protocol_handler(pUri, &clsid, &urlmon_protocol, &cf);
502 if(FAILED(hres))
503 return hres;
505 if(This->from_urlmon) {
506 hres = IClassFactory_CreateInstance(cf, NULL, &IID_IInternetProtocol, (void**)&protocol);
507 IClassFactory_Release(cf);
508 if(FAILED(hres))
509 return hres;
510 }else {
511 hres = IClassFactory_CreateInstance(cf, (IUnknown*)&This->IInternetBindInfo_iface,
512 &IID_IUnknown, (void**)&unk);
513 IClassFactory_Release(cf);
514 if(FAILED(hres))
515 return hres;
517 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocol, (void**)&protocol);
518 IUnknown_Release(unk);
519 if(FAILED(hres))
520 return hres;
524 StringFromCLSID(&clsid, &clsid_str);
525 IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_PROTOCOLCLASSID, clsid_str);
526 CoTaskMemFree(clsid_str);
528 This->protocol = protocol;
530 if(urlmon_protocol) {
531 IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&This->wininet_info);
532 IInternetProtocol_QueryInterface(protocol, &IID_IWinInetHttpInfo, (void**)&This->wininet_http_info);
535 set_binding_sink(This, pOIProtSink, pOIBindInfo);
537 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
538 if(SUCCEEDED(hres)) {
539 IInternetPriority_SetPriority(priority, This->priority);
540 IInternetPriority_Release(priority);
543 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolEx, (void**)&protocolex);
544 if(SUCCEEDED(hres)) {
545 hres = IInternetProtocolEx_StartEx(protocolex, pUri, &This->IInternetProtocolSink_iface,
546 &This->IInternetBindInfo_iface, 0, NULL);
547 IInternetProtocolEx_Release(protocolex);
548 }else {
549 hres = IUri_GetDisplayUri(pUri, &This->display_uri);
550 if(FAILED(hres))
551 return hres;
553 hres = IInternetProtocol_Start(protocol, This->display_uri, &This->IInternetProtocolSink_iface,
554 &This->IInternetBindInfo_iface, 0, 0);
557 if(SUCCEEDED(hres))
558 process_tasks(This);
559 return hres;
562 void set_binding_sink(BindProtocol *This, IInternetProtocolSink *sink, IInternetBindInfo *bind_info)
564 IInternetProtocolSink *prev_sink;
565 IServiceProvider *service_provider = NULL;
567 if(sink)
568 IInternetProtocolSink_AddRef(sink);
569 prev_sink = InterlockedExchangePointer((void**)&This->protocol_sink, sink);
570 if(prev_sink)
571 IInternetProtocolSink_Release(prev_sink);
573 if(sink)
574 IInternetProtocolSink_QueryInterface(sink, &IID_IServiceProvider, (void**)&service_provider);
575 service_provider = InterlockedExchangePointer((void**)&This->service_provider, service_provider);
576 if(service_provider)
577 IServiceProvider_Release(service_provider);
579 if(bind_info)
580 IInternetBindInfo_AddRef(bind_info);
581 bind_info = InterlockedExchangePointer((void**)&This->bind_info, bind_info);
582 if(bind_info)
583 IInternetBindInfo_Release(bind_info);
586 static const IInternetProtocolExVtbl BindProtocolVtbl = {
587 BindProtocol_QueryInterface,
588 BindProtocol_AddRef,
589 BindProtocol_Release,
590 BindProtocol_Start,
591 BindProtocol_Continue,
592 BindProtocol_Abort,
593 BindProtocol_Terminate,
594 BindProtocol_Suspend,
595 BindProtocol_Resume,
596 BindProtocol_Read,
597 BindProtocol_Seek,
598 BindProtocol_LockRequest,
599 BindProtocol_UnlockRequest,
600 BindProtocol_StartEx
603 static inline BindProtocol *impl_from_IInternetProtocol(IInternetProtocol *iface)
605 return CONTAINING_RECORD(iface, BindProtocol, default_protocol_handler.IInternetProtocol_iface);
608 static HRESULT WINAPI ProtocolHandler_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
610 BindProtocol *This = impl_from_IInternetProtocol(iface);
612 *ppv = NULL;
613 if(IsEqualGUID(&IID_IUnknown, riid)) {
614 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
615 *ppv = &This->default_protocol_handler.IInternetProtocol_iface;
616 }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
617 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
618 *ppv = &This->default_protocol_handler.IInternetProtocol_iface;
619 }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
620 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
621 *ppv = &This->default_protocol_handler.IInternetProtocol_iface;
622 }else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
623 TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
624 *ppv = &This->default_protocol_handler.IInternetProtocolSink_iface;
627 if(*ppv) {
628 IInternetProtocol_AddRef(iface);
629 return S_OK;
632 WARN("not supported interface %s\n", debugstr_guid(riid));
633 return E_NOINTERFACE;
636 static ULONG WINAPI ProtocolHandler_AddRef(IInternetProtocol *iface)
638 BindProtocol *This = impl_from_IInternetProtocol(iface);
639 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
642 static ULONG WINAPI ProtocolHandler_Release(IInternetProtocol *iface)
644 BindProtocol *This = impl_from_IInternetProtocol(iface);
645 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
648 static HRESULT WINAPI ProtocolHandler_Start(IInternetProtocol *iface, LPCWSTR szUrl,
649 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
650 DWORD grfPI, HANDLE_PTR dwReserved)
652 ERR("Should not be called\n");
653 return E_NOTIMPL;
656 static HRESULT WINAPI ProtocolHandler_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
658 BindProtocol *This = impl_from_IInternetProtocol(iface);
659 HRESULT hres;
661 TRACE("(%p)->(%p)\n", This, pProtocolData);
663 hres = IInternetProtocol_Continue(This->protocol, pProtocolData);
665 heap_free(pProtocolData);
666 return hres;
669 static HRESULT WINAPI ProtocolHandler_Abort(IInternetProtocol *iface, HRESULT hrReason,
670 DWORD dwOptions)
672 BindProtocol *This = impl_from_IInternetProtocol(iface);
674 TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
676 if(This->protocol && !This->reported_result)
677 return IInternetProtocol_Abort(This->protocol, hrReason, dwOptions);
679 return S_OK;
682 static HRESULT WINAPI ProtocolHandler_Terminate(IInternetProtocol *iface, DWORD dwOptions)
684 BindProtocol *This = impl_from_IInternetProtocol(iface);
686 TRACE("(%p)->(%08x)\n", This, dwOptions);
688 if(!This->reported_result)
689 return E_FAIL;
691 IInternetProtocol_Terminate(This->protocol, 0);
693 set_binding_sink(This, NULL, NULL);
695 if(This->bind_info) {
696 IInternetBindInfo_Release(This->bind_info);
697 This->bind_info = NULL;
700 return S_OK;
703 static HRESULT WINAPI ProtocolHandler_Suspend(IInternetProtocol *iface)
705 BindProtocol *This = impl_from_IInternetProtocol(iface);
706 FIXME("(%p)\n", This);
707 return E_NOTIMPL;
710 static HRESULT WINAPI ProtocolHandler_Resume(IInternetProtocol *iface)
712 BindProtocol *This = impl_from_IInternetProtocol(iface);
713 FIXME("(%p)\n", This);
714 return E_NOTIMPL;
717 static HRESULT WINAPI ProtocolHandler_Read(IInternetProtocol *iface, void *pv,
718 ULONG cb, ULONG *pcbRead)
720 BindProtocol *This = impl_from_IInternetProtocol(iface);
721 ULONG read = 0;
722 HRESULT hres = S_OK;
724 TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
726 if(This->buf_size) {
727 read = min(cb, This->buf_size);
728 memcpy(pv, This->buf, read);
730 if(read == This->buf_size) {
731 heap_free(This->buf);
732 This->buf = NULL;
733 }else {
734 memmove(This->buf, This->buf+cb, This->buf_size-cb);
737 This->buf_size -= read;
740 if(read < cb) {
741 ULONG cread = 0;
743 if(is_apartment_thread(This))
744 This->continue_call++;
745 hres = IInternetProtocol_Read(This->protocol, (BYTE*)pv+read, cb-read, &cread);
746 if(is_apartment_thread(This))
747 This->continue_call--;
748 read += cread;
751 *pcbRead = read;
752 return hres;
755 static HRESULT WINAPI ProtocolHandler_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
756 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
758 BindProtocol *This = impl_from_IInternetProtocol(iface);
759 FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
760 return E_NOTIMPL;
763 static HRESULT WINAPI ProtocolHandler_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
765 BindProtocol *This = impl_from_IInternetProtocol(iface);
767 TRACE("(%p)->(%08x)\n", This, dwOptions);
769 return IInternetProtocol_LockRequest(This->protocol, dwOptions);
772 static HRESULT WINAPI ProtocolHandler_UnlockRequest(IInternetProtocol *iface)
774 BindProtocol *This = impl_from_IInternetProtocol(iface);
776 TRACE("(%p)\n", This);
778 return IInternetProtocol_UnlockRequest(This->protocol);
781 static const IInternetProtocolVtbl InternetProtocolHandlerVtbl = {
782 ProtocolHandler_QueryInterface,
783 ProtocolHandler_AddRef,
784 ProtocolHandler_Release,
785 ProtocolHandler_Start,
786 ProtocolHandler_Continue,
787 ProtocolHandler_Abort,
788 ProtocolHandler_Terminate,
789 ProtocolHandler_Suspend,
790 ProtocolHandler_Resume,
791 ProtocolHandler_Read,
792 ProtocolHandler_Seek,
793 ProtocolHandler_LockRequest,
794 ProtocolHandler_UnlockRequest
797 static inline BindProtocol *impl_from_IInternetProtocolSinkHandler(IInternetProtocolSink *iface)
799 return CONTAINING_RECORD(iface, BindProtocol, default_protocol_handler.IInternetProtocolSink_iface);
802 static HRESULT WINAPI ProtocolSinkHandler_QueryInterface(IInternetProtocolSink *iface,
803 REFIID riid, void **ppvObject)
805 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
806 return IInternetProtocol_QueryInterface(&This->default_protocol_handler.IInternetProtocol_iface,
807 riid, ppvObject);
810 static ULONG WINAPI ProtocolSinkHandler_AddRef(IInternetProtocolSink *iface)
812 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
813 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
816 static ULONG WINAPI ProtocolSinkHandler_Release(IInternetProtocolSink *iface)
818 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
819 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
822 static HRESULT WINAPI ProtocolSinkHandler_Switch(IInternetProtocolSink *iface,
823 PROTOCOLDATA *pProtocolData)
825 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
827 TRACE("(%p)->(%p)\n", This, pProtocolData);
829 if(!This->protocol_sink) {
830 IInternetProtocol_Continue(This->protocol_handler, pProtocolData);
831 return S_OK;
834 return IInternetProtocolSink_Switch(This->protocol_sink, pProtocolData);
837 static HRESULT WINAPI ProtocolSinkHandler_ReportProgress(IInternetProtocolSink *iface,
838 ULONG status_code, LPCWSTR status_text)
840 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
842 TRACE("(%p)->(%s %s)\n", This, debugstr_bindstatus(status_code), debugstr_w(status_text));
844 if(!This->protocol_sink)
845 return S_OK;
847 switch(status_code) {
848 case BINDSTATUS_FINDINGRESOURCE:
849 case BINDSTATUS_CONNECTING:
850 case BINDSTATUS_REDIRECTING:
851 case BINDSTATUS_SENDINGREQUEST:
852 case BINDSTATUS_CACHEFILENAMEAVAILABLE:
853 case BINDSTATUS_DIRECTBIND:
854 case BINDSTATUS_ACCEPTRANGES:
855 case BINDSTATUS_DECODING:
856 IInternetProtocolSink_ReportProgress(This->protocol_sink, status_code, status_text);
857 break;
859 case BINDSTATUS_BEGINDOWNLOADDATA:
860 IInternetProtocolSink_ReportData(This->protocol_sink, This->bscf, This->progress, This->progress_max);
861 break;
863 case BINDSTATUS_MIMETYPEAVAILABLE:
864 mime_available(This, status_text, FALSE);
865 break;
867 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
868 mime_available(This, status_text, TRUE);
869 break;
871 default:
872 FIXME("unsupported ulStatusCode %u\n", status_code);
875 return S_OK;
878 static HRESULT WINAPI ProtocolSinkHandler_ReportData(IInternetProtocolSink *iface,
879 DWORD bscf, ULONG progress, ULONG progress_max)
881 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
883 TRACE("(%p)->(%x %u %u)\n", This, bscf, progress, progress_max);
885 This->bscf = bscf;
886 This->progress = progress;
887 This->progress_max = progress_max;
889 if(!This->protocol_sink)
890 return S_OK;
892 if((This->pi & PI_MIMEVERIFICATION) && !This->reported_mime) {
893 BYTE buf[BUFFER_SIZE];
894 DWORD read = 0;
895 LPWSTR mime;
896 HRESULT hres;
898 do {
899 read = 0;
900 hres = IInternetProtocol_Read(This->protocol, buf,
901 sizeof(buf)-This->buf_size, &read);
902 if(FAILED(hres) && hres != E_PENDING)
903 return hres;
905 if(!This->buf) {
906 This->buf = heap_alloc(BUFFER_SIZE);
907 if(!This->buf)
908 return E_OUTOFMEMORY;
909 }else if(read + This->buf_size > BUFFER_SIZE) {
910 BYTE *tmp;
912 tmp = heap_realloc(This->buf, read+This->buf_size);
913 if(!tmp)
914 return E_OUTOFMEMORY;
915 This->buf = tmp;
918 memcpy(This->buf+This->buf_size, buf, read);
919 This->buf_size += read;
920 }while(This->buf_size < MIME_TEST_SIZE && hres == S_OK);
922 if(This->buf_size < MIME_TEST_SIZE && hres != S_FALSE)
923 return S_OK;
925 bscf = BSCF_FIRSTDATANOTIFICATION;
926 if(hres == S_FALSE)
927 bscf |= BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE;
929 if(!This->reported_mime) {
930 BSTR raw_uri;
932 hres = IUri_GetRawUri(This->uri, &raw_uri);
933 if(FAILED(hres))
934 return hres;
936 hres = FindMimeFromData(NULL, raw_uri, This->buf, min(This->buf_size, MIME_TEST_SIZE),
937 This->mime, 0, &mime, 0);
938 SysFreeString(raw_uri);
939 if(FAILED(hres))
940 return hres;
942 heap_free(This->mime);
943 This->mime = heap_strdupW(mime);
944 CoTaskMemFree(mime);
945 This->reported_mime = TRUE;
946 if(This->protocol_sink)
947 IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, This->mime);
951 if(!This->protocol_sink)
952 return S_OK;
954 return IInternetProtocolSink_ReportData(This->protocol_sink, bscf, progress, progress_max);
957 static HRESULT WINAPI ProtocolSinkHandler_ReportResult(IInternetProtocolSink *iface,
958 HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
960 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
962 TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
964 if(This->protocol_sink)
965 return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
966 return S_OK;
969 static const IInternetProtocolSinkVtbl InternetProtocolSinkHandlerVtbl = {
970 ProtocolSinkHandler_QueryInterface,
971 ProtocolSinkHandler_AddRef,
972 ProtocolSinkHandler_Release,
973 ProtocolSinkHandler_Switch,
974 ProtocolSinkHandler_ReportProgress,
975 ProtocolSinkHandler_ReportData,
976 ProtocolSinkHandler_ReportResult
979 static inline BindProtocol *impl_from_IInternetBindInfo(IInternetBindInfo *iface)
981 return CONTAINING_RECORD(iface, BindProtocol, IInternetBindInfo_iface);
984 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface,
985 REFIID riid, void **ppv)
987 BindProtocol *This = impl_from_IInternetBindInfo(iface);
988 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
991 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
993 BindProtocol *This = impl_from_IInternetBindInfo(iface);
994 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
997 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
999 BindProtocol *This = impl_from_IInternetBindInfo(iface);
1000 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
1003 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface,
1004 DWORD *grfBINDF, BINDINFO *pbindinfo)
1006 BindProtocol *This = impl_from_IInternetBindInfo(iface);
1007 HRESULT hres;
1009 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
1011 hres = IInternetBindInfo_GetBindInfo(This->bind_info, grfBINDF, pbindinfo);
1012 if(FAILED(hres)) {
1013 WARN("GetBindInfo failed: %08x\n", hres);
1014 return hres;
1017 *grfBINDF |= BINDF_FROMURLMON;
1018 return hres;
1021 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface,
1022 ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
1024 BindProtocol *This = impl_from_IInternetBindInfo(iface);
1026 TRACE("(%p)->(%d %p %d %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched);
1028 return IInternetBindInfo_GetBindString(This->bind_info, ulStringType, ppwzStr, cEl, pcElFetched);
1031 static const IInternetBindInfoVtbl InternetBindInfoVtbl = {
1032 BindInfo_QueryInterface,
1033 BindInfo_AddRef,
1034 BindInfo_Release,
1035 BindInfo_GetBindInfo,
1036 BindInfo_GetBindString
1039 static inline BindProtocol *impl_from_IInternetPriority(IInternetPriority *iface)
1041 return CONTAINING_RECORD(iface, BindProtocol, IInternetPriority_iface);
1044 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
1045 REFIID riid, void **ppv)
1047 BindProtocol *This = impl_from_IInternetPriority(iface);
1048 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
1051 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
1053 BindProtocol *This = impl_from_IInternetPriority(iface);
1054 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
1057 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
1059 BindProtocol *This = impl_from_IInternetPriority(iface);
1060 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
1063 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
1065 BindProtocol *This = impl_from_IInternetPriority(iface);
1067 TRACE("(%p)->(%d)\n", This, nPriority);
1069 This->priority = nPriority;
1070 return S_OK;
1073 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
1075 BindProtocol *This = impl_from_IInternetPriority(iface);
1077 TRACE("(%p)->(%p)\n", This, pnPriority);
1079 *pnPriority = This->priority;
1080 return S_OK;
1083 static const IInternetPriorityVtbl InternetPriorityVtbl = {
1084 InternetPriority_QueryInterface,
1085 InternetPriority_AddRef,
1086 InternetPriority_Release,
1087 InternetPriority_SetPriority,
1088 InternetPriority_GetPriority
1092 static inline BindProtocol *impl_from_IInternetProtocolSink(IInternetProtocolSink *iface)
1094 return CONTAINING_RECORD(iface, BindProtocol, IInternetProtocolSink_iface);
1097 static HRESULT WINAPI BPInternetProtocolSink_QueryInterface(IInternetProtocolSink *iface,
1098 REFIID riid, void **ppv)
1100 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1101 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
1104 static ULONG WINAPI BPInternetProtocolSink_AddRef(IInternetProtocolSink *iface)
1106 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1107 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
1110 static ULONG WINAPI BPInternetProtocolSink_Release(IInternetProtocolSink *iface)
1112 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1113 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
1116 typedef struct {
1117 task_header_t header;
1118 PROTOCOLDATA *data;
1119 } switch_task_t;
1121 static void switch_proc(BindProtocol *bind, task_header_t *t)
1123 switch_task_t *task = (switch_task_t*)t;
1125 IInternetProtocol_Continue(bind->protocol_handler, task->data);
1127 heap_free(task);
1130 static HRESULT WINAPI BPInternetProtocolSink_Switch(IInternetProtocolSink *iface,
1131 PROTOCOLDATA *pProtocolData)
1133 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1134 PROTOCOLDATA *data;
1136 TRACE("(%p)->(%p)\n", This, pProtocolData);
1138 TRACE("flags %x state %x data %p cb %u\n", pProtocolData->grfFlags, pProtocolData->dwState,
1139 pProtocolData->pData, pProtocolData->cbData);
1141 data = heap_alloc(sizeof(PROTOCOLDATA));
1142 if(!data)
1143 return E_OUTOFMEMORY;
1144 memcpy(data, pProtocolData, sizeof(PROTOCOLDATA));
1146 if((This->pi&PI_APARTMENTTHREADED && pProtocolData->grfFlags&PI_FORCE_ASYNC)
1147 || !do_direct_notif(This)) {
1148 switch_task_t *task;
1150 task = heap_alloc(sizeof(switch_task_t));
1151 if(!task)
1153 heap_free(data);
1154 return E_OUTOFMEMORY;
1157 task->data = data;
1159 push_task(This, &task->header, switch_proc);
1160 return S_OK;
1163 return IInternetProtocolSink_Switch(This->protocol_sink_handler, data);
1166 typedef struct {
1167 task_header_t header;
1169 ULONG status_code;
1170 LPWSTR status_text;
1171 } on_progress_task_t;
1173 static void on_progress_proc(BindProtocol *This, task_header_t *t)
1175 on_progress_task_t *task = (on_progress_task_t*)t;
1177 IInternetProtocolSink_ReportProgress(This->protocol_sink_handler, task->status_code, task->status_text);
1179 heap_free(task->status_text);
1180 heap_free(task);
1183 static HRESULT WINAPI BPInternetProtocolSink_ReportProgress(IInternetProtocolSink *iface,
1184 ULONG ulStatusCode, LPCWSTR szStatusText)
1186 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1188 TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
1190 if(do_direct_notif(This)) {
1191 IInternetProtocolSink_ReportProgress(This->protocol_sink_handler, ulStatusCode, szStatusText);
1192 }else {
1193 on_progress_task_t *task;
1195 task = heap_alloc(sizeof(on_progress_task_t));
1197 task->status_code = ulStatusCode;
1198 task->status_text = heap_strdupW(szStatusText);
1200 push_task(This, &task->header, on_progress_proc);
1203 return S_OK;
1206 typedef struct {
1207 task_header_t header;
1208 DWORD bscf;
1209 ULONG progress;
1210 ULONG progress_max;
1211 } report_data_task_t;
1213 static void report_data_proc(BindProtocol *This, task_header_t *t)
1215 report_data_task_t *task = (report_data_task_t*)t;
1217 IInternetProtocolSink_ReportData(This->protocol_sink_handler,
1218 task->bscf, task->progress, task->progress_max);
1220 heap_free(task);
1223 static HRESULT WINAPI BPInternetProtocolSink_ReportData(IInternetProtocolSink *iface,
1224 DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax)
1226 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1228 TRACE("(%p)->(%x %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
1230 if(!This->protocol_sink)
1231 return S_OK;
1233 if(!do_direct_notif(This)) {
1234 report_data_task_t *task;
1236 task = heap_alloc(sizeof(report_data_task_t));
1237 if(!task)
1238 return E_OUTOFMEMORY;
1240 task->bscf = grfBSCF;
1241 task->progress = ulProgress;
1242 task->progress_max = ulProgressMax;
1244 push_task(This, &task->header, report_data_proc);
1245 return S_OK;
1248 return IInternetProtocolSink_ReportData(This->protocol_sink_handler,
1249 grfBSCF, ulProgress, ulProgressMax);
1252 typedef struct {
1253 task_header_t header;
1255 HRESULT hres;
1256 DWORD err;
1257 LPWSTR str;
1258 } report_result_task_t;
1260 static void report_result_proc(BindProtocol *This, task_header_t *t)
1262 report_result_task_t *task = (report_result_task_t*)t;
1264 IInternetProtocolSink_ReportResult(This->protocol_sink_handler, task->hres, task->err, task->str);
1266 heap_free(task->str);
1267 heap_free(task);
1270 static HRESULT WINAPI BPInternetProtocolSink_ReportResult(IInternetProtocolSink *iface,
1271 HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
1273 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1275 TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
1277 if(!This->protocol_sink)
1278 return E_FAIL;
1279 This->reported_result = TRUE;
1281 if(!do_direct_notif(This)) {
1282 report_result_task_t *task;
1284 task = heap_alloc(sizeof(report_result_task_t));
1285 if(!task)
1286 return E_OUTOFMEMORY;
1288 task->hres = hrResult;
1289 task->err = dwError;
1290 task->str = heap_strdupW(szResult);
1292 push_task(This, &task->header, report_result_proc);
1293 return S_OK;
1296 return IInternetProtocolSink_ReportResult(This->protocol_sink_handler, hrResult, dwError, szResult);
1299 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = {
1300 BPInternetProtocolSink_QueryInterface,
1301 BPInternetProtocolSink_AddRef,
1302 BPInternetProtocolSink_Release,
1303 BPInternetProtocolSink_Switch,
1304 BPInternetProtocolSink_ReportProgress,
1305 BPInternetProtocolSink_ReportData,
1306 BPInternetProtocolSink_ReportResult
1309 static inline BindProtocol *impl_from_IWinInetHttpInfo(IWinInetHttpInfo *iface)
1311 return CONTAINING_RECORD(iface, BindProtocol, IWinInetHttpInfo_iface);
1314 static HRESULT WINAPI WinInetHttpInfo_QueryInterface(IWinInetHttpInfo *iface, REFIID riid, void **ppv)
1316 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1317 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
1320 static ULONG WINAPI WinInetHttpInfo_AddRef(IWinInetHttpInfo *iface)
1322 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1323 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
1326 static ULONG WINAPI WinInetHttpInfo_Release(IWinInetHttpInfo *iface)
1328 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1329 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
1332 static HRESULT WINAPI WinInetHttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD dwOption,
1333 void *pBuffer, DWORD *pcbBuffer)
1335 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1336 FIXME("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer);
1337 return E_NOTIMPL;
1340 static HRESULT WINAPI WinInetHttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption,
1341 void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved)
1343 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1344 FIXME("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved);
1345 return E_NOTIMPL;
1348 static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = {
1349 WinInetHttpInfo_QueryInterface,
1350 WinInetHttpInfo_AddRef,
1351 WinInetHttpInfo_Release,
1352 WinInetHttpInfo_QueryOption,
1353 WinInetHttpInfo_QueryInfo
1356 static inline BindProtocol *impl_from_IServiceProvider(IServiceProvider *iface)
1358 return CONTAINING_RECORD(iface, BindProtocol, IServiceProvider_iface);
1361 static HRESULT WINAPI BPServiceProvider_QueryInterface(IServiceProvider *iface,
1362 REFIID riid, void **ppv)
1364 BindProtocol *This = impl_from_IServiceProvider(iface);
1365 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
1368 static ULONG WINAPI BPServiceProvider_AddRef(IServiceProvider *iface)
1370 BindProtocol *This = impl_from_IServiceProvider(iface);
1371 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
1374 static ULONG WINAPI BPServiceProvider_Release(IServiceProvider *iface)
1376 BindProtocol *This = impl_from_IServiceProvider(iface);
1377 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
1380 static HRESULT WINAPI BPServiceProvider_QueryService(IServiceProvider *iface,
1381 REFGUID guidService, REFIID riid, void **ppv)
1383 BindProtocol *This = impl_from_IServiceProvider(iface);
1385 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
1387 if(!This->service_provider)
1388 return E_NOINTERFACE;
1390 return IServiceProvider_QueryService(This->service_provider, guidService, riid, ppv);
1393 static const IServiceProviderVtbl ServiceProviderVtbl = {
1394 BPServiceProvider_QueryInterface,
1395 BPServiceProvider_AddRef,
1396 BPServiceProvider_Release,
1397 BPServiceProvider_QueryService
1400 HRESULT create_binding_protocol(BOOL from_urlmon, BindProtocol **protocol)
1402 BindProtocol *ret = heap_alloc_zero(sizeof(BindProtocol));
1404 ret->IInternetProtocolEx_iface.lpVtbl = &BindProtocolVtbl;
1405 ret->IInternetBindInfo_iface.lpVtbl = &InternetBindInfoVtbl;
1406 ret->IInternetPriority_iface.lpVtbl = &InternetPriorityVtbl;
1407 ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
1408 ret->IInternetProtocolSink_iface.lpVtbl = &InternetProtocolSinkVtbl;
1409 ret->IWinInetHttpInfo_iface.lpVtbl = &WinInetHttpInfoVtbl;
1411 ret->default_protocol_handler.IInternetProtocol_iface.lpVtbl = &InternetProtocolHandlerVtbl;
1412 ret->default_protocol_handler.IInternetProtocolSink_iface.lpVtbl = &InternetProtocolSinkHandlerVtbl;
1414 ret->ref = 1;
1415 ret->from_urlmon = from_urlmon;
1416 ret->apartment_thread = GetCurrentThreadId();
1417 ret->notif_hwnd = get_notif_hwnd();
1418 ret->protocol_handler = &ret->default_protocol_handler.IInternetProtocol_iface;
1419 ret->protocol_sink_handler = &ret->default_protocol_handler.IInternetProtocolSink_iface;
1420 InitializeCriticalSection(&ret->section);
1421 ret->section.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BindProtocol.section");
1423 URLMON_LockModule();
1425 *protocol = ret;
1426 return S_OK;