urlmon/tests: Remove stray ok() call.
[wine/multimedia.git] / dlls / urlmon / bindprot.c
blob043ff8538b44b4da382cd7bd8214337abc7a944e
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 LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
39 switch(msg) {
40 case WM_MK_CONTINUE: {
41 BindProtocol *This = (BindProtocol*)lParam;
42 task_header_t *task;
44 while(1) {
45 EnterCriticalSection(&This->section);
47 task = This->task_queue_head;
48 if(task) {
49 This->task_queue_head = task->next;
50 if(!This->task_queue_head)
51 This->task_queue_tail = NULL;
54 LeaveCriticalSection(&This->section);
56 if(!task)
57 break;
59 This->continue_call++;
60 task->proc(This, task);
61 This->continue_call--;
64 IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
65 return 0;
67 case WM_MK_RELEASE: {
68 tls_data_t *data = get_tls_data();
70 if(!--data->notif_hwnd_cnt) {
71 DestroyWindow(hwnd);
72 data->notif_hwnd = NULL;
77 return DefWindowProcW(hwnd, msg, wParam, lParam);
80 HWND get_notif_hwnd(void)
82 static ATOM wnd_class = 0;
83 tls_data_t *tls_data;
85 static const WCHAR wszURLMonikerNotificationWindow[] =
86 {'U','R','L',' ','M','o','n','i','k','e','r',' ',
87 'N','o','t','i','f','i','c','a','t','i','o','n',' ','W','i','n','d','o','w',0};
89 tls_data = get_tls_data();
90 if(!tls_data)
91 return NULL;
93 if(tls_data->notif_hwnd_cnt) {
94 tls_data->notif_hwnd_cnt++;
95 return tls_data->notif_hwnd;
98 if(!wnd_class) {
99 static WNDCLASSEXW wndclass = {
100 sizeof(wndclass), 0,
101 notif_wnd_proc, 0, 0,
102 NULL, NULL, NULL, NULL, NULL,
103 wszURLMonikerNotificationWindow,
104 NULL
107 wndclass.hInstance = hProxyDll;
109 wnd_class = RegisterClassExW(&wndclass);
110 if (!wnd_class && GetLastError() == ERROR_CLASS_ALREADY_EXISTS)
111 wnd_class = 1;
114 tls_data->notif_hwnd = CreateWindowExW(0, wszURLMonikerNotificationWindow,
115 wszURLMonikerNotificationWindow, 0, 0, 0, 0, 0, HWND_MESSAGE,
116 NULL, hProxyDll, NULL);
117 if(tls_data->notif_hwnd)
118 tls_data->notif_hwnd_cnt++;
120 TRACE("hwnd = %p\n", tls_data->notif_hwnd);
122 return tls_data->notif_hwnd;
125 void release_notif_hwnd(HWND hwnd)
127 tls_data_t *data = get_tls_data();
129 if(!data)
130 return;
132 if(data->notif_hwnd != hwnd) {
133 PostMessageW(data->notif_hwnd, WM_MK_RELEASE, 0, 0);
134 return;
137 if(!--data->notif_hwnd_cnt) {
138 DestroyWindow(data->notif_hwnd);
139 data->notif_hwnd = NULL;
143 static void push_task(BindProtocol *This, task_header_t *task, task_proc_t proc)
145 BOOL do_post = FALSE;
147 task->proc = proc;
148 task->next = NULL;
150 EnterCriticalSection(&This->section);
152 if(This->task_queue_tail) {
153 This->task_queue_tail->next = task;
154 This->task_queue_tail = task;
155 }else {
156 This->task_queue_tail = This->task_queue_head = task;
157 do_post = !This->continue_call;
160 LeaveCriticalSection(&This->section);
162 if(do_post) {
163 IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
164 PostMessageW(This->notif_hwnd, WM_MK_CONTINUE, 0, (LPARAM)This);
168 static inline BOOL do_direct_notif(BindProtocol *This)
170 return !(This->pi & PI_APARTMENTTHREADED) || (This->apartment_thread == GetCurrentThreadId() && !This->continue_call);
173 static HRESULT handle_mime_filter(BindProtocol *This, IInternetProtocol *mime_filter)
175 PROTOCOLFILTERDATA filter_data = { sizeof(PROTOCOLFILTERDATA), NULL, NULL, NULL, 0 };
176 HRESULT hres;
178 hres = IInternetProtocol_QueryInterface(mime_filter, &IID_IInternetProtocolSink, (void**)&This->protocol_sink_handler);
179 if(FAILED(hres)) {
180 This->protocol_sink_handler = &This->default_protocol_handler.IInternetProtocolSink_iface;
181 return hres;
184 IInternetProtocol_AddRef(mime_filter);
185 This->protocol_handler = mime_filter;
187 filter_data.pProtocol = &This->default_protocol_handler.IInternetProtocol_iface;
188 hres = IInternetProtocol_Start(mime_filter, This->mime, &This->default_protocol_handler.IInternetProtocolSink_iface,
189 &This->IInternetBindInfo_iface, PI_FILTER_MODE|PI_FORCE_ASYNC,
190 (HANDLE_PTR)&filter_data);
191 if(FAILED(hres)) {
192 IInternetProtocolSink_Release(This->protocol_sink_handler);
193 IInternetProtocol_Release(This->protocol_handler);
194 This->protocol_sink_handler = &This->default_protocol_handler.IInternetProtocolSink_iface;
195 This->protocol_handler = &This->default_protocol_handler.IInternetProtocol_iface;
196 return hres;
199 /* NOTE: IE9 calls it on the new protocol_sink. It doesn't make sense to is seems to be a bug there. */
200 IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_LOADINGMIMEHANDLER, NULL);
202 return S_OK;
205 static void mime_available(BindProtocol *This, LPCWSTR mime, BOOL verified)
207 IInternetProtocol *mime_filter;
208 HRESULT hres;
210 heap_free(This->mime);
211 This->mime = heap_strdupW(mime);
213 if(This->protocol_handler==&This->default_protocol_handler.IInternetProtocol_iface
214 && (mime_filter = get_mime_filter(mime))) {
215 TRACE("Got mime filter for %s\n", debugstr_w(mime));
217 hres = handle_mime_filter(This, mime_filter);
218 IInternetProtocol_Release(mime_filter);
219 if(FAILED(hres))
220 FIXME("MIME filter failed: %08x\n", hres);
223 if(This->reported_mime || verified || !(This->pi & PI_MIMEVERIFICATION)) {
224 This->reported_mime = TRUE;
225 IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, mime);
229 static inline BindProtocol *impl_from_IInternetProtocolEx(IInternetProtocolEx *iface)
231 return CONTAINING_RECORD(iface, BindProtocol, IInternetProtocolEx_iface);
234 static HRESULT WINAPI BindProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
236 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
238 *ppv = NULL;
239 if(IsEqualGUID(&IID_IUnknown, riid)) {
240 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
241 *ppv = &This->IInternetProtocolEx_iface;
242 }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
243 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
244 *ppv = &This->IInternetProtocolEx_iface;
245 }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
246 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
247 *ppv = &This->IInternetProtocolEx_iface;
248 }else if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) {
249 TRACE("(%p)->(IID_IInternetProtocolEx %p)\n", This, ppv);
250 *ppv = &This->IInternetProtocolEx_iface;
251 }else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) {
252 TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This, ppv);
253 *ppv = &This->IInternetBindInfo_iface;
254 }else if(IsEqualGUID(&IID_IInternetPriority, riid)) {
255 TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv);
256 *ppv = &This->IInternetPriority_iface;
257 }else if(IsEqualGUID(&IID_IAuthenticate, riid)) {
258 FIXME("(%p)->(IID_IAuthenticate %p)\n", This, ppv);
259 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
260 TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
261 *ppv = &This->IServiceProvider_iface;
262 }else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
263 TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
264 *ppv = &This->IInternetProtocolSink_iface;
265 }else if(IsEqualGUID(&IID_IWinInetInfo, riid)) {
266 TRACE("(%p)->(IID_IWinInetInfo %p)\n", This, ppv);
268 if(This->protocol) {
269 IWinInetInfo *inet_info;
270 HRESULT hres;
272 hres = IInternetProtocol_QueryInterface(This->protocol, &IID_IWinInetInfo, (void**)&inet_info);
273 if(SUCCEEDED(hres)) {
274 *ppv = &This->IWinInetHttpInfo_iface;
275 IWinInetInfo_Release(inet_info);
278 }else if(IsEqualGUID(&IID_IWinInetHttpInfo, riid)) {
279 TRACE("(%p)->(IID_IWinInetHttpInfo %p)\n", This, ppv);
281 if(This->protocol) {
282 IWinInetHttpInfo *http_info;
283 HRESULT hres;
285 hres = IInternetProtocol_QueryInterface(This->protocol, &IID_IWinInetHttpInfo, (void**)&http_info);
286 if(SUCCEEDED(hres)) {
287 *ppv = &This->IWinInetHttpInfo_iface;
288 IWinInetHttpInfo_Release(http_info);
291 }else {
292 WARN("not supported interface %s\n", debugstr_guid(riid));
295 if(!*ppv)
296 return E_NOINTERFACE;
298 IUnknown_AddRef((IUnknown*)*ppv);
299 return S_OK;
302 static ULONG WINAPI BindProtocol_AddRef(IInternetProtocolEx *iface)
304 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
305 LONG ref = InterlockedIncrement(&This->ref);
306 TRACE("(%p) ref=%d\n", This, ref);
307 return ref;
310 static ULONG WINAPI BindProtocol_Release(IInternetProtocolEx *iface)
312 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
313 LONG ref = InterlockedDecrement(&This->ref);
315 TRACE("(%p) ref=%d\n", This, ref);
317 if(!ref) {
318 if(This->wininet_info)
319 IWinInetInfo_Release(This->wininet_info);
320 if(This->wininet_http_info)
321 IWinInetHttpInfo_Release(This->wininet_http_info);
322 if(This->protocol)
323 IInternetProtocol_Release(This->protocol);
324 if(This->bind_info)
325 IInternetBindInfo_Release(This->bind_info);
326 if(This->protocol_handler && This->protocol_handler != &This->default_protocol_handler.IInternetProtocol_iface)
327 IInternetProtocol_Release(This->protocol_handler);
328 if(This->protocol_sink_handler &&
329 This->protocol_sink_handler != &This->default_protocol_handler.IInternetProtocolSink_iface)
330 IInternetProtocolSink_Release(This->protocol_sink_handler);
331 if(This->uri)
332 IUri_Release(This->uri);
333 SysFreeString(This->display_uri);
335 set_binding_sink(This, NULL, NULL);
337 if(This->notif_hwnd)
338 release_notif_hwnd(This->notif_hwnd);
339 This->section.DebugInfo->Spare[0] = 0;
340 DeleteCriticalSection(&This->section);
342 heap_free(This->mime);
343 heap_free(This);
345 URLMON_UnlockModule();
348 return ref;
351 static HRESULT WINAPI BindProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
352 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
353 DWORD grfPI, HANDLE_PTR dwReserved)
355 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
356 IUri *uri;
357 HRESULT hres;
359 TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
360 pOIBindInfo, grfPI, dwReserved);
362 hres = CreateUri(szUrl, Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri);
363 if(FAILED(hres))
364 return hres;
366 hres = IInternetProtocolEx_StartEx(&This->IInternetProtocolEx_iface, uri, pOIProtSink,
367 pOIBindInfo, grfPI, (HANDLE*)dwReserved);
369 IUri_Release(uri);
370 return hres;
373 static HRESULT WINAPI BindProtocol_Continue(IInternetProtocolEx *iface, PROTOCOLDATA *pProtocolData)
375 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
377 TRACE("(%p)->(%p)\n", This, pProtocolData);
379 return IInternetProtocol_Continue(This->protocol_handler, pProtocolData);
382 static HRESULT WINAPI BindProtocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason,
383 DWORD dwOptions)
385 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
387 TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
389 return IInternetProtocol_Abort(This->protocol_handler, hrReason, dwOptions);
392 static HRESULT WINAPI BindProtocol_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
394 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
396 TRACE("(%p)->(%08x)\n", This, dwOptions);
398 return IInternetProtocol_Terminate(This->protocol_handler, dwOptions);
401 static HRESULT WINAPI BindProtocol_Suspend(IInternetProtocolEx *iface)
403 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
404 FIXME("(%p)\n", This);
405 return E_NOTIMPL;
408 static HRESULT WINAPI BindProtocol_Resume(IInternetProtocolEx *iface)
410 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
411 FIXME("(%p)\n", This);
412 return E_NOTIMPL;
415 static HRESULT WINAPI BindProtocol_Read(IInternetProtocolEx *iface, void *pv,
416 ULONG cb, ULONG *pcbRead)
418 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
420 TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
422 if(pcbRead)
423 *pcbRead = 0;
424 return IInternetProtocol_Read(This->protocol_handler, pv, cb, pcbRead);
427 static HRESULT WINAPI BindProtocol_Seek(IInternetProtocolEx *iface, LARGE_INTEGER dlibMove,
428 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
430 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
431 FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
432 return E_NOTIMPL;
435 static HRESULT WINAPI BindProtocol_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
437 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
439 TRACE("(%p)->(%08x)\n", This, dwOptions);
441 return IInternetProtocol_LockRequest(This->protocol_handler, dwOptions);
444 static HRESULT WINAPI BindProtocol_UnlockRequest(IInternetProtocolEx *iface)
446 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
448 TRACE("(%p)\n", This);
450 return IInternetProtocol_UnlockRequest(This->protocol_handler);
453 static HRESULT WINAPI BindProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUri,
454 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
455 DWORD grfPI, HANDLE *dwReserved)
457 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
458 IInternetProtocol *protocol = NULL;
459 IInternetProtocolEx *protocolex;
460 IInternetPriority *priority;
461 IServiceProvider *service_provider;
462 BOOL urlmon_protocol = FALSE;
463 CLSID clsid = IID_NULL;
464 LPOLESTR clsid_str;
465 HRESULT hres;
467 TRACE("(%p)->(%p %p %p %08x %p)\n", This, pUri, pOIProtSink, pOIBindInfo, grfPI, dwReserved);
469 if(!pUri || !pOIProtSink || !pOIBindInfo)
470 return E_INVALIDARG;
472 This->pi = grfPI;
474 IUri_AddRef(pUri);
475 This->uri = pUri;
477 hres = IInternetProtocolSink_QueryInterface(pOIProtSink, &IID_IServiceProvider,
478 (void**)&service_provider);
479 if(SUCCEEDED(hres)) {
480 /* FIXME: What's protocol CLSID here? */
481 IServiceProvider_QueryService(service_provider, &IID_IInternetProtocol,
482 &IID_IInternetProtocol, (void**)&protocol);
483 IServiceProvider_Release(service_provider);
486 if(!protocol) {
487 IClassFactory *cf;
488 IUnknown *unk;
490 hres = get_protocol_handler(pUri, &clsid, &urlmon_protocol, &cf);
491 if(FAILED(hres))
492 return hres;
494 if(This->from_urlmon) {
495 hres = IClassFactory_CreateInstance(cf, NULL, &IID_IInternetProtocol, (void**)&protocol);
496 IClassFactory_Release(cf);
497 if(FAILED(hres))
498 return hres;
499 }else {
500 hres = IClassFactory_CreateInstance(cf, (IUnknown*)&This->IInternetBindInfo_iface,
501 &IID_IUnknown, (void**)&unk);
502 IClassFactory_Release(cf);
503 if(FAILED(hres))
504 return hres;
506 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocol, (void**)&protocol);
507 IUnknown_Release(unk);
508 if(FAILED(hres))
509 return hres;
513 StringFromCLSID(&clsid, &clsid_str);
514 IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_PROTOCOLCLASSID, clsid_str);
515 CoTaskMemFree(clsid_str);
517 This->protocol = protocol;
519 if(urlmon_protocol) {
520 IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&This->wininet_info);
521 IInternetProtocol_QueryInterface(protocol, &IID_IWinInetHttpInfo, (void**)&This->wininet_http_info);
524 set_binding_sink(This, pOIProtSink, pOIBindInfo);
526 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
527 if(SUCCEEDED(hres)) {
528 IInternetPriority_SetPriority(priority, This->priority);
529 IInternetPriority_Release(priority);
532 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolEx, (void**)&protocolex);
533 if(SUCCEEDED(hres)) {
534 hres = IInternetProtocolEx_StartEx(protocolex, pUri, &This->IInternetProtocolSink_iface,
535 &This->IInternetBindInfo_iface, 0, NULL);
536 IInternetProtocolEx_Release(protocolex);
537 }else {
538 hres = IUri_GetDisplayUri(pUri, &This->display_uri);
539 if(FAILED(hres))
540 return hres;
542 hres = IInternetProtocol_Start(protocol, This->display_uri, &This->IInternetProtocolSink_iface,
543 &This->IInternetBindInfo_iface, 0, 0);
546 return hres;
549 void set_binding_sink(BindProtocol *This, IInternetProtocolSink *sink, IInternetBindInfo *bind_info)
551 IInternetProtocolSink *prev_sink;
552 IServiceProvider *service_provider = NULL;
554 if(sink)
555 IInternetProtocolSink_AddRef(sink);
556 prev_sink = InterlockedExchangePointer((void**)&This->protocol_sink, sink);
557 if(prev_sink)
558 IInternetProtocolSink_Release(prev_sink);
560 if(sink)
561 IInternetProtocolSink_QueryInterface(sink, &IID_IServiceProvider, (void**)&service_provider);
562 service_provider = InterlockedExchangePointer((void**)&This->service_provider, service_provider);
563 if(service_provider)
564 IServiceProvider_Release(service_provider);
566 if(bind_info)
567 IInternetBindInfo_AddRef(bind_info);
568 bind_info = InterlockedExchangePointer((void**)&This->bind_info, bind_info);
569 if(bind_info)
570 IInternetBindInfo_Release(bind_info);
573 static const IInternetProtocolExVtbl BindProtocolVtbl = {
574 BindProtocol_QueryInterface,
575 BindProtocol_AddRef,
576 BindProtocol_Release,
577 BindProtocol_Start,
578 BindProtocol_Continue,
579 BindProtocol_Abort,
580 BindProtocol_Terminate,
581 BindProtocol_Suspend,
582 BindProtocol_Resume,
583 BindProtocol_Read,
584 BindProtocol_Seek,
585 BindProtocol_LockRequest,
586 BindProtocol_UnlockRequest,
587 BindProtocol_StartEx
590 static inline BindProtocol *impl_from_IInternetProtocol(IInternetProtocol *iface)
592 return CONTAINING_RECORD(iface, BindProtocol, default_protocol_handler.IInternetProtocol_iface);
595 static HRESULT WINAPI ProtocolHandler_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
597 BindProtocol *This = impl_from_IInternetProtocol(iface);
599 *ppv = NULL;
600 if(IsEqualGUID(&IID_IUnknown, riid)) {
601 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
602 *ppv = &This->default_protocol_handler.IInternetProtocol_iface;
603 }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
604 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
605 *ppv = &This->default_protocol_handler.IInternetProtocol_iface;
606 }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
607 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
608 *ppv = &This->default_protocol_handler.IInternetProtocol_iface;
609 }else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
610 TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
611 *ppv = &This->default_protocol_handler.IInternetProtocolSink_iface;
614 if(*ppv) {
615 IInternetProtocol_AddRef(iface);
616 return S_OK;
619 WARN("not supported interface %s\n", debugstr_guid(riid));
620 return E_NOINTERFACE;
623 static ULONG WINAPI ProtocolHandler_AddRef(IInternetProtocol *iface)
625 BindProtocol *This = impl_from_IInternetProtocol(iface);
626 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
629 static ULONG WINAPI ProtocolHandler_Release(IInternetProtocol *iface)
631 BindProtocol *This = impl_from_IInternetProtocol(iface);
632 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
635 static HRESULT WINAPI ProtocolHandler_Start(IInternetProtocol *iface, LPCWSTR szUrl,
636 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
637 DWORD grfPI, HANDLE_PTR dwReserved)
639 ERR("Should not be called\n");
640 return E_NOTIMPL;
643 static HRESULT WINAPI ProtocolHandler_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
645 BindProtocol *This = impl_from_IInternetProtocol(iface);
646 HRESULT hres;
648 TRACE("(%p)->(%p)\n", This, pProtocolData);
650 hres = IInternetProtocol_Continue(This->protocol, pProtocolData);
652 heap_free(pProtocolData);
653 return hres;
656 static HRESULT WINAPI ProtocolHandler_Abort(IInternetProtocol *iface, HRESULT hrReason,
657 DWORD dwOptions)
659 BindProtocol *This = impl_from_IInternetProtocol(iface);
661 TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
663 if(This->protocol && !This->reported_result)
664 return IInternetProtocol_Abort(This->protocol, hrReason, dwOptions);
666 return S_OK;
669 static HRESULT WINAPI ProtocolHandler_Terminate(IInternetProtocol *iface, DWORD dwOptions)
671 BindProtocol *This = impl_from_IInternetProtocol(iface);
673 TRACE("(%p)->(%08x)\n", This, dwOptions);
675 if(!This->reported_result)
676 return E_FAIL;
678 IInternetProtocol_Terminate(This->protocol, 0);
680 set_binding_sink(This, NULL, NULL);
682 if(This->bind_info) {
683 IInternetBindInfo_Release(This->bind_info);
684 This->bind_info = NULL;
687 return S_OK;
690 static HRESULT WINAPI ProtocolHandler_Suspend(IInternetProtocol *iface)
692 BindProtocol *This = impl_from_IInternetProtocol(iface);
693 FIXME("(%p)\n", This);
694 return E_NOTIMPL;
697 static HRESULT WINAPI ProtocolHandler_Resume(IInternetProtocol *iface)
699 BindProtocol *This = impl_from_IInternetProtocol(iface);
700 FIXME("(%p)\n", This);
701 return E_NOTIMPL;
704 static HRESULT WINAPI ProtocolHandler_Read(IInternetProtocol *iface, void *pv,
705 ULONG cb, ULONG *pcbRead)
707 BindProtocol *This = impl_from_IInternetProtocol(iface);
708 ULONG read = 0;
709 HRESULT hres = S_OK;
711 TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
713 if(This->buf_size) {
714 read = min(cb, This->buf_size);
715 memcpy(pv, This->buf, read);
717 if(read == This->buf_size) {
718 heap_free(This->buf);
719 This->buf = NULL;
720 }else {
721 memmove(This->buf, This->buf+cb, This->buf_size-cb);
724 This->buf_size -= read;
727 if(read < cb) {
728 ULONG cread = 0;
730 hres = IInternetProtocol_Read(This->protocol, (BYTE*)pv+read, cb-read, &cread);
731 read += cread;
734 *pcbRead = read;
735 return hres;
738 static HRESULT WINAPI ProtocolHandler_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
739 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
741 BindProtocol *This = impl_from_IInternetProtocol(iface);
742 FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
743 return E_NOTIMPL;
746 static HRESULT WINAPI ProtocolHandler_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
748 BindProtocol *This = impl_from_IInternetProtocol(iface);
750 TRACE("(%p)->(%08x)\n", This, dwOptions);
752 return IInternetProtocol_LockRequest(This->protocol, dwOptions);
755 static HRESULT WINAPI ProtocolHandler_UnlockRequest(IInternetProtocol *iface)
757 BindProtocol *This = impl_from_IInternetProtocol(iface);
759 TRACE("(%p)\n", This);
761 return IInternetProtocol_UnlockRequest(This->protocol);
764 static const IInternetProtocolVtbl InternetProtocolHandlerVtbl = {
765 ProtocolHandler_QueryInterface,
766 ProtocolHandler_AddRef,
767 ProtocolHandler_Release,
768 ProtocolHandler_Start,
769 ProtocolHandler_Continue,
770 ProtocolHandler_Abort,
771 ProtocolHandler_Terminate,
772 ProtocolHandler_Suspend,
773 ProtocolHandler_Resume,
774 ProtocolHandler_Read,
775 ProtocolHandler_Seek,
776 ProtocolHandler_LockRequest,
777 ProtocolHandler_UnlockRequest
780 static inline BindProtocol *impl_from_IInternetProtocolSinkHandler(IInternetProtocolSink *iface)
782 return CONTAINING_RECORD(iface, BindProtocol, default_protocol_handler.IInternetProtocolSink_iface);
785 static HRESULT WINAPI ProtocolSinkHandler_QueryInterface(IInternetProtocolSink *iface,
786 REFIID riid, void **ppvObject)
788 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
789 return IInternetProtocol_QueryInterface(&This->default_protocol_handler.IInternetProtocol_iface,
790 riid, ppvObject);
793 static ULONG WINAPI ProtocolSinkHandler_AddRef(IInternetProtocolSink *iface)
795 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
796 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
799 static ULONG WINAPI ProtocolSinkHandler_Release(IInternetProtocolSink *iface)
801 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
802 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
805 static HRESULT WINAPI ProtocolSinkHandler_Switch(IInternetProtocolSink *iface,
806 PROTOCOLDATA *pProtocolData)
808 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
810 TRACE("(%p)->(%p)\n", This, pProtocolData);
812 if(!This->protocol_sink) {
813 IInternetProtocol_Continue(This->protocol_handler, pProtocolData);
814 return S_OK;
817 return IInternetProtocolSink_Switch(This->protocol_sink, pProtocolData);
820 static HRESULT WINAPI ProtocolSinkHandler_ReportProgress(IInternetProtocolSink *iface,
821 ULONG status_code, LPCWSTR status_text)
823 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
825 TRACE("(%p)->(%u %s)\n", This, status_code, debugstr_w(status_text));
827 if(!This->protocol_sink)
828 return S_OK;
830 switch(status_code) {
831 case BINDSTATUS_FINDINGRESOURCE:
832 case BINDSTATUS_CONNECTING:
833 case BINDSTATUS_REDIRECTING:
834 case BINDSTATUS_SENDINGREQUEST:
835 case BINDSTATUS_CACHEFILENAMEAVAILABLE:
836 case BINDSTATUS_DIRECTBIND:
837 case BINDSTATUS_ACCEPTRANGES:
838 case BINDSTATUS_DECODING:
839 IInternetProtocolSink_ReportProgress(This->protocol_sink, status_code, status_text);
840 break;
842 case BINDSTATUS_BEGINDOWNLOADDATA:
843 IInternetProtocolSink_ReportData(This->protocol_sink, This->bscf, This->progress, This->progress_max);
844 break;
846 case BINDSTATUS_MIMETYPEAVAILABLE:
847 mime_available(This, status_text, FALSE);
848 break;
850 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
851 mime_available(This, status_text, TRUE);
852 break;
854 default:
855 FIXME("unsupported ulStatusCode %u\n", status_code);
858 return S_OK;
861 static HRESULT WINAPI ProtocolSinkHandler_ReportData(IInternetProtocolSink *iface,
862 DWORD bscf, ULONG progress, ULONG progress_max)
864 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
866 TRACE("(%p)->(%x %u %u)\n", This, bscf, progress, progress_max);
868 This->bscf = bscf;
869 This->progress = progress;
870 This->progress_max = progress_max;
872 if(!This->protocol_sink)
873 return S_OK;
875 if((This->pi & PI_MIMEVERIFICATION) && !This->reported_mime) {
876 BYTE buf[BUFFER_SIZE];
877 DWORD read = 0;
878 LPWSTR mime;
879 HRESULT hres;
881 do {
882 read = 0;
883 hres = IInternetProtocol_Read(This->protocol, buf,
884 sizeof(buf)-This->buf_size, &read);
885 if(FAILED(hres) && hres != E_PENDING)
886 return hres;
888 if(!This->buf) {
889 This->buf = heap_alloc(BUFFER_SIZE);
890 if(!This->buf)
891 return E_OUTOFMEMORY;
892 }else if(read + This->buf_size > BUFFER_SIZE) {
893 BYTE *tmp;
895 tmp = heap_realloc(This->buf, read+This->buf_size);
896 if(!tmp)
897 return E_OUTOFMEMORY;
898 This->buf = tmp;
901 memcpy(This->buf+This->buf_size, buf, read);
902 This->buf_size += read;
903 }while(This->buf_size < MIME_TEST_SIZE && hres == S_OK);
905 if(This->buf_size < MIME_TEST_SIZE && hres != S_FALSE)
906 return S_OK;
908 bscf = BSCF_FIRSTDATANOTIFICATION;
909 if(hres == S_FALSE)
910 bscf |= BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE;
912 if(!This->reported_mime) {
913 BSTR raw_uri;
915 hres = IUri_GetRawUri(This->uri, &raw_uri);
916 if(FAILED(hres))
917 return hres;
919 hres = FindMimeFromData(NULL, raw_uri, This->buf, min(This->buf_size, MIME_TEST_SIZE),
920 This->mime, 0, &mime, 0);
921 SysFreeString(raw_uri);
922 if(FAILED(hres))
923 return hres;
925 heap_free(This->mime);
926 This->mime = heap_strdupW(mime);
927 CoTaskMemFree(mime);
928 This->reported_mime = TRUE;
929 if(This->protocol_sink)
930 IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, This->mime);
934 if(!This->protocol_sink)
935 return S_OK;
937 return IInternetProtocolSink_ReportData(This->protocol_sink, bscf, progress, progress_max);
940 static HRESULT WINAPI ProtocolSinkHandler_ReportResult(IInternetProtocolSink *iface,
941 HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
943 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
945 TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
947 if(This->protocol_sink)
948 return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
949 return S_OK;
952 static const IInternetProtocolSinkVtbl InternetProtocolSinkHandlerVtbl = {
953 ProtocolSinkHandler_QueryInterface,
954 ProtocolSinkHandler_AddRef,
955 ProtocolSinkHandler_Release,
956 ProtocolSinkHandler_Switch,
957 ProtocolSinkHandler_ReportProgress,
958 ProtocolSinkHandler_ReportData,
959 ProtocolSinkHandler_ReportResult
962 static inline BindProtocol *impl_from_IInternetBindInfo(IInternetBindInfo *iface)
964 return CONTAINING_RECORD(iface, BindProtocol, IInternetBindInfo_iface);
967 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface,
968 REFIID riid, void **ppv)
970 BindProtocol *This = impl_from_IInternetBindInfo(iface);
971 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
974 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
976 BindProtocol *This = impl_from_IInternetBindInfo(iface);
977 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
980 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
982 BindProtocol *This = impl_from_IInternetBindInfo(iface);
983 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
986 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface,
987 DWORD *grfBINDF, BINDINFO *pbindinfo)
989 BindProtocol *This = impl_from_IInternetBindInfo(iface);
990 HRESULT hres;
992 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
994 hres = IInternetBindInfo_GetBindInfo(This->bind_info, grfBINDF, pbindinfo);
995 if(FAILED(hres)) {
996 WARN("GetBindInfo failed: %08x\n", hres);
997 return hres;
1000 *grfBINDF |= BINDF_FROMURLMON;
1001 return hres;
1004 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface,
1005 ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
1007 BindProtocol *This = impl_from_IInternetBindInfo(iface);
1009 TRACE("(%p)->(%d %p %d %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched);
1011 return IInternetBindInfo_GetBindString(This->bind_info, ulStringType, ppwzStr, cEl, pcElFetched);
1014 static const IInternetBindInfoVtbl InternetBindInfoVtbl = {
1015 BindInfo_QueryInterface,
1016 BindInfo_AddRef,
1017 BindInfo_Release,
1018 BindInfo_GetBindInfo,
1019 BindInfo_GetBindString
1022 static inline BindProtocol *impl_from_IInternetPriority(IInternetPriority *iface)
1024 return CONTAINING_RECORD(iface, BindProtocol, IInternetPriority_iface);
1027 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
1028 REFIID riid, void **ppv)
1030 BindProtocol *This = impl_from_IInternetPriority(iface);
1031 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
1034 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
1036 BindProtocol *This = impl_from_IInternetPriority(iface);
1037 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
1040 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
1042 BindProtocol *This = impl_from_IInternetPriority(iface);
1043 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
1046 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
1048 BindProtocol *This = impl_from_IInternetPriority(iface);
1050 TRACE("(%p)->(%d)\n", This, nPriority);
1052 This->priority = nPriority;
1053 return S_OK;
1056 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
1058 BindProtocol *This = impl_from_IInternetPriority(iface);
1060 TRACE("(%p)->(%p)\n", This, pnPriority);
1062 *pnPriority = This->priority;
1063 return S_OK;
1066 static const IInternetPriorityVtbl InternetPriorityVtbl = {
1067 InternetPriority_QueryInterface,
1068 InternetPriority_AddRef,
1069 InternetPriority_Release,
1070 InternetPriority_SetPriority,
1071 InternetPriority_GetPriority
1075 static inline BindProtocol *impl_from_IInternetProtocolSink(IInternetProtocolSink *iface)
1077 return CONTAINING_RECORD(iface, BindProtocol, IInternetProtocolSink_iface);
1080 static HRESULT WINAPI BPInternetProtocolSink_QueryInterface(IInternetProtocolSink *iface,
1081 REFIID riid, void **ppv)
1083 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1084 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
1087 static ULONG WINAPI BPInternetProtocolSink_AddRef(IInternetProtocolSink *iface)
1089 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1090 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
1093 static ULONG WINAPI BPInternetProtocolSink_Release(IInternetProtocolSink *iface)
1095 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1096 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
1099 typedef struct {
1100 task_header_t header;
1101 PROTOCOLDATA *data;
1102 } switch_task_t;
1104 static void switch_proc(BindProtocol *bind, task_header_t *t)
1106 switch_task_t *task = (switch_task_t*)t;
1108 IInternetProtocol_Continue(bind->protocol_handler, task->data);
1110 heap_free(task);
1113 static HRESULT WINAPI BPInternetProtocolSink_Switch(IInternetProtocolSink *iface,
1114 PROTOCOLDATA *pProtocolData)
1116 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1117 PROTOCOLDATA *data;
1119 TRACE("(%p)->(%p)\n", This, pProtocolData);
1121 TRACE("flags %x state %x data %p cb %u\n", pProtocolData->grfFlags, pProtocolData->dwState,
1122 pProtocolData->pData, pProtocolData->cbData);
1124 data = heap_alloc(sizeof(PROTOCOLDATA));
1125 if(!data)
1126 return E_OUTOFMEMORY;
1127 memcpy(data, pProtocolData, sizeof(PROTOCOLDATA));
1129 if((This->pi&PI_APARTMENTTHREADED && pProtocolData->grfFlags&PI_FORCE_ASYNC)
1130 || !do_direct_notif(This)) {
1131 switch_task_t *task;
1133 task = heap_alloc(sizeof(switch_task_t));
1134 if(!task)
1135 return E_OUTOFMEMORY;
1137 task->data = data;
1139 push_task(This, &task->header, switch_proc);
1140 return S_OK;
1143 return IInternetProtocolSink_Switch(This->protocol_sink_handler, data);
1146 typedef struct {
1147 task_header_t header;
1149 ULONG status_code;
1150 LPWSTR status_text;
1151 } on_progress_task_t;
1153 static void on_progress_proc(BindProtocol *This, task_header_t *t)
1155 on_progress_task_t *task = (on_progress_task_t*)t;
1157 IInternetProtocolSink_ReportProgress(This->protocol_sink_handler, task->status_code, task->status_text);
1159 heap_free(task->status_text);
1160 heap_free(task);
1163 static HRESULT WINAPI BPInternetProtocolSink_ReportProgress(IInternetProtocolSink *iface,
1164 ULONG ulStatusCode, LPCWSTR szStatusText)
1166 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1168 TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
1170 if(do_direct_notif(This)) {
1171 IInternetProtocolSink_ReportProgress(This->protocol_sink_handler, ulStatusCode, szStatusText);
1172 }else {
1173 on_progress_task_t *task;
1175 task = heap_alloc(sizeof(on_progress_task_t));
1177 task->status_code = ulStatusCode;
1178 task->status_text = heap_strdupW(szStatusText);
1180 push_task(This, &task->header, on_progress_proc);
1183 return S_OK;
1186 typedef struct {
1187 task_header_t header;
1188 DWORD bscf;
1189 ULONG progress;
1190 ULONG progress_max;
1191 } report_data_task_t;
1193 static void report_data_proc(BindProtocol *This, task_header_t *t)
1195 report_data_task_t *task = (report_data_task_t*)t;
1197 IInternetProtocolSink_ReportData(This->protocol_sink_handler,
1198 task->bscf, task->progress, task->progress_max);
1200 heap_free(task);
1203 static HRESULT WINAPI BPInternetProtocolSink_ReportData(IInternetProtocolSink *iface,
1204 DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax)
1206 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1208 TRACE("(%p)->(%x %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
1210 if(!This->protocol_sink)
1211 return S_OK;
1213 if(!do_direct_notif(This)) {
1214 report_data_task_t *task;
1216 task = heap_alloc(sizeof(report_data_task_t));
1217 if(!task)
1218 return E_OUTOFMEMORY;
1220 task->bscf = grfBSCF;
1221 task->progress = ulProgress;
1222 task->progress_max = ulProgressMax;
1224 push_task(This, &task->header, report_data_proc);
1225 return S_OK;
1228 return IInternetProtocolSink_ReportData(This->protocol_sink_handler,
1229 grfBSCF, ulProgress, ulProgressMax);
1232 typedef struct {
1233 task_header_t header;
1235 HRESULT hres;
1236 DWORD err;
1237 LPWSTR str;
1238 } report_result_task_t;
1240 static void report_result_proc(BindProtocol *This, task_header_t *t)
1242 report_result_task_t *task = (report_result_task_t*)t;
1244 IInternetProtocolSink_ReportResult(This->protocol_sink_handler, task->hres, task->err, task->str);
1246 heap_free(task->str);
1247 heap_free(task);
1250 static HRESULT WINAPI BPInternetProtocolSink_ReportResult(IInternetProtocolSink *iface,
1251 HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
1253 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1255 TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
1257 if(!This->protocol_sink)
1258 return E_FAIL;
1259 This->reported_result = TRUE;
1261 if(!do_direct_notif(This)) {
1262 report_result_task_t *task;
1264 task = heap_alloc(sizeof(report_result_task_t));
1265 if(!task)
1266 return E_OUTOFMEMORY;
1268 task->hres = hrResult;
1269 task->err = dwError;
1270 task->str = heap_strdupW(szResult);
1272 push_task(This, &task->header, report_result_proc);
1273 return S_OK;
1276 return IInternetProtocolSink_ReportResult(This->protocol_sink_handler, hrResult, dwError, szResult);
1279 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = {
1280 BPInternetProtocolSink_QueryInterface,
1281 BPInternetProtocolSink_AddRef,
1282 BPInternetProtocolSink_Release,
1283 BPInternetProtocolSink_Switch,
1284 BPInternetProtocolSink_ReportProgress,
1285 BPInternetProtocolSink_ReportData,
1286 BPInternetProtocolSink_ReportResult
1289 static inline BindProtocol *impl_from_IWinInetHttpInfo(IWinInetHttpInfo *iface)
1291 return CONTAINING_RECORD(iface, BindProtocol, IWinInetHttpInfo_iface);
1294 static HRESULT WINAPI WinInetHttpInfo_QueryInterface(IWinInetHttpInfo *iface, REFIID riid, void **ppv)
1296 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1297 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
1300 static ULONG WINAPI WinInetHttpInfo_AddRef(IWinInetHttpInfo *iface)
1302 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1303 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
1306 static ULONG WINAPI WinInetHttpInfo_Release(IWinInetHttpInfo *iface)
1308 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1309 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
1312 static HRESULT WINAPI WinInetHttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD dwOption,
1313 void *pBuffer, DWORD *pcbBuffer)
1315 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1316 FIXME("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer);
1317 return E_NOTIMPL;
1320 static HRESULT WINAPI WinInetHttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption,
1321 void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved)
1323 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1324 FIXME("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved);
1325 return E_NOTIMPL;
1328 static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = {
1329 WinInetHttpInfo_QueryInterface,
1330 WinInetHttpInfo_AddRef,
1331 WinInetHttpInfo_Release,
1332 WinInetHttpInfo_QueryOption,
1333 WinInetHttpInfo_QueryInfo
1336 static inline BindProtocol *impl_from_IServiceProvider(IServiceProvider *iface)
1338 return CONTAINING_RECORD(iface, BindProtocol, IServiceProvider_iface);
1341 static HRESULT WINAPI BPServiceProvider_QueryInterface(IServiceProvider *iface,
1342 REFIID riid, void **ppv)
1344 BindProtocol *This = impl_from_IServiceProvider(iface);
1345 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
1348 static ULONG WINAPI BPServiceProvider_AddRef(IServiceProvider *iface)
1350 BindProtocol *This = impl_from_IServiceProvider(iface);
1351 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
1354 static ULONG WINAPI BPServiceProvider_Release(IServiceProvider *iface)
1356 BindProtocol *This = impl_from_IServiceProvider(iface);
1357 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
1360 static HRESULT WINAPI BPServiceProvider_QueryService(IServiceProvider *iface,
1361 REFGUID guidService, REFIID riid, void **ppv)
1363 BindProtocol *This = impl_from_IServiceProvider(iface);
1365 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
1367 if(!This->service_provider)
1368 return E_NOINTERFACE;
1370 return IServiceProvider_QueryService(This->service_provider, guidService, riid, ppv);
1373 static const IServiceProviderVtbl ServiceProviderVtbl = {
1374 BPServiceProvider_QueryInterface,
1375 BPServiceProvider_AddRef,
1376 BPServiceProvider_Release,
1377 BPServiceProvider_QueryService
1380 HRESULT create_binding_protocol(BOOL from_urlmon, BindProtocol **protocol)
1382 BindProtocol *ret = heap_alloc_zero(sizeof(BindProtocol));
1384 ret->IInternetProtocolEx_iface.lpVtbl = &BindProtocolVtbl;
1385 ret->IInternetBindInfo_iface.lpVtbl = &InternetBindInfoVtbl;
1386 ret->IInternetPriority_iface.lpVtbl = &InternetPriorityVtbl;
1387 ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
1388 ret->IInternetProtocolSink_iface.lpVtbl = &InternetProtocolSinkVtbl;
1389 ret->IWinInetHttpInfo_iface.lpVtbl = &WinInetHttpInfoVtbl;
1391 ret->default_protocol_handler.IInternetProtocol_iface.lpVtbl = &InternetProtocolHandlerVtbl;
1392 ret->default_protocol_handler.IInternetProtocolSink_iface.lpVtbl = &InternetProtocolSinkHandlerVtbl;
1394 ret->ref = 1;
1395 ret->from_urlmon = from_urlmon;
1396 ret->apartment_thread = GetCurrentThreadId();
1397 ret->notif_hwnd = get_notif_hwnd();
1398 ret->protocol_handler = &ret->default_protocol_handler.IInternetProtocol_iface;
1399 ret->protocol_sink_handler = &ret->default_protocol_handler.IInternetProtocolSink_iface;
1400 InitializeCriticalSection(&ret->section);
1401 ret->section.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BindProtocol.section");
1403 URLMON_LockModule();
1405 *protocol = ret;
1406 return S_OK;