2 * Copyright 2008 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 IBindStatusCallbackVtbl
*lpBindStatusCallbackVtbl
;
26 const IServiceProviderVtbl
*lpServiceProviderVtbl
;
30 IBindStatusCallback
*callback
;
35 #define STATUSCLB(x) ((IBindStatusCallback*) &(x)->lpBindStatusCallbackVtbl)
36 #define SERVPROV(x) ((IServiceProvider*) &(x)->lpServiceProviderVtbl)
38 #define STATUSCLB_THIS(iface) DEFINE_THIS(DownloadBSC, BindStatusCallback, iface)
40 static HRESULT WINAPI
DownloadBSC_QueryInterface(IBindStatusCallback
*iface
,
41 REFIID riid
, void **ppv
)
43 DownloadBSC
*This
= STATUSCLB_THIS(iface
);
47 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
48 TRACE("(%p)->(IID_IUnknown, %p)\n", This
, ppv
);
49 *ppv
= STATUSCLB(This
);
50 }else if(IsEqualGUID(&IID_IBindStatusCallback
, riid
)) {
51 TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This
, ppv
);
52 *ppv
= STATUSCLB(This
);
53 }else if(IsEqualGUID(&IID_IServiceProvider
, riid
)) {
54 TRACE("(%p)->(IID_IServiceProvider, %p)\n", This
, ppv
);
55 *ppv
= SERVPROV(This
);
59 IBindStatusCallback_AddRef((IUnknown
*)*ppv
);
63 TRACE("Unsupported riid = %s\n", debugstr_guid(riid
));
67 static ULONG WINAPI
DownloadBSC_AddRef(IBindStatusCallback
*iface
)
69 DownloadBSC
*This
= STATUSCLB_THIS(iface
);
70 LONG ref
= InterlockedIncrement(&This
->ref
);
72 TRACE("(%p) ref = %d\n", This
, ref
);
77 static ULONG WINAPI
DownloadBSC_Release(IBindStatusCallback
*iface
)
79 DownloadBSC
*This
= STATUSCLB_THIS(iface
);
80 LONG ref
= InterlockedDecrement(&This
->ref
);
82 TRACE("(%p) ref = %d\n", This
, ref
);
86 IBindStatusCallback_Release(This
->callback
);
87 heap_free(This
->file_name
);
88 heap_free(This
->cache_file
);
95 static HRESULT WINAPI
DownloadBSC_OnStartBinding(IBindStatusCallback
*iface
,
96 DWORD dwReserved
, IBinding
*pbind
)
98 DownloadBSC
*This
= STATUSCLB_THIS(iface
);
100 TRACE("(%p)->(%d %p)\n", This
, dwReserved
, pbind
);
103 IBindStatusCallback_OnStartBinding(This
->callback
, dwReserved
, pbind
);
108 static HRESULT WINAPI
DownloadBSC_GetPriority(IBindStatusCallback
*iface
, LONG
*pnPriority
)
110 DownloadBSC
*This
= STATUSCLB_THIS(iface
);
111 FIXME("(%p)->(%p)\n", This
, pnPriority
);
115 static HRESULT WINAPI
DownloadBSC_OnLowResource(IBindStatusCallback
*iface
, DWORD reserved
)
117 DownloadBSC
*This
= STATUSCLB_THIS(iface
);
118 FIXME("(%p)->(%d)\n", This
, reserved
);
122 static HRESULT
on_progress(DownloadBSC
*This
, ULONG progress
, ULONG progress_max
, ULONG status_code
, LPCWSTR status_text
)
129 hres
= IBindStatusCallback_OnProgress(This
->callback
, progress
, progress_max
, status_code
, status_text
);
133 static HRESULT WINAPI
DownloadBSC_OnProgress(IBindStatusCallback
*iface
, ULONG ulProgress
,
134 ULONG ulProgressMax
, ULONG ulStatusCode
, LPCWSTR szStatusText
)
136 DownloadBSC
*This
= STATUSCLB_THIS(iface
);
139 TRACE("%p)->(%u %u %u %s)\n", This
, ulProgress
, ulProgressMax
, ulStatusCode
,
140 debugstr_w(szStatusText
));
142 switch(ulStatusCode
) {
143 case BINDSTATUS_CONNECTING
:
144 case BINDSTATUS_BEGINDOWNLOADDATA
:
145 case BINDSTATUS_DOWNLOADINGDATA
:
146 case BINDSTATUS_ENDDOWNLOADDATA
:
147 case BINDSTATUS_SENDINGREQUEST
:
148 case BINDSTATUS_MIMETYPEAVAILABLE
:
149 hres
= on_progress(This
, ulProgress
, ulProgressMax
, ulStatusCode
, szStatusText
);
152 case BINDSTATUS_CACHEFILENAMEAVAILABLE
:
153 hres
= on_progress(This
, ulProgress
, ulProgressMax
, ulStatusCode
, szStatusText
);
154 This
->cache_file
= heap_strdupW(szStatusText
);
157 case BINDSTATUS_FINDINGRESOURCE
: /* FIXME */
161 FIXME("Unsupported status %u\n", ulStatusCode
);
167 static HRESULT WINAPI
DownloadBSC_OnStopBinding(IBindStatusCallback
*iface
,
168 HRESULT hresult
, LPCWSTR szError
)
170 DownloadBSC
*This
= STATUSCLB_THIS(iface
);
172 TRACE("(%p)->(%08x %s)\n", This
, hresult
, debugstr_w(szError
));
174 if(This
->file_name
) {
175 if(This
->cache_file
) {
178 b
= CopyFileW(This
->cache_file
, This
->file_name
, FALSE
);
180 FIXME("CopyFile failed: %u\n", GetLastError());
182 FIXME("No cache file\n");
187 IBindStatusCallback_OnStopBinding(This
->callback
, hresult
, szError
);
192 static HRESULT WINAPI
DownloadBSC_GetBindInfo(IBindStatusCallback
*iface
,
193 DWORD
*grfBINDF
, BINDINFO
*pbindinfo
)
195 DownloadBSC
*This
= STATUSCLB_THIS(iface
);
198 TRACE("(%p)->(%p %p)\n", This
, grfBINDF
, pbindinfo
);
204 memset(&bindinfo
, 0, sizeof(bindinfo
));
205 bindinfo
.cbSize
= sizeof(bindinfo
);
207 hres
= IBindStatusCallback_GetBindInfo(This
->callback
, &bindf
, &bindinfo
);
209 ReleaseBindInfo(&bindinfo
);
212 *grfBINDF
= BINDF_PULLDATA
| BINDF_NEEDFILE
| (bindf
& BINDF_ENFORCERESTRICTED
);
216 static HRESULT WINAPI
DownloadBSC_OnDataAvailable(IBindStatusCallback
*iface
,
217 DWORD grfBSCF
, DWORD dwSize
, FORMATETC
*pformatetc
, STGMEDIUM
*pstgmed
)
219 DownloadBSC
*This
= STATUSCLB_THIS(iface
);
221 TRACE("(%p)->(%08x %d %p %p)\n", This
, grfBSCF
, dwSize
, pformatetc
, pstgmed
);
226 static HRESULT WINAPI
DownloadBSC_OnObjectAvailable(IBindStatusCallback
*iface
,
227 REFIID riid
, IUnknown
*punk
)
229 DownloadBSC
*This
= STATUSCLB_THIS(iface
);
230 FIXME("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), punk
);
234 #undef STATUSCLB_THIS
236 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl
= {
237 DownloadBSC_QueryInterface
,
240 DownloadBSC_OnStartBinding
,
241 DownloadBSC_GetPriority
,
242 DownloadBSC_OnLowResource
,
243 DownloadBSC_OnProgress
,
244 DownloadBSC_OnStopBinding
,
245 DownloadBSC_GetBindInfo
,
246 DownloadBSC_OnDataAvailable
,
247 DownloadBSC_OnObjectAvailable
250 #define SERVPROV_THIS(iface) DEFINE_THIS(DownloadBSC, ServiceProvider, iface)
252 static HRESULT WINAPI
DwlServiceProvider_QueryInterface(IServiceProvider
*iface
,
253 REFIID riid
, void **ppv
)
255 DownloadBSC
*This
= SERVPROV_THIS(iface
);
256 return IBindStatusCallback_QueryInterface(STATUSCLB(This
), riid
, ppv
);
259 static ULONG WINAPI
DwlServiceProvider_AddRef(IServiceProvider
*iface
)
261 DownloadBSC
*This
= SERVPROV_THIS(iface
);
262 return IBindStatusCallback_AddRef(STATUSCLB(This
));
265 static ULONG WINAPI
DwlServiceProvider_Release(IServiceProvider
*iface
)
267 DownloadBSC
*This
= SERVPROV_THIS(iface
);
268 return IBindStatusCallback_Release(STATUSCLB(This
));
271 static HRESULT WINAPI
DwlServiceProvider_QueryService(IServiceProvider
*iface
,
272 REFGUID guidService
, REFIID riid
, void **ppv
)
274 DownloadBSC
*This
= SERVPROV_THIS(iface
);
275 IServiceProvider
*serv_prov
;
278 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_guid(guidService
), debugstr_guid(riid
), ppv
);
281 return E_NOINTERFACE
;
283 hres
= IBindStatusCallback_QueryInterface(This
->callback
, riid
, ppv
);
287 hres
= IBindStatusCallback_QueryInterface(This
->callback
, &IID_IServiceProvider
, (void**)&serv_prov
);
288 if(SUCCEEDED(hres
)) {
289 hres
= IServiceProvider_QueryService(serv_prov
, guidService
, riid
, ppv
);
290 IServiceProvider_Release(serv_prov
);
294 return E_NOINTERFACE
;
299 static const IServiceProviderVtbl ServiceProviderVtbl
= {
300 DwlServiceProvider_QueryInterface
,
301 DwlServiceProvider_AddRef
,
302 DwlServiceProvider_Release
,
303 DwlServiceProvider_QueryService
306 static HRESULT
DownloadBSC_Create(IBindStatusCallback
*callback
, LPCWSTR file_name
, IBindStatusCallback
**ret_callback
)
308 DownloadBSC
*ret
= heap_alloc(sizeof(*ret
));
310 ret
->lpBindStatusCallbackVtbl
= &BindStatusCallbackVtbl
;
311 ret
->lpServiceProviderVtbl
= &ServiceProviderVtbl
;
313 ret
->file_name
= heap_strdupW(file_name
);
314 ret
->cache_file
= NULL
;
317 IBindStatusCallback_AddRef(callback
);
318 ret
->callback
= callback
;
320 *ret_callback
= STATUSCLB(ret
);
324 HRESULT
create_default_callback(IBindStatusCallback
**ret
)
326 IBindStatusCallback
*callback
;
329 hres
= DownloadBSC_Create(NULL
, NULL
, &callback
);
333 hres
= wrap_callback(callback
, ret
);
334 IBindStatusCallback_Release(callback
);
338 /***********************************************************************
339 * URLDownloadToFileW (URLMON.@)
341 * Downloads URL szURL to file szFileName and call lpfnCB callback to
345 * pCaller [I] controlling IUnknown interface.
346 * szURL [I] URL of the file to download
347 * szFileName [I] file name to store the content of the URL
348 * dwReserved [I] reserved - set to 0
349 * lpfnCB [I] callback for progress report
354 HRESULT WINAPI
URLDownloadToFileW(LPUNKNOWN pCaller
, LPCWSTR szURL
, LPCWSTR szFileName
,
355 DWORD dwReserved
, LPBINDSTATUSCALLBACK lpfnCB
)
357 IBindStatusCallback
*callback
;
363 TRACE("(%p %s %s %d %p)\n", pCaller
, debugstr_w(szURL
), debugstr_w(szFileName
), dwReserved
, lpfnCB
);
366 FIXME("pCaller not supported\n");
368 hres
= DownloadBSC_Create(lpfnCB
, szFileName
, &callback
);
372 hres
= CreateAsyncBindCtx(0, callback
, NULL
, &bindctx
);
373 IBindStatusCallback_Release(callback
);
377 hres
= CreateURLMoniker(NULL
, szURL
, &mon
);
379 IBindCtx_Release(bindctx
);
383 hres
= IMoniker_BindToStorage(mon
, bindctx
, NULL
, &IID_IUnknown
, (void**)&unk
);
384 IMoniker_Release(mon
);
385 IBindCtx_Release(bindctx
);
388 IUnknown_Release(unk
);
390 return hres
== MK_S_ASYNCHRONOUS
? S_OK
: hres
;
393 /***********************************************************************
394 * URLDownloadToFileA (URLMON.@)
396 * Downloads URL szURL to rile szFileName and call lpfnCB callback to
400 * pCaller [I] controlling IUnknown interface.
401 * szURL [I] URL of the file to download
402 * szFileName [I] file name to store the content of the URL
403 * dwReserved [I] reserved - set to 0
404 * lpfnCB [I] callback for progress report
409 HRESULT WINAPI
URLDownloadToFileA(LPUNKNOWN pCaller
, LPCSTR szURL
, LPCSTR szFileName
, DWORD dwReserved
,
410 LPBINDSTATUSCALLBACK lpfnCB
)
412 LPWSTR urlW
, file_nameW
;
415 TRACE("(%p %s %s %d %p)\n", pCaller
, debugstr_a(szURL
), debugstr_a(szFileName
), dwReserved
, lpfnCB
);
417 urlW
= heap_strdupAtoW(szURL
);
418 file_nameW
= heap_strdupAtoW(szFileName
);
420 hres
= URLDownloadToFileW(pCaller
, urlW
, file_nameW
, dwReserved
, lpfnCB
);
423 heap_free(file_nameW
);