user32/tests: Fix GetSystemMetrics test on Win8.
[wine/multimedia.git] / dlls / urlmon / bindprot.c
blob33d6a6418796283a4f04b0f49c6455e3264003c4
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 if(is_apartment_thread(This))
901 This->continue_call++;
902 hres = IInternetProtocol_Read(This->protocol, buf,
903 sizeof(buf)-This->buf_size, &read);
904 if(is_apartment_thread(This))
905 This->continue_call--;
906 if(FAILED(hres) && hres != E_PENDING)
907 return hres;
909 if(!This->buf) {
910 This->buf = heap_alloc(BUFFER_SIZE);
911 if(!This->buf)
912 return E_OUTOFMEMORY;
913 }else if(read + This->buf_size > BUFFER_SIZE) {
914 BYTE *tmp;
916 tmp = heap_realloc(This->buf, read+This->buf_size);
917 if(!tmp)
918 return E_OUTOFMEMORY;
919 This->buf = tmp;
922 memcpy(This->buf+This->buf_size, buf, read);
923 This->buf_size += read;
924 }while(This->buf_size < MIME_TEST_SIZE && hres == S_OK);
926 if(This->buf_size < MIME_TEST_SIZE && hres != S_FALSE)
927 return S_OK;
929 bscf = BSCF_FIRSTDATANOTIFICATION;
930 if(hres == S_FALSE)
931 bscf |= BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE;
933 if(!This->reported_mime) {
934 BSTR raw_uri;
936 hres = IUri_GetRawUri(This->uri, &raw_uri);
937 if(FAILED(hres))
938 return hres;
940 hres = FindMimeFromData(NULL, raw_uri, This->buf, min(This->buf_size, MIME_TEST_SIZE),
941 This->mime, 0, &mime, 0);
942 SysFreeString(raw_uri);
943 if(FAILED(hres))
944 return hres;
946 heap_free(This->mime);
947 This->mime = heap_strdupW(mime);
948 CoTaskMemFree(mime);
949 This->reported_mime = TRUE;
950 if(This->protocol_sink)
951 IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, This->mime);
955 if(!This->protocol_sink)
956 return S_OK;
958 return IInternetProtocolSink_ReportData(This->protocol_sink, bscf, progress, progress_max);
961 static HRESULT WINAPI ProtocolSinkHandler_ReportResult(IInternetProtocolSink *iface,
962 HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
964 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
966 TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
968 if(This->protocol_sink)
969 return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
970 return S_OK;
973 static const IInternetProtocolSinkVtbl InternetProtocolSinkHandlerVtbl = {
974 ProtocolSinkHandler_QueryInterface,
975 ProtocolSinkHandler_AddRef,
976 ProtocolSinkHandler_Release,
977 ProtocolSinkHandler_Switch,
978 ProtocolSinkHandler_ReportProgress,
979 ProtocolSinkHandler_ReportData,
980 ProtocolSinkHandler_ReportResult
983 static inline BindProtocol *impl_from_IInternetBindInfo(IInternetBindInfo *iface)
985 return CONTAINING_RECORD(iface, BindProtocol, IInternetBindInfo_iface);
988 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface,
989 REFIID riid, void **ppv)
991 BindProtocol *This = impl_from_IInternetBindInfo(iface);
992 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
995 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
997 BindProtocol *This = impl_from_IInternetBindInfo(iface);
998 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
1001 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
1003 BindProtocol *This = impl_from_IInternetBindInfo(iface);
1004 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
1007 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface,
1008 DWORD *grfBINDF, BINDINFO *pbindinfo)
1010 BindProtocol *This = impl_from_IInternetBindInfo(iface);
1011 HRESULT hres;
1013 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
1015 hres = IInternetBindInfo_GetBindInfo(This->bind_info, grfBINDF, pbindinfo);
1016 if(FAILED(hres)) {
1017 WARN("GetBindInfo failed: %08x\n", hres);
1018 return hres;
1021 *grfBINDF |= BINDF_FROMURLMON;
1022 return hres;
1025 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface,
1026 ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
1028 BindProtocol *This = impl_from_IInternetBindInfo(iface);
1030 TRACE("(%p)->(%d %p %d %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched);
1032 return IInternetBindInfo_GetBindString(This->bind_info, ulStringType, ppwzStr, cEl, pcElFetched);
1035 static const IInternetBindInfoVtbl InternetBindInfoVtbl = {
1036 BindInfo_QueryInterface,
1037 BindInfo_AddRef,
1038 BindInfo_Release,
1039 BindInfo_GetBindInfo,
1040 BindInfo_GetBindString
1043 static inline BindProtocol *impl_from_IInternetPriority(IInternetPriority *iface)
1045 return CONTAINING_RECORD(iface, BindProtocol, IInternetPriority_iface);
1048 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
1049 REFIID riid, void **ppv)
1051 BindProtocol *This = impl_from_IInternetPriority(iface);
1052 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
1055 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
1057 BindProtocol *This = impl_from_IInternetPriority(iface);
1058 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
1061 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
1063 BindProtocol *This = impl_from_IInternetPriority(iface);
1064 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
1067 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
1069 BindProtocol *This = impl_from_IInternetPriority(iface);
1071 TRACE("(%p)->(%d)\n", This, nPriority);
1073 This->priority = nPriority;
1074 return S_OK;
1077 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
1079 BindProtocol *This = impl_from_IInternetPriority(iface);
1081 TRACE("(%p)->(%p)\n", This, pnPriority);
1083 *pnPriority = This->priority;
1084 return S_OK;
1087 static const IInternetPriorityVtbl InternetPriorityVtbl = {
1088 InternetPriority_QueryInterface,
1089 InternetPriority_AddRef,
1090 InternetPriority_Release,
1091 InternetPriority_SetPriority,
1092 InternetPriority_GetPriority
1096 static inline BindProtocol *impl_from_IInternetProtocolSink(IInternetProtocolSink *iface)
1098 return CONTAINING_RECORD(iface, BindProtocol, IInternetProtocolSink_iface);
1101 static HRESULT WINAPI BPInternetProtocolSink_QueryInterface(IInternetProtocolSink *iface,
1102 REFIID riid, void **ppv)
1104 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1105 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
1108 static ULONG WINAPI BPInternetProtocolSink_AddRef(IInternetProtocolSink *iface)
1110 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1111 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
1114 static ULONG WINAPI BPInternetProtocolSink_Release(IInternetProtocolSink *iface)
1116 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1117 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
1120 typedef struct {
1121 task_header_t header;
1122 PROTOCOLDATA *data;
1123 } switch_task_t;
1125 static void switch_proc(BindProtocol *bind, task_header_t *t)
1127 switch_task_t *task = (switch_task_t*)t;
1129 IInternetProtocol_Continue(bind->protocol_handler, task->data);
1131 heap_free(task);
1134 static HRESULT WINAPI BPInternetProtocolSink_Switch(IInternetProtocolSink *iface,
1135 PROTOCOLDATA *pProtocolData)
1137 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1138 PROTOCOLDATA *data;
1140 TRACE("(%p)->(%p)\n", This, pProtocolData);
1142 TRACE("flags %x state %x data %p cb %u\n", pProtocolData->grfFlags, pProtocolData->dwState,
1143 pProtocolData->pData, pProtocolData->cbData);
1145 data = heap_alloc(sizeof(PROTOCOLDATA));
1146 if(!data)
1147 return E_OUTOFMEMORY;
1148 memcpy(data, pProtocolData, sizeof(PROTOCOLDATA));
1150 if((This->pi&PI_APARTMENTTHREADED && pProtocolData->grfFlags&PI_FORCE_ASYNC)
1151 || !do_direct_notif(This)) {
1152 switch_task_t *task;
1154 task = heap_alloc(sizeof(switch_task_t));
1155 if(!task)
1157 heap_free(data);
1158 return E_OUTOFMEMORY;
1161 task->data = data;
1163 push_task(This, &task->header, switch_proc);
1164 return S_OK;
1167 return IInternetProtocolSink_Switch(This->protocol_sink_handler, data);
1170 typedef struct {
1171 task_header_t header;
1173 ULONG status_code;
1174 LPWSTR status_text;
1175 } on_progress_task_t;
1177 static void on_progress_proc(BindProtocol *This, task_header_t *t)
1179 on_progress_task_t *task = (on_progress_task_t*)t;
1181 IInternetProtocolSink_ReportProgress(This->protocol_sink_handler, task->status_code, task->status_text);
1183 heap_free(task->status_text);
1184 heap_free(task);
1187 static HRESULT WINAPI BPInternetProtocolSink_ReportProgress(IInternetProtocolSink *iface,
1188 ULONG ulStatusCode, LPCWSTR szStatusText)
1190 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1192 TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
1194 if(do_direct_notif(This)) {
1195 IInternetProtocolSink_ReportProgress(This->protocol_sink_handler, ulStatusCode, szStatusText);
1196 }else {
1197 on_progress_task_t *task;
1199 task = heap_alloc(sizeof(on_progress_task_t));
1201 task->status_code = ulStatusCode;
1202 task->status_text = heap_strdupW(szStatusText);
1204 push_task(This, &task->header, on_progress_proc);
1207 return S_OK;
1210 typedef struct {
1211 task_header_t header;
1212 DWORD bscf;
1213 ULONG progress;
1214 ULONG progress_max;
1215 } report_data_task_t;
1217 static void report_data_proc(BindProtocol *This, task_header_t *t)
1219 report_data_task_t *task = (report_data_task_t*)t;
1221 IInternetProtocolSink_ReportData(This->protocol_sink_handler,
1222 task->bscf, task->progress, task->progress_max);
1224 heap_free(task);
1227 static HRESULT WINAPI BPInternetProtocolSink_ReportData(IInternetProtocolSink *iface,
1228 DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax)
1230 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1232 TRACE("(%p)->(%x %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
1234 if(!This->protocol_sink)
1235 return S_OK;
1237 if(!do_direct_notif(This)) {
1238 report_data_task_t *task;
1240 task = heap_alloc(sizeof(report_data_task_t));
1241 if(!task)
1242 return E_OUTOFMEMORY;
1244 task->bscf = grfBSCF;
1245 task->progress = ulProgress;
1246 task->progress_max = ulProgressMax;
1248 push_task(This, &task->header, report_data_proc);
1249 return S_OK;
1252 return IInternetProtocolSink_ReportData(This->protocol_sink_handler,
1253 grfBSCF, ulProgress, ulProgressMax);
1256 typedef struct {
1257 task_header_t header;
1259 HRESULT hres;
1260 DWORD err;
1261 LPWSTR str;
1262 } report_result_task_t;
1264 static void report_result_proc(BindProtocol *This, task_header_t *t)
1266 report_result_task_t *task = (report_result_task_t*)t;
1268 IInternetProtocolSink_ReportResult(This->protocol_sink_handler, task->hres, task->err, task->str);
1270 heap_free(task->str);
1271 heap_free(task);
1274 static HRESULT WINAPI BPInternetProtocolSink_ReportResult(IInternetProtocolSink *iface,
1275 HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
1277 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1279 TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
1281 if(!This->protocol_sink)
1282 return E_FAIL;
1283 This->reported_result = TRUE;
1285 if(!do_direct_notif(This)) {
1286 report_result_task_t *task;
1288 task = heap_alloc(sizeof(report_result_task_t));
1289 if(!task)
1290 return E_OUTOFMEMORY;
1292 task->hres = hrResult;
1293 task->err = dwError;
1294 task->str = heap_strdupW(szResult);
1296 push_task(This, &task->header, report_result_proc);
1297 return S_OK;
1300 return IInternetProtocolSink_ReportResult(This->protocol_sink_handler, hrResult, dwError, szResult);
1303 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = {
1304 BPInternetProtocolSink_QueryInterface,
1305 BPInternetProtocolSink_AddRef,
1306 BPInternetProtocolSink_Release,
1307 BPInternetProtocolSink_Switch,
1308 BPInternetProtocolSink_ReportProgress,
1309 BPInternetProtocolSink_ReportData,
1310 BPInternetProtocolSink_ReportResult
1313 static inline BindProtocol *impl_from_IWinInetHttpInfo(IWinInetHttpInfo *iface)
1315 return CONTAINING_RECORD(iface, BindProtocol, IWinInetHttpInfo_iface);
1318 static HRESULT WINAPI WinInetHttpInfo_QueryInterface(IWinInetHttpInfo *iface, REFIID riid, void **ppv)
1320 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1321 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
1324 static ULONG WINAPI WinInetHttpInfo_AddRef(IWinInetHttpInfo *iface)
1326 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1327 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
1330 static ULONG WINAPI WinInetHttpInfo_Release(IWinInetHttpInfo *iface)
1332 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1333 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
1336 static HRESULT WINAPI WinInetHttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD dwOption,
1337 void *pBuffer, DWORD *pcbBuffer)
1339 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1340 FIXME("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer);
1341 return E_NOTIMPL;
1344 static HRESULT WINAPI WinInetHttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption,
1345 void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved)
1347 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1348 FIXME("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved);
1349 return E_NOTIMPL;
1352 static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = {
1353 WinInetHttpInfo_QueryInterface,
1354 WinInetHttpInfo_AddRef,
1355 WinInetHttpInfo_Release,
1356 WinInetHttpInfo_QueryOption,
1357 WinInetHttpInfo_QueryInfo
1360 static inline BindProtocol *impl_from_IServiceProvider(IServiceProvider *iface)
1362 return CONTAINING_RECORD(iface, BindProtocol, IServiceProvider_iface);
1365 static HRESULT WINAPI BPServiceProvider_QueryInterface(IServiceProvider *iface,
1366 REFIID riid, void **ppv)
1368 BindProtocol *This = impl_from_IServiceProvider(iface);
1369 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
1372 static ULONG WINAPI BPServiceProvider_AddRef(IServiceProvider *iface)
1374 BindProtocol *This = impl_from_IServiceProvider(iface);
1375 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
1378 static ULONG WINAPI BPServiceProvider_Release(IServiceProvider *iface)
1380 BindProtocol *This = impl_from_IServiceProvider(iface);
1381 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
1384 static HRESULT WINAPI BPServiceProvider_QueryService(IServiceProvider *iface,
1385 REFGUID guidService, REFIID riid, void **ppv)
1387 BindProtocol *This = impl_from_IServiceProvider(iface);
1389 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
1391 if(!This->service_provider)
1392 return E_NOINTERFACE;
1394 return IServiceProvider_QueryService(This->service_provider, guidService, riid, ppv);
1397 static const IServiceProviderVtbl ServiceProviderVtbl = {
1398 BPServiceProvider_QueryInterface,
1399 BPServiceProvider_AddRef,
1400 BPServiceProvider_Release,
1401 BPServiceProvider_QueryService
1404 HRESULT create_binding_protocol(BOOL from_urlmon, BindProtocol **protocol)
1406 BindProtocol *ret = heap_alloc_zero(sizeof(BindProtocol));
1408 ret->IInternetProtocolEx_iface.lpVtbl = &BindProtocolVtbl;
1409 ret->IInternetBindInfo_iface.lpVtbl = &InternetBindInfoVtbl;
1410 ret->IInternetPriority_iface.lpVtbl = &InternetPriorityVtbl;
1411 ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
1412 ret->IInternetProtocolSink_iface.lpVtbl = &InternetProtocolSinkVtbl;
1413 ret->IWinInetHttpInfo_iface.lpVtbl = &WinInetHttpInfoVtbl;
1415 ret->default_protocol_handler.IInternetProtocol_iface.lpVtbl = &InternetProtocolHandlerVtbl;
1416 ret->default_protocol_handler.IInternetProtocolSink_iface.lpVtbl = &InternetProtocolSinkHandlerVtbl;
1418 ret->ref = 1;
1419 ret->from_urlmon = from_urlmon;
1420 ret->apartment_thread = GetCurrentThreadId();
1421 ret->notif_hwnd = get_notif_hwnd();
1422 ret->protocol_handler = &ret->default_protocol_handler.IInternetProtocol_iface;
1423 ret->protocol_sink_handler = &ret->default_protocol_handler.IInternetProtocolSink_iface;
1424 InitializeCriticalSection(&ret->section);
1425 ret->section.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BindProtocol.section");
1427 URLMON_LockModule();
1429 *protocol = ret;
1430 return S_OK;