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 void 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
);
131 FIXME("OnProgress failed: %08x\n", hres
);
134 static HRESULT WINAPI
DownloadBSC_OnProgress(IBindStatusCallback
*iface
, ULONG ulProgress
,
135 ULONG ulProgressMax
, ULONG ulStatusCode
, LPCWSTR szStatusText
)
137 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 on_progress(This
, ulProgress
, ulProgressMax
, ulStatusCode
, szStatusText
);
152 case BINDSTATUS_CACHEFILENAMEAVAILABLE
:
153 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
->cache_file
) {
177 b
= CopyFileW(This
->cache_file
, This
->file_name
, FALSE
);
179 FIXME("CopyFile failed: %u\n", GetLastError());
181 FIXME("No cache file\n");
185 IBindStatusCallback_OnStopBinding(This
->callback
, hresult
, szError
);
190 static HRESULT WINAPI
DownloadBSC_GetBindInfo(IBindStatusCallback
*iface
,
191 DWORD
*grfBINDF
, BINDINFO
*pbindinfo
)
193 DownloadBSC
*This
= STATUSCLB_THIS(iface
);
196 TRACE("(%p)->(%p %p)\n", This
, grfBINDF
, pbindinfo
);
202 memset(&bindinfo
, 0, sizeof(bindinfo
));
203 bindinfo
.cbSize
= sizeof(bindinfo
);
205 hres
= IBindStatusCallback_GetBindInfo(This
->callback
, &bindf
, &bindinfo
);
207 ReleaseBindInfo(&bindinfo
);
210 *grfBINDF
= BINDF_PULLDATA
| BINDF_NEEDFILE
| (bindf
& BINDF_ENFORCERESTRICTED
);
214 static HRESULT WINAPI
DownloadBSC_OnDataAvailable(IBindStatusCallback
*iface
,
215 DWORD grfBSCF
, DWORD dwSize
, FORMATETC
*pformatetc
, STGMEDIUM
*pstgmed
)
217 DownloadBSC
*This
= STATUSCLB_THIS(iface
);
219 TRACE("(%p)->(%08x %d %p %p)\n", This
, grfBSCF
, dwSize
, pformatetc
, pstgmed
);
224 static HRESULT WINAPI
DownloadBSC_OnObjectAvailable(IBindStatusCallback
*iface
,
225 REFIID riid
, IUnknown
*punk
)
227 DownloadBSC
*This
= STATUSCLB_THIS(iface
);
228 FIXME("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), punk
);
232 #undef STATUSCLB_THIS
234 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl
= {
235 DownloadBSC_QueryInterface
,
238 DownloadBSC_OnStartBinding
,
239 DownloadBSC_GetPriority
,
240 DownloadBSC_OnLowResource
,
241 DownloadBSC_OnProgress
,
242 DownloadBSC_OnStopBinding
,
243 DownloadBSC_GetBindInfo
,
244 DownloadBSC_OnDataAvailable
,
245 DownloadBSC_OnObjectAvailable
248 #define SERVPROV_THIS(iface) DEFINE_THIS(DownloadBSC, ServiceProvider, iface)
250 static HRESULT WINAPI
DwlServiceProvider_QueryInterface(IServiceProvider
*iface
,
251 REFIID riid
, void **ppv
)
253 DownloadBSC
*This
= SERVPROV_THIS(iface
);
254 return IBindStatusCallback_QueryInterface(STATUSCLB(This
), riid
, ppv
);
257 static ULONG WINAPI
DwlServiceProvider_AddRef(IServiceProvider
*iface
)
259 DownloadBSC
*This
= SERVPROV_THIS(iface
);
260 return IBindStatusCallback_AddRef(STATUSCLB(This
));
263 static ULONG WINAPI
DwlServiceProvider_Release(IServiceProvider
*iface
)
265 DownloadBSC
*This
= SERVPROV_THIS(iface
);
266 return IBindStatusCallback_Release(STATUSCLB(This
));
269 static HRESULT WINAPI
DwlServiceProvider_QueryService(IServiceProvider
*iface
,
270 REFGUID guidService
, REFIID riid
, void **ppv
)
272 DownloadBSC
*This
= SERVPROV_THIS(iface
);
273 IServiceProvider
*serv_prov
;
276 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_guid(guidService
), debugstr_guid(riid
), ppv
);
279 return E_NOINTERFACE
;
281 hres
= IBindStatusCallback_QueryInterface(This
->callback
, riid
, ppv
);
285 hres
= IBindStatusCallback_QueryInterface(This
->callback
, &IID_IServiceProvider
, (void**)&serv_prov
);
286 if(SUCCEEDED(hres
)) {
287 hres
= IServiceProvider_QueryService(serv_prov
, guidService
, riid
, ppv
);
288 IServiceProvider_Release(serv_prov
);
292 return E_NOINTERFACE
;
297 static const IServiceProviderVtbl ServiceProviderVtbl
= {
298 DwlServiceProvider_QueryInterface
,
299 DwlServiceProvider_AddRef
,
300 DwlServiceProvider_Release
,
301 DwlServiceProvider_QueryService
304 static IBindStatusCallback
*DownloadBSC_Create(IBindStatusCallback
*callback
, LPCWSTR file_name
)
306 DownloadBSC
*ret
= heap_alloc(sizeof(*ret
));
308 ret
->lpBindStatusCallbackVtbl
= &BindStatusCallbackVtbl
;
309 ret
->lpServiceProviderVtbl
= &ServiceProviderVtbl
;
311 ret
->file_name
= heap_strdupW(file_name
);
312 ret
->cache_file
= NULL
;
315 IBindStatusCallback_AddRef(callback
);
316 ret
->callback
= callback
;
318 return STATUSCLB(ret
);
321 /***********************************************************************
322 * URLDownloadToFileW (URLMON.@)
324 * Downloads URL szURL to file szFileName and call lpfnCB callback to
328 * pCaller [I] controlling IUnknown interface.
329 * szURL [I] URL of the file to download
330 * szFileName [I] file name to store the content of the URL
331 * dwReserved [I] reserved - set to 0
332 * lpfnCB [I] callback for progress report
337 HRESULT WINAPI
URLDownloadToFileW(LPUNKNOWN pCaller
, LPCWSTR szURL
, LPCWSTR szFileName
,
338 DWORD dwReserved
, LPBINDSTATUSCALLBACK lpfnCB
)
340 IBindStatusCallback
*callback
;
346 TRACE("(%p %s %s %d %p)\n", pCaller
, debugstr_w(szURL
), debugstr_w(szFileName
), dwReserved
, lpfnCB
);
349 FIXME("pCaller not supported\n");
351 callback
= DownloadBSC_Create(lpfnCB
, szFileName
);
352 hres
= CreateAsyncBindCtx(0, callback
, NULL
, &bindctx
);
353 IBindStatusCallback_Release(callback
);
357 hres
= CreateURLMoniker(NULL
, szURL
, &mon
);
359 IBindCtx_Release(bindctx
);
363 hres
= IMoniker_BindToStorage(mon
, bindctx
, NULL
, &IID_IUnknown
, (void**)&unk
);
364 IMoniker_Release(mon
);
365 IBindCtx_Release(bindctx
);
368 IUnknown_Release(unk
);
370 return hres
== MK_S_ASYNCHRONOUS
? S_OK
: hres
;
373 /***********************************************************************
374 * URLDownloadToFileA (URLMON.@)
376 * Downloads URL szURL to rile szFileName and call lpfnCB callback to
380 * pCaller [I] controlling IUnknown interface.
381 * szURL [I] URL of the file to download
382 * szFileName [I] file name to store the content of the URL
383 * dwReserved [I] reserved - set to 0
384 * lpfnCB [I] callback for progress report
389 HRESULT WINAPI
URLDownloadToFileA(LPUNKNOWN pCaller
, LPCSTR szURL
, LPCSTR szFileName
, DWORD dwReserved
,
390 LPBINDSTATUSCALLBACK lpfnCB
)
392 LPWSTR urlW
, file_nameW
;
395 TRACE("(%p %s %s %d %p)\n", pCaller
, debugstr_a(szURL
), debugstr_a(szFileName
), dwReserved
, lpfnCB
);
397 urlW
= heap_strdupAtoW(szURL
);
398 file_nameW
= heap_strdupAtoW(szFileName
);
400 hres
= URLDownloadToFileW(pCaller
, urlW
, file_nameW
, dwReserved
, lpfnCB
);
403 heap_free(file_nameW
);