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