ReactOS  0.4.14-dev-317-g96040ec
download.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Jacek Caban for CodeWeavers
3  *
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.
8  *
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.
13  *
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
17  */
18 
19 #include "urlmon_main.h"
20 #include "wine/debug.h"
21 
23 
24 typedef struct {
27 
29 
35 
37  void *ctx;
38 } DownloadBSC;
39 
41 {
42  return CONTAINING_RECORD(iface, DownloadBSC, IBindStatusCallback_iface);
43 }
44 
46 {
47  return CONTAINING_RECORD(iface, DownloadBSC, IServiceProvider_iface);
48 }
49 
51  REFIID riid, void **ppv)
52 {
54 
55  *ppv = NULL;
56 
58  TRACE("(%p)->(IID_IUnknown, %p)\n", This, ppv);
59  *ppv = &This->IBindStatusCallback_iface;
60  }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) {
61  TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv);
62  *ppv = &This->IBindStatusCallback_iface;
63  }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
64  TRACE("(%p)->(IID_IServiceProvider, %p)\n", This, ppv);
65  *ppv = &This->IServiceProvider_iface;
66  }
67 
68  if(*ppv) {
69  IUnknown_AddRef((IUnknown*)*ppv);
70  return S_OK;
71  }
72 
73  TRACE("Unsupported riid = %s\n", debugstr_guid(riid));
74  return E_NOINTERFACE;
75 }
76 
78 {
81 
82  TRACE("(%p) ref = %d\n", This, ref);
83 
84  return ref;
85 }
86 
88 {
91 
92  TRACE("(%p) ref = %d\n", This, ref);
93 
94  if(!ref) {
95  if(This->callback)
96  IBindStatusCallback_Release(This->callback);
97  if(This->binding)
98  IBinding_Release(This->binding);
99  heap_free(This->file_name);
100  heap_free(This->cache_file);
101  heap_free(This);
102  }
103 
104  return ref;
105 }
106 
108  DWORD dwReserved, IBinding *pbind)
109 {
111  HRESULT hres = S_OK;
112 
113  TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind);
114 
115  if(This->callback) {
116  hres = IBindStatusCallback_OnStartBinding(This->callback, dwReserved, pbind);
117 
118  IBinding_AddRef(pbind);
119  This->binding = pbind;
120  }
121 
122  /* Windows seems to ignore E_NOTIMPL if it's returned from the client. */
123  return hres == E_NOTIMPL ? S_OK : hres;
124 }
125 
127 {
129  FIXME("(%p)->(%p)\n", This, pnPriority);
130  return E_NOTIMPL;
131 }
132 
134 {
136  FIXME("(%p)->(%d)\n", This, reserved);
137  return E_NOTIMPL;
138 }
139 
141 {
142  HRESULT hres;
143 
144  if(!This->callback)
145  return S_OK;
146 
147  hres = IBindStatusCallback_OnProgress(This->callback, progress, progress_max, status_code, status_text);
148  if(hres == E_ABORT) {
149  if(This->binding)
150  IBinding_Abort(This->binding);
151  else
152  FIXME("No binding, not sure what to do!\n");
153  }
154 
155  return hres;
156 }
157 
159  ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
160 {
162  HRESULT hres = S_OK;
163 
164  TRACE("%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode,
165  debugstr_w(szStatusText));
166 
167  switch(ulStatusCode) {
168  case BINDSTATUS_CONNECTING:
169  case BINDSTATUS_BEGINDOWNLOADDATA:
170  case BINDSTATUS_DOWNLOADINGDATA:
171  case BINDSTATUS_ENDDOWNLOADDATA:
172  case BINDSTATUS_SENDINGREQUEST:
173  case BINDSTATUS_MIMETYPEAVAILABLE:
174  hres = on_progress(This, ulProgress, ulProgressMax, ulStatusCode, szStatusText);
175  break;
176 
177  case BINDSTATUS_CACHEFILENAMEAVAILABLE:
178  hres = on_progress(This, ulProgress, ulProgressMax, ulStatusCode, szStatusText);
179  This->cache_file = heap_strdupW(szStatusText);
180  break;
181 
182  case BINDSTATUS_FINDINGRESOURCE: /* FIXME */
183  break;
184 
185  default:
186  FIXME("Unsupported status %u\n", ulStatusCode);
187  }
188 
189  return hres;
190 }
191 
193  HRESULT hresult, LPCWSTR szError)
194 {
196  HRESULT hres = S_OK;
197 
198  TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
199 
200  if(This->file_name) {
201  if(This->cache_file) {
202  BOOL b;
203 
204  b = CopyFileW(This->cache_file, This->file_name, FALSE);
205  if(!b)
206  FIXME("CopyFile failed: %u\n", GetLastError());
207  }else {
208  FIXME("No cache file\n");
209  }
210  }
211 
212  if(This->onstop_proc)
213  hres = This->onstop_proc(This->ctx, This->cache_file, hresult, szError);
214  else if(This->callback)
215  IBindStatusCallback_OnStopBinding(This->callback, hresult, szError);
216 
217  if(This->binding) {
218  IBinding_Release(This->binding);
219  This->binding = NULL;
220  }
221 
222  return hres;
223 }
224 
226  DWORD *grfBINDF, BINDINFO *pbindinfo)
227 {
229  DWORD bindf = 0;
230 
231  TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
232 
233  if(This->callback) {
234  BINDINFO bindinfo;
235  HRESULT hres;
236 
237  memset(&bindinfo, 0, sizeof(bindinfo));
238  bindinfo.cbSize = sizeof(bindinfo);
239 
240  hres = IBindStatusCallback_GetBindInfo(This->callback, &bindf, &bindinfo);
241  if(SUCCEEDED(hres))
242  ReleaseBindInfo(&bindinfo);
243  }
244 
245  *grfBINDF = BINDF_PULLDATA | BINDF_NEEDFILE | (bindf & BINDF_ENFORCERESTRICTED) | This->bindf;
246  return S_OK;
247 }
248 
250  DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
251 {
253 
254  TRACE("(%p)->(%08x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed);
255 
256  return S_OK;
257 }
258 
260  REFIID riid, IUnknown *punk)
261 {
263  FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), punk);
264  return E_NOTIMPL;
265 }
266 
267 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
279 };
280 
282  REFIID riid, void **ppv)
283 {
285  return IBindStatusCallback_QueryInterface(&This->IBindStatusCallback_iface, riid, ppv);
286 }
287 
289 {
291  return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
292 }
293 
295 {
297  return IBindStatusCallback_Release(&This->IBindStatusCallback_iface);
298 }
299 
301  REFGUID guidService, REFIID riid, void **ppv)
302 {
304  IServiceProvider *serv_prov;
305  HRESULT hres;
306 
307  TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
308 
309  if(!This->callback)
310  return E_NOINTERFACE;
311 
312  hres = IBindStatusCallback_QueryInterface(This->callback, riid, ppv);
313  if(SUCCEEDED(hres))
314  return S_OK;
315 
316  hres = IBindStatusCallback_QueryInterface(This->callback, &IID_IServiceProvider, (void**)&serv_prov);
317  if(SUCCEEDED(hres)) {
318  hres = IServiceProvider_QueryService(serv_prov, guidService, riid, ppv);
319  IServiceProvider_Release(serv_prov);
320  return hres;
321  }
322 
323  return E_NOINTERFACE;
324 }
325 
326 static const IServiceProviderVtbl ServiceProviderVtbl = {
331 };
332 
334 {
335  DownloadBSC *ret;
336 
337  ret = heap_alloc_zero(sizeof(*ret));
338  if(!ret)
339  return E_OUTOFMEMORY;
340 
341  ret->IBindStatusCallback_iface.lpVtbl = &BindStatusCallbackVtbl;
342  ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
343  ret->ref = 1;
344 
345  if(file_name) {
346  ret->file_name = heap_strdupW(file_name);
347  if(!ret->file_name) {
348  heap_free(ret);
349  return E_OUTOFMEMORY;
350  }
351  }
352 
353  if(callback)
354  IBindStatusCallback_AddRef(callback);
355  ret->callback = callback;
356 
357  *ret_callback = ret;
358  return S_OK;
359 }
360 
362 {
364  HRESULT hres;
365 
367  if(FAILED(hres))
368  return hres;
369 
370  hres = wrap_callback(&callback->IBindStatusCallback_iface, ret);
371  IBindStatusCallback_Release(&callback->IBindStatusCallback_iface);
372  return hres;
373 }
374 
376 {
377  DownloadBSC *dwl_bsc;
378  IBindCtx *bindctx;
379  IMoniker *mon;
380  IUnknown *unk;
381  HRESULT hres;
382 
383  hres = DownloadBSC_Create(callback, NULL, &dwl_bsc);
384  if(FAILED(hres))
385  return hres;
386 
387  dwl_bsc->onstop_proc = proc;
388  dwl_bsc->ctx = ctx;
389  dwl_bsc->bindf = BINDF_ASYNCHRONOUS;
390 
391  hres = CreateAsyncBindCtx(0, &dwl_bsc->IBindStatusCallback_iface, NULL, &bindctx);
392  IBindStatusCallback_Release(&dwl_bsc->IBindStatusCallback_iface);
393  if(FAILED(hres))
394  return hres;
395 
396  hres = CreateURLMonikerEx2(NULL, uri, &mon, 0);
397  if(FAILED(hres)) {
398  IBindCtx_Release(bindctx);
399  return hres;
400  }
401 
402  hres = IMoniker_BindToStorage(mon, bindctx, NULL, &IID_IUnknown, (void**)&unk);
403  IMoniker_Release(mon);
404  IBindCtx_Release(bindctx);
405  if(SUCCEEDED(hres) && unk)
406  IUnknown_Release(unk);
407  return hres;
408 
409 }
410 
411 /***********************************************************************
412  * URLDownloadToFileW (URLMON.@)
413  *
414  * Downloads URL szURL to file szFileName and call lpfnCB callback to
415  * report progress.
416  *
417  * PARAMS
418  * pCaller [I] controlling IUnknown interface.
419  * szURL [I] URL of the file to download
420  * szFileName [I] file name to store the content of the URL
421  * dwReserved [I] reserved - set to 0
422  * lpfnCB [I] callback for progress report
423  *
424  * RETURNS
425  * S_OK on success
426  */
428  DWORD dwReserved, LPBINDSTATUSCALLBACK lpfnCB)
429 {
431  IUnknown *unk;
432  IMoniker *mon;
433  IBindCtx *bindctx;
434  HRESULT hres;
435 
436  TRACE("(%p %s %s %d %p)\n", pCaller, debugstr_w(szURL), debugstr_w(szFileName), dwReserved, lpfnCB);
437 
438  if(pCaller)
439  FIXME("pCaller not supported\n");
440 
441  hres = DownloadBSC_Create(lpfnCB, szFileName, &callback);
442  if(FAILED(hres))
443  return hres;
444 
445  hres = CreateAsyncBindCtx(0, &callback->IBindStatusCallback_iface, NULL, &bindctx);
446  IBindStatusCallback_Release(&callback->IBindStatusCallback_iface);
447  if(FAILED(hres))
448  return hres;
449 
450  hres = CreateURLMoniker(NULL, szURL, &mon);
451  if(FAILED(hres)) {
452  IBindCtx_Release(bindctx);
453  return hres;
454  }
455 
456  hres = IMoniker_BindToStorage(mon, bindctx, NULL, &IID_IUnknown, (void**)&unk);
457  IMoniker_Release(mon);
458  IBindCtx_Release(bindctx);
459 
460  if(unk)
461  IUnknown_Release(unk);
462 
463  return hres == MK_S_ASYNCHRONOUS ? S_OK : hres;
464 }
465 
466 /***********************************************************************
467  * URLDownloadToFileA (URLMON.@)
468  *
469  * Downloads URL szURL to rile szFileName and call lpfnCB callback to
470  * report progress.
471  *
472  * PARAMS
473  * pCaller [I] controlling IUnknown interface.
474  * szURL [I] URL of the file to download
475  * szFileName [I] file name to store the content of the URL
476  * dwReserved [I] reserved - set to 0
477  * lpfnCB [I] callback for progress report
478  *
479  * RETURNS
480  * S_OK on success
481  */
483  LPBINDSTATUSCALLBACK lpfnCB)
484 {
485  LPWSTR urlW, file_nameW;
486  HRESULT hres;
487 
488  TRACE("(%p %s %s %d %p)\n", pCaller, debugstr_a(szURL), debugstr_a(szFileName), dwReserved, lpfnCB);
489 
490  urlW = heap_strdupAtoW(szURL);
491  file_nameW = heap_strdupAtoW(szFileName);
492 
493  hres = URLDownloadToFileW(pCaller, urlW, file_nameW, dwReserved, lpfnCB);
494 
495  heap_free(urlW);
497 
498  return hres;
499 }
HRESULT wrap_callback(IBindStatusCallback *bsc, IBindStatusCallback **ret_iface)
Definition: bindctx.c:578
HRESULT WINAPI URLDownloadToFileW(LPUNKNOWN pCaller, LPCWSTR szURL, LPCWSTR szFileName, DWORD dwReserved, LPBINDSTATUSCALLBACK lpfnCB)
Definition: download.c:427
#define REFIID
Definition: guiddef.h:118
#define E_NOINTERFACE
Definition: winerror.h:2364
LPWSTR cache_file
Definition: download.c:33
stop_cache_binding_proc_t onstop_proc
Definition: download.c:36
Definition: scsiwmi.h:51
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
const char * uri
Definition: sec_mgr.c:1594
REFIID riid
Definition: precomp.h:44
static ULONG WINAPI DwlServiceProvider_AddRef(IServiceProvider *iface)
Definition: download.c:288
void WINAPI ReleaseBindInfo(BINDINFO *pbindinfo)
Definition: urlmon_main.c:572
static HRESULT DownloadBSC_Create(IBindStatusCallback *callback, LPCWSTR file_name, DownloadBSC **ret_callback)
Definition: download.c:333
REFIID LPVOID * ppv
Definition: atlbase.h:39
static const IBindStatusCallbackVtbl BindStatusCallbackVtbl
Definition: download.c:267
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
static HRESULT WINAPI DownloadBSC_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk)
Definition: download.c:259
HRESULT WINAPI URLDownloadToFileA(LPUNKNOWN pCaller, LPCSTR szURL, LPCSTR szFileName, DWORD dwReserved, LPBINDSTATUSCALLBACK lpfnCB)
Definition: download.c:482
static HANDLE proc()
Definition: pdb.c:32
IServiceProvider IServiceProvider_iface
Definition: download.c:26
Definition: send.c:47
DWORD bindf
Definition: download.c:34
static HRESULT WINAPI DownloadBSC_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
Definition: download.c:225
HRESULT(* stop_cache_binding_proc_t)(void *, const WCHAR *, HRESULT, const WCHAR *)
Definition: urlmon_main.h:91
void * ctx
Definition: download.c:37
static const WCHAR * file_nameW(const WCHAR *str)
Definition: path.c:44
static const IServiceProviderVtbl ServiceProviderVtbl
Definition: download.c:326
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
_In_ HANDLE _In_ DWORD _In_ DWORD _Inout_opt_ LPOVERLAPPED _In_opt_ LPTRANSMIT_FILE_BUFFERS _In_ DWORD dwReserved
Definition: mswsock.h:90
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
static LPUNKNOWN
Definition: ndr_ole.c:49
static WCHAR * heap_strdupW(const WCHAR *str)
Definition: propsheet.c:178
#define debugstr_w
Definition: kernel32.h:32
GLenum GLint ref
Definition: glext.h:6028
IBinding * binding
Definition: download.c:31
#define FIXME(fmt,...)
Definition: debug.h:110
r reserved
Definition: btrfs.c:2865
static ULONG WINAPI DownloadBSC_AddRef(IBindStatusCallback *iface)
Definition: download.c:77
smooth NULL
Definition: ftsmooth.c:416
static ULONG WINAPI DwlServiceProvider_Release(IServiceProvider *iface)
Definition: download.c:294
const char * LPCSTR
Definition: xmlstorage.h:183
HRESULT create_default_callback(IBindStatusCallback **ret)
Definition: download.c:361
#define debugstr_guid
Definition: kernel32.h:35
static WCHAR * heap_strdupAtoW(const char *str)
Definition: appwiz.h:80
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define b
Definition: ke_i.h:79
IBindStatusCallback * callback
Definition: download.c:30
static HRESULT WINAPI DownloadBSC_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
Definition: download.c:249
MmuTrapHandler callback[0x30]
Definition: mmuobject.c:44
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define TRACE(s)
Definition: solgame.cpp:4
HRESULT hres
Definition: protocol.c:465
LONG ref
Definition: download.c:28
#define debugstr_a
Definition: kernel32.h:31
LONG HRESULT
Definition: typedefs.h:77
BOOL WINAPI CopyFileW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN BOOL bFailIfExists)
Definition: copy.c:439
const GUID IID_IUnknown
static HRESULT WINAPI DownloadBSC_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved, IBinding *pbind)
Definition: download.c:107
HRESULT download_to_cache(IUri *uri, stop_cache_binding_proc_t proc, void *ctx, IBindStatusCallback *callback)
Definition: download.c:375
#define WINAPI
Definition: msvc.h:8
unsigned long DWORD
Definition: ntddk_ex.h:95
static HRESULT WINAPI DownloadBSC_QueryInterface(IBindStatusCallback *iface, REFIID riid, void **ppv)
Definition: download.c:50
static HRESULT WINAPI DownloadBSC_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
Definition: download.c:133
static HRESULT WINAPI DownloadBSC_OnProgress(IBindStatusCallback *iface, ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
Definition: download.c:158
int ret
static HRESULT WINAPI DownloadBSC_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError)
Definition: download.c:192
#define InterlockedDecrement
Definition: armddk.h:52
HRESULT WINAPI CreateURLMonikerEx2(IMoniker *pmkContext, IUri *pUri, IMoniker **ppmk, DWORD dwFlags)
Definition: umon.c:668
#define E_ABORT
Definition: winerror.h:2366
static DownloadBSC * impl_from_IBindStatusCallback(IBindStatusCallback *iface)
Definition: download.c:40
static HRESULT on_progress(DownloadBSC *This, ULONG progress, ULONG progress_max, ULONG status_code, LPCWSTR status_text)
Definition: download.c:140
#define S_OK
Definition: intsafe.h:59
HRESULT WINAPI CreateAsyncBindCtx(DWORD reserved, IBindStatusCallback *callback, IEnumFORMATETC *format, IBindCtx **pbind)
Definition: bindctx.c:899
#define InterlockedIncrement
Definition: armddk.h:53
static HRESULT WINAPI DwlServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
Definition: download.c:281
#define E_NOTIMPL
Definition: ddrawi.h:99
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4112
static ULONG WINAPI DownloadBSC_Release(IBindStatusCallback *iface)
Definition: download.c:87
cd_progress_ptr progress
Definition: cdjpeg.h:150
static LPCWSTR file_name
Definition: protocol.c:146
WINE_DEFAULT_DEBUG_CHANNEL(dmusic)
static HRESULT WINAPI DwlServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService, REFIID riid, void **ppv)
Definition: download.c:300
unsigned int ULONG
Definition: retypes.h:1
HRESULT WINAPI CreateURLMoniker(IMoniker *pmkContext, LPCWSTR szURL, IMoniker **ppmk)
Definition: umon.c:732
WCHAR * LPWSTR
Definition: xmlstorage.h:184
static HRESULT WINAPI DownloadBSC_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
Definition: download.c:126
#define memset(x, y, z)
Definition: compat.h:39
static DownloadBSC * impl_from_IServiceProvider(IServiceProvider *iface)
Definition: download.c:45
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:54
LPWSTR file_name
Definition: download.c:32
IBindStatusCallback IBindStatusCallback_iface
Definition: download.c:25
#define SUCCEEDED(hr)
Definition: intsafe.h:57
static BOOL heap_free(void *mem)
Definition: appwiz.h:75
static DWORD bindf
Definition: protocol.c:70