storage.dll16: Fix get_nth_next_small_blocknr.
[wine.git] / dlls / urlmon / umstream.c
blob01cc755c2314ca619a9be6daf40bfa74e412a21e
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 "urlmon_main.h"
24 #include "winreg.h"
25 #include "winternl.h"
26 #include "wininet.h"
27 #include "shlwapi.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
33 typedef struct ProxyBindStatusCallback
35 IBindStatusCallback IBindStatusCallback_iface;
37 IBindStatusCallback *pBSC;
38 } ProxyBindStatusCallback;
40 static inline ProxyBindStatusCallback *impl_from_IBindStatusCallback(IBindStatusCallback *iface)
42 return CONTAINING_RECORD(iface, ProxyBindStatusCallback, IBindStatusCallback_iface);
45 static HRESULT WINAPI ProxyBindStatusCallback_QueryInterface(IBindStatusCallback *iface, REFIID riid, void **ppv)
47 if (IsEqualGUID(&IID_IBindStatusCallback, riid) ||
48 IsEqualGUID(&IID_IUnknown, riid))
50 *ppv = iface;
51 IBindStatusCallback_AddRef(iface);
52 return S_OK;
55 *ppv = NULL;
56 return E_NOINTERFACE;
59 static ULONG WINAPI ProxyBindStatusCallback_AddRef(IBindStatusCallback *iface)
61 return 2;
64 static ULONG WINAPI ProxyBindStatusCallback_Release(IBindStatusCallback *iface)
66 return 1;
69 static HRESULT WINAPI ProxyBindStatusCallback_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved,
70 IBinding *pib)
72 ProxyBindStatusCallback *This = impl_from_IBindStatusCallback(iface);
74 if(This->pBSC)
75 return IBindStatusCallback_OnStartBinding(This->pBSC, dwReserved, pib);
77 return S_OK;
80 static HRESULT WINAPI ProxyBindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
82 ProxyBindStatusCallback *This = impl_from_IBindStatusCallback(iface);
84 if(This->pBSC)
85 return IBindStatusCallback_GetPriority(This->pBSC, pnPriority);
87 return S_OK;
90 static HRESULT WINAPI ProxyBindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
92 ProxyBindStatusCallback *This = impl_from_IBindStatusCallback(iface);
94 if(This->pBSC)
95 return IBindStatusCallback_OnLowResource(This->pBSC, reserved);
97 return S_OK;
100 static HRESULT WINAPI ProxyBindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
101 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
103 ProxyBindStatusCallback *This = impl_from_IBindStatusCallback(iface);
105 if(This->pBSC)
106 return IBindStatusCallback_OnProgress(This->pBSC, ulProgress,
107 ulProgressMax, ulStatusCode,
108 szStatusText);
110 return S_OK;
113 static HRESULT WINAPI ProxyBindStatusCallback_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError)
115 ProxyBindStatusCallback *This = impl_from_IBindStatusCallback(iface);
117 if(This->pBSC)
118 return IBindStatusCallback_OnStopBinding(This->pBSC, hresult, szError);
120 return S_OK;
123 static HRESULT WINAPI ProxyBindStatusCallback_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
125 DWORD size = pbindinfo->cbSize;
126 ProxyBindStatusCallback *This = impl_from_IBindStatusCallback(iface);
128 if(This->pBSC)
129 return IBindStatusCallback_GetBindInfo(This->pBSC, grfBINDF, pbindinfo);
131 memset(pbindinfo, 0, size);
132 pbindinfo->cbSize = size;
134 *grfBINDF = 0;
136 return S_OK;
139 static HRESULT WINAPI ProxyBindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
140 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
142 ProxyBindStatusCallback *This = impl_from_IBindStatusCallback(iface);
144 if(This->pBSC)
145 return IBindStatusCallback_OnDataAvailable(This->pBSC, grfBSCF, dwSize,
146 pformatetc, pstgmed);
148 return S_OK;
151 static HRESULT WINAPI ProxyBindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk)
153 ProxyBindStatusCallback *This = impl_from_IBindStatusCallback(iface);
155 if(This->pBSC)
156 return IBindStatusCallback_OnObjectAvailable(This->pBSC, riid, punk);
158 return S_OK;
161 static HRESULT WINAPI BlockingBindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
162 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
164 return S_OK;
167 static const IBindStatusCallbackVtbl BlockingBindStatusCallbackVtbl =
169 ProxyBindStatusCallback_QueryInterface,
170 ProxyBindStatusCallback_AddRef,
171 ProxyBindStatusCallback_Release,
172 ProxyBindStatusCallback_OnStartBinding,
173 ProxyBindStatusCallback_GetPriority,
174 ProxyBindStatusCallback_OnLowResource,
175 ProxyBindStatusCallback_OnProgress,
176 ProxyBindStatusCallback_OnStopBinding,
177 ProxyBindStatusCallback_GetBindInfo,
178 BlockingBindStatusCallback_OnDataAvailable,
179 ProxyBindStatusCallback_OnObjectAvailable
182 static HRESULT WINAPI AsyncBindStatusCallback_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
184 ProxyBindStatusCallback *This = impl_from_IBindStatusCallback(iface);
185 HRESULT hr = S_OK;
187 if(This->pBSC)
188 hr = IBindStatusCallback_GetBindInfo(This->pBSC, grfBINDF, pbindinfo);
189 else{
190 DWORD size = pbindinfo->cbSize;
191 memset(pbindinfo, 0, size);
192 pbindinfo->cbSize = size;
194 *grfBINDF = 0;
197 *grfBINDF |= BINDF_PULLDATA | BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE;
199 return hr;
202 static const IBindStatusCallbackVtbl AsyncBindStatusCallbackVtbl =
204 ProxyBindStatusCallback_QueryInterface,
205 ProxyBindStatusCallback_AddRef,
206 ProxyBindStatusCallback_Release,
207 ProxyBindStatusCallback_OnStartBinding,
208 ProxyBindStatusCallback_GetPriority,
209 ProxyBindStatusCallback_OnLowResource,
210 ProxyBindStatusCallback_OnProgress,
211 ProxyBindStatusCallback_OnStopBinding,
212 AsyncBindStatusCallback_GetBindInfo,
213 ProxyBindStatusCallback_OnDataAvailable,
214 ProxyBindStatusCallback_OnObjectAvailable
217 static HRESULT URLStartDownload(LPCWSTR szURL, LPSTREAM *ppStream, IBindStatusCallback *pBSC)
219 HRESULT hr;
220 IMoniker *pMoniker;
221 IBindCtx *pbc;
223 *ppStream = NULL;
225 hr = CreateURLMoniker(NULL, szURL, &pMoniker);
226 if (FAILED(hr))
227 return hr;
229 hr = CreateBindCtx(0, &pbc);
230 if (FAILED(hr))
232 IMoniker_Release(pMoniker);
233 return hr;
236 hr = RegisterBindStatusCallback(pbc, pBSC, NULL, 0);
237 if (FAILED(hr))
239 IBindCtx_Release(pbc);
240 IMoniker_Release(pMoniker);
241 return hr;
244 hr = IMoniker_BindToStorage(pMoniker, pbc, NULL, &IID_IStream, (void **)ppStream);
246 /* BindToStorage returning E_PENDING because it's asynchronous is not an error */
247 if (hr == E_PENDING) hr = S_OK;
249 IBindCtx_Release(pbc);
250 IMoniker_Release(pMoniker);
252 return hr;
255 /***********************************************************************
256 * URLOpenBlockingStreamA (URLMON.@)
258 HRESULT WINAPI URLOpenBlockingStreamA(LPUNKNOWN pCaller, LPCSTR szURL,
259 LPSTREAM *ppStream, DWORD dwReserved,
260 LPBINDSTATUSCALLBACK lpfnCB)
262 LPWSTR szURLW;
263 int len;
264 HRESULT hr;
266 TRACE("(%p, %s, %p, 0x%x, %p)\n", pCaller, szURL, ppStream, dwReserved, lpfnCB);
268 if (!szURL || !ppStream)
269 return E_INVALIDARG;
271 len = MultiByteToWideChar(CP_ACP, 0, szURL, -1, NULL, 0);
272 szURLW = heap_alloc(len * sizeof(WCHAR));
273 if (!szURLW)
275 *ppStream = NULL;
276 return E_OUTOFMEMORY;
278 MultiByteToWideChar(CP_ACP, 0, szURL, -1, szURLW, len);
280 hr = URLOpenBlockingStreamW(pCaller, szURLW, ppStream, dwReserved, lpfnCB);
282 heap_free(szURLW);
284 return hr;
287 /***********************************************************************
288 * URLOpenBlockingStreamW (URLMON.@)
290 HRESULT WINAPI URLOpenBlockingStreamW(LPUNKNOWN pCaller, LPCWSTR szURL,
291 LPSTREAM *ppStream, DWORD dwReserved,
292 LPBINDSTATUSCALLBACK lpfnCB)
294 ProxyBindStatusCallback blocking_bsc;
296 TRACE("(%p, %s, %p, 0x%x, %p)\n", pCaller, debugstr_w(szURL), ppStream,
297 dwReserved, lpfnCB);
299 if (!szURL || !ppStream)
300 return E_INVALIDARG;
302 blocking_bsc.IBindStatusCallback_iface.lpVtbl = &BlockingBindStatusCallbackVtbl;
303 blocking_bsc.pBSC = lpfnCB;
305 return URLStartDownload(szURL, ppStream, &blocking_bsc.IBindStatusCallback_iface);
308 /***********************************************************************
309 * URLOpenStreamA (URLMON.@)
311 HRESULT WINAPI URLOpenStreamA(LPUNKNOWN pCaller, LPCSTR szURL, DWORD dwReserved,
312 LPBINDSTATUSCALLBACK lpfnCB)
314 LPWSTR szURLW;
315 int len;
316 HRESULT hr;
318 TRACE("(%p, %s, 0x%x, %p)\n", pCaller, szURL, dwReserved, lpfnCB);
320 if (!szURL)
321 return E_INVALIDARG;
323 len = MultiByteToWideChar(CP_ACP, 0, szURL, -1, NULL, 0);
324 szURLW = heap_alloc(len * sizeof(WCHAR));
325 if (!szURLW)
326 return E_OUTOFMEMORY;
327 MultiByteToWideChar(CP_ACP, 0, szURL, -1, szURLW, len);
329 hr = URLOpenStreamW(pCaller, szURLW, dwReserved, lpfnCB);
331 heap_free(szURLW);
333 return hr;
336 /***********************************************************************
337 * URLOpenStreamW (URLMON.@)
339 HRESULT WINAPI URLOpenStreamW(LPUNKNOWN pCaller, LPCWSTR szURL, DWORD dwReserved,
340 LPBINDSTATUSCALLBACK lpfnCB)
342 HRESULT hr;
343 ProxyBindStatusCallback async_bsc;
344 IStream *pStream;
346 TRACE("(%p, %s, 0x%x, %p)\n", pCaller, debugstr_w(szURL), dwReserved,
347 lpfnCB);
349 if (!szURL)
350 return E_INVALIDARG;
352 async_bsc.IBindStatusCallback_iface.lpVtbl = &AsyncBindStatusCallbackVtbl;
353 async_bsc.pBSC = lpfnCB;
355 hr = URLStartDownload(szURL, &pStream, &async_bsc.IBindStatusCallback_iface);
356 if (SUCCEEDED(hr) && pStream)
357 IStream_Release(pStream);
359 return hr;