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