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
{
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
)
42 EnterCriticalSection(&This
->section
);
44 task
= This
->task_queue_head
;
46 This
->task_queue_head
= task
->next
;
47 if(!This
->task_queue_head
)
48 This
->task_queue_tail
= NULL
;
51 LeaveCriticalSection(&This
->section
);
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
)
65 case WM_MK_CONTINUE
: {
66 BindProtocol
*This
= (BindProtocol
*)lParam
;
70 IInternetProtocolEx_Release(&This
->IInternetProtocolEx_iface
);
74 tls_data_t
*data
= get_tls_data();
76 if(!--data
->notif_hwnd_cnt
) {
78 data
->notif_hwnd
= NULL
;
83 return DefWindowProcW(hwnd
, msg
, wParam
, lParam
);
86 static ATOM notif_wnd_class
;
88 static BOOL WINAPI
register_notif_wnd_class(INIT_ONCE
*once
, void *param
, void **context
)
90 static WNDCLASSEXW wndclass
= {
91 sizeof(wndclass
), 0, notif_wnd_proc
, 0, 0,
92 NULL
, NULL
, NULL
, NULL
, NULL
,
93 L
"URL Moniker Notification Window", NULL
96 wndclass
.hInstance
= hProxyDll
;
97 notif_wnd_class
= RegisterClassExW(&wndclass
);
101 void unregister_notif_wnd_class(void)
104 UnregisterClassW(MAKEINTRESOURCEW(notif_wnd_class
), hProxyDll
);
107 HWND
get_notif_hwnd(void)
109 tls_data_t
*tls_data
;
111 static INIT_ONCE init_once
= INIT_ONCE_STATIC_INIT
;
113 tls_data
= get_tls_data();
117 if(tls_data
->notif_hwnd_cnt
) {
118 tls_data
->notif_hwnd_cnt
++;
119 return tls_data
->notif_hwnd
;
122 InitOnceExecuteOnce(&init_once
, register_notif_wnd_class
, NULL
, NULL
);
126 tls_data
->notif_hwnd
= CreateWindowExW(0, MAKEINTRESOURCEW(notif_wnd_class
),
127 L
"URL Moniker Notification Window", 0, 0, 0, 0, 0, HWND_MESSAGE
,
128 NULL
, hProxyDll
, NULL
);
129 if(tls_data
->notif_hwnd
)
130 tls_data
->notif_hwnd_cnt
++;
132 TRACE("hwnd = %p\n", tls_data
->notif_hwnd
);
134 return tls_data
->notif_hwnd
;
137 void release_notif_hwnd(HWND hwnd
)
139 tls_data_t
*data
= get_tls_data();
144 if(data
->notif_hwnd
!= hwnd
) {
145 PostMessageW(data
->notif_hwnd
, WM_MK_RELEASE
, 0, 0);
149 if(!--data
->notif_hwnd_cnt
) {
150 DestroyWindow(data
->notif_hwnd
);
151 data
->notif_hwnd
= NULL
;
155 static void push_task(BindProtocol
*This
, task_header_t
*task
, task_proc_t proc
)
157 BOOL do_post
= FALSE
;
162 EnterCriticalSection(&This
->section
);
164 if(This
->task_queue_tail
) {
165 This
->task_queue_tail
->next
= task
;
166 This
->task_queue_tail
= task
;
168 This
->task_queue_tail
= This
->task_queue_head
= task
;
169 do_post
= !This
->continue_call
;
172 LeaveCriticalSection(&This
->section
);
175 IInternetProtocolEx_AddRef(&This
->IInternetProtocolEx_iface
);
176 PostMessageW(This
->notif_hwnd
, WM_MK_CONTINUE
, 0, (LPARAM
)This
);
180 static inline BOOL
is_apartment_thread(BindProtocol
*This
)
182 return This
->apartment_thread
== GetCurrentThreadId();
185 static inline BOOL
do_direct_notif(BindProtocol
*This
)
187 return !(This
->pi
& PI_APARTMENTTHREADED
) || (is_apartment_thread(This
) && !This
->continue_call
);
190 static HRESULT
handle_mime_filter(BindProtocol
*This
, IInternetProtocol
*mime_filter
)
192 PROTOCOLFILTERDATA filter_data
= { sizeof(PROTOCOLFILTERDATA
), NULL
, NULL
, NULL
, 0 };
195 hres
= IInternetProtocol_QueryInterface(mime_filter
, &IID_IInternetProtocolSink
, (void**)&This
->protocol_sink_handler
);
197 This
->protocol_sink_handler
= &This
->default_protocol_handler
.IInternetProtocolSink_iface
;
201 IInternetProtocol_AddRef(mime_filter
);
202 This
->protocol_handler
= mime_filter
;
204 filter_data
.pProtocol
= &This
->default_protocol_handler
.IInternetProtocol_iface
;
205 hres
= IInternetProtocol_Start(mime_filter
, This
->mime
, &This
->default_protocol_handler
.IInternetProtocolSink_iface
,
206 &This
->IInternetBindInfo_iface
, PI_FILTER_MODE
|PI_FORCE_ASYNC
,
207 (HANDLE_PTR
)&filter_data
);
209 IInternetProtocolSink_Release(This
->protocol_sink_handler
);
210 IInternetProtocol_Release(This
->protocol_handler
);
211 This
->protocol_sink_handler
= &This
->default_protocol_handler
.IInternetProtocolSink_iface
;
212 This
->protocol_handler
= &This
->default_protocol_handler
.IInternetProtocol_iface
;
216 /* NOTE: IE9 calls it on the new protocol_sink. It doesn't make sense so it seems to be a bug there. */
217 IInternetProtocolSink_ReportProgress(This
->protocol_sink
, BINDSTATUS_LOADINGMIMEHANDLER
, NULL
);
222 static void mime_available(BindProtocol
*This
, LPCWSTR mime
, BOOL verified
)
224 IInternetProtocol
*mime_filter
;
227 heap_free(This
->mime
);
228 This
->mime
= heap_strdupW(mime
);
230 if(This
->protocol_handler
==&This
->default_protocol_handler
.IInternetProtocol_iface
231 && (mime_filter
= get_mime_filter(mime
))) {
232 TRACE("Got mime filter for %s\n", debugstr_w(mime
));
234 hres
= handle_mime_filter(This
, mime_filter
);
235 IInternetProtocol_Release(mime_filter
);
237 FIXME("MIME filter failed: %08lx\n", hres
);
240 if(This
->reported_mime
|| verified
|| !(This
->pi
& PI_MIMEVERIFICATION
)) {
241 This
->reported_mime
= TRUE
;
242 IInternetProtocolSink_ReportProgress(This
->protocol_sink
, BINDSTATUS_MIMETYPEAVAILABLE
, mime
);
246 static inline BindProtocol
*impl_from_IInternetProtocolEx(IInternetProtocolEx
*iface
)
248 return CONTAINING_RECORD(iface
, BindProtocol
, IInternetProtocolEx_iface
);
251 static HRESULT WINAPI
BindProtocol_QueryInterface(IInternetProtocolEx
*iface
, REFIID riid
, void **ppv
)
253 BindProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
256 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
257 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
258 *ppv
= &This
->IInternetProtocolEx_iface
;
259 }else if(IsEqualGUID(&IID_IInternetProtocolRoot
, riid
)) {
260 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This
, ppv
);
261 *ppv
= &This
->IInternetProtocolEx_iface
;
262 }else if(IsEqualGUID(&IID_IInternetProtocol
, riid
)) {
263 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This
, ppv
);
264 *ppv
= &This
->IInternetProtocolEx_iface
;
265 }else if(IsEqualGUID(&IID_IInternetProtocolEx
, riid
)) {
266 TRACE("(%p)->(IID_IInternetProtocolEx %p)\n", This
, ppv
);
267 *ppv
= &This
->IInternetProtocolEx_iface
;
268 }else if(IsEqualGUID(&IID_IInternetBindInfo
, riid
)) {
269 TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This
, ppv
);
270 *ppv
= &This
->IInternetBindInfo_iface
;
271 }else if(IsEqualGUID(&IID_IInternetPriority
, riid
)) {
272 TRACE("(%p)->(IID_IInternetPriority %p)\n", This
, ppv
);
273 *ppv
= &This
->IInternetPriority_iface
;
274 }else if(IsEqualGUID(&IID_IAuthenticate
, riid
)) {
275 FIXME("(%p)->(IID_IAuthenticate %p)\n", This
, ppv
);
276 }else if(IsEqualGUID(&IID_IServiceProvider
, riid
)) {
277 TRACE("(%p)->(IID_IServiceProvider %p)\n", This
, ppv
);
278 *ppv
= &This
->IServiceProvider_iface
;
279 }else if(IsEqualGUID(&IID_IInternetProtocolSink
, riid
)) {
280 TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This
, ppv
);
281 *ppv
= &This
->IInternetProtocolSink_iface
;
282 }else if(This
->protocol_unk
) {
284 hres
= IUnknown_QueryInterface(This
->protocol_unk
, riid
, ppv
);
285 TRACE("(%p) aggregated handler returned %08lx for %s\n", This
, hres
, debugstr_guid(riid
));
288 WARN("not supported interface %s\n", debugstr_guid(riid
));
292 return E_NOINTERFACE
;
294 IUnknown_AddRef((IUnknown
*)*ppv
);
298 static ULONG WINAPI
BindProtocol_AddRef(IInternetProtocolEx
*iface
)
300 BindProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
301 LONG ref
= InterlockedIncrement(&This
->ref
);
302 TRACE("(%p) ref=%ld\n", This
, ref
);
306 static void release_protocol_handler(BindProtocol
*This
)
309 IInternetProtocol_Release(This
->protocol
);
310 This
->protocol
= NULL
;
312 if(This
->protocol_handler
&& This
->protocol_handler
!= &This
->default_protocol_handler
.IInternetProtocol_iface
) {
313 IInternetProtocol_Release(This
->protocol_handler
);
314 This
->protocol_handler
= &This
->default_protocol_handler
.IInternetProtocol_iface
;
316 if(This
->protocol_sink_handler
&&
317 This
->protocol_sink_handler
!= &This
->default_protocol_handler
.IInternetProtocolSink_iface
) {
318 IInternetProtocolSink_Release(This
->protocol_sink_handler
);
319 This
->protocol_sink_handler
= &This
->default_protocol_handler
.IInternetProtocolSink_iface
;
321 if(This
->protocol_unk
) {
322 IUnknown_Release(This
->protocol_unk
);
323 This
->protocol_unk
= NULL
;
327 static ULONG WINAPI
BindProtocol_Release(IInternetProtocolEx
*iface
)
329 BindProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
330 LONG ref
= InterlockedDecrement(&This
->ref
);
332 TRACE("(%p) ref=%ld\n", This
, ref
);
335 release_protocol_handler(This
);
336 if(This
->redirect_callback
)
337 IBindCallbackRedirect_Release(This
->redirect_callback
);
339 IInternetBindInfo_Release(This
->bind_info
);
341 IUri_Release(This
->uri
);
342 SysFreeString(This
->display_uri
);
344 set_binding_sink(This
, NULL
, NULL
);
347 release_notif_hwnd(This
->notif_hwnd
);
348 This
->section
.DebugInfo
->Spare
[0] = 0;
349 DeleteCriticalSection(&This
->section
);
351 heap_free(This
->mime
);
354 URLMON_UnlockModule();
360 static HRESULT WINAPI
BindProtocol_Start(IInternetProtocolEx
*iface
, LPCWSTR szUrl
,
361 IInternetProtocolSink
*pOIProtSink
, IInternetBindInfo
*pOIBindInfo
,
362 DWORD grfPI
, HANDLE_PTR dwReserved
)
364 BindProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
368 TRACE("(%p)->(%s %p %p %08lx %Ix)\n", This
, debugstr_w(szUrl
), pOIProtSink
,
369 pOIBindInfo
, grfPI
, dwReserved
);
371 hres
= CreateUri(szUrl
, Uri_CREATE_FILE_USE_DOS_PATH
, 0, &uri
);
375 hres
= IInternetProtocolEx_StartEx(&This
->IInternetProtocolEx_iface
, uri
, pOIProtSink
,
376 pOIBindInfo
, grfPI
, (HANDLE
*)dwReserved
);
382 static HRESULT WINAPI
BindProtocol_Continue(IInternetProtocolEx
*iface
, PROTOCOLDATA
*pProtocolData
)
384 BindProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
386 TRACE("(%p)->(%p)\n", This
, pProtocolData
);
388 return IInternetProtocol_Continue(This
->protocol_handler
, pProtocolData
);
391 static HRESULT WINAPI
BindProtocol_Abort(IInternetProtocolEx
*iface
, HRESULT hrReason
,
394 BindProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
396 TRACE("(%p)->(%08lx %08lx)\n", This
, hrReason
, dwOptions
);
398 return IInternetProtocol_Abort(This
->protocol_handler
, hrReason
, dwOptions
);
401 static HRESULT WINAPI
BindProtocol_Terminate(IInternetProtocolEx
*iface
, DWORD dwOptions
)
403 BindProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
405 TRACE("(%p)->(%08lx)\n", This
, dwOptions
);
407 return IInternetProtocol_Terminate(This
->protocol_handler
, dwOptions
);
410 static HRESULT WINAPI
BindProtocol_Suspend(IInternetProtocolEx
*iface
)
412 BindProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
413 FIXME("(%p)\n", This
);
417 static HRESULT WINAPI
BindProtocol_Resume(IInternetProtocolEx
*iface
)
419 BindProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
420 FIXME("(%p)\n", This
);
424 static HRESULT WINAPI
BindProtocol_Read(IInternetProtocolEx
*iface
, void *pv
,
425 ULONG cb
, ULONG
*pcbRead
)
427 BindProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
429 TRACE("(%p)->(%p %lu %p)\n", This
, pv
, cb
, pcbRead
);
433 return IInternetProtocol_Read(This
->protocol_handler
, pv
, cb
, pcbRead
);
436 static HRESULT WINAPI
BindProtocol_Seek(IInternetProtocolEx
*iface
, LARGE_INTEGER dlibMove
,
437 DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
439 BindProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
440 FIXME("(%p)->(%ld %ld %p)\n", This
, dlibMove
.u
.LowPart
, dwOrigin
, plibNewPosition
);
444 static HRESULT WINAPI
BindProtocol_LockRequest(IInternetProtocolEx
*iface
, DWORD dwOptions
)
446 BindProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
448 TRACE("(%p)->(%08lx)\n", This
, dwOptions
);
450 return IInternetProtocol_LockRequest(This
->protocol_handler
, dwOptions
);
453 static HRESULT WINAPI
BindProtocol_UnlockRequest(IInternetProtocolEx
*iface
)
455 BindProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
457 TRACE("(%p)\n", This
);
459 return IInternetProtocol_UnlockRequest(This
->protocol_handler
);
462 static HRESULT WINAPI
BindProtocol_StartEx(IInternetProtocolEx
*iface
, IUri
*pUri
,
463 IInternetProtocolSink
*pOIProtSink
, IInternetBindInfo
*pOIBindInfo
,
464 DWORD grfPI
, HANDLE
*dwReserved
)
466 BindProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
467 IInternetProtocol
*protocol
= NULL
;
468 IInternetProtocolEx
*protocolex
;
469 IInternetPriority
*priority
;
470 IServiceProvider
*service_provider
;
471 CLSID clsid
= IID_NULL
;
472 IUnknown
*protocol_unk
= NULL
;
476 TRACE("(%p)->(%p %p %p %08lx %p)\n", This
, pUri
, pOIProtSink
, pOIBindInfo
, grfPI
, dwReserved
);
478 if(!pUri
|| !pOIProtSink
|| !pOIBindInfo
)
484 SysFreeString(This
->display_uri
);
485 IUri_Release(This
->uri
);
490 hres
= IInternetProtocolSink_QueryInterface(pOIProtSink
, &IID_IServiceProvider
,
491 (void**)&service_provider
);
492 if(SUCCEEDED(hres
)) {
493 /* FIXME: What's protocol CLSID here? */
494 IServiceProvider_QueryService(service_provider
, &IID_IInternetProtocol
,
495 &IID_IInternetProtocol
, (void**)&protocol
);
496 IServiceProvider_Release(service_provider
);
502 hres
= get_protocol_handler(pUri
, &clsid
, &cf
);
506 hres
= IClassFactory_CreateInstance(cf
, (IUnknown
*)&This
->IInternetBindInfo_iface
,
507 &IID_IUnknown
, (void**)&protocol_unk
);
508 if(SUCCEEDED(hres
)) {
509 hres
= IUnknown_QueryInterface(protocol_unk
, &IID_IInternetProtocol
, (void**)&protocol
);
511 This
->protocol_unk
= protocol_unk
;
513 IUnknown_Release(protocol_unk
);
515 else if(hres
== CLASS_E_NOAGGREGATION
)
516 hres
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IInternetProtocol
, (void**)&protocol
);
518 IClassFactory_Release(cf
);
523 StringFromCLSID(&clsid
, &clsid_str
);
524 IInternetProtocolSink_ReportProgress(pOIProtSink
, BINDSTATUS_PROTOCOLCLASSID
, clsid_str
);
525 CoTaskMemFree(clsid_str
);
527 This
->protocol_unk
= protocol_unk
;
528 This
->protocol
= protocol
;
531 protocol_unk
= (IUnknown
*)protocol
;
533 set_binding_sink(This
, pOIProtSink
, pOIBindInfo
);
535 hres
= IUnknown_QueryInterface(protocol_unk
, &IID_IInternetPriority
, (void**)&priority
);
536 if(SUCCEEDED(hres
)) {
537 IInternetPriority_SetPriority(priority
, This
->priority
);
538 IInternetPriority_Release(priority
);
541 hres
= IUnknown_QueryInterface(protocol_unk
, &IID_IInternetProtocolEx
, (void**)&protocolex
);
542 if(SUCCEEDED(hres
)) {
543 hres
= IInternetProtocolEx_StartEx(protocolex
, pUri
, &This
->IInternetProtocolSink_iface
,
544 &This
->IInternetBindInfo_iface
, 0, NULL
);
545 IInternetProtocolEx_Release(protocolex
);
547 hres
= IUri_GetDisplayUri(pUri
, &This
->display_uri
);
551 hres
= IInternetProtocol_Start(protocol
, This
->display_uri
, &This
->IInternetProtocolSink_iface
,
552 &This
->IInternetBindInfo_iface
, 0, 0);
560 void set_binding_sink(BindProtocol
*This
, IInternetProtocolSink
*sink
, IInternetBindInfo
*bind_info
)
562 IInternetProtocolSink
*prev_sink
;
563 IServiceProvider
*service_provider
= NULL
;
566 IInternetProtocolSink_AddRef(sink
);
567 prev_sink
= InterlockedExchangePointer((void**)&This
->protocol_sink
, sink
);
569 IInternetProtocolSink_Release(prev_sink
);
572 IInternetProtocolSink_QueryInterface(sink
, &IID_IServiceProvider
, (void**)&service_provider
);
573 service_provider
= InterlockedExchangePointer((void**)&This
->service_provider
, service_provider
);
575 IServiceProvider_Release(service_provider
);
578 IInternetBindInfo_AddRef(bind_info
);
579 bind_info
= InterlockedExchangePointer((void**)&This
->bind_info
, bind_info
);
581 IInternetBindInfo_Release(bind_info
);
584 static const IInternetProtocolExVtbl BindProtocolVtbl
= {
585 BindProtocol_QueryInterface
,
587 BindProtocol_Release
,
589 BindProtocol_Continue
,
591 BindProtocol_Terminate
,
592 BindProtocol_Suspend
,
596 BindProtocol_LockRequest
,
597 BindProtocol_UnlockRequest
,
601 static inline BindProtocol
*impl_from_IInternetProtocol(IInternetProtocol
*iface
)
603 return CONTAINING_RECORD(iface
, BindProtocol
, default_protocol_handler
.IInternetProtocol_iface
);
606 static HRESULT WINAPI
ProtocolHandler_QueryInterface(IInternetProtocol
*iface
, REFIID riid
, void **ppv
)
608 BindProtocol
*This
= impl_from_IInternetProtocol(iface
);
611 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
612 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
613 *ppv
= &This
->default_protocol_handler
.IInternetProtocol_iface
;
614 }else if(IsEqualGUID(&IID_IInternetProtocolRoot
, riid
)) {
615 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This
, ppv
);
616 *ppv
= &This
->default_protocol_handler
.IInternetProtocol_iface
;
617 }else if(IsEqualGUID(&IID_IInternetProtocol
, riid
)) {
618 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This
, ppv
);
619 *ppv
= &This
->default_protocol_handler
.IInternetProtocol_iface
;
620 }else if(IsEqualGUID(&IID_IInternetProtocolSink
, riid
)) {
621 TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This
, ppv
);
622 *ppv
= &This
->default_protocol_handler
.IInternetProtocolSink_iface
;
626 IInternetProtocol_AddRef(iface
);
630 WARN("not supported interface %s\n", debugstr_guid(riid
));
631 return E_NOINTERFACE
;
634 static ULONG WINAPI
ProtocolHandler_AddRef(IInternetProtocol
*iface
)
636 BindProtocol
*This
= impl_from_IInternetProtocol(iface
);
637 return IInternetProtocolEx_AddRef(&This
->IInternetProtocolEx_iface
);
640 static ULONG WINAPI
ProtocolHandler_Release(IInternetProtocol
*iface
)
642 BindProtocol
*This
= impl_from_IInternetProtocol(iface
);
643 return IInternetProtocolEx_Release(&This
->IInternetProtocolEx_iface
);
646 static HRESULT WINAPI
ProtocolHandler_Start(IInternetProtocol
*iface
, LPCWSTR szUrl
,
647 IInternetProtocolSink
*pOIProtSink
, IInternetBindInfo
*pOIBindInfo
,
648 DWORD grfPI
, HANDLE_PTR dwReserved
)
650 ERR("Should not be called\n");
654 static HRESULT WINAPI
ProtocolHandler_Continue(IInternetProtocol
*iface
, PROTOCOLDATA
*pProtocolData
)
656 BindProtocol
*This
= impl_from_IInternetProtocol(iface
);
657 IInternetProtocol
*protocol
= NULL
;
660 TRACE("(%p)->(%p)\n", This
, pProtocolData
);
662 /* FIXME: This should not be needed. */
663 if(!This
->protocol
) {
664 if(!This
->protocol_unk
)
666 hres
= IUnknown_QueryInterface(This
->protocol_unk
, &IID_IInternetProtocol
, (void**)&protocol
);
671 hres
= IInternetProtocol_Continue(protocol
? protocol
: This
->protocol
, pProtocolData
);
673 heap_free(pProtocolData
);
675 IInternetProtocol_Release(protocol
);
679 static HRESULT WINAPI
ProtocolHandler_Abort(IInternetProtocol
*iface
, HRESULT hrReason
,
682 BindProtocol
*This
= impl_from_IInternetProtocol(iface
);
684 TRACE("(%p)->(%08lx %08lx)\n", This
, hrReason
, dwOptions
);
686 if(This
->protocol
&& !This
->reported_result
)
687 return IInternetProtocol_Abort(This
->protocol
, hrReason
, dwOptions
);
692 static HRESULT WINAPI
ProtocolHandler_Terminate(IInternetProtocol
*iface
, DWORD dwOptions
)
694 BindProtocol
*This
= impl_from_IInternetProtocol(iface
);
696 TRACE("(%p)->(%08lx)\n", This
, dwOptions
);
698 if(!This
->reported_result
)
701 /* This may get released in Terminate call. */
702 IInternetProtocolEx_AddRef(&This
->IInternetProtocolEx_iface
);
705 IInternetProtocol_Terminate(This
->protocol
, 0);
707 if (This
->protocol_unk
) {
708 IInternetProtocol_Release(This
->protocol
);
709 This
->protocol
= NULL
;
713 set_binding_sink(This
, NULL
, NULL
);
715 if(This
->bind_info
) {
716 IInternetBindInfo_Release(This
->bind_info
);
717 This
->bind_info
= NULL
;
720 if(This
->redirect_callback
) {
721 IBindCallbackRedirect_Release(This
->redirect_callback
);
722 This
->redirect_callback
= NULL
;
725 IInternetProtocolEx_Release(&This
->IInternetProtocolEx_iface
);
729 static HRESULT WINAPI
ProtocolHandler_Suspend(IInternetProtocol
*iface
)
731 BindProtocol
*This
= impl_from_IInternetProtocol(iface
);
732 FIXME("(%p)\n", This
);
736 static HRESULT WINAPI
ProtocolHandler_Resume(IInternetProtocol
*iface
)
738 BindProtocol
*This
= impl_from_IInternetProtocol(iface
);
739 FIXME("(%p)\n", This
);
743 static HRESULT WINAPI
ProtocolHandler_Read(IInternetProtocol
*iface
, void *pv
,
744 ULONG cb
, ULONG
*pcbRead
)
746 BindProtocol
*This
= impl_from_IInternetProtocol(iface
);
750 TRACE("(%p)->(%p %lu %p)\n", This
, pv
, cb
, pcbRead
);
753 read
= min(cb
, This
->buf_size
);
754 memcpy(pv
, This
->buf
, read
);
756 if(read
== This
->buf_size
) {
757 heap_free(This
->buf
);
760 memmove(This
->buf
, This
->buf
+cb
, This
->buf_size
-cb
);
763 This
->buf_size
-= read
;
767 IInternetProtocol
*protocol
;
770 /* FIXME: We shouldn't need it, but out binding code currently depends on it. */
771 if(!This
->protocol
&& This
->protocol_unk
) {
772 hres
= IUnknown_QueryInterface(This
->protocol_unk
, &IID_IInternetProtocol
,
777 protocol
= This
->protocol
;
780 if(is_apartment_thread(This
))
781 This
->continue_call
++;
782 hres
= IInternetProtocol_Read(protocol
, (BYTE
*)pv
+read
, cb
-read
, &cread
);
783 if(is_apartment_thread(This
))
784 This
->continue_call
--;
788 IInternetProtocol_Release(protocol
);
795 static HRESULT WINAPI
ProtocolHandler_Seek(IInternetProtocol
*iface
, LARGE_INTEGER dlibMove
,
796 DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
798 BindProtocol
*This
= impl_from_IInternetProtocol(iface
);
799 FIXME("(%p)->(%ld %ld %p)\n", This
, dlibMove
.u
.LowPart
, dwOrigin
, plibNewPosition
);
803 static HRESULT WINAPI
ProtocolHandler_LockRequest(IInternetProtocol
*iface
, DWORD dwOptions
)
805 BindProtocol
*This
= impl_from_IInternetProtocol(iface
);
807 TRACE("(%p)->(%08lx)\n", This
, dwOptions
);
809 return IInternetProtocol_LockRequest(This
->protocol
, dwOptions
);
812 static HRESULT WINAPI
ProtocolHandler_UnlockRequest(IInternetProtocol
*iface
)
814 BindProtocol
*This
= impl_from_IInternetProtocol(iface
);
816 TRACE("(%p)\n", This
);
818 return IInternetProtocol_UnlockRequest(This
->protocol
);
821 static const IInternetProtocolVtbl InternetProtocolHandlerVtbl
= {
822 ProtocolHandler_QueryInterface
,
823 ProtocolHandler_AddRef
,
824 ProtocolHandler_Release
,
825 ProtocolHandler_Start
,
826 ProtocolHandler_Continue
,
827 ProtocolHandler_Abort
,
828 ProtocolHandler_Terminate
,
829 ProtocolHandler_Suspend
,
830 ProtocolHandler_Resume
,
831 ProtocolHandler_Read
,
832 ProtocolHandler_Seek
,
833 ProtocolHandler_LockRequest
,
834 ProtocolHandler_UnlockRequest
837 static inline BindProtocol
*impl_from_IInternetProtocolSinkHandler(IInternetProtocolSink
*iface
)
839 return CONTAINING_RECORD(iface
, BindProtocol
, default_protocol_handler
.IInternetProtocolSink_iface
);
842 static HRESULT WINAPI
ProtocolSinkHandler_QueryInterface(IInternetProtocolSink
*iface
,
843 REFIID riid
, void **ppvObject
)
845 BindProtocol
*This
= impl_from_IInternetProtocolSinkHandler(iface
);
846 return IInternetProtocol_QueryInterface(&This
->default_protocol_handler
.IInternetProtocol_iface
,
850 static ULONG WINAPI
ProtocolSinkHandler_AddRef(IInternetProtocolSink
*iface
)
852 BindProtocol
*This
= impl_from_IInternetProtocolSinkHandler(iface
);
853 return IInternetProtocolEx_AddRef(&This
->IInternetProtocolEx_iface
);
856 static ULONG WINAPI
ProtocolSinkHandler_Release(IInternetProtocolSink
*iface
)
858 BindProtocol
*This
= impl_from_IInternetProtocolSinkHandler(iface
);
859 return IInternetProtocolEx_Release(&This
->IInternetProtocolEx_iface
);
862 static HRESULT WINAPI
ProtocolSinkHandler_Switch(IInternetProtocolSink
*iface
,
863 PROTOCOLDATA
*pProtocolData
)
865 BindProtocol
*This
= impl_from_IInternetProtocolSinkHandler(iface
);
867 TRACE("(%p)->(%p)\n", This
, pProtocolData
);
869 if(!This
->protocol_sink
) {
870 IInternetProtocol_Continue(This
->protocol_handler
, pProtocolData
);
874 return IInternetProtocolSink_Switch(This
->protocol_sink
, pProtocolData
);
877 static HRESULT WINAPI
ProtocolSinkHandler_ReportProgress(IInternetProtocolSink
*iface
,
878 ULONG status_code
, LPCWSTR status_text
)
880 BindProtocol
*This
= impl_from_IInternetProtocolSinkHandler(iface
);
882 TRACE("(%p)->(%s %s)\n", This
, debugstr_bindstatus(status_code
), debugstr_w(status_text
));
884 if(!This
->protocol_sink
)
887 switch(status_code
) {
888 case BINDSTATUS_FINDINGRESOURCE
:
889 case BINDSTATUS_CONNECTING
:
890 case BINDSTATUS_REDIRECTING
:
891 case BINDSTATUS_SENDINGREQUEST
:
892 case BINDSTATUS_CACHEFILENAMEAVAILABLE
:
893 case BINDSTATUS_DIRECTBIND
:
894 case BINDSTATUS_ACCEPTRANGES
:
895 case BINDSTATUS_DECODING
:
896 IInternetProtocolSink_ReportProgress(This
->protocol_sink
, status_code
, status_text
);
899 case BINDSTATUS_BEGINDOWNLOADDATA
:
900 IInternetProtocolSink_ReportData(This
->protocol_sink
, This
->bscf
, This
->progress
, This
->progress_max
);
903 case BINDSTATUS_MIMETYPEAVAILABLE
:
904 mime_available(This
, status_text
, FALSE
);
907 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE
:
908 mime_available(This
, status_text
, TRUE
);
912 FIXME("unsupported ulStatusCode %lu\n", status_code
);
918 static HRESULT
report_data(BindProtocol
*This
)
920 DWORD bscf
= This
->bscf
;
923 if((This
->pi
& PI_MIMEVERIFICATION
) && !This
->reported_mime
) {
924 BYTE buf
[BUFFER_SIZE
];
930 hres
= IInternetProtocol_Read(This
->protocol
, buf
,
931 sizeof(buf
)-This
->buf_size
, &read
);
932 if(FAILED(hres
) && hres
!= E_PENDING
)
936 This
->buf
= heap_alloc(BUFFER_SIZE
);
938 return E_OUTOFMEMORY
;
939 }else if(read
+ This
->buf_size
> BUFFER_SIZE
) {
942 tmp
= heap_realloc(This
->buf
, read
+This
->buf_size
);
944 return E_OUTOFMEMORY
;
948 memcpy(This
->buf
+This
->buf_size
, buf
, read
);
949 This
->buf_size
+= read
;
950 }while(This
->buf_size
< MIME_TEST_SIZE
&& hres
== S_OK
);
952 if(This
->buf_size
< MIME_TEST_SIZE
&& hres
!= S_FALSE
)
955 bscf
= BSCF_FIRSTDATANOTIFICATION
;
957 bscf
|= BSCF_LASTDATANOTIFICATION
|BSCF_DATAFULLYAVAILABLE
;
959 if(!This
->reported_mime
) {
962 hres
= IUri_GetRawUri(This
->uri
, &raw_uri
);
966 hres
= FindMimeFromData(NULL
, raw_uri
, This
->buf
, min(This
->buf_size
, MIME_TEST_SIZE
),
967 This
->mime
, 0, &mime
, 0);
968 SysFreeString(raw_uri
);
972 heap_free(This
->mime
);
973 This
->mime
= heap_strdupW(mime
);
975 This
->reported_mime
= TRUE
;
976 if(This
->protocol_sink
)
977 IInternetProtocolSink_ReportProgress(This
->protocol_sink
, BINDSTATUS_MIMETYPEAVAILABLE
, This
->mime
);
981 if(!This
->protocol_sink
)
984 return IInternetProtocolSink_ReportData(This
->protocol_sink
, bscf
, This
->progress
, This
->progress_max
);
987 static HRESULT WINAPI
ProtocolSinkHandler_ReportData(IInternetProtocolSink
*iface
,
988 DWORD bscf
, ULONG progress
, ULONG progress_max
)
990 BindProtocol
*This
= impl_from_IInternetProtocolSinkHandler(iface
);
993 TRACE("(%p)->(%lx %lu %lu)\n", This
, bscf
, progress
, progress_max
);
996 This
->progress
= progress
;
997 This
->progress_max
= progress_max
;
999 if(!This
->protocol_sink
)
1002 if(is_apartment_thread(This
))
1003 This
->continue_call
++;
1005 hres
= report_data(This
);
1007 if(is_apartment_thread(This
)) {
1008 This
->continue_call
--;
1009 process_tasks(This
);
1014 static HRESULT
handle_redirect(BindProtocol
*This
, const WCHAR
*url
)
1018 if(This
->redirect_callback
) {
1019 VARIANT_BOOL cancel
= VARIANT_FALSE
;
1020 IBindCallbackRedirect_Redirect(This
->redirect_callback
, url
, &cancel
);
1022 return INET_E_REDIRECT_FAILED
;
1025 if(This
->protocol_sink
) {
1026 hres
= IInternetProtocolSink_ReportProgress(This
->protocol_sink
, BINDSTATUS_REDIRECTING
, url
);
1031 IInternetProtocol_Terminate(This
->protocol
, 0); /* should this be done in StartEx? */
1032 release_protocol_handler(This
);
1034 return IInternetProtocolEx_Start(&This
->IInternetProtocolEx_iface
, url
, This
->protocol_sink
, This
->bind_info
, This
->pi
, 0);
1037 static HRESULT WINAPI
ProtocolSinkHandler_ReportResult(IInternetProtocolSink
*iface
,
1038 HRESULT hrResult
, DWORD dwError
, LPCWSTR szResult
)
1040 BindProtocol
*This
= impl_from_IInternetProtocolSinkHandler(iface
);
1042 TRACE("(%p)->(%08lx %ld %s)\n", This
, hrResult
, dwError
, debugstr_w(szResult
));
1044 if(hrResult
== INET_E_REDIRECT_FAILED
) {
1045 hrResult
= handle_redirect(This
, szResult
);
1046 if(hrResult
== S_OK
)
1051 if(This
->protocol_sink
)
1052 return IInternetProtocolSink_ReportResult(This
->protocol_sink
, hrResult
, dwError
, szResult
);
1056 static const IInternetProtocolSinkVtbl InternetProtocolSinkHandlerVtbl
= {
1057 ProtocolSinkHandler_QueryInterface
,
1058 ProtocolSinkHandler_AddRef
,
1059 ProtocolSinkHandler_Release
,
1060 ProtocolSinkHandler_Switch
,
1061 ProtocolSinkHandler_ReportProgress
,
1062 ProtocolSinkHandler_ReportData
,
1063 ProtocolSinkHandler_ReportResult
1066 static inline BindProtocol
*impl_from_IInternetBindInfo(IInternetBindInfo
*iface
)
1068 return CONTAINING_RECORD(iface
, BindProtocol
, IInternetBindInfo_iface
);
1071 static HRESULT WINAPI
BindInfo_QueryInterface(IInternetBindInfo
*iface
,
1072 REFIID riid
, void **ppv
)
1074 BindProtocol
*This
= impl_from_IInternetBindInfo(iface
);
1075 return IInternetProtocolEx_QueryInterface(&This
->IInternetProtocolEx_iface
, riid
, ppv
);
1078 static ULONG WINAPI
BindInfo_AddRef(IInternetBindInfo
*iface
)
1080 BindProtocol
*This
= impl_from_IInternetBindInfo(iface
);
1081 return IInternetProtocolEx_AddRef(&This
->IInternetProtocolEx_iface
);
1084 static ULONG WINAPI
BindInfo_Release(IInternetBindInfo
*iface
)
1086 BindProtocol
*This
= impl_from_IInternetBindInfo(iface
);
1087 return IInternetProtocolEx_Release(&This
->IInternetProtocolEx_iface
);
1090 static HRESULT WINAPI
BindInfo_GetBindInfo(IInternetBindInfo
*iface
,
1091 DWORD
*grfBINDF
, BINDINFO
*pbindinfo
)
1093 BindProtocol
*This
= impl_from_IInternetBindInfo(iface
);
1096 TRACE("(%p)->(%p %p)\n", This
, grfBINDF
, pbindinfo
);
1098 hres
= IInternetBindInfo_GetBindInfo(This
->bind_info
, grfBINDF
, pbindinfo
);
1100 WARN("GetBindInfo failed: %08lx\n", hres
);
1104 if((pbindinfo
->dwOptions
& BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS
) && !This
->redirect_callback
) {
1105 IServiceProvider
*service_provider
;
1107 hres
= IInternetProtocolSink_QueryInterface(This
->protocol_sink
, &IID_IServiceProvider
, (void**)&service_provider
);
1108 if(SUCCEEDED(hres
)) {
1109 hres
= IServiceProvider_QueryService(service_provider
, &IID_IBindCallbackRedirect
, &IID_IBindCallbackRedirect
,
1110 (void**)&This
->redirect_callback
);
1111 IServiceProvider_Release(service_provider
);
1115 *grfBINDF
|= BINDF_FROMURLMON
;
1119 static HRESULT WINAPI
BindInfo_GetBindString(IInternetBindInfo
*iface
,
1120 ULONG ulStringType
, LPOLESTR
*ppwzStr
, ULONG cEl
, ULONG
*pcElFetched
)
1122 BindProtocol
*This
= impl_from_IInternetBindInfo(iface
);
1124 TRACE("(%p)->(%ld %p %ld %p)\n", This
, ulStringType
, ppwzStr
, cEl
, pcElFetched
);
1126 return IInternetBindInfo_GetBindString(This
->bind_info
, ulStringType
, ppwzStr
, cEl
, pcElFetched
);
1129 static const IInternetBindInfoVtbl InternetBindInfoVtbl
= {
1130 BindInfo_QueryInterface
,
1133 BindInfo_GetBindInfo
,
1134 BindInfo_GetBindString
1137 static inline BindProtocol
*impl_from_IInternetPriority(IInternetPriority
*iface
)
1139 return CONTAINING_RECORD(iface
, BindProtocol
, IInternetPriority_iface
);
1142 static HRESULT WINAPI
InternetPriority_QueryInterface(IInternetPriority
*iface
,
1143 REFIID riid
, void **ppv
)
1145 BindProtocol
*This
= impl_from_IInternetPriority(iface
);
1146 return IInternetProtocolEx_QueryInterface(&This
->IInternetProtocolEx_iface
, riid
, ppv
);
1149 static ULONG WINAPI
InternetPriority_AddRef(IInternetPriority
*iface
)
1151 BindProtocol
*This
= impl_from_IInternetPriority(iface
);
1152 return IInternetProtocolEx_AddRef(&This
->IInternetProtocolEx_iface
);
1155 static ULONG WINAPI
InternetPriority_Release(IInternetPriority
*iface
)
1157 BindProtocol
*This
= impl_from_IInternetPriority(iface
);
1158 return IInternetProtocolEx_Release(&This
->IInternetProtocolEx_iface
);
1161 static HRESULT WINAPI
InternetPriority_SetPriority(IInternetPriority
*iface
, LONG nPriority
)
1163 BindProtocol
*This
= impl_from_IInternetPriority(iface
);
1165 TRACE("(%p)->(%ld)\n", This
, nPriority
);
1167 This
->priority
= nPriority
;
1171 static HRESULT WINAPI
InternetPriority_GetPriority(IInternetPriority
*iface
, LONG
*pnPriority
)
1173 BindProtocol
*This
= impl_from_IInternetPriority(iface
);
1175 TRACE("(%p)->(%p)\n", This
, pnPriority
);
1177 *pnPriority
= This
->priority
;
1181 static const IInternetPriorityVtbl InternetPriorityVtbl
= {
1182 InternetPriority_QueryInterface
,
1183 InternetPriority_AddRef
,
1184 InternetPriority_Release
,
1185 InternetPriority_SetPriority
,
1186 InternetPriority_GetPriority
1190 static inline BindProtocol
*impl_from_IInternetProtocolSink(IInternetProtocolSink
*iface
)
1192 return CONTAINING_RECORD(iface
, BindProtocol
, IInternetProtocolSink_iface
);
1195 static HRESULT WINAPI
BPInternetProtocolSink_QueryInterface(IInternetProtocolSink
*iface
,
1196 REFIID riid
, void **ppv
)
1198 BindProtocol
*This
= impl_from_IInternetProtocolSink(iface
);
1199 return IInternetProtocolEx_QueryInterface(&This
->IInternetProtocolEx_iface
, riid
, ppv
);
1202 static ULONG WINAPI
BPInternetProtocolSink_AddRef(IInternetProtocolSink
*iface
)
1204 BindProtocol
*This
= impl_from_IInternetProtocolSink(iface
);
1205 return IInternetProtocolEx_AddRef(&This
->IInternetProtocolEx_iface
);
1208 static ULONG WINAPI
BPInternetProtocolSink_Release(IInternetProtocolSink
*iface
)
1210 BindProtocol
*This
= impl_from_IInternetProtocolSink(iface
);
1211 return IInternetProtocolEx_Release(&This
->IInternetProtocolEx_iface
);
1215 task_header_t header
;
1219 static void switch_proc(BindProtocol
*bind
, task_header_t
*t
)
1221 switch_task_t
*task
= (switch_task_t
*)t
;
1223 IInternetProtocol_Continue(bind
->protocol_handler
, task
->data
);
1228 static HRESULT WINAPI
BPInternetProtocolSink_Switch(IInternetProtocolSink
*iface
,
1229 PROTOCOLDATA
*pProtocolData
)
1231 BindProtocol
*This
= impl_from_IInternetProtocolSink(iface
);
1234 TRACE("(%p)->(%p)\n", This
, pProtocolData
);
1236 TRACE("flags %lx state %lx data %p cb %lu\n", pProtocolData
->grfFlags
, pProtocolData
->dwState
,
1237 pProtocolData
->pData
, pProtocolData
->cbData
);
1239 data
= heap_alloc(sizeof(PROTOCOLDATA
));
1241 return E_OUTOFMEMORY
;
1242 memcpy(data
, pProtocolData
, sizeof(PROTOCOLDATA
));
1244 if((This
->pi
&PI_APARTMENTTHREADED
&& pProtocolData
->grfFlags
&PI_FORCE_ASYNC
)
1245 || !do_direct_notif(This
)) {
1246 switch_task_t
*task
;
1248 task
= heap_alloc(sizeof(switch_task_t
));
1252 return E_OUTOFMEMORY
;
1257 push_task(This
, &task
->header
, switch_proc
);
1261 return IInternetProtocolSink_Switch(This
->protocol_sink_handler
, data
);
1265 task_header_t header
;
1269 } on_progress_task_t
;
1271 static void on_progress_proc(BindProtocol
*This
, task_header_t
*t
)
1273 on_progress_task_t
*task
= (on_progress_task_t
*)t
;
1275 IInternetProtocolSink_ReportProgress(This
->protocol_sink_handler
, task
->status_code
, task
->status_text
);
1277 heap_free(task
->status_text
);
1281 static HRESULT WINAPI
BPInternetProtocolSink_ReportProgress(IInternetProtocolSink
*iface
,
1282 ULONG ulStatusCode
, LPCWSTR szStatusText
)
1284 BindProtocol
*This
= impl_from_IInternetProtocolSink(iface
);
1286 TRACE("(%p)->(%lu %s)\n", This
, ulStatusCode
, debugstr_w(szStatusText
));
1288 if(do_direct_notif(This
)) {
1289 IInternetProtocolSink_ReportProgress(This
->protocol_sink_handler
, ulStatusCode
, szStatusText
);
1291 on_progress_task_t
*task
;
1293 task
= heap_alloc(sizeof(on_progress_task_t
));
1295 task
->status_code
= ulStatusCode
;
1296 task
->status_text
= heap_strdupW(szStatusText
);
1298 push_task(This
, &task
->header
, on_progress_proc
);
1305 task_header_t header
;
1309 } report_data_task_t
;
1311 static void report_data_proc(BindProtocol
*This
, task_header_t
*t
)
1313 report_data_task_t
*task
= (report_data_task_t
*)t
;
1315 IInternetProtocolSink_ReportData(This
->protocol_sink_handler
,
1316 task
->bscf
, task
->progress
, task
->progress_max
);
1321 static HRESULT WINAPI
BPInternetProtocolSink_ReportData(IInternetProtocolSink
*iface
,
1322 DWORD grfBSCF
, ULONG ulProgress
, ULONG ulProgressMax
)
1324 BindProtocol
*This
= impl_from_IInternetProtocolSink(iface
);
1326 TRACE("(%p)->(%lx %lu %lu)\n", This
, grfBSCF
, ulProgress
, ulProgressMax
);
1328 if(!This
->protocol_sink
)
1331 if(!do_direct_notif(This
)) {
1332 report_data_task_t
*task
;
1334 task
= heap_alloc(sizeof(report_data_task_t
));
1336 return E_OUTOFMEMORY
;
1338 task
->bscf
= grfBSCF
;
1339 task
->progress
= ulProgress
;
1340 task
->progress_max
= ulProgressMax
;
1342 push_task(This
, &task
->header
, report_data_proc
);
1346 return IInternetProtocolSink_ReportData(This
->protocol_sink_handler
,
1347 grfBSCF
, ulProgress
, ulProgressMax
);
1351 task_header_t header
;
1356 } report_result_task_t
;
1358 static void report_result_proc(BindProtocol
*This
, task_header_t
*t
)
1360 report_result_task_t
*task
= (report_result_task_t
*)t
;
1362 IInternetProtocolSink_ReportResult(This
->protocol_sink_handler
, task
->hres
, task
->err
, task
->str
);
1364 heap_free(task
->str
);
1368 static HRESULT WINAPI
BPInternetProtocolSink_ReportResult(IInternetProtocolSink
*iface
,
1369 HRESULT hrResult
, DWORD dwError
, LPCWSTR szResult
)
1371 BindProtocol
*This
= impl_from_IInternetProtocolSink(iface
);
1373 TRACE("(%p)->(%08lx %ld %s)\n", This
, hrResult
, dwError
, debugstr_w(szResult
));
1375 if(!This
->protocol_sink
)
1377 This
->reported_result
= TRUE
;
1379 if(!do_direct_notif(This
)) {
1380 report_result_task_t
*task
;
1382 task
= heap_alloc(sizeof(report_result_task_t
));
1384 return E_OUTOFMEMORY
;
1386 task
->hres
= hrResult
;
1387 task
->err
= dwError
;
1388 task
->str
= heap_strdupW(szResult
);
1390 push_task(This
, &task
->header
, report_result_proc
);
1394 return IInternetProtocolSink_ReportResult(This
->protocol_sink_handler
, hrResult
, dwError
, szResult
);
1397 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl
= {
1398 BPInternetProtocolSink_QueryInterface
,
1399 BPInternetProtocolSink_AddRef
,
1400 BPInternetProtocolSink_Release
,
1401 BPInternetProtocolSink_Switch
,
1402 BPInternetProtocolSink_ReportProgress
,
1403 BPInternetProtocolSink_ReportData
,
1404 BPInternetProtocolSink_ReportResult
1407 static inline BindProtocol
*impl_from_IServiceProvider(IServiceProvider
*iface
)
1409 return CONTAINING_RECORD(iface
, BindProtocol
, IServiceProvider_iface
);
1412 static HRESULT WINAPI
BPServiceProvider_QueryInterface(IServiceProvider
*iface
,
1413 REFIID riid
, void **ppv
)
1415 BindProtocol
*This
= impl_from_IServiceProvider(iface
);
1416 return IInternetProtocolEx_QueryInterface(&This
->IInternetProtocolEx_iface
, riid
, ppv
);
1419 static ULONG WINAPI
BPServiceProvider_AddRef(IServiceProvider
*iface
)
1421 BindProtocol
*This
= impl_from_IServiceProvider(iface
);
1422 return IInternetProtocolEx_AddRef(&This
->IInternetProtocolEx_iface
);
1425 static ULONG WINAPI
BPServiceProvider_Release(IServiceProvider
*iface
)
1427 BindProtocol
*This
= impl_from_IServiceProvider(iface
);
1428 return IInternetProtocolEx_Release(&This
->IInternetProtocolEx_iface
);
1431 static HRESULT WINAPI
BPServiceProvider_QueryService(IServiceProvider
*iface
,
1432 REFGUID guidService
, REFIID riid
, void **ppv
)
1434 BindProtocol
*This
= impl_from_IServiceProvider(iface
);
1436 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_guid(guidService
), debugstr_guid(riid
), ppv
);
1438 if(!This
->service_provider
)
1439 return E_NOINTERFACE
;
1441 return IServiceProvider_QueryService(This
->service_provider
, guidService
, riid
, ppv
);
1444 static const IServiceProviderVtbl ServiceProviderVtbl
= {
1445 BPServiceProvider_QueryInterface
,
1446 BPServiceProvider_AddRef
,
1447 BPServiceProvider_Release
,
1448 BPServiceProvider_QueryService
1451 HRESULT
create_binding_protocol(BindProtocol
**protocol
)
1453 BindProtocol
*ret
= heap_alloc_zero(sizeof(BindProtocol
));
1455 ret
->IInternetProtocolEx_iface
.lpVtbl
= &BindProtocolVtbl
;
1456 ret
->IInternetBindInfo_iface
.lpVtbl
= &InternetBindInfoVtbl
;
1457 ret
->IInternetPriority_iface
.lpVtbl
= &InternetPriorityVtbl
;
1458 ret
->IServiceProvider_iface
.lpVtbl
= &ServiceProviderVtbl
;
1459 ret
->IInternetProtocolSink_iface
.lpVtbl
= &InternetProtocolSinkVtbl
;
1461 ret
->default_protocol_handler
.IInternetProtocol_iface
.lpVtbl
= &InternetProtocolHandlerVtbl
;
1462 ret
->default_protocol_handler
.IInternetProtocolSink_iface
.lpVtbl
= &InternetProtocolSinkHandlerVtbl
;
1465 ret
->apartment_thread
= GetCurrentThreadId();
1466 ret
->notif_hwnd
= get_notif_hwnd();
1467 ret
->protocol_handler
= &ret
->default_protocol_handler
.IInternetProtocol_iface
;
1468 ret
->protocol_sink_handler
= &ret
->default_protocol_handler
.IInternetProtocolSink_iface
;
1469 InitializeCriticalSection(&ret
->section
);
1470 ret
->section
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": BindProtocol.section");
1472 URLMON_LockModule();