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