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 struct BindProtocol BindProtocol
;
26 struct _task_header_t
;
28 typedef void (*task_proc_t
)(BindProtocol
*,struct _task_header_t
*);
30 typedef struct _task_header_t
{
32 struct _task_header_t
*next
;
36 const IInternetProtocolVtbl
*lpIInternetProtocolVtbl
;
37 const IInternetBindInfoVtbl
*lpInternetBindInfoVtbl
;
38 const IInternetPriorityVtbl
*lpInternetPriorityVtbl
;
39 const IServiceProviderVtbl
*lpServiceProviderVtbl
;
40 const IInternetProtocolSinkVtbl
*lpIInternetProtocolSinkVtbl
;
42 const IInternetProtocolVtbl
*lpIInternetProtocolHandlerVtbl
;
46 IInternetProtocol
*protocol
;
47 IInternetProtocol
*protocol_handler
;
48 IInternetBindInfo
*bind_info
;
49 IInternetProtocolSink
*protocol_sink
;
50 IServiceProvider
*service_provider
;
51 IWinInetInfo
*wininet_info
;
60 DWORD apartment_thread
;
64 CRITICAL_SECTION section
;
65 task_header_t
*task_queue_head
, *task_queue_tail
;
71 ProtocolProxy
*filter_proxy
;
74 #define BINDINFO(x) ((IInternetBindInfo*) &(x)->lpInternetBindInfoVtbl)
75 #define PRIORITY(x) ((IInternetPriority*) &(x)->lpInternetPriorityVtbl)
76 #define SERVPROV(x) ((IServiceProvider*) &(x)->lpServiceProviderVtbl)
78 #define PROTOCOLHANDLER(x) ((IInternetProtocol*) &(x)->lpIInternetProtocolHandlerVtbl)
80 #define BUFFER_SIZE 2048
81 #define MIME_TEST_SIZE 255
83 #define WM_MK_CONTINUE (WM_USER+101)
84 #define WM_MK_RELEASE (WM_USER+102)
86 static LRESULT WINAPI
notif_wnd_proc(HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
89 case WM_MK_CONTINUE
: {
90 BindProtocol
*This
= (BindProtocol
*)lParam
;
94 EnterCriticalSection(&This
->section
);
96 task
= This
->task_queue_head
;
98 This
->task_queue_head
= task
->next
;
99 if(!This
->task_queue_head
)
100 This
->task_queue_tail
= NULL
;
103 LeaveCriticalSection(&This
->section
);
108 This
->continue_call
++;
109 task
->proc(This
, task
);
110 This
->continue_call
--;
113 IInternetProtocol_Release(PROTOCOL(This
));
116 case WM_MK_RELEASE
: {
117 tls_data_t
*data
= get_tls_data();
119 if(!--data
->notif_hwnd_cnt
) {
121 data
->notif_hwnd
= NULL
;
126 return DefWindowProcW(hwnd
, msg
, wParam
, lParam
);
129 HWND
get_notif_hwnd(void)
131 static ATOM wnd_class
= 0;
132 tls_data_t
*tls_data
;
134 static const WCHAR wszURLMonikerNotificationWindow
[] =
135 {'U','R','L',' ','M','o','n','i','k','e','r',' ',
136 'N','o','t','i','f','i','c','a','t','i','o','n',' ','W','i','n','d','o','w',0};
138 tls_data
= get_tls_data();
142 if(tls_data
->notif_hwnd_cnt
) {
143 tls_data
->notif_hwnd_cnt
++;
144 return tls_data
->notif_hwnd
;
148 static WNDCLASSEXW wndclass
= {
150 notif_wnd_proc
, 0, 0,
151 NULL
, NULL
, NULL
, NULL
, NULL
,
152 wszURLMonikerNotificationWindow
,
156 wndclass
.hInstance
= URLMON_hInstance
;
158 wnd_class
= RegisterClassExW(&wndclass
);
159 if (!wnd_class
&& GetLastError() == ERROR_CLASS_ALREADY_EXISTS
)
163 tls_data
->notif_hwnd
= CreateWindowExW(0, wszURLMonikerNotificationWindow
,
164 wszURLMonikerNotificationWindow
, 0, 0, 0, 0, 0, HWND_MESSAGE
,
165 NULL
, URLMON_hInstance
, NULL
);
166 if(tls_data
->notif_hwnd
)
167 tls_data
->notif_hwnd_cnt
++;
169 TRACE("hwnd = %p\n", tls_data
->notif_hwnd
);
171 return tls_data
->notif_hwnd
;
174 void release_notif_hwnd(HWND hwnd
)
176 tls_data_t
*data
= get_tls_data();
181 if(data
->notif_hwnd
!= hwnd
) {
182 PostMessageW(data
->notif_hwnd
, WM_MK_RELEASE
, 0, 0);
186 if(!--data
->notif_hwnd_cnt
) {
187 DestroyWindow(data
->notif_hwnd
);
188 data
->notif_hwnd
= NULL
;
192 static void push_task(BindProtocol
*This
, task_header_t
*task
, task_proc_t proc
)
194 BOOL do_post
= FALSE
;
199 EnterCriticalSection(&This
->section
);
201 if(This
->task_queue_tail
) {
202 This
->task_queue_tail
->next
= task
;
203 This
->task_queue_tail
= task
;
205 This
->task_queue_tail
= This
->task_queue_head
= task
;
209 LeaveCriticalSection(&This
->section
);
212 IInternetProtocol_AddRef(PROTOCOL(This
));
213 PostMessageW(This
->notif_hwnd
, WM_MK_CONTINUE
, 0, (LPARAM
)This
);
217 static inline BOOL
do_direct_notif(BindProtocol
*This
)
219 return !(This
->pi
& PI_APARTMENTTHREADED
) || (This
->apartment_thread
== GetCurrentThreadId() && !This
->continue_call
);
222 static HRESULT
handle_mime_filter(BindProtocol
*This
, IInternetProtocol
*mime_filter
, LPCWSTR mime
)
224 PROTOCOLFILTERDATA filter_data
= { sizeof(PROTOCOLFILTERDATA
), NULL
, NULL
, NULL
, 0 };
225 IInternetProtocolSink
*protocol_sink
, *old_sink
;
226 ProtocolProxy
*filter_proxy
;
229 hres
= IInternetProtocol_QueryInterface(mime_filter
, &IID_IInternetProtocolSink
, (void**)&protocol_sink
);
233 hres
= create_protocol_proxy(PROTOCOLHANDLER(This
), This
->protocol_sink
, &filter_proxy
);
235 IInternetProtocolSink_Release(protocol_sink
);
239 old_sink
= This
->protocol_sink
;
240 This
->protocol_sink
= protocol_sink
;
241 This
->filter_proxy
= filter_proxy
;
243 IInternetProtocol_AddRef(mime_filter
);
244 This
->protocol_handler
= mime_filter
;
246 filter_data
.pProtocol
= PROTOCOL(filter_proxy
);
247 hres
= IInternetProtocol_Start(mime_filter
, mime
, PROTSINK(filter_proxy
), BINDINFO(This
),
248 PI_FILTER_MODE
|PI_FORCE_ASYNC
, (HANDLE_PTR
)&filter_data
);
250 IInternetProtocolSink_Release(old_sink
);
254 IInternetProtocolSink_ReportProgress(old_sink
, BINDSTATUS_LOADINGMIMEHANDLER
, NULL
);
255 IInternetProtocolSink_Release(old_sink
);
257 This
->pi
&= ~PI_MIMEVERIFICATION
; /* FIXME: more tests */
261 static void mime_available(BindProtocol
*This
, LPCWSTR mime
, BOOL verified
)
263 IInternetProtocol
*mime_filter
;
266 heap_free(This
->mime
);
269 mime_filter
= get_mime_filter(mime
);
271 TRACE("Got mime filter for %s\n", debugstr_w(mime
));
273 hres
= handle_mime_filter(This
, mime_filter
, mime
);
274 IInternetProtocol_Release(mime_filter
);
276 FIXME("MIME filter failed: %08x\n", hres
);
278 This
->mime
= heap_strdupW(mime
);
280 if(verified
|| !(This
->pi
& PI_MIMEVERIFICATION
)) {
281 This
->reported_mime
= TRUE
;
283 if(This
->protocol_sink
)
284 IInternetProtocolSink_ReportProgress(This
->protocol_sink
, BINDSTATUS_MIMETYPEAVAILABLE
, mime
);
289 #define PROTOCOL_THIS(iface) DEFINE_THIS(BindProtocol, IInternetProtocol, iface)
291 static HRESULT WINAPI
BindProtocol_QueryInterface(IInternetProtocol
*iface
, REFIID riid
, void **ppv
)
293 BindProtocol
*This
= PROTOCOL_THIS(iface
);
296 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
297 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
298 *ppv
= PROTOCOL(This
);
299 }else if(IsEqualGUID(&IID_IInternetProtocolRoot
, riid
)) {
300 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This
, ppv
);
301 *ppv
= PROTOCOL(This
);
302 }else if(IsEqualGUID(&IID_IInternetProtocol
, riid
)) {
303 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This
, ppv
);
304 *ppv
= PROTOCOL(This
);
305 }else if(IsEqualGUID(&IID_IInternetBindInfo
, riid
)) {
306 TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This
, ppv
);
307 *ppv
= BINDINFO(This
);
308 }else if(IsEqualGUID(&IID_IInternetPriority
, riid
)) {
309 TRACE("(%p)->(IID_IInternetPriority %p)\n", This
, ppv
);
310 *ppv
= PRIORITY(This
);
311 }else if(IsEqualGUID(&IID_IAuthenticate
, riid
)) {
312 FIXME("(%p)->(IID_IAuthenticate %p)\n", This
, ppv
);
313 }else if(IsEqualGUID(&IID_IServiceProvider
, riid
)) {
314 TRACE("(%p)->(IID_IServiceProvider %p)\n", This
, ppv
);
315 *ppv
= SERVPROV(This
);
316 }else if(IsEqualGUID(&IID_IInternetProtocolSink
, riid
)) {
317 TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This
, ppv
);
318 *ppv
= PROTSINK(This
);
322 IInternetProtocol_AddRef(iface
);
326 WARN("not supported interface %s\n", debugstr_guid(riid
));
327 return E_NOINTERFACE
;
330 static ULONG WINAPI
BindProtocol_AddRef(IInternetProtocol
*iface
)
332 BindProtocol
*This
= PROTOCOL_THIS(iface
);
333 LONG ref
= InterlockedIncrement(&This
->ref
);
334 TRACE("(%p) ref=%d\n", This
, ref
);
338 static ULONG WINAPI
BindProtocol_Release(IInternetProtocol
*iface
)
340 BindProtocol
*This
= PROTOCOL_THIS(iface
);
341 LONG ref
= InterlockedDecrement(&This
->ref
);
343 TRACE("(%p) ref=%d\n", This
, ref
);
346 if(This
->wininet_info
)
347 IWinInetInfo_Release(This
->wininet_info
);
349 IInternetProtocol_Release(This
->protocol
);
351 IInternetBindInfo_Release(This
->bind_info
);
352 if(This
->protocol_handler
&& This
->protocol_handler
!= PROTOCOLHANDLER(This
))
353 IInternetProtocol_Release(This
->protocol_handler
);
354 if(This
->filter_proxy
)
355 IInternetProtocol_Release(PROTOCOL(This
->filter_proxy
));
357 set_binding_sink(PROTOCOL(This
), NULL
);
360 release_notif_hwnd(This
->notif_hwnd
);
361 DeleteCriticalSection(&This
->section
);
363 heap_free(This
->mime
);
364 heap_free(This
->url
);
367 URLMON_UnlockModule();
373 static HRESULT WINAPI
BindProtocol_Start(IInternetProtocol
*iface
, LPCWSTR szUrl
,
374 IInternetProtocolSink
*pOIProtSink
, IInternetBindInfo
*pOIBindInfo
,
375 DWORD grfPI
, HANDLE_PTR dwReserved
)
377 BindProtocol
*This
= PROTOCOL_THIS(iface
);
379 TRACE("(%p)->(%s %p %p %08x %lx)\n", This
, debugstr_w(szUrl
), pOIProtSink
,
380 pOIBindInfo
, grfPI
, dwReserved
);
382 return IInternetProtocol_Start(This
->protocol_handler
, szUrl
, pOIProtSink
, pOIBindInfo
, grfPI
, dwReserved
);
385 static HRESULT WINAPI
BindProtocol_Continue(IInternetProtocol
*iface
, PROTOCOLDATA
*pProtocolData
)
387 BindProtocol
*This
= PROTOCOL_THIS(iface
);
389 TRACE("(%p)->(%p)\n", This
, pProtocolData
);
391 return IInternetProtocol_Continue(This
->protocol_handler
, pProtocolData
);
394 static HRESULT WINAPI
BindProtocol_Abort(IInternetProtocol
*iface
, HRESULT hrReason
,
397 BindProtocol
*This
= PROTOCOL_THIS(iface
);
398 FIXME("(%p)->(%08x %08x)\n", This
, hrReason
, dwOptions
);
402 static HRESULT WINAPI
BindProtocol_Terminate(IInternetProtocol
*iface
, DWORD dwOptions
)
404 BindProtocol
*This
= PROTOCOL_THIS(iface
);
406 TRACE("(%p)->(%08x)\n", This
, dwOptions
);
408 return IInternetProtocol_Terminate(This
->protocol_handler
, dwOptions
);
411 static HRESULT WINAPI
BindProtocol_Suspend(IInternetProtocol
*iface
)
413 BindProtocol
*This
= PROTOCOL_THIS(iface
);
414 FIXME("(%p)\n", This
);
418 static HRESULT WINAPI
BindProtocol_Resume(IInternetProtocol
*iface
)
420 BindProtocol
*This
= PROTOCOL_THIS(iface
);
421 FIXME("(%p)\n", This
);
425 static HRESULT WINAPI
BindProtocol_Read(IInternetProtocol
*iface
, void *pv
,
426 ULONG cb
, ULONG
*pcbRead
)
428 BindProtocol
*This
= PROTOCOL_THIS(iface
);
430 TRACE("(%p)->(%p %u %p)\n", This
, pv
, cb
, pcbRead
);
434 return IInternetProtocol_Read(This
->protocol_handler
, pv
, cb
, pcbRead
);
437 static HRESULT WINAPI
BindProtocol_Seek(IInternetProtocol
*iface
, LARGE_INTEGER dlibMove
,
438 DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
440 BindProtocol
*This
= PROTOCOL_THIS(iface
);
441 FIXME("(%p)->(%d %d %p)\n", This
, dlibMove
.u
.LowPart
, dwOrigin
, plibNewPosition
);
445 static HRESULT WINAPI
BindProtocol_LockRequest(IInternetProtocol
*iface
, DWORD dwOptions
)
447 BindProtocol
*This
= PROTOCOL_THIS(iface
);
449 TRACE("(%p)->(%08x)\n", This
, dwOptions
);
451 return IInternetProtocol_LockRequest(This
->protocol_handler
, dwOptions
);
454 static HRESULT WINAPI
BindProtocol_UnlockRequest(IInternetProtocol
*iface
)
456 BindProtocol
*This
= PROTOCOL_THIS(iface
);
458 TRACE("(%p)\n", This
);
460 return IInternetProtocol_UnlockRequest(This
->protocol_handler
);
463 void set_binding_sink(IInternetProtocol
*bind_protocol
, IInternetProtocolSink
*sink
)
465 BindProtocol
*This
= PROTOCOL_THIS(bind_protocol
);
466 IInternetProtocolSink
*prev_sink
;
467 IServiceProvider
*service_provider
= NULL
;
470 IInternetProtocolSink_AddRef(sink
);
471 prev_sink
= InterlockedExchangePointer((void**)&This
->protocol_sink
, sink
);
473 IInternetProtocolSink_Release(prev_sink
);
476 IInternetProtocolSink_QueryInterface(sink
, &IID_IServiceProvider
, (void**)&service_provider
);
477 service_provider
= InterlockedExchangePointer((void**)&This
->service_provider
, service_provider
);
479 IServiceProvider_Release(service_provider
);
482 IWinInetInfo
*get_wininet_info(IInternetProtocol
*bind_protocol
)
484 BindProtocol
*This
= PROTOCOL_THIS(bind_protocol
);
486 return This
->wininet_info
;
491 static const IInternetProtocolVtbl BindProtocolVtbl
= {
492 BindProtocol_QueryInterface
,
494 BindProtocol_Release
,
496 BindProtocol_Continue
,
498 BindProtocol_Terminate
,
499 BindProtocol_Suspend
,
503 BindProtocol_LockRequest
,
504 BindProtocol_UnlockRequest
507 #define PROTOCOLHANDLER_THIS(iface) DEFINE_THIS(BindProtocol, IInternetProtocolHandler, iface)
509 static HRESULT WINAPI
ProtocolHandler_QueryInterface(IInternetProtocol
*iface
, REFIID riid
, void **ppv
)
511 ERR("should not be called\n");
512 return E_NOINTERFACE
;
515 static ULONG WINAPI
ProtocolHandler_AddRef(IInternetProtocol
*iface
)
517 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
518 return IInternetProtocol_AddRef(PROTOCOL(This
));
521 static ULONG WINAPI
ProtocolHandler_Release(IInternetProtocol
*iface
)
523 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
524 return IInternetProtocol_Release(PROTOCOL(This
));
527 static HRESULT WINAPI
ProtocolHandler_Start(IInternetProtocol
*iface
, LPCWSTR szUrl
,
528 IInternetProtocolSink
*pOIProtSink
, IInternetBindInfo
*pOIBindInfo
,
529 DWORD grfPI
, HANDLE_PTR dwReserved
)
531 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
532 IInternetProtocol
*protocol
= NULL
;
533 IInternetPriority
*priority
;
534 IServiceProvider
*service_provider
;
535 BOOL urlmon_protocol
= FALSE
;
536 CLSID clsid
= IID_NULL
;
540 TRACE("(%p)->(%s %p %p %08x %lx)\n", This
, debugstr_w(szUrl
), pOIProtSink
,
541 pOIBindInfo
, grfPI
, dwReserved
);
543 if(!szUrl
|| !pOIProtSink
|| !pOIBindInfo
)
547 This
->url
= heap_strdupW(szUrl
);
549 hres
= IInternetProtocolSink_QueryInterface(pOIProtSink
, &IID_IServiceProvider
,
550 (void**)&service_provider
);
551 if(SUCCEEDED(hres
)) {
552 /* FIXME: What's protocol CLSID here? */
553 IServiceProvider_QueryService(service_provider
, &IID_IInternetProtocol
,
554 &IID_IInternetProtocol
, (void**)&protocol
);
555 IServiceProvider_Release(service_provider
);
562 hres
= get_protocol_handler(szUrl
, &clsid
, &urlmon_protocol
, &cf
);
566 if(This
->from_urlmon
) {
567 hres
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IInternetProtocol
, (void**)&protocol
);
568 IClassFactory_Release(cf
);
572 hres
= IClassFactory_CreateInstance(cf
, (IUnknown
*)BINDINFO(This
),
573 &IID_IUnknown
, (void**)&unk
);
574 IClassFactory_Release(cf
);
578 hres
= IUnknown_QueryInterface(unk
, &IID_IInternetProtocol
, (void**)&protocol
);
579 IUnknown_Release(unk
);
585 StringFromCLSID(&clsid
, &clsid_str
);
586 IInternetProtocolSink_ReportProgress(pOIProtSink
, BINDSTATUS_PROTOCOLCLASSID
, clsid_str
);
587 CoTaskMemFree(clsid_str
);
589 This
->protocol
= protocol
;
592 IInternetProtocol_QueryInterface(protocol
, &IID_IWinInetInfo
, (void**)&This
->wininet_info
);
594 IInternetBindInfo_AddRef(pOIBindInfo
);
595 This
->bind_info
= pOIBindInfo
;
597 set_binding_sink(PROTOCOL(This
), pOIProtSink
);
599 hres
= IInternetProtocol_QueryInterface(protocol
, &IID_IInternetPriority
, (void**)&priority
);
600 if(SUCCEEDED(hres
)) {
601 IInternetPriority_SetPriority(priority
, This
->priority
);
602 IInternetPriority_Release(priority
);
605 return IInternetProtocol_Start(protocol
, szUrl
, PROTSINK(This
), BINDINFO(This
), 0, 0);
608 static HRESULT WINAPI
ProtocolHandler_Continue(IInternetProtocol
*iface
, PROTOCOLDATA
*pProtocolData
)
610 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
613 TRACE("(%p)->(%p)\n", This
, pProtocolData
);
615 hres
= IInternetProtocol_Continue(This
->protocol
, pProtocolData
);
617 heap_free(pProtocolData
);
621 static HRESULT WINAPI
ProtocolHandler_Abort(IInternetProtocol
*iface
, HRESULT hrReason
,
624 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
625 FIXME("(%p)->(%08x %08x)\n", This
, hrReason
, dwOptions
);
629 static HRESULT WINAPI
ProtocolHandler_Terminate(IInternetProtocol
*iface
, DWORD dwOptions
)
631 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
633 TRACE("(%p)->(%08x)\n", This
, dwOptions
);
635 if(!This
->reported_result
)
638 IInternetProtocol_Terminate(This
->protocol
, 0);
640 if(This
->filter_proxy
) {
641 IInternetProtocol_Release(PROTOCOL(This
->filter_proxy
));
642 This
->filter_proxy
= NULL
;
645 set_binding_sink(PROTOCOL(This
), NULL
);
647 if(This
->bind_info
) {
648 IInternetBindInfo_Release(This
->bind_info
);
649 This
->bind_info
= NULL
;
655 static HRESULT WINAPI
ProtocolHandler_Suspend(IInternetProtocol
*iface
)
657 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
658 FIXME("(%p)\n", This
);
662 static HRESULT WINAPI
ProtocolHandler_Resume(IInternetProtocol
*iface
)
664 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
665 FIXME("(%p)\n", This
);
669 static HRESULT WINAPI
ProtocolHandler_Read(IInternetProtocol
*iface
, void *pv
,
670 ULONG cb
, ULONG
*pcbRead
)
672 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
676 TRACE("(%p)->(%p %u %p)\n", This
, pv
, cb
, pcbRead
);
679 read
= min(cb
, This
->buf_size
);
680 memcpy(pv
, This
->buf
, read
);
682 if(read
== This
->buf_size
) {
683 heap_free(This
->buf
);
686 memmove(This
->buf
, This
->buf
+cb
, This
->buf_size
-cb
);
689 This
->buf_size
-= read
;
695 hres
= IInternetProtocol_Read(This
->protocol
, (BYTE
*)pv
+read
, cb
-read
, &cread
);
703 static HRESULT WINAPI
ProtocolHandler_Seek(IInternetProtocol
*iface
, LARGE_INTEGER dlibMove
,
704 DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
706 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
707 FIXME("(%p)->(%d %d %p)\n", This
, dlibMove
.u
.LowPart
, dwOrigin
, plibNewPosition
);
711 static HRESULT WINAPI
ProtocolHandler_LockRequest(IInternetProtocol
*iface
, DWORD dwOptions
)
713 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
715 TRACE("(%p)->(%08x)\n", This
, dwOptions
);
717 return IInternetProtocol_LockRequest(This
->protocol
, dwOptions
);
720 static HRESULT WINAPI
ProtocolHandler_UnlockRequest(IInternetProtocol
*iface
)
722 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
724 TRACE("(%p)\n", This
);
726 return IInternetProtocol_UnlockRequest(This
->protocol
);
731 static const IInternetProtocolVtbl InternetProtocolHandlerVtbl
= {
732 ProtocolHandler_QueryInterface
,
733 ProtocolHandler_AddRef
,
734 ProtocolHandler_Release
,
735 ProtocolHandler_Start
,
736 ProtocolHandler_Continue
,
737 ProtocolHandler_Abort
,
738 ProtocolHandler_Terminate
,
739 ProtocolHandler_Suspend
,
740 ProtocolHandler_Resume
,
741 ProtocolHandler_Read
,
742 ProtocolHandler_Seek
,
743 ProtocolHandler_LockRequest
,
744 ProtocolHandler_UnlockRequest
747 #define BINDINFO_THIS(iface) DEFINE_THIS(BindProtocol, InternetBindInfo, iface)
749 static HRESULT WINAPI
BindInfo_QueryInterface(IInternetBindInfo
*iface
,
750 REFIID riid
, void **ppv
)
752 BindProtocol
*This
= BINDINFO_THIS(iface
);
753 return IInternetProtocol_QueryInterface(PROTOCOL(This
), riid
, ppv
);
756 static ULONG WINAPI
BindInfo_AddRef(IInternetBindInfo
*iface
)
758 BindProtocol
*This
= BINDINFO_THIS(iface
);
759 return IBinding_AddRef(PROTOCOL(This
));
762 static ULONG WINAPI
BindInfo_Release(IInternetBindInfo
*iface
)
764 BindProtocol
*This
= BINDINFO_THIS(iface
);
765 return IBinding_Release(PROTOCOL(This
));
768 static HRESULT WINAPI
BindInfo_GetBindInfo(IInternetBindInfo
*iface
,
769 DWORD
*grfBINDF
, BINDINFO
*pbindinfo
)
771 BindProtocol
*This
= BINDINFO_THIS(iface
);
774 TRACE("(%p)->(%p %p)\n", This
, grfBINDF
, pbindinfo
);
776 hres
= IInternetBindInfo_GetBindInfo(This
->bind_info
, grfBINDF
, pbindinfo
);
778 WARN("GetBindInfo failed: %08x\n", hres
);
782 *grfBINDF
|= BINDF_FROMURLMON
;
786 static HRESULT WINAPI
BindInfo_GetBindString(IInternetBindInfo
*iface
,
787 ULONG ulStringType
, LPOLESTR
*ppwzStr
, ULONG cEl
, ULONG
*pcElFetched
)
789 BindProtocol
*This
= BINDINFO_THIS(iface
);
791 TRACE("(%p)->(%d %p %d %p)\n", This
, ulStringType
, ppwzStr
, cEl
, pcElFetched
);
793 return IInternetBindInfo_GetBindString(This
->bind_info
, ulStringType
, ppwzStr
, cEl
, pcElFetched
);
798 static const IInternetBindInfoVtbl InternetBindInfoVtbl
= {
799 BindInfo_QueryInterface
,
802 BindInfo_GetBindInfo
,
803 BindInfo_GetBindString
806 #define PRIORITY_THIS(iface) DEFINE_THIS(BindProtocol, InternetPriority, iface)
808 static HRESULT WINAPI
InternetPriority_QueryInterface(IInternetPriority
*iface
,
809 REFIID riid
, void **ppv
)
811 BindProtocol
*This
= PRIORITY_THIS(iface
);
812 return IInternetProtocol_QueryInterface(PROTOCOL(This
), riid
, ppv
);
815 static ULONG WINAPI
InternetPriority_AddRef(IInternetPriority
*iface
)
817 BindProtocol
*This
= PRIORITY_THIS(iface
);
818 return IInternetProtocol_AddRef(PROTOCOL(This
));
821 static ULONG WINAPI
InternetPriority_Release(IInternetPriority
*iface
)
823 BindProtocol
*This
= PRIORITY_THIS(iface
);
824 return IInternetProtocol_Release(PROTOCOL(This
));
827 static HRESULT WINAPI
InternetPriority_SetPriority(IInternetPriority
*iface
, LONG nPriority
)
829 BindProtocol
*This
= PRIORITY_THIS(iface
);
831 TRACE("(%p)->(%d)\n", This
, nPriority
);
833 This
->priority
= nPriority
;
837 static HRESULT WINAPI
InternetPriority_GetPriority(IInternetPriority
*iface
, LONG
*pnPriority
)
839 BindProtocol
*This
= PRIORITY_THIS(iface
);
841 TRACE("(%p)->(%p)\n", This
, pnPriority
);
843 *pnPriority
= This
->priority
;
849 static const IInternetPriorityVtbl InternetPriorityVtbl
= {
850 InternetPriority_QueryInterface
,
851 InternetPriority_AddRef
,
852 InternetPriority_Release
,
853 InternetPriority_SetPriority
,
854 InternetPriority_GetPriority
858 #define PROTSINK_THIS(iface) DEFINE_THIS(BindProtocol, IInternetProtocolSink, iface)
860 static HRESULT WINAPI
BPInternetProtocolSink_QueryInterface(IInternetProtocolSink
*iface
,
861 REFIID riid
, void **ppv
)
863 BindProtocol
*This
= PROTSINK_THIS(iface
);
864 return IInternetProtocol_QueryInterface(PROTOCOL(This
), riid
, ppv
);
867 static ULONG WINAPI
BPInternetProtocolSink_AddRef(IInternetProtocolSink
*iface
)
869 BindProtocol
*This
= PROTSINK_THIS(iface
);
870 return IInternetProtocol_AddRef(PROTOCOL(This
));
873 static ULONG WINAPI
BPInternetProtocolSink_Release(IInternetProtocolSink
*iface
)
875 BindProtocol
*This
= PROTSINK_THIS(iface
);
876 return IInternetProtocol_Release(PROTOCOL(This
));
880 task_header_t header
;
884 static void switch_proc(BindProtocol
*bind
, task_header_t
*t
)
886 switch_task_t
*task
= (switch_task_t
*)t
;
888 IInternetProtocol_Continue(bind
->protocol_handler
, task
->data
);
893 static HRESULT WINAPI
BPInternetProtocolSink_Switch(IInternetProtocolSink
*iface
,
894 PROTOCOLDATA
*pProtocolData
)
896 BindProtocol
*This
= PROTSINK_THIS(iface
);
899 TRACE("(%p)->(%p)\n", This
, pProtocolData
);
901 TRACE("flags %x state %x data %p cb %u\n", pProtocolData
->grfFlags
, pProtocolData
->dwState
,
902 pProtocolData
->pData
, pProtocolData
->cbData
);
904 data
= heap_alloc(sizeof(PROTOCOLDATA
));
906 return E_OUTOFMEMORY
;
907 memcpy(data
, pProtocolData
, sizeof(PROTOCOLDATA
));
909 if(!do_direct_notif(This
)) {
912 task
= heap_alloc(sizeof(switch_task_t
));
914 return E_OUTOFMEMORY
;
918 push_task(This
, &task
->header
, switch_proc
);
922 if(!This
->protocol_sink
) {
923 IInternetProtocol_Continue(This
->protocol_handler
, data
);
927 return IInternetProtocolSink_Switch(This
->protocol_sink
, data
);
930 static void report_progress(BindProtocol
*This
, ULONG status_code
, LPCWSTR status_text
)
932 switch(status_code
) {
933 case BINDSTATUS_FINDINGRESOURCE
:
934 case BINDSTATUS_CONNECTING
:
935 case BINDSTATUS_BEGINDOWNLOADDATA
:
936 case BINDSTATUS_SENDINGREQUEST
:
937 case BINDSTATUS_CACHEFILENAMEAVAILABLE
:
938 case BINDSTATUS_DIRECTBIND
:
939 case BINDSTATUS_ACCEPTRANGES
:
940 if(This
->protocol_sink
)
941 IInternetProtocolSink_ReportProgress(This
->protocol_sink
, status_code
, status_text
);
944 case BINDSTATUS_MIMETYPEAVAILABLE
:
945 mime_available(This
, status_text
, FALSE
);
948 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE
:
949 mime_available(This
, status_text
, TRUE
);
953 FIXME("unsupported ulStatusCode %u\n", status_code
);
958 task_header_t header
;
962 } on_progress_task_t
;
964 static void on_progress_proc(BindProtocol
*This
, task_header_t
*t
)
966 on_progress_task_t
*task
= (on_progress_task_t
*)t
;
968 report_progress(This
, task
->status_code
, task
->status_text
);
970 heap_free(task
->status_text
);
974 static HRESULT WINAPI
BPInternetProtocolSink_ReportProgress(IInternetProtocolSink
*iface
,
975 ULONG ulStatusCode
, LPCWSTR szStatusText
)
977 BindProtocol
*This
= PROTSINK_THIS(iface
);
979 TRACE("(%p)->(%u %s)\n", This
, ulStatusCode
, debugstr_w(szStatusText
));
981 if(do_direct_notif(This
)) {
982 report_progress(This
, ulStatusCode
, szStatusText
);
984 on_progress_task_t
*task
;
986 task
= heap_alloc(sizeof(on_progress_task_t
));
988 task
->status_code
= ulStatusCode
;
989 task
->status_text
= heap_strdupW(szStatusText
);
991 push_task(This
, &task
->header
, on_progress_proc
);
997 static HRESULT
report_data(BindProtocol
*This
, DWORD bscf
, ULONG progress
, ULONG progress_max
)
999 if(!This
->protocol_sink
)
1002 if((This
->pi
& PI_MIMEVERIFICATION
) && !This
->reported_mime
) {
1008 This
->buf
= heap_alloc(BUFFER_SIZE
);
1010 return E_OUTOFMEMORY
;
1015 hres
= IInternetProtocol_Read(This
->protocol
, This
->buf
+This
->buf_size
,
1016 BUFFER_SIZE
-This
->buf_size
, &read
);
1017 if(FAILED(hres
) && hres
!= E_PENDING
)
1019 This
->buf_size
+= read
;
1020 }while(This
->buf_size
< MIME_TEST_SIZE
&& hres
== S_OK
);
1022 if(This
->buf_size
< MIME_TEST_SIZE
&& hres
!= S_FALSE
)
1025 hres
= FindMimeFromData(NULL
, This
->url
, This
->buf
, min(This
->buf_size
, MIME_TEST_SIZE
),
1026 This
->mime
, 0, &mime
, 0);
1030 mime_available(This
, mime
, TRUE
);
1031 CoTaskMemFree(mime
);
1034 return IInternetProtocolSink_ReportData(This
->protocol_sink
, bscf
, progress
, progress_max
);
1038 task_header_t header
;
1042 } report_data_task_t
;
1044 static void report_data_proc(BindProtocol
*This
, task_header_t
*t
)
1046 report_data_task_t
*task
= (report_data_task_t
*)t
;
1048 report_data(This
, task
->bscf
, task
->progress
, task
->progress_max
);
1052 static HRESULT WINAPI
BPInternetProtocolSink_ReportData(IInternetProtocolSink
*iface
,
1053 DWORD grfBSCF
, ULONG ulProgress
, ULONG ulProgressMax
)
1055 BindProtocol
*This
= PROTSINK_THIS(iface
);
1057 TRACE("(%p)->(%d %u %u)\n", This
, grfBSCF
, ulProgress
, ulProgressMax
);
1059 if(!This
->protocol_sink
)
1062 if(!do_direct_notif(This
)) {
1063 report_data_task_t
*task
;
1065 task
= heap_alloc(sizeof(report_data_task_t
));
1067 return E_OUTOFMEMORY
;
1069 task
->bscf
= grfBSCF
;
1070 task
->progress
= ulProgress
;
1071 task
->progress_max
= ulProgressMax
;
1073 push_task(This
, &task
->header
, report_data_proc
);
1077 return report_data(This
, grfBSCF
, ulProgress
, ulProgressMax
);
1081 task_header_t header
;
1086 } report_result_task_t
;
1088 static void report_result_proc(BindProtocol
*This
, task_header_t
*t
)
1090 report_result_task_t
*task
= (report_result_task_t
*)t
;
1092 if(This
->protocol_sink
)
1093 IInternetProtocolSink_ReportResult(This
->protocol_sink
, task
->hres
, task
->err
, task
->str
);
1095 heap_free(task
->str
);
1099 static HRESULT WINAPI
BPInternetProtocolSink_ReportResult(IInternetProtocolSink
*iface
,
1100 HRESULT hrResult
, DWORD dwError
, LPCWSTR szResult
)
1102 BindProtocol
*This
= PROTSINK_THIS(iface
);
1104 TRACE("(%p)->(%08x %d %s)\n", This
, hrResult
, dwError
, debugstr_w(szResult
));
1106 if(!This
->protocol_sink
)
1109 This
->reported_result
= TRUE
;
1111 if(!do_direct_notif(This
)) {
1112 report_result_task_t
*task
;
1114 task
= heap_alloc(sizeof(report_result_task_t
));
1116 return E_OUTOFMEMORY
;
1118 task
->hres
= hrResult
;
1119 task
->err
= dwError
;
1120 task
->str
= heap_strdupW(szResult
);
1122 push_task(This
, &task
->header
, report_result_proc
);
1126 return IInternetProtocolSink_ReportResult(This
->protocol_sink
, hrResult
, dwError
, szResult
);
1129 #undef PROTSINK_THIS
1131 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl
= {
1132 BPInternetProtocolSink_QueryInterface
,
1133 BPInternetProtocolSink_AddRef
,
1134 BPInternetProtocolSink_Release
,
1135 BPInternetProtocolSink_Switch
,
1136 BPInternetProtocolSink_ReportProgress
,
1137 BPInternetProtocolSink_ReportData
,
1138 BPInternetProtocolSink_ReportResult
1141 #define SERVPROV_THIS(iface) DEFINE_THIS(BindProtocol, ServiceProvider, iface)
1143 static HRESULT WINAPI
BPServiceProvider_QueryInterface(IServiceProvider
*iface
,
1144 REFIID riid
, void **ppv
)
1146 BindProtocol
*This
= SERVPROV_THIS(iface
);
1147 return IInternetProtocol_QueryInterface(PROTOCOL(This
), riid
, ppv
);
1150 static ULONG WINAPI
BPServiceProvider_AddRef(IServiceProvider
*iface
)
1152 BindProtocol
*This
= SERVPROV_THIS(iface
);
1153 return IInternetProtocol_AddRef(PROTOCOL(This
));
1156 static ULONG WINAPI
BPServiceProvider_Release(IServiceProvider
*iface
)
1158 BindProtocol
*This
= SERVPROV_THIS(iface
);
1159 return IInternetProtocol_Release(PROTOCOL(This
));
1162 static HRESULT WINAPI
BPServiceProvider_QueryService(IServiceProvider
*iface
,
1163 REFGUID guidService
, REFIID riid
, void **ppv
)
1165 BindProtocol
*This
= SERVPROV_THIS(iface
);
1167 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_guid(guidService
), debugstr_guid(riid
), ppv
);
1169 if(!This
->service_provider
)
1170 return E_NOINTERFACE
;
1172 return IServiceProvider_QueryService(This
->service_provider
, guidService
, riid
, ppv
);
1175 #undef SERVPROV_THIS
1177 static const IServiceProviderVtbl ServiceProviderVtbl
= {
1178 BPServiceProvider_QueryInterface
,
1179 BPServiceProvider_AddRef
,
1180 BPServiceProvider_Release
,
1181 BPServiceProvider_QueryService
1184 HRESULT
create_binding_protocol(LPCWSTR url
, BOOL from_urlmon
, IInternetProtocol
**protocol
)
1186 BindProtocol
*ret
= heap_alloc_zero(sizeof(BindProtocol
));
1188 ret
->lpIInternetProtocolVtbl
= &BindProtocolVtbl
;
1189 ret
->lpInternetBindInfoVtbl
= &InternetBindInfoVtbl
;
1190 ret
->lpInternetPriorityVtbl
= &InternetPriorityVtbl
;
1191 ret
->lpServiceProviderVtbl
= &ServiceProviderVtbl
;
1192 ret
->lpIInternetProtocolSinkVtbl
= &InternetProtocolSinkVtbl
;
1193 ret
->lpIInternetProtocolHandlerVtbl
= &InternetProtocolHandlerVtbl
;
1196 ret
->from_urlmon
= from_urlmon
;
1197 ret
->apartment_thread
= GetCurrentThreadId();
1198 ret
->notif_hwnd
= get_notif_hwnd();
1199 ret
->protocol_handler
= PROTOCOLHANDLER(ret
);
1200 InitializeCriticalSection(&ret
->section
);
1202 URLMON_LockModule();
1204 *protocol
= PROTOCOL(ret
);