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 IBindStatusCallback IBindStatusCallback_iface
;
26 IServiceProvider IServiceProvider_iface
;
30 IBindStatusCallback
*callback
;
35 static inline DownloadBSC
*impl_from_IBindStatusCallback(IBindStatusCallback
*iface
)
37 return CONTAINING_RECORD(iface
, DownloadBSC
, IBindStatusCallback_iface
);
40 static inline DownloadBSC
*impl_from_IServiceProvider(IServiceProvider
*iface
)
42 return CONTAINING_RECORD(iface
, DownloadBSC
, IServiceProvider_iface
);
45 static HRESULT WINAPI
DownloadBSC_QueryInterface(IBindStatusCallback
*iface
,
46 REFIID riid
, void **ppv
)
48 DownloadBSC
*This
= impl_from_IBindStatusCallback(iface
);
52 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
53 TRACE("(%p)->(IID_IUnknown, %p)\n", This
, ppv
);
54 *ppv
= &This
->IBindStatusCallback_iface
;
55 }else if(IsEqualGUID(&IID_IBindStatusCallback
, riid
)) {
56 TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This
, ppv
);
57 *ppv
= &This
->IBindStatusCallback_iface
;
58 }else if(IsEqualGUID(&IID_IServiceProvider
, riid
)) {
59 TRACE("(%p)->(IID_IServiceProvider, %p)\n", This
, ppv
);
60 *ppv
= &This
->IServiceProvider_iface
;
64 IBindStatusCallback_AddRef((IUnknown
*)*ppv
);
68 TRACE("Unsupported riid = %s\n", debugstr_guid(riid
));
72 static ULONG WINAPI
DownloadBSC_AddRef(IBindStatusCallback
*iface
)
74 DownloadBSC
*This
= impl_from_IBindStatusCallback(iface
);
75 LONG ref
= InterlockedIncrement(&This
->ref
);
77 TRACE("(%p) ref = %d\n", This
, ref
);
82 static ULONG WINAPI
DownloadBSC_Release(IBindStatusCallback
*iface
)
84 DownloadBSC
*This
= impl_from_IBindStatusCallback(iface
);
85 LONG ref
= InterlockedDecrement(&This
->ref
);
87 TRACE("(%p) ref = %d\n", This
, ref
);
91 IBindStatusCallback_Release(This
->callback
);
92 heap_free(This
->file_name
);
93 heap_free(This
->cache_file
);
100 static HRESULT WINAPI
DownloadBSC_OnStartBinding(IBindStatusCallback
*iface
,
101 DWORD dwReserved
, IBinding
*pbind
)
103 DownloadBSC
*This
= impl_from_IBindStatusCallback(iface
);
105 TRACE("(%p)->(%d %p)\n", This
, dwReserved
, pbind
);
108 IBindStatusCallback_OnStartBinding(This
->callback
, dwReserved
, pbind
);
113 static HRESULT WINAPI
DownloadBSC_GetPriority(IBindStatusCallback
*iface
, LONG
*pnPriority
)
115 DownloadBSC
*This
= impl_from_IBindStatusCallback(iface
);
116 FIXME("(%p)->(%p)\n", This
, pnPriority
);
120 static HRESULT WINAPI
DownloadBSC_OnLowResource(IBindStatusCallback
*iface
, DWORD reserved
)
122 DownloadBSC
*This
= impl_from_IBindStatusCallback(iface
);
123 FIXME("(%p)->(%d)\n", This
, reserved
);
127 static HRESULT
on_progress(DownloadBSC
*This
, ULONG progress
, ULONG progress_max
, ULONG status_code
, LPCWSTR status_text
)
134 hres
= IBindStatusCallback_OnProgress(This
->callback
, progress
, progress_max
, status_code
, status_text
);
138 static HRESULT WINAPI
DownloadBSC_OnProgress(IBindStatusCallback
*iface
, ULONG ulProgress
,
139 ULONG ulProgressMax
, ULONG ulStatusCode
, LPCWSTR szStatusText
)
141 DownloadBSC
*This
= impl_from_IBindStatusCallback(iface
);
144 TRACE("%p)->(%u %u %u %s)\n", This
, ulProgress
, ulProgressMax
, ulStatusCode
,
145 debugstr_w(szStatusText
));
147 switch(ulStatusCode
) {
148 case BINDSTATUS_CONNECTING
:
149 case BINDSTATUS_BEGINDOWNLOADDATA
:
150 case BINDSTATUS_DOWNLOADINGDATA
:
151 case BINDSTATUS_ENDDOWNLOADDATA
:
152 case BINDSTATUS_SENDINGREQUEST
:
153 case BINDSTATUS_MIMETYPEAVAILABLE
:
154 hres
= on_progress(This
, ulProgress
, ulProgressMax
, ulStatusCode
, szStatusText
);
157 case BINDSTATUS_CACHEFILENAMEAVAILABLE
:
158 hres
= on_progress(This
, ulProgress
, ulProgressMax
, ulStatusCode
, szStatusText
);
159 This
->cache_file
= heap_strdupW(szStatusText
);
162 case BINDSTATUS_FINDINGRESOURCE
: /* FIXME */
166 FIXME("Unsupported status %u\n", ulStatusCode
);
172 static HRESULT WINAPI
DownloadBSC_OnStopBinding(IBindStatusCallback
*iface
,
173 HRESULT hresult
, LPCWSTR szError
)
175 DownloadBSC
*This
= impl_from_IBindStatusCallback(iface
);
177 TRACE("(%p)->(%08x %s)\n", This
, hresult
, debugstr_w(szError
));
179 if(This
->file_name
) {
180 if(This
->cache_file
) {
183 b
= CopyFileW(This
->cache_file
, This
->file_name
, FALSE
);
185 FIXME("CopyFile failed: %u\n", GetLastError());
187 FIXME("No cache file\n");
192 IBindStatusCallback_OnStopBinding(This
->callback
, hresult
, szError
);
197 static HRESULT WINAPI
DownloadBSC_GetBindInfo(IBindStatusCallback
*iface
,
198 DWORD
*grfBINDF
, BINDINFO
*pbindinfo
)
200 DownloadBSC
*This
= impl_from_IBindStatusCallback(iface
);
203 TRACE("(%p)->(%p %p)\n", This
, grfBINDF
, pbindinfo
);
209 memset(&bindinfo
, 0, sizeof(bindinfo
));
210 bindinfo
.cbSize
= sizeof(bindinfo
);
212 hres
= IBindStatusCallback_GetBindInfo(This
->callback
, &bindf
, &bindinfo
);
214 ReleaseBindInfo(&bindinfo
);
217 *grfBINDF
= BINDF_PULLDATA
| BINDF_NEEDFILE
| (bindf
& BINDF_ENFORCERESTRICTED
);
221 static HRESULT WINAPI
DownloadBSC_OnDataAvailable(IBindStatusCallback
*iface
,
222 DWORD grfBSCF
, DWORD dwSize
, FORMATETC
*pformatetc
, STGMEDIUM
*pstgmed
)
224 DownloadBSC
*This
= impl_from_IBindStatusCallback(iface
);
226 TRACE("(%p)->(%08x %d %p %p)\n", This
, grfBSCF
, dwSize
, pformatetc
, pstgmed
);
231 static HRESULT WINAPI
DownloadBSC_OnObjectAvailable(IBindStatusCallback
*iface
,
232 REFIID riid
, IUnknown
*punk
)
234 DownloadBSC
*This
= impl_from_IBindStatusCallback(iface
);
235 FIXME("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), punk
);
239 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl
= {
240 DownloadBSC_QueryInterface
,
243 DownloadBSC_OnStartBinding
,
244 DownloadBSC_GetPriority
,
245 DownloadBSC_OnLowResource
,
246 DownloadBSC_OnProgress
,
247 DownloadBSC_OnStopBinding
,
248 DownloadBSC_GetBindInfo
,
249 DownloadBSC_OnDataAvailable
,
250 DownloadBSC_OnObjectAvailable
253 static HRESULT WINAPI
DwlServiceProvider_QueryInterface(IServiceProvider
*iface
,
254 REFIID riid
, void **ppv
)
256 DownloadBSC
*This
= impl_from_IServiceProvider(iface
);
257 return IBindStatusCallback_QueryInterface(&This
->IBindStatusCallback_iface
, riid
, ppv
);
260 static ULONG WINAPI
DwlServiceProvider_AddRef(IServiceProvider
*iface
)
262 DownloadBSC
*This
= impl_from_IServiceProvider(iface
);
263 return IBindStatusCallback_AddRef(&This
->IBindStatusCallback_iface
);
266 static ULONG WINAPI
DwlServiceProvider_Release(IServiceProvider
*iface
)
268 DownloadBSC
*This
= impl_from_IServiceProvider(iface
);
269 return IBindStatusCallback_Release(&This
->IBindStatusCallback_iface
);
272 static HRESULT WINAPI
DwlServiceProvider_QueryService(IServiceProvider
*iface
,
273 REFGUID guidService
, REFIID riid
, void **ppv
)
275 DownloadBSC
*This
= impl_from_IServiceProvider(iface
);
276 IServiceProvider
*serv_prov
;
279 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_guid(guidService
), debugstr_guid(riid
), ppv
);
282 return E_NOINTERFACE
;
284 hres
= IBindStatusCallback_QueryInterface(This
->callback
, riid
, ppv
);
288 hres
= IBindStatusCallback_QueryInterface(This
->callback
, &IID_IServiceProvider
, (void**)&serv_prov
);
289 if(SUCCEEDED(hres
)) {
290 hres
= IServiceProvider_QueryService(serv_prov
, guidService
, riid
, ppv
);
291 IServiceProvider_Release(serv_prov
);
295 return E_NOINTERFACE
;
298 static const IServiceProviderVtbl ServiceProviderVtbl
= {
299 DwlServiceProvider_QueryInterface
,
300 DwlServiceProvider_AddRef
,
301 DwlServiceProvider_Release
,
302 DwlServiceProvider_QueryService
305 static HRESULT
DownloadBSC_Create(IBindStatusCallback
*callback
, LPCWSTR file_name
, IBindStatusCallback
**ret_callback
)
307 DownloadBSC
*ret
= heap_alloc(sizeof(*ret
));
309 ret
->IBindStatusCallback_iface
.lpVtbl
= &BindStatusCallbackVtbl
;
310 ret
->IServiceProvider_iface
.lpVtbl
= &ServiceProviderVtbl
;
312 ret
->file_name
= heap_strdupW(file_name
);
313 ret
->cache_file
= NULL
;
316 IBindStatusCallback_AddRef(callback
);
317 ret
->callback
= callback
;
319 *ret_callback
= &ret
->IBindStatusCallback_iface
;
323 HRESULT
create_default_callback(IBindStatusCallback
**ret
)
325 IBindStatusCallback
*callback
;
328 hres
= DownloadBSC_Create(NULL
, NULL
, &callback
);
332 hres
= wrap_callback(callback
, ret
);
333 IBindStatusCallback_Release(callback
);
337 /***********************************************************************
338 * URLDownloadToFileW (URLMON.@)
340 * Downloads URL szURL to file szFileName and call lpfnCB callback to
344 * pCaller [I] controlling IUnknown interface.
345 * szURL [I] URL of the file to download
346 * szFileName [I] file name to store the content of the URL
347 * dwReserved [I] reserved - set to 0
348 * lpfnCB [I] callback for progress report
353 HRESULT WINAPI
URLDownloadToFileW(LPUNKNOWN pCaller
, LPCWSTR szURL
, LPCWSTR szFileName
,
354 DWORD dwReserved
, LPBINDSTATUSCALLBACK lpfnCB
)
356 IBindStatusCallback
*callback
;
362 TRACE("(%p %s %s %d %p)\n", pCaller
, debugstr_w(szURL
), debugstr_w(szFileName
), dwReserved
, lpfnCB
);
365 FIXME("pCaller not supported\n");
367 hres
= DownloadBSC_Create(lpfnCB
, szFileName
, &callback
);
371 hres
= CreateAsyncBindCtx(0, callback
, NULL
, &bindctx
);
372 IBindStatusCallback_Release(callback
);
376 hres
= CreateURLMoniker(NULL
, szURL
, &mon
);
378 IBindCtx_Release(bindctx
);
382 hres
= IMoniker_BindToStorage(mon
, bindctx
, NULL
, &IID_IUnknown
, (void**)&unk
);
383 IMoniker_Release(mon
);
384 IBindCtx_Release(bindctx
);
387 IUnknown_Release(unk
);
389 return hres
== MK_S_ASYNCHRONOUS
? S_OK
: hres
;
392 /***********************************************************************
393 * URLDownloadToFileA (URLMON.@)
395 * Downloads URL szURL to rile szFileName and call lpfnCB callback to
399 * pCaller [I] controlling IUnknown interface.
400 * szURL [I] URL of the file to download
401 * szFileName [I] file name to store the content of the URL
402 * dwReserved [I] reserved - set to 0
403 * lpfnCB [I] callback for progress report
408 HRESULT WINAPI
URLDownloadToFileA(LPUNKNOWN pCaller
, LPCSTR szURL
, LPCSTR szFileName
, DWORD dwReserved
,
409 LPBINDSTATUSCALLBACK lpfnCB
)
411 LPWSTR urlW
, file_nameW
;
414 TRACE("(%p %s %s %d %p)\n", pCaller
, debugstr_a(szURL
), debugstr_a(szFileName
), dwReserved
, lpfnCB
);
416 urlW
= heap_strdupAtoW(szURL
);
417 file_nameW
= heap_strdupAtoW(szFileName
);
419 hres
= URLDownloadToFileW(pCaller
, urlW
, file_nameW
, dwReserved
, lpfnCB
);
422 heap_free(file_nameW
);