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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
);
38 const IBindingVtbl
*lpBindingVtbl
;
39 const IInternetProtocolSinkVtbl
*lpInternetProtocolSinkVtbl
;
40 const IInternetBindInfoVtbl
*lpInternetBindInfoVtbl
;
41 const IServiceProviderVtbl
*lpServiceProviderVtbl
;
45 IBindStatusCallback
*callback
;
46 IInternetProtocol
*protocol
;
55 #define BINDING(x) ((IBinding*) &(x)->lpBindingVtbl)
56 #define PROTSINK(x) ((IInternetProtocolSink*) &(x)->lpInternetProtocolSinkVtbl)
57 #define BINDINF(x) ((IInternetBindInfo*) &(x)->lpInternetBindInfoVtbl)
58 #define SERVPROV(x) ((IServiceProvider*) &(x)->lpServiceProviderVtbl)
61 #define BINDING_THIS(iface) DEFINE_THIS(Binding, Binding, iface)
63 static HRESULT WINAPI
Binding_QueryInterface(IBinding
*iface
, REFIID riid
, void **ppv
)
65 Binding
*This
= BINDING_THIS(iface
);
69 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
70 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
72 }else if(IsEqualGUID(&IID_IBinding
, riid
)) {
73 TRACE("(%p)->(IID_IBinding %p)\n", This
, ppv
);
75 }else if(IsEqualGUID(&IID_IInternetProtocolSink
, riid
)) {
76 TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This
, ppv
);
77 *ppv
= PROTSINK(This
);
78 }else if(IsEqualGUID(&IID_IInternetBindInfo
, riid
)) {
79 TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This
, ppv
);
81 }else if(IsEqualGUID(&IID_IServiceProvider
, riid
)) {
82 TRACE("(%p)->(IID_IServiceProvider %p)\n", This
, ppv
);
83 *ppv
= SERVPROV(This
);
89 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
93 static ULONG WINAPI
Binding_AddRef(IBinding
*iface
)
95 Binding
*This
= BINDING_THIS(iface
);
96 LONG ref
= InterlockedIncrement(&This
->ref
);
98 TRACE("(%p) ref=%ld\n", This
, ref
);
103 static ULONG WINAPI
Binding_Release(IBinding
*iface
)
105 Binding
*This
= BINDING_THIS(iface
);
106 LONG ref
= InterlockedDecrement(&This
->ref
);
108 TRACE("(%p) ref=%ld\n", This
, ref
);
112 IBindStatusCallback_Release(This
->callback
);
114 IInternetProtocol_Release(This
->protocol
);
116 IStream_Release(This
->stream
);
118 ReleaseBindInfo(&This
->bindinfo
);
119 HeapFree(GetProcessHeap(), 0, This
->mime
);
120 HeapFree(GetProcessHeap(), 0, This
->url
);
122 HeapFree(GetProcessHeap(), 0, This
);
128 static HRESULT WINAPI
Binding_Abort(IBinding
*iface
)
130 Binding
*This
= BINDING_THIS(iface
);
131 FIXME("(%p)\n", This
);
135 static HRESULT WINAPI
Binding_Suspend(IBinding
*iface
)
137 Binding
*This
= BINDING_THIS(iface
);
138 FIXME("(%p)\n", This
);
142 static HRESULT WINAPI
Binding_Resume(IBinding
*iface
)
144 Binding
*This
= BINDING_THIS(iface
);
145 FIXME("(%p)\n", This
);
149 static HRESULT WINAPI
Binding_SetPriority(IBinding
*iface
, LONG nPriority
)
151 Binding
*This
= BINDING_THIS(iface
);
152 FIXME("(%p)->(%ld)\n", This
, nPriority
);
156 static HRESULT WINAPI
Binding_GetPriority(IBinding
*iface
, LONG
*pnPriority
)
158 Binding
*This
= BINDING_THIS(iface
);
159 FIXME("(%p)->(%p)\n", This
, pnPriority
);
163 static HRESULT WINAPI
Binding_GetBindResult(IBinding
*iface
, CLSID
*pclsidProtocol
,
164 DWORD
*pdwResult
, LPOLESTR
*pszResult
, DWORD
*pdwReserved
)
166 Binding
*This
= BINDING_THIS(iface
);
167 FIXME("(%p)->(%p %p %p %p)\n", This
, pclsidProtocol
, pdwResult
, pszResult
, pdwReserved
);
173 static const IBindingVtbl BindingVtbl
= {
174 Binding_QueryInterface
,
182 Binding_GetBindResult
185 #define PROTSINK_THIS(iface) DEFINE_THIS(Binding, InternetProtocolSink, iface)
187 static HRESULT WINAPI
InternetProtocolSink_QueryInterface(IInternetProtocolSink
*iface
,
188 REFIID riid
, void **ppv
)
190 Binding
*This
= PROTSINK_THIS(iface
);
191 return IBinding_QueryInterface(BINDING(This
), riid
, ppv
);
194 static ULONG WINAPI
InternetProtocolSink_AddRef(IInternetProtocolSink
*iface
)
196 Binding
*This
= PROTSINK_THIS(iface
);
197 return IBinding_AddRef(BINDING(This
));
200 static ULONG WINAPI
InternetProtocolSink_Release(IInternetProtocolSink
*iface
)
202 Binding
*This
= PROTSINK_THIS(iface
);
203 return IBinding_Release(BINDING(This
));
206 static HRESULT WINAPI
InternetProtocolSink_Switch(IInternetProtocolSink
*iface
,
207 PROTOCOLDATA
*pProtocolData
)
209 Binding
*This
= PROTSINK_THIS(iface
);
210 FIXME("(%p)->(%p)\n", This
, pProtocolData
);
214 static HRESULT WINAPI
InternetProtocolSink_ReportProgress(IInternetProtocolSink
*iface
,
215 ULONG ulStatusCode
, LPCWSTR szStatusText
)
217 Binding
*This
= PROTSINK_THIS(iface
);
219 TRACE("(%p)->(%lu %s)\n", This
, ulStatusCode
, debugstr_w(szStatusText
));
221 switch(ulStatusCode
) {
222 case BINDSTATUS_MIMETYPEAVAILABLE
: {
223 int len
= strlenW(szStatusText
)+1;
224 This
->mime
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
225 memcpy(This
->mime
, szStatusText
, len
*sizeof(WCHAR
));
229 FIXME("Unhandled status code %ld\n", ulStatusCode
);
236 static HRESULT WINAPI
InternetProtocolSink_ReportData(IInternetProtocolSink
*iface
,
237 DWORD grfBSCF
, ULONG ulProgress
, ULONG ulProgressMax
)
239 Binding
*This
= PROTSINK_THIS(iface
);
240 DWORD read
= 0, cread
;
244 TRACE("(%p)->(%ld %lu %lu)\n", This
, grfBSCF
, ulProgress
, ulProgressMax
);
246 if(grfBSCF
& BSCF_FIRSTDATANOTIFICATION
) {
248 IBindStatusCallback_OnProgress(This
->callback
, ulProgress
, ulProgressMax
,
249 BINDSTATUS_MIMETYPEAVAILABLE
, This
->mime
);
250 IBindStatusCallback_OnProgress(This
->callback
, ulProgress
, ulProgressMax
,
251 BINDSTATUS_BEGINDOWNLOADDATA
, This
->url
);
254 if(grfBSCF
& BSCF_LASTDATANOTIFICATION
)
255 IBindStatusCallback_OnProgress(This
->callback
, ulProgress
, ulProgressMax
,
256 BINDSTATUS_ENDDOWNLOADDATA
, This
->url
);
258 if(grfBSCF
& BSCF_FIRSTDATANOTIFICATION
)
259 IInternetProtocol_LockRequest(This
->protocol
, 0);
262 IInternetProtocol_Read(This
->protocol
, buf
, sizeof(buf
), &cread
);
263 IStream_Write(This
->stream
, buf
, read
, NULL
);
267 stgmed
.tymed
= TYMED_ISTREAM
;
268 stgmed
.u
.pstm
= This
->stream
;
270 IBindStatusCallback_OnDataAvailable(This
->callback
, grfBSCF
, read
,
271 NULL
/* FIXME */, &stgmed
);
273 if(grfBSCF
& BSCF_LASTDATANOTIFICATION
)
274 IBindStatusCallback_OnStopBinding(This
->callback
, S_OK
, NULL
);
279 static HRESULT WINAPI
InternetProtocolSink_ReportResult(IInternetProtocolSink
*iface
,
280 HRESULT hrResult
, DWORD dwError
, LPCWSTR szResult
)
282 Binding
*This
= PROTSINK_THIS(iface
);
283 FIXME("(%p)->(%08lx %ld %s)\n", This
, hrResult
, dwError
, debugstr_w(szResult
));
289 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl
= {
290 InternetProtocolSink_QueryInterface
,
291 InternetProtocolSink_AddRef
,
292 InternetProtocolSink_Release
,
293 InternetProtocolSink_Switch
,
294 InternetProtocolSink_ReportProgress
,
295 InternetProtocolSink_ReportData
,
296 InternetProtocolSink_ReportResult
299 #define BINDINF_THIS(iface) DEFINE_THIS(Binding, InternetBindInfo, iface)
301 static HRESULT WINAPI
InternetBindInfo_QueryInterface(IInternetBindInfo
*iface
,
302 REFIID riid
, void **ppv
)
304 Binding
*This
= BINDINF_THIS(iface
);
305 return IBinding_QueryInterface(BINDING(This
), riid
, ppv
);
308 static ULONG WINAPI
InternetBindInfo_AddRef(IInternetBindInfo
*iface
)
310 Binding
*This
= BINDINF_THIS(iface
);
311 return IBinding_AddRef(BINDING(This
));
314 static ULONG WINAPI
InternetBindInfo_Release(IInternetBindInfo
*iface
)
316 Binding
*This
= BINDINF_THIS(iface
);
317 return IBinding_Release(BINDING(This
));
320 static HRESULT WINAPI
InternetBindInfo_GetBindInfo(IInternetBindInfo
*iface
,
321 DWORD
*grfBINDF
, BINDINFO
*pbindinfo
)
323 Binding
*This
= BINDINF_THIS(iface
);
325 TRACE("(%p)->(%p %p)\n", This
, grfBINDF
, pbindinfo
);
327 *grfBINDF
= This
->bindf
;
329 memcpy(pbindinfo
, &This
->bindinfo
, sizeof(BINDINFO
));
331 if(pbindinfo
->szExtraInfo
|| pbindinfo
->szCustomVerb
)
332 FIXME("copy strings\n");
335 IUnknown_AddRef(pbindinfo
->pUnk
);
340 static HRESULT WINAPI
InternetBindInfo_GetBindString(IInternetBindInfo
*iface
,
341 ULONG ulStringType
, LPOLESTR
*ppwzStr
, ULONG cEl
, ULONG
*pcElFetched
)
343 Binding
*This
= BINDINF_THIS(iface
);
344 FIXME("(%p)->(%ld %p %ld %p)\n", This
, ulStringType
, ppwzStr
, cEl
, pcElFetched
);
350 static const IInternetBindInfoVtbl InternetBindInfoVtbl
= {
351 InternetBindInfo_QueryInterface
,
352 InternetBindInfo_AddRef
,
353 InternetBindInfo_Release
,
354 InternetBindInfo_GetBindInfo
,
355 InternetBindInfo_GetBindString
358 #define SERVPROV_THIS(iface) DEFINE_THIS(Binding, ServiceProvider, iface)
360 static HRESULT WINAPI
ServiceProvider_QueryInterface(IServiceProvider
*iface
,
361 REFIID riid
, void **ppv
)
363 Binding
*This
= SERVPROV_THIS(iface
);
364 return IBinding_QueryInterface(BINDING(This
), riid
, ppv
);
367 static ULONG WINAPI
ServiceProvider_AddRef(IServiceProvider
*iface
)
369 Binding
*This
= SERVPROV_THIS(iface
);
370 return IBinding_AddRef(BINDING(This
));
373 static ULONG WINAPI
ServiceProvider_Release(IServiceProvider
*iface
)
375 Binding
*This
= SERVPROV_THIS(iface
);
376 return IBinding_Release(BINDING(This
));
379 static HRESULT WINAPI
ServiceProvider_QueryService(IServiceProvider
*iface
,
380 REFGUID guidService
, REFIID riid
, void **ppv
)
382 Binding
*This
= SERVPROV_THIS(iface
);
383 FIXME("(%p)->(%s %s %p)\n", This
, debugstr_guid(guidService
), debugstr_guid(riid
), ppv
);
389 static const IServiceProviderVtbl ServiceProviderVtbl
= {
390 ServiceProvider_QueryInterface
,
391 ServiceProvider_AddRef
,
392 ServiceProvider_Release
,
393 ServiceProvider_QueryService
396 static HRESULT
get_callback(IBindCtx
*pbc
, IBindStatusCallback
**callback
)
400 static WCHAR wszBSCBHolder
[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_',0 };
402 hres
= IBindCtx_GetObjectParam(pbc
, wszBSCBHolder
, (IUnknown
**)callback
);
409 static HRESULT
get_protocol(Binding
*This
, LPCWSTR url
)
411 IUnknown
*unk
= NULL
;
412 IClassFactory
*cf
= NULL
;
415 hres
= IBindStatusCallback_QueryInterface(This
->callback
, &IID_IInternetProtocol
,
416 (void**)&This
->protocol
);
420 hres
= get_protocol_iface(url
, &unk
);
424 hres
= IUnknown_QueryInterface(unk
, &IID_IClassFactory
, (void**)&cf
);
425 IUnknown_Release(unk
);
429 hres
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IInternetProtocol
, (void**)&This
->protocol
);
430 IClassFactory_Release(cf
);
435 static HRESULT
Binding_Create(LPCWSTR url
, IBindCtx
*pbc
, REFIID riid
, Binding
**binding
)
441 if(!IsEqualGUID(&IID_IStream
, riid
)) {
442 FIXME("Unsupported riid %s\n", debugstr_guid(riid
));
446 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(Binding
));
448 ret
->lpBindingVtbl
= &BindingVtbl
;
449 ret
->lpInternetProtocolSinkVtbl
= &InternetProtocolSinkVtbl
;
450 ret
->lpInternetBindInfoVtbl
= &InternetBindInfoVtbl
;
451 ret
->lpServiceProviderVtbl
= &ServiceProviderVtbl
;
455 ret
->callback
= NULL
;
456 ret
->protocol
= NULL
;
461 memset(&ret
->bindinfo
, 0, sizeof(BINDINFO
));
462 ret
->bindinfo
.cbSize
= sizeof(BINDINFO
);
465 hres
= get_callback(pbc
, &ret
->callback
);
467 WARN("Could not get IBindStatusCallback\n");
468 IBinding_Release(BINDING(ret
));
472 hres
= get_protocol(ret
, url
);
474 WARN("Could not get protocol handler\n");
475 IBinding_Release(BINDING(ret
));
479 hres
= IBindStatusCallback_GetBindInfo(ret
->callback
, &ret
->bindf
, &ret
->bindinfo
);
481 WARN("GetBindInfo failed: %08lx\n", hres
);
482 IBinding_Release(BINDING(ret
));
486 ret
->bindf
|= (BINDF_FROMURLMON
|BINDF_NEEDFILE
);
488 len
= strlenW(url
)+1;
489 ret
->url
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
490 memcpy(ret
->url
, url
, len
*sizeof(WCHAR
));
492 CreateStreamOnHGlobal(NULL
, TRUE
, &ret
->stream
);
498 HRESULT
start_binding(LPCWSTR url
, IBindCtx
*pbc
, REFIID riid
, void **ppv
)
500 Binding
*binding
= NULL
;
505 hres
= Binding_Create(url
, pbc
, riid
, &binding
);
509 hres
= IBindStatusCallback_OnStartBinding(binding
->callback
, 0, BINDING(binding
));
511 WARN("OnStartBinding failed: %08lx\n", hres
);
512 IBindStatusCallback_OnStopBinding(binding
->callback
, 0x800c0008, NULL
);
513 IBinding_Release(BINDING(binding
));
517 hres
= IInternetProtocol_Start(binding
->protocol
, url
, PROTSINK(binding
),
518 BINDINF(binding
), 0, 0);
519 IInternetProtocol_Terminate(binding
->protocol
, 0);
521 if(SUCCEEDED(hres
)) {
522 IInternetProtocol_UnlockRequest(binding
->protocol
);
524 WARN("Start failed: %08lx\n", hres
);
525 IBindStatusCallback_OnStopBinding(binding
->callback
, S_OK
, NULL
);
528 IStream_AddRef(binding
->stream
);
529 *ppv
= binding
->stream
;
531 IBinding_Release(BINDING(binding
));