[URLMON_WINETEST] Sync with Wine Staging 1.7.37. CORE-9246
[reactos.git] / rostests / winetests / urlmon / stream.c
1 /*
2 * Copyright 2007 Robert Shearman 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 #define WIN32_NO_STATUS
20 #define _INC_WINDOWS
21 #define COM_NO_WINDOWS_H
22
23 #define COBJMACROS
24 #define CONST_VTABLE
25
26 #include <wine/test.h>
27 //#include <stdarg.h>
28 //#include <stddef.h>
29
30 //#include "windef.h"
31 //#include "winbase.h"
32 #include <winnls.h>
33 #include <ole2.h>
34 //#include "urlmon.h"
35 #include <wininet.h>
36
37 #define DEFINE_EXPECT(func) \
38 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
39
40 #define SET_EXPECT(func) \
41 expect_ ## func = TRUE
42
43 #define CHECK_EXPECT(func) \
44 do { \
45 ok(expect_ ##func, "unexpected call " #func "\n"); \
46 expect_ ## func = FALSE; \
47 called_ ## func = TRUE; \
48 }while(0)
49
50 #define CHECK_EXPECT2(func) \
51 do { \
52 ok(expect_ ##func, "unexpected call " #func "\n"); \
53 called_ ## func = TRUE; \
54 }while(0)
55
56 #define CHECK_CALLED(func) \
57 do { \
58 ok(called_ ## func, "expected " #func "\n"); \
59 expect_ ## func = called_ ## func = FALSE; \
60 }while(0)
61
62 #define CHECK_NOT_CALLED(func) \
63 do { \
64 ok(!called_ ## func, "unexpected " #func "\n"); \
65 expect_ ## func = called_ ## func = FALSE; \
66 }while(0)
67
68 #define CLEAR_CALLED(func) \
69 expect_ ## func = called_ ## func = FALSE
70
71 DEFINE_EXPECT(QueryInterface_IServiceProvider);
72 DEFINE_EXPECT(OnStartBinding);
73 DEFINE_EXPECT(OnProgress_FINDINGRESOURCE);
74 DEFINE_EXPECT(OnProgress_CONNECTING);
75 DEFINE_EXPECT(OnProgress_SENDINGREQUEST);
76 DEFINE_EXPECT(OnProgress_MIMETYPEAVAILABLE);
77 DEFINE_EXPECT(OnProgress_BEGINDOWNLOADDATA);
78 DEFINE_EXPECT(OnProgress_DOWNLOADINGDATA);
79 DEFINE_EXPECT(OnProgress_ENDDOWNLOADDATA);
80 DEFINE_EXPECT(OnStopBinding);
81 DEFINE_EXPECT(OnDataAvailable);
82 DEFINE_EXPECT(GetBindInfo);
83
84 static const CHAR wszIndexHtmlA[] = "index.html";
85 static WCHAR INDEX_HTML[MAX_PATH];
86 static const char szHtmlDoc[] = "<HTML></HTML>";
87
88 static HRESULT WINAPI statusclb_QueryInterface(IBindStatusCallback *iface, REFIID riid, void **ppv)
89 {
90 if (IsEqualGUID(&IID_IBindStatusCallback, riid) ||
91 IsEqualGUID(&IID_IUnknown, riid))
92 {
93 *ppv = iface;
94 return S_OK;
95 }
96 else if (IsEqualGUID(&IID_IServiceProvider, riid))
97 {
98 CHECK_EXPECT(QueryInterface_IServiceProvider);
99 }
100
101 return E_NOINTERFACE;
102 }
103
104 static ULONG WINAPI statusclb_AddRef(IBindStatusCallback *iface)
105 {
106 return 2;
107 }
108
109 static ULONG WINAPI statusclb_Release(IBindStatusCallback *iface)
110 {
111 return 1;
112 }
113
114 static HRESULT WINAPI statusclb_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved,
115 IBinding *pib)
116 {
117 HRESULT hres;
118 IMoniker *mon;
119
120 CHECK_EXPECT(OnStartBinding);
121
122 ok(pib != NULL, "pib should not be NULL\n");
123
124 hres = IBinding_QueryInterface(pib, &IID_IMoniker, (void**)&mon);
125 ok(hres == E_NOINTERFACE, "IBinding should not have IMoniker interface\n");
126 if(SUCCEEDED(hres))
127 IMoniker_Release(mon);
128
129 return S_OK;
130 }
131
132 static HRESULT WINAPI statusclb_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
133 {
134 ok(0, "unexpected call\n");
135 return E_NOTIMPL;
136 }
137
138 static HRESULT WINAPI statusclb_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
139 {
140 ok(0, "unexpected call\n");
141 return E_NOTIMPL;
142 }
143
144 static HRESULT WINAPI statusclb_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
145 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
146 {
147 switch(ulStatusCode) {
148 case BINDSTATUS_FINDINGRESOURCE:
149 CHECK_EXPECT(OnProgress_FINDINGRESOURCE);
150 break;
151 case BINDSTATUS_CONNECTING:
152 CHECK_EXPECT(OnProgress_CONNECTING);
153 break;
154 case BINDSTATUS_SENDINGREQUEST:
155 CHECK_EXPECT(OnProgress_SENDINGREQUEST);
156 break;
157 case BINDSTATUS_MIMETYPEAVAILABLE:
158 CHECK_EXPECT(OnProgress_MIMETYPEAVAILABLE);
159 break;
160 case BINDSTATUS_BEGINDOWNLOADDATA:
161 CHECK_EXPECT(OnProgress_BEGINDOWNLOADDATA);
162 ok(szStatusText != NULL, "szStatusText == NULL\n");
163 break;
164 case BINDSTATUS_DOWNLOADINGDATA:
165 CHECK_EXPECT2(OnProgress_DOWNLOADINGDATA);
166 break;
167 case BINDSTATUS_ENDDOWNLOADDATA:
168 CHECK_EXPECT(OnProgress_ENDDOWNLOADDATA);
169 ok(szStatusText != NULL, "szStatusText == NULL\n");
170 break;
171 case BINDSTATUS_CACHEFILENAMEAVAILABLE:
172 ok(szStatusText != NULL, "szStatusText == NULL\n");
173 break;
174 default:
175 todo_wine { ok(0, "unexpected code %d\n", ulStatusCode); }
176 };
177 return S_OK;
178 }
179
180 static HRESULT WINAPI statusclb_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError)
181 {
182 CHECK_EXPECT(OnStopBinding);
183
184 /* ignore DNS failure */
185 if (hresult != HRESULT_FROM_WIN32(ERROR_INTERNET_NAME_NOT_RESOLVED))
186 {
187 ok(SUCCEEDED(hresult), "Download failed: %08x\n", hresult);
188 ok(szError == NULL, "szError should be NULL\n");
189 }
190
191 return S_OK;
192 }
193
194 static HRESULT WINAPI statusclb_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
195 {
196 DWORD cbSize;
197
198 CHECK_EXPECT(GetBindInfo);
199
200 *grfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA;
201 cbSize = pbindinfo->cbSize;
202 memset(pbindinfo, 0, cbSize);
203 pbindinfo->cbSize = cbSize;
204
205 return S_OK;
206 }
207
208 static HRESULT WINAPI statusclb_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
209 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
210 {
211 HRESULT hres;
212 DWORD readed;
213 BYTE buf[512];
214
215 CHECK_EXPECT2(OnDataAvailable);
216
217 if (0)
218 {
219 /* FIXME: Uncomment after removing BindToStorage hack. */
220 ok(pformatetc != NULL, "pformatetx == NULL\n");
221 if(pformatetc) {
222 ok(pformatetc->cfFormat == 0xc02d, "clipformat=%x\n", pformatetc->cfFormat);
223 ok(pformatetc->ptd == NULL, "ptd = %p\n", pformatetc->ptd);
224 ok(pformatetc->dwAspect == 1, "dwAspect=%u\n", pformatetc->dwAspect);
225 ok(pformatetc->lindex == -1, "lindex=%d\n", pformatetc->lindex);
226 ok(pformatetc->tymed == TYMED_ISTREAM, "tymed=%u\n", pformatetc->tymed);
227 }
228
229 ok(pstgmed != NULL, "stgmeg == NULL\n");
230 if(pstgmed) {
231 ok(pstgmed->tymed == TYMED_ISTREAM, "tymed=%u\n", pstgmed->tymed);
232 ok(U(*pstgmed).pstm != NULL, "pstm == NULL\n");
233 ok(pstgmed->pUnkForRelease != NULL, "pUnkForRelease == NULL\n");
234 }
235 }
236
237 if(U(*pstgmed).pstm) {
238 do hres = IStream_Read(U(*pstgmed).pstm, buf, 512, &readed);
239 while(hres == S_OK);
240 ok(hres == S_FALSE || hres == E_PENDING, "IStream_Read returned %08x\n", hres);
241 }
242
243 return S_OK;
244 }
245
246 static HRESULT WINAPI statusclb_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk)
247 {
248 ok(0, "unexpected call\n");
249 return E_NOTIMPL;
250 }
251
252 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
253 statusclb_QueryInterface,
254 statusclb_AddRef,
255 statusclb_Release,
256 statusclb_OnStartBinding,
257 statusclb_GetPriority,
258 statusclb_OnLowResource,
259 statusclb_OnProgress,
260 statusclb_OnStopBinding,
261 statusclb_GetBindInfo,
262 statusclb_OnDataAvailable,
263 statusclb_OnObjectAvailable
264 };
265
266 static IBindStatusCallback BindStatusCallback = { &BindStatusCallbackVtbl };
267
268 static void set_file_url(char *path)
269 {
270 char INDEX_HTML_A[MAX_PATH];
271
272 lstrcpyA(INDEX_HTML_A, "file:///");
273 lstrcatA(INDEX_HTML_A, path);
274 MultiByteToWideChar(CP_ACP, 0, INDEX_HTML_A, -1, INDEX_HTML, MAX_PATH);
275 }
276
277 static void create_file(void)
278 {
279 HANDLE file;
280 DWORD size;
281 CHAR path[MAX_PATH];
282
283 file = CreateFileA(wszIndexHtmlA, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
284 FILE_ATTRIBUTE_NORMAL, NULL);
285 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
286 if(file == INVALID_HANDLE_VALUE)
287 return;
288
289 WriteFile(file, szHtmlDoc, sizeof(szHtmlDoc)-1, &size, NULL);
290 CloseHandle(file);
291
292 GetCurrentDirectoryA(MAX_PATH, path);
293 lstrcatA(path, "\\");
294 lstrcatA(path, wszIndexHtmlA);
295 set_file_url(path);
296 }
297
298 static void test_URLOpenBlockingStreamW(void)
299 {
300 HRESULT hr;
301 IStream *pStream = NULL;
302 char buffer[256];
303
304 hr = URLOpenBlockingStreamW(NULL, NULL, &pStream, 0, &BindStatusCallback);
305 ok(hr == E_INVALIDARG, "URLOpenBlockingStreamW should have failed with E_INVALIDARG instead of 0x%08x\n", hr);
306 if (0) /* crashes on Win2k */
307 {
308 hr = URLOpenBlockingStreamW(NULL, INDEX_HTML, NULL, 0, &BindStatusCallback);
309 ok(hr == E_INVALIDARG, "URLOpenBlockingStreamW should have failed with E_INVALIDARG instead of 0x%08x\n", hr);
310 }
311
312 SET_EXPECT(GetBindInfo);
313 SET_EXPECT(QueryInterface_IServiceProvider);
314 SET_EXPECT(OnStartBinding);
315 SET_EXPECT(OnProgress_SENDINGREQUEST);
316 SET_EXPECT(OnProgress_MIMETYPEAVAILABLE);
317 SET_EXPECT(OnProgress_BEGINDOWNLOADDATA);
318 SET_EXPECT(OnProgress_ENDDOWNLOADDATA);
319 SET_EXPECT(OnStopBinding);
320
321 hr = URLOpenBlockingStreamW(NULL, INDEX_HTML, &pStream, 0, &BindStatusCallback);
322 ok(hr == S_OK, "URLOpenBlockingStreamW failed with error 0x%08x\n", hr);
323
324 CHECK_CALLED(GetBindInfo);
325 todo_wine CHECK_CALLED(QueryInterface_IServiceProvider);
326 CHECK_CALLED(OnStartBinding);
327 CHECK_CALLED(OnProgress_SENDINGREQUEST);
328 CHECK_CALLED(OnProgress_MIMETYPEAVAILABLE);
329 CHECK_CALLED(OnProgress_BEGINDOWNLOADDATA);
330 CHECK_CALLED(OnProgress_ENDDOWNLOADDATA);
331 CHECK_CALLED(OnStopBinding);
332
333 ok(pStream != NULL, "pStream is NULL\n");
334 if(pStream)
335 {
336 hr = IStream_Read(pStream, buffer, sizeof(buffer), NULL);
337 ok(hr == S_OK, "IStream_Read failed with error 0x%08x\n", hr);
338 ok(!memcmp(buffer, szHtmlDoc, sizeof(szHtmlDoc)-1), "read data differs from file\n");
339
340 IStream_Release(pStream);
341 }
342 }
343
344 static void test_URLOpenStreamW(void)
345 {
346 HRESULT hr;
347
348 hr = URLOpenStreamW(NULL, NULL, 0, &BindStatusCallback);
349 ok(hr == E_INVALIDARG, "URLOpenStreamW should have failed with E_INVALIDARG instead of 0x%08x\n", hr);
350
351 SET_EXPECT(GetBindInfo);
352 SET_EXPECT(QueryInterface_IServiceProvider);
353 SET_EXPECT(OnStartBinding);
354 SET_EXPECT(OnProgress_SENDINGREQUEST);
355 SET_EXPECT(OnProgress_MIMETYPEAVAILABLE);
356 SET_EXPECT(OnProgress_BEGINDOWNLOADDATA);
357 SET_EXPECT(OnProgress_ENDDOWNLOADDATA);
358 SET_EXPECT(OnDataAvailable);
359 SET_EXPECT(OnStopBinding);
360
361 hr = URLOpenStreamW(NULL, INDEX_HTML, 0, &BindStatusCallback);
362 ok(hr == S_OK, "URLOpenStreamW failed with error 0x%08x\n", hr);
363
364 CHECK_CALLED(GetBindInfo);
365 todo_wine CHECK_CALLED(QueryInterface_IServiceProvider);
366 CHECK_CALLED(OnStartBinding);
367 CHECK_CALLED(OnProgress_SENDINGREQUEST);
368 CHECK_CALLED(OnProgress_MIMETYPEAVAILABLE);
369 CHECK_CALLED(OnProgress_BEGINDOWNLOADDATA);
370 CHECK_CALLED(OnProgress_ENDDOWNLOADDATA);
371 CHECK_CALLED(OnDataAvailable);
372 CHECK_CALLED(OnStopBinding);
373 }
374
375 START_TEST(stream)
376 {
377 if(!GetProcAddress(GetModuleHandleA("urlmon.dll"), "CompareSecurityIds")) {
378 win_skip("Too old IE\n");
379 return;
380 }
381
382 create_file();
383 test_URLOpenBlockingStreamW();
384 test_URLOpenStreamW();
385 DeleteFileA(wszIndexHtmlA);
386 }