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
;
41 const IWinInetHttpInfoVtbl
*lpIWinInetHttpInfoVtbl
;
43 const IInternetProtocolVtbl
*lpIInternetProtocolHandlerVtbl
;
47 IInternetProtocol
*protocol
;
48 IInternetProtocol
*protocol_handler
;
49 IInternetBindInfo
*bind_info
;
50 IInternetProtocolSink
*protocol_sink
;
51 IServiceProvider
*service_provider
;
52 IWinInetInfo
*wininet_info
;
61 DWORD apartment_thread
;
65 CRITICAL_SECTION section
;
66 task_header_t
*task_queue_head
, *task_queue_tail
;
72 ProtocolProxy
*filter_proxy
;
75 #define BINDINFO(x) ((IInternetBindInfo*) &(x)->lpInternetBindInfoVtbl)
76 #define PRIORITY(x) ((IInternetPriority*) &(x)->lpInternetPriorityVtbl)
77 #define HTTPINFO(x) ((IWinInetHttpInfo*) &(x)->lpIWinInetHttpInfoVtbl)
78 #define SERVPROV(x) ((IServiceProvider*) &(x)->lpServiceProviderVtbl)
80 #define PROTOCOLHANDLER(x) ((IInternetProtocol*) &(x)->lpIInternetProtocolHandlerVtbl)
82 #define BUFFER_SIZE 2048
83 #define MIME_TEST_SIZE 255
85 #define WM_MK_CONTINUE (WM_USER+101)
86 #define WM_MK_RELEASE (WM_USER+102)
88 static LRESULT WINAPI
notif_wnd_proc(HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
91 case WM_MK_CONTINUE
: {
92 BindProtocol
*This
= (BindProtocol
*)lParam
;
96 EnterCriticalSection(&This
->section
);
98 task
= This
->task_queue_head
;
100 This
->task_queue_head
= task
->next
;
101 if(!This
->task_queue_head
)
102 This
->task_queue_tail
= NULL
;
105 LeaveCriticalSection(&This
->section
);
110 This
->continue_call
++;
111 task
->proc(This
, task
);
112 This
->continue_call
--;
115 IInternetProtocol_Release(PROTOCOL(This
));
118 case WM_MK_RELEASE
: {
119 tls_data_t
*data
= get_tls_data();
121 if(!--data
->notif_hwnd_cnt
) {
123 data
->notif_hwnd
= NULL
;
128 return DefWindowProcW(hwnd
, msg
, wParam
, lParam
);
131 HWND
get_notif_hwnd(void)
133 static ATOM wnd_class
= 0;
134 tls_data_t
*tls_data
;
136 static const WCHAR wszURLMonikerNotificationWindow
[] =
137 {'U','R','L',' ','M','o','n','i','k','e','r',' ',
138 'N','o','t','i','f','i','c','a','t','i','o','n',' ','W','i','n','d','o','w',0};
140 tls_data
= get_tls_data();
144 if(tls_data
->notif_hwnd_cnt
) {
145 tls_data
->notif_hwnd_cnt
++;
146 return tls_data
->notif_hwnd
;
150 static WNDCLASSEXW wndclass
= {
152 notif_wnd_proc
, 0, 0,
153 NULL
, NULL
, NULL
, NULL
, NULL
,
154 wszURLMonikerNotificationWindow
,
158 wndclass
.hInstance
= hProxyDll
;
160 wnd_class
= RegisterClassExW(&wndclass
);
161 if (!wnd_class
&& GetLastError() == ERROR_CLASS_ALREADY_EXISTS
)
165 tls_data
->notif_hwnd
= CreateWindowExW(0, wszURLMonikerNotificationWindow
,
166 wszURLMonikerNotificationWindow
, 0, 0, 0, 0, 0, HWND_MESSAGE
,
167 NULL
, hProxyDll
, NULL
);
168 if(tls_data
->notif_hwnd
)
169 tls_data
->notif_hwnd_cnt
++;
171 TRACE("hwnd = %p\n", tls_data
->notif_hwnd
);
173 return tls_data
->notif_hwnd
;
176 void release_notif_hwnd(HWND hwnd
)
178 tls_data_t
*data
= get_tls_data();
183 if(data
->notif_hwnd
!= hwnd
) {
184 PostMessageW(data
->notif_hwnd
, WM_MK_RELEASE
, 0, 0);
188 if(!--data
->notif_hwnd_cnt
) {
189 DestroyWindow(data
->notif_hwnd
);
190 data
->notif_hwnd
= NULL
;
194 static void push_task(BindProtocol
*This
, task_header_t
*task
, task_proc_t proc
)
196 BOOL do_post
= FALSE
;
201 EnterCriticalSection(&This
->section
);
203 if(This
->task_queue_tail
) {
204 This
->task_queue_tail
->next
= task
;
205 This
->task_queue_tail
= task
;
207 This
->task_queue_tail
= This
->task_queue_head
= task
;
208 do_post
= !This
->continue_call
;
211 LeaveCriticalSection(&This
->section
);
214 IInternetProtocol_AddRef(PROTOCOL(This
));
215 PostMessageW(This
->notif_hwnd
, WM_MK_CONTINUE
, 0, (LPARAM
)This
);
219 static inline BOOL
do_direct_notif(BindProtocol
*This
)
221 return !(This
->pi
& PI_APARTMENTTHREADED
) || (This
->apartment_thread
== GetCurrentThreadId() && !This
->continue_call
);
224 static HRESULT
handle_mime_filter(BindProtocol
*This
, IInternetProtocol
*mime_filter
, LPCWSTR mime
)
226 PROTOCOLFILTERDATA filter_data
= { sizeof(PROTOCOLFILTERDATA
), NULL
, NULL
, NULL
, 0 };
227 IInternetProtocolSink
*protocol_sink
, *old_sink
;
228 ProtocolProxy
*filter_proxy
;
231 hres
= IInternetProtocol_QueryInterface(mime_filter
, &IID_IInternetProtocolSink
, (void**)&protocol_sink
);
235 hres
= create_protocol_proxy(PROTOCOLHANDLER(This
), This
->protocol_sink
, &filter_proxy
);
237 IInternetProtocolSink_Release(protocol_sink
);
241 old_sink
= This
->protocol_sink
;
242 This
->protocol_sink
= protocol_sink
;
243 This
->filter_proxy
= filter_proxy
;
245 IInternetProtocol_AddRef(mime_filter
);
246 This
->protocol_handler
= mime_filter
;
248 filter_data
.pProtocol
= PROTOCOL(filter_proxy
);
249 hres
= IInternetProtocol_Start(mime_filter
, mime
, PROTSINK(filter_proxy
), BINDINFO(This
),
250 PI_FILTER_MODE
|PI_FORCE_ASYNC
, (HANDLE_PTR
)&filter_data
);
252 IInternetProtocolSink_Release(old_sink
);
256 IInternetProtocolSink_ReportProgress(old_sink
, BINDSTATUS_LOADINGMIMEHANDLER
, NULL
);
257 IInternetProtocolSink_Release(old_sink
);
259 This
->pi
&= ~PI_MIMEVERIFICATION
; /* FIXME: more tests */
263 static void mime_available(BindProtocol
*This
, LPCWSTR mime
, BOOL verified
)
265 IInternetProtocol
*mime_filter
;
268 heap_free(This
->mime
);
271 mime_filter
= get_mime_filter(mime
);
273 TRACE("Got mime filter for %s\n", debugstr_w(mime
));
275 hres
= handle_mime_filter(This
, mime_filter
, mime
);
276 IInternetProtocol_Release(mime_filter
);
278 FIXME("MIME filter failed: %08x\n", hres
);
280 This
->mime
= heap_strdupW(mime
);
282 if(verified
|| !(This
->pi
& PI_MIMEVERIFICATION
)) {
283 This
->reported_mime
= TRUE
;
285 if(This
->protocol_sink
)
286 IInternetProtocolSink_ReportProgress(This
->protocol_sink
, BINDSTATUS_MIMETYPEAVAILABLE
, mime
);
291 #define PROTOCOL_THIS(iface) DEFINE_THIS(BindProtocol, IInternetProtocol, iface)
293 static HRESULT WINAPI
BindProtocol_QueryInterface(IInternetProtocol
*iface
, REFIID riid
, void **ppv
)
295 BindProtocol
*This
= PROTOCOL_THIS(iface
);
298 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
299 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
300 *ppv
= PROTOCOL(This
);
301 }else if(IsEqualGUID(&IID_IInternetProtocolRoot
, riid
)) {
302 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This
, ppv
);
303 *ppv
= PROTOCOL(This
);
304 }else if(IsEqualGUID(&IID_IInternetProtocol
, riid
)) {
305 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This
, ppv
);
306 *ppv
= PROTOCOL(This
);
307 }else if(IsEqualGUID(&IID_IInternetBindInfo
, riid
)) {
308 TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This
, ppv
);
309 *ppv
= BINDINFO(This
);
310 }else if(IsEqualGUID(&IID_IInternetPriority
, riid
)) {
311 TRACE("(%p)->(IID_IInternetPriority %p)\n", This
, ppv
);
312 *ppv
= PRIORITY(This
);
313 }else if(IsEqualGUID(&IID_IAuthenticate
, riid
)) {
314 FIXME("(%p)->(IID_IAuthenticate %p)\n", This
, ppv
);
315 }else if(IsEqualGUID(&IID_IServiceProvider
, riid
)) {
316 TRACE("(%p)->(IID_IServiceProvider %p)\n", This
, ppv
);
317 *ppv
= SERVPROV(This
);
318 }else if(IsEqualGUID(&IID_IInternetProtocolSink
, riid
)) {
319 TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This
, ppv
);
320 *ppv
= PROTSINK(This
);
321 }else if(IsEqualGUID(&IID_IWinInetInfo
, riid
)) {
322 TRACE("(%p)->(IID_IWinInetInfo %p)\n", This
, ppv
);
325 IWinInetInfo
*inet_info
;
328 hres
= IInternetProtocol_QueryInterface(This
->protocol
, &IID_IWinInetInfo
, (void**)&inet_info
);
329 if(SUCCEEDED(hres
)) {
330 *ppv
= HTTPINFO(This
);
331 IWinInetInfo_Release(inet_info
);
334 }else if(IsEqualGUID(&IID_IWinInetHttpInfo
, riid
)) {
335 TRACE("(%p)->(IID_IWinInetHttpInfo %p)\n", This
, ppv
);
338 IWinInetHttpInfo
*http_info
;
341 hres
= IInternetProtocol_QueryInterface(This
->protocol
, &IID_IWinInetHttpInfo
, (void**)&http_info
);
342 if(SUCCEEDED(hres
)) {
343 *ppv
= HTTPINFO(This
);
344 IWinInetHttpInfo_Release(http_info
);
348 WARN("not supported interface %s\n", debugstr_guid(riid
));
352 return E_NOINTERFACE
;
354 IUnknown_AddRef((IUnknown
*)*ppv
);
358 static ULONG WINAPI
BindProtocol_AddRef(IInternetProtocol
*iface
)
360 BindProtocol
*This
= PROTOCOL_THIS(iface
);
361 LONG ref
= InterlockedIncrement(&This
->ref
);
362 TRACE("(%p) ref=%d\n", This
, ref
);
366 static ULONG WINAPI
BindProtocol_Release(IInternetProtocol
*iface
)
368 BindProtocol
*This
= PROTOCOL_THIS(iface
);
369 LONG ref
= InterlockedDecrement(&This
->ref
);
371 TRACE("(%p) ref=%d\n", This
, ref
);
374 if(This
->wininet_info
)
375 IWinInetInfo_Release(This
->wininet_info
);
377 IInternetProtocol_Release(This
->protocol
);
379 IInternetBindInfo_Release(This
->bind_info
);
380 if(This
->protocol_handler
&& This
->protocol_handler
!= PROTOCOLHANDLER(This
))
381 IInternetProtocol_Release(This
->protocol_handler
);
382 if(This
->filter_proxy
)
383 IInternetProtocol_Release(PROTOCOL(This
->filter_proxy
));
385 set_binding_sink(PROTOCOL(This
), NULL
, NULL
);
388 release_notif_hwnd(This
->notif_hwnd
);
389 DeleteCriticalSection(&This
->section
);
391 heap_free(This
->mime
);
392 heap_free(This
->url
);
395 URLMON_UnlockModule();
401 static HRESULT WINAPI
BindProtocol_Start(IInternetProtocol
*iface
, LPCWSTR szUrl
,
402 IInternetProtocolSink
*pOIProtSink
, IInternetBindInfo
*pOIBindInfo
,
403 DWORD grfPI
, HANDLE_PTR dwReserved
)
405 BindProtocol
*This
= PROTOCOL_THIS(iface
);
407 TRACE("(%p)->(%s %p %p %08x %lx)\n", This
, debugstr_w(szUrl
), pOIProtSink
,
408 pOIBindInfo
, grfPI
, dwReserved
);
410 return IInternetProtocol_Start(This
->protocol_handler
, szUrl
, pOIProtSink
, pOIBindInfo
, grfPI
, dwReserved
);
413 static HRESULT WINAPI
BindProtocol_Continue(IInternetProtocol
*iface
, PROTOCOLDATA
*pProtocolData
)
415 BindProtocol
*This
= PROTOCOL_THIS(iface
);
417 TRACE("(%p)->(%p)\n", This
, pProtocolData
);
419 return IInternetProtocol_Continue(This
->protocol_handler
, pProtocolData
);
422 static HRESULT WINAPI
BindProtocol_Abort(IInternetProtocol
*iface
, HRESULT hrReason
,
425 BindProtocol
*This
= PROTOCOL_THIS(iface
);
427 TRACE("(%p)->(%08x %08x)\n", This
, hrReason
, dwOptions
);
429 return IInternetProtocol_Abort(This
->protocol_handler
, hrReason
, dwOptions
);
432 static HRESULT WINAPI
BindProtocol_Terminate(IInternetProtocol
*iface
, DWORD dwOptions
)
434 BindProtocol
*This
= PROTOCOL_THIS(iface
);
436 TRACE("(%p)->(%08x)\n", This
, dwOptions
);
438 return IInternetProtocol_Terminate(This
->protocol_handler
, dwOptions
);
441 static HRESULT WINAPI
BindProtocol_Suspend(IInternetProtocol
*iface
)
443 BindProtocol
*This
= PROTOCOL_THIS(iface
);
444 FIXME("(%p)\n", This
);
448 static HRESULT WINAPI
BindProtocol_Resume(IInternetProtocol
*iface
)
450 BindProtocol
*This
= PROTOCOL_THIS(iface
);
451 FIXME("(%p)\n", This
);
455 static HRESULT WINAPI
BindProtocol_Read(IInternetProtocol
*iface
, void *pv
,
456 ULONG cb
, ULONG
*pcbRead
)
458 BindProtocol
*This
= PROTOCOL_THIS(iface
);
460 TRACE("(%p)->(%p %u %p)\n", This
, pv
, cb
, pcbRead
);
464 return IInternetProtocol_Read(This
->protocol_handler
, pv
, cb
, pcbRead
);
467 static HRESULT WINAPI
BindProtocol_Seek(IInternetProtocol
*iface
, LARGE_INTEGER dlibMove
,
468 DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
470 BindProtocol
*This
= PROTOCOL_THIS(iface
);
471 FIXME("(%p)->(%d %d %p)\n", This
, dlibMove
.u
.LowPart
, dwOrigin
, plibNewPosition
);
475 static HRESULT WINAPI
BindProtocol_LockRequest(IInternetProtocol
*iface
, DWORD dwOptions
)
477 BindProtocol
*This
= PROTOCOL_THIS(iface
);
479 TRACE("(%p)->(%08x)\n", This
, dwOptions
);
481 return IInternetProtocol_LockRequest(This
->protocol_handler
, dwOptions
);
484 static HRESULT WINAPI
BindProtocol_UnlockRequest(IInternetProtocol
*iface
)
486 BindProtocol
*This
= PROTOCOL_THIS(iface
);
488 TRACE("(%p)\n", This
);
490 return IInternetProtocol_UnlockRequest(This
->protocol_handler
);
493 void set_binding_sink(IInternetProtocol
*bind_protocol
, IInternetProtocolSink
*sink
, IInternetBindInfo
*bind_info
)
495 BindProtocol
*This
= PROTOCOL_THIS(bind_protocol
);
496 IInternetProtocolSink
*prev_sink
;
497 IServiceProvider
*service_provider
= NULL
;
500 IInternetProtocolSink_AddRef(sink
);
501 prev_sink
= InterlockedExchangePointer((void**)&This
->protocol_sink
, sink
);
503 IInternetProtocolSink_Release(prev_sink
);
506 IInternetProtocolSink_QueryInterface(sink
, &IID_IServiceProvider
, (void**)&service_provider
);
507 service_provider
= InterlockedExchangePointer((void**)&This
->service_provider
, service_provider
);
509 IServiceProvider_Release(service_provider
);
512 IInternetBindInfo_AddRef(bind_info
);
513 bind_info
= InterlockedExchangePointer((void**)&This
->bind_info
, bind_info
);
515 IInternetBindInfo_Release(bind_info
);
518 IWinInetInfo
*get_wininet_info(IInternetProtocol
*bind_protocol
)
520 BindProtocol
*This
= PROTOCOL_THIS(bind_protocol
);
522 return This
->wininet_info
;
527 static const IInternetProtocolVtbl BindProtocolVtbl
= {
528 BindProtocol_QueryInterface
,
530 BindProtocol_Release
,
532 BindProtocol_Continue
,
534 BindProtocol_Terminate
,
535 BindProtocol_Suspend
,
539 BindProtocol_LockRequest
,
540 BindProtocol_UnlockRequest
543 #define PROTOCOLHANDLER_THIS(iface) DEFINE_THIS(BindProtocol, IInternetProtocolHandler, iface)
545 static HRESULT WINAPI
ProtocolHandler_QueryInterface(IInternetProtocol
*iface
, REFIID riid
, void **ppv
)
547 ERR("should not be called\n");
548 return E_NOINTERFACE
;
551 static ULONG WINAPI
ProtocolHandler_AddRef(IInternetProtocol
*iface
)
553 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
554 return IInternetProtocol_AddRef(PROTOCOL(This
));
557 static ULONG WINAPI
ProtocolHandler_Release(IInternetProtocol
*iface
)
559 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
560 return IInternetProtocol_Release(PROTOCOL(This
));
563 static HRESULT WINAPI
ProtocolHandler_Start(IInternetProtocol
*iface
, LPCWSTR szUrl
,
564 IInternetProtocolSink
*pOIProtSink
, IInternetBindInfo
*pOIBindInfo
,
565 DWORD grfPI
, HANDLE_PTR dwReserved
)
567 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
568 IInternetProtocol
*protocol
= NULL
;
569 IInternetPriority
*priority
;
570 IServiceProvider
*service_provider
;
571 BOOL urlmon_protocol
= FALSE
;
572 CLSID clsid
= IID_NULL
;
576 TRACE("(%p)->(%s %p %p %08x %lx)\n", This
, debugstr_w(szUrl
), pOIProtSink
,
577 pOIBindInfo
, grfPI
, dwReserved
);
579 if(!szUrl
|| !pOIProtSink
|| !pOIBindInfo
)
583 This
->url
= heap_strdupW(szUrl
);
585 hres
= IInternetProtocolSink_QueryInterface(pOIProtSink
, &IID_IServiceProvider
,
586 (void**)&service_provider
);
587 if(SUCCEEDED(hres
)) {
588 /* FIXME: What's protocol CLSID here? */
589 IServiceProvider_QueryService(service_provider
, &IID_IInternetProtocol
,
590 &IID_IInternetProtocol
, (void**)&protocol
);
591 IServiceProvider_Release(service_provider
);
598 hres
= get_protocol_handler(szUrl
, &clsid
, &urlmon_protocol
, &cf
);
602 if(This
->from_urlmon
) {
603 hres
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IInternetProtocol
, (void**)&protocol
);
604 IClassFactory_Release(cf
);
608 hres
= IClassFactory_CreateInstance(cf
, (IUnknown
*)BINDINFO(This
),
609 &IID_IUnknown
, (void**)&unk
);
610 IClassFactory_Release(cf
);
614 hres
= IUnknown_QueryInterface(unk
, &IID_IInternetProtocol
, (void**)&protocol
);
615 IUnknown_Release(unk
);
621 StringFromCLSID(&clsid
, &clsid_str
);
622 IInternetProtocolSink_ReportProgress(pOIProtSink
, BINDSTATUS_PROTOCOLCLASSID
, clsid_str
);
623 CoTaskMemFree(clsid_str
);
625 This
->protocol
= protocol
;
628 IInternetProtocol_QueryInterface(protocol
, &IID_IWinInetInfo
, (void**)&This
->wininet_info
);
630 set_binding_sink(PROTOCOL(This
), pOIProtSink
, pOIBindInfo
);
632 hres
= IInternetProtocol_QueryInterface(protocol
, &IID_IInternetPriority
, (void**)&priority
);
633 if(SUCCEEDED(hres
)) {
634 IInternetPriority_SetPriority(priority
, This
->priority
);
635 IInternetPriority_Release(priority
);
638 return IInternetProtocol_Start(protocol
, szUrl
, PROTSINK(This
), BINDINFO(This
), 0, 0);
641 static HRESULT WINAPI
ProtocolHandler_Continue(IInternetProtocol
*iface
, PROTOCOLDATA
*pProtocolData
)
643 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
646 TRACE("(%p)->(%p)\n", This
, pProtocolData
);
648 hres
= IInternetProtocol_Continue(This
->protocol
, pProtocolData
);
650 heap_free(pProtocolData
);
654 static HRESULT WINAPI
ProtocolHandler_Abort(IInternetProtocol
*iface
, HRESULT hrReason
,
657 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
659 TRACE("(%p)->(%08x %08x)\n", This
, hrReason
, dwOptions
);
661 if(This
->protocol
&& !This
->reported_result
)
662 return IInternetProtocol_Abort(This
->protocol
, hrReason
, dwOptions
);
667 static HRESULT WINAPI
ProtocolHandler_Terminate(IInternetProtocol
*iface
, DWORD dwOptions
)
669 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
671 TRACE("(%p)->(%08x)\n", This
, dwOptions
);
673 if(!This
->reported_result
)
676 IInternetProtocol_Terminate(This
->protocol
, 0);
678 if(This
->filter_proxy
) {
679 IInternetProtocol_Release(PROTOCOL(This
->filter_proxy
));
680 This
->filter_proxy
= NULL
;
683 set_binding_sink(PROTOCOL(This
), NULL
, NULL
);
685 if(This
->bind_info
) {
686 IInternetBindInfo_Release(This
->bind_info
);
687 This
->bind_info
= NULL
;
693 static HRESULT WINAPI
ProtocolHandler_Suspend(IInternetProtocol
*iface
)
695 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
696 FIXME("(%p)\n", This
);
700 static HRESULT WINAPI
ProtocolHandler_Resume(IInternetProtocol
*iface
)
702 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
703 FIXME("(%p)\n", This
);
707 static HRESULT WINAPI
ProtocolHandler_Read(IInternetProtocol
*iface
, void *pv
,
708 ULONG cb
, ULONG
*pcbRead
)
710 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
714 TRACE("(%p)->(%p %u %p)\n", This
, pv
, cb
, pcbRead
);
717 read
= min(cb
, This
->buf_size
);
718 memcpy(pv
, This
->buf
, read
);
720 if(read
== This
->buf_size
) {
721 heap_free(This
->buf
);
724 memmove(This
->buf
, This
->buf
+cb
, This
->buf_size
-cb
);
727 This
->buf_size
-= read
;
733 hres
= IInternetProtocol_Read(This
->protocol
, (BYTE
*)pv
+read
, cb
-read
, &cread
);
741 static HRESULT WINAPI
ProtocolHandler_Seek(IInternetProtocol
*iface
, LARGE_INTEGER dlibMove
,
742 DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
744 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
745 FIXME("(%p)->(%d %d %p)\n", This
, dlibMove
.u
.LowPart
, dwOrigin
, plibNewPosition
);
749 static HRESULT WINAPI
ProtocolHandler_LockRequest(IInternetProtocol
*iface
, DWORD dwOptions
)
751 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
753 TRACE("(%p)->(%08x)\n", This
, dwOptions
);
755 return IInternetProtocol_LockRequest(This
->protocol
, dwOptions
);
758 static HRESULT WINAPI
ProtocolHandler_UnlockRequest(IInternetProtocol
*iface
)
760 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
762 TRACE("(%p)\n", This
);
764 return IInternetProtocol_UnlockRequest(This
->protocol
);
769 static const IInternetProtocolVtbl InternetProtocolHandlerVtbl
= {
770 ProtocolHandler_QueryInterface
,
771 ProtocolHandler_AddRef
,
772 ProtocolHandler_Release
,
773 ProtocolHandler_Start
,
774 ProtocolHandler_Continue
,
775 ProtocolHandler_Abort
,
776 ProtocolHandler_Terminate
,
777 ProtocolHandler_Suspend
,
778 ProtocolHandler_Resume
,
779 ProtocolHandler_Read
,
780 ProtocolHandler_Seek
,
781 ProtocolHandler_LockRequest
,
782 ProtocolHandler_UnlockRequest
785 #define BINDINFO_THIS(iface) DEFINE_THIS(BindProtocol, InternetBindInfo, iface)
787 static HRESULT WINAPI
BindInfo_QueryInterface(IInternetBindInfo
*iface
,
788 REFIID riid
, void **ppv
)
790 BindProtocol
*This
= BINDINFO_THIS(iface
);
791 return IInternetProtocol_QueryInterface(PROTOCOL(This
), riid
, ppv
);
794 static ULONG WINAPI
BindInfo_AddRef(IInternetBindInfo
*iface
)
796 BindProtocol
*This
= BINDINFO_THIS(iface
);
797 return IBinding_AddRef(PROTOCOL(This
));
800 static ULONG WINAPI
BindInfo_Release(IInternetBindInfo
*iface
)
802 BindProtocol
*This
= BINDINFO_THIS(iface
);
803 return IBinding_Release(PROTOCOL(This
));
806 static HRESULT WINAPI
BindInfo_GetBindInfo(IInternetBindInfo
*iface
,
807 DWORD
*grfBINDF
, BINDINFO
*pbindinfo
)
809 BindProtocol
*This
= BINDINFO_THIS(iface
);
812 TRACE("(%p)->(%p %p)\n", This
, grfBINDF
, pbindinfo
);
814 hres
= IInternetBindInfo_GetBindInfo(This
->bind_info
, grfBINDF
, pbindinfo
);
816 WARN("GetBindInfo failed: %08x\n", hres
);
820 *grfBINDF
|= BINDF_FROMURLMON
;
824 static HRESULT WINAPI
BindInfo_GetBindString(IInternetBindInfo
*iface
,
825 ULONG ulStringType
, LPOLESTR
*ppwzStr
, ULONG cEl
, ULONG
*pcElFetched
)
827 BindProtocol
*This
= BINDINFO_THIS(iface
);
829 TRACE("(%p)->(%d %p %d %p)\n", This
, ulStringType
, ppwzStr
, cEl
, pcElFetched
);
831 return IInternetBindInfo_GetBindString(This
->bind_info
, ulStringType
, ppwzStr
, cEl
, pcElFetched
);
836 static const IInternetBindInfoVtbl InternetBindInfoVtbl
= {
837 BindInfo_QueryInterface
,
840 BindInfo_GetBindInfo
,
841 BindInfo_GetBindString
844 #define PRIORITY_THIS(iface) DEFINE_THIS(BindProtocol, InternetPriority, iface)
846 static HRESULT WINAPI
InternetPriority_QueryInterface(IInternetPriority
*iface
,
847 REFIID riid
, void **ppv
)
849 BindProtocol
*This
= PRIORITY_THIS(iface
);
850 return IInternetProtocol_QueryInterface(PROTOCOL(This
), riid
, ppv
);
853 static ULONG WINAPI
InternetPriority_AddRef(IInternetPriority
*iface
)
855 BindProtocol
*This
= PRIORITY_THIS(iface
);
856 return IInternetProtocol_AddRef(PROTOCOL(This
));
859 static ULONG WINAPI
InternetPriority_Release(IInternetPriority
*iface
)
861 BindProtocol
*This
= PRIORITY_THIS(iface
);
862 return IInternetProtocol_Release(PROTOCOL(This
));
865 static HRESULT WINAPI
InternetPriority_SetPriority(IInternetPriority
*iface
, LONG nPriority
)
867 BindProtocol
*This
= PRIORITY_THIS(iface
);
869 TRACE("(%p)->(%d)\n", This
, nPriority
);
871 This
->priority
= nPriority
;
875 static HRESULT WINAPI
InternetPriority_GetPriority(IInternetPriority
*iface
, LONG
*pnPriority
)
877 BindProtocol
*This
= PRIORITY_THIS(iface
);
879 TRACE("(%p)->(%p)\n", This
, pnPriority
);
881 *pnPriority
= This
->priority
;
887 static const IInternetPriorityVtbl InternetPriorityVtbl
= {
888 InternetPriority_QueryInterface
,
889 InternetPriority_AddRef
,
890 InternetPriority_Release
,
891 InternetPriority_SetPriority
,
892 InternetPriority_GetPriority
896 #define PROTSINK_THIS(iface) DEFINE_THIS(BindProtocol, IInternetProtocolSink, iface)
898 static HRESULT WINAPI
BPInternetProtocolSink_QueryInterface(IInternetProtocolSink
*iface
,
899 REFIID riid
, void **ppv
)
901 BindProtocol
*This
= PROTSINK_THIS(iface
);
902 return IInternetProtocol_QueryInterface(PROTOCOL(This
), riid
, ppv
);
905 static ULONG WINAPI
BPInternetProtocolSink_AddRef(IInternetProtocolSink
*iface
)
907 BindProtocol
*This
= PROTSINK_THIS(iface
);
908 return IInternetProtocol_AddRef(PROTOCOL(This
));
911 static ULONG WINAPI
BPInternetProtocolSink_Release(IInternetProtocolSink
*iface
)
913 BindProtocol
*This
= PROTSINK_THIS(iface
);
914 return IInternetProtocol_Release(PROTOCOL(This
));
918 task_header_t header
;
922 static void switch_proc(BindProtocol
*bind
, task_header_t
*t
)
924 switch_task_t
*task
= (switch_task_t
*)t
;
926 IInternetProtocol_Continue(bind
->protocol_handler
, task
->data
);
931 static HRESULT WINAPI
BPInternetProtocolSink_Switch(IInternetProtocolSink
*iface
,
932 PROTOCOLDATA
*pProtocolData
)
934 BindProtocol
*This
= PROTSINK_THIS(iface
);
937 TRACE("(%p)->(%p)\n", This
, pProtocolData
);
939 TRACE("flags %x state %x data %p cb %u\n", pProtocolData
->grfFlags
, pProtocolData
->dwState
,
940 pProtocolData
->pData
, pProtocolData
->cbData
);
942 data
= heap_alloc(sizeof(PROTOCOLDATA
));
944 return E_OUTOFMEMORY
;
945 memcpy(data
, pProtocolData
, sizeof(PROTOCOLDATA
));
947 if(!do_direct_notif(This
)) {
950 task
= heap_alloc(sizeof(switch_task_t
));
952 return E_OUTOFMEMORY
;
956 push_task(This
, &task
->header
, switch_proc
);
960 if(!This
->protocol_sink
) {
961 IInternetProtocol_Continue(This
->protocol_handler
, data
);
965 return IInternetProtocolSink_Switch(This
->protocol_sink
, data
);
968 static void report_progress(BindProtocol
*This
, ULONG status_code
, LPCWSTR status_text
)
970 switch(status_code
) {
971 case BINDSTATUS_FINDINGRESOURCE
:
972 case BINDSTATUS_CONNECTING
:
973 case BINDSTATUS_REDIRECTING
:
974 case BINDSTATUS_BEGINDOWNLOADDATA
:
975 case BINDSTATUS_SENDINGREQUEST
:
976 case BINDSTATUS_CACHEFILENAMEAVAILABLE
:
977 case BINDSTATUS_DIRECTBIND
:
978 case BINDSTATUS_ACCEPTRANGES
:
979 if(This
->protocol_sink
)
980 IInternetProtocolSink_ReportProgress(This
->protocol_sink
, status_code
, status_text
);
983 case BINDSTATUS_MIMETYPEAVAILABLE
:
984 mime_available(This
, status_text
, FALSE
);
987 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE
:
988 mime_available(This
, status_text
, TRUE
);
992 FIXME("unsupported ulStatusCode %u\n", status_code
);
997 task_header_t header
;
1001 } on_progress_task_t
;
1003 static void on_progress_proc(BindProtocol
*This
, task_header_t
*t
)
1005 on_progress_task_t
*task
= (on_progress_task_t
*)t
;
1007 report_progress(This
, task
->status_code
, task
->status_text
);
1009 heap_free(task
->status_text
);
1013 static HRESULT WINAPI
BPInternetProtocolSink_ReportProgress(IInternetProtocolSink
*iface
,
1014 ULONG ulStatusCode
, LPCWSTR szStatusText
)
1016 BindProtocol
*This
= PROTSINK_THIS(iface
);
1018 TRACE("(%p)->(%u %s)\n", This
, ulStatusCode
, debugstr_w(szStatusText
));
1020 if(do_direct_notif(This
)) {
1021 report_progress(This
, ulStatusCode
, szStatusText
);
1023 on_progress_task_t
*task
;
1025 task
= heap_alloc(sizeof(on_progress_task_t
));
1027 task
->status_code
= ulStatusCode
;
1028 task
->status_text
= heap_strdupW(szStatusText
);
1030 push_task(This
, &task
->header
, on_progress_proc
);
1036 static HRESULT
report_data(BindProtocol
*This
, DWORD bscf
, ULONG progress
, ULONG progress_max
)
1038 if(!This
->protocol_sink
)
1041 if((This
->pi
& PI_MIMEVERIFICATION
) && !This
->reported_mime
) {
1042 BYTE buf
[BUFFER_SIZE
];
1049 hres
= IInternetProtocol_Read(This
->protocol
, buf
,
1050 sizeof(buf
)-This
->buf_size
, &read
);
1051 if(FAILED(hres
) && hres
!= E_PENDING
)
1055 This
->buf
= heap_alloc(BUFFER_SIZE
);
1057 return E_OUTOFMEMORY
;
1058 }else if(read
+ This
->buf_size
> BUFFER_SIZE
) {
1061 tmp
= heap_realloc(This
->buf
, read
+This
->buf_size
);
1063 return E_OUTOFMEMORY
;
1067 memcpy(This
->buf
+This
->buf_size
, buf
, read
);
1068 This
->buf_size
+= read
;
1069 }while(This
->buf_size
< MIME_TEST_SIZE
&& hres
== S_OK
);
1071 if(This
->buf_size
< MIME_TEST_SIZE
&& hres
!= S_FALSE
)
1074 bscf
= BSCF_FIRSTDATANOTIFICATION
;
1076 bscf
|= BSCF_LASTDATANOTIFICATION
|BSCF_DATAFULLYAVAILABLE
;
1078 if(!This
->reported_mime
) {
1079 hres
= FindMimeFromData(NULL
, This
->url
, This
->buf
, min(This
->buf_size
, MIME_TEST_SIZE
),
1080 This
->mime
, 0, &mime
, 0);
1084 mime_available(This
, mime
, TRUE
);
1085 CoTaskMemFree(mime
);
1089 if(!This
->protocol_sink
)
1092 return IInternetProtocolSink_ReportData(This
->protocol_sink
, bscf
, progress
, progress_max
);
1096 task_header_t header
;
1100 } report_data_task_t
;
1102 static void report_data_proc(BindProtocol
*This
, task_header_t
*t
)
1104 report_data_task_t
*task
= (report_data_task_t
*)t
;
1106 report_data(This
, task
->bscf
, task
->progress
, task
->progress_max
);
1110 static HRESULT WINAPI
BPInternetProtocolSink_ReportData(IInternetProtocolSink
*iface
,
1111 DWORD grfBSCF
, ULONG ulProgress
, ULONG ulProgressMax
)
1113 BindProtocol
*This
= PROTSINK_THIS(iface
);
1115 TRACE("(%p)->(%d %u %u)\n", This
, grfBSCF
, ulProgress
, ulProgressMax
);
1117 if(!This
->protocol_sink
)
1120 if(!do_direct_notif(This
)) {
1121 report_data_task_t
*task
;
1123 task
= heap_alloc(sizeof(report_data_task_t
));
1125 return E_OUTOFMEMORY
;
1127 task
->bscf
= grfBSCF
;
1128 task
->progress
= ulProgress
;
1129 task
->progress_max
= ulProgressMax
;
1131 push_task(This
, &task
->header
, report_data_proc
);
1135 return report_data(This
, grfBSCF
, ulProgress
, ulProgressMax
);
1139 task_header_t header
;
1144 } report_result_task_t
;
1146 static void report_result_proc(BindProtocol
*This
, task_header_t
*t
)
1148 report_result_task_t
*task
= (report_result_task_t
*)t
;
1150 if(This
->protocol_sink
)
1151 IInternetProtocolSink_ReportResult(This
->protocol_sink
, task
->hres
, task
->err
, task
->str
);
1153 heap_free(task
->str
);
1157 static HRESULT WINAPI
BPInternetProtocolSink_ReportResult(IInternetProtocolSink
*iface
,
1158 HRESULT hrResult
, DWORD dwError
, LPCWSTR szResult
)
1160 BindProtocol
*This
= PROTSINK_THIS(iface
);
1162 TRACE("(%p)->(%08x %d %s)\n", This
, hrResult
, dwError
, debugstr_w(szResult
));
1164 if(!This
->protocol_sink
)
1167 This
->reported_result
= TRUE
;
1169 if(!do_direct_notif(This
)) {
1170 report_result_task_t
*task
;
1172 task
= heap_alloc(sizeof(report_result_task_t
));
1174 return E_OUTOFMEMORY
;
1176 task
->hres
= hrResult
;
1177 task
->err
= dwError
;
1178 task
->str
= heap_strdupW(szResult
);
1180 push_task(This
, &task
->header
, report_result_proc
);
1184 return IInternetProtocolSink_ReportResult(This
->protocol_sink
, hrResult
, dwError
, szResult
);
1187 #undef PROTSINK_THIS
1189 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl
= {
1190 BPInternetProtocolSink_QueryInterface
,
1191 BPInternetProtocolSink_AddRef
,
1192 BPInternetProtocolSink_Release
,
1193 BPInternetProtocolSink_Switch
,
1194 BPInternetProtocolSink_ReportProgress
,
1195 BPInternetProtocolSink_ReportData
,
1196 BPInternetProtocolSink_ReportResult
1199 #define INETINFO_THIS(iface) DEFINE_THIS(BindProtocol, IWinInetHttpInfo, iface)
1201 static HRESULT WINAPI
WinInetHttpInfo_QueryInterface(IWinInetHttpInfo
*iface
, REFIID riid
, void **ppv
)
1203 BindProtocol
*This
= INETINFO_THIS(iface
);
1204 return IInternetProtocol_QueryInterface(PROTOCOL(This
), riid
, ppv
);
1207 static ULONG WINAPI
WinInetHttpInfo_AddRef(IWinInetHttpInfo
*iface
)
1209 BindProtocol
*This
= INETINFO_THIS(iface
);
1210 return IInternetProtocol_AddRef(PROTOCOL(This
));
1213 static ULONG WINAPI
WinInetHttpInfo_Release(IWinInetHttpInfo
*iface
)
1215 BindProtocol
*This
= INETINFO_THIS(iface
);
1216 return IInternetProtocol_Release(PROTOCOL(This
));
1219 static HRESULT WINAPI
WinInetHttpInfo_QueryOption(IWinInetHttpInfo
*iface
, DWORD dwOption
,
1220 void *pBuffer
, DWORD
*pcbBuffer
)
1222 BindProtocol
*This
= INETINFO_THIS(iface
);
1223 FIXME("(%p)->(%x %p %p)\n", This
, dwOption
, pBuffer
, pcbBuffer
);
1227 static HRESULT WINAPI
WinInetHttpInfo_QueryInfo(IWinInetHttpInfo
*iface
, DWORD dwOption
,
1228 void *pBuffer
, DWORD
*pcbBuffer
, DWORD
*pdwFlags
, DWORD
*pdwReserved
)
1230 BindProtocol
*This
= INETINFO_THIS(iface
);
1231 FIXME("(%p)->(%x %p %p %p %p)\n", This
, dwOption
, pBuffer
, pcbBuffer
, pdwFlags
, pdwReserved
);
1235 #undef INETINFO_THIS
1237 static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl
= {
1238 WinInetHttpInfo_QueryInterface
,
1239 WinInetHttpInfo_AddRef
,
1240 WinInetHttpInfo_Release
,
1241 WinInetHttpInfo_QueryOption
,
1242 WinInetHttpInfo_QueryInfo
1245 #define SERVPROV_THIS(iface) DEFINE_THIS(BindProtocol, ServiceProvider, iface)
1247 static HRESULT WINAPI
BPServiceProvider_QueryInterface(IServiceProvider
*iface
,
1248 REFIID riid
, void **ppv
)
1250 BindProtocol
*This
= SERVPROV_THIS(iface
);
1251 return IInternetProtocol_QueryInterface(PROTOCOL(This
), riid
, ppv
);
1254 static ULONG WINAPI
BPServiceProvider_AddRef(IServiceProvider
*iface
)
1256 BindProtocol
*This
= SERVPROV_THIS(iface
);
1257 return IInternetProtocol_AddRef(PROTOCOL(This
));
1260 static ULONG WINAPI
BPServiceProvider_Release(IServiceProvider
*iface
)
1262 BindProtocol
*This
= SERVPROV_THIS(iface
);
1263 return IInternetProtocol_Release(PROTOCOL(This
));
1266 static HRESULT WINAPI
BPServiceProvider_QueryService(IServiceProvider
*iface
,
1267 REFGUID guidService
, REFIID riid
, void **ppv
)
1269 BindProtocol
*This
= SERVPROV_THIS(iface
);
1271 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_guid(guidService
), debugstr_guid(riid
), ppv
);
1273 if(!This
->service_provider
)
1274 return E_NOINTERFACE
;
1276 return IServiceProvider_QueryService(This
->service_provider
, guidService
, riid
, ppv
);
1279 #undef SERVPROV_THIS
1281 static const IServiceProviderVtbl ServiceProviderVtbl
= {
1282 BPServiceProvider_QueryInterface
,
1283 BPServiceProvider_AddRef
,
1284 BPServiceProvider_Release
,
1285 BPServiceProvider_QueryService
1288 HRESULT
create_binding_protocol(LPCWSTR url
, BOOL from_urlmon
, IInternetProtocol
**protocol
)
1290 BindProtocol
*ret
= heap_alloc_zero(sizeof(BindProtocol
));
1292 ret
->lpIInternetProtocolVtbl
= &BindProtocolVtbl
;
1293 ret
->lpInternetBindInfoVtbl
= &InternetBindInfoVtbl
;
1294 ret
->lpInternetPriorityVtbl
= &InternetPriorityVtbl
;
1295 ret
->lpServiceProviderVtbl
= &ServiceProviderVtbl
;
1296 ret
->lpIInternetProtocolSinkVtbl
= &InternetProtocolSinkVtbl
;
1297 ret
->lpIInternetProtocolHandlerVtbl
= &InternetProtocolHandlerVtbl
;
1298 ret
->lpIWinInetHttpInfoVtbl
= &WinInetHttpInfoVtbl
;
1301 ret
->from_urlmon
= from_urlmon
;
1302 ret
->apartment_thread
= GetCurrentThreadId();
1303 ret
->notif_hwnd
= get_notif_hwnd();
1304 ret
->protocol_handler
= PROTOCOLHANDLER(ret
);
1305 InitializeCriticalSection(&ret
->section
);
1307 URLMON_LockModule();
1309 *protocol
= PROTOCOL(ret
);