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
);
25 const IInternetProtocolVtbl
*lpInternetProtocolVtbl
;
26 const IInternetBindInfoVtbl
*lpInternetBindInfoVtbl
;
27 const IInternetPriorityVtbl
*lpInternetPriorityVtbl
;
28 const IServiceProviderVtbl
*lpServiceProviderVtbl
;
29 const IInternetProtocolSinkVtbl
*lpInternetProtocolSinkVtbl
;
33 IInternetProtocol
*protocol
;
34 IInternetBindInfo
*bind_info
;
35 IInternetProtocolSink
*protocol_sink
;
36 IServiceProvider
*service_provider
;
37 IWinInetInfo
*wininet_info
;
45 #define PROTOCOL(x) ((IInternetProtocol*) &(x)->lpInternetProtocolVtbl)
46 #define BINDINFO(x) ((IInternetBindInfo*) &(x)->lpInternetBindInfoVtbl)
47 #define PRIORITY(x) ((IInternetPriority*) &(x)->lpInternetPriorityVtbl)
48 #define SERVPROV(x) ((IServiceProvider*) &(x)->lpServiceProviderVtbl)
49 #define PROTSINK(x) ((IInternetProtocolSink*) &(x)->lpInternetProtocolSinkVtbl)
51 #define PROTOCOL_THIS(iface) DEFINE_THIS(BindProtocol, InternetProtocol, iface)
53 static HRESULT WINAPI
BindProtocol_QueryInterface(IInternetProtocol
*iface
, REFIID riid
, void **ppv
)
55 BindProtocol
*This
= PROTOCOL_THIS(iface
);
58 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
59 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
60 *ppv
= PROTOCOL(This
);
61 }else if(IsEqualGUID(&IID_IInternetProtocolRoot
, riid
)) {
62 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This
, ppv
);
63 *ppv
= PROTOCOL(This
);
64 }else if(IsEqualGUID(&IID_IInternetProtocol
, riid
)) {
65 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This
, ppv
);
66 *ppv
= PROTOCOL(This
);
67 }else if(IsEqualGUID(&IID_IInternetBindInfo
, riid
)) {
68 TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This
, ppv
);
69 *ppv
= BINDINFO(This
);
70 }else if(IsEqualGUID(&IID_IInternetPriority
, riid
)) {
71 TRACE("(%p)->(IID_IInternetPriority %p)\n", This
, ppv
);
72 *ppv
= PRIORITY(This
);
73 }else if(IsEqualGUID(&IID_IAuthenticate
, riid
)) {
74 FIXME("(%p)->(IID_IAuthenticate %p)\n", This
, ppv
);
75 }else if(IsEqualGUID(&IID_IServiceProvider
, riid
)) {
76 TRACE("(%p)->(IID_IServiceProvider %p)\n", This
, ppv
);
77 *ppv
= SERVPROV(This
);
78 }else if(IsEqualGUID(&IID_IInternetProtocolSink
, riid
)) {
79 TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This
, ppv
);
80 *ppv
= PROTSINK(This
);
84 IInternetProtocol_AddRef(iface
);
88 WARN("not supported interface %s\n", debugstr_guid(riid
));
92 static ULONG WINAPI
BindProtocol_AddRef(IInternetProtocol
*iface
)
94 BindProtocol
*This
= PROTOCOL_THIS(iface
);
95 LONG ref
= InterlockedIncrement(&This
->ref
);
96 TRACE("(%p) ref=%d\n", This
, ref
);
100 static ULONG WINAPI
BindProtocol_Release(IInternetProtocol
*iface
)
102 BindProtocol
*This
= PROTOCOL_THIS(iface
);
103 LONG ref
= InterlockedDecrement(&This
->ref
);
105 TRACE("(%p) ref=%d\n", This
, ref
);
108 if(This
->wininet_info
)
109 IWinInetInfo_Release(This
->wininet_info
);
111 IInternetProtocol_Release(This
->protocol
);
113 IInternetBindInfo_Release(This
->bind_info
);
115 set_binding_sink(PROTOCOL(This
), NULL
);
118 URLMON_UnlockModule();
124 static HRESULT WINAPI
BindProtocol_Start(IInternetProtocol
*iface
, LPCWSTR szUrl
,
125 IInternetProtocolSink
*pOIProtSink
, IInternetBindInfo
*pOIBindInfo
,
126 DWORD grfPI
, HANDLE_PTR dwReserved
)
128 BindProtocol
*This
= PROTOCOL_THIS(iface
);
129 IInternetProtocol
*protocol
= NULL
;
130 IInternetPriority
*priority
;
131 IServiceProvider
*service_provider
;
132 BOOL urlmon_protocol
= FALSE
;
133 CLSID clsid
= IID_NULL
;
137 TRACE("(%p)->(%s %p %p %08x %lx)\n", This
, debugstr_w(szUrl
), pOIProtSink
,
138 pOIBindInfo
, grfPI
, dwReserved
);
140 if(!szUrl
|| !pOIProtSink
|| !pOIBindInfo
)
143 hres
= IInternetProtocolSink_QueryInterface(pOIProtSink
, &IID_IServiceProvider
,
144 (void**)&service_provider
);
145 if(SUCCEEDED(hres
)) {
146 /* FIXME: What's protocol CLSID here? */
147 IServiceProvider_QueryService(service_provider
, &IID_IInternetProtocol
,
148 &IID_IInternetProtocol
, (void**)&protocol
);
149 IServiceProvider_Release(service_provider
);
156 hres
= get_protocol_handler(szUrl
, &clsid
, &urlmon_protocol
, &cf
);
160 if(This
->from_urlmon
) {
161 hres
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IInternetProtocol
, (void**)&protocol
);
162 IClassFactory_Release(cf
);
166 hres
= IClassFactory_CreateInstance(cf
, (IUnknown
*)BINDINFO(This
),
167 &IID_IUnknown
, (void**)&unk
);
168 IClassFactory_Release(cf
);
172 hres
= IUnknown_QueryInterface(unk
, &IID_IInternetProtocol
, (void**)&protocol
);
173 IUnknown_Release(unk
);
179 StringFromCLSID(&clsid
, &clsid_str
);
180 IInternetProtocolSink_ReportProgress(pOIProtSink
, BINDSTATUS_PROTOCOLCLASSID
, clsid_str
);
181 CoTaskMemFree(clsid_str
);
183 This
->protocol
= protocol
;
186 IInternetProtocol_QueryInterface(protocol
, &IID_IWinInetInfo
, (void**)&This
->wininet_info
);
188 IInternetBindInfo_AddRef(pOIBindInfo
);
189 This
->bind_info
= pOIBindInfo
;
191 set_binding_sink(PROTOCOL(This
), pOIProtSink
);
193 hres
= IInternetProtocol_QueryInterface(protocol
, &IID_IInternetPriority
, (void**)&priority
);
194 if(SUCCEEDED(hres
)) {
195 IInternetPriority_SetPriority(priority
, This
->priority
);
196 IInternetPriority_Release(priority
);
199 return IInternetProtocol_Start(protocol
, szUrl
, PROTSINK(This
), BINDINFO(This
), 0, 0);
202 static HRESULT WINAPI
BindProtocol_Continue(IInternetProtocol
*iface
, PROTOCOLDATA
*pProtocolData
)
204 BindProtocol
*This
= PROTOCOL_THIS(iface
);
206 TRACE("(%p)->(%p)\n", This
, pProtocolData
);
208 return IInternetProtocol_Continue(This
->protocol
, pProtocolData
);
211 static HRESULT WINAPI
BindProtocol_Abort(IInternetProtocol
*iface
, HRESULT hrReason
,
214 BindProtocol
*This
= PROTOCOL_THIS(iface
);
215 FIXME("(%p)->(%08x %08x)\n", This
, hrReason
, dwOptions
);
219 static HRESULT WINAPI
BindProtocol_Terminate(IInternetProtocol
*iface
, DWORD dwOptions
)
221 BindProtocol
*This
= PROTOCOL_THIS(iface
);
223 TRACE("(%p)->(%08x)\n", This
, dwOptions
);
225 if(!This
->reported_result
)
228 IInternetProtocol_Terminate(This
->protocol
, 0);
230 set_binding_sink(PROTOCOL(This
), NULL
);
232 if(This
->bind_info
) {
233 IInternetBindInfo_Release(This
->bind_info
);
234 This
->bind_info
= NULL
;
240 static HRESULT WINAPI
BindProtocol_Suspend(IInternetProtocol
*iface
)
242 BindProtocol
*This
= PROTOCOL_THIS(iface
);
243 FIXME("(%p)\n", This
);
247 static HRESULT WINAPI
BindProtocol_Resume(IInternetProtocol
*iface
)
249 BindProtocol
*This
= PROTOCOL_THIS(iface
);
250 FIXME("(%p)\n", This
);
254 static HRESULT WINAPI
BindProtocol_Read(IInternetProtocol
*iface
, void *pv
,
255 ULONG cb
, ULONG
*pcbRead
)
257 BindProtocol
*This
= PROTOCOL_THIS(iface
);
261 TRACE("(%p)->(%p %u %p)\n", This
, pv
, cb
, pcbRead
);
263 hres
= IInternetProtocol_Read(This
->protocol
, pv
, cb
, &read
);
269 static HRESULT WINAPI
BindProtocol_Seek(IInternetProtocol
*iface
, LARGE_INTEGER dlibMove
,
270 DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
272 BindProtocol
*This
= PROTOCOL_THIS(iface
);
273 FIXME("(%p)->(%d %d %p)\n", This
, dlibMove
.u
.LowPart
, dwOrigin
, plibNewPosition
);
277 static HRESULT WINAPI
BindProtocol_LockRequest(IInternetProtocol
*iface
, DWORD dwOptions
)
279 BindProtocol
*This
= PROTOCOL_THIS(iface
);
281 TRACE("(%p)->(%08x)\n", This
, dwOptions
);
283 return IInternetProtocol_LockRequest(This
->protocol
, dwOptions
);
286 static HRESULT WINAPI
BindProtocol_UnlockRequest(IInternetProtocol
*iface
)
288 BindProtocol
*This
= PROTOCOL_THIS(iface
);
290 TRACE("(%p)\n", This
);
292 return IInternetProtocol_UnlockRequest(This
->protocol
);
295 void set_binding_sink(IInternetProtocol
*bind_protocol
, IInternetProtocolSink
*sink
)
297 BindProtocol
*This
= PROTOCOL_THIS(bind_protocol
);
298 IInternetProtocolSink
*prev_sink
;
299 IServiceProvider
*service_provider
= NULL
;
302 IInternetProtocolSink_AddRef(sink
);
303 prev_sink
= InterlockedExchangePointer((void**)&This
->protocol_sink
, sink
);
305 IInternetProtocolSink_Release(prev_sink
);
308 IInternetProtocolSink_QueryInterface(sink
, &IID_IServiceProvider
, (void**)&service_provider
);
309 service_provider
= InterlockedExchangePointer((void**)&This
->service_provider
, service_provider
);
311 IServiceProvider_Release(service_provider
);
314 IWinInetInfo
*get_wininet_info(IInternetProtocol
*bind_protocol
)
316 BindProtocol
*This
= PROTOCOL_THIS(bind_protocol
);
318 return This
->wininet_info
;
323 static const IInternetProtocolVtbl BindProtocolVtbl
= {
324 BindProtocol_QueryInterface
,
326 BindProtocol_Release
,
328 BindProtocol_Continue
,
330 BindProtocol_Terminate
,
331 BindProtocol_Suspend
,
335 BindProtocol_LockRequest
,
336 BindProtocol_UnlockRequest
339 #define BINDINFO_THIS(iface) DEFINE_THIS(BindProtocol, InternetBindInfo, iface)
341 static HRESULT WINAPI
BindInfo_QueryInterface(IInternetBindInfo
*iface
,
342 REFIID riid
, void **ppv
)
344 BindProtocol
*This
= BINDINFO_THIS(iface
);
345 return IInternetProtocol_QueryInterface(PROTOCOL(This
), riid
, ppv
);
348 static ULONG WINAPI
BindInfo_AddRef(IInternetBindInfo
*iface
)
350 BindProtocol
*This
= BINDINFO_THIS(iface
);
351 return IBinding_AddRef(PROTOCOL(This
));
354 static ULONG WINAPI
BindInfo_Release(IInternetBindInfo
*iface
)
356 BindProtocol
*This
= BINDINFO_THIS(iface
);
357 return IBinding_Release(PROTOCOL(This
));
360 static HRESULT WINAPI
BindInfo_GetBindInfo(IInternetBindInfo
*iface
,
361 DWORD
*grfBINDF
, BINDINFO
*pbindinfo
)
363 BindProtocol
*This
= BINDINFO_THIS(iface
);
366 TRACE("(%p)->(%p %p)\n", This
, grfBINDF
, pbindinfo
);
368 hres
= IInternetBindInfo_GetBindInfo(This
->bind_info
, grfBINDF
, pbindinfo
);
370 WARN("GetBindInfo failed: %08x\n", hres
);
374 *grfBINDF
|= BINDF_FROMURLMON
;
378 static HRESULT WINAPI
BindInfo_GetBindString(IInternetBindInfo
*iface
,
379 ULONG ulStringType
, LPOLESTR
*ppwzStr
, ULONG cEl
, ULONG
*pcElFetched
)
381 BindProtocol
*This
= BINDINFO_THIS(iface
);
383 TRACE("(%p)->(%d %p %d %p)\n", This
, ulStringType
, ppwzStr
, cEl
, pcElFetched
);
385 return IInternetBindInfo_GetBindString(This
->bind_info
, ulStringType
, ppwzStr
, cEl
, pcElFetched
);
390 static const IInternetBindInfoVtbl InternetBindInfoVtbl
= {
391 BindInfo_QueryInterface
,
394 BindInfo_GetBindInfo
,
395 BindInfo_GetBindString
398 #define PRIORITY_THIS(iface) DEFINE_THIS(BindProtocol, InternetPriority, iface)
400 static HRESULT WINAPI
InternetPriority_QueryInterface(IInternetPriority
*iface
,
401 REFIID riid
, void **ppv
)
403 BindProtocol
*This
= PRIORITY_THIS(iface
);
404 return IInternetProtocol_QueryInterface(PROTOCOL(This
), riid
, ppv
);
407 static ULONG WINAPI
InternetPriority_AddRef(IInternetPriority
*iface
)
409 BindProtocol
*This
= PRIORITY_THIS(iface
);
410 return IInternetProtocol_AddRef(PROTOCOL(This
));
413 static ULONG WINAPI
InternetPriority_Release(IInternetPriority
*iface
)
415 BindProtocol
*This
= PRIORITY_THIS(iface
);
416 return IInternetProtocol_Release(PROTOCOL(This
));
419 static HRESULT WINAPI
InternetPriority_SetPriority(IInternetPriority
*iface
, LONG nPriority
)
421 BindProtocol
*This
= PRIORITY_THIS(iface
);
423 TRACE("(%p)->(%d)\n", This
, nPriority
);
425 This
->priority
= nPriority
;
429 static HRESULT WINAPI
InternetPriority_GetPriority(IInternetPriority
*iface
, LONG
*pnPriority
)
431 BindProtocol
*This
= PRIORITY_THIS(iface
);
433 TRACE("(%p)->(%p)\n", This
, pnPriority
);
435 *pnPriority
= This
->priority
;
441 static const IInternetPriorityVtbl InternetPriorityVtbl
= {
442 InternetPriority_QueryInterface
,
443 InternetPriority_AddRef
,
444 InternetPriority_Release
,
445 InternetPriority_SetPriority
,
446 InternetPriority_GetPriority
450 #define PROTSINK_THIS(iface) DEFINE_THIS(BindProtocol, InternetProtocolSink, iface)
452 static HRESULT WINAPI
BPInternetProtocolSink_QueryInterface(IInternetProtocolSink
*iface
,
453 REFIID riid
, void **ppv
)
455 BindProtocol
*This
= PROTSINK_THIS(iface
);
456 return IInternetProtocol_QueryInterface(PROTOCOL(This
), riid
, ppv
);
459 static ULONG WINAPI
BPInternetProtocolSink_AddRef(IInternetProtocolSink
*iface
)
461 BindProtocol
*This
= PROTSINK_THIS(iface
);
462 return IInternetProtocol_AddRef(PROTOCOL(This
));
465 static ULONG WINAPI
BPInternetProtocolSink_Release(IInternetProtocolSink
*iface
)
467 BindProtocol
*This
= PROTSINK_THIS(iface
);
468 return IInternetProtocol_Release(PROTOCOL(This
));
471 static HRESULT WINAPI
BPInternetProtocolSink_Switch(IInternetProtocolSink
*iface
,
472 PROTOCOLDATA
*pProtocolData
)
474 BindProtocol
*This
= PROTSINK_THIS(iface
);
476 TRACE("(%p)->(%p)\n", This
, pProtocolData
);
478 TRACE("flags %x state %x data %p cb %u\n", pProtocolData
->grfFlags
, pProtocolData
->dwState
,
479 pProtocolData
->pData
, pProtocolData
->cbData
);
481 if(!This
->protocol_sink
) {
482 IInternetProtocol_Continue(This
->protocol
, pProtocolData
);
486 return IInternetProtocolSink_Switch(This
->protocol_sink
, pProtocolData
);
489 static HRESULT WINAPI
BPInternetProtocolSink_ReportProgress(IInternetProtocolSink
*iface
,
490 ULONG ulStatusCode
, LPCWSTR szStatusText
)
492 BindProtocol
*This
= PROTSINK_THIS(iface
);
494 TRACE("(%p)->(%u %s)\n", This
, ulStatusCode
, debugstr_w(szStatusText
));
496 switch(ulStatusCode
) {
497 case BINDSTATUS_FINDINGRESOURCE
:
498 case BINDSTATUS_CONNECTING
:
499 case BINDSTATUS_BEGINDOWNLOADDATA
:
500 case BINDSTATUS_SENDINGREQUEST
:
501 case BINDSTATUS_CACHEFILENAMEAVAILABLE
:
502 case BINDSTATUS_DIRECTBIND
:
503 case BINDSTATUS_ACCEPTRANGES
:
504 case BINDSTATUS_MIMETYPEAVAILABLE
:
505 if(!This
->protocol_sink
)
507 return IInternetProtocolSink_ReportProgress(This
->protocol_sink
,
508 ulStatusCode
, szStatusText
);
510 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE
:
511 if(!This
->protocol_sink
)
513 return IInternetProtocolSink_ReportProgress(This
->protocol_sink
,
514 This
->from_urlmon
? BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE
: BINDSTATUS_MIMETYPEAVAILABLE
,
517 FIXME("unsupported ulStatusCode %u\n", ulStatusCode
);
523 static HRESULT WINAPI
BPInternetProtocolSink_ReportData(IInternetProtocolSink
*iface
,
524 DWORD grfBSCF
, ULONG ulProgress
, ULONG ulProgressMax
)
526 BindProtocol
*This
= PROTSINK_THIS(iface
);
528 TRACE("(%p)->(%d %u %u)\n", This
, grfBSCF
, ulProgress
, ulProgressMax
);
530 if(!This
->protocol_sink
)
533 return IInternetProtocolSink_ReportData(This
->protocol_sink
, grfBSCF
, ulProgress
, ulProgressMax
);
536 static HRESULT WINAPI
BPInternetProtocolSink_ReportResult(IInternetProtocolSink
*iface
,
537 HRESULT hrResult
, DWORD dwError
, LPCWSTR szResult
)
539 BindProtocol
*This
= PROTSINK_THIS(iface
);
541 TRACE("(%p)->(%08x %d %s)\n", This
, hrResult
, dwError
, debugstr_w(szResult
));
543 if(!This
->protocol_sink
)
546 This
->reported_result
= TRUE
;
548 return IInternetProtocolSink_ReportResult(This
->protocol_sink
, hrResult
, dwError
, szResult
);
553 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl
= {
554 BPInternetProtocolSink_QueryInterface
,
555 BPInternetProtocolSink_AddRef
,
556 BPInternetProtocolSink_Release
,
557 BPInternetProtocolSink_Switch
,
558 BPInternetProtocolSink_ReportProgress
,
559 BPInternetProtocolSink_ReportData
,
560 BPInternetProtocolSink_ReportResult
563 #define SERVPROV_THIS(iface) DEFINE_THIS(BindProtocol, ServiceProvider, iface)
565 static HRESULT WINAPI
BPServiceProvider_QueryInterface(IServiceProvider
*iface
,
566 REFIID riid
, void **ppv
)
568 BindProtocol
*This
= SERVPROV_THIS(iface
);
569 return IInternetProtocol_QueryInterface(PROTOCOL(This
), riid
, ppv
);
572 static ULONG WINAPI
BPServiceProvider_AddRef(IServiceProvider
*iface
)
574 BindProtocol
*This
= SERVPROV_THIS(iface
);
575 return IInternetProtocol_AddRef(PROTOCOL(This
));
578 static ULONG WINAPI
BPServiceProvider_Release(IServiceProvider
*iface
)
580 BindProtocol
*This
= SERVPROV_THIS(iface
);
581 return IInternetProtocol_Release(PROTOCOL(This
));
584 static HRESULT WINAPI
BPServiceProvider_QueryService(IServiceProvider
*iface
,
585 REFGUID guidService
, REFIID riid
, void **ppv
)
587 BindProtocol
*This
= SERVPROV_THIS(iface
);
589 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_guid(guidService
), debugstr_guid(riid
), ppv
);
591 if(!This
->service_provider
)
592 return E_NOINTERFACE
;
594 return IServiceProvider_QueryService(This
->service_provider
, guidService
, riid
, ppv
);
599 static const IServiceProviderVtbl ServiceProviderVtbl
= {
600 BPServiceProvider_QueryInterface
,
601 BPServiceProvider_AddRef
,
602 BPServiceProvider_Release
,
603 BPServiceProvider_QueryService
606 HRESULT
create_binding_protocol(LPCWSTR url
, BOOL from_urlmon
, IInternetProtocol
**protocol
)
608 BindProtocol
*ret
= heap_alloc_zero(sizeof(BindProtocol
));
610 ret
->lpInternetProtocolVtbl
= &BindProtocolVtbl
;
611 ret
->lpInternetBindInfoVtbl
= &InternetBindInfoVtbl
;
612 ret
->lpInternetPriorityVtbl
= &InternetPriorityVtbl
;
613 ret
->lpServiceProviderVtbl
= &ServiceProviderVtbl
;
614 ret
->lpInternetProtocolSinkVtbl
= &InternetProtocolSinkVtbl
;
617 ret
->from_urlmon
= from_urlmon
;
621 *protocol
= PROTOCOL(ret
);