2 * Copyright 2007 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
*lpInternetProtocolVtbl
;
37 const IInternetBindInfoVtbl
*lpInternetBindInfoVtbl
;
38 const IInternetPriorityVtbl
*lpInternetPriorityVtbl
;
39 const IServiceProviderVtbl
*lpServiceProviderVtbl
;
40 const IInternetProtocolSinkVtbl
*lpInternetProtocolSinkVtbl
;
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
;
73 #define PROTOCOL(x) ((IInternetProtocol*) &(x)->lpInternetProtocolVtbl)
74 #define BINDINFO(x) ((IInternetBindInfo*) &(x)->lpInternetBindInfoVtbl)
75 #define PRIORITY(x) ((IInternetPriority*) &(x)->lpInternetPriorityVtbl)
76 #define SERVPROV(x) ((IServiceProvider*) &(x)->lpServiceProviderVtbl)
77 #define PROTSINK(x) ((IInternetProtocolSink*) &(x)->lpInternetProtocolSinkVtbl)
79 #define PROTOCOLHANDLER(x) ((IInternetProtocol*) &(x)->lpIInternetProtocolHandlerVtbl)
81 #define BUFFER_SIZE 2048
82 #define MIME_TEST_SIZE 255
84 #define WM_MK_CONTINUE (WM_USER+101)
85 #define WM_MK_RELEASE (WM_USER+102)
87 static LRESULT WINAPI
notif_wnd_proc(HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
90 case WM_MK_CONTINUE
: {
91 BindProtocol
*This
= (BindProtocol
*)lParam
;
95 EnterCriticalSection(&This
->section
);
97 task
= This
->task_queue_head
;
99 This
->task_queue_head
= task
->next
;
100 if(!This
->task_queue_head
)
101 This
->task_queue_tail
= NULL
;
104 LeaveCriticalSection(&This
->section
);
109 This
->continue_call
++;
110 task
->proc(This
, task
);
111 This
->continue_call
--;
114 IInternetProtocol_Release(PROTOCOL(This
));
117 case WM_MK_RELEASE
: {
118 tls_data_t
*data
= get_tls_data();
120 if(!--data
->notif_hwnd_cnt
) {
122 data
->notif_hwnd
= NULL
;
127 return DefWindowProcW(hwnd
, msg
, wParam
, lParam
);
130 HWND
get_notif_hwnd(void)
132 static ATOM wnd_class
= 0;
133 tls_data_t
*tls_data
;
135 static const WCHAR wszURLMonikerNotificationWindow
[] =
136 {'U','R','L',' ','M','o','n','i','k','e','r',' ',
137 'N','o','t','i','f','i','c','a','t','i','o','n',' ','W','i','n','d','o','w',0};
139 tls_data
= get_tls_data();
143 if(tls_data
->notif_hwnd_cnt
) {
144 tls_data
->notif_hwnd_cnt
++;
145 return tls_data
->notif_hwnd
;
149 static WNDCLASSEXW wndclass
= {
151 notif_wnd_proc
, 0, 0,
152 NULL
, NULL
, NULL
, NULL
, NULL
,
153 wszURLMonikerNotificationWindow
,
157 wndclass
.hInstance
= URLMON_hInstance
;
159 wnd_class
= RegisterClassExW(&wndclass
);
160 if (!wnd_class
&& GetLastError() == ERROR_CLASS_ALREADY_EXISTS
)
164 tls_data
->notif_hwnd
= CreateWindowExW(0, wszURLMonikerNotificationWindow
,
165 wszURLMonikerNotificationWindow
, 0, 0, 0, 0, 0, HWND_MESSAGE
,
166 NULL
, URLMON_hInstance
, NULL
);
167 if(tls_data
->notif_hwnd
)
168 tls_data
->notif_hwnd_cnt
++;
170 TRACE("hwnd = %p\n", tls_data
->notif_hwnd
);
172 return tls_data
->notif_hwnd
;
175 void release_notif_hwnd(HWND hwnd
)
177 tls_data_t
*data
= get_tls_data();
182 if(data
->notif_hwnd
!= hwnd
) {
183 PostMessageW(data
->notif_hwnd
, WM_MK_RELEASE
, 0, 0);
187 if(!--data
->notif_hwnd_cnt
) {
188 DestroyWindow(data
->notif_hwnd
);
189 data
->notif_hwnd
= NULL
;
193 static void push_task(BindProtocol
*This
, task_header_t
*task
, task_proc_t proc
)
195 BOOL do_post
= FALSE
;
200 EnterCriticalSection(&This
->section
);
202 if(This
->task_queue_tail
) {
203 This
->task_queue_tail
->next
= task
;
204 This
->task_queue_tail
= task
;
206 This
->task_queue_tail
= This
->task_queue_head
= task
;
210 LeaveCriticalSection(&This
->section
);
213 IInternetProtocol_AddRef(PROTOCOL(This
));
214 PostMessageW(This
->notif_hwnd
, WM_MK_CONTINUE
, 0, (LPARAM
)This
);
218 static BOOL
inline do_direct_notif(BindProtocol
*This
)
220 return !(This
->pi
& PI_APARTMENTTHREADED
) || (This
->apartment_thread
== GetCurrentThreadId() && !This
->continue_call
);
223 #define PROTOCOL_THIS(iface) DEFINE_THIS(BindProtocol, InternetProtocol, iface)
225 static HRESULT WINAPI
BindProtocol_QueryInterface(IInternetProtocol
*iface
, REFIID riid
, void **ppv
)
227 BindProtocol
*This
= PROTOCOL_THIS(iface
);
230 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
231 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
232 *ppv
= PROTOCOL(This
);
233 }else if(IsEqualGUID(&IID_IInternetProtocolRoot
, riid
)) {
234 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This
, ppv
);
235 *ppv
= PROTOCOL(This
);
236 }else if(IsEqualGUID(&IID_IInternetProtocol
, riid
)) {
237 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This
, ppv
);
238 *ppv
= PROTOCOL(This
);
239 }else if(IsEqualGUID(&IID_IInternetBindInfo
, riid
)) {
240 TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This
, ppv
);
241 *ppv
= BINDINFO(This
);
242 }else if(IsEqualGUID(&IID_IInternetPriority
, riid
)) {
243 TRACE("(%p)->(IID_IInternetPriority %p)\n", This
, ppv
);
244 *ppv
= PRIORITY(This
);
245 }else if(IsEqualGUID(&IID_IAuthenticate
, riid
)) {
246 FIXME("(%p)->(IID_IAuthenticate %p)\n", This
, ppv
);
247 }else if(IsEqualGUID(&IID_IServiceProvider
, riid
)) {
248 TRACE("(%p)->(IID_IServiceProvider %p)\n", This
, ppv
);
249 *ppv
= SERVPROV(This
);
250 }else if(IsEqualGUID(&IID_IInternetProtocolSink
, riid
)) {
251 TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This
, ppv
);
252 *ppv
= PROTSINK(This
);
256 IInternetProtocol_AddRef(iface
);
260 WARN("not supported interface %s\n", debugstr_guid(riid
));
261 return E_NOINTERFACE
;
264 static ULONG WINAPI
BindProtocol_AddRef(IInternetProtocol
*iface
)
266 BindProtocol
*This
= PROTOCOL_THIS(iface
);
267 LONG ref
= InterlockedIncrement(&This
->ref
);
268 TRACE("(%p) ref=%d\n", This
, ref
);
272 static ULONG WINAPI
BindProtocol_Release(IInternetProtocol
*iface
)
274 BindProtocol
*This
= PROTOCOL_THIS(iface
);
275 LONG ref
= InterlockedDecrement(&This
->ref
);
277 TRACE("(%p) ref=%d\n", This
, ref
);
280 if(This
->wininet_info
)
281 IWinInetInfo_Release(This
->wininet_info
);
283 IInternetProtocol_Release(This
->protocol
);
285 IInternetBindInfo_Release(This
->bind_info
);
286 if(This
->protocol_handler
&& This
->protocol_handler
!= PROTOCOLHANDLER(This
))
287 IInternetProtocol_Release(This
->protocol_handler
);
289 set_binding_sink(PROTOCOL(This
), NULL
);
292 release_notif_hwnd(This
->notif_hwnd
);
293 DeleteCriticalSection(&This
->section
);
295 heap_free(This
->mime
);
296 heap_free(This
->url
);
299 URLMON_UnlockModule();
305 static HRESULT WINAPI
BindProtocol_Start(IInternetProtocol
*iface
, LPCWSTR szUrl
,
306 IInternetProtocolSink
*pOIProtSink
, IInternetBindInfo
*pOIBindInfo
,
307 DWORD grfPI
, HANDLE_PTR dwReserved
)
309 BindProtocol
*This
= PROTOCOL_THIS(iface
);
311 TRACE("(%p)->(%s %p %p %08x %lx)\n", This
, debugstr_w(szUrl
), pOIProtSink
,
312 pOIBindInfo
, grfPI
, dwReserved
);
314 return IInternetProtocol_Start(This
->protocol_handler
, szUrl
, pOIProtSink
, pOIBindInfo
, grfPI
, dwReserved
);
317 static HRESULT WINAPI
BindProtocol_Continue(IInternetProtocol
*iface
, PROTOCOLDATA
*pProtocolData
)
319 BindProtocol
*This
= PROTOCOL_THIS(iface
);
321 TRACE("(%p)->(%p)\n", This
, pProtocolData
);
323 return IInternetProtocol_Continue(This
->protocol_handler
, pProtocolData
);
326 static HRESULT WINAPI
BindProtocol_Abort(IInternetProtocol
*iface
, HRESULT hrReason
,
329 BindProtocol
*This
= PROTOCOL_THIS(iface
);
330 FIXME("(%p)->(%08x %08x)\n", This
, hrReason
, dwOptions
);
334 static HRESULT WINAPI
BindProtocol_Terminate(IInternetProtocol
*iface
, DWORD dwOptions
)
336 BindProtocol
*This
= PROTOCOL_THIS(iface
);
338 TRACE("(%p)->(%08x)\n", This
, dwOptions
);
340 return IInternetProtocol_Terminate(This
->protocol_handler
, dwOptions
);
343 static HRESULT WINAPI
BindProtocol_Suspend(IInternetProtocol
*iface
)
345 BindProtocol
*This
= PROTOCOL_THIS(iface
);
346 FIXME("(%p)\n", This
);
350 static HRESULT WINAPI
BindProtocol_Resume(IInternetProtocol
*iface
)
352 BindProtocol
*This
= PROTOCOL_THIS(iface
);
353 FIXME("(%p)\n", This
);
357 static HRESULT WINAPI
BindProtocol_Read(IInternetProtocol
*iface
, void *pv
,
358 ULONG cb
, ULONG
*pcbRead
)
360 BindProtocol
*This
= PROTOCOL_THIS(iface
);
362 TRACE("(%p)->(%p %u %p)\n", This
, pv
, cb
, pcbRead
);
366 return IInternetProtocol_Read(This
->protocol_handler
, pv
, cb
, pcbRead
);
369 static HRESULT WINAPI
BindProtocol_Seek(IInternetProtocol
*iface
, LARGE_INTEGER dlibMove
,
370 DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
372 BindProtocol
*This
= PROTOCOL_THIS(iface
);
373 FIXME("(%p)->(%d %d %p)\n", This
, dlibMove
.u
.LowPart
, dwOrigin
, plibNewPosition
);
377 static HRESULT WINAPI
BindProtocol_LockRequest(IInternetProtocol
*iface
, DWORD dwOptions
)
379 BindProtocol
*This
= PROTOCOL_THIS(iface
);
381 TRACE("(%p)->(%08x)\n", This
, dwOptions
);
383 return IInternetProtocol_LockRequest(This
->protocol_handler
, dwOptions
);
386 static HRESULT WINAPI
BindProtocol_UnlockRequest(IInternetProtocol
*iface
)
388 BindProtocol
*This
= PROTOCOL_THIS(iface
);
390 TRACE("(%p)\n", This
);
392 return IInternetProtocol_UnlockRequest(This
->protocol_handler
);
395 void set_binding_sink(IInternetProtocol
*bind_protocol
, IInternetProtocolSink
*sink
)
397 BindProtocol
*This
= PROTOCOL_THIS(bind_protocol
);
398 IInternetProtocolSink
*prev_sink
;
399 IServiceProvider
*service_provider
= NULL
;
402 IInternetProtocolSink_AddRef(sink
);
403 prev_sink
= InterlockedExchangePointer((void**)&This
->protocol_sink
, sink
);
405 IInternetProtocolSink_Release(prev_sink
);
408 IInternetProtocolSink_QueryInterface(sink
, &IID_IServiceProvider
, (void**)&service_provider
);
409 service_provider
= InterlockedExchangePointer((void**)&This
->service_provider
, service_provider
);
411 IServiceProvider_Release(service_provider
);
414 IWinInetInfo
*get_wininet_info(IInternetProtocol
*bind_protocol
)
416 BindProtocol
*This
= PROTOCOL_THIS(bind_protocol
);
418 return This
->wininet_info
;
423 static const IInternetProtocolVtbl BindProtocolVtbl
= {
424 BindProtocol_QueryInterface
,
426 BindProtocol_Release
,
428 BindProtocol_Continue
,
430 BindProtocol_Terminate
,
431 BindProtocol_Suspend
,
435 BindProtocol_LockRequest
,
436 BindProtocol_UnlockRequest
439 #define PROTOCOLHANDLER_THIS(iface) DEFINE_THIS(BindProtocol, IInternetProtocolHandler, iface)
441 static HRESULT WINAPI
ProtocolHandler_QueryInterface(IInternetProtocol
*iface
, REFIID riid
, void **ppv
)
443 ERR("should not be called\n");
444 return E_NOINTERFACE
;
447 static ULONG WINAPI
ProtocolHandler_AddRef(IInternetProtocol
*iface
)
449 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
450 return IInternetProtocol_AddRef(PROTOCOL(This
));
453 static ULONG WINAPI
ProtocolHandler_Release(IInternetProtocol
*iface
)
455 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
456 return IInternetProtocol_Release(PROTOCOL(This
));
459 static HRESULT WINAPI
ProtocolHandler_Start(IInternetProtocol
*iface
, LPCWSTR szUrl
,
460 IInternetProtocolSink
*pOIProtSink
, IInternetBindInfo
*pOIBindInfo
,
461 DWORD grfPI
, HANDLE_PTR dwReserved
)
463 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
464 IInternetProtocol
*protocol
= NULL
;
465 IInternetPriority
*priority
;
466 IServiceProvider
*service_provider
;
467 BOOL urlmon_protocol
= FALSE
;
468 CLSID clsid
= IID_NULL
;
472 TRACE("(%p)->(%s %p %p %08x %lx)\n", This
, debugstr_w(szUrl
), pOIProtSink
,
473 pOIBindInfo
, grfPI
, dwReserved
);
475 if(!szUrl
|| !pOIProtSink
|| !pOIBindInfo
)
479 This
->url
= heap_strdupW(szUrl
);
481 hres
= IInternetProtocolSink_QueryInterface(pOIProtSink
, &IID_IServiceProvider
,
482 (void**)&service_provider
);
483 if(SUCCEEDED(hres
)) {
484 /* FIXME: What's protocol CLSID here? */
485 IServiceProvider_QueryService(service_provider
, &IID_IInternetProtocol
,
486 &IID_IInternetProtocol
, (void**)&protocol
);
487 IServiceProvider_Release(service_provider
);
494 hres
= get_protocol_handler(szUrl
, &clsid
, &urlmon_protocol
, &cf
);
498 if(This
->from_urlmon
) {
499 hres
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IInternetProtocol
, (void**)&protocol
);
500 IClassFactory_Release(cf
);
504 hres
= IClassFactory_CreateInstance(cf
, (IUnknown
*)BINDINFO(This
),
505 &IID_IUnknown
, (void**)&unk
);
506 IClassFactory_Release(cf
);
510 hres
= IUnknown_QueryInterface(unk
, &IID_IInternetProtocol
, (void**)&protocol
);
511 IUnknown_Release(unk
);
517 StringFromCLSID(&clsid
, &clsid_str
);
518 IInternetProtocolSink_ReportProgress(pOIProtSink
, BINDSTATUS_PROTOCOLCLASSID
, clsid_str
);
519 CoTaskMemFree(clsid_str
);
521 This
->protocol
= protocol
;
524 IInternetProtocol_QueryInterface(protocol
, &IID_IWinInetInfo
, (void**)&This
->wininet_info
);
526 IInternetBindInfo_AddRef(pOIBindInfo
);
527 This
->bind_info
= pOIBindInfo
;
529 set_binding_sink(PROTOCOL(This
), pOIProtSink
);
531 hres
= IInternetProtocol_QueryInterface(protocol
, &IID_IInternetPriority
, (void**)&priority
);
532 if(SUCCEEDED(hres
)) {
533 IInternetPriority_SetPriority(priority
, This
->priority
);
534 IInternetPriority_Release(priority
);
537 return IInternetProtocol_Start(protocol
, szUrl
, PROTSINK(This
), BINDINFO(This
), 0, 0);
540 static HRESULT WINAPI
ProtocolHandler_Continue(IInternetProtocol
*iface
, PROTOCOLDATA
*pProtocolData
)
542 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
544 TRACE("(%p)->(%p)\n", This
, pProtocolData
);
546 return IInternetProtocol_Continue(This
->protocol
, pProtocolData
);
549 static HRESULT WINAPI
ProtocolHandler_Abort(IInternetProtocol
*iface
, HRESULT hrReason
,
552 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
553 FIXME("(%p)->(%08x %08x)\n", This
, hrReason
, dwOptions
);
557 static HRESULT WINAPI
ProtocolHandler_Terminate(IInternetProtocol
*iface
, DWORD dwOptions
)
559 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
561 TRACE("(%p)->(%08x)\n", This
, dwOptions
);
563 if(!This
->reported_result
)
566 IInternetProtocol_Terminate(This
->protocol
, 0);
568 set_binding_sink(PROTOCOL(This
), NULL
);
570 if(This
->bind_info
) {
571 IInternetBindInfo_Release(This
->bind_info
);
572 This
->bind_info
= NULL
;
578 static HRESULT WINAPI
ProtocolHandler_Suspend(IInternetProtocol
*iface
)
580 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
581 FIXME("(%p)\n", This
);
585 static HRESULT WINAPI
ProtocolHandler_Resume(IInternetProtocol
*iface
)
587 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
588 FIXME("(%p)\n", This
);
592 static HRESULT WINAPI
ProtocolHandler_Read(IInternetProtocol
*iface
, void *pv
,
593 ULONG cb
, ULONG
*pcbRead
)
595 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
599 TRACE("(%p)->(%p %u %p)\n", This
, pv
, cb
, pcbRead
);
602 read
= min(cb
, This
->buf_size
);
603 memcpy(pv
, This
->buf
, read
);
605 if(read
== This
->buf_size
) {
606 heap_free(This
->buf
);
609 memmove(This
->buf
, This
->buf
+cb
, This
->buf_size
-cb
);
612 This
->buf_size
-= read
;
618 hres
= IInternetProtocol_Read(This
->protocol
, (BYTE
*)pv
+read
, cb
-read
, &cread
);
626 static HRESULT WINAPI
ProtocolHandler_Seek(IInternetProtocol
*iface
, LARGE_INTEGER dlibMove
,
627 DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
629 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
630 FIXME("(%p)->(%d %d %p)\n", This
, dlibMove
.u
.LowPart
, dwOrigin
, plibNewPosition
);
634 static HRESULT WINAPI
ProtocolHandler_LockRequest(IInternetProtocol
*iface
, DWORD dwOptions
)
636 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
638 TRACE("(%p)->(%08x)\n", This
, dwOptions
);
640 return IInternetProtocol_LockRequest(This
->protocol
, dwOptions
);
643 static HRESULT WINAPI
ProtocolHandler_UnlockRequest(IInternetProtocol
*iface
)
645 BindProtocol
*This
= PROTOCOLHANDLER_THIS(iface
);
647 TRACE("(%p)\n", This
);
649 return IInternetProtocol_UnlockRequest(This
->protocol
);
654 static const IInternetProtocolVtbl InternetProtocolHandlerVtbl
= {
655 ProtocolHandler_QueryInterface
,
656 ProtocolHandler_AddRef
,
657 ProtocolHandler_Release
,
658 ProtocolHandler_Start
,
659 ProtocolHandler_Continue
,
660 ProtocolHandler_Abort
,
661 ProtocolHandler_Terminate
,
662 ProtocolHandler_Suspend
,
663 ProtocolHandler_Resume
,
664 ProtocolHandler_Read
,
665 ProtocolHandler_Seek
,
666 ProtocolHandler_LockRequest
,
667 ProtocolHandler_UnlockRequest
670 #define BINDINFO_THIS(iface) DEFINE_THIS(BindProtocol, InternetBindInfo, iface)
672 static HRESULT WINAPI
BindInfo_QueryInterface(IInternetBindInfo
*iface
,
673 REFIID riid
, void **ppv
)
675 BindProtocol
*This
= BINDINFO_THIS(iface
);
676 return IInternetProtocol_QueryInterface(PROTOCOL(This
), riid
, ppv
);
679 static ULONG WINAPI
BindInfo_AddRef(IInternetBindInfo
*iface
)
681 BindProtocol
*This
= BINDINFO_THIS(iface
);
682 return IBinding_AddRef(PROTOCOL(This
));
685 static ULONG WINAPI
BindInfo_Release(IInternetBindInfo
*iface
)
687 BindProtocol
*This
= BINDINFO_THIS(iface
);
688 return IBinding_Release(PROTOCOL(This
));
691 static HRESULT WINAPI
BindInfo_GetBindInfo(IInternetBindInfo
*iface
,
692 DWORD
*grfBINDF
, BINDINFO
*pbindinfo
)
694 BindProtocol
*This
= BINDINFO_THIS(iface
);
697 TRACE("(%p)->(%p %p)\n", This
, grfBINDF
, pbindinfo
);
699 hres
= IInternetBindInfo_GetBindInfo(This
->bind_info
, grfBINDF
, pbindinfo
);
701 WARN("GetBindInfo failed: %08x\n", hres
);
705 *grfBINDF
|= BINDF_FROMURLMON
;
709 static HRESULT WINAPI
BindInfo_GetBindString(IInternetBindInfo
*iface
,
710 ULONG ulStringType
, LPOLESTR
*ppwzStr
, ULONG cEl
, ULONG
*pcElFetched
)
712 BindProtocol
*This
= BINDINFO_THIS(iface
);
714 TRACE("(%p)->(%d %p %d %p)\n", This
, ulStringType
, ppwzStr
, cEl
, pcElFetched
);
716 return IInternetBindInfo_GetBindString(This
->bind_info
, ulStringType
, ppwzStr
, cEl
, pcElFetched
);
721 static const IInternetBindInfoVtbl InternetBindInfoVtbl
= {
722 BindInfo_QueryInterface
,
725 BindInfo_GetBindInfo
,
726 BindInfo_GetBindString
729 #define PRIORITY_THIS(iface) DEFINE_THIS(BindProtocol, InternetPriority, iface)
731 static HRESULT WINAPI
InternetPriority_QueryInterface(IInternetPriority
*iface
,
732 REFIID riid
, void **ppv
)
734 BindProtocol
*This
= PRIORITY_THIS(iface
);
735 return IInternetProtocol_QueryInterface(PROTOCOL(This
), riid
, ppv
);
738 static ULONG WINAPI
InternetPriority_AddRef(IInternetPriority
*iface
)
740 BindProtocol
*This
= PRIORITY_THIS(iface
);
741 return IInternetProtocol_AddRef(PROTOCOL(This
));
744 static ULONG WINAPI
InternetPriority_Release(IInternetPriority
*iface
)
746 BindProtocol
*This
= PRIORITY_THIS(iface
);
747 return IInternetProtocol_Release(PROTOCOL(This
));
750 static HRESULT WINAPI
InternetPriority_SetPriority(IInternetPriority
*iface
, LONG nPriority
)
752 BindProtocol
*This
= PRIORITY_THIS(iface
);
754 TRACE("(%p)->(%d)\n", This
, nPriority
);
756 This
->priority
= nPriority
;
760 static HRESULT WINAPI
InternetPriority_GetPriority(IInternetPriority
*iface
, LONG
*pnPriority
)
762 BindProtocol
*This
= PRIORITY_THIS(iface
);
764 TRACE("(%p)->(%p)\n", This
, pnPriority
);
766 *pnPriority
= This
->priority
;
772 static const IInternetPriorityVtbl InternetPriorityVtbl
= {
773 InternetPriority_QueryInterface
,
774 InternetPriority_AddRef
,
775 InternetPriority_Release
,
776 InternetPriority_SetPriority
,
777 InternetPriority_GetPriority
781 #define PROTSINK_THIS(iface) DEFINE_THIS(BindProtocol, InternetProtocolSink, iface)
783 static HRESULT WINAPI
BPInternetProtocolSink_QueryInterface(IInternetProtocolSink
*iface
,
784 REFIID riid
, void **ppv
)
786 BindProtocol
*This
= PROTSINK_THIS(iface
);
787 return IInternetProtocol_QueryInterface(PROTOCOL(This
), riid
, ppv
);
790 static ULONG WINAPI
BPInternetProtocolSink_AddRef(IInternetProtocolSink
*iface
)
792 BindProtocol
*This
= PROTSINK_THIS(iface
);
793 return IInternetProtocol_AddRef(PROTOCOL(This
));
796 static ULONG WINAPI
BPInternetProtocolSink_Release(IInternetProtocolSink
*iface
)
798 BindProtocol
*This
= PROTSINK_THIS(iface
);
799 return IInternetProtocol_Release(PROTOCOL(This
));
803 task_header_t header
;
807 static void switch_proc(BindProtocol
*bind
, task_header_t
*t
)
809 switch_task_t
*task
= (switch_task_t
*)t
;
811 IInternetProtocol_Continue(bind
->protocol
, &task
->data
);
816 static HRESULT WINAPI
BPInternetProtocolSink_Switch(IInternetProtocolSink
*iface
,
817 PROTOCOLDATA
*pProtocolData
)
819 BindProtocol
*This
= PROTSINK_THIS(iface
);
821 TRACE("(%p)->(%p)\n", This
, pProtocolData
);
823 TRACE("flags %x state %x data %p cb %u\n", pProtocolData
->grfFlags
, pProtocolData
->dwState
,
824 pProtocolData
->pData
, pProtocolData
->cbData
);
826 if(!do_direct_notif(This
)) {
829 task
= heap_alloc(sizeof(switch_task_t
));
831 return E_OUTOFMEMORY
;
833 task
->data
= *pProtocolData
;
835 push_task(This
, &task
->header
, switch_proc
);
839 if(!This
->protocol_sink
) {
840 IInternetProtocol_Continue(This
->protocol
, pProtocolData
);
844 return IInternetProtocolSink_Switch(This
->protocol_sink
, pProtocolData
);
847 static void report_progress(BindProtocol
*This
, ULONG status_code
, LPCWSTR status_text
)
849 switch(status_code
) {
850 case BINDSTATUS_FINDINGRESOURCE
:
851 case BINDSTATUS_CONNECTING
:
852 case BINDSTATUS_BEGINDOWNLOADDATA
:
853 case BINDSTATUS_SENDINGREQUEST
:
854 case BINDSTATUS_CACHEFILENAMEAVAILABLE
:
855 case BINDSTATUS_DIRECTBIND
:
856 case BINDSTATUS_ACCEPTRANGES
:
857 if(This
->protocol_sink
)
858 IInternetProtocolSink_ReportProgress(This
->protocol_sink
, status_code
, status_text
);
861 case BINDSTATUS_MIMETYPEAVAILABLE
:
862 if(!This
->reported_mime
) {
863 heap_free(This
->mime
);
864 This
->mime
= heap_strdupW(status_text
);
867 if(This
->protocol_sink
&& !(This
->pi
& PI_MIMEVERIFICATION
))
868 IInternetProtocolSink_ReportProgress(This
->protocol_sink
, status_code
, status_text
);
871 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE
:
872 if(!This
->reported_mime
) {
873 heap_free(This
->mime
);
874 This
->mime
= heap_strdupW(status_text
);
877 if(This
->protocol_sink
) {
878 This
->reported_mime
= TRUE
;
879 IInternetProtocolSink_ReportProgress(This
->protocol_sink
, BINDSTATUS_MIMETYPEAVAILABLE
, status_text
);
884 FIXME("unsupported ulStatusCode %u\n", status_code
);
889 task_header_t header
;
893 } on_progress_task_t
;
895 static void on_progress_proc(BindProtocol
*This
, task_header_t
*t
)
897 on_progress_task_t
*task
= (on_progress_task_t
*)t
;
899 report_progress(This
, task
->status_code
, task
->status_text
);
901 heap_free(task
->status_text
);
905 static HRESULT WINAPI
BPInternetProtocolSink_ReportProgress(IInternetProtocolSink
*iface
,
906 ULONG ulStatusCode
, LPCWSTR szStatusText
)
908 BindProtocol
*This
= PROTSINK_THIS(iface
);
910 TRACE("(%p)->(%u %s)\n", This
, ulStatusCode
, debugstr_w(szStatusText
));
912 if(do_direct_notif(This
)) {
913 report_progress(This
, ulStatusCode
, szStatusText
);
915 on_progress_task_t
*task
;
917 task
= heap_alloc(sizeof(on_progress_task_t
));
919 task
->status_code
= ulStatusCode
;
920 task
->status_text
= heap_strdupW(szStatusText
);
922 push_task(This
, &task
->header
, on_progress_proc
);
928 static HRESULT
report_data(BindProtocol
*This
, DWORD bscf
, ULONG progress
, ULONG progress_max
)
930 if(!This
->protocol_sink
)
933 if((This
->pi
& PI_MIMEVERIFICATION
) && !This
->reported_mime
) {
939 This
->buf
= heap_alloc(BUFFER_SIZE
);
941 return E_OUTOFMEMORY
;
946 hres
= IInternetProtocol_Read(This
->protocol
, This
->buf
+This
->buf_size
, BUFFER_SIZE
-This
->buf_size
, &read
);
949 This
->buf_size
+= read
;
950 }while(This
->buf_size
< MIME_TEST_SIZE
);
951 if(FAILED(hres
) && hres
!= E_PENDING
)
954 This
->buf_size
+= read
;
955 if(This
->buf_size
< MIME_TEST_SIZE
&& hres
!= S_FALSE
)
959 hres
= FindMimeFromData(NULL
, This
->url
, This
->buf
, min(This
->buf_size
, MIME_TEST_SIZE
), This
->mime
, 0, &mime
, 0);
963 heap_free(This
->mime
);
964 This
->mime
= heap_strdupW(mime
);
967 This
->reported_mime
= TRUE
;
968 IInternetProtocolSink_ReportProgress(This
->protocol_sink
, BINDSTATUS_MIMETYPEAVAILABLE
, This
->mime
);
971 return IInternetProtocolSink_ReportData(This
->protocol_sink
, bscf
, progress
, progress_max
);
975 task_header_t header
;
979 } report_data_task_t
;
981 static void report_data_proc(BindProtocol
*This
, task_header_t
*t
)
983 report_data_task_t
*task
= (report_data_task_t
*)t
;
985 report_data(This
, task
->bscf
, task
->progress
, task
->progress_max
);
989 static HRESULT WINAPI
BPInternetProtocolSink_ReportData(IInternetProtocolSink
*iface
,
990 DWORD grfBSCF
, ULONG ulProgress
, ULONG ulProgressMax
)
992 BindProtocol
*This
= PROTSINK_THIS(iface
);
994 TRACE("(%p)->(%d %u %u)\n", This
, grfBSCF
, ulProgress
, ulProgressMax
);
996 if(!This
->protocol_sink
)
999 if(!do_direct_notif(This
)) {
1000 report_data_task_t
*task
;
1002 task
= heap_alloc(sizeof(report_data_task_t
));
1004 return E_OUTOFMEMORY
;
1006 task
->bscf
= grfBSCF
;
1007 task
->progress
= ulProgress
;
1008 task
->progress_max
= ulProgressMax
;
1010 push_task(This
, &task
->header
, report_data_proc
);
1014 return report_data(This
, grfBSCF
, ulProgress
, ulProgressMax
);
1018 task_header_t header
;
1023 } report_result_task_t
;
1025 static void report_result_proc(BindProtocol
*This
, task_header_t
*t
)
1027 report_result_task_t
*task
= (report_result_task_t
*)t
;
1029 if(This
->protocol_sink
)
1030 IInternetProtocolSink_ReportResult(This
->protocol_sink
, task
->hres
, task
->err
, task
->str
);
1032 heap_free(task
->str
);
1036 static HRESULT WINAPI
BPInternetProtocolSink_ReportResult(IInternetProtocolSink
*iface
,
1037 HRESULT hrResult
, DWORD dwError
, LPCWSTR szResult
)
1039 BindProtocol
*This
= PROTSINK_THIS(iface
);
1041 TRACE("(%p)->(%08x %d %s)\n", This
, hrResult
, dwError
, debugstr_w(szResult
));
1043 if(!This
->protocol_sink
)
1046 This
->reported_result
= TRUE
;
1048 if(!do_direct_notif(This
)) {
1049 report_result_task_t
*task
;
1051 task
= heap_alloc(sizeof(report_result_task_t
));
1053 return E_OUTOFMEMORY
;
1055 task
->hres
= hrResult
;
1056 task
->err
= dwError
;
1057 task
->str
= heap_strdupW(szResult
);
1059 push_task(This
, &task
->header
, report_result_proc
);
1063 return IInternetProtocolSink_ReportResult(This
->protocol_sink
, hrResult
, dwError
, szResult
);
1066 #undef PROTSINK_THIS
1068 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl
= {
1069 BPInternetProtocolSink_QueryInterface
,
1070 BPInternetProtocolSink_AddRef
,
1071 BPInternetProtocolSink_Release
,
1072 BPInternetProtocolSink_Switch
,
1073 BPInternetProtocolSink_ReportProgress
,
1074 BPInternetProtocolSink_ReportData
,
1075 BPInternetProtocolSink_ReportResult
1078 #define SERVPROV_THIS(iface) DEFINE_THIS(BindProtocol, ServiceProvider, iface)
1080 static HRESULT WINAPI
BPServiceProvider_QueryInterface(IServiceProvider
*iface
,
1081 REFIID riid
, void **ppv
)
1083 BindProtocol
*This
= SERVPROV_THIS(iface
);
1084 return IInternetProtocol_QueryInterface(PROTOCOL(This
), riid
, ppv
);
1087 static ULONG WINAPI
BPServiceProvider_AddRef(IServiceProvider
*iface
)
1089 BindProtocol
*This
= SERVPROV_THIS(iface
);
1090 return IInternetProtocol_AddRef(PROTOCOL(This
));
1093 static ULONG WINAPI
BPServiceProvider_Release(IServiceProvider
*iface
)
1095 BindProtocol
*This
= SERVPROV_THIS(iface
);
1096 return IInternetProtocol_Release(PROTOCOL(This
));
1099 static HRESULT WINAPI
BPServiceProvider_QueryService(IServiceProvider
*iface
,
1100 REFGUID guidService
, REFIID riid
, void **ppv
)
1102 BindProtocol
*This
= SERVPROV_THIS(iface
);
1104 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_guid(guidService
), debugstr_guid(riid
), ppv
);
1106 if(!This
->service_provider
)
1107 return E_NOINTERFACE
;
1109 return IServiceProvider_QueryService(This
->service_provider
, guidService
, riid
, ppv
);
1112 #undef SERVPROV_THIS
1114 static const IServiceProviderVtbl ServiceProviderVtbl
= {
1115 BPServiceProvider_QueryInterface
,
1116 BPServiceProvider_AddRef
,
1117 BPServiceProvider_Release
,
1118 BPServiceProvider_QueryService
1121 HRESULT
create_binding_protocol(LPCWSTR url
, BOOL from_urlmon
, IInternetProtocol
**protocol
)
1123 BindProtocol
*ret
= heap_alloc_zero(sizeof(BindProtocol
));
1125 ret
->lpInternetProtocolVtbl
= &BindProtocolVtbl
;
1126 ret
->lpInternetBindInfoVtbl
= &InternetBindInfoVtbl
;
1127 ret
->lpInternetPriorityVtbl
= &InternetPriorityVtbl
;
1128 ret
->lpServiceProviderVtbl
= &ServiceProviderVtbl
;
1129 ret
->lpInternetProtocolSinkVtbl
= &InternetProtocolSinkVtbl
;
1130 ret
->lpIInternetProtocolHandlerVtbl
= &InternetProtocolHandlerVtbl
;
1133 ret
->from_urlmon
= from_urlmon
;
1134 ret
->apartment_thread
= GetCurrentThreadId();
1135 ret
->notif_hwnd
= get_notif_hwnd();
1136 ret
->protocol_handler
= PROTOCOLHANDLER(ret
);
1137 InitializeCriticalSection(&ret
->section
);
1139 URLMON_LockModule();
1141 *protocol
= PROTOCOL(ret
);