2 * Copyright 2005 Jacek Caban
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
22 #define NONAMELESSUNION
23 #define NONAMELESSSTRUCT
30 #include "urlmon_main.h"
32 #include "wine/debug.h"
33 #include "wine/unicode.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(urlmon
);
37 typedef struct ProtocolStream ProtocolStream
;
40 const IBindingVtbl
*lpBindingVtbl
;
41 const IInternetProtocolSinkVtbl
*lpInternetProtocolSinkVtbl
;
42 const IInternetBindInfoVtbl
*lpInternetBindInfoVtbl
;
43 const IServiceProviderVtbl
*lpServiceProviderVtbl
;
47 IBindStatusCallback
*callback
;
48 IInternetProtocol
*protocol
;
49 IServiceProvider
*service_provider
;
50 ProtocolStream
*stream
;
57 DWORD apartment_thread
;
61 struct ProtocolStream
{
62 const IStreamVtbl
*lpStreamVtbl
;
66 IInternetProtocol
*protocol
;
73 #define BINDING(x) ((IBinding*) &(x)->lpBindingVtbl)
74 #define PROTSINK(x) ((IInternetProtocolSink*) &(x)->lpInternetProtocolSinkVtbl)
75 #define BINDINF(x) ((IInternetBindInfo*) &(x)->lpInternetBindInfoVtbl)
76 #define SERVPROV(x) ((IServiceProvider*) &(x)->lpServiceProviderVtbl)
78 #define STREAM(x) ((IStream*) &(x)->lpStreamVtbl)
80 #define WM_MK_ONPROGRESS (WM_USER+100)
81 #define WM_MK_CONTINUE (WM_USER+101)
96 static LRESULT WINAPI
notif_wnd_proc(HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
99 case WM_MK_ONPROGRESS
: {
100 on_progress_data
*data
= (on_progress_data
*)lParam
;
102 TRACE("WM_MK_PROGRESS %p\n", data
);
104 IBindStatusCallback_OnProgress(data
->binding
->callback
, data
->progress
,
105 data
->progress_max
, data
->status_code
, data
->status_text
);
107 IBinding_Release(BINDING(data
->binding
));
108 HeapFree(GetProcessHeap(), 0, data
->status_text
);
109 HeapFree(GetProcessHeap(), 0, data
);
113 case WM_MK_CONTINUE
: {
114 switch_data
*data
= (switch_data
*)lParam
;
116 IInternetProtocol_Continue(data
->binding
->protocol
, data
->data
);
118 IBinding_Release(BINDING(data
->binding
));
119 HeapFree(GetProcessHeap(), 0, data
);
124 return DefWindowProcW(hwnd
, msg
, wParam
, lParam
);
127 static HWND
get_notif_hwnd(void)
129 static ATOM wnd_class
= 0;
132 static const WCHAR wszURLMonikerNotificationWindow
[] =
133 {'U','R','L',' ','M','o','n','i','k','e','r',' ',
134 'N','o','t','i','f','i','c','a','t','i','o','n',' ','W','i','n','d','o','w',0};
137 static WNDCLASSEXW wndclass
= {
139 notif_wnd_proc
, 0, 0,
140 NULL
, NULL
, NULL
, NULL
, NULL
,
141 wszURLMonikerNotificationWindow
,
145 wndclass
.hInstance
= URLMON_hInstance
;
147 wnd_class
= RegisterClassExW(&wndclass
);
151 urlmon_tls
= TlsAlloc();
153 hwnd
= TlsGetValue(urlmon_tls
);
157 hwnd
= CreateWindowExW(0, MAKEINTATOMW(wnd_class
),
158 wszURLMonikerNotificationWindow
, 0, 0, 0, 0, 0, HWND_MESSAGE
,
159 NULL
, URLMON_hInstance
, NULL
);
160 TlsSetValue(urlmon_tls
, hwnd
);
162 TRACE("hwnd = %p\n", hwnd
);
167 static void on_progress(Binding
*This
, ULONG progress
, ULONG progress_max
,
168 ULONG status_code
, LPCWSTR status_text
)
170 on_progress_data
*data
;
172 if(GetCurrentThreadId() == This
->apartment_thread
) {
173 IBindStatusCallback_OnProgress(This
->callback
, progress
, progress_max
,
174 status_code
, status_text
);
178 data
= HeapAlloc(GetProcessHeap(), 0, sizeof(*data
));
180 IBinding_AddRef(BINDING(This
));
182 data
->binding
= This
;
183 data
->progress
= progress
;
184 data
->progress_max
= progress_max
;
185 data
->status_code
= status_code
;
188 DWORD size
= (strlenW(status_text
)+1)*sizeof(WCHAR
);
190 data
->status_text
= HeapAlloc(GetProcessHeap(), 0, size
);
191 memcpy(data
->status_text
, status_text
, size
);
193 data
->status_text
= NULL
;
196 PostMessageW(This
->notif_hwnd
, WM_MK_ONPROGRESS
, 0, (LPARAM
)data
);
199 static HRESULT WINAPI
HttpNegotiate_QueryInterface(IHttpNegotiate2
*iface
,
200 REFIID riid
, void **ppv
)
204 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
205 TRACE("(IID_IUnknown %p)\n", ppv
);
207 }else if(IsEqualGUID(&IID_IHttpNegotiate
, riid
)) {
208 TRACE("(IID_IHttpNegotiate %p)\n", ppv
);
210 }else if(IsEqualGUID(&IID_IHttpNegotiate2
, riid
)) {
211 TRACE("(IID_IHttpNegotiate2 %p)\n", ppv
);
216 IHttpNegotiate2_AddRef(iface
);
220 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
221 return E_NOINTERFACE
;
224 static ULONG WINAPI
HttpNegotiate_AddRef(IHttpNegotiate2
*iface
)
230 static ULONG WINAPI
HttpNegotiate_Release(IHttpNegotiate2
*iface
)
232 URLMON_UnlockModule();
236 static HRESULT WINAPI
HttpNegotiate_BeginningTransaction(IHttpNegotiate2
*iface
,
237 LPCWSTR szURL
, LPCWSTR szHeaders
, DWORD dwReserved
, LPWSTR
*pszAdditionalHeaders
)
239 TRACE("(%s %s %ld %p)\n", debugstr_w(szURL
), debugstr_w(szHeaders
), dwReserved
,
240 pszAdditionalHeaders
);
242 *pszAdditionalHeaders
= NULL
;
246 static HRESULT WINAPI
HttpNegotiate_OnResponse(IHttpNegotiate2
*iface
, DWORD dwResponseCode
,
247 LPCWSTR szResponseHeaders
, LPCWSTR szRequestHeaders
,
248 LPWSTR
*pszAdditionalRequestHeaders
)
250 FIXME("(%ld %s %s %p)\n", dwResponseCode
, debugstr_w(szResponseHeaders
),
251 debugstr_w(szRequestHeaders
), pszAdditionalRequestHeaders
);
255 static HRESULT WINAPI
HttpNegotiate_GetRootSecurityId(IHttpNegotiate2
*iface
,
256 BYTE
*pbSecurityId
, DWORD
*pcbSecurityId
, DWORD_PTR dwReserved
)
258 TRACE("(%p %p %ld)\n", pbSecurityId
, pcbSecurityId
, dwReserved
);
260 /* That's all we have to do here */
264 static const IHttpNegotiate2Vtbl HttpNegotiate2Vtbl
= {
265 HttpNegotiate_QueryInterface
,
266 HttpNegotiate_AddRef
,
267 HttpNegotiate_Release
,
268 HttpNegotiate_BeginningTransaction
,
269 HttpNegotiate_OnResponse
,
270 HttpNegotiate_GetRootSecurityId
273 static IHttpNegotiate2 HttpNegotiate
= { &HttpNegotiate2Vtbl
};
275 #define STREAM_THIS(iface) DEFINE_THIS(ProtocolStream, Stream, iface)
277 static HRESULT WINAPI
ProtocolStream_QueryInterface(IStream
*iface
,
278 REFIID riid
, void **ppv
)
280 ProtocolStream
*This
= STREAM_THIS(iface
);
284 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
285 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
287 }else if(IsEqualGUID(&IID_ISequentialStream
, riid
)) {
288 TRACE("(%p)->(IID_ISequentialStream %p)\n", This
, ppv
);
290 }else if(IsEqualGUID(&IID_IStream
, riid
)) {
291 TRACE("(%p)->(IID_IStream %p)\n", This
, ppv
);
296 IStream_AddRef(STREAM(This
));
300 WARN("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
301 return E_NOINTERFACE
;
304 static ULONG WINAPI
ProtocolStream_AddRef(IStream
*iface
)
306 ProtocolStream
*This
= STREAM_THIS(iface
);
307 LONG ref
= InterlockedIncrement(&This
->ref
);
309 TRACE("(%p) ref=%ld\n", This
, ref
);
314 static ULONG WINAPI
ProtocolStream_Release(IStream
*iface
)
316 ProtocolStream
*This
= STREAM_THIS(iface
);
317 LONG ref
= InterlockedDecrement(&This
->ref
);
319 TRACE("(%p) ref=%ld\n", This
, ref
);
322 IInternetProtocol_Release(This
->protocol
);
323 HeapFree(GetProcessHeap(), 0, This
);
325 URLMON_UnlockModule();
331 static HRESULT WINAPI
ProtocolStream_Read(IStream
*iface
, void *pv
,
332 ULONG cb
, ULONG
*pcbRead
)
334 ProtocolStream
*This
= STREAM_THIS(iface
);
335 DWORD read
= 0, pread
= 0;
338 TRACE("(%p)->(%p %ld %p)\n", This
, pv
, cb
, pcbRead
);
343 if(read
> This
->buf_size
)
344 read
= This
->buf_size
;
346 memcpy(pv
, This
->buf
, read
);
348 if(read
< This
->buf_size
)
349 memmove(This
->buf
, This
->buf
+read
, This
->buf_size
-read
);
350 This
->buf_size
-= read
;
358 hres
= IInternetProtocol_Read(This
->protocol
, (PBYTE
)pv
+read
, cb
-read
, &pread
);
359 *pcbRead
= read
+ pread
;
361 if(hres
== E_PENDING
)
363 else if(FAILED(hres
))
364 FIXME("Read failed: %08lx\n", hres
);
366 return read
|| pread
? S_OK
: S_FALSE
;
369 static HRESULT WINAPI
ProtocolStream_Write(IStream
*iface
, const void *pv
,
370 ULONG cb
, ULONG
*pcbWritten
)
372 ProtocolStream
*This
= STREAM_THIS(iface
);
374 TRACE("(%p)->(%p %ld %p)\n", This
, pv
, cb
, pcbWritten
);
376 return STG_E_ACCESSDENIED
;
379 static HRESULT WINAPI
ProtocolStream_Seek(IStream
*iface
, LARGE_INTEGER dlibMove
,
380 DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
382 ProtocolStream
*This
= STREAM_THIS(iface
);
383 FIXME("(%p)->(%ld %08lx %p)\n", This
, dlibMove
.u
.LowPart
, dwOrigin
, plibNewPosition
);
387 static HRESULT WINAPI
ProtocolStream_SetSize(IStream
*iface
, ULARGE_INTEGER libNewSize
)
389 ProtocolStream
*This
= STREAM_THIS(iface
);
390 FIXME("(%p)->(%ld)\n", This
, libNewSize
.u
.LowPart
);
394 static HRESULT WINAPI
ProtocolStream_CopyTo(IStream
*iface
, IStream
*pstm
,
395 ULARGE_INTEGER cb
, ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*pcbWritten
)
397 ProtocolStream
*This
= STREAM_THIS(iface
);
398 FIXME("(%p)->(%p %ld %p %p)\n", This
, pstm
, cb
.u
.LowPart
, pcbRead
, pcbWritten
);
402 static HRESULT WINAPI
ProtocolStream_Commit(IStream
*iface
, DWORD grfCommitFlags
)
404 ProtocolStream
*This
= STREAM_THIS(iface
);
406 TRACE("(%p)->(%08lx)\n", This
, grfCommitFlags
);
411 static HRESULT WINAPI
ProtocolStream_Revert(IStream
*iface
)
413 ProtocolStream
*This
= STREAM_THIS(iface
);
415 TRACE("(%p)\n", This
);
420 static HRESULT WINAPI
ProtocolStream_LockRegion(IStream
*iface
, ULARGE_INTEGER libOffset
,
421 ULARGE_INTEGER cb
, DWORD dwLockType
)
423 ProtocolStream
*This
= STREAM_THIS(iface
);
424 FIXME("(%p)->(%ld %ld %ld)\n", This
, libOffset
.u
.LowPart
, cb
.u
.LowPart
, dwLockType
);
428 static HRESULT WINAPI
ProtocolStream_UnlockRegion(IStream
*iface
,
429 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
431 ProtocolStream
*This
= STREAM_THIS(iface
);
432 FIXME("(%p)->(%ld %ld %ld)\n", This
, libOffset
.u
.LowPart
, cb
.u
.LowPart
, dwLockType
);
436 static HRESULT WINAPI
ProtocolStream_Stat(IStream
*iface
, STATSTG
*pstatstg
,
439 ProtocolStream
*This
= STREAM_THIS(iface
);
440 FIXME("(%p)->(%p %08lx)\n", This
, pstatstg
, dwStatFlag
);
444 static HRESULT WINAPI
ProtocolStream_Clone(IStream
*iface
, IStream
**ppstm
)
446 ProtocolStream
*This
= STREAM_THIS(iface
);
447 FIXME("(%p)->(%p)\n", This
, ppstm
);
453 static const IStreamVtbl ProtocolStreamVtbl
= {
454 ProtocolStream_QueryInterface
,
455 ProtocolStream_AddRef
,
456 ProtocolStream_Release
,
458 ProtocolStream_Write
,
460 ProtocolStream_SetSize
,
461 ProtocolStream_CopyTo
,
462 ProtocolStream_Commit
,
463 ProtocolStream_Revert
,
464 ProtocolStream_LockRegion
,
465 ProtocolStream_UnlockRegion
,
470 #define BINDING_THIS(iface) DEFINE_THIS(Binding, Binding, iface)
472 static ProtocolStream
*create_stream(IInternetProtocol
*protocol
)
474 ProtocolStream
*ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(ProtocolStream
));
476 ret
->lpStreamVtbl
= &ProtocolStreamVtbl
;
479 ret
->init_buf
= FALSE
;
481 IInternetProtocol_AddRef(protocol
);
482 ret
->protocol
= protocol
;
489 static void fill_stream_buffer(ProtocolStream
*This
)
494 hres
= IInternetProtocol_Read(This
->protocol
, This
->buf
+This
->buf_size
,
495 sizeof(This
->buf
)-This
->buf_size
, &read
);
496 if(SUCCEEDED(hres
)) {
497 This
->buf_size
+= read
;
498 This
->init_buf
= TRUE
;
502 static HRESULT WINAPI
Binding_QueryInterface(IBinding
*iface
, REFIID riid
, void **ppv
)
504 Binding
*This
= BINDING_THIS(iface
);
508 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
509 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
510 *ppv
= BINDING(This
);
511 }else if(IsEqualGUID(&IID_IBinding
, riid
)) {
512 TRACE("(%p)->(IID_IBinding %p)\n", This
, ppv
);
513 *ppv
= BINDING(This
);
514 }else if(IsEqualGUID(&IID_IInternetProtocolSink
, riid
)) {
515 TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This
, ppv
);
516 *ppv
= PROTSINK(This
);
517 }else if(IsEqualGUID(&IID_IInternetBindInfo
, riid
)) {
518 TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This
, ppv
);
519 *ppv
= BINDINF(This
);
520 }else if(IsEqualGUID(&IID_IServiceProvider
, riid
)) {
521 TRACE("(%p)->(IID_IServiceProvider %p)\n", This
, ppv
);
522 *ppv
= SERVPROV(This
);
526 IBinding_AddRef(BINDING(This
));
530 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
531 return E_NOINTERFACE
;
534 static ULONG WINAPI
Binding_AddRef(IBinding
*iface
)
536 Binding
*This
= BINDING_THIS(iface
);
537 LONG ref
= InterlockedIncrement(&This
->ref
);
539 TRACE("(%p) ref=%ld\n", This
, ref
);
544 static ULONG WINAPI
Binding_Release(IBinding
*iface
)
546 Binding
*This
= BINDING_THIS(iface
);
547 LONG ref
= InterlockedDecrement(&This
->ref
);
549 TRACE("(%p) ref=%ld\n", This
, ref
);
553 IBindStatusCallback_Release(This
->callback
);
555 IInternetProtocol_Release(This
->protocol
);
556 if(This
->service_provider
)
557 IServiceProvider_Release(This
->service_provider
);
559 IStream_Release(STREAM(This
->stream
));
561 ReleaseBindInfo(&This
->bindinfo
);
562 HeapFree(GetProcessHeap(), 0, This
->mime
);
563 HeapFree(GetProcessHeap(), 0, This
->url
);
565 HeapFree(GetProcessHeap(), 0, This
);
567 URLMON_UnlockModule();
573 static HRESULT WINAPI
Binding_Abort(IBinding
*iface
)
575 Binding
*This
= BINDING_THIS(iface
);
576 FIXME("(%p)\n", This
);
580 static HRESULT WINAPI
Binding_Suspend(IBinding
*iface
)
582 Binding
*This
= BINDING_THIS(iface
);
583 FIXME("(%p)\n", This
);
587 static HRESULT WINAPI
Binding_Resume(IBinding
*iface
)
589 Binding
*This
= BINDING_THIS(iface
);
590 FIXME("(%p)\n", This
);
594 static HRESULT WINAPI
Binding_SetPriority(IBinding
*iface
, LONG nPriority
)
596 Binding
*This
= BINDING_THIS(iface
);
597 FIXME("(%p)->(%ld)\n", This
, nPriority
);
601 static HRESULT WINAPI
Binding_GetPriority(IBinding
*iface
, LONG
*pnPriority
)
603 Binding
*This
= BINDING_THIS(iface
);
604 FIXME("(%p)->(%p)\n", This
, pnPriority
);
608 static HRESULT WINAPI
Binding_GetBindResult(IBinding
*iface
, CLSID
*pclsidProtocol
,
609 DWORD
*pdwResult
, LPOLESTR
*pszResult
, DWORD
*pdwReserved
)
611 Binding
*This
= BINDING_THIS(iface
);
612 FIXME("(%p)->(%p %p %p %p)\n", This
, pclsidProtocol
, pdwResult
, pszResult
, pdwReserved
);
618 static const IBindingVtbl BindingVtbl
= {
619 Binding_QueryInterface
,
627 Binding_GetBindResult
630 #define PROTSINK_THIS(iface) DEFINE_THIS(Binding, InternetProtocolSink, iface)
632 static HRESULT WINAPI
InternetProtocolSink_QueryInterface(IInternetProtocolSink
*iface
,
633 REFIID riid
, void **ppv
)
635 Binding
*This
= PROTSINK_THIS(iface
);
636 return IBinding_QueryInterface(BINDING(This
), riid
, ppv
);
639 static ULONG WINAPI
InternetProtocolSink_AddRef(IInternetProtocolSink
*iface
)
641 Binding
*This
= PROTSINK_THIS(iface
);
642 return IBinding_AddRef(BINDING(This
));
645 static ULONG WINAPI
InternetProtocolSink_Release(IInternetProtocolSink
*iface
)
647 Binding
*This
= PROTSINK_THIS(iface
);
648 return IBinding_Release(BINDING(This
));
651 static HRESULT WINAPI
InternetProtocolSink_Switch(IInternetProtocolSink
*iface
,
652 PROTOCOLDATA
*pProtocolData
)
654 Binding
*This
= PROTSINK_THIS(iface
);
657 TRACE("(%p)->(%p)\n", This
, pProtocolData
);
659 data
= HeapAlloc(GetProcessHeap(), 0, sizeof(switch_data
));
661 IBinding_AddRef(BINDING(This
));
662 data
->binding
= This
;
663 data
->data
= pProtocolData
;
665 PostMessageW(This
->notif_hwnd
, WM_MK_CONTINUE
, 0, (LPARAM
)data
);
670 static HRESULT WINAPI
InternetProtocolSink_ReportProgress(IInternetProtocolSink
*iface
,
671 ULONG ulStatusCode
, LPCWSTR szStatusText
)
673 Binding
*This
= PROTSINK_THIS(iface
);
675 TRACE("(%p)->(%lu %s)\n", This
, ulStatusCode
, debugstr_w(szStatusText
));
677 switch(ulStatusCode
) {
678 case BINDSTATUS_FINDINGRESOURCE
:
679 on_progress(This
, 0, 0, BINDSTATUS_FINDINGRESOURCE
, szStatusText
);
681 case BINDSTATUS_CONNECTING
:
682 on_progress(This
, 0, 0, BINDSTATUS_CONNECTING
, szStatusText
);
684 case BINDSTATUS_MIMETYPEAVAILABLE
: {
685 int len
= strlenW(szStatusText
)+1;
686 This
->mime
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
687 memcpy(This
->mime
, szStatusText
, len
*sizeof(WCHAR
));
690 case BINDSTATUS_SENDINGREQUEST
:
691 on_progress(This
, 0, 0, BINDSTATUS_SENDINGREQUEST
, szStatusText
);
693 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE
:
694 on_progress(This
, 0, 0, BINDSTATUS_MIMETYPEAVAILABLE
, szStatusText
);
696 case BINDSTATUS_CACHEFILENAMEAVAILABLE
:
699 FIXME("Unhandled status code %ld\n", ulStatusCode
);
706 static HRESULT WINAPI
InternetProtocolSink_ReportData(IInternetProtocolSink
*iface
,
707 DWORD grfBSCF
, ULONG ulProgress
, ULONG ulProgressMax
)
709 Binding
*This
= PROTSINK_THIS(iface
);
713 TRACE("(%p)->(%ld %lu %lu)\n", This
, grfBSCF
, ulProgress
, ulProgressMax
);
715 if(grfBSCF
& BSCF_FIRSTDATANOTIFICATION
) {
717 IBindStatusCallback_OnProgress(This
->callback
, ulProgress
, ulProgressMax
,
718 BINDSTATUS_MIMETYPEAVAILABLE
, This
->mime
);
719 IBindStatusCallback_OnProgress(This
->callback
, ulProgress
, ulProgressMax
,
720 BINDSTATUS_BEGINDOWNLOADDATA
, This
->url
);
723 if(grfBSCF
& BSCF_LASTDATANOTIFICATION
)
724 IBindStatusCallback_OnProgress(This
->callback
, ulProgress
, ulProgressMax
,
725 BINDSTATUS_ENDDOWNLOADDATA
, This
->url
);
727 if(grfBSCF
& BSCF_FIRSTDATANOTIFICATION
)
728 IInternetProtocol_LockRequest(This
->protocol
, 0);
730 fill_stream_buffer(This
->stream
);
732 stgmed
.tymed
= TYMED_ISTREAM
;
733 stgmed
.u
.pstm
= STREAM(This
->stream
);
735 formatetc
.cfFormat
= 0; /* FIXME */
736 formatetc
.ptd
= NULL
;
737 formatetc
.dwAspect
= 1;
738 formatetc
.lindex
= -1;
739 formatetc
.tymed
= TYMED_ISTREAM
;
741 IBindStatusCallback_OnDataAvailable(This
->callback
, grfBSCF
, This
->stream
->buf_size
,
742 &formatetc
, &stgmed
);
744 if(grfBSCF
& BSCF_LASTDATANOTIFICATION
)
745 IBindStatusCallback_OnStopBinding(This
->callback
, S_OK
, NULL
);
750 static HRESULT WINAPI
InternetProtocolSink_ReportResult(IInternetProtocolSink
*iface
,
751 HRESULT hrResult
, DWORD dwError
, LPCWSTR szResult
)
753 Binding
*This
= PROTSINK_THIS(iface
);
755 TRACE("(%p)->(%08lx %ld %s)\n", This
, hrResult
, dwError
, debugstr_w(szResult
));
757 IInternetProtocol_Terminate(This
->protocol
, 0);
763 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl
= {
764 InternetProtocolSink_QueryInterface
,
765 InternetProtocolSink_AddRef
,
766 InternetProtocolSink_Release
,
767 InternetProtocolSink_Switch
,
768 InternetProtocolSink_ReportProgress
,
769 InternetProtocolSink_ReportData
,
770 InternetProtocolSink_ReportResult
773 #define BINDINF_THIS(iface) DEFINE_THIS(Binding, InternetBindInfo, iface)
775 static HRESULT WINAPI
InternetBindInfo_QueryInterface(IInternetBindInfo
*iface
,
776 REFIID riid
, void **ppv
)
778 Binding
*This
= BINDINF_THIS(iface
);
779 return IBinding_QueryInterface(BINDING(This
), riid
, ppv
);
782 static ULONG WINAPI
InternetBindInfo_AddRef(IInternetBindInfo
*iface
)
784 Binding
*This
= BINDINF_THIS(iface
);
785 return IBinding_AddRef(BINDING(This
));
788 static ULONG WINAPI
InternetBindInfo_Release(IInternetBindInfo
*iface
)
790 Binding
*This
= BINDINF_THIS(iface
);
791 return IBinding_Release(BINDING(This
));
794 static HRESULT WINAPI
InternetBindInfo_GetBindInfo(IInternetBindInfo
*iface
,
795 DWORD
*grfBINDF
, BINDINFO
*pbindinfo
)
797 Binding
*This
= BINDINF_THIS(iface
);
799 TRACE("(%p)->(%p %p)\n", This
, grfBINDF
, pbindinfo
);
801 *grfBINDF
= This
->bindf
;
803 memcpy(pbindinfo
, &This
->bindinfo
, sizeof(BINDINFO
));
805 if(pbindinfo
->szExtraInfo
|| pbindinfo
->szCustomVerb
)
806 FIXME("copy strings\n");
809 IUnknown_AddRef(pbindinfo
->pUnk
);
814 static HRESULT WINAPI
InternetBindInfo_GetBindString(IInternetBindInfo
*iface
,
815 ULONG ulStringType
, LPOLESTR
*ppwzStr
, ULONG cEl
, ULONG
*pcElFetched
)
817 Binding
*This
= BINDINF_THIS(iface
);
819 TRACE("(%p)->(%ld %p %ld %p)\n", This
, ulStringType
, ppwzStr
, cEl
, pcElFetched
);
821 switch(ulStringType
) {
822 case BINDSTRING_ACCEPT_MIMES
: {
823 static const WCHAR wszMimes
[] = {'*','/','*',0};
825 if(!ppwzStr
|| !pcElFetched
)
828 ppwzStr
[0] = CoTaskMemAlloc(sizeof(wszMimes
));
829 memcpy(ppwzStr
[0], wszMimes
, sizeof(wszMimes
));
833 case BINDSTRING_USER_AGENT
: {
834 IInternetBindInfo
*bindinfo
= NULL
;
837 hres
= IBindStatusCallback_QueryInterface(This
->callback
, &IID_IInternetBindInfo
,
842 hres
= IInternetBindInfo_GetBindString(bindinfo
, ulStringType
, ppwzStr
,
844 IInternetBindInfo_Release(bindinfo
);
850 FIXME("not supported string type %ld\n", ulStringType
);
856 static const IInternetBindInfoVtbl InternetBindInfoVtbl
= {
857 InternetBindInfo_QueryInterface
,
858 InternetBindInfo_AddRef
,
859 InternetBindInfo_Release
,
860 InternetBindInfo_GetBindInfo
,
861 InternetBindInfo_GetBindString
864 #define SERVPROV_THIS(iface) DEFINE_THIS(Binding, ServiceProvider, iface)
866 static HRESULT WINAPI
ServiceProvider_QueryInterface(IServiceProvider
*iface
,
867 REFIID riid
, void **ppv
)
869 Binding
*This
= SERVPROV_THIS(iface
);
870 return IBinding_QueryInterface(BINDING(This
), riid
, ppv
);
873 static ULONG WINAPI
ServiceProvider_AddRef(IServiceProvider
*iface
)
875 Binding
*This
= SERVPROV_THIS(iface
);
876 return IBinding_AddRef(BINDING(This
));
879 static ULONG WINAPI
ServiceProvider_Release(IServiceProvider
*iface
)
881 Binding
*This
= SERVPROV_THIS(iface
);
882 return IBinding_Release(BINDING(This
));
885 static HRESULT WINAPI
ServiceProvider_QueryService(IServiceProvider
*iface
,
886 REFGUID guidService
, REFIID riid
, void **ppv
)
888 Binding
*This
= SERVPROV_THIS(iface
);
891 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_guid(guidService
), debugstr_guid(riid
), ppv
);
893 if(This
->service_provider
) {
894 hres
= IServiceProvider_QueryService(This
->service_provider
, guidService
,
900 if(IsEqualGUID(&IID_IHttpNegotiate
, guidService
)
901 || IsEqualGUID(&IID_IHttpNegotiate2
, guidService
))
902 return IHttpNegotiate2_QueryInterface(&HttpNegotiate
, riid
, ppv
);
904 WARN("unknown service %s\n", debugstr_guid(guidService
));
910 static const IServiceProviderVtbl ServiceProviderVtbl
= {
911 ServiceProvider_QueryInterface
,
912 ServiceProvider_AddRef
,
913 ServiceProvider_Release
,
914 ServiceProvider_QueryService
917 static HRESULT
get_callback(IBindCtx
*pbc
, IBindStatusCallback
**callback
)
921 static WCHAR wszBSCBHolder
[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_',0 };
923 hres
= IBindCtx_GetObjectParam(pbc
, wszBSCBHolder
, (IUnknown
**)callback
);
930 static HRESULT
get_protocol(Binding
*This
, LPCWSTR url
)
932 IClassFactory
*cf
= NULL
;
935 hres
= IBindStatusCallback_QueryInterface(This
->callback
, &IID_IInternetProtocol
,
936 (void**)&This
->protocol
);
940 if(This
->service_provider
) {
941 hres
= IServiceProvider_QueryService(This
->service_provider
, &IID_IInternetProtocol
,
942 &IID_IInternetProtocol
, (void**)&This
->protocol
);
947 hres
= get_protocol_handler(url
, &cf
);
951 hres
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IInternetProtocol
, (void**)&This
->protocol
);
952 IClassFactory_Release(cf
);
957 static HRESULT
Binding_Create(LPCWSTR url
, IBindCtx
*pbc
, REFIID riid
, Binding
**binding
)
963 static const WCHAR wszFile
[] = {'f','i','l','e',':'};
965 if(!IsEqualGUID(&IID_IStream
, riid
)) {
966 FIXME("Unsupported riid %s\n", debugstr_guid(riid
));
972 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(Binding
));
974 ret
->lpBindingVtbl
= &BindingVtbl
;
975 ret
->lpInternetProtocolSinkVtbl
= &InternetProtocolSinkVtbl
;
976 ret
->lpInternetBindInfoVtbl
= &InternetBindInfoVtbl
;
977 ret
->lpServiceProviderVtbl
= &ServiceProviderVtbl
;
981 ret
->callback
= NULL
;
982 ret
->protocol
= NULL
;
983 ret
->service_provider
= NULL
;
987 ret
->apartment_thread
= GetCurrentThreadId();
988 ret
->notif_hwnd
= get_notif_hwnd();
990 memset(&ret
->bindinfo
, 0, sizeof(BINDINFO
));
991 ret
->bindinfo
.cbSize
= sizeof(BINDINFO
);
994 hres
= get_callback(pbc
, &ret
->callback
);
996 WARN("Could not get IBindStatusCallback\n");
997 IBinding_Release(BINDING(ret
));
1001 IBindStatusCallback_QueryInterface(ret
->callback
, &IID_IServiceProvider
,
1002 (void**)&ret
->service_provider
);
1004 hres
= get_protocol(ret
, url
);
1006 WARN("Could not get protocol handler\n");
1007 IBinding_Release(BINDING(ret
));
1011 hres
= IBindStatusCallback_GetBindInfo(ret
->callback
, &ret
->bindf
, &ret
->bindinfo
);
1013 WARN("GetBindInfo failed: %08lx\n", hres
);
1014 IBinding_Release(BINDING(ret
));
1018 ret
->bindf
|= BINDF_FROMURLMON
;
1020 len
= strlenW(url
)+1;
1022 if(len
< sizeof(wszFile
)/sizeof(WCHAR
) || memcmp(wszFile
, url
, sizeof(wszFile
)))
1023 ret
->bindf
|= BINDF_NEEDFILE
;
1025 ret
->url
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
1026 memcpy(ret
->url
, url
, len
*sizeof(WCHAR
));
1028 ret
->stream
= create_stream(ret
->protocol
);
1034 HRESULT
start_binding(LPCWSTR url
, IBindCtx
*pbc
, REFIID riid
, void **ppv
)
1036 Binding
*binding
= NULL
;
1041 hres
= Binding_Create(url
, pbc
, riid
, &binding
);
1045 hres
= IBindStatusCallback_OnStartBinding(binding
->callback
, 0, BINDING(binding
));
1047 WARN("OnStartBinding failed: %08lx\n", hres
);
1048 IBindStatusCallback_OnStopBinding(binding
->callback
, 0x800c0008, NULL
);
1049 IBinding_Release(BINDING(binding
));
1053 hres
= IInternetProtocol_Start(binding
->protocol
, url
, PROTSINK(binding
),
1054 BINDINF(binding
), 0, 0);
1057 WARN("Start failed: %08lx\n", hres
);
1059 IInternetProtocol_Terminate(binding
->protocol
, 0);
1060 IBindStatusCallback_OnStopBinding(binding
->callback
, S_OK
, NULL
);
1061 IBinding_Release(BINDING(binding
));
1066 if(binding
->stream
->init_buf
) {
1067 IInternetProtocol_UnlockRequest(binding
->protocol
);
1069 IStream_AddRef(STREAM(binding
->stream
));
1070 *ppv
= binding
->stream
;
1074 hres
= MK_S_ASYNCHRONOUS
;
1077 IBinding_Release(BINDING(binding
));