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
32 #include "wine/debug.h"
33 #include "wine/unicode.h"
38 #include "urlmon_main.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(urlmon
);
42 static const IStreamVtbl stvt
;
44 HRESULT
UMCreateStreamOnCacheFile(LPCWSTR pszURL
,
48 IUMCacheStream
**ppstr
)
50 IUMCacheStream
* ucstr
;
53 LPWSTR url
, c
, ext
= NULL
;
56 size
= (strlenW(pszURL
)+1)*sizeof(WCHAR
);
57 url
= HeapAlloc(GetProcessHeap(), 0, size
);
58 memcpy(url
, pszURL
, size
);
60 for (c
= url
; *c
&& *c
!= '#' && *c
!= '?'; ++c
)
70 if(!CreateUrlCacheEntryW(url
, dwSize
, ext
, pszFileName
, 0))
71 hr
= HRESULT_FROM_WIN32(GetLastError());
75 HeapFree(GetProcessHeap(), 0, url
);
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());
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();
98 return HRESULT_FROM_WIN32(dwError
);
102 ucstr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,sizeof(IUMCacheStream
));
105 ucstr
->pszURL
= HeapAlloc(GetProcessHeap(),
107 sizeof(WCHAR
) * (lstrlenW(pszURL
) + 1));
110 ucstr
->pszFileName
= HeapAlloc(GetProcessHeap(),
112 sizeof(WCHAR
) * (lstrlenW(pszFileName
) + 1));
113 if (ucstr
->pszFileName
)
117 ucstr
->handle
= handle
;
119 lstrcpyW(ucstr
->pszURL
, pszURL
);
120 lstrcpyW(ucstr
->pszFileName
, pszFileName
);
126 HeapFree(GetProcessHeap(), 0, ucstr
->pszURL
);
128 HeapFree(GetProcessHeap(), 0, ucstr
);
132 CloseHandle(*phfile
);
133 return E_OUTOFMEMORY
;
136 void UMCloseCacheFileStream(IUMCacheStream
*This
)
142 ftZero
.dwLowDateTime
= ftZero
.dwHighDateTime
= 0;
145 CommitUrlCacheEntryW(This
->pszURL
,
157 /**************************************************************************
158 * IStream_fnQueryInterface
160 static HRESULT WINAPI
IStream_fnQueryInterface(IStream
*iface
,
164 IUMCacheStream
*This
= (IUMCacheStream
*)iface
;
166 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
170 if(IsEqualIID(riid
, &IID_IUnknown
) ||
171 IsEqualIID(riid
, &IID_IStream
))
178 IStream_AddRef((IStream
*)*ppvObj
);
179 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
182 TRACE("-- Interface: E_NOINTERFACE\n");
183 return E_NOINTERFACE
;
186 /**************************************************************************
189 static ULONG WINAPI
IStream_fnAddRef(IStream
*iface
)
191 IUMCacheStream
*This
= (IUMCacheStream
*)iface
;
192 ULONG refCount
= InterlockedIncrement(&This
->ref
);
194 TRACE("(%p)->(count=%u)\n", This
, refCount
- 1);
199 /**************************************************************************
202 static ULONG WINAPI
IStream_fnRelease(IStream
*iface
)
204 IUMCacheStream
*This
= (IUMCacheStream
*)iface
;
205 ULONG refCount
= InterlockedDecrement(&This
->ref
);
207 TRACE("(%p)->(count=%u)\n", This
, refCount
+ 1);
211 TRACE(" destroying UMCacheStream (%p)\n",This
);
212 UMCloseCacheFileStream(This
);
213 CloseHandle(This
->handle
);
214 HeapFree(GetProcessHeap(), 0, This
->pszFileName
);
215 HeapFree(GetProcessHeap(), 0, This
->pszURL
);
216 HeapFree(GetProcessHeap(),0,This
);
221 static HRESULT WINAPI
IStream_fnRead (IStream
* iface
,
227 IUMCacheStream
*This
= (IUMCacheStream
*)iface
;
229 TRACE("(%p)->(%p,0x%08x,%p)\n",This
, pv
, cb
, pcbRead
);
232 return STG_E_INVALIDPOINTER
;
235 pcbRead
= &dwBytesRead
;
237 if ( ! ReadFile( This
->handle
, pv
, cb
, (LPDWORD
)pcbRead
, NULL
) )
241 return This
->closed
? S_FALSE
: E_PENDING
;
245 static HRESULT WINAPI
IStream_fnWrite (IStream
* iface
,
253 static HRESULT WINAPI
IStream_fnSeek (IStream
* iface
,
254 LARGE_INTEGER dlibMove
,
256 ULARGE_INTEGER
* plibNewPosition
)
258 LARGE_INTEGER newpos
;
259 IUMCacheStream
*This
= (IUMCacheStream
*)iface
;
261 TRACE("(%p)\n",This
);
263 if (!SetFilePointerEx( This
->handle
, dlibMove
, &newpos
, dwOrigin
))
267 plibNewPosition
->QuadPart
= newpos
.QuadPart
;
272 static HRESULT WINAPI
IStream_fnSetSize (IStream
* iface
,
273 ULARGE_INTEGER libNewSize
)
275 LARGE_INTEGER newpos
;
276 IUMCacheStream
*This
= (IUMCacheStream
*)iface
;
278 TRACE("(%p)\n",This
);
280 newpos
.QuadPart
= libNewSize
.QuadPart
;
281 if( ! SetFilePointerEx( This
->handle
, newpos
, NULL
, FILE_BEGIN
) )
284 if( ! SetEndOfFile( This
->handle
) )
290 static HRESULT WINAPI
IStream_fnCopyTo (IStream
* iface
,
293 ULARGE_INTEGER
* pcbRead
,
294 ULARGE_INTEGER
* pcbWritten
)
296 IUMCacheStream
*This
= (IUMCacheStream
*)iface
;
298 TRACE("(%p)\n",This
);
303 static HRESULT WINAPI
IStream_fnCommit (IStream
* iface
,
304 DWORD grfCommitFlags
)
306 IUMCacheStream
*This
= (IUMCacheStream
*)iface
;
308 TRACE("(%p)\n",This
);
313 static HRESULT WINAPI
IStream_fnRevert (IStream
* iface
)
315 IUMCacheStream
*This
= (IUMCacheStream
*)iface
;
317 TRACE("(%p)\n",This
);
321 static HRESULT WINAPI
IStream_fnLockRegion (IStream
* iface
,
322 ULARGE_INTEGER libOffset
,
326 IUMCacheStream
*This
= (IUMCacheStream
*)iface
;
328 TRACE("(%p)\n",This
);
332 static HRESULT WINAPI
IStream_fnUnlockRegion (IStream
* iface
,
333 ULARGE_INTEGER libOffset
,
337 IUMCacheStream
*This
= (IUMCacheStream
*)iface
;
339 TRACE("(%p)\n",This
);
343 static HRESULT WINAPI
IStream_fnStat (IStream
* iface
,
347 IUMCacheStream
*This
= (IUMCacheStream
*)iface
;
349 TRACE("(%p)\n",This
);
353 static HRESULT WINAPI
IStream_fnClone (IStream
* iface
,
356 IUMCacheStream
*This
= (IUMCacheStream
*)iface
;
358 TRACE("(%p)\n",This
);
363 static const IStreamVtbl stvt
=
365 IStream_fnQueryInterface
,
375 IStream_fnLockRegion
,
376 IStream_fnUnlockRegion
,
382 typedef struct ProxyBindStatusCallback
384 const IBindStatusCallbackVtbl
*lpVtbl
;
386 IBindStatusCallback
*pBSC
;
387 } ProxyBindStatusCallback
;
389 static HRESULT WINAPI
ProxyBindStatusCallback_QueryInterface(IBindStatusCallback
*iface
, REFIID riid
, void **ppv
)
391 if (IsEqualGUID(&IID_IBindStatusCallback
, riid
) ||
392 IsEqualGUID(&IID_IUnknown
, riid
))
395 IUnknown_AddRef(iface
);
400 return E_NOINTERFACE
;
403 static ULONG WINAPI
ProxyBindStatusCallback_AddRef(IBindStatusCallback
*iface
)
408 static ULONG WINAPI
ProxyBindStatusCallback_Release(IBindStatusCallback
*iface
)
413 static HRESULT WINAPI
ProxyBindStatusCallback_OnStartBinding(IBindStatusCallback
*iface
, DWORD dwReserved
,
416 ProxyBindStatusCallback
*This
= (ProxyBindStatusCallback
*)iface
;
417 return IBindStatusCallback_OnStartBinding(This
->pBSC
, dwReserved
, pib
);
420 static HRESULT WINAPI
ProxyBindStatusCallback_GetPriority(IBindStatusCallback
*iface
, LONG
*pnPriority
)
422 ProxyBindStatusCallback
*This
= (ProxyBindStatusCallback
*)iface
;
423 return IBindStatusCallback_GetPriority(This
->pBSC
, pnPriority
);
426 static HRESULT WINAPI
ProxyBindStatusCallback_OnLowResource(IBindStatusCallback
*iface
, DWORD reserved
)
428 ProxyBindStatusCallback
*This
= (ProxyBindStatusCallback
*)iface
;
429 return IBindStatusCallback_OnLowResource(This
->pBSC
, reserved
);
432 static HRESULT WINAPI
ProxyBindStatusCallback_OnProgress(IBindStatusCallback
*iface
, ULONG ulProgress
,
433 ULONG ulProgressMax
, ULONG ulStatusCode
, LPCWSTR szStatusText
)
435 ProxyBindStatusCallback
*This
= (ProxyBindStatusCallback
*)iface
;
436 return IBindStatusCallback_OnProgress(This
->pBSC
, ulProgress
,
437 ulProgressMax
, ulStatusCode
,
441 static HRESULT WINAPI
ProxyBindStatusCallback_OnStopBinding(IBindStatusCallback
*iface
, HRESULT hresult
, LPCWSTR szError
)
443 ProxyBindStatusCallback
*This
= (ProxyBindStatusCallback
*)iface
;
444 return IBindStatusCallback_OnStopBinding(This
->pBSC
, hresult
, szError
);
447 static HRESULT WINAPI
ProxyBindStatusCallback_GetBindInfo(IBindStatusCallback
*iface
, DWORD
*grfBINDF
, BINDINFO
*pbindinfo
)
449 ProxyBindStatusCallback
*This
= (ProxyBindStatusCallback
*)iface
;
450 return IBindStatusCallback_GetBindInfo(This
->pBSC
, grfBINDF
, pbindinfo
);
453 static HRESULT WINAPI
ProxyBindStatusCallback_OnDataAvailable(IBindStatusCallback
*iface
, DWORD grfBSCF
,
454 DWORD dwSize
, FORMATETC
* pformatetc
, STGMEDIUM
* pstgmed
)
456 ProxyBindStatusCallback
*This
= (ProxyBindStatusCallback
*)iface
;
457 return IBindStatusCallback_OnDataAvailable(This
->pBSC
, grfBSCF
, dwSize
,
458 pformatetc
, pstgmed
);
461 static HRESULT WINAPI
ProxyBindStatusCallback_OnObjectAvailable(IBindStatusCallback
*iface
, REFIID riid
, IUnknown
*punk
)
463 ProxyBindStatusCallback
*This
= (ProxyBindStatusCallback
*)iface
;
464 return IBindStatusCallback_OnObjectAvailable(This
->pBSC
, riid
, punk
);
467 static HRESULT WINAPI
BlockingBindStatusCallback_OnDataAvailable(IBindStatusCallback
*iface
, DWORD grfBSCF
,
468 DWORD dwSize
, FORMATETC
* pformatetc
, STGMEDIUM
* pstgmed
)
473 static const IBindStatusCallbackVtbl BlockingBindStatusCallbackVtbl
=
475 ProxyBindStatusCallback_QueryInterface
,
476 ProxyBindStatusCallback_AddRef
,
477 ProxyBindStatusCallback_Release
,
478 ProxyBindStatusCallback_OnStartBinding
,
479 ProxyBindStatusCallback_GetPriority
,
480 ProxyBindStatusCallback_OnLowResource
,
481 ProxyBindStatusCallback_OnProgress
,
482 ProxyBindStatusCallback_OnStopBinding
,
483 ProxyBindStatusCallback_GetBindInfo
,
484 BlockingBindStatusCallback_OnDataAvailable
,
485 ProxyBindStatusCallback_OnObjectAvailable
488 static HRESULT WINAPI
AsyncBindStatusCallback_GetBindInfo(IBindStatusCallback
*iface
, DWORD
*grfBINDF
, BINDINFO
*pbindinfo
)
490 ProxyBindStatusCallback
*This
= (ProxyBindStatusCallback
*)iface
;
491 HRESULT hr
= IBindStatusCallback_GetBindInfo(This
->pBSC
, grfBINDF
, pbindinfo
);
492 *grfBINDF
|= BINDF_PULLDATA
| BINDF_ASYNCHRONOUS
| BINDF_ASYNCSTORAGE
;
496 static const IBindStatusCallbackVtbl AsyncBindStatusCallbackVtbl
=
498 ProxyBindStatusCallback_QueryInterface
,
499 ProxyBindStatusCallback_AddRef
,
500 ProxyBindStatusCallback_Release
,
501 ProxyBindStatusCallback_OnStartBinding
,
502 ProxyBindStatusCallback_GetPriority
,
503 ProxyBindStatusCallback_OnLowResource
,
504 ProxyBindStatusCallback_OnProgress
,
505 ProxyBindStatusCallback_OnStopBinding
,
506 AsyncBindStatusCallback_GetBindInfo
,
507 ProxyBindStatusCallback_OnDataAvailable
,
508 ProxyBindStatusCallback_OnObjectAvailable
511 static HRESULT
URLStartDownload(LPCWSTR szURL
, LPSTREAM
*ppStream
, IBindStatusCallback
*pBSC
)
519 hr
= CreateURLMoniker(NULL
, szURL
, &pMoniker
);
523 hr
= CreateBindCtx(0, &pbc
);
526 IMoniker_Release(pMoniker
);
530 hr
= RegisterBindStatusCallback(pbc
, pBSC
, NULL
, 0);
533 IBindCtx_Release(pbc
);
534 IMoniker_Release(pMoniker
);
538 hr
= IMoniker_BindToStorage(pMoniker
, pbc
, NULL
, &IID_IStream
, (void **)ppStream
);
540 /* BindToStorage returning E_PENDING because it's asynchronous is not an error */
541 if (hr
== E_PENDING
) hr
= S_OK
;
543 IBindCtx_Release(pbc
);
544 IMoniker_Release(pMoniker
);
549 /***********************************************************************
550 * URLOpenBlockingStreamA (URLMON.@)
552 HRESULT WINAPI
URLOpenBlockingStreamA(LPUNKNOWN pCaller
, LPCSTR szURL
,
553 LPSTREAM
*ppStream
, DWORD dwReserved
,
554 LPBINDSTATUSCALLBACK lpfnCB
)
560 TRACE("(%p, %s, %p, 0x%x, %p)\n", pCaller
, szURL
, ppStream
, dwReserved
, lpfnCB
);
562 if (!szURL
|| !ppStream
)
565 len
= MultiByteToWideChar(CP_ACP
, 0, szURL
, -1, NULL
, 0);
566 szURLW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
570 return E_OUTOFMEMORY
;
572 MultiByteToWideChar(CP_ACP
, 0, szURL
, -1, szURLW
, len
);
574 hr
= URLOpenBlockingStreamW(pCaller
, szURLW
, ppStream
, dwReserved
, lpfnCB
);
576 HeapFree(GetProcessHeap(), 0, szURLW
);
581 /***********************************************************************
582 * URLOpenBlockingStreamW (URLMON.@)
584 HRESULT WINAPI
URLOpenBlockingStreamW(LPUNKNOWN pCaller
, LPCWSTR szURL
,
585 LPSTREAM
*ppStream
, DWORD dwReserved
,
586 LPBINDSTATUSCALLBACK lpfnCB
)
588 ProxyBindStatusCallback blocking_bsc
;
590 TRACE("(%p, %s, %p, 0x%x, %p)\n", pCaller
, debugstr_w(szURL
), ppStream
,
593 if (!szURL
|| !ppStream
)
596 blocking_bsc
.lpVtbl
= &BlockingBindStatusCallbackVtbl
;
597 blocking_bsc
.pBSC
= lpfnCB
;
599 return URLStartDownload(szURL
, ppStream
, (IBindStatusCallback
*)&blocking_bsc
);
602 /***********************************************************************
603 * URLOpenStreamA (URLMON.@)
605 HRESULT WINAPI
URLOpenStreamA(LPUNKNOWN pCaller
, LPCSTR szURL
, DWORD dwReserved
,
606 LPBINDSTATUSCALLBACK lpfnCB
)
612 TRACE("(%p, %s, 0x%x, %p)\n", pCaller
, szURL
, dwReserved
, lpfnCB
);
617 len
= MultiByteToWideChar(CP_ACP
, 0, szURL
, -1, NULL
, 0);
618 szURLW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
620 return E_OUTOFMEMORY
;
621 MultiByteToWideChar(CP_ACP
, 0, szURL
, -1, szURLW
, len
);
623 hr
= URLOpenStreamW(pCaller
, szURLW
, dwReserved
, lpfnCB
);
625 HeapFree(GetProcessHeap(), 0, szURLW
);
630 /***********************************************************************
631 * URLOpenStreamW (URLMON.@)
633 HRESULT WINAPI
URLOpenStreamW(LPUNKNOWN pCaller
, LPCWSTR szURL
, DWORD dwReserved
,
634 LPBINDSTATUSCALLBACK lpfnCB
)
637 ProxyBindStatusCallback async_bsc
;
640 TRACE("(%p, %s, 0x%x, %p)\n", pCaller
, debugstr_w(szURL
), dwReserved
,
646 async_bsc
.lpVtbl
= &AsyncBindStatusCallbackVtbl
;
647 async_bsc
.pBSC
= lpfnCB
;
649 hr
= URLStartDownload(szURL
, &pStream
, (IBindStatusCallback
*)&async_bsc
);
650 if (SUCCEEDED(hr
) && pStream
)
651 IStream_Release(pStream
);