[FREELDR]
[reactos.git] / dll / win32 / urlmon / umstream.c
1 /*
2 * Based on ../shell32/memorystream.c
3 *
4 * Copyright 1999 Juergen Schmied
5 * Copyright 2003 Mike McCormack for CodeWeavers
6 *
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.
11 *
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.
16 *
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
20 */
21
22 #include "urlmon_main.h"
23
24 #include "winreg.h"
25 #include "winternl.h"
26 #include "wininet.h"
27 #include "shlwapi.h"
28
29 #include "wine/debug.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
32
33 typedef struct ProxyBindStatusCallback
34 {
35 const IBindStatusCallbackVtbl *lpVtbl;
36
37 IBindStatusCallback *pBSC;
38 } ProxyBindStatusCallback;
39
40 static HRESULT WINAPI ProxyBindStatusCallback_QueryInterface(IBindStatusCallback *iface, REFIID riid, void **ppv)
41 {
42 if (IsEqualGUID(&IID_IBindStatusCallback, riid) ||
43 IsEqualGUID(&IID_IUnknown, riid))
44 {
45 *ppv = iface;
46 IUnknown_AddRef(iface);
47 return S_OK;
48 }
49
50 *ppv = NULL;
51 return E_NOINTERFACE;
52 }
53
54 static ULONG WINAPI ProxyBindStatusCallback_AddRef(IBindStatusCallback *iface)
55 {
56 return 2;
57 }
58
59 static ULONG WINAPI ProxyBindStatusCallback_Release(IBindStatusCallback *iface)
60 {
61 return 1;
62 }
63
64 static HRESULT WINAPI ProxyBindStatusCallback_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved,
65 IBinding *pib)
66 {
67 ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
68
69 if(This->pBSC)
70 return IBindStatusCallback_OnStartBinding(This->pBSC, dwReserved, pib);
71
72 return S_OK;
73 }
74
75 static HRESULT WINAPI ProxyBindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
76 {
77 ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
78
79 if(This->pBSC)
80 return IBindStatusCallback_GetPriority(This->pBSC, pnPriority);
81
82 return S_OK;
83 }
84
85 static HRESULT WINAPI ProxyBindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
86 {
87 ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
88
89 if(This->pBSC)
90 return IBindStatusCallback_OnLowResource(This->pBSC, reserved);
91
92 return S_OK;
93 }
94
95 static HRESULT WINAPI ProxyBindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
96 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
97 {
98 ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
99
100 if(This->pBSC)
101 return IBindStatusCallback_OnProgress(This->pBSC, ulProgress,
102 ulProgressMax, ulStatusCode,
103 szStatusText);
104
105 return S_OK;
106 }
107
108 static HRESULT WINAPI ProxyBindStatusCallback_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError)
109 {
110 ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
111
112 if(This->pBSC)
113 return IBindStatusCallback_OnStopBinding(This->pBSC, hresult, szError);
114
115 return S_OK;
116 }
117
118 static HRESULT WINAPI ProxyBindStatusCallback_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
119 {
120 ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
121
122 if(This->pBSC)
123 return IBindStatusCallback_GetBindInfo(This->pBSC, grfBINDF, pbindinfo);
124
125 return E_INVALIDARG;
126 }
127
128 static HRESULT WINAPI ProxyBindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
129 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
130 {
131 ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
132
133 if(This->pBSC)
134 return IBindStatusCallback_OnDataAvailable(This->pBSC, grfBSCF, dwSize,
135 pformatetc, pstgmed);
136
137 return S_OK;
138 }
139
140 static HRESULT WINAPI ProxyBindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk)
141 {
142 ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
143
144 if(This->pBSC)
145 return IBindStatusCallback_OnObjectAvailable(This->pBSC, riid, punk);
146
147 return S_OK;
148 }
149
150 static HRESULT WINAPI BlockingBindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
151 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
152 {
153 return S_OK;
154 }
155
156 static const IBindStatusCallbackVtbl BlockingBindStatusCallbackVtbl =
157 {
158 ProxyBindStatusCallback_QueryInterface,
159 ProxyBindStatusCallback_AddRef,
160 ProxyBindStatusCallback_Release,
161 ProxyBindStatusCallback_OnStartBinding,
162 ProxyBindStatusCallback_GetPriority,
163 ProxyBindStatusCallback_OnLowResource,
164 ProxyBindStatusCallback_OnProgress,
165 ProxyBindStatusCallback_OnStopBinding,
166 ProxyBindStatusCallback_GetBindInfo,
167 BlockingBindStatusCallback_OnDataAvailable,
168 ProxyBindStatusCallback_OnObjectAvailable
169 };
170
171 static HRESULT WINAPI AsyncBindStatusCallback_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
172 {
173 ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
174 HRESULT hr = IBindStatusCallback_GetBindInfo(This->pBSC, grfBINDF, pbindinfo);
175 *grfBINDF |= BINDF_PULLDATA | BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE;
176 return hr;
177 }
178
179 static const IBindStatusCallbackVtbl AsyncBindStatusCallbackVtbl =
180 {
181 ProxyBindStatusCallback_QueryInterface,
182 ProxyBindStatusCallback_AddRef,
183 ProxyBindStatusCallback_Release,
184 ProxyBindStatusCallback_OnStartBinding,
185 ProxyBindStatusCallback_GetPriority,
186 ProxyBindStatusCallback_OnLowResource,
187 ProxyBindStatusCallback_OnProgress,
188 ProxyBindStatusCallback_OnStopBinding,
189 AsyncBindStatusCallback_GetBindInfo,
190 ProxyBindStatusCallback_OnDataAvailable,
191 ProxyBindStatusCallback_OnObjectAvailable
192 };
193
194 static HRESULT URLStartDownload(LPCWSTR szURL, LPSTREAM *ppStream, IBindStatusCallback *pBSC)
195 {
196 HRESULT hr;
197 IMoniker *pMoniker;
198 IBindCtx *pbc;
199
200 *ppStream = NULL;
201
202 hr = CreateURLMoniker(NULL, szURL, &pMoniker);
203 if (FAILED(hr))
204 return hr;
205
206 hr = CreateBindCtx(0, &pbc);
207 if (FAILED(hr))
208 {
209 IMoniker_Release(pMoniker);
210 return hr;
211 }
212
213 hr = RegisterBindStatusCallback(pbc, pBSC, NULL, 0);
214 if (FAILED(hr))
215 {
216 IBindCtx_Release(pbc);
217 IMoniker_Release(pMoniker);
218 return hr;
219 }
220
221 hr = IMoniker_BindToStorage(pMoniker, pbc, NULL, &IID_IStream, (void **)ppStream);
222
223 /* BindToStorage returning E_PENDING because it's asynchronous is not an error */
224 if (hr == E_PENDING) hr = S_OK;
225
226 IBindCtx_Release(pbc);
227 IMoniker_Release(pMoniker);
228
229 return hr;
230 }
231
232 /***********************************************************************
233 * URLOpenBlockingStreamA (URLMON.@)
234 */
235 HRESULT WINAPI URLOpenBlockingStreamA(LPUNKNOWN pCaller, LPCSTR szURL,
236 LPSTREAM *ppStream, DWORD dwReserved,
237 LPBINDSTATUSCALLBACK lpfnCB)
238 {
239 LPWSTR szURLW;
240 int len;
241 HRESULT hr;
242
243 TRACE("(%p, %s, %p, 0x%x, %p)\n", pCaller, szURL, ppStream, dwReserved, lpfnCB);
244
245 if (!szURL || !ppStream)
246 return E_INVALIDARG;
247
248 len = MultiByteToWideChar(CP_ACP, 0, szURL, -1, NULL, 0);
249 szURLW = heap_alloc(len * sizeof(WCHAR));
250 if (!szURLW)
251 {
252 *ppStream = NULL;
253 return E_OUTOFMEMORY;
254 }
255 MultiByteToWideChar(CP_ACP, 0, szURL, -1, szURLW, len);
256
257 hr = URLOpenBlockingStreamW(pCaller, szURLW, ppStream, dwReserved, lpfnCB);
258
259 heap_free(szURLW);
260
261 return hr;
262 }
263
264 /***********************************************************************
265 * URLOpenBlockingStreamW (URLMON.@)
266 */
267 HRESULT WINAPI URLOpenBlockingStreamW(LPUNKNOWN pCaller, LPCWSTR szURL,
268 LPSTREAM *ppStream, DWORD dwReserved,
269 LPBINDSTATUSCALLBACK lpfnCB)
270 {
271 ProxyBindStatusCallback blocking_bsc;
272
273 TRACE("(%p, %s, %p, 0x%x, %p)\n", pCaller, debugstr_w(szURL), ppStream,
274 dwReserved, lpfnCB);
275
276 if (!szURL || !ppStream)
277 return E_INVALIDARG;
278
279 blocking_bsc.lpVtbl = &BlockingBindStatusCallbackVtbl;
280 blocking_bsc.pBSC = lpfnCB;
281
282 return URLStartDownload(szURL, ppStream, (IBindStatusCallback *)&blocking_bsc);
283 }
284
285 /***********************************************************************
286 * URLOpenStreamA (URLMON.@)
287 */
288 HRESULT WINAPI URLOpenStreamA(LPUNKNOWN pCaller, LPCSTR szURL, DWORD dwReserved,
289 LPBINDSTATUSCALLBACK lpfnCB)
290 {
291 LPWSTR szURLW;
292 int len;
293 HRESULT hr;
294
295 TRACE("(%p, %s, 0x%x, %p)\n", pCaller, szURL, dwReserved, lpfnCB);
296
297 if (!szURL)
298 return E_INVALIDARG;
299
300 len = MultiByteToWideChar(CP_ACP, 0, szURL, -1, NULL, 0);
301 szURLW = heap_alloc(len * sizeof(WCHAR));
302 if (!szURLW)
303 return E_OUTOFMEMORY;
304 MultiByteToWideChar(CP_ACP, 0, szURL, -1, szURLW, len);
305
306 hr = URLOpenStreamW(pCaller, szURLW, dwReserved, lpfnCB);
307
308 heap_free(szURLW);
309
310 return hr;
311 }
312
313 /***********************************************************************
314 * URLOpenStreamW (URLMON.@)
315 */
316 HRESULT WINAPI URLOpenStreamW(LPUNKNOWN pCaller, LPCWSTR szURL, DWORD dwReserved,
317 LPBINDSTATUSCALLBACK lpfnCB)
318 {
319 HRESULT hr;
320 ProxyBindStatusCallback async_bsc;
321 IStream *pStream;
322
323 TRACE("(%p, %s, 0x%x, %p)\n", pCaller, debugstr_w(szURL), dwReserved,
324 lpfnCB);
325
326 if (!szURL)
327 return E_INVALIDARG;
328
329 async_bsc.lpVtbl = &AsyncBindStatusCallbackVtbl;
330 async_bsc.pBSC = lpfnCB;
331
332 hr = URLStartDownload(szURL, &pStream, (IBindStatusCallback *)&async_bsc);
333 if (SUCCEEDED(hr) && pStream)
334 IStream_Release(pStream);
335
336 return hr;
337 }