d9024dfb7d86d0a2e6869360de69fdc561779ff1
[reactos.git] / modules / 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 <stdio.h>
38 //#include "initguid.h"
39 #include <httprequest.h>
40 #include <httprequestid.h>
41
42 #include <wine/test.h>
43
44 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
45
46 static const WCHAR test_useragent[] =
47 {'W','i','n','e',' ','R','e','g','r','e','s','s','i','o','n',' ','T','e','s','t',0};
48 static const WCHAR test_winehq[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
49 static const WCHAR test_winehq_https[] = {'h','t','t','p','s',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',':','4','4','3',0};
50 static const WCHAR localhostW[] = {'l','o','c','a','l','h','o','s','t',0};
51
52 static BOOL proxy_active(void)
53 {
54 WINHTTP_PROXY_INFO proxy_info;
55 BOOL active = FALSE;
56
57 SetLastError(0xdeadbeef);
58 if (WinHttpGetDefaultProxyConfiguration(&proxy_info))
59 {
60 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
61 "got %u\n", GetLastError());
62 active = (proxy_info.lpszProxy != NULL);
63 if (active)
64 GlobalFree(proxy_info.lpszProxy);
65 if (proxy_info.lpszProxyBypass != NULL)
66 GlobalFree(proxy_info.lpszProxyBypass);
67 }
68 else
69 active = FALSE;
70
71 return active;
72 }
73
74 static void test_QueryOption(void)
75 {
76 BOOL ret;
77 HINTERNET session, request, connection;
78 DWORD feature, size;
79
80 SetLastError(0xdeadbeef);
81 session = WinHttpOpen(test_useragent, 0, 0, 0, 0);
82 ok(session != NULL, "WinHttpOpen failed to open session, error %u\n", GetLastError());
83
84 SetLastError(0xdeadbeef);
85 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, NULL);
86 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
87 ok(GetLastError() == ERROR_INVALID_PARAMETER,
88 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
89
90 size = 0xdeadbeef;
91 SetLastError(0xdeadbeef);
92 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, &size);
93 ok(!ret, "should fail to query option\n");
94 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
95 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
96 ok(size == 4, "expected 4, got %u\n", size);
97
98 feature = 0xdeadbeef;
99 size = sizeof(feature) - 1;
100 SetLastError(0xdeadbeef);
101 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
102 ok(!ret, "should fail to query option\n");
103 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
104 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
105 ok(size == 4, "expected 4, got %u\n", size);
106
107 feature = 0xdeadbeef;
108 size = sizeof(feature) + 1;
109 SetLastError(0xdeadbeef);
110 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
111 ok(ret, "failed to query option %u\n", GetLastError());
112 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
113 "got %u\n", GetLastError());
114 ok(size == sizeof(feature), "WinHttpQueryOption should set the size: %u\n", size);
115 ok(feature == WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP,
116 "expected WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP, got %#x\n", feature);
117
118 SetLastError(0xdeadbeef);
119 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, sizeof(feature));
120 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
121 ok(GetLastError() == ERROR_INVALID_PARAMETER,
122 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
123
124 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
125 SetLastError(0xdeadbeef);
126 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature) - 1);
127 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
128 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
129 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
130
131 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
132 SetLastError(0xdeadbeef);
133 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature) + 1);
134 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
135 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
136 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
137
138 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
139 SetLastError(0xdeadbeef);
140 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature));
141 ok(ret, "failed to set redirect policy %u\n", GetLastError());
142
143 feature = 0xdeadbeef;
144 size = sizeof(feature);
145 SetLastError(0xdeadbeef);
146 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
147 ok(ret, "failed to query option %u\n", GetLastError());
148 ok(feature == WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS,
149 "expected WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS, got %#x\n", feature);
150
151 feature = WINHTTP_DISABLE_COOKIES;
152 SetLastError(0xdeadbeef);
153 ret = WinHttpSetOption(session, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
154 ok(!ret, "should fail to set disable feature for a session\n");
155 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
156 "expected ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, got %u\n", GetLastError());
157
158 SetLastError(0xdeadbeef);
159 connection = WinHttpConnect(session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
160 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u\n", GetLastError());
161
162 feature = WINHTTP_DISABLE_COOKIES;
163 SetLastError(0xdeadbeef);
164 ret = WinHttpSetOption(connection, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
165 ok(!ret, "should fail to set disable feature for a connection\n");
166 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
167 "expected ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, got %u\n", GetLastError());
168
169 SetLastError(0xdeadbeef);
170 request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
171 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
172 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
173 {
174 skip("Network unreachable, skipping the test\n");
175 goto done;
176 }
177
178 feature = 0xdeadbeef;
179 size = sizeof(feature);
180 SetLastError(0xdeadbeef);
181 ret = WinHttpQueryOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, &size);
182 ok(!ret, "should fail to query disable feature for a request\n");
183 ok(GetLastError() == ERROR_INVALID_PARAMETER,
184 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
185
186 feature = 0;
187 size = sizeof(feature);
188 SetLastError(0xdeadbeef);
189 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
190 ok(ret, "failed to set feature %u\n", GetLastError());
191
192 feature = 0xffffffff;
193 size = sizeof(feature);
194 SetLastError(0xdeadbeef);
195 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
196 ok(ret, "failed to set feature %u\n", GetLastError());
197
198 feature = WINHTTP_DISABLE_COOKIES;
199 size = sizeof(feature);
200 SetLastError(0xdeadbeef);
201 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
202 ok(ret, "failed to set feature %u\n", GetLastError());
203
204 size = 0;
205 SetLastError(0xdeadbeef);
206 ret = WinHttpQueryOption(request, WINHTTP_OPTION_DISABLE_FEATURE, NULL, &size);
207 ok(!ret, "should fail to query disable feature for a request\n");
208 ok(GetLastError() == ERROR_INVALID_PARAMETER,
209 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
210
211 SetLastError(0xdeadbeef);
212 ret = WinHttpCloseHandle(request);
213 ok(ret, "WinHttpCloseHandle failed on closing request: %u\n", GetLastError());
214
215 done:
216 SetLastError(0xdeadbeef);
217 ret = WinHttpCloseHandle(connection);
218 ok(ret, "WinHttpCloseHandle failed on closing connection: %u\n", GetLastError());
219 SetLastError(0xdeadbeef);
220 ret = WinHttpCloseHandle(session);
221 ok(ret, "WinHttpCloseHandle failed on closing session: %u\n", GetLastError());
222 }
223
224 static void test_OpenRequest (void)
225 {
226 BOOL ret;
227 HINTERNET session, request, connection;
228 DWORD err;
229
230 SetLastError(0xdeadbeef);
231 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
232 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
233 err = GetLastError();
234 ok(session != NULL, "WinHttpOpen failed to open session.\n");
235 ok(err == ERROR_SUCCESS, "got %u\n", err);
236
237 /* Test with a bad server name */
238 SetLastError(0xdeadbeef);
239 connection = WinHttpConnect(session, NULL, INTERNET_DEFAULT_HTTP_PORT, 0);
240 err = GetLastError();
241 ok (connection == NULL, "WinHttpConnect succeeded in opening connection to NULL server argument.\n");
242 ok(err == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u.\n", err);
243
244 /* Test with a valid server name */
245 SetLastError(0xdeadbeef);
246 connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
247 err = GetLastError();
248 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", err);
249 ok(err == ERROR_SUCCESS || broken(err == WSAEINVAL) /* < win7 */, "got %u\n", err);
250
251 SetLastError(0xdeadbeef);
252 request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
253 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
254 err = GetLastError();
255 if (request == NULL && err == ERROR_WINHTTP_NAME_NOT_RESOLVED)
256 {
257 skip("Network unreachable, skipping.\n");
258 goto done;
259 }
260 ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", err);
261 ok(err == ERROR_SUCCESS, "got %u\n", err);
262
263 SetLastError(0xdeadbeef);
264 ret = WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, NULL, 0, 0, 0);
265 err = GetLastError();
266 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
267 {
268 skip("Connection failed, skipping.\n");
269 goto done;
270 }
271 ok(ret, "WinHttpSendRequest failed: %u\n", err);
272 ok(err == ERROR_SUCCESS, "got %u\n", err);
273
274 SetLastError(0xdeadbeef);
275 ret = WinHttpCloseHandle(request);
276 err = GetLastError();
277 ok(ret, "WinHttpCloseHandle failed on closing request, got %u.\n", err);
278 ok(err == ERROR_SUCCESS, "got %u\n", err);
279
280 done:
281 ret = WinHttpCloseHandle(connection);
282 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
283 ret = WinHttpCloseHandle(session);
284 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
285
286 }
287
288 static void test_empty_headers_param(void)
289 {
290 static const WCHAR empty[] = {0};
291 HINTERNET ses, con, req;
292 DWORD err;
293 BOOL ret;
294
295 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
296 ok(ses != NULL, "failed to open session %u\n", GetLastError());
297
298 con = WinHttpConnect(ses, test_winehq, 80, 0);
299 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
300
301 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
302 ok(req != NULL, "failed to open a request %u\n", GetLastError());
303
304 ret = WinHttpSendRequest(req, empty, 0, NULL, 0, 0, 0);
305 err = GetLastError();
306 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
307 {
308 skip("connection failed, skipping\n");
309 goto done;
310 }
311 ok(ret, "failed to send request %u\n", GetLastError());
312
313 done:
314 WinHttpCloseHandle(req);
315 WinHttpCloseHandle(con);
316 WinHttpCloseHandle(ses);
317 }
318
319 static void test_SendRequest (void)
320 {
321 static const WCHAR content_type[] =
322 {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t','i','o','n',
323 '/','x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o','d','e','d',0};
324 static const WCHAR test_file[] = {'t','e','s','t','s','/','p','o','s','t','.','p','h','p',0};
325 static const WCHAR test_verb[] = {'P','O','S','T',0};
326 static CHAR post_data[] = "mode=Test";
327 static const char test_post[] = "mode => Test\0\n";
328 HINTERNET session, request, connection;
329 DWORD header_len, optional_len, total_len, bytes_rw, size, err, disable;
330 DWORD_PTR context;
331 BOOL ret;
332 CHAR buffer[256];
333 int i;
334
335 header_len = -1L;
336 total_len = optional_len = sizeof(post_data);
337 memset(buffer, 0xff, sizeof(buffer));
338
339 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
340 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
341 ok(session != NULL, "WinHttpOpen failed to open session.\n");
342
343 connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
344 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
345
346 request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
347 WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
348 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
349 {
350 skip("Network unreachable, skipping.\n");
351 goto done;
352 }
353 ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError());
354 if (!request) goto done;
355
356 context = 0xdeadbeef;
357 ret = WinHttpSetOption(request, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(context));
358 ok(ret, "WinHttpSetOption failed: %u\n", GetLastError());
359
360 /* writing more data than promised by the content-length header causes an error when the connection
361 is resued, so disable keep-alive */
362 disable = WINHTTP_DISABLE_KEEP_ALIVE;
363 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &disable, sizeof(disable));
364 ok(ret, "WinHttpSetOption failed: %u\n", GetLastError());
365
366 context++;
367 ret = WinHttpSendRequest(request, content_type, header_len, post_data, optional_len, total_len, context);
368 err = GetLastError();
369 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
370 {
371 skip("connection failed, skipping\n");
372 goto done;
373 }
374 ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError());
375
376 context = 0;
377 size = sizeof(context);
378 ret = WinHttpQueryOption(request, WINHTTP_OPTION_CONTEXT_VALUE, &context, &size);
379 ok(ret, "WinHttpQueryOption failed: %u\n", GetLastError());
380 ok(context == 0xdeadbef0, "expected 0xdeadbef0, got %lx\n", context);
381
382 for (i = 3; post_data[i]; i++)
383 {
384 bytes_rw = -1;
385 SetLastError(0xdeadbeef);
386 ret = WinHttpWriteData(request, &post_data[i], 1, &bytes_rw);
387 if (ret)
388 {
389 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %u.\n", GetLastError());
390 ok(bytes_rw == 1, "WinHttpWriteData failed, wrote %u bytes instead of 1 byte.\n", bytes_rw);
391 }
392 else /* Since we already passed all optional data in WinHttpSendRequest Win7 fails our WinHttpWriteData call */
393 {
394 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER got %u.\n", GetLastError());
395 ok(bytes_rw == -1, "Expected bytes_rw to remain unchanged.\n");
396 }
397 }
398
399 SetLastError(0xdeadbeef);
400 ret = WinHttpReceiveResponse(request, NULL);
401 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == ERROR_NO_TOKEN) /* < win7 */,
402 "Expected ERROR_SUCCESS got %u.\n", GetLastError());
403 ok(ret == TRUE, "WinHttpReceiveResponse failed: %u.\n", GetLastError());
404
405 bytes_rw = -1;
406 ret = WinHttpReadData(request, buffer, sizeof(buffer) - 1, &bytes_rw);
407 ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
408
409 ok(bytes_rw == sizeof(test_post) - 1, "Read %u bytes\n", bytes_rw);
410 ok(!memcmp(buffer, test_post, sizeof(test_post) - 1), "Data read did not match.\n");
411
412 done:
413 ret = WinHttpCloseHandle(request);
414 ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
415 ret = WinHttpCloseHandle(connection);
416 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
417 ret = WinHttpCloseHandle(session);
418 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
419 }
420
421 static void test_WinHttpTimeFromSystemTime(void)
422 {
423 BOOL ret;
424 static const SYSTEMTIME time = {2008, 7, 1, 28, 10, 5, 52, 0};
425 static const WCHAR expected_string[] =
426 {'M','o','n',',',' ','2','8',' ','J','u','l',' ','2','0','0','8',' ',
427 '1','0',':','0','5',':','5','2',' ','G','M','T',0};
428 WCHAR time_string[WINHTTP_TIME_FORMAT_BUFSIZE+1];
429 DWORD err;
430
431 SetLastError(0xdeadbeef);
432 ret = WinHttpTimeFromSystemTime(&time, NULL);
433 err = GetLastError();
434 ok(!ret, "WinHttpTimeFromSystemTime succeeded\n");
435 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
436
437 SetLastError(0xdeadbeef);
438 ret = WinHttpTimeFromSystemTime(NULL, time_string);
439 err = GetLastError();
440 ok(!ret, "WinHttpTimeFromSystemTime succeeded\n");
441 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
442
443 SetLastError(0xdeadbeef);
444 ret = WinHttpTimeFromSystemTime(&time, time_string);
445 err = GetLastError();
446 ok(ret, "WinHttpTimeFromSystemTime failed: %u\n", err);
447 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
448 ok(memcmp(time_string, expected_string, sizeof(expected_string)) == 0,
449 "Time string returned did not match expected time string.\n");
450 }
451
452 static void test_WinHttpTimeToSystemTime(void)
453 {
454 BOOL ret;
455 SYSTEMTIME time;
456 static const SYSTEMTIME expected_time = {2008, 7, 1, 28, 10, 5, 52, 0};
457 static const WCHAR time_string1[] =
458 {'M','o','n',',',' ','2','8',' ','J','u','l',' ','2','0','0','8',' ',
459 + '1','0',':','0','5',':','5','2',' ','G','M','T','\n',0};
460 static const WCHAR time_string2[] =
461 {' ','m','o','n',' ','2','8',' ','j','u','l',' ','2','0','0','8',' ',
462 '1','0',' ','0','5',' ','5','2','\n',0};
463 DWORD err;
464
465 SetLastError(0xdeadbeef);
466 ret = WinHttpTimeToSystemTime(time_string1, NULL);
467 err = GetLastError();
468 ok(!ret, "WinHttpTimeToSystemTime succeeded\n");
469 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
470
471 SetLastError(0xdeadbeef);
472 ret = WinHttpTimeToSystemTime(NULL, &time);
473 err = GetLastError();
474 ok(!ret, "WinHttpTimeToSystemTime succeeded\n");
475 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
476
477 SetLastError(0xdeadbeef);
478 ret = WinHttpTimeToSystemTime(time_string1, &time);
479 err = GetLastError();
480 ok(ret, "WinHttpTimeToSystemTime failed: %u\n", err);
481 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
482 ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
483 "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
484
485 SetLastError(0xdeadbeef);
486 ret = WinHttpTimeToSystemTime(time_string2, &time);
487 err = GetLastError();
488 ok(ret, "WinHttpTimeToSystemTime failed: %u\n", err);
489 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
490 ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
491 "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
492 }
493
494 static void test_WinHttpAddHeaders(void)
495 {
496 HINTERNET session, request, connection;
497 BOOL ret, reverse;
498 WCHAR buffer[MAX_PATH];
499 WCHAR check_buffer[MAX_PATH];
500 DWORD err, index, len, oldlen;
501
502 static const WCHAR test_file[] = {'/','p','o','s','t','t','e','s','t','.','p','h','p',0};
503 static const WCHAR test_verb[] = {'P','O','S','T',0};
504 static const WCHAR test_header_begin[] =
505 {'P','O','S','T',' ','/','p','o','s','t','t','e','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
506 static const WCHAR full_path_test_header_begin[] =
507 {'P','O','S','T',' ','h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',':','8','0',
508 '/','p','o','s','t','t','e','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
509 static const WCHAR test_header_end[] = {'\r','\n','\r','\n',0};
510 static const WCHAR test_header_name[] = {'W','a','r','n','i','n','g',0};
511 static const WCHAR test_header_name2[] = {'n','a','m','e',0};
512 static const WCHAR test_header_name3[] = {'a',0};
513 static const WCHAR test_header_range[] = {'R','a','n','g','e',0};
514 static const WCHAR test_header_range_bytes[] = {'R','a','n','g','e',':',' ','b','y','t','e','s','=','0','-','7','7','3','\r','\n',0};
515 static const WCHAR test_header_bytes[] = {'b','y','t','e','s','=','0','-','7','7','3',0};
516
517 static const WCHAR test_flag_coalesce[] = {'t','e','s','t','2',',',' ','t','e','s','t','4',0};
518 static const WCHAR test_flag_coalesce_reverse[] = {'t','e','s','t','3',',',' ','t','e','s','t','4',0};
519 static const WCHAR test_flag_coalesce_comma[] =
520 {'t','e','s','t','2',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',0};
521 static const WCHAR test_flag_coalesce_comma_reverse[] =
522 {'t','e','s','t','3',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',0};
523 static const WCHAR test_flag_coalesce_semicolon[] =
524 {'t','e','s','t','2',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',';',' ','t','e','s','t','6',0};
525 static const WCHAR test_flag_coalesce_semicolon_reverse[] =
526 {'t','e','s','t','3',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',';',' ','t','e','s','t','6',0};
527
528 static const WCHAR field[] = {'f','i','e','l','d',0};
529 static const WCHAR value[] = {'v','a','l','u','e',' ',0};
530 static const WCHAR value_nospace[] = {'v','a','l','u','e',0};
531 static const WCHAR empty[] = {0};
532
533 static const WCHAR test_headers[][14] =
534 {
535 {'W','a','r','n','i','n','g',':','t','e','s','t','1',0},
536 {'W','a','r','n','i','n','g',':','t','e','s','t','2',0},
537 {'W','a','r','n','i','n','g',':','t','e','s','t','3',0},
538 {'W','a','r','n','i','n','g',':','t','e','s','t','4',0},
539 {'W','a','r','n','i','n','g',':','t','e','s','t','5',0},
540 {'W','a','r','n','i','n','g',':','t','e','s','t','6',0},
541 {'W','a','r','n','i','n','g',':','t','e','s','t','7',0},
542 {0},
543 {':',0},
544 {'a',':',0},
545 {':','b',0},
546 {'c','d',0},
547 {' ','e',' ',':','f',0},
548 {'f','i','e','l','d',':',' ','v','a','l','u','e',' ',0},
549 {'n','a','m','e',':',' ','v','a','l','u','e',0},
550 {'n','a','m','e',':',0}
551 };
552 static const WCHAR test_indices[][6] =
553 {
554 {'t','e','s','t','1',0},
555 {'t','e','s','t','2',0},
556 {'t','e','s','t','3',0},
557 {'t','e','s','t','4',0}
558 };
559
560 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
561 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
562 ok(session != NULL, "WinHttpOpen failed to open session.\n");
563
564 connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
565 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
566
567 request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
568 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
569 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
570 {
571 skip("Network unreachable, skipping.\n");
572 goto done;
573 }
574 ok(request != NULL, "WinHttpOpenRequest failed to open a request, error: %u.\n", GetLastError());
575
576 index = 0;
577 len = sizeof(buffer);
578 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
579 test_header_name, buffer, &len, &index);
580 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, found 'Warning' header.\n");
581 SetLastError(0xdeadbeef);
582 ret = WinHttpAddRequestHeaders(request, test_headers[0], -1L, WINHTTP_ADDREQ_FLAG_ADD);
583 err = GetLastError();
584 ok(ret, "WinHttpAddRequestHeaders failed to add new header, got %d with error %u.\n", ret, err);
585 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
586
587 index = 0;
588 len = sizeof(buffer);
589 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
590 test_header_name, buffer, &len, &index);
591 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
592 ok(index == 1, "WinHttpQueryHeaders failed: header index not incremented\n");
593 ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders failed: incorrect string returned\n");
594 ok(len == 5*sizeof(WCHAR), "WinHttpQueryHeaders failed: invalid length returned, expected 5, got %d\n", len);
595
596 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
597 test_header_name, buffer, &len, &index);
598 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, second index should not exist.\n");
599
600 /* Try to fetch the header info with a buffer that's big enough to fit the
601 * string but not the NULL terminator.
602 */
603 index = 0;
604 len = 5*sizeof(WCHAR);
605 memset(check_buffer, 0xab, sizeof(check_buffer));
606 memcpy(buffer, check_buffer, sizeof(buffer));
607 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
608 test_header_name, buffer, &len, &index);
609 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded with a buffer that's too small.\n");
610 ok(memcmp(buffer, check_buffer, sizeof(buffer)) == 0,
611 "WinHttpQueryHeaders failed, modified the buffer when it should not have.\n");
612 ok(len == 6*sizeof(WCHAR), "WinHttpQueryHeaders returned invalid length, expected 12, got %d\n", len);
613
614 /* Try with a NULL buffer */
615 index = 0;
616 len = sizeof(buffer);
617 SetLastError(0xdeadbeef);
618 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
619 test_header_name, NULL, &len, &index);
620 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
621 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
622 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
623 ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
624
625 /* Try with a NULL buffer and a length that's too small */
626 index = 0;
627 len = 10;
628 SetLastError(0xdeadbeef);
629 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
630 test_header_name, NULL, &len, &index);
631 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
632 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
633 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICENT_BUFFER, got %u\n", GetLastError());
634 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
635 ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
636
637 index = 0;
638 len = 0;
639 SetLastError(0xdeadbeef);
640 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
641 test_header_name, NULL, &len, &index);
642 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
643 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
644 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
645 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
646 ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
647
648 /* valid query */
649 oldlen = len;
650 index = 0;
651 len = sizeof(buffer);
652 memset(buffer, 0xff, sizeof(buffer));
653 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
654 test_header_name, buffer, &len, &index);
655 ok(ret == TRUE, "WinHttpQueryHeaders failed: got %d\n", ret);
656 ok(len + sizeof(WCHAR) <= oldlen, "WinHttpQueryHeaders resulting length longer than advertized.\n");
657 ok((len < sizeof(buffer) - sizeof(WCHAR)) && buffer[len / sizeof(WCHAR)] == 0, "WinHttpQueryHeaders did not append NULL terminator\n");
658 ok(len == lstrlenW(buffer) * sizeof(WCHAR), "WinHttpQueryHeaders returned incorrect length.\n");
659 ok(memcmp(buffer, test_header_begin, sizeof(test_header_begin)) == 0 ||
660 memcmp(buffer, full_path_test_header_begin, sizeof(full_path_test_header_begin)) == 0,
661 "WinHttpQueryHeaders returned invalid beginning of header string.\n");
662 ok(memcmp(buffer + lstrlenW(buffer) - 4, test_header_end, sizeof(test_header_end)) == 0,
663 "WinHttpQueryHeaders returned invalid end of header string.\n");
664 ok(index == 0, "WinHttpQueryHeaders incremented header index.\n");
665
666 index = 0;
667 len = 0;
668 SetLastError(0xdeadbeef);
669 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
670 test_header_name, NULL, &len, &index);
671 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
672 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
673 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
674 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
675 ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
676
677 oldlen = len;
678 index = 0;
679 len = sizeof(buffer);
680 memset(buffer, 0xff, sizeof(buffer));
681 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
682 test_header_name, buffer, &len, &index);
683 ok(ret == TRUE, "WinHttpQueryHeaders failed %u\n", GetLastError());
684 ok(len + sizeof(WCHAR) <= oldlen, "resulting length longer than advertized\n");
685 ok((len < sizeof(buffer) - sizeof(WCHAR)) && !buffer[len / sizeof(WCHAR)] && !buffer[len / sizeof(WCHAR) - 1],
686 "no double NULL terminator\n");
687 ok(memcmp(buffer, test_header_begin, sizeof(test_header_begin)) == 0 ||
688 memcmp(buffer, full_path_test_header_begin, sizeof(full_path_test_header_begin)) == 0,
689 "invalid beginning of header string.\n");
690 ok(index == 0, "header index was incremented\n");
691
692 /* tests for more indices */
693 ret = WinHttpAddRequestHeaders(request, test_headers[1], -1L, WINHTTP_ADDREQ_FLAG_ADD);
694 ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header: %d\n", ret);
695
696 index = 0;
697 len = sizeof(buffer);
698 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
699 test_header_name, buffer, &len, &index);
700 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
701 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
702 ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
703
704 len = sizeof(buffer);
705 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
706 test_header_name, buffer, &len, &index);
707 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
708 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
709 ok(memcmp(buffer, test_indices[1], sizeof(test_indices[1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
710
711 ret = WinHttpAddRequestHeaders(request, test_headers[2], -1L, WINHTTP_ADDREQ_FLAG_REPLACE);
712 ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header.\n");
713
714 index = 0;
715 len = sizeof(buffer);
716 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
717 test_header_name, buffer, &len, &index);
718 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
719 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
720 reverse = (memcmp(buffer, test_indices[1], sizeof(test_indices[1])) != 0); /* Win7 returns values in reverse order of adding */
721 ok(memcmp(buffer, test_indices[reverse ? 2 : 1], sizeof(test_indices[reverse ? 2 : 1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
722
723 len = sizeof(buffer);
724 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
725 test_header_name, buffer, &len, &index);
726 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
727 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
728 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
729
730 /* add if new flag */
731 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW);
732 ok(ret == FALSE, "WinHttpAddRequestHeaders incorrectly replaced existing header.\n");
733
734 index = 0;
735 len = sizeof(buffer);
736 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
737 test_header_name, buffer, &len, &index);
738 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
739 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
740 ok(memcmp(buffer, test_indices[reverse ? 2 : 1], sizeof(test_indices[reverse ? 2 : 1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
741
742 len = sizeof(buffer);
743 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
744 test_header_name, buffer, &len, &index);
745 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
746 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
747 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
748
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 == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
753
754 /* coalesce flag */
755 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_COALESCE);
756 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE.\n");
757
758 index = 0;
759 len = sizeof(buffer);
760 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
761 test_header_name, buffer, &len, &index);
762 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
763 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
764 ok(memcmp(buffer, reverse ? test_flag_coalesce_reverse : test_flag_coalesce,
765 reverse ? sizeof(test_flag_coalesce_reverse) : sizeof(test_flag_coalesce)) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
766
767 len = sizeof(buffer);
768 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
769 test_header_name, buffer, &len, &index);
770 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
771 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
772 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
773
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 == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
778
779 /* coalesce with comma flag */
780 ret = WinHttpAddRequestHeaders(request, test_headers[4], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA);
781 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA.\n");
782
783 index = 0;
784 len = sizeof(buffer);
785 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
786 test_header_name, buffer, &len, &index);
787 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
788 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
789 ok(memcmp(buffer, reverse ? test_flag_coalesce_comma_reverse : test_flag_coalesce_comma,
790 reverse ? sizeof(test_flag_coalesce_comma_reverse) : sizeof(test_flag_coalesce_comma)) == 0,
791 "WinHttpQueryHeaders returned incorrect string.\n");
792
793 len = sizeof(buffer);
794 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
795 test_header_name, buffer, &len, &index);
796 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
797 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
798 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
799
800 len = sizeof(buffer);
801 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
802 test_header_name, buffer, &len, &index);
803 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
804
805
806 /* coalesce with semicolon flag */
807 ret = WinHttpAddRequestHeaders(request, test_headers[5], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON);
808 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON.\n");
809
810 index = 0;
811 len = sizeof(buffer);
812 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
813 test_header_name, buffer, &len, &index);
814 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
815 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
816 ok(memcmp(buffer, reverse ? test_flag_coalesce_semicolon_reverse : test_flag_coalesce_semicolon,
817 reverse ? sizeof(test_flag_coalesce_semicolon_reverse) : sizeof(test_flag_coalesce_semicolon)) == 0,
818 "WinHttpQueryHeaders returned incorrect string.\n");
819
820 len = sizeof(buffer);
821 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
822 test_header_name, buffer, &len, &index);
823 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
824 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
825 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
826
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 == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
831
832 /* add and replace flags */
833 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
834 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE.\n");
835
836 index = 0;
837 len = sizeof(buffer);
838 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
839 test_header_name, buffer, &len, &index);
840 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
841 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
842 ok(memcmp(buffer, test_indices[reverse ? 3 : 2], sizeof(test_indices[reverse ? 3 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
843
844 len = sizeof(buffer);
845 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
846 test_header_name, buffer, &len, &index);
847 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
848 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
849 ok(memcmp(buffer, test_indices[reverse ? 1 : 3], sizeof(test_indices[reverse ? 1 : 3])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
850
851 len = sizeof(buffer);
852 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
853 test_header_name, buffer, &len, &index);
854 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
855
856 ret = WinHttpAddRequestHeaders(request, test_headers[8], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
857 ok(!ret, "WinHttpAddRequestHeaders failed\n");
858
859 ret = WinHttpAddRequestHeaders(request, test_headers[9], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
860 ok(ret, "WinHttpAddRequestHeaders failed\n");
861
862 index = 0;
863 memset(buffer, 0xff, sizeof(buffer));
864 len = sizeof(buffer);
865 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
866 test_header_name3, buffer, &len, &index);
867 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
868 ok(!memcmp(buffer, empty, sizeof(empty)), "unexpected result\n");
869
870 ret = WinHttpAddRequestHeaders(request, test_headers[10], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
871 ok(!ret, "WinHttpAddRequestHeaders failed\n");
872
873 ret = WinHttpAddRequestHeaders(request, test_headers[11], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
874 ok(!ret, "WinHttpAddRequestHeaders failed\n");
875
876 ret = WinHttpAddRequestHeaders(request, test_headers[12], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
877 ok(!ret, "WinHttpAddRequestHeaders failed\n");
878
879 ret = WinHttpAddRequestHeaders(request, test_headers[13], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
880 ok(ret, "WinHttpAddRequestHeaders failed\n");
881
882 index = 0;
883 buffer[0] = 0;
884 len = sizeof(buffer);
885 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
886 field, buffer, &len, &index);
887 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
888 ok(!memcmp(buffer, value, sizeof(value)) || ! memcmp(buffer, value_nospace, sizeof(value_nospace)), "unexpected result\n");
889
890 SetLastError(0xdeadbeef);
891 ret = WinHttpAddRequestHeaders(request, test_header_range_bytes, 0,
892 WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
893 err = GetLastError();
894 ok(!ret, "unexpected success\n");
895 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
896
897 ret = WinHttpAddRequestHeaders(request, test_header_range_bytes, ~0u,
898 WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
899 ok(ret, "failed to add header: %u\n", GetLastError());
900
901 index = 0;
902 len = sizeof(buffer);
903 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
904 test_header_range, buffer, &len, &index);
905 ok(ret, "failed to get range header %u\n", GetLastError());
906 ok(!memcmp(buffer, test_header_bytes, sizeof(test_header_bytes)), "incorrect string returned\n");
907 ok(len == lstrlenW(test_header_bytes) * sizeof(WCHAR), "wrong length %u\n", len);
908 ok(index == 1, "wrong index %u\n", index);
909
910 index = 0;
911 len = sizeof(buffer);
912 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
913 test_header_name2, buffer, &len, &index);
914 ok(!ret, "unexpected success\n");
915
916 SetLastError(0xdeadbeef);
917 ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
918 err = GetLastError();
919 ok(!ret, "unexpected success\n");
920 ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
921
922 ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
923 ok(ret, "got %u\n", GetLastError());
924
925 index = 0;
926 len = sizeof(buffer);
927 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
928 test_header_name2, buffer, &len, &index);
929 ok(ret, "got %u\n", GetLastError());
930 ok(index == 1, "wrong index %u\n", index);
931 ok(!memcmp(buffer, value_nospace, sizeof(value_nospace)), "incorrect string\n");
932
933 ret = WinHttpAddRequestHeaders(request, test_headers[15], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
934 ok(ret, "got %u\n", GetLastError());
935
936 index = 0;
937 len = sizeof(buffer);
938 SetLastError(0xdeadbeef);
939 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
940 test_header_name2, buffer, &len, &index);
941 err = GetLastError();
942 ok(!ret, "unexpected success\n");
943 ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
944
945 ret = WinHttpAddRequestHeaders(request, test_headers[14], -1L, 0);
946 ok(ret, "got %u\n", GetLastError());
947
948 index = 0;
949 len = sizeof(buffer);
950 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
951 test_header_name2, buffer, &len, &index);
952 ok(ret, "got %u\n", GetLastError());
953 ok(index == 1, "wrong index %u\n", index);
954 ok(!memcmp(buffer, value_nospace, sizeof(value_nospace)), "incorrect string\n");
955
956 ret = WinHttpCloseHandle(request);
957 ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
958 done:
959 ret = WinHttpCloseHandle(connection);
960 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
961 ret = WinHttpCloseHandle(session);
962 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
963
964 }
965
966 static void CALLBACK cert_error(HINTERNET handle, DWORD_PTR ctx, DWORD status, LPVOID buf, DWORD len)
967 {
968 DWORD flags = *(DWORD *)buf;
969
970 if (!flags)
971 {
972 trace("WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR\n");
973 return;
974 }
975 #define X(x) if (flags & x) trace("%s\n", #x);
976 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED)
977 X(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT)
978 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED)
979 X(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA)
980 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID)
981 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID)
982 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE)
983 #undef X
984 }
985
986 static void test_secure_connection(void)
987 {
988 static const char data_start[] = "<!DOCTYPE html PUBLIC";
989 HINTERNET ses, con, req;
990 DWORD size, status, policy, bitness, read_size, err, available_size, protocols;
991 BOOL ret;
992 CERT_CONTEXT *cert;
993 WINHTTP_CERTIFICATE_INFO info;
994 char buffer[32];
995
996 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
997 ok(ses != NULL, "failed to open session %u\n", GetLastError());
998
999 policy = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
1000 ret = WinHttpSetOption(ses, WINHTTP_OPTION_REDIRECT_POLICY, &policy, sizeof(policy));
1001 ok(ret, "failed to set redirect policy %u\n", GetLastError());
1002
1003 protocols = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;
1004 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SECURE_PROTOCOLS, &protocols, sizeof(protocols));
1005 err = GetLastError();
1006 ok(ret || err == ERROR_INVALID_PARAMETER /* < win7 */, "failed to set protocols %u\n", err);
1007
1008 con = WinHttpConnect(ses, test_winehq, 443, 0);
1009 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1010
1011 /* try without setting WINHTTP_FLAG_SECURE */
1012 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1013 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1014
1015 ret = WinHttpSetOption(req, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0);
1016 err = GetLastError();
1017 ok(!ret, "unexpected success\n");
1018 ok(err == ERROR_WINHTTP_INCORRECT_HANDLE_STATE || broken(err == ERROR_INVALID_PARAMETER) /* winxp */,
1019 "setting client cert context returned %u\n", err);
1020
1021 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1022 err = GetLastError();
1023 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
1024 {
1025 skip("Connection failed, skipping.\n");
1026 goto cleanup;
1027 }
1028 ok(ret, "failed to send request %u\n", GetLastError());
1029
1030 ret = WinHttpReceiveResponse(req, NULL);
1031 ok(ret, "failed to receive response %u\n", GetLastError());
1032
1033 status = 0xdeadbeef;
1034 size = sizeof(status);
1035 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1036 ok(ret, "header query failed %u\n", GetLastError());
1037 ok(status == HTTP_STATUS_BAD_REQUEST, "got %u\n", status);
1038
1039 WinHttpCloseHandle(req);
1040
1041 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, WINHTTP_FLAG_SECURE);
1042 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1043
1044 ret = WinHttpSetOption(req, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0);
1045 err = GetLastError();
1046 ok(ret || broken(!ret && err == ERROR_INVALID_PARAMETER) /* winxp */, "failed to set client cert context %u\n", err);
1047
1048 WinHttpSetStatusCallback(req, cert_error, WINHTTP_CALLBACK_STATUS_SECURE_FAILURE, 0);
1049
1050 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1051 err = GetLastError();
1052 if (!ret && (err == ERROR_WINHTTP_SECURE_FAILURE || err == ERROR_WINHTTP_CANNOT_CONNECT ||
1053 err == ERROR_WINHTTP_TIMEOUT))
1054 {
1055 skip("secure connection failed, skipping remaining secure tests\n");
1056 goto cleanup;
1057 }
1058 ok(ret, "failed to send request %u\n", GetLastError());
1059
1060 size = sizeof(cert);
1061 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert, &size );
1062 ok(ret, "failed to retrieve certificate context %u\n", GetLastError());
1063 if (ret) CertFreeCertificateContext(cert);
1064
1065 size = sizeof(bitness);
1066 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_KEY_BITNESS, &bitness, &size );
1067 ok(ret, "failed to retrieve key bitness %u\n", GetLastError());
1068
1069 size = sizeof(info);
1070 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT, &info, &size );
1071 ok(ret, "failed to retrieve certificate info %u\n", GetLastError());
1072
1073 if (ret)
1074 {
1075 trace("lpszSubjectInfo %s\n", wine_dbgstr_w(info.lpszSubjectInfo));
1076 trace("lpszIssuerInfo %s\n", wine_dbgstr_w(info.lpszIssuerInfo));
1077 trace("lpszProtocolName %s\n", wine_dbgstr_w(info.lpszProtocolName));
1078 trace("lpszSignatureAlgName %s\n", wine_dbgstr_w(info.lpszSignatureAlgName));
1079 trace("lpszEncryptionAlgName %s\n", wine_dbgstr_w(info.lpszEncryptionAlgName));
1080 trace("dwKeySize %u\n", info.dwKeySize);
1081 LocalFree( info.lpszSubjectInfo );
1082 LocalFree( info.lpszIssuerInfo );
1083 }
1084
1085 ret = WinHttpReceiveResponse(req, NULL);
1086 ok(ret, "failed to receive response %u\n", GetLastError());
1087
1088 available_size = 0;
1089 ret = WinHttpQueryDataAvailable(req, &available_size);
1090 ok(ret, "failed to query available data %u\n", GetLastError());
1091 ok(available_size > 2014, "available_size = %u\n", available_size);
1092
1093 status = 0xdeadbeef;
1094 size = sizeof(status);
1095 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1096 ok(ret, "failed unexpectedly %u\n", GetLastError());
1097 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1098
1099 size = 0;
1100 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL);
1101 ok(!ret, "succeeded unexpectedly\n");
1102
1103 read_size = 0;
1104 for (;;)
1105 {
1106 size = 0;
1107 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
1108 ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
1109 if (!size) break;
1110 read_size += size;
1111
1112 if (read_size <= 32)
1113 ok(!memcmp(buffer, data_start, sizeof(data_start)-1), "not expected: %.32s\n", buffer);
1114 }
1115 ok(read_size >= available_size, "read_size = %u, available_size = %u\n", read_size, available_size);
1116
1117 cleanup:
1118 WinHttpCloseHandle(req);
1119 WinHttpCloseHandle(con);
1120 WinHttpCloseHandle(ses);
1121 }
1122
1123 static void test_request_parameter_defaults(void)
1124 {
1125 static const WCHAR empty[] = {0};
1126 HINTERNET ses, con, req;
1127 DWORD size, status, error;
1128 WCHAR *version;
1129 BOOL ret;
1130
1131 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1132 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1133
1134 con = WinHttpConnect(ses, test_winehq, 0, 0);
1135 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1136
1137 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1138 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1139
1140 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1141 error = GetLastError();
1142 if (!ret && (error == ERROR_WINHTTP_CANNOT_CONNECT || error == ERROR_WINHTTP_TIMEOUT))
1143 {
1144 skip("connection failed, skipping\n");
1145 goto done;
1146 }
1147 ok(ret, "failed to send request %u\n", GetLastError());
1148
1149 ret = WinHttpReceiveResponse(req, NULL);
1150 if (!ret && GetLastError() == ERROR_WINHTTP_INVALID_SERVER_RESPONSE) /* win2k */
1151 {
1152 win_skip("invalid response\n");
1153 goto done;
1154 }
1155 ok(ret, "failed to receive response %u\n", GetLastError());
1156
1157 status = 0xdeadbeef;
1158 size = sizeof(status);
1159 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1160 ok(ret, "failed unexpectedly %u\n", GetLastError());
1161 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1162
1163 WinHttpCloseHandle(req);
1164
1165 req = WinHttpOpenRequest(con, empty, empty, empty, NULL, NULL, 0);
1166 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1167
1168 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1169 error = GetLastError();
1170 if (!ret && (error == ERROR_WINHTTP_CANNOT_CONNECT || error == ERROR_WINHTTP_TIMEOUT))
1171 {
1172 skip("connection failed, skipping\n");
1173 goto done;
1174 }
1175 ok(ret, "failed to send request %u\n", GetLastError());
1176
1177 ret = WinHttpReceiveResponse(req, NULL);
1178 ok(ret, "failed to receive response %u\n", GetLastError());
1179
1180 size = 0;
1181 SetLastError(0xdeadbeef);
1182 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, NULL, &size, NULL);
1183 error = GetLastError();
1184 ok(!ret, "succeeded unexpectedly\n");
1185 ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error);
1186
1187 version = HeapAlloc(GetProcessHeap(), 0, size);
1188 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, version, &size, NULL);
1189 ok(ret, "failed unexpectedly %u\n", GetLastError());
1190 ok(lstrlenW(version) == size / sizeof(WCHAR), "unexpected size %u\n", size);
1191 HeapFree(GetProcessHeap(), 0, version);
1192
1193 status = 0xdeadbeef;
1194 size = sizeof(status);
1195 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1196 ok(ret, "failed unexpectedly %u\n", GetLastError());
1197 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1198
1199 done:
1200 WinHttpCloseHandle(req);
1201 WinHttpCloseHandle(con);
1202 WinHttpCloseHandle(ses);
1203 }
1204
1205 static const WCHAR Connections[] = {
1206 'S','o','f','t','w','a','r','e','\\',
1207 'M','i','c','r','o','s','o','f','t','\\',
1208 'W','i','n','d','o','w','s','\\',
1209 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1210 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
1211 'C','o','n','n','e','c','t','i','o','n','s',0 };
1212 static const WCHAR WinHttpSettings[] = {
1213 'W','i','n','H','t','t','p','S','e','t','t','i','n','g','s',0 };
1214
1215 static DWORD get_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD *type )
1216 {
1217 LONG l;
1218 HKEY key;
1219 DWORD ret = 0;
1220
1221 l = RegOpenKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, KEY_READ, &key );
1222 if (!l)
1223 {
1224 DWORD size = 0;
1225
1226 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, NULL, &size );
1227 if (!l)
1228 {
1229 if (size <= len)
1230 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, buf,
1231 &size );
1232 if (!l)
1233 ret = size;
1234 }
1235 RegCloseKey( key );
1236 }
1237 return ret;
1238 }
1239
1240 static void set_proxy( REGSAM access, BYTE *buf, DWORD len, DWORD type )
1241 {
1242 HKEY hkey;
1243 if (!RegCreateKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, NULL, 0, access, NULL, &hkey, NULL ))
1244 {
1245 if (len) RegSetValueExW( hkey, WinHttpSettings, 0, type, buf, len );
1246 else RegDeleteValueW( hkey, WinHttpSettings );
1247 RegCloseKey( hkey );
1248 }
1249 }
1250
1251 static void set_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD type )
1252 {
1253 BOOL wow64;
1254 IsWow64Process( GetCurrentProcess(), &wow64 );
1255 if (sizeof(void *) > sizeof(int) || wow64)
1256 {
1257 set_proxy( KEY_WRITE|KEY_WOW64_64KEY, buf, len, type );
1258 set_proxy( KEY_WRITE|KEY_WOW64_32KEY, buf, len, type );
1259 }
1260 else
1261 set_proxy( KEY_WRITE, buf, len, type );
1262 }
1263
1264 static void test_set_default_proxy_config(void)
1265 {
1266 static WCHAR wideString[] = { 0x226f, 0x575b, 0 };
1267 static WCHAR normalString[] = { 'f','o','o',0 };
1268 DWORD type, len;
1269 BYTE *saved_proxy_settings = NULL;
1270 WINHTTP_PROXY_INFO info;
1271 BOOL ret;
1272
1273 /* FIXME: it would be simpler to read the current settings using
1274 * WinHttpGetDefaultProxyConfiguration and save them using
1275 * WinHttpSetDefaultProxyConfiguration, but they appear to have a bug.
1276 *
1277 * If a proxy is configured in the registry, e.g. via 'proxcfg -p "foo"',
1278 * the access type reported by WinHttpGetDefaultProxyConfiguration is 1,
1279 * WINHTTP_ACCESS_TYPE_NO_PROXY, whereas it should be
1280 * WINHTTP_ACCESS_TYPE_NAMED_PROXY.
1281 * If WinHttpSetDefaultProxyConfiguration is called with dwAccessType = 1,
1282 * the lpszProxy and lpszProxyBypass values are ignored.
1283 * Thus, if a proxy is set with proxycfg, then calling
1284 * WinHttpGetDefaultProxyConfiguration followed by
1285 * WinHttpSetDefaultProxyConfiguration results in the proxy settings
1286 * getting deleted from the registry.
1287 *
1288 * Instead I read the current registry value and restore it directly.
1289 */
1290 len = get_default_proxy_reg_value( NULL, 0, &type );
1291 if (len)
1292 {
1293 saved_proxy_settings = HeapAlloc( GetProcessHeap(), 0, len );
1294 len = get_default_proxy_reg_value( saved_proxy_settings, len, &type );
1295 }
1296
1297 if (0)
1298 {
1299 /* Crashes on Vista and higher */
1300 SetLastError(0xdeadbeef);
1301 ret = WinHttpSetDefaultProxyConfiguration(NULL);
1302 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1303 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1304 }
1305
1306 /* test with invalid access type */
1307 info.dwAccessType = 0xdeadbeef;
1308 info.lpszProxy = info.lpszProxyBypass = NULL;
1309 SetLastError(0xdeadbeef);
1310 ret = WinHttpSetDefaultProxyConfiguration(&info);
1311 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1312 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1313
1314 /* at a minimum, the proxy server must be set */
1315 info.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
1316 info.lpszProxy = info.lpszProxyBypass = NULL;
1317 SetLastError(0xdeadbeef);
1318 ret = WinHttpSetDefaultProxyConfiguration(&info);
1319 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1320 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1321 info.lpszProxyBypass = normalString;
1322 SetLastError(0xdeadbeef);
1323 ret = WinHttpSetDefaultProxyConfiguration(&info);
1324 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1325 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1326
1327 /* the proxy server can't have wide characters */
1328 info.lpszProxy = wideString;
1329 SetLastError(0xdeadbeef);
1330 ret = WinHttpSetDefaultProxyConfiguration(&info);
1331 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1332 skip("couldn't set default proxy configuration: access denied\n");
1333 else
1334 ok((!ret && GetLastError() == ERROR_INVALID_PARAMETER) ||
1335 broken(ret), /* Earlier winhttp versions on W2K/XP */
1336 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1337
1338 info.lpszProxy = normalString;
1339 SetLastError(0xdeadbeef);
1340 ret = WinHttpSetDefaultProxyConfiguration(&info);
1341 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1342 skip("couldn't set default proxy configuration: access denied\n");
1343 else
1344 {
1345 ok(ret, "WinHttpSetDefaultProxyConfiguration failed: %u\n", GetLastError());
1346 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
1347 "got %u\n", GetLastError());
1348 }
1349 set_default_proxy_reg_value( saved_proxy_settings, len, type );
1350 }
1351
1352 static void test_Timeouts (void)
1353 {
1354 BOOL ret;
1355 DWORD value, size;
1356 HINTERNET ses, req, con;
1357
1358 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1359 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1360
1361 SetLastError(0xdeadbeef);
1362 ret = WinHttpSetTimeouts(ses, -2, 0, 0, 0);
1363 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1364 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1365
1366 SetLastError(0xdeadbeef);
1367 ret = WinHttpSetTimeouts(ses, 0, -2, 0, 0);
1368 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1369 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1370
1371 SetLastError(0xdeadbeef);
1372 ret = WinHttpSetTimeouts(ses, 0, 0, -2, 0);
1373 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1374 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1375
1376 SetLastError(0xdeadbeef);
1377 ret = WinHttpSetTimeouts(ses, 0, 0, 0, -2);
1378 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1379 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1380
1381 SetLastError(0xdeadbeef);
1382 ret = WinHttpSetTimeouts(ses, -1, -1, -1, -1);
1383 ok(ret, "%u\n", GetLastError());
1384 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
1385 "expected ERROR_SUCCESS, got %u\n", GetLastError());
1386
1387 SetLastError(0xdeadbeef);
1388 ret = WinHttpSetTimeouts(ses, 0, 0, 0, 0);
1389 ok(ret, "%u\n", GetLastError());
1390
1391 SetLastError(0xdeadbeef);
1392 ret = WinHttpSetTimeouts(ses, 0x0123, 0x4567, 0x89ab, 0xcdef);
1393 ok(ret, "%u\n", GetLastError());
1394
1395 SetLastError(0xdeadbeef);
1396 value = 0xdeadbeef;
1397 size = sizeof(DWORD);
1398 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1399 ok(ret, "%u\n", GetLastError());
1400 ok(value == 0x0123, "Expected 0x0123, got %u\n", value);
1401
1402 SetLastError(0xdeadbeef);
1403 value = 0xdeadbeef;
1404 size = sizeof(DWORD);
1405 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1406 ok(ret, "%u\n", GetLastError());
1407 ok(value == 0x4567, "Expected 0x4567, got %u\n", value);
1408
1409 SetLastError(0xdeadbeef);
1410 value = 0xdeadbeef;
1411 size = sizeof(DWORD);
1412 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1413 ok(ret, "%u\n", GetLastError());
1414 ok(value == 0x89ab, "Expected 0x89ab, got %u\n", value);
1415
1416 SetLastError(0xdeadbeef);
1417 value = 0xdeadbeef;
1418 size = sizeof(DWORD);
1419 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1420 ok(ret, "%u\n", GetLastError());
1421 ok(value == 0xcdef, "Expected 0xcdef, got %u\n", value);
1422
1423 SetLastError(0xdeadbeef);
1424 value = 0;
1425 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1426 ok(ret, "%u\n", GetLastError());
1427
1428 SetLastError(0xdeadbeef);
1429 value = 0xdeadbeef;
1430 size = sizeof(DWORD);
1431 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1432 ok(ret, "%u\n", GetLastError());
1433 ok(value == 0, "Expected 0, got %u\n", value);
1434
1435 SetLastError(0xdeadbeef);
1436 value = 0;
1437 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1438 ok(ret, "%u\n", GetLastError());
1439
1440 SetLastError(0xdeadbeef);
1441 value = 0xdeadbeef;
1442 size = sizeof(DWORD);
1443 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1444 ok(ret, "%u\n", GetLastError());
1445 ok(value == 0, "Expected 0, got %u\n", value);
1446
1447 SetLastError(0xdeadbeef);
1448 value = 0;
1449 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1450 ok(ret, "%u\n", GetLastError());
1451
1452 SetLastError(0xdeadbeef);
1453 value = 0xdeadbeef;
1454 size = sizeof(DWORD);
1455 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1456 ok(ret, "%u\n", GetLastError());
1457 ok(value == 0, "Expected 0, got %u\n", value);
1458
1459 SetLastError(0xdeadbeef);
1460 value = 0;
1461 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1462 ok(ret, "%u\n", GetLastError());
1463
1464 SetLastError(0xdeadbeef);
1465 value = 0xdeadbeef;
1466 size = sizeof(DWORD);
1467 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1468 ok(ret, "%u\n", GetLastError());
1469 ok(value == 0, "Expected 0, got %u\n", value);
1470
1471 SetLastError(0xdeadbeef);
1472 value = 0xbeefdead;
1473 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1474 ok(ret, "%u\n", GetLastError());
1475
1476 SetLastError(0xdeadbeef);
1477 value = 0xdeadbeef;
1478 size = sizeof(DWORD);
1479 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1480 ok(ret, "%u\n", GetLastError());
1481 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1482
1483 SetLastError(0xdeadbeef);
1484 value = 0xbeefdead;
1485 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1486 ok(ret, "%u\n", GetLastError());
1487
1488 SetLastError(0xdeadbeef);
1489 value = 0xdeadbeef;
1490 size = sizeof(DWORD);
1491 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1492 ok(ret, "%u\n", GetLastError());
1493 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1494
1495 SetLastError(0xdeadbeef);
1496 value = 0xbeefdead;
1497 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1498 ok(ret, "%u\n", GetLastError());
1499
1500 SetLastError(0xdeadbeef);
1501 value = 0xdeadbeef;
1502 size = sizeof(DWORD);
1503 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1504 ok(ret, "%u\n", GetLastError());
1505 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1506
1507 SetLastError(0xdeadbeef);
1508 value = 0xbeefdead;
1509 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1510 ok(ret, "%u\n", GetLastError());
1511
1512 SetLastError(0xdeadbeef);
1513 value = 0xdeadbeef;
1514 size = sizeof(DWORD);
1515 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1516 ok(ret, "%u\n", GetLastError());
1517 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1518
1519 con = WinHttpConnect(ses, test_winehq, 0, 0);
1520 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1521
1522 /* Timeout values should match the last one set for session */
1523 SetLastError(0xdeadbeef);
1524 value = 0xdeadbeef;
1525 size = sizeof(DWORD);
1526 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1527 ok(ret, "%u\n", GetLastError());
1528 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1529
1530 SetLastError(0xdeadbeef);
1531 value = 0xdeadbeef;
1532 size = sizeof(DWORD);
1533 ret = WinHttpQueryOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1534 ok(ret, "%u\n", GetLastError());
1535 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1536
1537 SetLastError(0xdeadbeef);
1538 value = 0xdeadbeef;
1539 size = sizeof(DWORD);
1540 ret = WinHttpQueryOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1541 ok(ret, "%u\n", GetLastError());
1542 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1543
1544 SetLastError(0xdeadbeef);
1545 value = 0xdeadbeef;
1546 size = sizeof(DWORD);
1547 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1548 ok(ret, "%u\n", GetLastError());
1549 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1550
1551 SetLastError(0xdeadbeef);
1552 ret = WinHttpSetTimeouts(con, -2, 0, 0, 0);
1553 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1554 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1555
1556 SetLastError(0xdeadbeef);
1557 ret = WinHttpSetTimeouts(con, 0, -2, 0, 0);
1558 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1559 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1560
1561 SetLastError(0xdeadbeef);
1562 ret = WinHttpSetTimeouts(con, 0, 0, -2, 0);
1563 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1564 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1565
1566 SetLastError(0xdeadbeef);
1567 ret = WinHttpSetTimeouts(con, 0, 0, 0, -2);
1568 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1569 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1570
1571 SetLastError(0xdeadbeef);
1572 ret = WinHttpSetTimeouts(con, -1, -1, -1, -1);
1573 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1574 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1575
1576 SetLastError(0xdeadbeef);
1577 ret = WinHttpSetTimeouts(con, 0, 0, 0, 0);
1578 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1579 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1580
1581 SetLastError(0xdeadbeef);
1582 value = 0;
1583 ret = WinHttpSetOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1584 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1585 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1586
1587 SetLastError(0xdeadbeef);
1588 value = 0;
1589 ret = WinHttpSetOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1590 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1591 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1592
1593 SetLastError(0xdeadbeef);
1594 value = 0;
1595 ret = WinHttpSetOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1596 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1597 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1598
1599 SetLastError(0xdeadbeef);
1600 value = 0;
1601 ret = WinHttpSetOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1602 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1603 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1604
1605 /* Changing timeout values for session should affect the values for connection */
1606 SetLastError(0xdeadbeef);
1607 value = 0xdead;
1608 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1609 ok(ret, "%u\n", GetLastError());
1610
1611 SetLastError(0xdeadbeef);
1612 value = 0xdeadbeef;
1613 size = sizeof(DWORD);
1614 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1615 ok(ret, "%u\n", GetLastError());
1616 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1617
1618 SetLastError(0xdeadbeef);
1619 value = 0xdead;
1620 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1621 ok(ret, "%u\n", GetLastError());
1622
1623 SetLastError(0xdeadbeef);
1624 value = 0xdeadbeef;
1625 size = sizeof(DWORD);
1626 ret = WinHttpQueryOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1627 ok(ret, "%u\n", GetLastError());
1628 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1629
1630 SetLastError(0xdeadbeef);
1631 value = 0xdead;
1632 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1633 ok(ret, "%u\n", GetLastError());
1634
1635 SetLastError(0xdeadbeef);
1636 value = 0xdeadbeef;
1637 size = sizeof(DWORD);
1638 ret = WinHttpQueryOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1639 ok(ret, "%u\n", GetLastError());
1640 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1641
1642 SetLastError(0xdeadbeef);
1643 value = 0xdead;
1644 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1645 ok(ret, "%u\n", GetLastError());
1646
1647 SetLastError(0xdeadbeef);
1648 value = 0xdeadbeef;
1649 size = sizeof(DWORD);
1650 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1651 ok(ret, "%u\n", GetLastError());
1652 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1653
1654 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1655 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1656
1657 /* Timeout values should match the last one set for session */
1658 SetLastError(0xdeadbeef);
1659 value = 0xdeadbeef;
1660 size = sizeof(DWORD);
1661 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1662 ok(ret, "%u\n", GetLastError());
1663 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1664
1665 SetLastError(0xdeadbeef);
1666 value = 0xdeadbeef;
1667 size = sizeof(DWORD);
1668 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1669 ok(ret, "%u\n", GetLastError());
1670 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1671
1672 SetLastError(0xdeadbeef);
1673 value = 0xdeadbeef;
1674 size = sizeof(DWORD);
1675 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1676 ok(ret, "%u\n", GetLastError());
1677 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1678
1679 SetLastError(0xdeadbeef);
1680 value = 0xdeadbeef;
1681 size = sizeof(DWORD);
1682 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1683 ok(ret, "%u\n", GetLastError());
1684 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1685
1686 SetLastError(0xdeadbeef);
1687 ret = WinHttpSetTimeouts(req, -2, 0, 0, 0);
1688 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1689 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1690
1691 SetLastError(0xdeadbeef);
1692 ret = WinHttpSetTimeouts(req, 0, -2, 0, 0);
1693 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1694 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1695
1696 SetLastError(0xdeadbeef);
1697 ret = WinHttpSetTimeouts(req, 0, 0, -2, 0);
1698 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1699 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1700
1701 SetLastError(0xdeadbeef);
1702 ret = WinHttpSetTimeouts(req, 0, 0, 0, -2);
1703 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1704 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1705
1706 SetLastError(0xdeadbeef);
1707 ret = WinHttpSetTimeouts(req, -1, -1, -1, -1);
1708 ok(ret, "%u\n", GetLastError());
1709
1710 SetLastError(0xdeadbeef);
1711 ret = WinHttpSetTimeouts(req, 0, 0, 0, 0);
1712 ok(ret, "%u\n", GetLastError());
1713
1714 SetLastError(0xdeadbeef);
1715 ret = WinHttpSetTimeouts(req, 0xcdef, 0x89ab, 0x4567, 0x0123);
1716 ok(ret, "%u\n", GetLastError());
1717
1718 SetLastError(0xdeadbeef);
1719 value = 0xdeadbeef;
1720 size = sizeof(DWORD);
1721 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1722 ok(ret, "%u\n", GetLastError());
1723 ok(value == 0xcdef, "Expected 0xcdef, got %u\n", value);
1724
1725 SetLastError(0xdeadbeef);
1726 value = 0xdeadbeef;
1727 size = sizeof(DWORD);
1728 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1729 ok(ret, "%u\n", GetLastError());
1730 ok(value == 0x89ab, "Expected 0x89ab, got %u\n", value);
1731
1732 SetLastError(0xdeadbeef);
1733 value = 0xdeadbeef;
1734 size = sizeof(DWORD);
1735 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1736 ok(ret, "%u\n", GetLastError());
1737 ok(value == 0x4567, "Expected 0x4567, got %u\n", value);
1738
1739 SetLastError(0xdeadbeef);
1740 value = 0xdeadbeef;
1741 size = sizeof(DWORD);
1742 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1743 ok(ret, "%u\n", GetLastError());
1744 ok(value == 0x0123, "Expected 0x0123, got %u\n", value);
1745
1746 SetLastError(0xdeadbeef);
1747 value = 0;
1748 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1749 ok(ret, "%u\n", GetLastError());
1750
1751 SetLastError(0xdeadbeef);
1752 value = 0xdeadbeef;
1753 size = sizeof(DWORD);
1754 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1755 ok(ret, "%u\n", GetLastError());
1756 ok(value == 0, "Expected 0, got %u\n", value);
1757
1758 SetLastError(0xdeadbeef);
1759 value = 0;
1760 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1761 ok(ret, "%u\n", GetLastError());
1762
1763 SetLastError(0xdeadbeef);
1764 value = 0xdeadbeef;
1765 size = sizeof(DWORD);
1766 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1767 ok(ret, "%u\n", GetLastError());
1768 ok(value == 0, "Expected 0, got %u\n", value);
1769
1770 SetLastError(0xdeadbeef);
1771 value = 0;
1772 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1773 ok(ret, "%u\n", GetLastError());
1774
1775 SetLastError(0xdeadbeef);
1776 value = 0xdeadbeef;
1777 size = sizeof(DWORD);
1778 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1779 ok(ret, "%u\n", GetLastError());
1780 ok(value == 0, "Expected 0, got %u\n", value);
1781
1782 SetLastError(0xdeadbeef);
1783 value = 0;
1784 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1785 ok(ret, "%u\n", GetLastError());
1786
1787 SetLastError(0xdeadbeef);
1788 value = 0xdeadbeef;
1789 size = sizeof(DWORD);
1790 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1791 ok(ret, "%u\n", GetLastError());
1792 ok(value == 0, "Expected 0, got %u\n", value);
1793
1794 SetLastError(0xdeadbeef);
1795 value = 0xbeefdead;
1796 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1797 ok(ret, "%u\n", GetLastError());
1798
1799 SetLastError(0xdeadbeef);
1800 value = 0xdeadbeef;
1801 size = sizeof(DWORD);
1802 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1803 ok(ret, "%u\n", GetLastError());
1804 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1805
1806 SetLastError(0xdeadbeef);
1807 value = 0xbeefdead;
1808 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1809 ok(ret, "%u\n", GetLastError());
1810
1811 SetLastError(0xdeadbeef);
1812 value = 0xdeadbeef;
1813 size = sizeof(DWORD);
1814 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1815 ok(ret, "%u\n", GetLastError());
1816 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1817
1818 SetLastError(0xdeadbeef);
1819 value = 0xbeefdead;
1820 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1821 ok(ret, "%u\n", GetLastError());
1822
1823 SetLastError(0xdeadbeef);
1824 value = 0xdeadbeef;
1825 size = sizeof(DWORD);
1826 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1827 ok(ret, "%u\n", GetLastError());
1828 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1829
1830 SetLastError(0xdeadbeef);
1831 value = 0xbeefdead;
1832 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1833 ok(ret, "%u\n", GetLastError());
1834
1835 SetLastError(0xdeadbeef);
1836 value = 0xdeadbeef;
1837 size = sizeof(DWORD);
1838 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1839 ok(ret, "%u\n", GetLastError());
1840 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1841
1842 /* Changing timeout values for session should not affect the values for a request,
1843 * neither should the other way around.
1844 */
1845 SetLastError(0xdeadbeef);
1846 value = 0xbeefdead;
1847 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1848 ok(ret, "%u\n", GetLastError());
1849
1850 SetLastError(0xdeadbeef);
1851 value = 0xdeadbeef;
1852 size = sizeof(DWORD);
1853 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1854 ok(ret, "%u\n", GetLastError());
1855 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1856
1857 SetLastError(0xdeadbeef);
1858 value = 0xbeefdead;
1859 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1860 ok(ret, "%u\n", GetLastError());
1861
1862 SetLastError(0xdeadbeef);
1863 value = 0xdeadbeef;
1864 size = sizeof(DWORD);
1865 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1866 ok(ret, "%u\n", GetLastError());
1867 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1868
1869 SetLastError(0xdeadbeef);
1870 value = 0xbeefdead;
1871 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1872 ok(ret, "%u\n", GetLastError());
1873
1874 SetLastError(0xdeadbeef);
1875 value = 0xdeadbeef;
1876 size = sizeof(DWORD);
1877 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1878 ok(ret, "%u\n", GetLastError());
1879 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1880
1881 SetLastError(0xdeadbeef);
1882 value = 0xbeefdead;
1883 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1884 ok(ret, "%u\n", GetLastError());
1885
1886 SetLastError(0xdeadbeef);
1887 value = 0xdeadbeef;
1888 size = sizeof(DWORD);
1889 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1890 ok(ret, "%u\n", GetLastError());
1891 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1892
1893 SetLastError(0xdeadbeef);
1894 value = 0xbeef;
1895 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1896 ok(ret, "%u\n", GetLastError());
1897
1898 SetLastError(0xdeadbeef);
1899 value = 0xdeadbeef;
1900 size = sizeof(DWORD);
1901 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1902 ok(ret, "%u\n", GetLastError());
1903 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1904
1905 SetLastError(0xdeadbeef);
1906 value = 0xbeef;
1907 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1908 ok(ret, "%u\n", GetLastError());
1909
1910 SetLastError(0xdeadbeef);
1911 value = 0xdeadbeef;
1912 size = sizeof(DWORD);
1913 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1914 ok(ret, "%u\n", GetLastError());
1915 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1916
1917 SetLastError(0xdeadbeef);
1918 value = 0xbeef;
1919 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1920 ok(ret, "%u\n", GetLastError());
1921
1922 SetLastError(0xdeadbeef);
1923 value = 0xdeadbeef;
1924 size = sizeof(DWORD);
1925 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1926 ok(ret, "%u\n", GetLastError());
1927 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1928
1929 SetLastError(0xdeadbeef);
1930 value = 0xbeef;
1931 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1932 ok(ret, "%u\n", GetLastError());
1933
1934 SetLastError(0xdeadbeef);
1935 value = 0xdeadbeef;
1936 size = sizeof(DWORD);
1937 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1938 ok(ret, "%u\n", GetLastError());
1939 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1940
1941 WinHttpCloseHandle(req);
1942 WinHttpCloseHandle(con);
1943 WinHttpCloseHandle(ses);
1944 }
1945
1946 static void test_resolve_timeout(void)
1947 {
1948 static const WCHAR nxdomain[] =
1949 {'n','x','d','o','m','a','i','n','.','w','i','n','e','h','q','.','o','r','g',0};
1950 HINTERNET ses, con, req;
1951 DWORD timeout;
1952 BOOL ret;
1953
1954 if (! proxy_active())
1955 {
1956 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1957 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1958
1959 timeout = 10000;
1960 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
1961 ok(ret, "failed to set resolve timeout %u\n", GetLastError());
1962
1963 con = WinHttpConnect(ses, nxdomain, 0, 0);
1964 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1965
1966 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1967 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1968
1969 SetLastError(0xdeadbeef);
1970 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1971 if (ret)
1972 {
1973 skip("nxdomain returned success. Broken ISP redirects?\n");
1974 goto done;
1975 }
1976 ok(GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED,
1977 "expected ERROR_WINHTTP_NAME_NOT_RESOLVED got %u\n", GetLastError());
1978
1979 WinHttpCloseHandle(req);
1980 WinHttpCloseHandle(con);
1981 WinHttpCloseHandle(ses);
1982 }
1983 else
1984 skip("Skipping host resolution tests, host resolution preformed by proxy\n");
1985
1986 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1987 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1988
1989 timeout = 10000;
1990 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
1991 ok(ret, "failed to set resolve timeout %u\n", GetLastError());
1992
1993 con = WinHttpConnect(ses, test_winehq, 0, 0);
1994 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1995
1996 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1997 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1998
1999 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2000 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
2001 {
2002 skip("connection failed, skipping\n");
2003 goto done;
2004 }
2005 ok(ret, "failed to send request\n");
2006
2007 done:
2008 WinHttpCloseHandle(req);
2009 WinHttpCloseHandle(con);
2010 WinHttpCloseHandle(ses);
2011 }
2012
2013 static const char page1[] =
2014 "<HTML>\r\n"
2015 "<HEAD><TITLE>winhttp test page</TITLE></HEAD>\r\n"
2016 "<BODY>The quick brown fox jumped over the lazy dog<P></BODY>\r\n"
2017 "</HTML>\r\n\r\n";
2018
2019 static const char okmsg[] =
2020 "HTTP/1.1 200 OK\r\n"
2021 "Server: winetest\r\n"
2022 "\r\n";
2023
2024 static const char notokmsg[] =
2025 "HTTP/1.1 400 Bad Request\r\n"
2026 "\r\n";
2027
2028 static const char cookiemsg[] =
2029 "HTTP/1.1 200 OK\r\n"
2030 "Set-Cookie: name = value \r\n"
2031 "Set-Cookie: NAME = value \r\n"
2032 "\r\n";
2033
2034 static const char cookiemsg2[] =
2035 "HTTP/1.1 200 OK\r\n"
2036 "Set-Cookie: name2=value; Domain = localhost; Path=/cookie5;Expires=Wed, 13 Jan 2021 22:23:01 GMT; HttpOnly; \r\n"
2037 "\r\n";
2038
2039 static const char nocontentmsg[] =
2040 "HTTP/1.1 204 No Content\r\n"
2041 "Server: winetest\r\n"
2042 "\r\n";
2043
2044 static const char notmodified[] =
2045 "HTTP/1.1 304 Not Modified\r\n"
2046 "\r\n";
2047
2048 static const char noauthmsg[] =
2049 "HTTP/1.1 401 Unauthorized\r\n"
2050 "Server: winetest\r\n"
2051 "Connection: close\r\n"
2052 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
2053 "Content-Length: 12\r\n"
2054 "Content-Type: text/plain\r\n"
2055 "\r\n";
2056
2057 static const char okauthmsg[] =
2058 "HTTP/1.1 200 OK\r\n"
2059 "Server: winetest\r\n"
2060 "Connection: close\r\n"
2061 "Content-Length: 11\r\n"
2062 "Content-Type: text/plain\r\n"
2063 "\r\n";
2064
2065 static const char headmsg[] =
2066 "HTTP/1.1 200 OK\r\n"
2067 "Content-Length: 100\r\n"
2068 "\r\n";
2069
2070 static const char multiauth[] =
2071 "HTTP/1.1 401 Unauthorized\r\n"
2072 "Server: winetest\r\n"
2073 "WWW-Authenticate: Bearer\r\n"
2074 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
2075 "WWW-Authenticate: NTLM\r\n"
2076 "Content-Length: 10\r\n"
2077 "Content-Type: text/plain\r\n"
2078 "\r\n";
2079
2080 static const char largeauth[] =
2081 "HTTP/1.1 401 Unauthorized\r\n"
2082 "Server: winetest\r\n"
2083 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
2084 "WWW-Authenticate: NTLM\r\n"
2085 "Content-Length: 10240\r\n"
2086 "Content-Type: text/plain\r\n"
2087 "\r\n";
2088
2089 static const char unauthorized[] = "Unauthorized";
2090 static const char hello_world[] = "Hello World";
2091 static const char auth_unseen[] = "Auth Unseen";
2092
2093 struct server_info
2094 {
2095 HANDLE event;
2096 int port;
2097 };
2098
2099 #define BIG_BUFFER_LEN 0x2250
2100
2101 static DWORD CALLBACK server_thread(LPVOID param)
2102 {
2103 struct server_info *si = param;
2104 int r, c = -1, i, on;
2105 SOCKET s;
2106 struct sockaddr_in sa;
2107 char buffer[0x100];
2108 WSADATA wsaData;
2109 int last_request = 0;
2110
2111 WSAStartup(MAKEWORD(1,1), &wsaData);
2112
2113 s = socket(AF_INET, SOCK_STREAM, 0);
2114 if (s == INVALID_SOCKET)
2115 return 1;
2116
2117 on = 1;
2118 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof on);
2119
2120 memset(&sa, 0, sizeof sa);
2121 sa.sin_family = AF_INET;
2122 sa.sin_port = htons(si->port);
2123 sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
2124
2125 r = bind(s, (struct sockaddr *)&sa, sizeof(sa));
2126 if (r < 0)
2127 return 1;
2128
2129 listen(s, 0);
2130 SetEvent(si->event);
2131 do
2132 {
2133 if (c == -1) c = accept(s, NULL, NULL);
2134
2135 memset(buffer, 0, sizeof buffer);
2136 for(i = 0; i < sizeof buffer - 1; i++)
2137 {
2138 r = recv(c, &buffer[i], 1, 0);
2139 if (r != 1)
2140 break;
2141 if (i < 4) continue;
2142 if (buffer[i - 2] == '\n' && buffer[i] == '\n' &&
2143 buffer[i - 3] == '\r' && buffer[i - 1] == '\r')
2144 break;
2145 }
2146 if (strstr(buffer, "GET /basic"))
2147 {
2148 send(c, okmsg, sizeof okmsg - 1, 0);
2149 send(c, page1, sizeof page1 - 1, 0);
2150 }
2151 if (strstr(buffer, "/auth_with_creds"))
2152 {
2153 send(c, okauthmsg, sizeof okauthmsg - 1, 0);
2154 if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
2155 send(c, hello_world, sizeof hello_world - 1, 0);
2156 else
2157 send(c, auth_unseen, sizeof auth_unseen - 1, 0);
2158 continue;
2159 }
2160 if (strstr(buffer, "/auth"))
2161 {
2162 if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
2163 {
2164 send(c, okauthmsg, sizeof okauthmsg - 1, 0);
2165 send(c, hello_world, sizeof hello_world - 1, 0);
2166 }
2167 else
2168 {
2169 send(c, noauthmsg, sizeof noauthmsg - 1, 0);
2170 send(c, unauthorized, sizeof unauthorized - 1, 0);
2171 }
2172 continue;
2173 }
2174 if (strstr(buffer, "/big"))
2175 {
2176 char msg[BIG_BUFFER_LEN];
2177 memset(msg, 'm', sizeof(msg));
2178 send(c, okmsg, sizeof(okmsg) - 1, 0);
2179 send(c, msg, sizeof(msg), 0);
2180 }
2181 if (strstr(buffer, "/no_headers"))
2182 {
2183 send(c, page1, sizeof page1 - 1, 0);
2184 }
2185 if (strstr(buffer, "GET /no_content"))
2186 {
2187 send(c, nocontentmsg, sizeof nocontentmsg - 1, 0);
2188 continue;
2189 }
2190 if (strstr(buffer, "GET /not_modified"))
2191 {
2192 if (strstr(buffer, "If-Modified-Since:")) send(c, notmodified, sizeof notmodified - 1, 0);
2193 else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2194 continue;
2195 }
2196 if (strstr(buffer, "HEAD /head"))
2197 {
2198 send(c, headmsg, sizeof headmsg - 1, 0);
2199 continue;
2200 }
2201 if (strstr(buffer, "GET /multiauth"))
2202 {
2203 send(c, multiauth, sizeof multiauth - 1, 0);
2204 }
2205 if (strstr(buffer, "GET /largeauth"))
2206 {
2207 if (strstr(buffer, "Authorization: NTLM"))
2208 send(c, okmsg, sizeof(okmsg) - 1, 0);
2209 else
2210 {
2211 send(c, largeauth, sizeof largeauth - 1, 0);
2212 #ifdef __REACTOS__
2213 memset(buffer, 'A', sizeof(buffer));
2214 for (i = 0; i < (10240 / sizeof(buffer)); i++) send(c, buffer, sizeof(buffer), 0);
2215 #else
2216 for (i = 0; i < 10240; i++) send(c, "A", 1, 0);
2217 #endif
2218 continue;
2219 }
2220 }
2221 if (strstr(buffer, "GET /cookie5"))
2222 {
2223 if (strstr(buffer, "Cookie: name2=value\r\n"))
2224 send(c, okmsg, sizeof(okmsg) - 1, 0);
2225 else
2226 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2227 }
2228 if (strstr(buffer, "GET /cookie4"))
2229 {
2230 send(c, cookiemsg2, sizeof(cookiemsg2) - 1, 0);
2231 }
2232 if (strstr(buffer, "GET /cookie3"))
2233 {
2234 if (strstr(buffer, "Cookie: name=value2; NAME=value; name=value\r\n") ||
2235 broken(strstr(buffer, "Cookie: name=value2; name=value; NAME=value\r\n") != NULL))
2236 send(c, okmsg, sizeof(okmsg) - 1, 0);
2237 else
2238 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2239 }
2240 if (strstr(buffer, "GET /cookie2"))
2241 {
2242 if (strstr(buffer, "Cookie: NAME=value; name=value\r\n") ||
2243 broken(strstr(buffer, "Cookie: name=value; NAME=value\r\n") != NULL))
2244 send(c, okmsg, sizeof(okmsg) - 1, 0);
2245 else
2246 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2247 }
2248 else if (strstr(buffer, "GET /cookie"))
2249 {
2250 if (!strstr(buffer, "Cookie: name=value\r\n")) send(c, cookiemsg, sizeof(cookiemsg) - 1, 0);
2251 else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2252 }
2253 if (strstr(buffer, "GET /quit"))
2254 {
2255 send(c, okmsg, sizeof okmsg - 1, 0);
2256 send(c, page1, sizeof page1 - 1, 0);
2257 last_request = 1;
2258 }
2259 shutdown(c, 2);
2260 closesocket(c);
2261 c = -1;
2262
2263 } while (!last_request);
2264
2265 closesocket(s);
2266 return 0;
2267 }
2268
2269 static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path)
2270 {
2271 static const WCHAR test_header_end_clrf[] = {'\r','\n','\r','\n',0};
2272 static const WCHAR test_header_end_raw[] = {0,0};
2273 HINTERNET ses, con, req;
2274 char buffer[0x100];
2275 WCHAR buffer2[0x100];
2276 DWORD count, status, size, error, supported, first, target;
2277 BOOL ret;
2278
2279 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2280 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2281
2282 con = WinHttpConnect(ses, localhostW, port, 0);
2283 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2284
2285 req = WinHttpOpenRequest(con, verb, path, NULL, NULL, NULL, 0);
2286 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2287
2288 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2289 ok(ret, "failed to send request %u\n", GetLastError());
2290
2291 ret = WinHttpReceiveResponse(req, NULL);
2292 ok(ret, "failed to receive response %u\n", GetLastError());
2293
2294 status = 0xdeadbeef;
2295 size = sizeof(status);
2296 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2297 ok(ret, "failed to query status code %u\n", GetLastError());
2298 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2299
2300 supported = first = target = 0xdeadbeef;
2301 SetLastError(0xdeadbeef);
2302 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2303 error = GetLastError();
2304 ok(!ret, "unexpected success\n");
2305 todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
2306 ok(supported == 0xdeadbeef, "got %x\n", supported);
2307 ok(first == 0xdeadbeef, "got %x\n", first);
2308 ok(target == 0xdeadbeef, "got %x\n", target);
2309
2310 size = sizeof(buffer2);
2311 memset(buffer2, 0, sizeof(buffer2));
2312 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, buffer2, &size, NULL);
2313 ok(ret, "failed to query for raw headers: %u\n", GetLastError());
2314 ok(!memcmp(buffer2 + lstrlenW(buffer2) - 4, test_header_end_clrf, sizeof(test_header_end_clrf)),
2315 "WinHttpQueryHeaders returned invalid end of header string\n");
2316
2317 size = sizeof(buffer2);
2318 memset(buffer2, 0, sizeof(buffer2));
2319 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS, NULL, buffer2, &size, NULL);
2320 ok(ret, "failed to query for raw headers: %u\n", GetLastError());
2321 ok(!memcmp(buffer2 + (size / sizeof(WCHAR)) - 1, test_header_end_raw, sizeof(test_header_end_raw)),
2322 "WinHttpQueryHeaders returned invalid end of header string\n");
2323 ok(buffer2[(size / sizeof(WCHAR)) - 2] != 0, "returned string has too many NULL characters\n");
2324
2325 count = 0;
2326 memset(buffer, 0, sizeof(buffer));
2327 ret = WinHttpReadData(req, buffer, sizeof buffer, &count);
2328 ok(ret, "failed to read data %u\n", GetLastError());
2329 ok(count == sizeof page1 - 1, "count was wrong\n");
2330 ok(!memcmp(buffer, page1, sizeof page1), "http data wrong\n");
2331
2332 WinHttpCloseHandle(req);
2333 WinHttpCloseHandle(con);
2334 WinHttpCloseHandle(ses);
2335 }
2336
2337 static void test_basic_authentication(int port)
2338 {
2339 static const WCHAR authW[] = {'/','a','u','t','h',0};
2340 static const WCHAR auth_with_credsW[] = {'/','a','u','t','h','_','w','i','t','h','_','c','r','e','d','s',0};
2341 static WCHAR userW[] = {'u','s','e','r',0};
2342 static WCHAR passW[] = {'p','w','d',0};
2343 static WCHAR pass2W[] = {'p','w','d','2',0};
2344 HINTERNET ses, con, req;
2345 DWORD status, size, error, supported, first, target;
2346 char buffer[32];
2347 BOOL ret;
2348
2349 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2350 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2351
2352 con = WinHttpConnect(ses, localhostW, port, 0);
2353 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2354
2355 req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2356 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2357
2358 SetLastError(0xdeadbeef);
2359 ret = WinHttpQueryAuthSchemes(NULL, NULL, NULL, NULL);
2360 error = GetLastError();
2361 ok(!ret, "expected failure\n");
2362 ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
2363
2364 SetLastError(0xdeadbeef);
2365 ret = WinHttpQueryAuthSchemes(req, NULL, NULL, NULL);
2366 error = GetLastError();
2367 ok(!ret, "expected failure\n");
2368 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2369
2370 supported = 0xdeadbeef;
2371 SetLastError(0xdeadbeef);
2372 ret = WinHttpQueryAuthSchemes(req, &supported, NULL, NULL);
2373 error = GetLastError();
2374 ok(!ret, "expected failure\n");
2375 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2376 ok(supported == 0xdeadbeef, "got %x\n", supported);
2377
2378 supported = first = 0xdeadbeef;
2379 SetLastError(0xdeadbeef);
2380 ret = WinHttpQueryAuthSchemes(req, &supported, &first, NULL);
2381 error = GetLastError();
2382 ok(!ret, "expected failure\n");
2383 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2384 ok(supported == 0xdeadbeef, "got %x\n", supported);
2385 ok(first == 0xdeadbeef, "got %x\n", first);
2386
2387 supported = first = target = 0xdeadbeef;
2388 SetLastError(0xdeadbeef);
2389 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2390 error = GetLastError();
2391 ok(!ret, "expected failure\n");
2392 todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
2393 ok(supported == 0xdeadbeef, "got %x\n", supported);
2394 ok(first == 0xdeadbeef, "got %x\n", first);
2395 ok(target == 0xdeadbeef, "got %x\n", target);
2396
2397 supported = first = target = 0xdeadbeef;
2398 SetLastError(0xdeadbeef);
2399 ret = WinHttpQueryAuthSchemes(NULL, &supported, &first, &target);
2400 error = GetLastError();
2401 ok(!ret, "expected failure\n");
2402 ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
2403 ok(supported == 0xdeadbeef, "got %x\n", supported);
2404 ok(first == 0xdeadbeef, "got %x\n", first);
2405 ok(target == 0xdeadbeef, "got %x\n", target);
2406
2407 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2408 ok(ret, "failed to send request %u\n", GetLastError());
2409
2410 ret = WinHttpReceiveResponse(req, NULL);
2411 ok(ret, "failed to receive response %u\n", GetLastError());
2412
2413 status = 0xdeadbeef;
2414 size = sizeof(status);
2415 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2416 ok(ret, "failed to query status code %u\n", GetLastError());
2417 ok(status == HTTP_STATUS_DENIED, "request failed unexpectedly %u\n", status);
2418
2419 size = 0;
2420 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
2421 error = GetLastError();
2422 ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError());
2423 if (ret)
2424 {
2425 ok(size == 12, "expected 12, got %u\n", size);
2426 ok(!memcmp(buffer, unauthorized, 12), "got %s\n", buffer);
2427 }
2428
2429 supported = first = target = 0xdeadbeef;
2430 SetLastError(0xdeadbeef);
2431 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2432 error = GetLastError();
2433 ok(ret, "failed to query authentication schemes %u\n", error);
2434 ok(error == ERROR_SUCCESS || broken(error == 0xdeadbeef) /* < win7 */, "expected ERROR_SUCCESS, got %u\n", error);
2435 ok(supported == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", supported);
2436 ok(first == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", first);
2437 ok(target == WINHTTP_AUTH_TARGET_SERVER, "got %x\n", target);
2438
2439 SetLastError(0xdeadbeef);
2440 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NTLM, NULL, NULL, NULL);
2441 error = GetLastError();
2442 ok(ret, "failed to set credentials %u\n", error);
2443 ok(error == ERROR_SUCCESS || broken(error == 0xdeadbeef) /* < win7 */, "expected ERROR_SUCCESS, got %u\n", error);
2444
2445 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_PASSPORT, NULL, NULL, NULL);
2446 ok(ret, "failed to set credentials %u\n", GetLastError());
2447
2448 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NEGOTIATE, NULL, NULL, NULL);
2449 ok(ret, "failed to set credentials %u\n", GetLastError());
2450
2451 SetLastError(0xdeadbeef);
2452 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_DIGEST, NULL, NULL, NULL);
2453 error = GetLastError();
2454 ok(!ret, "expected failure\n");
2455 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2456
2457 SetLastError(0xdeadbeef);
2458 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, NULL, NULL);
2459 error = GetLastError();
2460 ok(!ret, "expected failure\n");
2461 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2462
2463 SetLastError(0xdeadbeef);
2464 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, NULL, NULL);
2465 error = GetLastError();
2466 ok(!ret, "expected failure\n");
2467 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2468
2469 SetLastError(0xdeadbeef);
2470 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, passW, NULL);
2471 error = GetLastError();
2472 ok(!ret, "expected failure\n");
2473 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2474
2475 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
2476 ok(ret, "failed to set credentials %u\n", GetLastError());
2477
2478 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2479 ok(ret, "failed to send request %u\n", GetLastError());
2480
2481 ret = WinHttpReceiveResponse(req, NULL);
2482 ok(ret, "failed to receive response %u\n", GetLastError());
2483
2484 status = 0xdeadbeef;
2485 size = sizeof(status);
2486 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2487 ok(ret, "failed to query status code %u\n", GetLastError());
2488 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2489
2490 size = 0;
2491 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
2492 error = GetLastError();
2493 ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError());
2494 if (ret)
2495 {
2496 ok(size == 11, "expected 11, got %u\n", size);
2497 ok(!memcmp(buffer, hello_world, 11), "got %s\n", buffer);
2498 }
2499
2500 WinHttpCloseHandle(req);
2501 WinHttpCloseHandle(con);
2502 WinHttpCloseHandle(ses);
2503
2504 /* now set the credentials first to show that they get sent with the first request */
2505 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2506 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2507
2508 con = WinHttpConnect(ses, localhostW, port, 0);
2509 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2510
2511 req = WinHttpOpenRequest(con, NULL, auth_with_credsW, NULL, NULL, NULL, 0);
2512 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2513
2514 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
2515 ok(ret, "failed to set credentials %u\n", GetLastError());
2516
2517 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2518 ok(ret, "failed to send request %u\n", GetLastError());
2519
2520 ret = WinHttpReceiveResponse(req, NULL);
2521 ok(ret, "failed to receive response %u\n", GetLastError());
2522
2523 status = 0xdeadbeef;
2524 size = sizeof(status);
2525 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2526 ok(ret, "failed to query status code %u\n", GetLastError());
2527 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2528
2529 size = 0;
2530 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
2531 error = GetLastError();
2532 ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError());
2533 if (ret)
2534 {
2535 ok(size == 11, "expected 11, got %u\n", size);
2536 ok(!memcmp(buffer, hello_world, 11), "got %s\n", buffer);
2537 }
2538
2539 WinHttpCloseHandle(req);
2540 WinHttpCloseHandle(con);
2541 WinHttpCloseHandle(ses);
2542
2543 /* credentials set with WinHttpSetCredentials take precedence over those set through options */
2544
2545 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2546 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2547
2548 con = WinHttpConnect(ses, localhostW, port, 0);
2549 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2550
2551 req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2552 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2553
2554 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
2555 ok(ret, "failed to set credentials %u\n", GetLastError());
2556
2557 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
2558 ok(ret, "failed to set username %u\n", GetLastError());
2559
2560 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, pass2W, lstrlenW(pass2W));
2561 ok(ret, "failed to set password %u\n", GetLastError());
2562
2563 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2564 ok(ret, "failed to send request %u\n", GetLastError());
2565
2566 ret = WinHttpReceiveResponse(req, NULL);
2567 ok(ret, "failed to receive response %u\n", GetLastError());
2568
2569 status = 0xdeadbeef;
2570 size = sizeof(status);
2571 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2572 ok(ret, "failed to query status code %u\n", GetLastError());
2573 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2574
2575 WinHttpCloseHandle(req);
2576 WinHttpCloseHandle(con);
2577 WinHttpCloseHandle(ses);
2578
2579 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2580 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2581
2582 con = WinHttpConnect(ses, localhostW, port, 0);
2583 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2584
2585 req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2586 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2587
2588 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
2589 ok(ret, "failed to set username %u\n", GetLastError());
2590
2591 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, passW, lstrlenW(passW));
2592 ok(ret, "failed to set password %u\n", GetLastError());
2593
2594 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, pass2W, NULL);
2595 ok(ret, "failed to set credentials %u\n", GetLastError());
2596
2597 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2598 ok(ret, "failed to send request %u\n", GetLastError());
2599
2600 ret = WinHttpReceiveResponse(req, NULL);
2601 ok(ret, "failed to receive response %u\n", GetLastError());
2602
2603 status = 0xdeadbeef;
2604 size = sizeof(status);
2605 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2606 ok(ret, "failed to query status code %u\n", GetLastError());
2607 ok(status == HTTP_STATUS_DENIED, "request failed unexpectedly %u\n", status);
2608
2609 WinHttpCloseHandle(req);
2610 WinHttpCloseHandle(con);
2611 WinHttpCloseHandle(ses);
2612 }
2613
2614 static void test_multi_authentication(int port)
2615 {
2616 static const WCHAR multiauthW[] = {'/','m','u','l','t','i','a','u','t','h',0};
2617 static const WCHAR getW[] = {'G','E','T',0};
2618 HINTERNET ses, con, req;
2619 DWORD supported, first, target;
2620 BOOL ret;
2621
2622 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2623 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2624
2625 con = WinHttpConnect(ses, localhostW, port, 0);
2626 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2627
2628 req = WinHttpOpenRequest(con, getW, multiauthW, NULL, NULL, NULL, 0);
2629 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2630
2631 ret = WinHttpSendRequest(req, WINHTTP_NO_ADDITIONAL_HEADERS, 0,
2632 WINHTTP_NO_REQUEST_DATA,0, 0, 0 );
2633 ok(ret, "expected success\n");
2634
2635 ret = WinHttpReceiveResponse(req, NULL);
2636 ok(ret, "expected success\n");
2637
2638 supported = first = target = 0xdeadbeef;
2639 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2640 ok(ret, "expected success\n");
2641 ok(supported == (WINHTTP_AUTH_SCHEME_BASIC | WINHTTP_AUTH_SCHEME_NTLM), "got %x\n", supported);
2642 ok(target == WINHTTP_AUTH_TARGET_SERVER, "got %x\n", target);
2643 ok(first == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", first);
2644
2645 WinHttpCloseHandle(req);
2646 WinHttpCloseHandle(con);
2647 WinHttpCloseHandle(ses);
2648 }
2649
2650 static void test_large_data_authentication(int port)
2651 {
2652 static const WCHAR largeauthW[] = {'/','l','a','r','g','e','a','u','t','h',0};
2653 static const WCHAR getW[] = {'G','E','T',0};
2654 static WCHAR userW[] = {'u','s','e','r',0};
2655 static WCHAR passW[] = {'p','w','d',0};
2656 HINTERNET ses, con, req;
2657 DWORD status, size;
2658 BOOL ret;
2659
2660 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2661 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2662
2663 con = WinHttpConnect(ses, localhostW, port, 0);
2664 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2665
2666 req = WinHttpOpenRequest(con, getW, largeauthW, NULL, NULL, NULL, 0);
2667 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2668
2669 ret = WinHttpSendRequest(req, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
2670 ok(ret, "expected success\n");
2671
2672 ret = WinHttpReceiveResponse(req, NULL);
2673 ok(ret, "expected success\n");
2674
2675 size = sizeof(status);
2676 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL,
2677 &status, &size, NULL);
2678 ok(ret, "expected success\n");
2679 ok(status == HTTP_STATUS_DENIED, "got %d\n", status);
2680
2681 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NTLM, userW, passW, NULL);
2682 ok(ret, "expected success\n");
2683
2684 ret = WinHttpSendRequest(req, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
2685 ok(ret, "expected success %d\n", GetLastError());
2686
2687 ret = WinHttpReceiveResponse(req, NULL);
2688 ok(ret, "expected success\n");
2689
2690 size = sizeof(status);
2691 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL,
2692 &status, &size, NULL);
2693 ok(ret, "expected success\n");
2694 ok