[WINHTTP_WINETEST] Sync with Wine Staging 1.7.55. CORE-10536
[reactos.git] / rostests / winetests / winhttp / winhttp.c
1 /*
2 * WinHTTP - tests
3 *
4 * Copyright 2008 Google (Zac Brown)
5 * Copyright 2015 Dmitry Timoshkov
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 #define WIN32_NO_STATUS
23 #define _INC_WINDOWS
24 #define COM_NO_WINDOWS_H
25
26 #define COBJMACROS
27 #include <stdarg.h>
28 #include <windef.h>
29 #include <winbase.h>
30 #include <winnls.h>
31 #include <ole2.h>
32 #include <winsock2.h>
33 //#include <ws2tcpip.h>
34 #include <winhttp.h>
35 #include <wincrypt.h>
36 #include <winreg.h>
37 //#include "initguid.h"
38 #include <httprequest.h>
39 #include <httprequestid.h>
40
41 #include <wine/test.h>
42
43 static const WCHAR test_useragent[] =
44 {'W','i','n','e',' ','R','e','g','r','e','s','s','i','o','n',' ','T','e','s','t',0};
45 static const WCHAR test_winehq[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
46 static const WCHAR localhostW[] = {'l','o','c','a','l','h','o','s','t',0};
47
48 static BOOL proxy_active(void)
49 {
50 WINHTTP_PROXY_INFO proxy_info;
51 BOOL active = FALSE;
52
53 SetLastError(0xdeadbeef);
54 if (WinHttpGetDefaultProxyConfiguration(&proxy_info))
55 {
56 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
57 "got %u\n", GetLastError());
58 active = (proxy_info.lpszProxy != NULL);
59 if (active)
60 GlobalFree(proxy_info.lpszProxy);
61 if (proxy_info.lpszProxyBypass != NULL)
62 GlobalFree(proxy_info.lpszProxyBypass);
63 }
64 else
65 active = FALSE;
66
67 return active;
68 }
69
70 static void test_QueryOption(void)
71 {
72 BOOL ret;
73 HINTERNET session, request, connection;
74 DWORD feature, size;
75
76 SetLastError(0xdeadbeef);
77 session = WinHttpOpen(test_useragent, 0, 0, 0, 0);
78 ok(session != NULL, "WinHttpOpen failed to open session, error %u\n", GetLastError());
79
80 SetLastError(0xdeadbeef);
81 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, NULL);
82 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
83 ok(GetLastError() == ERROR_INVALID_PARAMETER,
84 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
85
86 size = 0xdeadbeef;
87 SetLastError(0xdeadbeef);
88 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, &size);
89 ok(!ret, "should fail to query option\n");
90 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
91 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
92 ok(size == 4, "expected 4, got %u\n", size);
93
94 feature = 0xdeadbeef;
95 size = sizeof(feature) - 1;
96 SetLastError(0xdeadbeef);
97 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
98 ok(!ret, "should fail to query option\n");
99 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
100 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
101 ok(size == 4, "expected 4, got %u\n", size);
102
103 feature = 0xdeadbeef;
104 size = sizeof(feature) + 1;
105 SetLastError(0xdeadbeef);
106 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
107 ok(ret, "failed to query option %u\n", GetLastError());
108 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
109 "got %u\n", GetLastError());
110 ok(size == sizeof(feature), "WinHttpQueryOption should set the size: %u\n", size);
111 ok(feature == WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP,
112 "expected WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP, got %#x\n", feature);
113
114 SetLastError(0xdeadbeef);
115 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, sizeof(feature));
116 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
117 ok(GetLastError() == ERROR_INVALID_PARAMETER,
118 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
119
120 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
121 SetLastError(0xdeadbeef);
122 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature) - 1);
123 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
124 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
125 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
126
127 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
128 SetLastError(0xdeadbeef);
129 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature) + 1);
130 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
131 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
132 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
133
134 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
135 SetLastError(0xdeadbeef);
136 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature));
137 ok(ret, "failed to set redirect policy %u\n", GetLastError());
138
139 feature = 0xdeadbeef;
140 size = sizeof(feature);
141 SetLastError(0xdeadbeef);
142 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
143 ok(ret, "failed to query option %u\n", GetLastError());
144 ok(feature == WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS,
145 "expected WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS, got %#x\n", feature);
146
147 feature = WINHTTP_DISABLE_COOKIES;
148 SetLastError(0xdeadbeef);
149 ret = WinHttpSetOption(session, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
150 ok(!ret, "should fail to set disable feature for a session\n");
151 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
152 "expected ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, got %u\n", GetLastError());
153
154 SetLastError(0xdeadbeef);
155 connection = WinHttpConnect(session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
156 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u\n", GetLastError());
157
158 feature = WINHTTP_DISABLE_COOKIES;
159 SetLastError(0xdeadbeef);
160 ret = WinHttpSetOption(connection, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
161 ok(!ret, "should fail to set disable feature for a connection\n");
162 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
163 "expected ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, got %u\n", GetLastError());
164
165 SetLastError(0xdeadbeef);
166 request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
167 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
168 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
169 {
170 skip("Network unreachable, skipping the test\n");
171 goto done;
172 }
173
174 feature = 0xdeadbeef;
175 size = sizeof(feature);
176 SetLastError(0xdeadbeef);
177 ret = WinHttpQueryOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, &size);
178 ok(!ret, "should fail to query disable feature for a request\n");
179 ok(GetLastError() == ERROR_INVALID_PARAMETER,
180 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
181
182 feature = 0;
183 size = sizeof(feature);
184 SetLastError(0xdeadbeef);
185 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
186 ok(ret, "failed to set feature %u\n", GetLastError());
187
188 feature = 0xffffffff;
189 size = sizeof(feature);
190 SetLastError(0xdeadbeef);
191 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
192 ok(ret, "failed to set feature %u\n", GetLastError());
193
194 feature = WINHTTP_DISABLE_COOKIES;
195 size = sizeof(feature);
196 SetLastError(0xdeadbeef);
197 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
198 ok(ret, "failed to set feature %u\n", GetLastError());
199
200 size = 0;
201 SetLastError(0xdeadbeef);
202 ret = WinHttpQueryOption(request, WINHTTP_OPTION_DISABLE_FEATURE, NULL, &size);
203 ok(!ret, "should fail to query disable feature for a request\n");
204 ok(GetLastError() == ERROR_INVALID_PARAMETER,
205 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
206
207 SetLastError(0xdeadbeef);
208 ret = WinHttpCloseHandle(request);
209 ok(ret, "WinHttpCloseHandle failed on closing request: %u\n", GetLastError());
210
211 done:
212 SetLastError(0xdeadbeef);
213 ret = WinHttpCloseHandle(connection);
214 ok(ret, "WinHttpCloseHandle failed on closing connection: %u\n", GetLastError());
215 SetLastError(0xdeadbeef);
216 ret = WinHttpCloseHandle(session);
217 ok(ret, "WinHttpCloseHandle failed on closing session: %u\n", GetLastError());
218 }
219
220 static void test_OpenRequest (void)
221 {
222 BOOL ret;
223 HINTERNET session, request, connection;
224 DWORD err;
225
226 SetLastError(0xdeadbeef);
227 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
228 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
229 err = GetLastError();
230 ok(session != NULL, "WinHttpOpen failed to open session.\n");
231 ok(err == ERROR_SUCCESS, "got %u\n", err);
232
233 /* Test with a bad server name */
234 SetLastError(0xdeadbeef);
235 connection = WinHttpConnect(session, NULL, INTERNET_DEFAULT_HTTP_PORT, 0);
236 err = GetLastError();
237 ok (connection == NULL, "WinHttpConnect succeeded in opening connection to NULL server argument.\n");
238 ok(err == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u.\n", err);
239
240 /* Test with a valid server name */
241 SetLastError(0xdeadbeef);
242 connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
243 err = GetLastError();
244 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", err);
245 ok(err == ERROR_SUCCESS || broken(err == WSAEINVAL) /* < win7 */, "got %u\n", err);
246
247 SetLastError(0xdeadbeef);
248 request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
249 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
250 err = GetLastError();
251 if (request == NULL && err == ERROR_WINHTTP_NAME_NOT_RESOLVED)
252 {
253 skip("Network unreachable, skipping.\n");
254 goto done;
255 }
256 ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", err);
257 ok(err == ERROR_SUCCESS, "got %u\n", err);
258
259 SetLastError(0xdeadbeef);
260 ret = WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, NULL, 0, 0, 0);
261 err = GetLastError();
262 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
263 {
264 skip("Connection failed, skipping.\n");
265 goto done;
266 }
267 ok(ret, "WinHttpSendRequest failed: %u\n", err);
268 ok(err == ERROR_SUCCESS, "got %u\n", err);
269
270 SetLastError(0xdeadbeef);
271 ret = WinHttpCloseHandle(request);
272 err = GetLastError();
273 ok(ret, "WinHttpCloseHandle failed on closing request, got %u.\n", err);
274 ok(err == ERROR_SUCCESS, "got %u\n", err);
275
276 done:
277 ret = WinHttpCloseHandle(connection);
278 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
279 ret = WinHttpCloseHandle(session);
280 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
281
282 }
283
284 static void test_empty_headers_param(void)
285 {
286 static const WCHAR empty[] = {0};
287 HINTERNET ses, con, req;
288 DWORD err;
289 BOOL ret;
290
291 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
292 ok(ses != NULL, "failed to open session %u\n", GetLastError());
293
294 con = WinHttpConnect(ses, test_winehq, 80, 0);
295 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
296
297 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
298 ok(req != NULL, "failed to open a request %u\n", GetLastError());
299
300 ret = WinHttpSendRequest(req, empty, 0, NULL, 0, 0, 0);
301 err = GetLastError();
302 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
303 {
304 skip("connection failed, skipping\n");
305 goto done;
306 }
307 ok(ret, "failed to send request %u\n", GetLastError());
308
309 done:
310 WinHttpCloseHandle(req);
311 WinHttpCloseHandle(con);
312 WinHttpCloseHandle(ses);
313 }
314
315 static void test_SendRequest (void)
316 {
317 static const WCHAR content_type[] =
318 {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t','i','o','n',
319 '/','x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o','d','e','d',0};
320 static const WCHAR test_file[] = {'t','e','s','t','s','/','p','o','s','t','.','p','h','p',0};
321 static const WCHAR test_verb[] = {'P','O','S','T',0};
322 static CHAR post_data[] = "mode=Test";
323 static const char test_post[] = "mode => Test\0\n";
324 HINTERNET session, request, connection;
325 DWORD header_len, optional_len, total_len, bytes_rw, size, err;
326 DWORD_PTR context;
327 BOOL ret;
328 CHAR buffer[256];
329 int i;
330
331 header_len = -1L;
332 total_len = optional_len = sizeof(post_data);
333 memset(buffer, 0xff, sizeof(buffer));
334
335 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
336 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
337 ok(session != NULL, "WinHttpOpen failed to open session.\n");
338
339 connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
340 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
341
342 request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
343 WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
344 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
345 {
346 skip("Network unreachable, skipping.\n");
347 goto done;
348 }
349 ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError());
350 if (!request) goto done;
351
352 context = 0xdeadbeef;
353 ret = WinHttpSetOption(request, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(context));
354 ok(ret, "WinHttpSetOption failed: %u\n", GetLastError());
355
356 context++;
357 ret = WinHttpSendRequest(request, content_type, header_len, post_data, optional_len, total_len, context);
358 err = GetLastError();
359 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
360 {
361 skip("connection failed, skipping\n");
362 goto done;
363 }
364 ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError());
365
366 context = 0;
367 size = sizeof(context);
368 ret = WinHttpQueryOption(request, WINHTTP_OPTION_CONTEXT_VALUE, &context, &size);
369 ok(ret, "WinHttpQueryOption failed: %u\n", GetLastError());
370 ok(context == 0xdeadbef0, "expected 0xdeadbef0, got %lx\n", context);
371
372 for (i = 3; post_data[i]; i++)
373 {
374 bytes_rw = -1;
375 SetLastError(0xdeadbeef);
376 ret = WinHttpWriteData(request, &post_data[i], 1, &bytes_rw);
377 if (ret)
378 {
379 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %u.\n", GetLastError());
380 ok(bytes_rw == 1, "WinHttpWriteData failed, wrote %u bytes instead of 1 byte.\n", bytes_rw);
381 }
382 else /* Since we already passed all optional data in WinHttpSendRequest Win7 fails our WinHttpWriteData call */
383 {
384 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER got %u.\n", GetLastError());
385 ok(bytes_rw == -1, "Expected bytes_rw to remain unchanged.\n");
386 }
387 }
388
389 SetLastError(0xdeadbeef);
390 ret = WinHttpReceiveResponse(request, NULL);
391 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == ERROR_NO_TOKEN) /* < win7 */,
392 "Expected ERROR_SUCCESS got %u.\n", GetLastError());
393 ok(ret == TRUE, "WinHttpReceiveResponse failed: %u.\n", GetLastError());
394
395 bytes_rw = -1;
396 ret = WinHttpReadData(request, buffer, sizeof(buffer) - 1, &bytes_rw);
397 ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
398
399 ok(bytes_rw == sizeof(test_post) - 1, "Read %u bytes\n", bytes_rw);
400 ok(!memcmp(buffer, test_post, sizeof(test_post) - 1), "Data read did not match.\n");
401
402 done:
403 ret = WinHttpCloseHandle(request);
404 ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
405 ret = WinHttpCloseHandle(connection);
406 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
407 ret = WinHttpCloseHandle(session);
408 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
409 }
410
411 static void test_WinHttpTimeFromSystemTime(void)
412 {
413 BOOL ret;
414 static const SYSTEMTIME time = {2008, 7, 1, 28, 10, 5, 52, 0};
415 static const WCHAR expected_string[] =
416 {'M','o','n',',',' ','2','8',' ','J','u','l',' ','2','0','0','8',' ',
417 '1','0',':','0','5',':','5','2',' ','G','M','T',0};
418 WCHAR time_string[WINHTTP_TIME_FORMAT_BUFSIZE+1];
419 DWORD err;
420
421 SetLastError(0xdeadbeef);
422 ret = WinHttpTimeFromSystemTime(&time, NULL);
423 err = GetLastError();
424 ok(!ret, "WinHttpTimeFromSystemTime succeeded\n");
425 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
426
427 SetLastError(0xdeadbeef);
428 ret = WinHttpTimeFromSystemTime(NULL, time_string);
429 err = GetLastError();
430 ok(!ret, "WinHttpTimeFromSystemTime succeeded\n");
431 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
432
433 SetLastError(0xdeadbeef);
434 ret = WinHttpTimeFromSystemTime(&time, time_string);
435 err = GetLastError();
436 ok(ret, "WinHttpTimeFromSystemTime failed: %u\n", err);
437 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
438 ok(memcmp(time_string, expected_string, sizeof(expected_string)) == 0,
439 "Time string returned did not match expected time string.\n");
440 }
441
442 static void test_WinHttpTimeToSystemTime(void)
443 {
444 BOOL ret;
445 SYSTEMTIME time;
446 static const SYSTEMTIME expected_time = {2008, 7, 1, 28, 10, 5, 52, 0};
447 static const WCHAR time_string1[] =
448 {'M','o','n',',',' ','2','8',' ','J','u','l',' ','2','0','0','8',' ',
449 + '1','0',':','0','5',':','5','2',' ','G','M','T','\n',0};
450 static const WCHAR time_string2[] =
451 {' ','m','o','n',' ','2','8',' ','j','u','l',' ','2','0','0','8',' ',
452 '1','0',' ','0','5',' ','5','2','\n',0};
453 DWORD err;
454
455 SetLastError(0xdeadbeef);
456 ret = WinHttpTimeToSystemTime(time_string1, NULL);
457 err = GetLastError();
458 ok(!ret, "WinHttpTimeToSystemTime succeeded\n");
459 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
460
461 SetLastError(0xdeadbeef);
462 ret = WinHttpTimeToSystemTime(NULL, &time);
463 err = GetLastError();
464 ok(!ret, "WinHttpTimeToSystemTime succeeded\n");
465 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
466
467 SetLastError(0xdeadbeef);
468 ret = WinHttpTimeToSystemTime(time_string1, &time);
469 err = GetLastError();
470 ok(ret, "WinHttpTimeToSystemTime failed: %u\n", err);
471 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
472 ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
473 "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
474
475 SetLastError(0xdeadbeef);
476 ret = WinHttpTimeToSystemTime(time_string2, &time);
477 err = GetLastError();
478 ok(ret, "WinHttpTimeToSystemTime failed: %u\n", err);
479 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
480 ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
481 "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
482 }
483
484 static void test_WinHttpAddHeaders(void)
485 {
486 HINTERNET session, request, connection;
487 BOOL ret, reverse;
488 WCHAR buffer[MAX_PATH];
489 WCHAR check_buffer[MAX_PATH];
490 DWORD err, index, len, oldlen;
491
492 static const WCHAR test_file[] = {'/','p','o','s','t','t','e','s','t','.','p','h','p',0};
493 static const WCHAR test_verb[] = {'P','O','S','T',0};
494 static const WCHAR test_header_begin[] =
495 {'P','O','S','T',' ','/','p','o','s','t','t','e','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
496 static const WCHAR full_path_test_header_begin[] =
497 {'P','O','S','T',' ','h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',':','8','0',
498 '/','p','o','s','t','t','e','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
499 static const WCHAR test_header_end[] = {'\r','\n','\r','\n',0};
500 static const WCHAR test_header_name[] = {'W','a','r','n','i','n','g',0};
501 static const WCHAR test_header_name2[] = {'n','a','m','e',0};
502 static const WCHAR test_header_name3[] = {'a',0};
503 static const WCHAR test_header_range[] = {'R','a','n','g','e',0};
504 static const WCHAR test_header_range_bytes[] = {'R','a','n','g','e',':',' ','b','y','t','e','s','=','0','-','7','7','3','\r','\n',0};
505 static const WCHAR test_header_bytes[] = {'b','y','t','e','s','=','0','-','7','7','3',0};
506
507 static const WCHAR test_flag_coalesce[] = {'t','e','s','t','2',',',' ','t','e','s','t','4',0};
508 static const WCHAR test_flag_coalesce_reverse[] = {'t','e','s','t','3',',',' ','t','e','s','t','4',0};
509 static const WCHAR test_flag_coalesce_comma[] =
510 {'t','e','s','t','2',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',0};
511 static const WCHAR test_flag_coalesce_comma_reverse[] =
512 {'t','e','s','t','3',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',0};
513 static const WCHAR test_flag_coalesce_semicolon[] =
514 {'t','e','s','t','2',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',';',' ','t','e','s','t','6',0};
515 static const WCHAR test_flag_coalesce_semicolon_reverse[] =
516 {'t','e','s','t','3',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',';',' ','t','e','s','t','6',0};
517
518 static const WCHAR field[] = {'f','i','e','l','d',0};
519 static const WCHAR value[] = {'v','a','l','u','e',' ',0};
520 static const WCHAR value_nospace[] = {'v','a','l','u','e',0};
521 static const WCHAR empty[] = {0};
522
523 static const WCHAR test_headers[][14] =
524 {
525 {'W','a','r','n','i','n','g',':','t','e','s','t','1',0},
526 {'W','a','r','n','i','n','g',':','t','e','s','t','2',0},
527 {'W','a','r','n','i','n','g',':','t','e','s','t','3',0},
528 {'W','a','r','n','i','n','g',':','t','e','s','t','4',0},
529 {'W','a','r','n','i','n','g',':','t','e','s','t','5',0},
530 {'W','a','r','n','i','n','g',':','t','e','s','t','6',0},
531 {'W','a','r','n','i','n','g',':','t','e','s','t','7',0},
532 {0},
533 {':',0},
534 {'a',':',0},
535 {':','b',0},
536 {'c','d',0},
537 {' ','e',' ',':','f',0},
538 {'f','i','e','l','d',':',' ','v','a','l','u','e',' ',0},
539 {'n','a','m','e',':',' ','v','a','l','u','e',0},
540 {'n','a','m','e',':',0}
541 };
542 static const WCHAR test_indices[][6] =
543 {
544 {'t','e','s','t','1',0},
545 {'t','e','s','t','2',0},
546 {'t','e','s','t','3',0},
547 {'t','e','s','t','4',0}
548 };
549
550 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
551 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
552 ok(session != NULL, "WinHttpOpen failed to open session.\n");
553
554 connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
555 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
556
557 request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
558 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
559 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
560 {
561 skip("Network unreachable, skipping.\n");
562 goto done;
563 }
564 ok(request != NULL, "WinHttpOpenRequest failed to open a request, error: %u.\n", GetLastError());
565
566 index = 0;
567 len = sizeof(buffer);
568 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
569 test_header_name, buffer, &len, &index);
570 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, found 'Warning' header.\n");
571 SetLastError(0xdeadbeef);
572 ret = WinHttpAddRequestHeaders(request, test_headers[0], -1L, WINHTTP_ADDREQ_FLAG_ADD);
573 err = GetLastError();
574 ok(ret, "WinHttpAddRequestHeader failed to add new header, got %d with error %u.\n", ret, err);
575 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
576
577 index = 0;
578 len = sizeof(buffer);
579 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
580 test_header_name, buffer, &len, &index);
581 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
582 ok(index == 1, "WinHttpQueryHeaders failed: header index not incremented\n");
583 ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders failed: incorrect string returned\n");
584 ok(len == 5*sizeof(WCHAR), "WinHttpQueryHeaders failed: invalid length returned, expected 5, got %d\n", len);
585
586 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
587 test_header_name, buffer, &len, &index);
588 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, second index should not exist.\n");
589
590 /* Try to fetch the header info with a buffer that's big enough to fit the
591 * string but not the NULL terminator.
592 */
593 index = 0;
594 len = 5*sizeof(WCHAR);
595 memset(check_buffer, 0xab, sizeof(check_buffer));
596 memcpy(buffer, check_buffer, sizeof(buffer));
597 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
598 test_header_name, buffer, &len, &index);
599 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded with a buffer that's too small.\n");
600 ok(memcmp(buffer, check_buffer, sizeof(buffer)) == 0,
601 "WinHttpQueryHeaders failed, modified the buffer when it should not have.\n");
602 ok(len == 6*sizeof(WCHAR), "WinHttpQueryHeaders returned invalid length, expected 12, got %d\n", len);
603
604 /* Try with a NULL buffer */
605 index = 0;
606 len = sizeof(buffer);
607 SetLastError(0xdeadbeef);
608 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
609 test_header_name, NULL, &len, &index);
610 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
611 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
612 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
613 ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
614
615 /* Try with a NULL buffer and a length that's too small */
616 index = 0;
617 len = 10;
618 SetLastError(0xdeadbeef);
619 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
620 test_header_name, NULL, &len, &index);
621 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
622 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
623 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICENT_BUFFER, go %u\n", GetLastError());
624 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
625 ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
626
627 index = 0;
628 len = 0;
629 SetLastError(0xdeadbeef);
630 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
631 test_header_name, NULL, &len, &index);
632 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
633 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
634 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
635 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
636 ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
637
638 /* valid query */
639 oldlen = len;
640 index = 0;
641 len = sizeof(buffer);
642 memset(buffer, 0xff, sizeof(buffer));
643 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
644 test_header_name, buffer, &len, &index);
645 ok(ret == TRUE, "WinHttpQueryHeaders failed: got %d\n", ret);
646 ok(len + sizeof(WCHAR) <= oldlen, "WinHttpQueryHeaders resulting length longer than advertized.\n");
647 ok((len < sizeof(buffer) - sizeof(WCHAR)) && buffer[len / sizeof(WCHAR)] == 0, "WinHttpQueryHeaders did not append NULL terminator\n");
648 ok(len == lstrlenW(buffer) * sizeof(WCHAR), "WinHttpQueryHeaders returned incorrect length.\n");
649 ok(memcmp(buffer, test_header_begin, sizeof(test_header_begin)) == 0 ||
650 memcmp(buffer, full_path_test_header_begin, sizeof(full_path_test_header_begin)) == 0,
651 "WinHttpQueryHeaders returned invalid beginning of header string.\n");
652 ok(memcmp(buffer + lstrlenW(buffer) - 4, test_header_end, sizeof(test_header_end)) == 0,
653 "WinHttpQueryHeaders returned invalid end of header string.\n");
654 ok(index == 0, "WinHttpQueryHeaders incremented header index.\n");
655
656 index = 0;
657 len = 0;
658 SetLastError(0xdeadbeef);
659 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
660 test_header_name, NULL, &len, &index);
661 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
662 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
663 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
664 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
665 ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
666
667 oldlen = len;
668 index = 0;
669 len = sizeof(buffer);
670 memset(buffer, 0xff, sizeof(buffer));
671 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
672 test_header_name, buffer, &len, &index);
673 ok(ret == TRUE, "WinHttpQueryHeaders failed %u\n", GetLastError());
674 ok(len + sizeof(WCHAR) <= oldlen, "resulting length longer than advertized\n");
675 ok((len < sizeof(buffer) - sizeof(WCHAR)) && !buffer[len / sizeof(WCHAR)] && !buffer[len / sizeof(WCHAR) - 1],
676 "no double NULL terminator\n");
677 ok(memcmp(buffer, test_header_begin, sizeof(test_header_begin)) == 0 ||
678 memcmp(buffer, full_path_test_header_begin, sizeof(full_path_test_header_begin)) == 0,
679 "invalid beginning of header string.\n");
680 ok(index == 0, "header index was incremented\n");
681
682 /* tests for more indices */
683 ret = WinHttpAddRequestHeaders(request, test_headers[1], -1L, WINHTTP_ADDREQ_FLAG_ADD);
684 ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header: %d\n", ret);
685
686 index = 0;
687 len = sizeof(buffer);
688 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
689 test_header_name, buffer, &len, &index);
690 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
691 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
692 ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
693
694 len = sizeof(buffer);
695 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
696 test_header_name, buffer, &len, &index);
697 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
698 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
699 ok(memcmp(buffer, test_indices[1], sizeof(test_indices[1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
700
701 ret = WinHttpAddRequestHeaders(request, test_headers[2], -1L, WINHTTP_ADDREQ_FLAG_REPLACE);
702 ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header.\n");
703
704 index = 0;
705 len = sizeof(buffer);
706 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
707 test_header_name, buffer, &len, &index);
708 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
709 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
710 reverse = (memcmp(buffer, test_indices[1], sizeof(test_indices[1])) != 0); /* Win7 returns values in reverse order of adding */
711 ok(memcmp(buffer, test_indices[reverse ? 2 : 1], sizeof(test_indices[reverse ? 2 : 1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
712
713 len = sizeof(buffer);
714 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
715 test_header_name, buffer, &len, &index);
716 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
717 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
718 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
719
720 /* add if new flag */
721 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW);
722 ok(ret == FALSE, "WinHttpAddRequestHeaders incorrectly replaced existing header.\n");
723
724 index = 0;
725 len = sizeof(buffer);
726 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
727 test_header_name, buffer, &len, &index);
728 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
729 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
730 ok(memcmp(buffer, test_indices[reverse ? 2 : 1], sizeof(test_indices[reverse ? 2 : 1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
731
732 len = sizeof(buffer);
733 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
734 test_header_name, buffer, &len, &index);
735 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
736 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
737 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
738
739 len = sizeof(buffer);
740 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
741 test_header_name, buffer, &len, &index);
742 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
743
744 /* coalesce flag */
745 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_COALESCE);
746 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE.\n");
747
748 index = 0;
749 len = sizeof(buffer);
750 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
751 test_header_name, buffer, &len, &index);
752 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
753 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
754 ok(memcmp(buffer, reverse ? test_flag_coalesce_reverse : test_flag_coalesce,
755 reverse ? sizeof(test_flag_coalesce_reverse) : sizeof(test_flag_coalesce)) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
756
757 len = sizeof(buffer);
758 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
759 test_header_name, buffer, &len, &index);
760 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
761 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
762 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
763
764 len = sizeof(buffer);
765 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
766 test_header_name, buffer, &len, &index);
767 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
768
769 /* coalesce with comma flag */
770 ret = WinHttpAddRequestHeaders(request, test_headers[4], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA);
771 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA.\n");
772
773 index = 0;
774 len = sizeof(buffer);
775 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
776 test_header_name, buffer, &len, &index);
777 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
778 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
779 ok(memcmp(buffer, reverse ? test_flag_coalesce_comma_reverse : test_flag_coalesce_comma,
780 reverse ? sizeof(test_flag_coalesce_comma_reverse) : sizeof(test_flag_coalesce_comma)) == 0,
781 "WinHttpQueryHeaders returned incorrect string.\n");
782
783 len = sizeof(buffer);
784 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
785 test_header_name, buffer, &len, &index);
786 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
787 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
788 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
789
790 len = sizeof(buffer);
791 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
792 test_header_name, buffer, &len, &index);
793 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
794
795
796 /* coalesce with semicolon flag */
797 ret = WinHttpAddRequestHeaders(request, test_headers[5], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON);
798 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON.\n");
799
800 index = 0;
801 len = sizeof(buffer);
802 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
803 test_header_name, buffer, &len, &index);
804 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
805 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
806 ok(memcmp(buffer, reverse ? test_flag_coalesce_semicolon_reverse : test_flag_coalesce_semicolon,
807 reverse ? sizeof(test_flag_coalesce_semicolon_reverse) : sizeof(test_flag_coalesce_semicolon)) == 0,
808 "WinHttpQueryHeaders returned incorrect string.\n");
809
810 len = sizeof(buffer);
811 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
812 test_header_name, buffer, &len, &index);
813 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
814 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
815 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
816
817 len = sizeof(buffer);
818 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
819 test_header_name, buffer, &len, &index);
820 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
821
822 /* add and replace flags */
823 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
824 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE.\n");
825
826 index = 0;
827 len = sizeof(buffer);
828 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
829 test_header_name, buffer, &len, &index);
830 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
831 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
832 ok(memcmp(buffer, test_indices[reverse ? 3 : 2], sizeof(test_indices[reverse ? 3 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
833
834 len = sizeof(buffer);
835 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
836 test_header_name, buffer, &len, &index);
837 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
838 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
839 ok(memcmp(buffer, test_indices[reverse ? 1 : 3], sizeof(test_indices[reverse ? 1 : 3])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
840
841 len = sizeof(buffer);
842 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
843 test_header_name, buffer, &len, &index);
844 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
845
846 ret = WinHttpAddRequestHeaders(request, test_headers[8], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
847 ok(!ret, "WinHttpAddRequestHeaders failed\n");
848
849 ret = WinHttpAddRequestHeaders(request, test_headers[9], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
850 ok(ret, "WinHttpAddRequestHeaders failed\n");
851
852 index = 0;
853 memset(buffer, 0xff, sizeof(buffer));
854 len = sizeof(buffer);
855 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
856 test_header_name3, buffer, &len, &index);
857 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
858 ok(!memcmp(buffer, empty, sizeof(empty)), "unexpected result\n");
859
860 ret = WinHttpAddRequestHeaders(request, test_headers[10], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
861 ok(!ret, "WinHttpAddRequestHeaders failed\n");
862
863 ret = WinHttpAddRequestHeaders(request, test_headers[11], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
864 ok(!ret, "WinHttpAddRequestHeaders failed\n");
865
866 ret = WinHttpAddRequestHeaders(request, test_headers[12], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
867 ok(!ret, "WinHttpAddRequestHeaders failed\n");
868
869 ret = WinHttpAddRequestHeaders(request, test_headers[13], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
870 ok(ret, "WinHttpAddRequestHeaders failed\n");
871
872 index = 0;
873 buffer[0] = 0;
874 len = sizeof(buffer);
875 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
876 field, buffer, &len, &index);
877 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
878 ok(!memcmp(buffer, value, sizeof(value)) || ! memcmp(buffer, value_nospace, sizeof(value_nospace)), "unexpected result\n");
879
880 SetLastError(0xdeadbeef);
881 ret = WinHttpAddRequestHeaders(request, test_header_range_bytes, 0,
882 WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
883 err = GetLastError();
884 ok(!ret, "unexpected success\n");
885 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
886
887 ret = WinHttpAddRequestHeaders(request, test_header_range_bytes, ~0u,
888 WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
889 ok(ret, "failed to add header: %u\n", GetLastError());
890
891 index = 0;
892 len = sizeof(buffer);
893 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
894 test_header_range, buffer, &len, &index);
895 ok(ret, "failed to get range header %u\n", GetLastError());
896 ok(!memcmp(buffer, test_header_bytes, sizeof(test_header_bytes)), "incorrect string returned\n");
897 ok(len == lstrlenW(test_header_bytes) * sizeof(WCHAR), "wrong length %u\n", len);
898 ok(index == 1, "wrong index %u\n", index);
899
900 index = 0;
901 len = sizeof(buffer);
902 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
903 test_header_name2, buffer, &len, &index);
904 ok(!ret, "unexpected success\n");
905
906 SetLastError(0xdeadbeef);
907 ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
908 err = GetLastError();
909 ok(!ret, "unexpected success\n");
910 ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
911
912 ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
913 ok(ret, "got %u\n", GetLastError());
914
915 index = 0;
916 len = sizeof(buffer);
917 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
918 test_header_name2, buffer, &len, &index);
919 ok(ret, "got %u\n", GetLastError());
920 ok(index == 1, "wrong index %u\n", index);
921 ok(!memcmp(buffer, value_nospace, sizeof(value_nospace)), "incorrect string\n");
922
923 ret = WinHttpAddRequestHeaders(request, test_headers[15], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
924 ok(ret, "got %u\n", GetLastError());
925
926 index = 0;
927 len = sizeof(buffer);
928 SetLastError(0xdeadbeef);
929 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
930 test_header_name2, buffer, &len, &index);
931 err = GetLastError();
932 ok(!ret, "unexpected success\n");
933 ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
934
935 ret = WinHttpAddRequestHeaders(request, test_headers[14], -1L, 0);
936 ok(ret, "got %u\n", GetLastError());
937
938 index = 0;
939 len = sizeof(buffer);
940 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
941 test_header_name2, buffer, &len, &index);
942 ok(ret, "got %u\n", GetLastError());
943 ok(index == 1, "wrong index %u\n", index);
944 ok(!memcmp(buffer, value_nospace, sizeof(value_nospace)), "incorrect string\n");
945
946 ret = WinHttpCloseHandle(request);
947 ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
948 done:
949 ret = WinHttpCloseHandle(connection);
950 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
951 ret = WinHttpCloseHandle(session);
952 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
953
954 }
955
956 static void CALLBACK cert_error(HINTERNET handle, DWORD_PTR ctx, DWORD status, LPVOID buf, DWORD len)
957 {
958 DWORD flags = *(DWORD *)buf;
959
960 if (!flags)
961 {
962 trace("WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR\n");
963 return;
964 }
965 #define X(x) if (flags & x) trace("%s\n", #x);
966 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED)
967 X(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT)
968 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED)
969 X(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA)
970 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID)
971 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID)
972 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE)
973 #undef X
974 }
975
976 static void test_secure_connection(void)
977 {
978 HINTERNET ses, con, req;
979 DWORD size, status, policy, bitness, read_size, err;
980 BOOL ret;
981 CERT_CONTEXT *cert;
982 WINHTTP_CERTIFICATE_INFO info;
983 char buffer[32];
984
985 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
986 ok(ses != NULL, "failed to open session %u\n", GetLastError());
987
988 policy = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
989 ret = WinHttpSetOption(ses, WINHTTP_OPTION_REDIRECT_POLICY, &policy, sizeof(policy));
990 ok(ret, "failed to set redirect policy %u\n", GetLastError());
991
992 con = WinHttpConnect(ses, test_winehq, 443, 0);
993 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
994
995 /* try without setting WINHTTP_FLAG_SECURE */
996 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
997 ok(req != NULL, "failed to open a request %u\n", GetLastError());
998
999 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1000 err = GetLastError();
1001 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
1002 {
1003 skip("Connection failed, skipping.\n");
1004 goto cleanup;
1005 }
1006 ok(ret, "failed to send request %u\n", GetLastError());
1007
1008 ret = WinHttpReceiveResponse(req, NULL);
1009 ok(!ret || proxy_active(), "succeeded unexpectedly\n");
1010
1011 size = 0;
1012 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL);
1013 ok(!ret, "succeeded unexpectedly\n");
1014
1015 WinHttpCloseHandle(req);
1016
1017 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, WINHTTP_FLAG_SECURE);
1018 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1019
1020 WinHttpSetStatusCallback(req, cert_error, WINHTTP_CALLBACK_STATUS_SECURE_FAILURE, 0);
1021
1022 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1023 err = GetLastError();
1024 if (!ret && (err == ERROR_WINHTTP_SECURE_FAILURE || err == ERROR_WINHTTP_CANNOT_CONNECT ||
1025 err == ERROR_WINHTTP_TIMEOUT))
1026 {
1027 skip("secure connection failed, skipping remaining secure tests\n");
1028 goto cleanup;
1029 }
1030 ok(ret, "failed to send request %u\n", GetLastError());
1031
1032 size = sizeof(cert);
1033 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert, &size );
1034 ok(ret, "failed to retrieve certificate context %u\n", GetLastError());
1035 if (ret) CertFreeCertificateContext(cert);
1036
1037 size = sizeof(bitness);
1038 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_KEY_BITNESS, &bitness, &size );
1039 ok(ret, "failed to retrieve key bitness %u\n", GetLastError());
1040
1041 size = sizeof(info);
1042 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT, &info, &size );
1043 ok(ret, "failed to retrieve certificate info %u\n", GetLastError());
1044
1045 if (ret)
1046 {
1047 trace("lpszSubjectInfo %s\n", wine_dbgstr_w(info.lpszSubjectInfo));
1048 trace("lpszIssuerInfo %s\n", wine_dbgstr_w(info.lpszIssuerInfo));
1049 trace("lpszProtocolName %s\n", wine_dbgstr_w(info.lpszProtocolName));
1050 trace("lpszSignatureAlgName %s\n", wine_dbgstr_w(info.lpszSignatureAlgName));
1051 trace("lpszEncryptionAlgName %s\n", wine_dbgstr_w(info.lpszEncryptionAlgName));
1052 trace("dwKeySize %u\n", info.dwKeySize);
1053 }
1054
1055 ret = WinHttpReceiveResponse(req, NULL);
1056 ok(ret, "failed to receive response %u\n", GetLastError());
1057
1058 status = 0xdeadbeef;
1059 size = sizeof(status);
1060 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1061 ok(ret, "failed unexpectedly %u\n", GetLastError());
1062 ok(status == 200, "request failed unexpectedly %u\n", status);
1063
1064 size = 0;
1065 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL);
1066 ok(!ret, "succeeded unexpectedly\n");
1067
1068 read_size = 0;
1069 for (;;)
1070 {
1071 size = 0;
1072 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
1073 ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
1074 if (!size) break;
1075 read_size += size;
1076 }
1077 ok(read_size > 2014, "read_size = %u\n", read_size);
1078
1079 cleanup:
1080 WinHttpCloseHandle(req);
1081 WinHttpCloseHandle(con);
1082 WinHttpCloseHandle(ses);
1083 }
1084
1085 static void test_request_parameter_defaults(void)
1086 {
1087 static const WCHAR empty[] = {0};
1088 HINTERNET ses, con, req;
1089 DWORD size, status, error;
1090 WCHAR *version;
1091 BOOL ret;
1092
1093 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1094 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1095
1096 con = WinHttpConnect(ses, test_winehq, 0, 0);
1097 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1098
1099 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1100 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1101
1102 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1103 error = GetLastError();
1104 if (!ret && (error == ERROR_WINHTTP_CANNOT_CONNECT || error == ERROR_WINHTTP_TIMEOUT))
1105 {
1106 skip("connection failed, skipping\n");
1107 goto done;
1108 }
1109 ok(ret, "failed to send request %u\n", GetLastError());
1110
1111 ret = WinHttpReceiveResponse(req, NULL);
1112 if (!ret && GetLastError() == ERROR_WINHTTP_INVALID_SERVER_RESPONSE) /* win2k */
1113 {
1114 win_skip("invalid response\n");
1115 goto done;
1116 }
1117 ok(ret, "failed to receive response %u\n", GetLastError());
1118
1119 status = 0xdeadbeef;
1120 size = sizeof(status);
1121 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1122 ok(ret, "failed unexpectedly %u\n", GetLastError());
1123 ok(status == 200, "request failed unexpectedly %u\n", status);
1124
1125 WinHttpCloseHandle(req);
1126
1127 req = WinHttpOpenRequest(con, empty, empty, empty, NULL, NULL, 0);
1128 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1129
1130 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1131 error = GetLastError();
1132 if (!ret && (error == ERROR_WINHTTP_CANNOT_CONNECT || error == ERROR_WINHTTP_TIMEOUT))
1133 {
1134 skip("connection failed, skipping\n");
1135 goto done;
1136 }
1137 ok(ret, "failed to send request %u\n", GetLastError());
1138
1139 ret = WinHttpReceiveResponse(req, NULL);
1140 ok(ret, "failed to receive response %u\n", GetLastError());
1141
1142 size = 0;
1143 SetLastError(0xdeadbeef);
1144 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, NULL, &size, NULL);
1145 error = GetLastError();
1146 ok(!ret, "succeeded unexpectedly\n");
1147 ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error);
1148
1149 version = HeapAlloc(GetProcessHeap(), 0, size);
1150 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, version, &size, NULL);
1151 ok(ret, "failed unexpectedly %u\n", GetLastError());
1152 ok(lstrlenW(version) == size / sizeof(WCHAR), "unexpected size %u\n", size);
1153 HeapFree(GetProcessHeap(), 0, version);
1154
1155 status = 0xdeadbeef;
1156 size = sizeof(status);
1157 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1158 ok(ret, "failed unexpectedly %u\n", GetLastError());
1159 ok(status == 200, "request failed unexpectedly %u\n", status);
1160
1161 done:
1162 WinHttpCloseHandle(req);
1163 WinHttpCloseHandle(con);
1164 WinHttpCloseHandle(ses);
1165 }
1166
1167 static const WCHAR Connections[] = {
1168 'S','o','f','t','w','a','r','e','\\',
1169 'M','i','c','r','o','s','o','f','t','\\',
1170 'W','i','n','d','o','w','s','\\',
1171 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1172 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
1173 'C','o','n','n','e','c','t','i','o','n','s',0 };
1174 static const WCHAR WinHttpSettings[] = {
1175 'W','i','n','H','t','t','p','S','e','t','t','i','n','g','s',0 };
1176
1177 static DWORD get_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD *type )
1178 {
1179 LONG l;
1180 HKEY key;
1181 DWORD ret = 0;
1182
1183 l = RegOpenKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, KEY_READ, &key );
1184 if (!l)
1185 {
1186 DWORD size = 0;
1187
1188 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, NULL, &size );
1189 if (!l)
1190 {
1191 if (size <= len)
1192 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, buf,
1193 &size );
1194 if (!l)
1195 ret = size;
1196 }
1197 RegCloseKey( key );
1198 }
1199 return ret;
1200 }
1201
1202 static void set_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD type )
1203 {
1204 LONG l;
1205 HKEY key;
1206
1207 l = RegCreateKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, NULL, 0,
1208 KEY_WRITE, NULL, &key, NULL );
1209 if (!l)
1210 {
1211 if (len)
1212 RegSetValueExW( key, WinHttpSettings, 0, type, buf, len );
1213 else
1214 RegDeleteValueW( key, WinHttpSettings );
1215 RegCloseKey( key );
1216 }
1217 }
1218
1219 static void test_set_default_proxy_config(void)
1220 {
1221 static WCHAR wideString[] = { 0x226f, 0x575b, 0 };
1222 static WCHAR normalString[] = { 'f','o','o',0 };
1223 DWORD type, len;
1224 BYTE *saved_proxy_settings = NULL;
1225 WINHTTP_PROXY_INFO info;
1226 BOOL ret;
1227
1228 /* FIXME: it would be simpler to read the current settings using
1229 * WinHttpGetDefaultProxyConfiguration and save them using
1230 * WinHttpSetDefaultProxyConfiguration, but they appear to have a bug.
1231 *
1232 * If a proxy is configured in the registry, e.g. via 'proxcfg -p "foo"',
1233 * the access type reported by WinHttpGetDefaultProxyConfiguration is 1,
1234 * WINHTTP_ACCESS_TYPE_NO_PROXY, whereas it should be
1235 * WINHTTP_ACCESS_TYPE_NAMED_PROXY.
1236 * If WinHttpSetDefaultProxyConfiguration is called with dwAccessType = 1,
1237 * the lpszProxy and lpszProxyBypass values are ignored.
1238 * Thus, if a proxy is set with proxycfg, then calling
1239 * WinHttpGetDefaultProxyConfiguration followed by
1240 * WinHttpSetDefaultProxyConfiguration results in the proxy settings
1241 * getting deleted from the registry.
1242 *
1243 * Instead I read the current registry value and restore it directly.
1244 */
1245 len = get_default_proxy_reg_value( NULL, 0, &type );
1246 if (len)
1247 {
1248 saved_proxy_settings = HeapAlloc( GetProcessHeap(), 0, len );
1249 len = get_default_proxy_reg_value( saved_proxy_settings, len, &type );
1250 }
1251
1252 if (0)
1253 {
1254 /* Crashes on Vista and higher */
1255 SetLastError(0xdeadbeef);
1256 ret = WinHttpSetDefaultProxyConfiguration(NULL);
1257 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1258 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1259 }
1260
1261 /* test with invalid access type */
1262 info.dwAccessType = 0xdeadbeef;
1263 info.lpszProxy = info.lpszProxyBypass = NULL;
1264 SetLastError(0xdeadbeef);
1265 ret = WinHttpSetDefaultProxyConfiguration(&info);
1266 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1267 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1268
1269 /* at a minimum, the proxy server must be set */
1270 info.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
1271 info.lpszProxy = info.lpszProxyBypass = NULL;
1272 SetLastError(0xdeadbeef);
1273 ret = WinHttpSetDefaultProxyConfiguration(&info);
1274 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1275 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1276 info.lpszProxyBypass = normalString;
1277 SetLastError(0xdeadbeef);
1278 ret = WinHttpSetDefaultProxyConfiguration(&info);
1279 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1280 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1281
1282 /* the proxy server can't have wide characters */
1283 info.lpszProxy = wideString;
1284 SetLastError(0xdeadbeef);
1285 ret = WinHttpSetDefaultProxyConfiguration(&info);
1286 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1287 skip("couldn't set default proxy configuration: access denied\n");
1288 else
1289 ok((!ret && GetLastError() == ERROR_INVALID_PARAMETER) ||
1290 broken(ret), /* Earlier winhttp versions on W2K/XP */
1291 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1292
1293 info.lpszProxy = normalString;
1294 SetLastError(0xdeadbeef);
1295 ret = WinHttpSetDefaultProxyConfiguration(&info);
1296 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1297 skip("couldn't set default proxy configuration: access denied\n");
1298 else
1299 {
1300 ok(ret, "WinHttpSetDefaultProxyConfiguration failed: %u\n", GetLastError());
1301 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
1302 "got %u\n", GetLastError());
1303 }
1304 set_default_proxy_reg_value( saved_proxy_settings, len, type );
1305 }
1306
1307 static void test_Timeouts (void)
1308 {
1309 BOOL ret;
1310 DWORD value, size;
1311 HINTERNET ses, req, con;
1312
1313 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1314 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1315
1316 SetLastError(0xdeadbeef);
1317 ret = WinHttpSetTimeouts(ses, -2, 0, 0, 0);
1318 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1319 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1320
1321 SetLastError(0xdeadbeef);
1322 ret = WinHttpSetTimeouts(ses, 0, -2, 0, 0);
1323 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1324 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1325
1326 SetLastError(0xdeadbeef);
1327 ret = WinHttpSetTimeouts(ses, 0, 0, -2, 0);
1328 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1329 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1330
1331 SetLastError(0xdeadbeef);
1332 ret = WinHttpSetTimeouts(ses, 0, 0, 0, -2);
1333 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1334 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1335
1336 SetLastError(0xdeadbeef);
1337 ret = WinHttpSetTimeouts(ses, -1, -1, -1, -1);
1338 ok(ret, "%u\n", GetLastError());
1339 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
1340 "expected ERROR_SUCCESS, got %u\n", GetLastError());
1341
1342 SetLastError(0xdeadbeef);
1343 ret = WinHttpSetTimeouts(ses, 0, 0, 0, 0);
1344 ok(ret, "%u\n", GetLastError());
1345
1346 SetLastError(0xdeadbeef);
1347 ret = WinHttpSetTimeouts(ses, 0x0123, 0x4567, 0x89ab, 0xcdef);
1348 ok(ret, "%u\n", GetLastError());
1349
1350 SetLastError(0xdeadbeef);
1351 value = 0xdeadbeef;
1352 size = sizeof(DWORD);
1353 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1354 ok(ret, "%u\n", GetLastError());
1355 ok(value == 0x0123, "Expected 0x0123, got %u\n", value);
1356
1357 SetLastError(0xdeadbeef);
1358 value = 0xdeadbeef;
1359 size = sizeof(DWORD);
1360 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1361 ok(ret, "%u\n", GetLastError());
1362 ok(value == 0x4567, "Expected 0x4567, got %u\n", value);
1363
1364 SetLastError(0xdeadbeef);
1365 value = 0xdeadbeef;
1366 size = sizeof(DWORD);
1367 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1368 ok(ret, "%u\n", GetLastError());
1369 ok(value == 0x89ab, "Expected 0x89ab, got %u\n", value);
1370
1371 SetLastError(0xdeadbeef);
1372 value = 0xdeadbeef;
1373 size = sizeof(DWORD);
1374 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1375 ok(ret, "%u\n", GetLastError());
1376 ok(value == 0xcdef, "Expected 0xcdef, got %u\n", value);
1377
1378 SetLastError(0xdeadbeef);
1379 value = 0;
1380 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1381 ok(ret, "%u\n", GetLastError());
1382
1383 SetLastError(0xdeadbeef);
1384 value = 0xdeadbeef;
1385 size = sizeof(DWORD);
1386 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1387 ok(ret, "%u\n", GetLastError());
1388 ok(value == 0, "Expected 0, got %u\n", value);
1389
1390 SetLastError(0xdeadbeef);
1391 value = 0;
1392 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1393 ok(ret, "%u\n", GetLastError());
1394
1395 SetLastError(0xdeadbeef);
1396 value = 0xdeadbeef;
1397 size = sizeof(DWORD);
1398 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1399 ok(ret, "%u\n", GetLastError());
1400 ok(value == 0, "Expected 0, got %u\n", value);
1401
1402 SetLastError(0xdeadbeef);
1403 value = 0;
1404 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1405 ok(ret, "%u\n", GetLastError());
1406
1407 SetLastError(0xdeadbeef);
1408 value = 0xdeadbeef;
1409 size = sizeof(DWORD);
1410 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1411 ok(ret, "%u\n", GetLastError());
1412 ok(value == 0, "Expected 0, got %u\n", value);
1413
1414 SetLastError(0xdeadbeef);
1415 value = 0;
1416 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1417 ok(ret, "%u\n", GetLastError());
1418
1419 SetLastError(0xdeadbeef);
1420 value = 0xdeadbeef;
1421 size = sizeof(DWORD);
1422 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1423 ok(ret, "%u\n", GetLastError());
1424 ok(value == 0, "Expected 0, got %u\n", value);
1425
1426 SetLastError(0xdeadbeef);
1427 value = 0xbeefdead;
1428 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1429 ok(ret, "%u\n", GetLastError());
1430
1431 SetLastError(0xdeadbeef);
1432 value = 0xdeadbeef;
1433 size = sizeof(DWORD);
1434 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1435 ok(ret, "%u\n", GetLastError());
1436 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1437
1438 SetLastError(0xdeadbeef);
1439 value = 0xbeefdead;
1440 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1441 ok(ret, "%u\n", GetLastError());
1442
1443 SetLastError(0xdeadbeef);
1444 value = 0xdeadbeef;
1445 size = sizeof(DWORD);
1446 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1447 ok(ret, "%u\n", GetLastError());
1448 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1449
1450 SetLastError(0xdeadbeef);
1451 value = 0xbeefdead;
1452 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1453 ok(ret, "%u\n", GetLastError());
1454
1455 SetLastError(0xdeadbeef);
1456 value = 0xdeadbeef;
1457 size = sizeof(DWORD);
1458 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1459 ok(ret, "%u\n", GetLastError());
1460 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1461
1462 SetLastError(0xdeadbeef);
1463 value = 0xbeefdead;
1464 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1465 ok(ret, "%u\n", GetLastError());
1466
1467 SetLastError(0xdeadbeef);
1468 value = 0xdeadbeef;
1469 size = sizeof(DWORD);
1470 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1471 ok(ret, "%u\n", GetLastError());
1472 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1473
1474 con = WinHttpConnect(ses, test_winehq, 0, 0);
1475 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1476
1477 /* Timeout values should match the last one set for session */
1478 SetLastError(0xdeadbeef);
1479 value = 0xdeadbeef;
1480 size = sizeof(DWORD);
1481 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1482 ok(ret, "%u\n", GetLastError());
1483 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1484
1485 SetLastError(0xdeadbeef);
1486 value = 0xdeadbeef;
1487 size = sizeof(DWORD);
1488 ret = WinHttpQueryOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1489 ok(ret, "%u\n", GetLastError());
1490 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1491
1492 SetLastError(0xdeadbeef);
1493 value = 0xdeadbeef;
1494 size = sizeof(DWORD);
1495 ret = WinHttpQueryOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1496 ok(ret, "%u\n", GetLastError());
1497 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1498
1499 SetLastError(0xdeadbeef);
1500 value = 0xdeadbeef;
1501 size = sizeof(DWORD);
1502 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1503 ok(ret, "%u\n", GetLastError());
1504 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1505
1506 SetLastError(0xdeadbeef);
1507 ret = WinHttpSetTimeouts(con, -2, 0, 0, 0);
1508 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1509 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1510
1511 SetLastError(0xdeadbeef);
1512 ret = WinHttpSetTimeouts(con, 0, -2, 0, 0);
1513 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1514 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1515
1516 SetLastError(0xdeadbeef);
1517 ret = WinHttpSetTimeouts(con, 0, 0, -2, 0);
1518 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1519 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1520
1521 SetLastError(0xdeadbeef);
1522 ret = WinHttpSetTimeouts(con, 0, 0, 0, -2);
1523 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1524 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1525
1526 SetLastError(0xdeadbeef);
1527 ret = WinHttpSetTimeouts(con, -1, -1, -1, -1);
1528 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1529 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1530
1531 SetLastError(0xdeadbeef);
1532 ret = WinHttpSetTimeouts(con, 0, 0, 0, 0);
1533 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1534 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1535
1536 SetLastError(0xdeadbeef);
1537 value = 0;
1538 ret = WinHttpSetOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1539 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1540 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1541
1542 SetLastError(0xdeadbeef);
1543 value = 0;
1544 ret = WinHttpSetOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1545 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1546 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1547
1548 SetLastError(0xdeadbeef);
1549 value = 0;
1550 ret = WinHttpSetOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1551 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1552 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1553
1554 SetLastError(0xdeadbeef);
1555 value = 0;
1556 ret = WinHttpSetOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1557 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1558 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1559
1560 /* Changing timeout values for session should affect the values for connection */
1561 SetLastError(0xdeadbeef);
1562 value = 0xdead;
1563 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1564 ok(ret, "%u\n", GetLastError());
1565
1566 SetLastError(0xdeadbeef);
1567 value = 0xdeadbeef;
1568 size = sizeof(DWORD);
1569 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1570 ok(ret, "%u\n", GetLastError());
1571 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1572
1573 SetLastError(0xdeadbeef);
1574 value = 0xdead;
1575 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1576 ok(ret, "%u\n", GetLastError());
1577
1578 SetLastError(0xdeadbeef);
1579 value = 0xdeadbeef;
1580 size = sizeof(DWORD);
1581 ret = WinHttpQueryOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1582 ok(ret, "%u\n", GetLastError());
1583 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1584
1585 SetLastError(0xdeadbeef);
1586 value = 0xdead;
1587 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1588 ok(ret, "%u\n", GetLastError());
1589
1590 SetLastError(0xdeadbeef);
1591 value = 0xdeadbeef;
1592 size = sizeof(DWORD);
1593 ret = WinHttpQueryOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1594 ok(ret, "%u\n", GetLastError());
1595 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1596
1597 SetLastError(0xdeadbeef);
1598 value = 0xdead;
1599 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1600 ok(ret, "%u\n", GetLastError());
1601
1602 SetLastError(0xdeadbeef);
1603 value = 0xdeadbeef;
1604 size = sizeof(DWORD);
1605 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1606 ok(ret, "%u\n", GetLastError());
1607 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1608
1609 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1610 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1611
1612 /* Timeout values should match the last one set for session */
1613 SetLastError(0xdeadbeef);
1614 value = 0xdeadbeef;
1615 size = sizeof(DWORD);
1616 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1617 ok(ret, "%u\n", GetLastError());
1618 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1619
1620 SetLastError(0xdeadbeef);
1621 value = 0xdeadbeef;
1622 size = sizeof(DWORD);
1623 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1624 ok(ret, "%u\n", GetLastError());
1625 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1626
1627 SetLastError(0xdeadbeef);
1628 value = 0xdeadbeef;
1629 size = sizeof(DWORD);
1630 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1631 ok(ret, "%u\n", GetLastError());
1632 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1633
1634 SetLastError(0xdeadbeef);
1635 value = 0xdeadbeef;
1636 size = sizeof(DWORD);
1637 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1638 ok(ret, "%u\n", GetLastError());
1639 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1640
1641 SetLastError(0xdeadbeef);
1642 ret = WinHttpSetTimeouts(req, -2, 0, 0, 0);
1643 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1644 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1645
1646 SetLastError(0xdeadbeef);
1647 ret = WinHttpSetTimeouts(req, 0, -2, 0, 0);
1648 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1649 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1650
1651 SetLastError(0xdeadbeef);
1652 ret = WinHttpSetTimeouts(req, 0, 0, -2, 0);
1653 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1654 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1655
1656 SetLastError(0xdeadbeef);
1657 ret = WinHttpSetTimeouts(req, 0, 0, 0, -2);
1658 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1659 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1660
1661 SetLastError(0xdeadbeef);
1662 ret = WinHttpSetTimeouts(req, -1, -1, -1, -1);
1663 ok(ret, "%u\n", GetLastError());
1664
1665 SetLastError(0xdeadbeef);
1666 ret = WinHttpSetTimeouts(req, 0, 0, 0, 0);
1667 ok(ret, "%u\n", GetLastError());
1668
1669 SetLastError(0xdeadbeef);
1670 ret = WinHttpSetTimeouts(req, 0xcdef, 0x89ab, 0x4567, 0x0123);
1671 ok(ret, "%u\n", GetLastError());
1672
1673 SetLastError(0xdeadbeef);
1674 value = 0xdeadbeef;
1675 size = sizeof(DWORD);
1676 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1677 ok(ret, "%u\n", GetLastError());
1678 ok(value == 0xcdef, "Expected 0xcdef, got %u\n", value);
1679
1680 SetLastError(0xdeadbeef);
1681 value = 0xdeadbeef;
1682 size = sizeof(DWORD);
1683 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1684 ok(ret, "%u\n", GetLastError());
1685 ok(value == 0x89ab, "Expected 0x89ab, got %u\n", value);
1686
1687 SetLastError(0xdeadbeef);
1688 value = 0xdeadbeef;
1689 size = sizeof(DWORD);
1690 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1691 ok(ret, "%u\n", GetLastError());
1692 ok(value == 0x4567, "Expected 0x4567, got %u\n", value);
1693
1694 SetLastError(0xdeadbeef);
1695 value = 0xdeadbeef;
1696 size = sizeof(DWORD);
1697 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1698 ok(ret, "%u\n", GetLastError());
1699 ok(value == 0x0123, "Expected 0x0123, got %u\n", value);
1700
1701 SetLastError(0xdeadbeef);
1702 value = 0;
1703 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1704 ok(ret, "%u\n", GetLastError());
1705
1706 SetLastError(0xdeadbeef);
1707 value = 0xdeadbeef;
1708 size = sizeof(DWORD);
1709 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1710 ok(ret, "%u\n", GetLastError());
1711 ok(value == 0, "Expected 0, got %u\n", value);
1712
1713 SetLastError(0xdeadbeef);
1714 value = 0;
1715 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1716 ok(ret, "%u\n", GetLastError());
1717
1718 SetLastError(0xdeadbeef);
1719 value = 0xdeadbeef;
1720 size = sizeof(DWORD);
1721 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1722 ok(ret, "%u\n", GetLastError());
1723 ok(value == 0, "Expected 0, got %u\n", value);
1724
1725 SetLastError(0xdeadbeef);
1726 value = 0;
1727 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1728 ok(ret, "%u\n", GetLastError());
1729
1730 SetLastError(0xdeadbeef);
1731 value = 0xdeadbeef;
1732 size = sizeof(DWORD);
1733 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1734 ok(ret, "%u\n", GetLastError());
1735 ok(value == 0, "Expected 0, got %u\n", value);
1736
1737 SetLastError(0xdeadbeef);
1738 value = 0;
1739 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1740 ok(ret, "%u\n", GetLastError());
1741
1742 SetLastError(0xdeadbeef);
1743 value = 0xdeadbeef;
1744 size = sizeof(DWORD);
1745 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1746 ok(ret, "%u\n", GetLastError());
1747 ok(value == 0, "Expected 0, got %u\n", value);
1748
1749 SetLastError(0xdeadbeef);
1750 value = 0xbeefdead;
1751 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1752 ok(ret, "%u\n", GetLastError());
1753
1754 SetLastError(0xdeadbeef);
1755 value = 0xdeadbeef;
1756 size = sizeof(DWORD);
1757 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1758 ok(ret, "%u\n", GetLastError());
1759 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1760
1761 SetLastError(0xdeadbeef);
1762 value = 0xbeefdead;
1763 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1764 ok(ret, "%u\n", GetLastError());
1765
1766 SetLastError(0xdeadbeef);
1767 value = 0xdeadbeef;
1768 size = sizeof(DWORD);
1769 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1770 ok(ret, "%u\n", GetLastError());
1771 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1772
1773 SetLastError(0xdeadbeef);
1774 value = 0xbeefdead;
1775 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1776 ok(ret, "%u\n", GetLastError());
1777
1778 SetLastError(0xdeadbeef);
1779 value = 0xdeadbeef;
1780 size = sizeof(DWORD);
1781 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1782 ok(ret, "%u\n", GetLastError());
1783 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1784
1785 SetLastError(0xdeadbeef);
1786 value = 0xbeefdead;
1787 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1788 ok(ret, "%u\n", GetLastError());
1789
1790 SetLastError(0xdeadbeef);
1791 value = 0xdeadbeef;
1792 size = sizeof(DWORD);
1793 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1794 ok(ret, "%u\n", GetLastError());
1795 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1796
1797 /* Changing timeout values for session should not affect the values for a request,
1798 * neither should the other way around.
1799 */
1800 SetLastError(0xdeadbeef);
1801 value = 0xbeefdead;
1802 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1803 ok(ret, "%u\n", GetLastError());
1804
1805 SetLastError(0xdeadbeef);
1806 value = 0xdeadbeef;
1807 size = sizeof(DWORD);
1808 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1809 ok(ret, "%u\n", GetLastError());
1810 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1811
1812 SetLastError(0xdeadbeef);
1813 value = 0xbeefdead;
1814 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1815 ok(ret, "%u\n", GetLastError());
1816
1817 SetLastError(0xdeadbeef);
1818 value = 0xdeadbeef;
1819 size = sizeof(DWORD);
1820 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1821 ok(ret, "%u\n", GetLastError());
1822 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1823
1824 SetLastError(0xdeadbeef);
1825 value = 0xbeefdead;
1826 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1827 ok(ret, "%u\n", GetLastError());
1828
1829 SetLastError(0xdeadbeef);
1830 value = 0xdeadbeef;
1831 size = sizeof(DWORD);
1832 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1833 ok(ret, "%u\n", GetLastError());
1834 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1835
1836 SetLastError(0xdeadbeef);
1837 value = 0xbeefdead;
1838 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1839 ok(ret, "%u\n", GetLastError());
1840
1841 SetLastError(0xdeadbeef);
1842 value = 0xdeadbeef;
1843 size = sizeof(DWORD);
1844 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1845 ok(ret, "%u\n", GetLastError());
1846 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1847
1848 SetLastError(0xdeadbeef);
1849 value = 0xbeef;
1850 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1851 ok(ret, "%u\n", GetLastError());
1852
1853 SetLastError(0xdeadbeef);
1854 value = 0xdeadbeef;
1855 size = sizeof(DWORD);
1856 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1857 ok(ret, "%u\n", GetLastError());
1858 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1859
1860 SetLastError(0xdeadbeef);
1861 value = 0xbeef;
1862 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1863 ok(ret, "%u\n", GetLastError());
1864
1865 SetLastError(0xdeadbeef);
1866 value = 0xdeadbeef;
1867 size = sizeof(DWORD);
1868 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1869 ok(ret, "%u\n", GetLastError());
1870 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1871
1872 SetLastError(0xdeadbeef);
1873 value = 0xbeef;
1874 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1875 ok(ret, "%u\n", GetLastError());
1876
1877 SetLastError(0xdeadbeef);
1878 value = 0xdeadbeef;
1879 size = sizeof(DWORD);
1880 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1881 ok(ret, "%u\n", GetLastError());
1882 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1883
1884 SetLastError(0xdeadbeef);
1885 value = 0xbeef;
1886 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1887 ok(ret, "%u\n", GetLastError());
1888
1889 SetLastError(0xdeadbeef);
1890 value = 0xdeadbeef;
1891 size = sizeof(DWORD);
1892 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1893 ok(ret, "%u\n", GetLastError());
1894 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1895
1896 WinHttpCloseHandle(req);
1897 WinHttpCloseHandle(con);
1898 WinHttpCloseHandle(ses);
1899 }
1900
1901 static void test_resolve_timeout(void)
1902 {
1903 static const WCHAR nxdomain[] =
1904 {'n','x','d','o','m','a','i','n','.','w','i','n','e','h','q','.','o','r','g',0};
1905 HINTERNET ses, con, req;
1906 DWORD timeout;
1907 BOOL ret;
1908
1909 if (! proxy_active())
1910 {
1911 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1912 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1913
1914 timeout = 10000;
1915 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
1916 ok(ret, "failed to set resolve timeout %u\n", GetLastError());
1917
1918 con = WinHttpConnect(ses, nxdomain, 0, 0);
1919 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1920
1921 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1922 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1923
1924 SetLastError(0xdeadbeef);
1925 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1926 if (ret)
1927 {
1928 skip("nxdomain returned success. Broken ISP redirects?\n");
1929 goto done;
1930 }
1931 ok(GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED,
1932 "expected ERROR_WINHTTP_NAME_NOT_RESOLVED got %u\n", GetLastError());
1933
1934 WinHttpCloseHandle(req);
1935 WinHttpCloseHandle(con);
1936 WinHttpCloseHandle(ses);
1937 }
1938 else
1939 skip("Skipping host resolution tests, host resolution preformed by proxy\n");
1940
1941 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1942 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1943
1944 timeout = 10000;
1945 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
1946 ok(ret, "failed to set resolve timeout %u\n", GetLastError());
1947
1948 con = WinHttpConnect(ses, test_winehq, 0, 0);
1949 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1950
1951 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1952 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1953
1954 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1955 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
1956 {
1957 skip("connection failed, skipping\n");
1958 goto done;
1959 }
1960 ok(ret, "failed to send request\n");
1961
1962 done:
1963 WinHttpCloseHandle(req);
1964 WinHttpCloseHandle(con);
1965 WinHttpCloseHandle(ses);
1966 }
1967
1968 static const char page1[] =
1969 "<HTML>\r\n"
1970 "<HEAD><TITLE>winhttp test page</TITLE></HEAD>\r\n"
1971 "<BODY>The quick brown fox jumped over the lazy dog<P></BODY>\r\n"
1972 "</HTML>\r\n\r\n";
1973
1974 static const char okmsg[] =
1975 "HTTP/1.1 200 OK\r\n"
1976 "Server: winetest\r\n"
1977 "\r\n";
1978
1979 static const char notokmsg[] =
1980 "HTTP/1.1 400 Bad Request\r\n"
1981 "\r\n";
1982
1983 static const char cookiemsg[] =
1984 "HTTP/1.1 200 OK\r\n"
1985 "Set-Cookie: name = value \r\n"
1986 "Set-Cookie: NAME = value \r\n"
1987 "\r\n";
1988
1989 static const char nocontentmsg[] =
1990 "HTTP/1.1 204 No Content\r\n"
1991 "Server: winetest\r\n"
1992 "\r\n";
1993
1994 static const char notmodified[] =
1995 "HTTP/1.1 304 Not Modified\r\n"
1996 "\r\n";
1997
1998 static const char noauthmsg[] =
1999 "HTTP/1.1 401 Unauthorized\r\n"
2000 "Server: winetest\r\n"
2001 "Connection: close\r\n"
2002 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
2003 "\r\n";
2004
2005 static const char okauthmsg[] =
2006 "HTTP/1.1 200 OK\r\n"
2007 "Server: winetest\r\n"
2008 "Connection: close\r\n"
2009 "\r\n";
2010
2011 static const char headmsg[] =
2012 "HTTP/1.1 200 OK\r\n"
2013 "Content-Length: 100\r\n"
2014 "\r\n";
2015
2016 struct server_info
2017 {
2018 HANDLE event;
2019 int port;
2020 };
2021
2022 #define BIG_BUFFER_LEN 0x2250
2023
2024 static DWORD CALLBACK server_thread(LPVOID param)
2025 {
2026 struct server_info *si = param;
2027 int r, c = -1, i, on;
2028 SOCKET s;
2029 struct sockaddr_in sa;
2030 char buffer[0x100];
2031 WSADATA wsaData;
2032 int last_request = 0;
2033
2034 WSAStartup(MAKEWORD(1,1), &wsaData);
2035
2036 s = socket(AF_INET, SOCK_STREAM, 0);
2037 if (s == INVALID_SOCKET)
2038 return 1;
2039
2040 on = 1;
2041 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof on);
2042
2043 memset(&sa, 0, sizeof sa);
2044 sa.sin_family = AF_INET;
2045 sa.sin_port = htons(si->port);
2046 sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
2047
2048 r = bind(s, (struct sockaddr *)&sa, sizeof(sa));
2049 if (r < 0)
2050 return 1;
2051
2052 listen(s, 0);
2053 SetEvent(si->event);
2054 do
2055 {
2056 if (c == -1) c = accept(s, NULL, NULL);
2057
2058 memset(buffer, 0, sizeof buffer);
2059 for(i = 0; i < sizeof buffer - 1; i++)
2060 {
2061 r = recv(c, &buffer[i], 1, 0);
2062 if (r != 1)
2063 break;
2064 if (i < 4) continue;
2065 if (buffer[i - 2] == '\n' && buffer[i] == '\n' &&
2066 buffer[i - 3] == '\r' && buffer[i - 1] == '\r')
2067 break;
2068 }
2069 if (strstr(buffer, "GET /basic"))
2070 {
2071 send(c, okmsg, sizeof okmsg - 1, 0);
2072 send(c, page1, sizeof page1 - 1, 0);
2073 }
2074 if (strstr(buffer, "/auth"))
2075 {
2076 if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
2077 send(c, okauthmsg, sizeof okauthmsg - 1, 0);
2078 else
2079 send(c, noauthmsg, sizeof noauthmsg - 1, 0);
2080 }
2081 if (strstr(buffer, "/big"))
2082 {
2083 char msg[BIG_BUFFER_LEN];
2084 memset(msg, 'm', sizeof(msg));
2085 send(c, okmsg, sizeof(okmsg) - 1, 0);
2086 send(c, msg, sizeof(msg), 0);
2087 }
2088 if (strstr(buffer, "/no_headers"))
2089 {
2090 send(c, page1, sizeof page1 - 1, 0);
2091 }
2092 if (strstr(buffer, "GET /no_content"))
2093 {
2094 send(c, nocontentmsg, sizeof nocontentmsg - 1, 0);
2095 continue;
2096 }
2097 if (strstr(buffer, "GET /not_modified"))
2098 {
2099 if (strstr(buffer, "If-Modified-Since:")) send(c, notmodified, sizeof notmodified - 1, 0);
2100 else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2101 continue;
2102 }
2103 if (strstr(buffer, "HEAD /head"))
2104 {
2105 send(c, headmsg, sizeof headmsg - 1, 0);
2106 continue;
2107 }
2108 if (strstr(buffer, "GET /cookie3"))
2109 {
2110 if (strstr(buffer, "Cookie: name=value2; NAME=value; name=value\r\n") ||
2111 broken(strstr(buffer, "Cookie: name=value2; name=value; NAME=value\r\n") != NULL))
2112 send(c, okmsg, sizeof(okmsg) - 1, 0);
2113 else
2114 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2115 }
2116 if (strstr(buffer, "GET /cookie2"))
2117 {
2118 if (strstr(buffer, "Cookie: NAME=value; name=value\r\n") ||
2119 broken(strstr(buffer, "Cookie: name=value; NAME=value\r\n") != NULL))
2120 send(c, okmsg, sizeof(okmsg) - 1, 0);
2121 else
2122 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2123 }
2124 else if (strstr(buffer, "GET /cookie"))
2125 {
2126 if (!strstr(buffer, "Cookie: name=value\r\n")) send(c, cookiemsg, sizeof(cookiemsg) - 1, 0);
2127 else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2128 }
2129 if (strstr(buffer, "GET /quit"))
2130 {
2131 send(c, okmsg, sizeof okmsg - 1, 0);
2132 send(c, page1, sizeof page1 - 1, 0);
2133 last_request = 1;
2134 }
2135 shutdown(c, 2);
2136 closesocket(c);
2137 c = -1;
2138
2139 } while (!last_request);
2140
2141 closesocket(s);
2142 return 0;
2143 }
2144
2145 static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path)
2146 {
2147 static const WCHAR test_header_end_clrf[] = {'\r','\n','\r','\n',0};
2148 static const WCHAR test_header_end_raw[] = {0,0};
2149 HINTERNET ses, con, req;
2150 char buffer[0x100];
2151 WCHAR buffer2[0x100];
2152 DWORD count, status, size, error, supported, first, target;
2153 BOOL ret;
2154
2155 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2156 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2157
2158 con = WinHttpConnect(ses, localhostW, port, 0);
2159 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2160
2161 req = WinHttpOpenRequest(con, verb, path, NULL, NULL, NULL, 0);
2162 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2163
2164 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2165 ok(ret, "failed to send request %u\n", GetLastError());
2166
2167 ret = WinHttpReceiveResponse(req, NULL);
2168 ok(ret, "failed to receive response %u\n", GetLastError());
2169
2170 status = 0xdeadbeef;
2171 size = sizeof(status);
2172 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2173 ok(ret, "failed to query status code %u\n", GetLastError());
2174 ok(status == 200, "request failed unexpectedly %u\n", status);
2175
2176 supported = first = target = 0xdeadbeef;
2177 SetLastError(0xdeadbeef);
2178 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2179 error = GetLastError();
2180 ok(!ret, "unexpected success\n");
2181 todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
2182 ok(supported == 0xdeadbeef, "got %x\n", supported);
2183 ok(first == 0xdeadbeef, "got %x\n", first);
2184 ok(target == 0xdeadbeef, "got %x\n", target);
2185
2186 size = sizeof(buffer2);
2187 memset(buffer2, 0, sizeof(buffer2));
2188 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, buffer2, &size, NULL);
2189 ok(ret, "failed to query for raw headers: %u\n", GetLastError());
2190 ok(!memcmp(buffer2 + lstrlenW(buffer2) - 4, test_header_end_clrf, sizeof(test_header_end_clrf)),
2191 "WinHttpQueryHeaders returned invalid end of header string\n");
2192
2193 size = sizeof(buffer2);
2194 memset(buffer2, 0, sizeof(buffer2));
2195 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS, NULL, buffer2, &size, NULL);
2196 ok(ret, "failed to query for raw headers: %u\n", GetLastError());
2197 ok(!memcmp(buffer2 + (size / sizeof(WCHAR)) - 1, test_header_end_raw, sizeof(test_header_end_raw)),
2198 "WinHttpQueryHeaders returned invalid end of header string\n");
2199 ok(buffer2[(size / sizeof(WCHAR)) - 2] != 0, "returned string has too many NULL characters\n");
2200
2201 count = 0;
2202 memset(buffer, 0, sizeof(buffer));
2203 ret = WinHttpReadData(req, buffer, sizeof buffer, &count);
2204 ok(ret, "failed to read data %u\n", GetLastError());
2205 ok(count == sizeof page1 - 1, "count was wrong\n");
2206 ok(!memcmp(buffer, page1, sizeof page1), "http data wrong\n");
2207
2208 WinHttpCloseHandle(req);
2209 WinHttpCloseHandle(con);
2210 WinHttpCloseHandle(ses);
2211 }
2212
2213 static void test_basic_authentication(int port)
2214 {
2215 static const WCHAR authW[] = {'/','a','u','t','h',0};
2216 static WCHAR userW[] = {'u','s','e','r',0};
2217 static WCHAR passW[] = {'p','w','d',0};
2218 static WCHAR pass2W[] = {'p','w','d','2',0};
2219 HINTERNET ses, con, req;
2220 DWORD status, size, error, supported, first, target;
2221 BOOL ret;
2222
2223 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2224 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2225
2226 con = WinHttpConnect(ses, localhostW, port, 0);
2227 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2228
2229 req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2230 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2231
2232 SetLastError(0xdeadbeef);
2233 ret = WinHttpQueryAuthSchemes(NULL, NULL, NULL, NULL);
2234 error = GetLastError();
2235 ok(!ret, "expected failure\n");
2236 ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
2237
2238 SetLastError(0xdeadbeef);
2239 ret = WinHttpQueryAuthSchemes(req, NULL, NULL, NULL);
2240 error = GetLastError();
2241 ok(!ret, "expected failure\n");
2242 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2243
2244 supported = 0xdeadbeef;
2245 SetLastError(0xdeadbeef);
2246 ret = WinHttpQueryAuthSchemes(req, &supported, NULL, NULL);
2247 error = GetLastError();
2248 ok(!ret, "expected failure\n");
2249 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2250 ok(supported == 0xdeadbeef, "got %x\n", supported);
2251
2252 supported = first = 0xdeadbeef;
2253 SetLastError(0xdeadbeef);
2254 ret = WinHttpQueryAuthSchemes(req, &supported, &first, NULL);
2255 error = GetLastError();
2256 ok(!ret, "expected failure\n");
2257 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2258 ok(supported == 0xdeadbeef, "got %x\n", supported);
2259 ok(first == 0xdeadbeef, "got %x\n", first);
2260
2261 supported = first = target = 0xdeadbeef;
2262 SetLastError(0xdeadbeef);
2263 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2264 error = GetLastError();
2265 ok(!ret, "expected failure\n");
2266 todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
2267 ok(supported == 0xdeadbeef, "got %x\n", supported);
2268 ok(first == 0xdeadbeef, "got %x\n", first);
2269 ok(target == 0xdeadbeef, "got %x\n", target);
2270
2271 supported = first = target = 0xdeadbeef;
2272 SetLastError(0xdeadbeef);
2273 ret = WinHttpQueryAuthSchemes(NULL, &supported, &first, &target);
2274 error = GetLastError();
2275 ok(!ret, "expected failure\n");
2276 ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
2277 ok(supported == 0xdeadbeef, "got %x\n", supported);
2278 ok(first == 0xdeadbeef, "got %x\n", first);
2279 ok(target == 0xdeadbeef, "got %x\n", target);
2280
2281 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2282 ok(ret, "failed to send request %u\n", GetLastError());
2283
2284 ret = WinHttpReceiveResponse(req, NULL);
2285 ok(ret, "failed to receive response %u\n", GetLastError());
2286
2287 status = 0xdeadbeef;
2288 size = sizeof(status);
2289 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2290 ok(ret, "failed to query status code %u\n", GetLastError());
2291 ok(status == 401, "request failed unexpectedly %u\n", status);
2292
2293 supported = first = target = 0xdeadbeef;
2294 SetLastError(0xdeadbeef);
2295 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2296 error = GetLastError();
2297 ok(ret, "failed to query authentication schemes %u\n", error);
2298 ok(error == ERROR_SUCCESS || broken(error == 0xdeadbeef) /* < win7 */, "expected ERROR_SUCCESS, got %u\n", error);
2299 ok(supported == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", supported);
2300 ok(first == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", first);
2301 ok(target == WINHTTP_AUTH_TARGET_SERVER, "got %x\n", target);
2302
2303 SetLastError(0xdeadbeef);
2304 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NTLM, NULL, NULL, NULL);
2305 error = GetLastError();
2306 ok(ret, "failed to set credentials %u\n", error);
2307 ok(error == ERROR_SUCCESS || broken(error == 0xdeadbeef) /* < win7 */, "expected ERROR_SUCCESS, got %u\n", error);
2308
2309 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_PASSPORT, NULL, NULL, NULL);
2310 ok(ret, "failed to set credentials %u\n", GetLastError());
2311
2312 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NEGOTIATE, NULL, NULL, NULL);
2313 ok(ret, "failed to set credentials %u\n", GetLastError());
2314
2315 SetLastError(0xdeadbeef);
2316 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_DIGEST, NULL, NULL, NULL);
2317 error = GetLastError();
2318 ok(!ret, "expected failure\n");
2319 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2320
2321 SetLastError(0xdeadbeef);
2322 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, NULL, NULL);
2323 error = GetLastError();
2324 ok(!ret, "expected failure\n");
2325 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2326
2327 SetLastError(0xdeadbeef);
2328 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, NULL, NULL);
2329 error = GetLastError();
2330 ok(!ret, "expected failure\n");
2331 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2332
2333 SetLastError(0xdeadbeef);
2334 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, passW, NULL);
2335 error = GetLastError();
2336 ok(!ret, "expected failure\n");
2337 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2338
2339 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
2340 ok(ret, "failed to set credentials %u\n", GetLastError());
2341
2342 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2343 ok(ret, "failed to send request %u\n", GetLastError());
2344
2345 ret = WinHttpReceiveResponse(req, NULL);
2346 ok(ret, "failed to receive response %u\n", GetLastError());
2347
2348 status = 0xdeadbeef;
2349 size = sizeof(status);
2350 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2351 ok(ret, "failed to query status code %u\n", GetLastError());
2352 ok(status == 200, "request failed unexpectedly %u\n", status);
2353
2354 WinHttpCloseHandle(req);
2355 WinHttpCloseHandle(con);
2356 WinHttpCloseHandle(ses);
2357
2358 /* credentials set with WinHttpSetCredentials take precedence over those set through options */
2359
2360 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2361 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2362
2363 con = WinHttpConnect(ses, localhostW, port, 0);
2364 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2365
2366 req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2367 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2368
2369 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
2370 ok(ret, "failed to set credentials %u\n", GetLastError());
2371
2372 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
2373 ok(ret, "failed to set username %u\n", GetLastError());
2374
2375 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, pass2W, lstrlenW(pass2W));
2376 ok(ret, "failed to set password %u\n", GetLastError());
2377
2378 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2379 ok(ret, "failed to send request %u\n", GetLastError());
2380
2381 ret = WinHttpReceiveResponse(req, NULL);
2382 ok(ret, "failed to receive response %u\n", GetLastError());
2383
2384 status = 0xdeadbeef;
2385 size = sizeof(status);
2386 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2387 ok(ret, "failed to query status code %u\n", GetLastError());
2388 ok(status == 200, "request failed unexpectedly %u\n", status);
2389
2390 WinHttpCloseHandle(req);
2391 WinHttpCloseHandle(con);
2392 WinHttpCloseHandle(ses);
2393
2394 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2395 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2396
2397 con = WinHttpConnect(ses, localhostW, port, 0);
2398 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2399
2400 req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2401 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2402
2403 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
2404 ok(ret, "failed to set username %u\n", GetLastError());
2405
2406 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, pass2W, lstrlenW(passW));
2407 ok(ret, "failed to set password %u\n", GetLastError());
2408
2409 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, pass2W, NULL);
2410 ok(ret, "failed to set credentials %u\n", GetLastError());
2411
2412 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2413 ok(ret, "failed to send request %u\n", GetLastError());
2414
2415 ret = WinHttpReceiveResponse(req, NULL);
2416 ok(ret, "failed to receive response %u\n", GetLastError());
2417
2418 status = 0xdeadbeef;
2419 size = sizeof(status);
2420 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2421 ok(ret, "failed to query status code %u\n", GetLastError());
2422 ok(status == 401, "request failed unexpectedly %u\n", status);
2423
2424 WinHttpCloseHandle(req);
2425 WinHttpCloseHandle(con);
2426 WinHttpCloseHandle(ses);
2427 }
2428
2429 static void test_no_headers(int port)
2430 {
2431 static const WCHAR no_headersW[] = {'/','n','o','_','h','e','a','d','e','r','s',0};
2432 HINTERNET ses, con, req;
2433 DWORD error;
2434 BOOL ret;
2435
2436 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2437 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2438
2439 con = WinHttpConnect(ses, localhostW, port, 0);
2440 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2441
2442 req = WinHttpOpenRequest(con, NULL, no_headersW, NULL, NULL, NULL, 0);
2443 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2444
2445 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2446 if (!ret)
2447 {
2448 error = GetLastError();
2449 ok(error == ERROR_WINHTTP_INVALID_SERVER_RESPONSE, "got %u\n", error);
2450 }
2451 else
2452 {
2453 SetLastError(0xdeadbeef);
2454 ret = WinHttpReceiveResponse(req, NULL);
2455 error = GetLastError();
2456 ok(!ret, "expected failure\n");
2457 ok(error == ERROR_WINHTTP_INVALID_SERVER_RESPONSE, "got %u\n", error);
2458 }
2459
2460 WinHttpCloseHandle(req);
2461 WinHttpCloseHandle(con);
2462 WinHttpCloseHandle(ses);
2463 }
2464
2465 static void test_no_content(int port)
2466 {
2467 static const WCHAR no_contentW[] = {'/','n','o','_','c','o','n','t','e','n','t',0};
2468 HINTERNET ses, con, req;
2469 char buf[128];
2470 DWORD size, len = sizeof(buf), bytes_read, status;
2471 BOOL ret;
2472
2473 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2474 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2475
2476 con = WinHttpConnect(ses, localhostW, port, 0);
2477 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2478
2479 req = WinHttpOpenRequest(con, NULL, no_contentW, NULL, NULL, NULL, 0);
2480 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2481
2482 size = 12345;
2483 SetLastError(0xdeadbeef);
2484 ret = WinHttpQueryDataAvailable(req, &size);
2485 todo_wine {
2486 ok(!ret, "expected error\n");
2487 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_STATE,
2488 "expected ERROR_WINHTTP_INCORRECT_HANDLE_STATE, got 0x%08x\n", GetLastError());
2489 ok(size == 12345 || broken(size == 0) /* Win <= 2003 */,
2490 "expected 12345, got %u\n", size);
2491 }
2492
2493 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2494 ok(ret, "expected success\n");
2495
2496 ret = WinHttpReceiveResponse(req, NULL);
2497 ok(ret, "expected success\n");
2498
2499 status = 0xdeadbeef;
2500 size = sizeof(status);
2501 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
2502 NULL, &status, &size, NULL);
2503 ok(ret, "expected success\n");
2504 ok(status == 204, "expected status 204, got %d\n", status);
2505
2506 SetLastError(0xdeadbeef);
2507 size = sizeof(status);
2508 status = 12345;
2509 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
2510 NULL, &status, &size, 0);
2511 ok(!ret, "expected no content-length header\n");
2512 ok(GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND, "wrong error %u\n", GetLastError());
2513 ok(status == 12345, "expected 0, got %d\n", status);
2514
2515 SetLastError(0xdeadbeef);
2516 size = 12345;
2517 ret = WinHttpQueryDataAvailable(req, &size);
2518 ok(ret, "expected success\n");
2519 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
2520 "wrong error %u\n", GetLastError());
2521 ok(!size, "expected 0, got %u\n", size);
2522
2523 SetLastError(0xdeadbeef);
2524 ret = WinHttpReadData(req, buf, len, &bytes_read);
2525 ok(ret, "expected success\n");
2526 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
2527 "wrong error %u\n", GetLastError());
2528 ok(!bytes_read, "expected 0, got %u\n", bytes_read);
2529
2530 size = 12345;
2531 ret = WinHttpQueryDataAvailable(req, &size);
2532 ok(ret, "expected success\n");
2533 ok(size == 0, "expected 0, got %d\n", size);
2534
2535 WinHttpCloseHandle(req);
2536
2537 size = 12345;
2538 SetLastError(0xdeadbeef);
2539 ret = WinHttpQueryDataAvailable(req, &size);
2540 ok(!ret, "expected error\n");
2541 ok(GetLastError() == ERROR_INVALID_HANDLE,
2542 "expected ERROR_INVALID_HANDLE, got 0x%08x\n", GetLastError());
2543 ok(size == 12345, "expected 12345, got %u\n", size);
2544
2545 WinHttpCloseHandle(con);
2546 WinHttpCloseHandle(ses);
2547 }
2548
2549 static void test_head_request(int port)
2550 {
2551 static const WCHAR verbW[] = {'H','E','A','D',0};
2552 static const WCHAR headW[] = {'/','h','e','a','d',0};
2553 HINTERNET ses, con, req;
2554 char buf[128];
2555 DWORD size, len, count, status;
2556 BOOL ret;
2557
2558 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2559 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2560
2561 con = WinHttpConnect(ses, localhostW, port, 0);
2562 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2563
2564 req = WinHttpOpenRequest(con, verbW, headW, NULL, NULL, NULL, 0);
2565 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2566
2567 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2568 ok(ret, "failed to send request %u\n", GetLastError());
2569
2570 ret = WinHttpReceiveResponse(req, NULL);
2571 ok(ret, "failed to receive response %u\n", GetLastError());
2572
2573 status = 0xdeadbeef;
2574 size = sizeof(status);
2575 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
2576 NULL, &status, &size, NULL);
2577 ok(ret, "failed to get status code %u\n", GetLastError());
2578 ok(status == 200, "got %u\n", status);
2579
2580 len = 0xdeadbeef;
2581 size = sizeof(len);
2582 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
2583 NULL, &len, &size, 0);
2584 ok(ret, "failed to get content-length header %u\n", GetLastError());
2585 ok(len == 100, "got %u\n", len);
2586
2587 count = 0xdeadbeef;
2588 ret = WinHttpQueryDataAvailable(req, &count);
2589 ok(ret, "failed to query data available %u\n", GetLastError());
2590 ok(!count, "got %u\n", count);
2591
2592 len = sizeof(buf);
2593 count = 0xdeadbeef;
2594 ret = WinHttpReadData(req, buf, len, &count);
2595 ok(ret, "failed to read data %u\n", GetLastError());
2596 ok(!count, "got %u\n", count);
2597
2598 count = 0xdeadbeef;
2599 ret = WinHttpQueryDataAvailable(req, &count);
2600 ok(ret, "failed to query data available %u\n", GetLastError());
2601 ok(!count, "got %u\n", count);
2602
2603 WinHttpCloseHandle(req);
2604 WinHttpCloseHandle(con);
2605 WinHttpCloseHandle(ses);
2606 }
2607
2608 static void test_not_modified(int port)
2609 {
2610 static const WCHAR pathW[] = {'/','n','o','t','_','m','o','d','i','f','i','e','d',0};
2611 static const WCHAR ifmodifiedW[] = {'I','f','-','M','o','d','i','f','i','e','d','-','S','i','n','c','e',':',' '};
2612 static const WCHAR ifmodified2W[] = {'I','f','-','M','o','d','i','f','i','e','d','-','S','i','n','c','e',0};
2613 BOOL ret;
2614 HINTERNET session, request, connection;
2615 DWORD index, len, status, size, start = GetTickCount();
2616 SYSTEMTIME st;
2617 WCHAR today[(sizeof(ifmodifiedW) + WINHTTP_TIME_FORMAT_BUFSIZE)/sizeof(WCHAR) + 3], buffer[32];
2618
2619 memcpy(today, ifmodifiedW, sizeof(ifmodifiedW));
2620 GetSystemTime(&st);
2621 WinHttpTimeFromSystemTime(&st, &today[sizeof(ifmodifiedW)/sizeof(WCHAR)]);
2622
2623 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY,
2624 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
2625 ok(session != NULL, "WinHttpOpen failed: %u\n", GetLastError());
2626
2627 connection = WinHttpConnect(session, localhostW, port, 0);
2628 ok(connection != NULL, "WinHttpConnect failed: %u\n", GetLastError());
2629
2630 request = WinHttpOpenRequest(connection, NULL, pathW, NULL, WINHTTP_NO_REFERER,
2631 WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
2632 ok(request != NULL, "WinHttpOpenrequest failed: %u\n", GetLastError());
2633
2634 ret = WinHttpSendRequest(request, today, 0, NULL, 0, 0, 0);
2635 ok(ret, "WinHttpSendRequest failed: %u\n", GetLastError());
2636
2637 ret = WinHttpReceiveResponse(request, NULL);
2638 ok(ret, "WinHttpReceiveResponse failed: %u\n", GetLastError());
2639
2640 index = 0;
2641 len = sizeof(buffer);
2642 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
2643 ifmodified2W, buffer, &len, &index);
2644 ok(ret, "failed to get header %u\n", GetLastError());
2645
2646 status = 0xdeadbeef;
2647 size = sizeof(status);
2648 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER,
2649 NULL, &status, &size, NULL);
2650 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
2651 ok(status == HTTP_STATUS_NOT_MODIFIED, "got %u\n", status);
2652
2653 size = 0xdeadbeef;
2654 ret = WinHttpQueryDataAvailable(request, &size);
2655 ok(ret, "WinHttpQueryDataAvailable failed: %u\n", GetLastError());
2656 ok(!size, "got %u\n", size);
2657
2658 WinHttpCloseHandle(request);
2659 WinHttpCloseHandle(connection);
2660 WinHttpCloseHandle(session);
2661 start = GetTickCount() - start;
2662 ok(start <= 2000, "Expected less than 2 seconds for the test, got %u ms\n", start);
2663 }
2664
2665 static void test_bad_header( int port )
2666 {
2667 static const WCHAR bad_headerW[] =
2668 {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ',
2669 't','e','x','t','/','h','t','m','l','\n','\r',0};
2670 static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
2671 static const WCHAR content_typeW[] = {'C','o','n','t','e','n','t','-','T','y','p','e',0};
2672 WCHAR buffer[32];
2673 HINTERNET ses, con, req;
2674 DWORD index, len;
2675 BOOL ret;
2676
2677 ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
2678 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
2679
2680 con = WinHttpConnect( ses, localhostW, port, 0 );
2681 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2682
2683 req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
2684 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2685
2686 ret = WinHttpAddRequestHeaders( req, bad_headerW, ~0u, WINHTTP_ADDREQ_FLAG_ADD );
2687 ok( ret, "failed to add header %u\n", GetLastError() );
2688
2689 index = 0;
2690 buffer[0] = 0;
2691 len = sizeof(buffer);
2692 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_CUSTOM|WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
2693 content_typeW, buffer, &len, &index );
2694 ok( ret, "failed to query headers %u\n", GetLastError() );
2695 ok( !lstrcmpW( buffer, text_htmlW ), "got %s\n", wine_dbgstr_w(buffer) );
2696
2697 WinHttpCloseHandle( req );
2698 WinHttpCloseHandle( con );
2699 WinHttpCloseHandle( ses );
2700 }
2701
2702 static void test_multiple_reads(int port)
2703 {
2704 static const WCHAR bigW[] = {'b','i','g',0};
2705 HINTERNET ses, con, req;
2706 DWORD total_len = 0;
2707 BOOL ret;
2708
2709 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2710 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2711
2712 con = WinHttpConnect(ses, localhostW, port, 0);
2713 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2714
2715 req = WinHttpOpenRequest(con, NULL, bigW, NULL, NULL, NULL, 0);
2716 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2717
2718 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2719 ok(ret, "failed to send request %u\n", GetLastError());
2720
2721 ret = WinHttpReceiveResponse(req, NULL);
2722 ok(ret == TRUE, "expected success\n");
2723
2724 for (;;)
2725 {
2726 DWORD len = 0xdeadbeef;
2727 ret = WinHttpQueryDataAvailable( req, &len );
2728 ok( ret, "WinHttpQueryDataAvailable failed with error %u\n", GetLastError() );
2729 if (ret) ok( len != 0xdeadbeef, "WinHttpQueryDataAvailable return wrong length\n" );
2730 if (len)
2731 {
2732 DWORD bytes_read;
2733 char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 );
2734
2735 ret = WinHttpReadData( req, buf, len, &bytes_read );
2736 ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len );
2737
2738 HeapFree( GetProcessHeap(), 0, buf );
2739 if (!bytes_read) break;
2740 total_len += bytes_read;
2741 }
2742 if (!len) break;
2743 }
2744 ok(total_len == BIG_BUFFER_LEN, "got wrong length: 0x%x\n", total_len);
2745
2746 WinHttpCloseHandle(req);
2747 WinHttpCloseHandle(con);
2748 WinHttpCloseHandle(ses);
2749 }
2750
2751 static void test_cookies( int port )
2752 {
2753 static const WCHAR cookieW[] = {'/','c','o','o','k','i','e',0};
2754 static const WCHAR cookie2W[] = {'/','c','o','o','k','i','e','2',0};
2755 static const WCHAR cookie3W[] = {'/','c','o','o','k','i','e','3',0};
2756 static const WCHAR cookieheaderW[] =
2757 {'C','o','o','k','i','e',':',' ','n','a','m','e','=','v','a','l','u','e','2','\r','\n',0};
2758 HINTERNET ses, con, req;
2759 DWORD status, size;
2760 BOOL ret;
2761
2762 ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
2763 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
2764
2765 con = WinHttpConnect( ses, localhostW, port, 0 );
2766 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2767
2768 req = WinHttpOpenRequest( con, NULL, cookieW, NULL, NULL, NULL, 0 );
2769 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2770
2771 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2772 ok( ret, "failed to send request %u\n", GetLastError() );
2773
2774 ret = WinHttpReceiveResponse( req, NULL );
2775 ok( ret, "failed to receive response %u\n", GetLastError() );
2776
2777 status = 0xdeadbeef;
2778 size = sizeof(status);
2779 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
2780 ok( ret, "failed to query status code %u\n", GetLastError() );
2781 ok( status == 200, "request failed unexpectedly %u\n", status );
2782
2783 WinHttpCloseHandle( req );
2784
2785 req = WinHttpOpenRequest( con, NULL, cookie2W, NULL, NULL, NULL, 0 );
2786 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2787
2788 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2789 ok( ret, "failed to send request %u\n", GetLastError() );
2790
2791 ret = WinHttpReceiveResponse( req, NULL );
2792 ok( ret, "failed to receive response %u\n", GetLastError() );
2793
2794 status = 0xdeadbeef;
2795 size = sizeof(status);
2796 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
2797 ok( ret, "failed to query status code %u\n", GetLastError() );
2798 ok( status == 200, "request failed unexpectedly %u\n", status );
2799
2800 WinHttpCloseHandle( req );
2801 WinHttpCloseHandle( con );
2802
2803 con = WinHttpConnect( ses, localhostW, port, 0 );
2804 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2805
2806 req = WinHttpOpenRequest( con, NULL, cookie2W, NULL, NULL, NULL, 0 );
2807 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2808
2809 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2810 ok( ret, "failed to send request %u\n", GetLastError() );
2811
2812 ret = WinHttpReceiveResponse( req, NULL );
2813 ok( ret, "failed to receive response %u\n", GetLastError() );
2814
2815 status = 0xdeadbeef;
2816 size = sizeof(status);
2817 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
2818 ok( ret, "failed to query status code %u\n", GetLastError() );
2819 ok( status == 200, "request failed unexpectedly %u\n", status );
2820
2821 WinHttpCloseHandle( req );
2822
2823 req = WinHttpOpenRequest( con, NULL, cookie3W, NULL, NULL, NULL, 0 );
2824 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2825
2826 ret = WinHttpSendRequest( req, cookieheaderW, ~0u, NULL, 0, 0, 0 );
2827 ok( ret, "failed to send request %u\n", GetLastError() );
2828
2829 ret = WinHttpReceiveResponse( req, NULL );
2830 ok( ret, "failed to receive response %u\n", GetLastError() );
2831
2832 status = 0xdeadbeef;
2833 size = sizeof(status);
2834 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
2835 ok( ret, "failed to query status code %u\n", GetLastError() );
2836 ok( status == 200 || broken(status == 400), "request failed unexpectedly %u\n", status );
2837
2838 WinHttpCloseHandle( req );
2839 WinHttpCloseHandle( con );
2840 WinHttpCloseHandle( ses );
2841
2842 ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
2843 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
2844
2845 con = WinHttpConnect( ses, localhostW, port, 0 );
2846 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2847
2848 req = WinHttpOpenRequest( con, NULL, cookie2W, NULL, NULL, NULL, 0 );
2849 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2850
2851 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2852 ok( ret, "failed to send request %u\n", GetLastError() );
2853
2854 ret = WinHttpReceiveResponse( req, NULL );
2855 ok( ret, "failed to receive response %u\n", GetLastError() );
2856
2857 status = 0xdeadbeef;
2858 size = sizeof(status);
2859 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
2860 ok( ret, "failed to query status code %u\n", GetLastError() );
2861 ok( status == 400, "request failed unexpectedly %u\n", status );
2862
2863 WinHttpCloseHandle( req );
2864 WinHttpCloseHandle( con );
2865 WinHttpCloseHandle( ses );
2866 }
2867
2868 static void test_connection_info( int port )
2869 {
2870 static const WCHAR basicW[] = {'/','b','a','s','i','c',0};
2871 HINTERNET ses, con, req;
2872 WINHTTP_CONNECTION_INFO info;
2873 DWORD size, error;
2874 BOOL ret;
2875
2876 ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
2877 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
2878
2879 con = WinHttpConnect( ses, localhostW, port, 0 );
2880 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2881
2882 req = WinHttpOpenRequest( con, NULL, basicW, NULL, NULL, NULL, 0 );
2883 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2884
2885 size = sizeof(info);
2886 SetLastError( 0xdeadbeef );
2887 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
2888 error = GetLastError();
2889 if (!ret && error == ERROR_INVALID_PARAMETER)
2890 {
2891 win_skip( "WINHTTP_OPTION_CONNECTION_INFO not supported\n" );
2892 return;
2893 }
2894 ok( !ret, "unexpected success\n" );
2895 ok( error == ERROR_WINHTTP_INCORRECT_HANDLE_STATE, "got %u\n", error );
2896
2897 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2898 ok( ret, "failed to send request %u\n", GetLastError() );
2899
2900 size = 0;
2901 SetLastError( 0xdeadbeef );
2902 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
2903 error = GetLastError();
2904 ok( !ret, "unexpected success\n" );
2905 ok( error == ERROR_INSUFFICIENT_BUFFER, "got %u\n", error );
2906
2907 size = sizeof(info);
2908 memset( &info, 0, sizeof(info) );
2909 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
2910 ok( ret, "failed to retrieve connection info %u\n", GetLastError() );
2911 ok( info.cbSize == sizeof(info), "wrong size %u\n", info.cbSize );
2912
2913 ret = WinHttpReceiveResponse( req, NULL );
2914 ok( ret, "failed to receive response %u\n", GetLastError() );
2915
2916 size = sizeof(info);
2917 memset( &info, 0, sizeof(info) );
2918 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
2919 ok( ret, "failed to retrieve connection info %u\n", GetLastError() );
2920 ok( info.cbSize == sizeof(info), "wrong size %u\n", info.cbSize );
2921
2922 WinHttpCloseHandle( req );
2923 WinHttpCloseHandle( con );
2924 WinHttpCloseHandle( ses );
2925 }
2926
2927 static void test_credentials(void)
2928 {
2929 static WCHAR userW[] = {'u','s','e','r',0};
2930 static WCHAR passW[] = {'p','a','s','s',0};
2931 static WCHAR proxy_userW[] = {'p','r','o','x','y','u','s','e','r',0};
2932 static WCHAR proxy_passW[] = {'p','r','o','x','y','p','a','s','s',0};
2933 HINTERNET ses, con, req;
2934 DWORD size, error;
2935 WCHAR buffer[32];
2936 BOOL ret;
2937
2938 ses = WinHttpOpen(test_useragent, 0, proxy_userW, proxy_passW, 0);
2939 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2940
2941 con = WinHttpConnect(ses, localhostW, 0, 0);
2942 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2943
2944 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
2945 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2946
2947 size = sizeof(buffer)/sizeof(WCHAR);
2948 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size);
2949 ok(ret, "failed to query proxy username %u\n", GetLastError());
2950 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
2951 ok(!size, "expected 0, got %u\n", size);
2952
2953 size = sizeof(buffer)/sizeof(WCHAR);
2954 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size);
2955 ok(ret, "failed to query proxy password %u\n", GetLastError());
2956 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
2957 ok(!size, "expected 0, got %u\n", size);
2958
2959 ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_USERNAME, proxy_userW, lstrlenW(proxy_userW));
2960 ok(ret, "failed to set username %u\n", GetLastError());
2961
2962 size = sizeof(buffer)/sizeof(WCHAR);
2963 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size);
2964 ok(ret, "failed to query proxy username %u\n", GetLastError());
2965 ok(!winetest_strcmpW(buffer, proxy_userW), "unexpected result %s\n", wine_dbgstr_w(buffer));
2966 ok(size == lstrlenW(proxy_userW) * sizeof(WCHAR), "unexpected result %u\n", size);
2967
2968 size = sizeof(buffer)/sizeof(WCHAR);
2969 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
2970 ok(ret, "failed to query username %u\n", GetLastError());
2971 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
2972 ok(!size, "expected 0, got %u\n", size);
2973
2974 size = sizeof(buffer)/sizeof(WCHAR);
2975 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
2976 ok(ret, "failed to query password %u\n", GetLastError());
2977 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
2978 ok(!size, "expected 0, got %u\n", size);
2979
2980 ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_PASSWORD, proxy_passW, lstrlenW(proxy_passW));
2981 ok(ret, "failed to set proxy password %u\n", GetLastError());
2982
2983 size = sizeof(buffer)/sizeof(WCHAR);
2984 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size);
2985 ok(ret, "failed to query proxy password %u\n", GetLastError());
2986 ok(!winetest_strcmpW(buffer, proxy_passW), "unexpected result %s\n", wine_dbgstr_w(buffer));
2987 ok(size == lstrlenW(proxy_passW) * sizeof(WCHAR), "unexpected result %u\n", size);
2988
2989 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
2990 ok(ret, "failed to set username %u\n", GetLastError());
2991
2992 size = sizeof(buffer)/sizeof(WCHAR);
2993 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
2994 ok(ret, "failed to query username %u\n", GetLastError());
2995 ok(!winetest_strcmpW(buffer, userW), "unexpected result %s\n", wine_dbgstr_w(buffer));
2996 ok(size == lstrlenW(userW) * sizeof(WCHAR), "unexpected result %u\n", size);
2997
2998 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, passW, lstrlenW(passW));
2999 ok(ret, "failed to set password %u\n", GetLastError());
3000
3001 size = sizeof(buffer)/sizeof(WCHAR);
3002 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3003 ok(ret, "failed to query password %u\n", GetLastError());
3004 ok(!winetest_strcmpW(buffer, passW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3005 ok(size == lstrlenW(passW) * sizeof(WCHAR), "unexpected result %u\n", size);
3006
3007 WinHttpCloseHandle(req);
3008
3009 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
3010 ok(req != NULL, "failed to open a request %u\n", GetLastError());
3011
3012 SetLastError(0xdeadbeef);
3013 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, NULL, NULL);
3014 error = GetLastError();
3015 ok(!ret, "expected failure\n");
3016 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
3017
3018 SetLastError(0xdeadbeef);
3019 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, passW, NULL);
3020 error = GetLastError();
3021 ok(!ret, "expected failure\n");
3022 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
3023
3024 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
3025 ok(ret, "failed to set credentials %u\n", GetLastError());
3026
3027 size = sizeof(buffer)/sizeof(WCHAR);
3028 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
3029 ok(ret, "failed to query username %u\n", GetLastError());
3030 todo_wine {
3031 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3032 ok(!size, "expected 0, got %u\n", size);
3033 }
3034
3035 size = sizeof(buffer)/sizeof(WCHAR);
3036 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3037 ok(ret, "failed to query password %u\n", GetLastError());
3038 todo_wine {
3039 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3040 ok(!size, "expected 0, got %u\n", size);
3041 }
3042
3043 WinHttpCloseHandle(req);
3044 WinHttpCloseHandle(con);
3045 WinHttpCloseHandle(ses);
3046 }
3047
3048 static void test_IWinHttpRequest(void)
3049 {
3050 static const WCHAR usernameW[] = {'u','s','e','r','n','a','m','e',0};
3051 static const WCHAR passwordW[] = {'p','a','s','s','w','o','r','d',0};
3052 static const WCHAR url1W[] = {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
3053 static const WCHAR url2W[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
3054 static const WCHAR url3W[] = {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.',
3055 'o','r','g','/','t','e','s','t','s','/','p','o','s','t','.','p','h','p',0};
3056 static const WCHAR method1W[] = {'G','E','T',0};
3057 static const WCHAR method2W[] = {'I','N','V','A','L','I','D',0};
3058 static const WCHAR method3W[] = {'P','O','S','T',0};
3059 static const WCHAR proxy_serverW[] = {'p','r','o','x','y','s','e','r','v','e','r',0};
3060 static const WCHAR bypas_listW[] = {'b','y','p','a','s','s','l','i','s','t',0};
3061 static const WCHAR connectionW[] = {'C','o','n','n','e','c','t','i','o','n',0};
3062 static const WCHAR dateW[] = {'D','a','t','e',0};
3063 static const WCHAR test_dataW[] = {'t','e','s','t','d','a','t','a',128,0};
3064 static const WCHAR utf8W[] = {'u','t','f','-','8',0};
3065 HRESULT hr;
3066 IWinHttpRequest *req;
3067 BSTR method, url, username, password, response = NULL, status_text = NULL, headers = NULL;
3068 BSTR date, today, connection, value = NULL;
3069 VARIANT async, empty, timeout, body, body2, proxy_server, bypass_list, data, cp;
3070 VARIANT_BOOL succeeded;
3071 LONG status;
3072 WCHAR todayW[WINHTTP_TIME_FORMAT_BUFSIZE];
3073 SYSTEMTIME st;
3074 IStream *stream, *stream2;
3075 LARGE_INTEGER pos;
3076 char buf[128];
3077 DWORD count;
3078
3079 GetSystemTime( &st );
3080 WinHttpTimeFromSystemTime( &st, todayW );
3081
3082 CoInitialize( NULL );
3083 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3084 ok( hr == S_OK, "got %08x\n", hr );
3085
3086 V_VT( &empty ) = VT_ERROR;
3087 V_ERROR( &empty ) = 0xdeadbeef;
3088
3089 V_VT( &async ) = VT_BOOL;
3090 V_BOOL( &async ) = VARIANT_FALSE;
3091
3092 method = SysAllocString( method3W );
3093 url = SysAllocString( url3W );
3094 hr = IWinHttpRequest_Open( req, method, url, async );
3095 ok( hr == S_OK, "got %08x\n", hr );
3096 SysFreeString( method );
3097 SysFreeString( url );
3098
3099 V_VT( &data ) = VT_BSTR;
3100 V_BSTR( &data ) = SysAllocString( test_dataW );
3101 hr = IWinHttpRequest_Send( req, data );
3102 ok( hr == S_OK || broken(hr == HRESULT_FROM_WIN32(ERROR_WINHTTP_INVALID_SERVER_RESPONSE)),
3103 "got %08x\n", hr );
3104 SysFreeString( V_BSTR( &data ) );
3105
3106 hr = IWinHttpRequest_Open( req, NULL, NULL, empty );
3107 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3108
3109 method = SysAllocString( method1W );
3110 hr = IWinHttpRequest_Open( req, method, NULL, empty );
3111 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3112
3113 hr = IWinHttpRequest_Open( req, method, NULL, async );
3114 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3115
3116 url = SysAllocString( url1W );
3117 hr = IWinHttpRequest_Open( req, NULL, url, empty );
3118 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3119
3120 hr = IWinHttpRequest_Abort( req );
3121 ok( hr == S_OK, "got %08x\n", hr );
3122
3123 hr = IWinHttpRequest_Open( req, method, url, empty );
3124 ok( hr == S_OK, "got %08x\n", hr );
3125
3126 hr = IWinHttpRequest_Abort( req );
3127 ok( hr == S_OK, "got %08x\n", hr );
3128
3129 IWinHttpRequest_Release( req );
3130
3131 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3132 ok( hr == S_OK, "got %08x\n", hr );
3133
3134 SysFreeString( url );
3135 url = SysAllocString( url2W );
3136 hr = IWinHttpRequest_Open( req, method, url, async );
3137 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ), "got %08x\n", hr );
3138
3139 SysFreeString( method );
3140 method = SysAllocString( method2W );
3141 hr = IWinHttpRequest_Open( req, method, url, async );
3142 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ), "got %08x\n", hr );
3143
3144 SysFreeString( method );
3145 method = SysAllocString( method1W );
3146 SysFreeString( url );
3147 url = SysAllocString( url1W );
3148 V_VT( &async ) = VT_ERROR;
3149 V_ERROR( &async ) = DISP_E_PARAMNOTFOUND;
3150 hr = IWinHttpRequest_Open( req, method, url, async );
3151 ok( hr == S_OK, "got %08x\n", hr );
3152
3153 V_VT( &cp ) = VT_ERROR;
3154 V_ERROR( &cp ) = 0xdeadbeef;
3155 hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3156 ok( hr == S_OK, "got %08x\n", hr );
3157 ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3158 ok( V_I4( &cp ) == CP_UTF8, "got %u\n", V_I4( &cp ) );
3159
3160 V_VT( &cp ) = VT_UI4;
3161 V_UI4( &cp ) = CP_ACP;
3162 hr = IWinHttpRequest_put_Option( req, WinHttpRequestOption_URLCodePage, cp );
3163 ok( hr == S_OK, "got %08x\n", hr );
3164
3165 V_VT( &cp ) = VT_ERROR;
3166 V_ERROR( &cp ) = 0xdeadbeef;
3167 hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3168 ok( hr == S_OK, "got %08x\n", hr );
3169 ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3170 ok( V_I4( &cp ) == CP_ACP, "got %u\n", V_I4( &cp ) );
3171
3172 value = SysAllocString( utf8W );
3173 V_VT( &cp ) = VT_BSTR;
3174 V_BSTR( &cp ) = value;
3175 hr = IWinHttpRequest_put_Option( req, WinHttpRequestOption_URLCodePage, cp );
3176 ok( hr == S_OK, "got %08x\n", hr );
3177 SysFreeString( value );
3178
3179 V_VT( &cp ) = VT_ERROR;
3180 V_ERROR( &cp ) = 0xdeadbeef;
3181 hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3182 ok( hr == S_OK, "got %08x\n", hr );
3183 ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3184 ok( V_I4( &cp ) == CP_UTF8, "got %u\n", V_I4( &cp ) );
3185
3186 hr = IWinHttpRequest_Abort( req );
3187 ok( hr == S_OK, "got %08x\n", hr );
3188
3189 hr = IWinHttpRequest_Send( req, empty );
3190 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3191
3192 hr = IWinHttpRequest_Abort( req );
3193 ok( hr == S_OK, "got %08x\n", hr );
3194
3195 IWinHttpRequest_Release( req );
3196
3197 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3198 ok( hr == S_OK, "got %08x\n", hr );
3199
3200 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3201 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3202
3203 hr = IWinHttpRequest_get_ResponseText( req, &response );
3204 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3205
3206 hr = IWinHttpRequest_get_Status( req, NULL );
3207 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3208
3209 hr = IWinHttpRequest_get_Status( req, &status );
3210 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3211
3212 hr = IWinHttpRequest_get_StatusText( req, NULL );
3213 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3214
3215 hr = IWinHttpRequest_get_StatusText( req, &status_text );
3216 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3217
3218 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3219 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3220
3221 hr = IWinHttpRequest_SetTimeouts( req, 10000, 10000, 10000, 10000 );
3222 ok( hr == S_OK, "got %08x\n", hr );
3223
3224 hr = IWinHttpRequest_SetCredentials( req, NULL, NULL, 0xdeadbeef );
3225 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3226
3227 VariantInit( &proxy_server );
3228 V_VT( &proxy_server ) = VT_ERROR;
3229 VariantInit( &bypass_list );
3230 V_VT( &bypass_list ) = VT_ERROR;
3231 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3232 ok( hr == S_OK, "got %08x\n", hr );
3233
3234 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3235 ok( hr == S_OK, "got %08x\n", hr );
3236
3237 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3238 ok( hr == S_OK, "got %08x\n", hr );
3239
3240 hr = IWinHttpRequest_GetAllResponseHeaders( req, NULL );
3241 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3242
3243 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3244 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3245
3246 hr = IWinHttpRequest_GetResponseHeader( req, NULL, NULL );
3247 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3248
3249 connection = SysAllocString( connectionW );
3250 hr = IWinHttpRequest_GetResponseHeader( req, connection, NULL );
3251 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3252
3253 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3254 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3255
3256 hr = IWinHttpRequest_SetRequestHeader( req, NULL, NULL );
3257 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3258
3259 date = SysAllocString( dateW );
3260 hr = IWinHttpRequest_SetRequestHeader( req, date, NULL );
3261 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3262
3263 today = SysAllocString( todayW );
3264 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3265 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3266
3267 hr = IWinHttpRequest_SetAutoLogonPolicy( req, 0xdeadbeef );
3268 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3269
3270 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3271 ok( hr == S_OK, "got %08x\n", hr );
3272
3273 SysFreeString( method );
3274 method = SysAllocString( method1W );
3275 SysFreeString( url );
3276 url = SysAllocString( url1W );
3277 hr = IWinHttpRequest_Open( req, method, url, async );
3278 ok( hr == S_OK, "got %08x\n", hr );
3279
3280 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3281 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3282
3283 hr = IWinHttpRequest_get_ResponseText( req, &response );
3284 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3285
3286 hr = IWinHttpRequest_get_Status( req, &status );
3287 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3288
3289 hr = IWinHttpRequest_get_StatusText( req, &status_text );
3290 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3291
3292 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3293 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3294
3295 hr = IWinHttpRequest_SetTimeouts( req, 10000, 10000, 10000, 10000 );
3296 ok( hr == S_OK, "got %08x\n", hr );
3297
3298 hr = IWinHttpRequest_SetCredentials( req, NULL, NULL, 0xdeadbeef );
3299 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3300
3301 username = SysAllocString( usernameW );
3302 hr = IWinHttpRequest_SetCredentials( req, username, NULL, 0xdeadbeef );
3303 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3304
3305 password = SysAllocString( passwordW );
3306 hr = IWinHttpRequest_SetCredentials( req, NULL, password, 0xdeadbeef );
3307 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3308
3309 hr = IWinHttpRequest_SetCredentials( req, username, password, 0xdeadbeef );
3310 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3311
3312 hr = IWinHttpRequest_SetCredentials( req, NULL, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3313 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3314
3315 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3316 ok( hr == S_OK, "got %08x\n", hr );
3317
3318 V_VT( &proxy_server ) = VT_BSTR;
3319 V_BSTR( &proxy_server ) = SysAllocString( proxy_serverW );
3320 V_VT( &bypass_list ) = VT_BSTR;
3321 V_BSTR( &bypass_list ) = SysAllocString( bypas_listW );
3322 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3323 ok( hr == S_OK, "got %08x\n", hr );
3324
3325 hr = IWinHttpRequest_SetProxy( req, 0xdeadbeef, proxy_server, bypass_list );
3326 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3327
3328 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3329 ok( hr == S_OK, "got %08x\n", hr );
3330
3331 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3332 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3333
3334 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3335 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3336
3337 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3338 ok( hr == S_OK, "got %08x\n", hr );
3339
3340 hr = IWinHttpRequest_SetRequestHeader( req, date, NULL );
3341 ok( hr == S_OK, "got %08x\n", hr );
3342
3343 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3344 ok( hr == S_OK, "got %08x\n", hr );
3345
3346 hr = IWinHttpRequest_Send( req, empty );
3347 ok( hr == S_OK, "got %08x\n", hr );
3348
3349 hr = IWinHttpRequest_Send( req, empty );
3350 ok( hr == S_OK, "got %08x\n", hr );
3351
3352 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3353 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3354
3355 hr = IWinHttpRequest_get_ResponseText( req, &response );
3356 ok( hr == S_OK, "got %08x\n", hr );
3357 SysFreeString( response );
3358
3359 hr = IWinHttpRequest_get_Status( req, NULL );
3360 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3361
3362 status = 0;
3363 hr = IWinHttpRequest_get_Status( req, &status );
3364 ok( hr == S_OK, "got %08x\n", hr );
3365 trace("Status=%d\n", status);
3366
3367 hr = IWinHttpRequest_get_StatusText( req, NULL );
3368 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3369
3370 hr = IWinHttpRequest_get_StatusText( req, &status_text );
3371 ok( hr == S_OK, "got %08x\n", hr );
3372 trace("StatusText=%s\n", wine_dbgstr_w(status_text));
3373 SysFreeString( status_text );
3374
3375 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3376 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3377
3378 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3379 ok( hr == S_OK, "got %08x\n", hr );
3380
3381 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3382 ok( hr == S_OK, "got %08x\n", hr );
3383
3384 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3385 ok( hr == S_OK, "got %08x\n", hr );
3386
3387 hr = IWinHttpRequest_GetAllResponseHeaders( req, NULL );
3388 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3389
3390 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3391 ok( hr == S_OK, "got %08x\n", hr );
3392 SysFreeString( headers );
3393
3394 hr = IWinHttpRequest_GetResponseHeader( req, NULL, NULL );
3395 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3396
3397 hr = IWinHttpRequest_GetResponseHeader( req, connection, NULL );
3398 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3399
3400 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3401 ok( hr == S_OK, "got %08x\n", hr );
3402 SysFreeString( value );
3403
3404 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3405 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND ), "got %08x\n", hr );
3406
3407 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3408 ok( hr == S_OK, "got %08x\n", hr );
3409
3410 VariantInit( &timeout );
3411 V_VT( &timeout ) = VT_I4;
3412 V_I4( &timeout ) = 10;
3413 hr = IWinHttpRequest_WaitForResponse( req, timeout, &succeeded );
3414 ok( hr == S_OK, "got %08x\n", hr );
3415
3416 hr = IWinHttpRequest_get_Status( req, &status );
3417 ok( hr == S_OK, "got %08x\n", hr );
3418
3419 hr = IWinHttpRequest_get_StatusText( req, &status_text );
3420 ok( hr == S_OK, "got %08x\n", hr );
3421 SysFreeString( status_text );
3422
3423 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3424 ok( hr == S_OK, "got %08x\n", hr );
3425
3426 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3427 ok( hr == S_OK, "got %08x\n", hr );
3428
3429 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3430 ok( hr == S_OK, "got %08x\n", hr );
3431
3432 hr = IWinHttpRequest_Send( req, empty );
3433 ok( hr == S_OK, "got %08x\n", hr );
3434
3435 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3436 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3437
3438 hr = IWinHttpRequest_get_ResponseText( req, &response );
3439 ok( hr == S_OK, "got %08x\n", hr );
3440 SysFreeString( response );
3441
3442 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3443 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3444
3445 VariantInit( &body );
3446 V_VT( &body ) = VT_ERROR;
3447 hr = IWinHttpRequest_get_ResponseBody( req, &body );
3448 ok( hr == S_OK, "got %08x\n", hr );
3449 ok( V_VT( &body ) == (VT_ARRAY|VT_UI1), "got %08x\n", V_VT( &body ) );
3450
3451 hr = VariantClear( &body );
3452 ok( hr == S_OK, "got %08x\n", hr );
3453
3454 VariantInit( &body );
3455 V_VT( &body ) = VT_ERROR;
3456 hr = IWinHttpRequest_get_ResponseStream( req, &body );
3457 ok( hr == S_OK, "got %08x\n", hr );
3458 ok( V_VT( &body ) == VT_UNKNOWN, "got %08x\n", V_VT( &body ) );
3459
3460 hr = IUnknown_QueryInterface( V_UNKNOWN( &body ), &IID_IStream, (void **)&stream );
3461 ok( hr == S_OK, "got %08x\n", hr );
3462 ok( V_UNKNOWN( &body ) == (IUnknown *)stream, "got different interface pointer\n" );
3463
3464 buf[0] = 0;
3465 count = 0xdeadbeef;
3466 hr = IStream_Read( stream, buf, 128, &count );
3467 ok( hr == S_OK, "got %08x\n", hr );
3468 ok( count != 0xdeadbeef, "count not set\n" );
3469 ok( buf[0], "no data\n" );
3470
3471 VariantInit( &body2 );
3472 V_VT( &body2 ) = VT_ERROR;
3473 hr = IWinHttpRequest_get_ResponseStream( req, &body2 );
3474 ok( hr == S_OK, "got %08x\n", hr );
3475 ok( V_VT( &body2 ) == VT_UNKNOWN, "got %08x\n", V_VT( &body2 ) );
3476 ok( V_UNKNOWN( &body ) != V_UNKNOWN( &body2 ), "got same interface pointer\n" );
3477
3478 hr = IUnknown_QueryInterface( V_UNKNOWN( &body2 ), &IID_IStream, (void **)&stream2 );
3479 ok( hr == S_OK, "got %08x\n", hr );
3480 ok( V_UNKNOWN( &body2 ) == (IUnknown *)stream2, "got different interface pointer\n" );
3481 IStream_Release( stream2 );
3482
3483 hr = VariantClear( &body );
3484 ok( hr == S_OK, "got %08x\n", hr );
3485
3486 hr = VariantClear( &body2 );
3487 ok( hr == S_OK, "got %08x\n", hr );
3488
3489 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3490 ok( hr == S_OK, "got %08x\n", hr );
3491
3492 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3493 ok( hr == S_OK, "got %08x\n", hr );
3494
3495 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3496 ok( hr == S_OK, "got %08x\n", hr );
3497 SysFreeString( headers );
3498
3499 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3500 ok( hr == S_OK, "got %08x\n", hr );
3501 SysFreeString( value );
3502
3503 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3504 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND ), "got %08x\n", hr );
3505
3506 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3507 ok( hr == S_OK, "got %08x\n", hr );
3508
3509 hr = IWinHttpRequest_Send( req, empty );
3510 ok( hr == S_OK, "got %08x\n", hr );
3511
3512 hr = IWinHttpRequest_Abort( req );
3513 ok( hr == S_OK, "got %08x\n", hr );
3514
3515 hr = IWinHttpRequest_Abort( req );
3516 ok( hr == S_OK, "got %08x\n", hr );
3517
3518 IWinHttpRequest_Release( req );
3519
3520 pos.QuadPart = 0;
3521 hr = IStream_Seek( stream, pos, STREAM_SEEK_SET, NULL );
3522 ok( hr == S_OK, "got %08x\n", hr );
3523
3524 buf[0] = 0;
3525 count = 0xdeadbeef;
3526 hr = IStream_Read( stream, buf, 128, &count );
3527 ok( hr == S_OK, "got %08x\n", hr );
3528 ok( count != 0xdeadbeef, "count not set\n" );
3529 ok( buf[0], "no data\n" );
3530 IStream_Release( stream );
3531
3532 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3533 ok( hr == S_OK, "got %08x\n", hr );
3534
3535 V_VT( &async ) = VT_I4;
3536 V_I4( &async ) = 1;
3537 hr = IWinHttpRequest_Open( req, method, url, async );
3538 ok( hr == S_OK, "got %08x\n", hr );
3539
3540 hr = IWinHttpRequest_Send( req, empty );
3541 ok( hr == S_OK, "got %08x\n", hr );
3542
3543 hr = IWinHttpRequest_WaitForResponse( req, timeout, &succeeded );
3544 ok( hr == S_OK, "got %08x\n", hr );
3545
3546 IWinHttpRequest_Release( req );
3547
3548 SysFreeString( method );
3549 SysFreeString( url );
3550 SysFreeString( username );
3551 SysFreeString( password );
3552 SysFreeString( connection );
3553 SysFreeString( date );
3554 SysFreeString( today );
3555 VariantClear( &proxy_server );
3556 VariantClear( &bypass_list );
3557 CoUninitialize();
3558 }
3559
3560 static void request_get_property(IWinHttpRequest *request, int property, VARIANT *ret)
3561 {
3562 DISPPARAMS params;
3563 VARIANT arg;
3564 HRESULT hr;
3565
3566 memset(&params, 0, sizeof(params));
3567 params.cNamedArgs = 0;
3568 params.rgdispidNamedArgs = NULL;
3569 params.cArgs = 1;
3570 params.rgvarg = &arg;
3571 VariantInit(&arg);
3572 V_VT(&arg) = VT_I4;
3573 V_I4(&arg) = property;
3574 VariantInit(ret);
3575 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
3576 DISPATCH_PROPERTYGET, &params, ret, NULL, NULL);
3577 ok(hr == S_OK, "error %#x\n", hr);
3578 }
3579
3580 static void test_IWinHttpRequest_Invoke(void)
3581 {
3582 static const WCHAR utf8W[] = {'U','T','F','-','8',0};
3583 static const WCHAR regid[] = {'W','i','n','H','t','t','p','.','W','i','n','H','t','t','p','R','e','q','u','e','s','t','.','5','.','1',0};
3584 WCHAR openW[] = {'O','p','e','n',0};
3585 WCHAR optionW[] = {'O','p','t','i','o','n',0};
3586 OLECHAR *open = openW, *option = optionW;
3587 BSTR utf8;
3588 CLSID clsid;
3589 IWinHttpRequest *request;
3590 IDispatch *dispatch;
3591 DISPID id;
3592 DISPPARAMS params;
3593 VARIANT arg[3], ret;
3594 UINT err;
3595 BOOL bret;
3596 HRESULT hr;
3597
3598 CoInitialize(NULL);
3599
3600 hr = CLSIDFromProgID(regid, &clsid);
3601 ok(hr == S_OK, "CLSIDFromProgID error %#x\n", hr);
3602 bret = IsEqualIID(&clsid, &CLSID_WinHttpRequest);
3603 ok(bret || broken(!bret) /* win2003 */, "not expected %s\n", wine_dbgstr_guid(&clsid));
3604
3605 hr = CoCreateInstance(&CLSID_WinHttpRequest, 0, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&request);
3606 ok(hr == S_OK, "error %#x\n", hr);
3607
3608 hr = IWinHttpRequest_QueryInterface(request, &IID_IDispatch, (void **)&dispatch);
3609 ok(hr == S_OK, "error %#x\n", hr);
3610 IDispatch_Release(dispatch);
3611
3612 hr = IWinHttpRequest_GetIDsOfNames(request, &IID_NULL, &open, 1, 0x0409, &id);
3613 ok(hr == S_OK, "error %#x\n", hr);
3614 ok(id == DISPID_HTTPREQUEST_OPEN, "expected DISPID_HTTPREQUEST_OPEN, got %u\n", id);
3615
3616 hr = IWinHttpRequest_GetIDsOfNames(request, &IID_NULL, &option, 1, 0x0409, &id);
3617 ok(hr == S_OK, "error %#x\n", hr);
3618 ok(id == DISPID_HTTPREQUEST_OPTION, "expected DISPID_HTTPREQUEST_OPTION, got %u\n", id);
3619
3620 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3621 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3622 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
3623
3624 memset(&params, 0, sizeof(params));
3625 params.cArgs = 2;
3626 params.cNamedArgs = 0;
3627 params.rgvarg = arg;
3628 V_VT(&arg[0]) = VT_I4;
3629 V_I4(&arg[0]) = 1252;
3630 V_VT(&arg[1]) = VT_R8;
3631 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
3632 VariantInit(&ret);
3633 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
3634 DISPATCH_METHOD, &params, NULL, NULL, &err);
3635 ok(hr == S_OK, "error %#x\n", hr);
3636
3637 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3638 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3639 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
3640
3641 memset(&params, 0, sizeof(params));
3642 params.cArgs = 2;
3643 params.cNamedArgs = 0;
3644 params.rgvarg = arg;
3645 V_VT(&arg[0]) = VT_I4;
3646 V_I4(&arg[0]) = 1252;
3647 V_VT(&arg[1]) = VT_R8;
3648 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
3649 VariantInit(&ret);
3650 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
3651 DISPATCH_METHOD | DISPATCH_PROPERTYPUT, &params, NULL, NULL, &err);
3652 ok(hr == S_OK, "error %#x\n", hr);
3653
3654 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3655 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3656 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
3657
3658 memset(&params, 0, sizeof(params));
3659 params.cArgs = 2;
3660 params.cNamedArgs = 0;
3661 params.rgvarg = arg;
3662 V_VT(&arg[0]) = VT_I4;
3663 V_I4(&arg[0]) = 1252;
3664 V_VT(&arg[1]) = VT_R8;
3665 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
3666 VariantInit(&ret);
3667 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
3668 DISPATCH_PROPERTYPUT, &params, NULL, NULL, &err);
3669 ok(hr == S_OK, "error %#x\n", hr);
3670
3671 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3672 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3673 ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
3674
3675 memset(&params, 0, sizeof(params));
3676 params.cArgs = 2;
3677 params.cNamedArgs = 0;
3678 params.rgvarg = arg;
3679 V_VT(&arg[0]) = VT_BSTR;
3680 utf8 = SysAllocString(utf8W);
3681 V_BSTR(&arg[0]) = utf8;
3682 V_VT(&arg[1]) = VT_R8;
3683 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
3684 hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_METHOD, &params, NULL, NULL, &err);
3685 ok(hr == S_OK, "error %#x\n", hr);
3686
3687 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3688 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3689 ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
3690
3691 VariantInit(&ret);
3692 hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_METHOD, &params, &ret, NULL, &err);
3693 ok(hr == S_OK, "error %#x\n", hr);
3694
3695 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3696 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3697 ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
3698
3699 VariantInit(&ret);
3700 hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
3701 ok(hr == S_OK, "error %#x\n", hr);
3702
3703 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3704 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3705 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
3706
3707 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, NULL, NULL, NULL);
3708 ok(hr == S_OK, "error %#x\n", hr);
3709
3710 hr = IWinHttpRequest_Invoke(request, 255, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, NULL, NULL, NULL);
3711 ok(hr == DISP_E_MEMBERNOTFOUND, "error %#x\n", hr);
3712
3713 VariantInit(&ret);
3714 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
3715 ok(hr == DISP_E_UNKNOWNINTERFACE, "error %#x\n", hr);
3716
3717 VariantInit(&ret);
3718 if (0) /* crashes */
3719 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, &ret, NULL, &err);
3720
3721 params.cArgs = 1;
3722 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
3723 ok(hr == DISP_E_TYPEMISMATCH, "error %#x\n", hr);
3724
3725 VariantInit(&arg[2]);
3726 params.cArgs = 3;
3727 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
3728 todo_wine
3729 ok(hr == S_OK, "error %#x\n", hr);
3730
3731 VariantInit(&arg[0]);
3732 VariantInit(&arg[1]);
3733 VariantInit(&arg[2]);
3734
3735 params.cArgs = 1;
3736 V_VT(&arg[0]) = VT_I4;
3737 V_I4(&arg[0]) = WinHttpRequestOption_URLCodePage;
3738 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
3739 ok(hr == S_OK, "error %#x\n", hr);
3740
3741 V_VT(&ret) = 0xdead;
3742 V_I4(&ret) = 0xbeef;
3743 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &params, &ret, NULL, NULL);
3744 ok(hr == S_OK, "error %#x\n", hr);
3745 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3746 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
3747
3748 V_VT(&ret) = 0xdead;
3749 V_I4(&ret) = 0xbeef;
3750 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD, &params, &ret, NULL, NULL);
3751 ok(hr == S_OK, "error %#x\n", hr);
3752 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3753 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
3754
3755 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
3756 ok(hr == S_OK, "error %#x\n", hr);
3757
3758 V_VT(&ret) = 0xdead;
3759 V_I4(&ret) = 0xbeef;
3760 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, 0, &params, &ret, NULL, NULL);
3761 ok(hr == S_OK, "error %#x\n", hr);
3762 ok(V_VT(&ret) == VT_EMPTY, "expected VT_EMPTY, got %d\n", V_VT(&ret));
3763 ok(V_I4(&ret) == 0xbeef || V_I4(&ret) == 0 /* Win8 */, "expected 0xdead, got %d\n", V_I4(&ret));
3764
3765 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, 0, &params, NULL, NULL, NULL);
3766 ok(hr == S_OK, "error %#x\n", hr);
3767
3768 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_IUnknown, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
3769 ok(hr == DISP_E_UNKNOWNINTERFACE, "error %#x\n", hr);
3770
3771 params.cArgs = 2;
3772 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
3773 todo_wine
3774 ok(hr == S_OK, "error %#x\n", hr);
3775
3776 params.cArgs = 0;
3777 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
3778 ok(hr == DISP_E_PARAMNOTFOUND, "error %#x\n", hr);
3779
3780 SysFreeString(utf8);
3781
3782 params.cArgs = 1;
3783 V_VT(&arg[0]) = VT_I4;
3784 V_I4(&arg[0]) = AutoLogonPolicy_Never;
3785 VariantInit(&ret);
3786 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_SETAUTOLOGONPOLICY, &IID_NULL, 0,
3787 DISPATCH_METHOD, &params, &ret, NULL, NULL);
3788 ok(hr == S_OK, "error %#x\n", hr);
3789
3790 IWinHttpRequest_Release(request);
3791
3792 CoUninitialize();
3793 }
3794
3795 static void test_WinHttpDetectAutoProxyConfigUrl(void)
3796 {
3797 BOOL ret;
3798 WCHAR *url;
3799 DWORD error;
3800
3801 if (0) /* crashes on some win2k systems */
3802 {
3803 SetLastError(0xdeadbeef);
3804 ret = WinHttpDetectAutoProxyConfigUrl( 0, NULL );
3805 error = GetLastError();
3806 ok( !ret, "expected failure\n" );
3807 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3808 }
3809 url = NULL;
3810 SetLastError(0xdeadbeef);
3811 ret = WinHttpDetectAutoProxyConfigUrl( 0, &url );
3812 error = GetLastError();
3813 ok( !ret, "expected failure\n" );
3814 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3815
3816 if (0) /* crashes on some win2k systems */
3817 {
3818 SetLastError(0xdeadbeef);
3819 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, NULL );
3820 error = GetLastError();
3821 ok( !ret, "expected failure\n" );
3822 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3823 }
3824 url = (WCHAR *)0xdeadbeef;
3825 SetLastError(0xdeadbeef);
3826 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, &url );
3827 error = GetLastError();
3828 if (!ret)
3829 {
3830 ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED, "got %u\n", error );
3831 ok( !url || broken(url == (WCHAR *)0xdeadbeef), "got %p\n", url );
3832 }
3833 else
3834 {
3835 trace("%s\n", wine_dbgstr_w(url));
3836 GlobalFree( url );
3837 }
3838
3839 url = (WCHAR *)0xdeadbeef;
3840 SetLastError(0xdeadbeef);
3841 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DHCP, &url );
3842 error = GetLastError();
3843 if (!ret)
3844 {
3845 ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED, "got %u\n", error );
3846 ok( !url || broken(url == (WCHAR *)0xdeadbeef), "got %p\n", url );
3847 }
3848 else
3849 {
3850 ok( error == ERROR_SUCCESS, "got %u\n", error );
3851 trace("%s\n", wine_dbgstr_w(url));
3852 GlobalFree( url );
3853 }
3854 }
3855
3856 static void test_WinHttpGetIEProxyConfigForCurrentUser(void)
3857 {
3858 BOOL ret;
3859 DWORD error;
3860 WINHTTP_CURRENT_USER_IE_PROXY_CONFIG cfg;
3861
3862 memset( &cfg, 0, sizeof(cfg) );
3863
3864 SetLastError(0xdeadbeef);
3865 ret = WinHttpGetIEProxyConfigForCurrentUser( NULL );
3866 error = GetLastError();
3867 ok( !ret, "expected failure\n" );
3868 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3869
3870 SetLastError(0xdeadbeef);
3871 ret = WinHttpGetIEProxyConfigForCurrentUser( &cfg );
3872 error = GetLastError();
3873 ok( ret, "expected success\n" );
3874 ok( error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* < win7 */, "got %u\n", error );
3875
3876 trace("IEProxy.AutoDetect=%d\n", cfg.fAutoDetect);
3877 trace("IEProxy.AutoConfigUrl=%s\n", wine_dbgstr_w(cfg.lpszAutoConfigUrl));
3878 trace("IEProxy.Proxy=%s\n", wine_dbgstr_w(cfg.lpszProxy));
3879 trace("IEProxy.ProxyBypass=%s\n", wine_dbgstr_w(cfg.lpszProxyBypass));
3880 GlobalFree( cfg.lpszAutoConfigUrl );
3881 GlobalFree( cfg.lpszProxy );
3882 GlobalFree( cfg.lpszProxyBypass );
3883 }
3884
3885 static void test_WinHttpGetProxyForUrl(void)
3886 {
3887 static const WCHAR urlW[] = {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0};
3888 static const WCHAR wpadW[] = {'h','t','t','p',':','/','/','w','p','a','d','/','w','p','a','d','.','d','a','t',0};
3889 static const WCHAR emptyW[] = {0};
3890 BOOL ret;
3891 DWORD error;
3892 HINTERNET session;
3893 WINHTTP_AUTOPROXY_OPTIONS options;
3894 WINHTTP_PROXY_INFO info;
3895
3896 memset( &options, 0, sizeof(options) );
3897
3898 SetLastError(0xdeadbeef);
3899 ret = WinHttpGetProxyForUrl( NULL, NULL, NULL, NULL );
3900 error = GetLastError();
3901 ok( !ret, "expected failure\n" );
3902 ok( error == ERROR_INVALID_HANDLE, "got %u\n", error );
3903
3904 session = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
3905 ok( session != NULL, "failed to open session %u\n", GetLastError() );
3906
3907 SetLastError(0xdeadbeef);
3908 ret = WinHttpGetProxyForUrl( session, NULL, NULL, NULL );
3909 error = GetLastError();
3910 ok( !ret, "expected failure\n" );
3911 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3912
3913 SetLastError(0xdeadbeef);
3914 ret = WinHttpGetProxyForUrl( session, emptyW, NULL, NULL );
3915 error = GetLastError();
3916 ok( !ret, "expected failure\n" );
3917 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3918
3919 SetLastError(0xdeadbeef);
3920 ret = WinHttpGetProxyForUrl( session, urlW, NULL, NULL );
3921 error = GetLastError();
3922 ok( !ret, "expected failure\n" );
3923 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3924
3925 SetLastError(0xdeadbeef);
3926 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
3927 error = GetLastError();
3928 ok( !ret, "expected failure\n" );
3929 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3930
3931 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
3932 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
3933
3934 SetLastError(0xdeadbeef);
3935 ret = WinHttpGetProxyForUrl( session, urlW, &options, NULL );
3936 error = GetLastError();
3937 ok( !ret, "expected failure\n" );
3938 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3939
3940 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
3941 options.dwAutoDetectFlags = 0;
3942
3943 SetLastError(0xdeadbeef);
3944 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
3945 error = GetLastError();
3946 ok( !ret, "expected failure\n" );
3947 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3948
3949 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT | WINHTTP_AUTOPROXY_CONFIG_URL;
3950 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
3951
3952 SetLastError(0xdeadbeef);
3953 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
3954 error = GetLastError();
3955 ok( !ret, "expected failure\n" );
3956 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3957
3958 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
3959 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
3960
3961 memset( &info, 0, sizeof(info) );
3962 SetLastError(0xdeadbeef);
3963 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
3964 error = GetLastError();
3965 if (ret)
3966 {
3967 ok( error == ERROR_SUCCESS, "got %u\n", error );
3968 trace("Proxy.AccessType=%u\n", info.dwAccessType);
3969 trace("Proxy.Proxy=%s\n", wine_dbgstr_w(info.lpszProxy));
3970 trace("Proxy.ProxyBypass=%s\n", wine_dbgstr_w(info.lpszProxyBypass));
3971 GlobalFree( info.lpszProxy );
3972 GlobalFree( info.lpszProxyBypass );
3973 }
3974
3975 options.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
3976 options.dwAutoDetectFlags = 0;
3977 options.lpszAutoConfigUrl = wpadW;
3978
3979 memset( &info, 0, sizeof(info) );
3980 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
3981 if (ret)
3982 {
3983 trace("Proxy.AccessType=%u\n", info.dwAccessType);
3984 trace("Proxy.Proxy=%s\n", wine_dbgstr_w(info.lpszProxy));
3985 trace("Proxy.ProxyBypass=%s\n", wine_dbgstr_w(info.lpszProxyBypass));
3986 GlobalFree( info.lpszProxy );
3987 GlobalFree( info.lpszProxyBypass );
3988 }
3989 WinHttpCloseHandle( session );
3990 }
3991
3992 static void test_chunked_read(void)
3993 {
3994 static const WCHAR verb[] = {'/','t','e','s','t','c','h','u','n','k','e','d',0};
3995 static const WCHAR chunked[] = {'c','h','u','n','k','e','d',0};
3996 WCHAR header[32];
3997 DWORD len, err;
3998 HINTERNET ses, con = NULL, req = NULL;
3999 BOOL ret;
4000
4001 trace( "starting chunked read test\n" );
4002
4003 ses = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
4004 ok( ses != NULL, "WinHttpOpen failed with error %u\n", GetLastError() );
4005 if (!ses) goto done;
4006
4007 con = WinHttpConnect( ses, test_winehq, 0, 0 );
4008 ok( con != NULL, "WinHttpConnect failed with error %u\n", GetLastError() );
4009 if (!con) goto done;
4010
4011 req = WinHttpOpenRequest( con, NULL, verb, NULL, NULL, NULL, 0 );
4012 ok( req != NULL, "WinHttpOpenRequest failed with error %u\n", GetLastError() );
4013 if (!req) goto done;
4014
4015 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
4016 err = GetLastError();
4017 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
4018 {
4019 skip("connection failed, skipping\n");
4020 goto done;
4021 }
4022 ok( ret, "WinHttpSendRequest failed with error %u\n", GetLastError() );
4023
4024 ret = WinHttpReceiveResponse( req, NULL );
4025 ok( ret, "WinHttpReceiveResponse failed with error %u\n", GetLastError() );
4026
4027 header[0] = 0;
4028 len = sizeof(header);
4029 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, header, &len, 0 );
4030 ok( ret, "failed to get TRANSFER_ENCODING header (error %u)\n", GetLastError() );
4031 ok( !lstrcmpW( header, chunked ), "wrong transfer encoding %s\n", wine_dbgstr_w(header) );
4032 trace( "transfer encoding: %s\n", wine_dbgstr_w(header) );
4033
4034 header[0] = 0;
4035 len = sizeof(header);
4036 SetLastError( 0xdeadbeef );
4037 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_CONTENT_LENGTH, NULL, &header, &len, 0 );
4038 ok( !ret, "unexpected CONTENT_LENGTH header %s\n", wine_dbgstr_w(header) );
4039 ok( GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND, "wrong error %u\n", GetLastError() );
4040
4041 trace( "entering query loop\n" );
4042 for (;;)
4043 {
4044 len = 0xdeadbeef;
4045 ret = WinHttpQueryDataAvailable( req, &len );
4046 ok( ret, "WinHttpQueryDataAvailable failed with error %u\n", GetLastError() );
4047 if (ret) ok( len != 0xdeadbeef, "WinHttpQueryDataAvailable return wrong length\n" );
4048 trace( "got %u available\n", len );
4049 if (len)
4050 {
4051 DWORD bytes_read;
4052 char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 );
4053
4054 ret = WinHttpReadData( req, buf, len, &bytes_read );
4055
4056 buf[bytes_read] = 0;
4057 trace( "WinHttpReadData -> %d %u\n", ret, bytes_read );
4058 ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len );
4059 ok( buf[bytes_read - 1] == '\n', "received partial line '%s'\n", buf );
4060
4061 HeapFree( GetProcessHeap(), 0, buf );
4062 if (!bytes_read) break;
4063 }
4064 if (!len) break;
4065 }
4066 trace( "done\n" );
4067
4068 done:
4069 if (req) WinHttpCloseHandle( req );
4070 if (con) WinHttpCloseHandle( con );
4071 if (ses) WinHttpCloseHandle( ses );
4072 }
4073
4074 START_TEST (winhttp)
4075 {
4076 static const WCHAR basicW[] = {'/','b','a','s','i','c',0};
4077 static const WCHAR quitW[] = {'/','q','u','i','t',0};
4078 struct server_info si;
4079 HANDLE thread;
4080 DWORD ret;
4081
4082 test_OpenRequest();
4083 test_SendRequest();
4084 test_WinHttpTimeFromSystemTime();
4085 test_WinHttpTimeToSystemTime();
4086 test_WinHttpAddHeaders();
4087 test_secure_connection();
4088 test_request_parameter_defaults();
4089 test_QueryOption();
4090 test_set_default_proxy_config();
4091 test_empty_headers_param();
4092 test_Timeouts();
4093 test_resolve_timeout();
4094 test_credentials();
4095 test_IWinHttpRequest();
4096 test_IWinHttpRequest_Invoke();
4097 test_WinHttpDetectAutoProxyConfigUrl();
4098 test_WinHttpGetIEProxyConfigForCurrentUser();
4099 test_WinHttpGetProxyForUrl();
4100 test_chunked_read();
4101
4102 si.event = CreateEventW(NULL, 0, 0, NULL);
4103 si.port = 7532;
4104
4105 thread = CreateThread(NULL, 0, server_thread, (LPVOID)&si, 0, NULL);
4106 ok(thread != NULL, "failed to create thread %u\n", GetLastError());
4107
4108 ret = WaitForSingleObject(si.event, 10000);
4109 ok(ret == WAIT_OBJECT_0, "failed to start winhttp test server %u\n", GetLastError());
4110 if (ret != WAIT_OBJECT_0)
4111 return;
4112
4113 test_connection_info(si.port);
4114 test_basic_request(si.port, NULL, basicW);
4115 test_no_headers(si.port);
4116 test_no_content(si.port);
4117 test_head_request(si.port);
4118 test_not_modified(si.port);
4119 test_basic_authentication(si.port);
4120 test_bad_header(si.port);
4121 test_multiple_reads(si.port);
4122 test_cookies(si.port);
4123
4124 /* send the basic request again to shutdown the server thread */
4125 test_basic_request(si.port, NULL, quitW);
4126
4127 WaitForSingleObject(thread, 3000);
4128 }