urlmon: Rename the wrappers around HeapAlloc() &Co to use the new standard naming.
[wine/gsoc_dplay.git] / dlls / urlmon / umstream.c
blobb70a2cd4701a124fce4d00e38b4e0978edc4c430
1 /*
2 * Based on ../shell32/memorystream.c
4 * Copyright 1999 Juergen Schmied
5 * Copyright 2003 Mike McCormack for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <stdarg.h>
24 #define COBJMACROS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "winternl.h"
30 #include "winuser.h"
31 #include "objbase.h"
32 #include "wine/debug.h"
33 #include "wine/unicode.h"
34 #include "ole2.h"
35 #include "urlmon.h"
36 #include "wininet.h"
37 #include "shlwapi.h"
38 #include "urlmon_main.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
42 static const IStreamVtbl stvt;
44 HRESULT UMCreateStreamOnCacheFile(LPCWSTR pszURL,
45 DWORD dwSize,
46 LPWSTR pszFileName,
47 HANDLE *phfile,
48 IUMCacheStream **ppstr)
50 IUMCacheStream* ucstr;
51 HANDLE handle;
52 DWORD size;
53 LPWSTR url, c, ext = NULL;
54 HRESULT hr;
56 size = (strlenW(pszURL)+1)*sizeof(WCHAR);
57 url = heap_alloc(size);
58 memcpy(url, pszURL, size);
60 for (c = url; *c && *c != '#' && *c != '?'; ++c)
62 if (*c == '.')
63 ext = c+1;
64 else if(*c == '/')
65 ext = NULL;
68 *c = 0;
70 if(!CreateUrlCacheEntryW(url, dwSize, ext, pszFileName, 0))
71 hr = HRESULT_FROM_WIN32(GetLastError());
72 else
73 hr = 0;
75 heap_free(url);
77 if (hr)
78 return hr;
80 TRACE("Opening %s\n", debugstr_w(pszFileName) );
82 handle = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL );
83 if( handle == INVALID_HANDLE_VALUE )
84 return HRESULT_FROM_WIN32(GetLastError());
86 if (phfile)
88 /* Call CreateFileW again because we need a handle with its own file pointer, and DuplicateHandle will return
89 * a handle that shares its file pointer with the original.
91 *phfile = CreateFileW( pszFileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
93 if (*phfile == (HANDLE) HFILE_ERROR)
95 DWORD dwError = GetLastError();
97 CloseHandle(handle);
98 return HRESULT_FROM_WIN32(dwError);
102 ucstr = heap_alloc_zero(sizeof(IUMCacheStream));
103 if(ucstr)
105 ucstr->pszURL = heap_alloc_zero(sizeof(WCHAR) * (lstrlenW(pszURL) + 1));
106 if (ucstr->pszURL)
108 ucstr->pszFileName = heap_alloc_zero(sizeof(WCHAR) * (lstrlenW(pszFileName) + 1));
109 if (ucstr->pszFileName)
111 ucstr->lpVtbl=&stvt;
112 ucstr->ref = 1;
113 ucstr->handle = handle;
114 ucstr->closed = 0;
115 lstrcpyW(ucstr->pszURL, pszURL);
116 lstrcpyW(ucstr->pszFileName, pszFileName);
118 *ppstr = ucstr;
120 return S_OK;
122 heap_free(ucstr->pszURL);
124 heap_free(ucstr);
126 CloseHandle(handle);
127 if (phfile)
128 CloseHandle(*phfile);
129 return E_OUTOFMEMORY;
132 void UMCloseCacheFileStream(IUMCacheStream *This)
134 if (!This->closed)
136 FILETIME ftZero;
138 ftZero.dwLowDateTime = ftZero.dwHighDateTime = 0;
140 This->closed = 1;
141 CommitUrlCacheEntryW(This->pszURL,
142 This->pszFileName,
143 ftZero,
144 ftZero,
145 NORMAL_CACHE_ENTRY,
153 /**************************************************************************
154 * IStream_fnQueryInterface
156 static HRESULT WINAPI IStream_fnQueryInterface(IStream *iface,
157 REFIID riid,
158 LPVOID *ppvObj)
160 IUMCacheStream *This = (IUMCacheStream *)iface;
162 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
164 *ppvObj = NULL;
166 if(IsEqualIID(riid, &IID_IUnknown) ||
167 IsEqualIID(riid, &IID_IStream))
169 *ppvObj = This;
172 if(*ppvObj)
174 IStream_AddRef((IStream*)*ppvObj);
175 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
176 return S_OK;
178 TRACE("-- Interface: E_NOINTERFACE\n");
179 return E_NOINTERFACE;
182 /**************************************************************************
183 * IStream_fnAddRef
185 static ULONG WINAPI IStream_fnAddRef(IStream *iface)
187 IUMCacheStream *This = (IUMCacheStream *)iface;
188 ULONG refCount = InterlockedIncrement(&This->ref);
190 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
192 return refCount;
195 /**************************************************************************
196 * IStream_fnRelease
198 static ULONG WINAPI IStream_fnRelease(IStream *iface)
200 IUMCacheStream *This = (IUMCacheStream *)iface;
201 ULONG refCount = InterlockedDecrement(&This->ref);
203 TRACE("(%p)->(count=%u)\n", This, refCount + 1);
205 if (!refCount)
207 TRACE(" destroying UMCacheStream (%p)\n",This);
208 UMCloseCacheFileStream(This);
209 CloseHandle(This->handle);
210 heap_free(This->pszFileName);
211 heap_free(This->pszURL);
212 heap_free(This);
214 return refCount;
217 static HRESULT WINAPI IStream_fnRead (IStream * iface,
218 void* pv,
219 ULONG cb,
220 ULONG* pcbRead)
222 ULONG dwBytesRead;
223 IUMCacheStream *This = (IUMCacheStream *)iface;
225 TRACE("(%p)->(%p,0x%08x,%p)\n",This, pv, cb, pcbRead);
227 if ( !pv )
228 return STG_E_INVALIDPOINTER;
230 if ( !pcbRead)
231 pcbRead = &dwBytesRead;
233 if ( ! ReadFile( This->handle, pv, cb, (LPDWORD)pcbRead, NULL ) )
234 return S_FALSE;
236 if (!*pcbRead)
237 return This->closed ? S_FALSE : E_PENDING;
238 return S_OK;
241 static HRESULT WINAPI IStream_fnWrite (IStream * iface,
242 const void* pv,
243 ULONG cb,
244 ULONG* pcbWritten)
246 return E_NOTIMPL;
249 static HRESULT WINAPI IStream_fnSeek (IStream * iface,
250 LARGE_INTEGER dlibMove,
251 DWORD dwOrigin,
252 ULARGE_INTEGER* plibNewPosition)
254 LARGE_INTEGER newpos;
255 IUMCacheStream *This = (IUMCacheStream *)iface;
257 TRACE("(%p)\n",This);
259 if (!SetFilePointerEx( This->handle, dlibMove, &newpos, dwOrigin ))
260 return E_FAIL;
262 if (plibNewPosition)
263 plibNewPosition->QuadPart = newpos.QuadPart;
265 return S_OK;
268 static HRESULT WINAPI IStream_fnSetSize (IStream * iface,
269 ULARGE_INTEGER libNewSize)
271 LARGE_INTEGER newpos;
272 IUMCacheStream *This = (IUMCacheStream *)iface;
274 TRACE("(%p)\n",This);
276 newpos.QuadPart = libNewSize.QuadPart;
277 if( ! SetFilePointerEx( This->handle, newpos, NULL, FILE_BEGIN ) )
278 return E_FAIL;
280 if( ! SetEndOfFile( This->handle ) )
281 return E_FAIL;
283 return S_OK;
286 static HRESULT WINAPI IStream_fnCopyTo (IStream * iface,
287 IStream* pstm,
288 ULARGE_INTEGER cb,
289 ULARGE_INTEGER* pcbRead,
290 ULARGE_INTEGER* pcbWritten)
292 IUMCacheStream *This = (IUMCacheStream *)iface;
294 TRACE("(%p)\n",This);
296 return E_NOTIMPL;
299 static HRESULT WINAPI IStream_fnCommit (IStream * iface,
300 DWORD grfCommitFlags)
302 IUMCacheStream *This = (IUMCacheStream *)iface;
304 TRACE("(%p)\n",This);
306 return E_NOTIMPL;
309 static HRESULT WINAPI IStream_fnRevert (IStream * iface)
311 IUMCacheStream *This = (IUMCacheStream *)iface;
313 TRACE("(%p)\n",This);
315 return E_NOTIMPL;
317 static HRESULT WINAPI IStream_fnLockRegion (IStream * iface,
318 ULARGE_INTEGER libOffset,
319 ULARGE_INTEGER cb,
320 DWORD dwLockType)
322 IUMCacheStream *This = (IUMCacheStream *)iface;
324 TRACE("(%p)\n",This);
326 return E_NOTIMPL;
328 static HRESULT WINAPI IStream_fnUnlockRegion (IStream * iface,
329 ULARGE_INTEGER libOffset,
330 ULARGE_INTEGER cb,
331 DWORD dwLockType)
333 IUMCacheStream *This = (IUMCacheStream *)iface;
335 TRACE("(%p)\n",This);
337 return E_NOTIMPL;
339 static HRESULT WINAPI IStream_fnStat (IStream * iface,
340 STATSTG* pstatstg,
341 DWORD grfStatFlag)
343 IUMCacheStream *This = (IUMCacheStream *)iface;
345 TRACE("(%p)\n",This);
347 return E_NOTIMPL;
349 static HRESULT WINAPI IStream_fnClone (IStream * iface,
350 IStream** ppstm)
352 IUMCacheStream *This = (IUMCacheStream *)iface;
354 TRACE("(%p)\n",This);
356 return E_NOTIMPL;
359 static const IStreamVtbl stvt =
361 IStream_fnQueryInterface,
362 IStream_fnAddRef,
363 IStream_fnRelease,
364 IStream_fnRead,
365 IStream_fnWrite,
366 IStream_fnSeek,
367 IStream_fnSetSize,
368 IStream_fnCopyTo,
369 IStream_fnCommit,
370 IStream_fnRevert,
371 IStream_fnLockRegion,
372 IStream_fnUnlockRegion,
373 IStream_fnStat,
374 IStream_fnClone
378 typedef struct ProxyBindStatusCallback
380 const IBindStatusCallbackVtbl *lpVtbl;
382 IBindStatusCallback *pBSC;
383 } ProxyBindStatusCallback;
385 static HRESULT WINAPI ProxyBindStatusCallback_QueryInterface(IBindStatusCallback *iface, REFIID riid, void **ppv)
387 if (IsEqualGUID(&IID_IBindStatusCallback, riid) ||
388 IsEqualGUID(&IID_IUnknown, riid))
390 *ppv = iface;
391 IUnknown_AddRef(iface);
392 return S_OK;
395 *ppv = NULL;
396 return E_NOINTERFACE;
399 static ULONG WINAPI ProxyBindStatusCallback_AddRef(IBindStatusCallback *iface)
401 return 2;
404 static ULONG WINAPI ProxyBindStatusCallback_Release(IBindStatusCallback *iface)
406 return 1;
409 static HRESULT WINAPI ProxyBindStatusCallback_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved,
410 IBinding *pib)
412 ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
414 if(This->pBSC)
415 return IBindStatusCallback_OnStartBinding(This->pBSC, dwReserved, pib);
417 return S_OK;
420 static HRESULT WINAPI ProxyBindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
422 ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
424 if(This->pBSC)
425 return IBindStatusCallback_GetPriority(This->pBSC, pnPriority);
427 return S_OK;
430 static HRESULT WINAPI ProxyBindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
432 ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
434 if(This->pBSC)
435 return IBindStatusCallback_OnLowResource(This->pBSC, reserved);
437 return S_OK;
440 static HRESULT WINAPI ProxyBindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
441 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
443 ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
445 if(This->pBSC)
446 return IBindStatusCallback_OnProgress(This->pBSC, ulProgress,
447 ulProgressMax, ulStatusCode,
448 szStatusText);
450 return S_OK;
453 static HRESULT WINAPI ProxyBindStatusCallback_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError)
455 ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
457 if(This->pBSC)
458 return IBindStatusCallback_OnStopBinding(This->pBSC, hresult, szError);
460 return S_OK;
463 static HRESULT WINAPI ProxyBindStatusCallback_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
465 ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
467 if(This->pBSC)
468 return IBindStatusCallback_GetBindInfo(This->pBSC, grfBINDF, pbindinfo);
470 return E_INVALIDARG;
473 static HRESULT WINAPI ProxyBindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
474 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
476 ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
478 if(This->pBSC)
479 return IBindStatusCallback_OnDataAvailable(This->pBSC, grfBSCF, dwSize,
480 pformatetc, pstgmed);
482 return S_OK;
485 static HRESULT WINAPI ProxyBindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk)
487 ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
489 if(This->pBSC)
490 return IBindStatusCallback_OnObjectAvailable(This->pBSC, riid, punk);
492 return S_OK;
495 static HRESULT WINAPI BlockingBindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
496 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
498 return S_OK;
501 static const IBindStatusCallbackVtbl BlockingBindStatusCallbackVtbl =
503 ProxyBindStatusCallback_QueryInterface,
504 ProxyBindStatusCallback_AddRef,
505 ProxyBindStatusCallback_Release,
506 ProxyBindStatusCallback_OnStartBinding,
507 ProxyBindStatusCallback_GetPriority,
508 ProxyBindStatusCallback_OnLowResource,
509 ProxyBindStatusCallback_OnProgress,
510 ProxyBindStatusCallback_OnStopBinding,
511 ProxyBindStatusCallback_GetBindInfo,
512 BlockingBindStatusCallback_OnDataAvailable,
513 ProxyBindStatusCallback_OnObjectAvailable
516 static HRESULT WINAPI AsyncBindStatusCallback_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
518 ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
519 HRESULT hr = IBindStatusCallback_GetBindInfo(This->pBSC, grfBINDF, pbindinfo);
520 *grfBINDF |= BINDF_PULLDATA | BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE;
521 return hr;
524 static const IBindStatusCallbackVtbl AsyncBindStatusCallbackVtbl =
526 ProxyBindStatusCallback_QueryInterface,
527 ProxyBindStatusCallback_AddRef,
528 ProxyBindStatusCallback_Release,
529 ProxyBindStatusCallback_OnStartBinding,
530 ProxyBindStatusCallback_GetPriority,
531 ProxyBindStatusCallback_OnLowResource,
532 ProxyBindStatusCallback_OnProgress,
533 ProxyBindStatusCallback_OnStopBinding,
534 AsyncBindStatusCallback_GetBindInfo,
535 ProxyBindStatusCallback_OnDataAvailable,
536 ProxyBindStatusCallback_OnObjectAvailable
539 static HRESULT URLStartDownload(LPCWSTR szURL, LPSTREAM *ppStream, IBindStatusCallback *pBSC)
541 HRESULT hr;
542 IMoniker *pMoniker;
543 IBindCtx *pbc;
545 *ppStream = NULL;
547 hr = CreateURLMoniker(NULL, szURL, &pMoniker);
548 if (FAILED(hr))
549 return hr;
551 hr = CreateBindCtx(0, &pbc);
552 if (FAILED(hr))
554 IMoniker_Release(pMoniker);
555 return hr;
558 hr = RegisterBindStatusCallback(pbc, pBSC, NULL, 0);
559 if (FAILED(hr))
561 IBindCtx_Release(pbc);
562 IMoniker_Release(pMoniker);
563 return hr;
566 hr = IMoniker_BindToStorage(pMoniker, pbc, NULL, &IID_IStream, (void **)ppStream);
568 /* BindToStorage returning E_PENDING because it's asynchronous is not an error */
569 if (hr == E_PENDING) hr = S_OK;
571 IBindCtx_Release(pbc);
572 IMoniker_Release(pMoniker);
574 return hr;
577 /***********************************************************************
578 * URLOpenBlockingStreamA (URLMON.@)
580 HRESULT WINAPI URLOpenBlockingStreamA(LPUNKNOWN pCaller, LPCSTR szURL,
581 LPSTREAM *ppStream, DWORD dwReserved,
582 LPBINDSTATUSCALLBACK lpfnCB)
584 LPWSTR szURLW;
585 int len;
586 HRESULT hr;
588 TRACE("(%p, %s, %p, 0x%x, %p)\n", pCaller, szURL, ppStream, dwReserved, lpfnCB);
590 if (!szURL || !ppStream)
591 return E_INVALIDARG;
593 len = MultiByteToWideChar(CP_ACP, 0, szURL, -1, NULL, 0);
594 szURLW = heap_alloc(len * sizeof(WCHAR));
595 if (!szURLW)
597 *ppStream = NULL;
598 return E_OUTOFMEMORY;
600 MultiByteToWideChar(CP_ACP, 0, szURL, -1, szURLW, len);
602 hr = URLOpenBlockingStreamW(pCaller, szURLW, ppStream, dwReserved, lpfnCB);
604 heap_free(szURLW);
606 return hr;
609 /***********************************************************************
610 * URLOpenBlockingStreamW (URLMON.@)
612 HRESULT WINAPI URLOpenBlockingStreamW(LPUNKNOWN pCaller, LPCWSTR szURL,
613 LPSTREAM *ppStream, DWORD dwReserved,
614 LPBINDSTATUSCALLBACK lpfnCB)
616 ProxyBindStatusCallback blocking_bsc;
618 TRACE("(%p, %s, %p, 0x%x, %p)\n", pCaller, debugstr_w(szURL), ppStream,
619 dwReserved, lpfnCB);
621 if (!szURL || !ppStream)
622 return E_INVALIDARG;
624 blocking_bsc.lpVtbl = &BlockingBindStatusCallbackVtbl;
625 blocking_bsc.pBSC = lpfnCB;
627 return URLStartDownload(szURL, ppStream, (IBindStatusCallback *)&blocking_bsc);
630 /***********************************************************************
631 * URLOpenStreamA (URLMON.@)
633 HRESULT WINAPI URLOpenStreamA(LPUNKNOWN pCaller, LPCSTR szURL, DWORD dwReserved,
634 LPBINDSTATUSCALLBACK lpfnCB)
636 LPWSTR szURLW;
637 int len;
638 HRESULT hr;
640 TRACE("(%p, %s, 0x%x, %p)\n", pCaller, szURL, dwReserved, lpfnCB);
642 if (!szURL)
643 return E_INVALIDARG;
645 len = MultiByteToWideChar(CP_ACP, 0, szURL, -1, NULL, 0);
646 szURLW = heap_alloc(len * sizeof(WCHAR));
647 if (!szURLW)
648 return E_OUTOFMEMORY;
649 MultiByteToWideChar(CP_ACP, 0, szURL, -1, szURLW, len);
651 hr = URLOpenStreamW(pCaller, szURLW, dwReserved, lpfnCB);
653 heap_free(szURLW);
655 return hr;
658 /***********************************************************************
659 * URLOpenStreamW (URLMON.@)
661 HRESULT WINAPI URLOpenStreamW(LPUNKNOWN pCaller, LPCWSTR szURL, DWORD dwReserved,
662 LPBINDSTATUSCALLBACK lpfnCB)
664 HRESULT hr;
665 ProxyBindStatusCallback async_bsc;
666 IStream *pStream;
668 TRACE("(%p, %s, 0x%x, %p)\n", pCaller, debugstr_w(szURL), dwReserved,
669 lpfnCB);
671 if (!szURL)
672 return E_INVALIDARG;
674 async_bsc.lpVtbl = &AsyncBindStatusCallbackVtbl;
675 async_bsc.pBSC = lpfnCB;
677 hr = URLStartDownload(szURL, &pStream, (IBindStatusCallback *)&async_bsc);
678 if (SUCCEEDED(hr) && pStream)
679 IStream_Release(pStream);
681 return hr;