makefiles: Don't use standard libs for programs that specify -nodefaultlibs.
[wine/zf.git] / dlls / winhttp / tests / winhttp.c
blobab91940ebb887c3e956746185e28e846e69ba381
1 /*
2 * WinHTTP - tests
4 * Copyright 2008 Google (Zac Brown)
5 * Copyright 2015 Dmitry Timoshkov
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.
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.
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
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>
35 #include "wine/test.h"
36 #include "wine/heap.h"
38 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
40 static BOOL proxy_active(void)
42 WINHTTP_PROXY_INFO proxy_info;
43 BOOL active = FALSE;
45 SetLastError(0xdeadbeef);
46 if (WinHttpGetDefaultProxyConfiguration(&proxy_info))
48 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
49 "got %u\n", GetLastError());
50 active = (proxy_info.lpszProxy != NULL);
51 if (active)
52 GlobalFree(proxy_info.lpszProxy);
53 if (proxy_info.lpszProxyBypass != NULL)
54 GlobalFree(proxy_info.lpszProxyBypass);
56 else
57 active = FALSE;
59 return active;
62 static void test_WinHttpQueryOption(void)
64 BOOL ret;
65 HINTERNET session, request, connection;
66 DWORD feature, size;
68 SetLastError(0xdeadbeef);
69 session = WinHttpOpen(L"winetest", 0, 0, 0, 0);
70 ok(session != NULL, "WinHttpOpen failed to open session, error %u\n", GetLastError());
72 SetLastError(0xdeadbeef);
73 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, NULL);
74 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
75 ok(GetLastError() == ERROR_INVALID_PARAMETER,
76 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
78 size = 0xdeadbeef;
79 SetLastError(0xdeadbeef);
80 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, &size);
81 ok(!ret, "should fail to query option\n");
82 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
83 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
84 ok(size == 4, "expected 4, got %u\n", size);
86 feature = 0xdeadbeef;
87 size = sizeof(feature) - 1;
88 SetLastError(0xdeadbeef);
89 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
90 ok(!ret, "should fail to query option\n");
91 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
92 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
93 ok(size == 4, "expected 4, got %u\n", size);
95 feature = 0xdeadbeef;
96 size = sizeof(feature) + 1;
97 SetLastError(0xdeadbeef);
98 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
99 ok(ret, "failed to query option %u\n", GetLastError());
100 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
101 "got %u\n", GetLastError());
102 ok(size == sizeof(feature), "WinHttpQueryOption should set the size: %u\n", size);
103 ok(feature == WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP,
104 "expected WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP, got %#x\n", feature);
106 SetLastError(0xdeadbeef);
107 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, sizeof(feature));
108 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
109 ok(GetLastError() == ERROR_INVALID_PARAMETER,
110 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
112 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
113 SetLastError(0xdeadbeef);
114 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature) - 1);
115 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
116 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
117 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
119 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
120 SetLastError(0xdeadbeef);
121 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature) + 1);
122 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
123 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
124 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
126 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
127 SetLastError(0xdeadbeef);
128 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature));
129 ok(ret, "failed to set redirect policy %u\n", GetLastError());
131 feature = 0xdeadbeef;
132 size = sizeof(feature);
133 SetLastError(0xdeadbeef);
134 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
135 ok(ret, "failed to query option %u\n", GetLastError());
136 ok(feature == WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS,
137 "expected WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS, got %#x\n", feature);
139 feature = WINHTTP_DISABLE_COOKIES;
140 SetLastError(0xdeadbeef);
141 ret = WinHttpSetOption(session, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
142 ok(!ret, "should fail to set disable feature for a session\n");
143 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
144 "expected ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, got %u\n", GetLastError());
146 SetLastError(0xdeadbeef);
147 connection = WinHttpConnect(session, L"test.winehq.org", INTERNET_DEFAULT_HTTP_PORT, 0);
148 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u\n", GetLastError());
150 feature = WINHTTP_DISABLE_COOKIES;
151 SetLastError(0xdeadbeef);
152 ret = WinHttpSetOption(connection, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
153 ok(!ret, "should fail to set disable feature for a connection\n");
154 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
155 "expected ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, got %u\n", GetLastError());
157 SetLastError(0xdeadbeef);
158 request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
159 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
160 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
162 skip("Network unreachable, skipping the test\n");
163 goto done;
166 feature = 0xdeadbeef;
167 size = sizeof(feature);
168 SetLastError(0xdeadbeef);
169 ret = WinHttpQueryOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, &size);
170 ok(!ret, "should fail to query disable feature for a request\n");
171 ok(GetLastError() == ERROR_INVALID_PARAMETER,
172 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
174 feature = 0;
175 size = sizeof(feature);
176 SetLastError(0xdeadbeef);
177 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
178 ok(ret, "failed to set feature %u\n", GetLastError());
180 feature = 0xffffffff;
181 size = sizeof(feature);
182 SetLastError(0xdeadbeef);
183 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
184 ok(ret, "failed to set feature %u\n", GetLastError());
186 feature = WINHTTP_DISABLE_COOKIES;
187 size = sizeof(feature);
188 SetLastError(0xdeadbeef);
189 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
190 ok(ret, "failed to set feature %u\n", GetLastError());
192 size = 0;
193 SetLastError(0xdeadbeef);
194 ret = WinHttpQueryOption(request, WINHTTP_OPTION_DISABLE_FEATURE, NULL, &size);
195 ok(!ret, "should fail to query disable feature for a request\n");
196 ok(GetLastError() == ERROR_INVALID_PARAMETER,
197 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
199 feature = 0xdeadbeef;
200 size = sizeof(feature);
201 SetLastError(0xdeadbeef);
202 ret = WinHttpQueryOption(request, WINHTTP_OPTION_ENABLE_FEATURE, &feature, &size);
203 ok(!ret, "should fail to query enabled features for a request\n");
204 ok(feature == 0xdeadbeef, "expect feature 0xdeadbeef, got %u\n", feature);
205 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
207 feature = WINHTTP_ENABLE_SSL_REVOCATION;
208 SetLastError(0xdeadbeef);
209 ret = WinHttpSetOption(request, WINHTTP_OPTION_ENABLE_FEATURE, 0, sizeof(feature));
210 ok(!ret, "should fail to enable WINHTTP_ENABLE_SSL_REVOCATION with invalid parameters\n");
211 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
213 SetLastError(0xdeadbeef);
214 ret = WinHttpSetOption(request, WINHTTP_OPTION_ENABLE_FEATURE, &feature, 0);
215 ok(!ret, "should fail to enable WINHTTP_ENABLE_SSL_REVOCATION with invalid parameters\n");
216 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
218 SetLastError(0xdeadbeef);
219 ret = WinHttpSetOption(request, WINHTTP_OPTION_ENABLE_FEATURE, &feature, sizeof(feature));
220 ok(ret, "failed to set feature\n");
221 ok(GetLastError() == NO_ERROR || broken(GetLastError() == 0xdeadbeef), /* Doesn't set error code on Vista or older */
222 "expected NO_ERROR, got %u\n", GetLastError());
224 feature = 0xdeadbeef;
225 SetLastError(0xdeadbeef);
226 ret = WinHttpSetOption(request, WINHTTP_OPTION_ENABLE_FEATURE, &feature, sizeof(feature));
227 ok(!ret, "should fail to enable WINHTTP_ENABLE_SSL_REVOCATION with invalid parameters\n");
228 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
230 feature = 6;
231 size = sizeof(feature);
232 ret = WinHttpSetOption(request, WINHTTP_OPTION_CONNECT_RETRIES, &feature, sizeof(feature));
233 ok(ret, "failed to set WINHTTP_OPTION_CONNECT_RETRIES %u\n", GetLastError());
235 SetLastError(0xdeadbeef);
236 ret = WinHttpCloseHandle(request);
237 ok(ret, "WinHttpCloseHandle failed on closing request: %u\n", GetLastError());
239 done:
240 SetLastError(0xdeadbeef);
241 ret = WinHttpCloseHandle(connection);
242 ok(ret, "WinHttpCloseHandle failed on closing connection: %u\n", GetLastError());
243 SetLastError(0xdeadbeef);
244 ret = WinHttpCloseHandle(session);
245 ok(ret, "WinHttpCloseHandle failed on closing session: %u\n", GetLastError());
248 static void test_WinHttpOpenRequest (void)
250 BOOL ret;
251 HINTERNET session, request, connection;
252 DWORD err;
254 SetLastError(0xdeadbeef);
255 session = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
256 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
257 err = GetLastError();
258 ok(session != NULL, "WinHttpOpen failed to open session.\n");
259 ok(err == ERROR_SUCCESS, "got %u\n", err);
261 /* Test with a bad server name */
262 SetLastError(0xdeadbeef);
263 connection = WinHttpConnect(session, NULL, INTERNET_DEFAULT_HTTP_PORT, 0);
264 err = GetLastError();
265 ok (connection == NULL, "WinHttpConnect succeeded in opening connection to NULL server argument.\n");
266 ok(err == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u.\n", err);
268 /* Test with a valid server name */
269 SetLastError(0xdeadbeef);
270 connection = WinHttpConnect (session, L"test.winehq.org", INTERNET_DEFAULT_HTTP_PORT, 0);
271 err = GetLastError();
272 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", err);
273 ok(err == ERROR_SUCCESS || broken(err == WSAEINVAL) /* < win7 */, "got %u\n", err);
275 SetLastError(0xdeadbeef);
276 request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
277 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
278 err = GetLastError();
279 if (request == NULL && err == ERROR_WINHTTP_NAME_NOT_RESOLVED)
281 skip("Network unreachable, skipping.\n");
282 goto done;
284 ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", err);
285 ok(err == ERROR_SUCCESS, "got %u\n", err);
287 SetLastError(0xdeadbeef);
288 ret = WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, NULL, 0, 0, 0);
289 err = GetLastError();
290 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
292 skip("Connection failed, skipping.\n");
293 goto done;
295 ok(ret, "WinHttpSendRequest failed: %u\n", err);
296 ok(err == ERROR_SUCCESS, "got %u\n", err);
298 SetLastError(0xdeadbeef);
299 ret = WinHttpCloseHandle(request);
300 err = GetLastError();
301 ok(ret, "WinHttpCloseHandle failed on closing request, got %u.\n", err);
302 ok(err == ERROR_SUCCESS, "got %u\n", err);
304 done:
305 ret = WinHttpCloseHandle(connection);
306 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
307 ret = WinHttpCloseHandle(session);
308 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
312 static void test_empty_headers_param(void)
314 HINTERNET ses, con, req;
315 DWORD err;
316 BOOL ret;
318 ses = WinHttpOpen(L"winetest", 0, NULL, NULL, 0);
319 ok(ses != NULL, "failed to open session %u\n", GetLastError());
321 con = WinHttpConnect(ses, L"test.winehq.org", 80, 0);
322 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
324 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
325 ok(req != NULL, "failed to open a request %u\n", GetLastError());
327 ret = WinHttpSendRequest(req, L"", 0, NULL, 0, 0, 0);
328 err = GetLastError();
329 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
331 skip("connection failed, skipping\n");
332 goto done;
334 ok(ret, "failed to send request %u\n", GetLastError());
336 done:
337 WinHttpCloseHandle(req);
338 WinHttpCloseHandle(con);
339 WinHttpCloseHandle(ses);
342 static void test_WinHttpSendRequest (void)
344 static const WCHAR content_type[] = L"Content-Type: application/x-www-form-urlencoded";
345 static char post_data[] = "mode=Test";
346 static const char test_post[] = "mode => Test\0\n";
347 HINTERNET session, request, connection;
348 DWORD header_len, optional_len, total_len, bytes_rw, size, err, disable, len;
349 DWORD_PTR context;
350 BOOL ret;
351 CHAR buffer[256];
352 WCHAR method[8];
353 int i;
355 header_len = -1L;
356 total_len = optional_len = sizeof(post_data);
357 memset(buffer, 0xff, sizeof(buffer));
359 session = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
360 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
361 ok(session != NULL, "WinHttpOpen failed to open session.\n");
363 connection = WinHttpConnect (session, L"test.winehq.org", INTERNET_DEFAULT_HTTP_PORT, 0);
364 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
366 request = WinHttpOpenRequest(connection, L"POST", L"tests/post.php", NULL, WINHTTP_NO_REFERER,
367 WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
368 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
370 skip("Network unreachable, skipping.\n");
371 goto done;
373 ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError());
374 if (!request) goto done;
376 method[0] = 0;
377 len = sizeof(method);
378 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_REQUEST_METHOD, NULL, method, &len, NULL);
379 ok(ret, "got %u\n", GetLastError());
380 ok(len == lstrlenW(L"POST") * sizeof(WCHAR), "got %u\n", len);
381 ok(!lstrcmpW(method, L"POST"), "got %s\n", wine_dbgstr_w(method));
383 context = 0xdeadbeef;
384 ret = WinHttpSetOption(request, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(context));
385 ok(ret, "WinHttpSetOption failed: %u\n", GetLastError());
387 /* writing more data than promised by the content-length header causes an error when the connection
388 is reused, so disable keep-alive */
389 disable = WINHTTP_DISABLE_KEEP_ALIVE;
390 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &disable, sizeof(disable));
391 ok(ret, "WinHttpSetOption failed: %u\n", GetLastError());
393 context++;
394 ret = WinHttpSendRequest(request, content_type, header_len, post_data, optional_len, total_len, context);
395 err = GetLastError();
396 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
398 skip("connection failed, skipping\n");
399 goto done;
401 ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError());
403 context = 0;
404 size = sizeof(context);
405 ret = WinHttpQueryOption(request, WINHTTP_OPTION_CONTEXT_VALUE, &context, &size);
406 ok(ret, "WinHttpQueryOption failed: %u\n", GetLastError());
407 ok(context == 0xdeadbef0, "expected 0xdeadbef0, got %lx\n", context);
409 for (i = 3; post_data[i]; i++)
411 bytes_rw = -1;
412 SetLastError(0xdeadbeef);
413 ret = WinHttpWriteData(request, &post_data[i], 1, &bytes_rw);
414 if (ret)
416 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %u.\n", GetLastError());
417 ok(bytes_rw == 1, "WinHttpWriteData failed, wrote %u bytes instead of 1 byte.\n", bytes_rw);
419 else /* Since we already passed all optional data in WinHttpSendRequest Win7 fails our WinHttpWriteData call */
421 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER got %u.\n", GetLastError());
422 ok(bytes_rw == -1, "Expected bytes_rw to remain unchanged.\n");
426 SetLastError(0xdeadbeef);
427 ret = WinHttpReceiveResponse(request, NULL);
428 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == ERROR_NO_TOKEN) /* < win7 */,
429 "Expected ERROR_SUCCESS got %u.\n", GetLastError());
430 ok(ret == TRUE, "WinHttpReceiveResponse failed: %u.\n", GetLastError());
432 SetLastError(0xdeadbeef);
433 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_ORIG_URI, NULL, NULL, &len, NULL);
434 ok(!ret && GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", GetLastError());
436 SetLastError(0xdeadbeef);
437 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_MAX + 1, NULL, NULL, &len, NULL);
438 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %u\n", GetLastError());
440 bytes_rw = -1;
441 ret = WinHttpReadData(request, buffer, sizeof(buffer) - 1, &bytes_rw);
442 ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
444 ok(bytes_rw == sizeof(test_post) - 1, "Read %u bytes\n", bytes_rw);
445 ok(!memcmp(buffer, test_post, sizeof(test_post) - 1), "Data read did not match.\n");
447 done:
448 ret = WinHttpCloseHandle(request);
449 ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
450 ret = WinHttpCloseHandle(connection);
451 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
452 ret = WinHttpCloseHandle(session);
453 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
456 static void test_WinHttpTimeFromSystemTime(void)
458 BOOL ret;
459 static const SYSTEMTIME time = {2008, 7, 1, 28, 10, 5, 52, 0};
460 WCHAR time_string[WINHTTP_TIME_FORMAT_BUFSIZE+1];
461 DWORD err;
463 SetLastError(0xdeadbeef);
464 ret = WinHttpTimeFromSystemTime(&time, NULL);
465 err = GetLastError();
466 ok(!ret, "WinHttpTimeFromSystemTime succeeded\n");
467 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
469 SetLastError(0xdeadbeef);
470 ret = WinHttpTimeFromSystemTime(NULL, time_string);
471 err = GetLastError();
472 ok(!ret, "WinHttpTimeFromSystemTime succeeded\n");
473 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
475 SetLastError(0xdeadbeef);
476 ret = WinHttpTimeFromSystemTime(&time, time_string);
477 err = GetLastError();
478 ok(ret, "WinHttpTimeFromSystemTime failed: %u\n", err);
479 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
480 ok(!memcmp(time_string, L"Mon, 28 Jul 2008 10:05:52 GMT", sizeof(L"Mon, 28 Jul 2008 10:05:52 GMT")),
481 "Time string returned did not match expected time string.\n");
484 static void test_WinHttpTimeToSystemTime(void)
486 BOOL ret;
487 SYSTEMTIME time;
488 static const SYSTEMTIME expected_time = {2008, 7, 1, 28, 10, 5, 52, 0};
489 DWORD err;
491 SetLastError(0xdeadbeef);
492 ret = WinHttpTimeToSystemTime(L"Mon, 28 Jul 2008 10:05:52 GMT\n", NULL);
493 err = GetLastError();
494 ok(!ret, "WinHttpTimeToSystemTime succeeded\n");
495 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
497 SetLastError(0xdeadbeef);
498 ret = WinHttpTimeToSystemTime(NULL, &time);
499 err = GetLastError();
500 ok(!ret, "WinHttpTimeToSystemTime succeeded\n");
501 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
503 SetLastError(0xdeadbeef);
504 ret = WinHttpTimeToSystemTime(L"Mon, 28 Jul 2008 10:05:52 GMT\n", &time);
505 err = GetLastError();
506 ok(ret, "WinHttpTimeToSystemTime failed: %u\n", err);
507 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
508 ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
509 "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
511 SetLastError(0xdeadbeef);
512 ret = WinHttpTimeToSystemTime(L" mon 28 jul 2008 10 05 52\n", &time);
513 err = GetLastError();
514 ok(ret, "WinHttpTimeToSystemTime failed: %u\n", err);
515 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
516 ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
517 "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
520 static void test_WinHttpAddHeaders(void)
522 static const WCHAR test_header_begin[] =
523 {'P','O','S','T',' ','/','p','o','s','t','t','e','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
524 HINTERNET session, request, connection;
525 BOOL ret, reverse;
526 WCHAR buffer[MAX_PATH];
527 WCHAR check_buffer[MAX_PATH];
528 DWORD err, index, len, oldlen;
530 static const WCHAR test_headers[][14] =
532 L"Warning:test1",
533 L"Warning:test2",
534 L"Warning:test3",
535 L"Warning:test4",
536 L"Warning:test5",
537 L"Warning:test6",
538 L"Warning:test7",
539 L"",
540 L":",
541 L"a:",
542 L":b",
543 L"cd",
544 L" e :f",
545 L"field: value ",
546 L"name: value",
547 L"name:",
549 static const WCHAR test_indices[][6] =
551 L"test1",
552 L"test2",
553 L"test3",
554 L"test4",
557 session = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
558 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
559 ok(session != NULL, "WinHttpOpen failed to open session.\n");
561 connection = WinHttpConnect (session, L"test.winehq.org", INTERNET_DEFAULT_HTTP_PORT, 0);
562 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
564 request = WinHttpOpenRequest(connection, L"POST", L"/posttest.php", NULL, WINHTTP_NO_REFERER,
565 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
566 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
568 skip("Network unreachable, skipping.\n");
569 goto done;
571 ok(request != NULL, "WinHttpOpenRequest failed to open a request, error: %u.\n", GetLastError());
573 index = 0;
574 len = sizeof(buffer);
575 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
576 L"Warning", buffer, &len, &index);
577 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, found 'Warning' header.\n");
578 SetLastError(0xdeadbeef);
579 ret = WinHttpAddRequestHeaders(request, test_headers[0], -1L, WINHTTP_ADDREQ_FLAG_ADD);
580 err = GetLastError();
581 ok(ret, "WinHttpAddRequestHeaders failed to add new header, got %d with error %u.\n", ret, err);
582 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
584 index = 0;
585 len = sizeof(buffer);
586 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
587 L"Warning", buffer, &len, &index);
588 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
589 ok(index == 1, "WinHttpQueryHeaders failed: header index not incremented\n");
590 ok(!memcmp(buffer, test_indices[0], sizeof(test_indices[0])),
591 "WinHttpQueryHeaders failed: incorrect string returned\n");
592 ok(len == 5*sizeof(WCHAR), "WinHttpQueryHeaders failed: invalid length returned, expected 5, got %d\n", len);
594 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
595 L"Warning", buffer, &len, &index);
596 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, second index should not exist.\n");
598 /* Try to fetch the header info with a buffer that's big enough to fit the
599 * string but not the NULL terminator.
601 index = 0;
602 len = 5*sizeof(WCHAR);
603 memset(check_buffer, 0xab, sizeof(check_buffer));
604 memcpy(buffer, check_buffer, sizeof(buffer));
605 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
606 L"Warning", buffer, &len, &index);
607 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded with a buffer that's too small.\n");
608 ok(memcmp(buffer, check_buffer, sizeof(buffer)) == 0,
609 "WinHttpQueryHeaders failed, modified the buffer when it should not have.\n");
610 ok(len == 6*sizeof(WCHAR), "WinHttpQueryHeaders returned invalid length, expected 12, got %d\n", len);
612 /* Try with a NULL buffer */
613 index = 0;
614 len = sizeof(buffer);
615 SetLastError(0xdeadbeef);
616 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
617 L"Warning", NULL, &len, &index);
618 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
619 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
620 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
621 ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
623 /* Try with a NULL buffer and a length that's too small */
624 index = 0;
625 len = 10;
626 SetLastError(0xdeadbeef);
627 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
628 L"Warning", NULL, &len, &index);
629 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
630 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
631 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
632 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
633 ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
635 index = 0;
636 len = 0;
637 SetLastError(0xdeadbeef);
638 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
639 L"Warning", NULL, &len, &index);
640 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
641 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
642 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
643 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
644 ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
646 /* valid query */
647 oldlen = len;
648 index = 0;
649 len = sizeof(buffer);
650 memset(buffer, 0xff, sizeof(buffer));
651 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
652 L"Warning", buffer, &len, &index);
653 ok(ret == TRUE, "WinHttpQueryHeaders failed: got %d\n", ret);
654 ok(len + sizeof(WCHAR) <= oldlen, "WinHttpQueryHeaders resulting length longer than advertized.\n");
655 ok((len < sizeof(buffer) - sizeof(WCHAR)) && !buffer[len / sizeof(WCHAR)],
656 "WinHttpQueryHeaders did not append NULL terminator\n");
657 ok(len == lstrlenW(buffer) * sizeof(WCHAR), "WinHttpQueryHeaders returned incorrect length.\n");
658 ok(!memcmp(buffer, test_header_begin, sizeof(test_header_begin)), "invalid beginning of header string.\n");
659 ok(!memcmp(buffer + lstrlenW(buffer) - 4, L"\r\n\r\n", sizeof(L"\r\n\r\n")),
660 "WinHttpQueryHeaders returned invalid end of header string.\n");
661 ok(index == 0, "WinHttpQueryHeaders incremented header index.\n");
663 index = 0;
664 len = 0;
665 SetLastError(0xdeadbeef);
666 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
667 L"Warning", NULL, &len, &index);
668 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
669 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
670 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
671 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
672 ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
674 oldlen = len;
675 index = 0;
676 len = sizeof(buffer);
677 memset(buffer, 0xff, sizeof(buffer));
678 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
679 L"Warning", buffer, &len, &index);
680 ok(ret == TRUE, "WinHttpQueryHeaders failed %u\n", GetLastError());
681 ok(len + sizeof(WCHAR) <= oldlen, "resulting length longer than advertized\n");
682 ok((len < sizeof(buffer) - sizeof(WCHAR)) && !buffer[len / sizeof(WCHAR)] && !buffer[len / sizeof(WCHAR) - 1],
683 "no double NULL terminator\n");
684 ok(!memcmp(buffer, test_header_begin, sizeof(test_header_begin)), "invalid beginning of header string.\n");
685 ok(index == 0, "header index was incremented\n");
687 /* tests for more indices */
688 ret = WinHttpAddRequestHeaders(request, test_headers[1], -1L, WINHTTP_ADDREQ_FLAG_ADD);
689 ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header: %d\n", ret);
691 index = 0;
692 len = sizeof(buffer);
693 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
694 L"Warning", buffer, &len, &index);
695 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
696 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
697 ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
699 len = sizeof(buffer);
700 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
701 L"Warning", buffer, &len, &index);
702 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
703 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
704 ok(memcmp(buffer, test_indices[1], sizeof(test_indices[1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
706 ret = WinHttpAddRequestHeaders(request, test_headers[2], -1L, WINHTTP_ADDREQ_FLAG_REPLACE);
707 ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header.\n");
709 index = 0;
710 len = sizeof(buffer);
711 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
712 L"Warning", buffer, &len, &index);
713 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
714 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
715 reverse = (memcmp(buffer, test_indices[1], sizeof(test_indices[1])) != 0); /* Win7 returns values in reverse order of adding */
716 ok(!memcmp(buffer, test_indices[reverse ? 2 : 1], sizeof(test_indices[reverse ? 2 : 1])),
717 "WinHttpQueryHeaders returned incorrect string.\n");
719 len = sizeof(buffer);
720 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
721 L"Warning", buffer, &len, &index);
722 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
723 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
724 ok(!memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])),
725 "WinHttpQueryHeaders returned incorrect string.\n");
727 /* add if new flag */
728 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW);
729 ok(ret == FALSE, "WinHttpAddRequestHeaders incorrectly replaced existing header.\n");
731 index = 0;
732 len = sizeof(buffer);
733 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
734 L"Warning", buffer, &len, &index);
735 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
736 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
737 ok(!memcmp(buffer, test_indices[reverse ? 2 : 1], sizeof(test_indices[reverse ? 2 : 1])),
738 "WinHttpQueryHeaders returned incorrect string.\n");
740 len = sizeof(buffer);
741 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
742 L"Warning", buffer, &len, &index);
743 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
744 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
745 ok(!memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])),
746 "WinHttpQueryHeaders returned incorrect string.\n");
748 len = sizeof(buffer);
749 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
750 L"Warning", buffer, &len, &index);
751 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
753 /* coalesce flag */
754 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_COALESCE);
755 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE.\n");
757 index = 0;
758 len = sizeof(buffer);
759 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
760 L"Warning", buffer, &len, &index);
761 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
762 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
763 ok(!memcmp(buffer, reverse ? L"test3, test4" : L"test2, test4",
764 reverse ? sizeof(L"test3, test4") : sizeof(L"test2, test4")),
765 "WinHttpQueryHeaders returned incorrect string.\n");
767 len = sizeof(buffer);
768 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
769 L"Warning", buffer, &len, &index);
770 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
771 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
772 ok(!memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])),
773 "WinHttpQueryHeaders returned incorrect string.\n");
775 len = sizeof(buffer);
776 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
777 L"Warning", buffer, &len, &index);
778 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
780 /* coalesce with comma flag */
781 ret = WinHttpAddRequestHeaders(request, test_headers[4], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA);
782 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA.\n");
784 index = 0;
785 len = sizeof(buffer);
786 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
787 L"Warning", buffer, &len, &index);
788 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
789 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
791 ok(!memcmp(buffer, reverse ? L"test3, test4, test5" : L"test2, test4, test5",
792 reverse ? sizeof(L"test3, test4, test5") : sizeof(L"test2, test4, test5")),
793 "WinHttpQueryHeaders returned incorrect string.\n");
795 len = sizeof(buffer);
796 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
797 L"Warning", buffer, &len, &index);
798 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
799 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
800 ok(!memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])),
801 "WinHttpQueryHeaders returned incorrect string.\n");
803 len = sizeof(buffer);
804 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
805 L"Warning", buffer, &len, &index);
806 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
809 /* coalesce with semicolon flag */
810 ret = WinHttpAddRequestHeaders(request, test_headers[5], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON);
811 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON.\n");
813 index = 0;
814 len = sizeof(buffer);
815 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
816 L"Warning", buffer, &len, &index);
817 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
818 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
820 ok(!memcmp(buffer, reverse ? L"test3, test4, test5; test6" : L"test2, test4, test5; test6",
821 reverse ? sizeof(L"test3, test4, test5; test6") : sizeof(L"test2, test4, test5; test6")),
822 "WinHttpQueryHeaders returned incorrect string.\n");
824 len = sizeof(buffer);
825 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
826 L"Warning", buffer, &len, &index);
827 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
828 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
829 ok(!memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])),
830 "WinHttpQueryHeaders returned incorrect string.\n");
832 len = sizeof(buffer);
833 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
834 L"Warning", buffer, &len, &index);
835 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
837 /* add and replace flags */
838 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
839 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE.\n");
841 index = 0;
842 len = sizeof(buffer);
843 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
844 L"Warning", buffer, &len, &index);
845 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
846 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
847 ok(!memcmp(buffer, test_indices[reverse ? 3 : 2], sizeof(test_indices[reverse ? 3 : 2])),
848 "WinHttpQueryHeaders returned incorrect string.\n");
850 len = sizeof(buffer);
851 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
852 L"Warning", buffer, &len, &index);
853 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
854 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
855 ok(!memcmp(buffer, test_indices[reverse ? 1 : 3], sizeof(test_indices[reverse ? 1 : 3])),
856 "WinHttpQueryHeaders returned incorrect string.\n");
858 len = sizeof(buffer);
859 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
860 L"Warning", buffer, &len, &index);
861 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
863 ret = WinHttpAddRequestHeaders(request, test_headers[8], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
864 ok(!ret, "WinHttpAddRequestHeaders failed\n");
866 ret = WinHttpAddRequestHeaders(request, test_headers[9], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
867 ok(ret, "WinHttpAddRequestHeaders failed\n");
869 index = 0;
870 memset(buffer, 0xff, sizeof(buffer));
871 len = sizeof(buffer);
872 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
873 L"a", buffer, &len, &index);
874 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
875 ok(!memcmp(buffer, L"", sizeof(L"")), "unexpected result\n");
877 ret = WinHttpAddRequestHeaders(request, test_headers[10], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
878 ok(!ret, "WinHttpAddRequestHeaders failed\n");
880 ret = WinHttpAddRequestHeaders(request, test_headers[11], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
881 ok(!ret, "WinHttpAddRequestHeaders failed\n");
883 ret = WinHttpAddRequestHeaders(request, test_headers[12], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
884 ok(!ret, "WinHttpAddRequestHeaders failed\n");
886 ret = WinHttpAddRequestHeaders(request, test_headers[13], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
887 ok(ret, "WinHttpAddRequestHeaders failed\n");
889 index = 0;
890 buffer[0] = 0;
891 len = sizeof(buffer);
892 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
893 L"field", buffer, &len, &index);
894 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
895 ok(!memcmp(buffer, L"value ", sizeof(L"value ")) || !memcmp(buffer, L"value", sizeof(L"value")),
896 "unexpected result\n");
898 SetLastError(0xdeadbeef);
899 ret = WinHttpAddRequestHeaders(request, L"Range: bytes=0-773\r\n", 0,
900 WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
901 err = GetLastError();
902 ok(!ret, "unexpected success\n");
903 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
905 ret = WinHttpAddRequestHeaders(request, L"Range: bytes=0-773\r\n", ~0u,
906 WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
907 ok(ret, "failed to add header: %u\n", GetLastError());
909 index = 0;
910 len = sizeof(buffer);
911 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
912 L"Range", buffer, &len, &index);
913 ok(ret, "failed to get range header %u\n", GetLastError());
914 ok(!memcmp(buffer, L"bytes=0-773", sizeof(L"bytes=0-773")), "incorrect string returned\n");
915 ok(len == lstrlenW(L"bytes=0-773") * sizeof(WCHAR), "wrong length %u\n", len);
916 ok(index == 1, "wrong index %u\n", index);
917 index = 0;
918 len = sizeof(buffer);
919 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
920 L"name", buffer, &len, &index);
921 ok(!ret, "unexpected success\n");
923 SetLastError(0xdeadbeef);
924 ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
925 err = GetLastError();
926 ok(!ret, "unexpected success\n");
927 ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
929 ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
930 ok(ret, "got %u\n", GetLastError());
932 index = 0;
933 len = sizeof(buffer);
934 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
935 L"name", buffer, &len, &index);
936 ok(ret, "got %u\n", GetLastError());
937 ok(index == 1, "wrong index %u\n", index);
938 ok(!memcmp(buffer, L"value", sizeof(L"value")), "incorrect string\n");
940 ret = WinHttpAddRequestHeaders(request, test_headers[15], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
941 ok(ret, "got %u\n", GetLastError());
943 index = 0;
944 len = sizeof(buffer);
945 SetLastError(0xdeadbeef);
946 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
947 L"name", buffer, &len, &index);
948 err = GetLastError();
949 ok(!ret, "unexpected success\n");
950 ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
952 ret = WinHttpAddRequestHeaders(request, test_headers[14], -1L, 0);
953 ok(ret, "got %u\n", GetLastError());
955 index = 0;
956 len = sizeof(buffer);
957 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
958 L"name", buffer, &len, &index);
959 ok(ret, "got %u\n", GetLastError());
960 ok(index == 1, "wrong index %u\n", index);
961 ok(!memcmp(buffer, L"value", sizeof(L"value")), "incorrect string\n");
963 ret = WinHttpCloseHandle(request);
964 ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
965 done:
966 ret = WinHttpCloseHandle(connection);
967 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
968 ret = WinHttpCloseHandle(session);
969 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
973 static void CALLBACK cert_error(HINTERNET handle, DWORD_PTR ctx, DWORD status, LPVOID buf, DWORD len)
975 DWORD flags = *(DWORD *)buf;
977 if (!flags)
979 trace("WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR\n");
980 return;
982 #define X(x) if (flags & x) trace("%s\n", #x);
983 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED)
984 X(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT)
985 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED)
986 X(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA)
987 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID)
988 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID)
989 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE)
990 #undef X
993 static void test_secure_connection(void)
995 static const char data_start[] = "<!DOCTYPE html PUBLIC";
996 HINTERNET ses, con, req;
997 DWORD size, status, policy, bitness, read_size, err, available_size, protocols, flags;
998 BOOL ret;
999 CERT_CONTEXT *cert;
1000 WINHTTP_CERTIFICATE_INFO info;
1001 char buffer[32];
1003 ses = WinHttpOpen(L"winetest", 0, NULL, NULL, 0);
1004 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1006 policy = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
1007 ret = WinHttpSetOption(ses, WINHTTP_OPTION_REDIRECT_POLICY, &policy, sizeof(policy));
1008 ok(ret, "failed to set redirect policy %u\n", GetLastError());
1010 protocols = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;
1011 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SECURE_PROTOCOLS, &protocols, sizeof(protocols));
1012 err = GetLastError();
1013 ok(ret || err == ERROR_INVALID_PARAMETER /* < win7 */, "failed to set protocols %u\n", err);
1015 con = WinHttpConnect(ses, L"test.winehq.org", 443, 0);
1016 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1018 SetLastError( 0xdeadbeef );
1019 protocols = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;
1020 ret = WinHttpSetOption(con, WINHTTP_OPTION_SECURE_PROTOCOLS, &protocols, sizeof(protocols));
1021 err = GetLastError();
1022 ok(!ret, "unexpected success\n");
1023 ok(err == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, "got %u\n", err);
1025 /* try without setting WINHTTP_FLAG_SECURE */
1026 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1027 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1029 ret = WinHttpSetOption(req, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0);
1030 err = GetLastError();
1031 ok(!ret, "unexpected success\n");
1032 ok(err == ERROR_WINHTTP_INCORRECT_HANDLE_STATE || broken(err == ERROR_INVALID_PARAMETER) /* winxp */,
1033 "setting client cert context returned %u\n", err);
1035 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1036 err = GetLastError();
1037 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
1039 skip("Connection failed, skipping.\n");
1040 goto cleanup;
1042 ok(ret, "failed to send request %u\n", GetLastError());
1044 ret = WinHttpReceiveResponse(req, NULL);
1045 ok(ret, "failed to receive response %u\n", GetLastError());
1047 status = 0xdeadbeef;
1048 size = sizeof(status);
1049 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1050 ok(ret, "header query failed %u\n", GetLastError());
1051 ok(status == HTTP_STATUS_BAD_REQUEST, "got %u\n", status);
1053 WinHttpCloseHandle(req);
1055 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, WINHTTP_FLAG_SECURE);
1056 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1058 flags = 0xdeadbeef;
1059 size = sizeof(flags);
1060 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, &size);
1061 ok(ret, "failed to query security flags %u\n", GetLastError());
1062 ok(!flags, "got %08x\n", flags);
1064 flags = SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE;
1065 ret = WinHttpSetOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
1066 ok(ret, "failed to set security flags %u\n", GetLastError());
1068 flags = SECURITY_FLAG_SECURE;
1069 ret = WinHttpSetOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
1070 ok(!ret, "success\n");
1072 flags = SECURITY_FLAG_STRENGTH_STRONG;
1073 ret = WinHttpSetOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
1074 ok(!ret, "success\n");
1076 flags = SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
1077 SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
1078 ret = WinHttpSetOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
1079 ok(ret, "failed to set security flags %u\n", GetLastError());
1081 flags = 0;
1082 ret = WinHttpSetOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
1083 ok(ret, "failed to set security flags %u\n", GetLastError());
1085 ret = WinHttpSetOption(req, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0);
1086 err = GetLastError();
1087 ok(ret || broken(!ret && err == ERROR_INVALID_PARAMETER) /* winxp */, "failed to set client cert context %u\n", err);
1089 WinHttpSetStatusCallback(req, cert_error, WINHTTP_CALLBACK_STATUS_SECURE_FAILURE, 0);
1091 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1092 err = GetLastError();
1093 if (!ret && (err == ERROR_WINHTTP_SECURE_FAILURE || err == ERROR_WINHTTP_CANNOT_CONNECT ||
1094 err == ERROR_WINHTTP_TIMEOUT || err == SEC_E_ILLEGAL_MESSAGE))
1096 skip("secure connection failed, skipping remaining secure tests\n");
1097 goto cleanup;
1099 ok(ret, "failed to send request %u\n", GetLastError());
1101 size = sizeof(cert);
1102 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert, &size );
1103 ok(ret, "failed to retrieve certificate context %u\n", GetLastError());
1104 if (ret) CertFreeCertificateContext(cert);
1106 size = sizeof(bitness);
1107 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_KEY_BITNESS, &bitness, &size );
1108 ok(ret, "failed to retrieve key bitness %u\n", GetLastError());
1110 size = sizeof(info);
1111 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT, &info, &size );
1112 ok(ret, "failed to retrieve certificate info %u\n", GetLastError());
1114 if (ret)
1116 trace("lpszSubjectInfo %s\n", wine_dbgstr_w(info.lpszSubjectInfo));
1117 trace("lpszIssuerInfo %s\n", wine_dbgstr_w(info.lpszIssuerInfo));
1118 trace("lpszProtocolName %s\n", wine_dbgstr_w(info.lpszProtocolName));
1119 trace("lpszSignatureAlgName %s\n", wine_dbgstr_w(info.lpszSignatureAlgName));
1120 trace("lpszEncryptionAlgName %s\n", wine_dbgstr_w(info.lpszEncryptionAlgName));
1121 trace("dwKeySize %u\n", info.dwKeySize);
1122 LocalFree( info.lpszSubjectInfo );
1123 LocalFree( info.lpszIssuerInfo );
1126 ret = WinHttpReceiveResponse(req, NULL);
1127 if (!ret && GetLastError() == ERROR_WINHTTP_CONNECTION_ERROR)
1129 skip("connection error, skipping remaining secure tests\n");
1130 goto cleanup;
1132 ok(ret, "failed to receive response %u\n", GetLastError());
1134 available_size = 0;
1135 ret = WinHttpQueryDataAvailable(req, &available_size);
1136 ok(ret, "failed to query available data %u\n", GetLastError());
1137 ok(available_size > 2014, "available_size = %u\n", available_size);
1139 status = 0xdeadbeef;
1140 size = sizeof(status);
1141 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1142 ok(ret, "failed unexpectedly %u\n", GetLastError());
1143 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1145 size = 0;
1146 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL);
1147 ok(!ret, "succeeded unexpectedly\n");
1149 read_size = 0;
1150 for (;;)
1152 size = 0;
1153 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
1154 ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
1155 if (!size) break;
1156 read_size += size;
1158 if (read_size <= 32)
1159 ok(!memcmp(buffer, data_start, sizeof(data_start)-1), "not expected: %.32s\n", buffer);
1161 ok(read_size >= available_size, "read_size = %u, available_size = %u\n", read_size, available_size);
1163 size = sizeof(cert);
1164 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert, &size);
1165 ok(ret, "failed to retrieve certificate context %u\n", GetLastError());
1166 if (ret) CertFreeCertificateContext(cert);
1168 cleanup:
1169 WinHttpCloseHandle(req);
1170 WinHttpCloseHandle(con);
1171 WinHttpCloseHandle(ses);
1174 static void test_request_parameter_defaults(void)
1176 HINTERNET ses, con, req;
1177 DWORD size, status, error;
1178 WCHAR *version;
1179 BOOL ret;
1181 ses = WinHttpOpen(L"winetest", 0, NULL, NULL, 0);
1182 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1184 con = WinHttpConnect(ses, L"test.winehq.org", 0, 0);
1185 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1187 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1188 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1190 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1191 error = GetLastError();
1192 if (!ret && (error == ERROR_WINHTTP_CANNOT_CONNECT || error == ERROR_WINHTTP_TIMEOUT))
1194 skip("connection failed, skipping\n");
1195 goto done;
1197 ok(ret, "failed to send request %u\n", GetLastError());
1199 ret = WinHttpReceiveResponse(req, NULL);
1200 ok(ret, "failed to receive response %u\n", GetLastError());
1202 status = 0xdeadbeef;
1203 size = sizeof(status);
1204 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1205 ok(ret, "failed unexpectedly %u\n", GetLastError());
1206 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1208 WinHttpCloseHandle(req);
1210 req = WinHttpOpenRequest(con, L"", L"", L"", NULL, NULL, 0);
1211 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1213 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1214 error = GetLastError();
1215 if (!ret && (error == ERROR_WINHTTP_CANNOT_CONNECT || error == ERROR_WINHTTP_TIMEOUT))
1217 skip("connection failed, skipping\n");
1218 goto done;
1220 ok(ret, "failed to send request %u\n", GetLastError());
1222 ret = WinHttpReceiveResponse(req, NULL);
1223 ok(ret, "failed to receive response %u\n", GetLastError());
1225 size = 0;
1226 SetLastError(0xdeadbeef);
1227 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, NULL, &size, NULL);
1228 error = GetLastError();
1229 ok(!ret, "succeeded unexpectedly\n");
1230 ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error);
1232 version = HeapAlloc(GetProcessHeap(), 0, size);
1233 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, version, &size, NULL);
1234 ok(ret, "failed unexpectedly %u\n", GetLastError());
1235 ok(lstrlenW(version) == size / sizeof(WCHAR), "unexpected size %u\n", size);
1236 HeapFree(GetProcessHeap(), 0, version);
1238 status = 0xdeadbeef;
1239 size = sizeof(status);
1240 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1241 ok(ret, "failed unexpectedly %u\n", GetLastError());
1242 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1244 done:
1245 WinHttpCloseHandle(req);
1246 WinHttpCloseHandle(con);
1247 WinHttpCloseHandle(ses);
1250 static const WCHAR Connections[] = {
1251 'S','o','f','t','w','a','r','e','\\',
1252 'M','i','c','r','o','s','o','f','t','\\',
1253 'W','i','n','d','o','w','s','\\',
1254 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1255 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
1256 'C','o','n','n','e','c','t','i','o','n','s',0 };
1257 static const WCHAR WinHttpSettings[] = {
1258 'W','i','n','H','t','t','p','S','e','t','t','i','n','g','s',0 };
1260 static DWORD get_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD *type )
1262 LONG l;
1263 HKEY key;
1264 DWORD ret = 0;
1266 l = RegOpenKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, KEY_READ, &key );
1267 if (!l)
1269 DWORD size = 0;
1271 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, NULL, &size );
1272 if (!l)
1274 if (size <= len)
1275 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, buf,
1276 &size );
1277 if (!l)
1278 ret = size;
1280 RegCloseKey( key );
1282 return ret;
1285 static void set_proxy( REGSAM access, BYTE *buf, DWORD len, DWORD type )
1287 HKEY hkey;
1288 if (!RegCreateKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, NULL, 0, access, NULL, &hkey, NULL ))
1290 if (len) RegSetValueExW( hkey, WinHttpSettings, 0, type, buf, len );
1291 else RegDeleteValueW( hkey, WinHttpSettings );
1292 RegCloseKey( hkey );
1296 static void set_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD type )
1298 BOOL wow64;
1299 IsWow64Process( GetCurrentProcess(), &wow64 );
1300 if (sizeof(void *) > sizeof(int) || wow64)
1302 set_proxy( KEY_WRITE|KEY_WOW64_64KEY, buf, len, type );
1303 set_proxy( KEY_WRITE|KEY_WOW64_32KEY, buf, len, type );
1305 else
1306 set_proxy( KEY_WRITE, buf, len, type );
1309 static void test_set_default_proxy_config(void)
1311 static WCHAR wideString[] = { 0x226f, 0x575b, 0 };
1312 static WCHAR normalString[] = { 'f','o','o',0 };
1313 DWORD type, len;
1314 BYTE *saved_proxy_settings = NULL;
1315 WINHTTP_PROXY_INFO info;
1316 BOOL ret;
1318 /* FIXME: it would be simpler to read the current settings using
1319 * WinHttpGetDefaultProxyConfiguration and save them using
1320 * WinHttpSetDefaultProxyConfiguration, but they appear to have a bug.
1322 * If a proxy is configured in the registry, e.g. via 'proxcfg -p "foo"',
1323 * the access type reported by WinHttpGetDefaultProxyConfiguration is 1,
1324 * WINHTTP_ACCESS_TYPE_NO_PROXY, whereas it should be
1325 * WINHTTP_ACCESS_TYPE_NAMED_PROXY.
1326 * If WinHttpSetDefaultProxyConfiguration is called with dwAccessType = 1,
1327 * the lpszProxy and lpszProxyBypass values are ignored.
1328 * Thus, if a proxy is set with proxycfg, then calling
1329 * WinHttpGetDefaultProxyConfiguration followed by
1330 * WinHttpSetDefaultProxyConfiguration results in the proxy settings
1331 * getting deleted from the registry.
1333 * Instead I read the current registry value and restore it directly.
1335 len = get_default_proxy_reg_value( NULL, 0, &type );
1336 if (len)
1338 saved_proxy_settings = HeapAlloc( GetProcessHeap(), 0, len );
1339 len = get_default_proxy_reg_value( saved_proxy_settings, len, &type );
1342 if (0)
1344 /* Crashes on Vista and higher */
1345 SetLastError(0xdeadbeef);
1346 ret = WinHttpSetDefaultProxyConfiguration(NULL);
1347 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1348 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1351 /* test with invalid access type */
1352 info.dwAccessType = 0xdeadbeef;
1353 info.lpszProxy = info.lpszProxyBypass = NULL;
1354 SetLastError(0xdeadbeef);
1355 ret = WinHttpSetDefaultProxyConfiguration(&info);
1356 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1357 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1359 /* at a minimum, the proxy server must be set */
1360 info.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
1361 info.lpszProxy = info.lpszProxyBypass = NULL;
1362 SetLastError(0xdeadbeef);
1363 ret = WinHttpSetDefaultProxyConfiguration(&info);
1364 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1365 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1366 info.lpszProxyBypass = normalString;
1367 SetLastError(0xdeadbeef);
1368 ret = WinHttpSetDefaultProxyConfiguration(&info);
1369 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1370 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1372 /* the proxy server can't have wide characters */
1373 info.lpszProxy = wideString;
1374 SetLastError(0xdeadbeef);
1375 ret = WinHttpSetDefaultProxyConfiguration(&info);
1376 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1377 skip("couldn't set default proxy configuration: access denied\n");
1378 else
1379 ok((!ret && GetLastError() == ERROR_INVALID_PARAMETER) ||
1380 broken(ret), /* Earlier winhttp versions on W2K/XP */
1381 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1383 info.lpszProxy = normalString;
1384 SetLastError(0xdeadbeef);
1385 ret = WinHttpSetDefaultProxyConfiguration(&info);
1386 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1387 skip("couldn't set default proxy configuration: access denied\n");
1388 else
1390 ok(ret, "WinHttpSetDefaultProxyConfiguration failed: %u\n", GetLastError());
1391 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
1392 "got %u\n", GetLastError());
1394 set_default_proxy_reg_value( saved_proxy_settings, len, type );
1397 static void test_timeouts(void)
1399 BOOL ret;
1400 DWORD value, size;
1401 HINTERNET ses, req, con;
1403 ses = WinHttpOpen(L"winetest", 0, NULL, NULL, 0);
1404 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1406 SetLastError(0xdeadbeef);
1407 ret = WinHttpSetTimeouts(ses, -2, 0, 0, 0);
1408 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1409 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1411 SetLastError(0xdeadbeef);
1412 ret = WinHttpSetTimeouts(ses, 0, -2, 0, 0);
1413 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1414 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1416 SetLastError(0xdeadbeef);
1417 ret = WinHttpSetTimeouts(ses, 0, 0, -2, 0);
1418 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1419 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1421 SetLastError(0xdeadbeef);
1422 ret = WinHttpSetTimeouts(ses, 0, 0, 0, -2);
1423 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1424 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1426 SetLastError(0xdeadbeef);
1427 ret = WinHttpSetTimeouts(ses, -1, -1, -1, -1);
1428 ok(ret, "%u\n", GetLastError());
1429 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
1430 "expected ERROR_SUCCESS, got %u\n", GetLastError());
1432 SetLastError(0xdeadbeef);
1433 ret = WinHttpSetTimeouts(ses, 0, 0, 0, 0);
1434 ok(ret, "%u\n", GetLastError());
1436 SetLastError(0xdeadbeef);
1437 ret = WinHttpSetTimeouts(ses, 0x0123, 0x4567, 0x89ab, 0xcdef);
1438 ok(ret, "%u\n", GetLastError());
1440 SetLastError(0xdeadbeef);
1441 value = 0xdeadbeef;
1442 size = sizeof(DWORD);
1443 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1444 ok(ret, "%u\n", GetLastError());
1445 ok(value == 0x0123, "Expected 0x0123, got %u\n", value);
1447 SetLastError(0xdeadbeef);
1448 value = 0xdeadbeef;
1449 size = sizeof(DWORD);
1450 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1451 ok(ret, "%u\n", GetLastError());
1452 ok(value == 0x4567, "Expected 0x4567, got %u\n", value);
1454 SetLastError(0xdeadbeef);
1455 value = 0xdeadbeef;
1456 size = sizeof(DWORD);
1457 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1458 ok(ret, "%u\n", GetLastError());
1459 ok(value == 0x89ab, "Expected 0x89ab, got %u\n", value);
1461 SetLastError(0xdeadbeef);
1462 value = 0xdeadbeef;
1463 size = sizeof(DWORD);
1464 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1465 ok(ret, "%u\n", GetLastError());
1466 ok(value == 0xcdef, "Expected 0xcdef, got %u\n", value);
1468 SetLastError(0xdeadbeef);
1469 value = 0;
1470 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1471 ok(ret, "%u\n", GetLastError());
1473 SetLastError(0xdeadbeef);
1474 value = 0xdeadbeef;
1475 size = sizeof(DWORD);
1476 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1477 ok(ret, "%u\n", GetLastError());
1478 ok(value == 0, "Expected 0, got %u\n", value);
1480 SetLastError(0xdeadbeef);
1481 value = 0;
1482 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1483 ok(ret, "%u\n", GetLastError());
1485 SetLastError(0xdeadbeef);
1486 value = 0xdeadbeef;
1487 size = sizeof(DWORD);
1488 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1489 ok(ret, "%u\n", GetLastError());
1490 ok(value == 0, "Expected 0, got %u\n", value);
1492 SetLastError(0xdeadbeef);
1493 value = 0;
1494 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1495 ok(ret, "%u\n", GetLastError());
1497 SetLastError(0xdeadbeef);
1498 value = 0xdeadbeef;
1499 size = sizeof(DWORD);
1500 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1501 ok(ret, "%u\n", GetLastError());
1502 ok(value == 0, "Expected 0, got %u\n", value);
1504 SetLastError(0xdeadbeef);
1505 value = 0;
1506 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1507 ok(ret, "%u\n", GetLastError());
1509 SetLastError(0xdeadbeef);
1510 value = 0xdeadbeef;
1511 size = sizeof(DWORD);
1512 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1513 ok(ret, "%u\n", GetLastError());
1514 ok(value == 0, "Expected 0, got %u\n", value);
1516 SetLastError(0xdeadbeef);
1517 value = 0xbeefdead;
1518 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1519 ok(ret, "%u\n", GetLastError());
1521 SetLastError(0xdeadbeef);
1522 value = 0xdeadbeef;
1523 size = sizeof(DWORD);
1524 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1525 ok(ret, "%u\n", GetLastError());
1526 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1528 SetLastError(0xdeadbeef);
1529 value = 0xbeefdead;
1530 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1531 ok(ret, "%u\n", GetLastError());
1533 SetLastError(0xdeadbeef);
1534 value = 0xdeadbeef;
1535 size = sizeof(DWORD);
1536 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1537 ok(ret, "%u\n", GetLastError());
1538 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1540 SetLastError(0xdeadbeef);
1541 value = 0xbeefdead;
1542 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1543 ok(ret, "%u\n", GetLastError());
1545 SetLastError(0xdeadbeef);
1546 value = 0xdeadbeef;
1547 size = sizeof(DWORD);
1548 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1549 ok(ret, "%u\n", GetLastError());
1550 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1552 SetLastError(0xdeadbeef);
1553 value = 0xbeefdead;
1554 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1555 ok(ret, "%u\n", GetLastError());
1557 SetLastError(0xdeadbeef);
1558 value = 0xdeadbeef;
1559 size = sizeof(DWORD);
1560 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1561 ok(ret, "%u\n", GetLastError());
1562 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1564 con = WinHttpConnect(ses, L"test.winehq.org", 0, 0);
1565 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1567 /* Timeout values should match the last one set for session */
1568 SetLastError(0xdeadbeef);
1569 value = 0xdeadbeef;
1570 size = sizeof(DWORD);
1571 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1572 ok(ret, "%u\n", GetLastError());
1573 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1575 SetLastError(0xdeadbeef);
1576 value = 0xdeadbeef;
1577 size = sizeof(DWORD);
1578 ret = WinHttpQueryOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1579 ok(ret, "%u\n", GetLastError());
1580 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1582 SetLastError(0xdeadbeef);
1583 value = 0xdeadbeef;
1584 size = sizeof(DWORD);
1585 ret = WinHttpQueryOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1586 ok(ret, "%u\n", GetLastError());
1587 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1589 SetLastError(0xdeadbeef);
1590 value = 0xdeadbeef;
1591 size = sizeof(DWORD);
1592 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1593 ok(ret, "%u\n", GetLastError());
1594 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1596 SetLastError(0xdeadbeef);
1597 ret = WinHttpSetTimeouts(con, -2, 0, 0, 0);
1598 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1599 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1601 SetLastError(0xdeadbeef);
1602 ret = WinHttpSetTimeouts(con, 0, -2, 0, 0);
1603 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1604 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1606 SetLastError(0xdeadbeef);
1607 ret = WinHttpSetTimeouts(con, 0, 0, -2, 0);
1608 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1609 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1611 SetLastError(0xdeadbeef);
1612 ret = WinHttpSetTimeouts(con, 0, 0, 0, -2);
1613 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1614 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1616 SetLastError(0xdeadbeef);
1617 ret = WinHttpSetTimeouts(con, -1, -1, -1, -1);
1618 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1619 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1621 SetLastError(0xdeadbeef);
1622 ret = WinHttpSetTimeouts(con, 0, 0, 0, 0);
1623 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1624 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1626 SetLastError(0xdeadbeef);
1627 value = 0;
1628 ret = WinHttpSetOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1629 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1630 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1632 SetLastError(0xdeadbeef);
1633 value = 0;
1634 ret = WinHttpSetOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1635 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1636 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1638 SetLastError(0xdeadbeef);
1639 value = 0;
1640 ret = WinHttpSetOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1641 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1642 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1644 SetLastError(0xdeadbeef);
1645 value = 0;
1646 ret = WinHttpSetOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1647 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1648 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1650 /* Changing timeout values for session should affect the values for connection */
1651 SetLastError(0xdeadbeef);
1652 value = 0xdead;
1653 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1654 ok(ret, "%u\n", GetLastError());
1656 SetLastError(0xdeadbeef);
1657 value = 0xdeadbeef;
1658 size = sizeof(DWORD);
1659 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1660 ok(ret, "%u\n", GetLastError());
1661 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1663 SetLastError(0xdeadbeef);
1664 value = 0xdead;
1665 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1666 ok(ret, "%u\n", GetLastError());
1668 SetLastError(0xdeadbeef);
1669 value = 0xdeadbeef;
1670 size = sizeof(DWORD);
1671 ret = WinHttpQueryOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1672 ok(ret, "%u\n", GetLastError());
1673 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1675 SetLastError(0xdeadbeef);
1676 value = 0xdead;
1677 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1678 ok(ret, "%u\n", GetLastError());
1680 SetLastError(0xdeadbeef);
1681 value = 0xdeadbeef;
1682 size = sizeof(DWORD);
1683 ret = WinHttpQueryOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1684 ok(ret, "%u\n", GetLastError());
1685 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1687 SetLastError(0xdeadbeef);
1688 value = 0xdead;
1689 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1690 ok(ret, "%u\n", GetLastError());
1692 SetLastError(0xdeadbeef);
1693 value = 0xdeadbeef;
1694 size = sizeof(DWORD);
1695 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1696 ok(ret, "%u\n", GetLastError());
1697 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1699 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1700 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1702 /* Timeout values should match the last one set for session */
1703 SetLastError(0xdeadbeef);
1704 value = 0xdeadbeef;
1705 size = sizeof(DWORD);
1706 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1707 ok(ret, "%u\n", GetLastError());
1708 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1710 SetLastError(0xdeadbeef);
1711 value = 0xdeadbeef;
1712 size = sizeof(DWORD);
1713 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1714 ok(ret, "%u\n", GetLastError());
1715 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1717 SetLastError(0xdeadbeef);
1718 value = 0xdeadbeef;
1719 size = sizeof(DWORD);
1720 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1721 ok(ret, "%u\n", GetLastError());
1722 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1724 SetLastError(0xdeadbeef);
1725 value = 0xdeadbeef;
1726 size = sizeof(DWORD);
1727 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1728 ok(ret, "%u\n", GetLastError());
1729 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1731 SetLastError(0xdeadbeef);
1732 ret = WinHttpSetTimeouts(req, -2, 0, 0, 0);
1733 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1734 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1736 SetLastError(0xdeadbeef);
1737 ret = WinHttpSetTimeouts(req, 0, -2, 0, 0);
1738 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1739 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1741 SetLastError(0xdeadbeef);
1742 ret = WinHttpSetTimeouts(req, 0, 0, -2, 0);
1743 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1744 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1746 SetLastError(0xdeadbeef);
1747 ret = WinHttpSetTimeouts(req, 0, 0, 0, -2);
1748 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1749 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1751 SetLastError(0xdeadbeef);
1752 ret = WinHttpSetTimeouts(req, -1, -1, -1, -1);
1753 ok(ret, "%u\n", GetLastError());
1755 SetLastError(0xdeadbeef);
1756 ret = WinHttpSetTimeouts(req, 0, 0, 0, 0);
1757 ok(ret, "%u\n", GetLastError());
1759 SetLastError(0xdeadbeef);
1760 ret = WinHttpSetTimeouts(req, 0xcdef, 0x89ab, 0x4567, 0x0123);
1761 ok(ret, "%u\n", GetLastError());
1763 SetLastError(0xdeadbeef);
1764 value = 0xdeadbeef;
1765 size = sizeof(DWORD);
1766 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1767 ok(ret, "%u\n", GetLastError());
1768 ok(value == 0xcdef, "Expected 0xcdef, got %u\n", value);
1770 SetLastError(0xdeadbeef);
1771 value = 0xdeadbeef;
1772 size = sizeof(DWORD);
1773 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1774 ok(ret, "%u\n", GetLastError());
1775 ok(value == 0x89ab, "Expected 0x89ab, got %u\n", value);
1777 SetLastError(0xdeadbeef);
1778 value = 0xdeadbeef;
1779 size = sizeof(DWORD);
1780 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1781 ok(ret, "%u\n", GetLastError());
1782 ok(value == 0x4567, "Expected 0x4567, got %u\n", value);
1784 SetLastError(0xdeadbeef);
1785 value = 0xdeadbeef;
1786 size = sizeof(DWORD);
1787 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1788 ok(ret, "%u\n", GetLastError());
1789 ok(value == 0x0123, "Expected 0x0123, got %u\n", value);
1791 SetLastError(0xdeadbeef);
1792 value = 0;
1793 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1794 ok(ret, "%u\n", GetLastError());
1796 SetLastError(0xdeadbeef);
1797 value = 0xdeadbeef;
1798 size = sizeof(DWORD);
1799 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1800 ok(ret, "%u\n", GetLastError());
1801 ok(value == 0, "Expected 0, got %u\n", value);
1803 SetLastError(0xdeadbeef);
1804 value = 0;
1805 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1806 ok(ret, "%u\n", GetLastError());
1808 SetLastError(0xdeadbeef);
1809 value = 0xdeadbeef;
1810 size = sizeof(DWORD);
1811 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1812 ok(ret, "%u\n", GetLastError());
1813 ok(value == 0, "Expected 0, got %u\n", value);
1815 SetLastError(0xdeadbeef);
1816 value = 0;
1817 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1818 ok(ret, "%u\n", GetLastError());
1820 SetLastError(0xdeadbeef);
1821 value = 0xdeadbeef;
1822 size = sizeof(DWORD);
1823 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1824 ok(ret, "%u\n", GetLastError());
1825 ok(value == 0, "Expected 0, got %u\n", value);
1827 SetLastError(0xdeadbeef);
1828 value = 0;
1829 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1830 ok(ret, "%u\n", GetLastError());
1832 SetLastError(0xdeadbeef);
1833 value = 0xdeadbeef;
1834 size = sizeof(DWORD);
1835 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1836 ok(ret, "%u\n", GetLastError());
1837 ok(value == 0, "Expected 0, got %u\n", value);
1839 SetLastError(0xdeadbeef);
1840 value = 0xbeefdead;
1841 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1842 ok(ret, "%u\n", GetLastError());
1844 SetLastError(0xdeadbeef);
1845 value = 0xdeadbeef;
1846 size = sizeof(DWORD);
1847 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1848 ok(ret, "%u\n", GetLastError());
1849 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1851 SetLastError(0xdeadbeef);
1852 value = 0xbeefdead;
1853 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1854 ok(ret, "%u\n", GetLastError());
1856 SetLastError(0xdeadbeef);
1857 value = 0xdeadbeef;
1858 size = sizeof(DWORD);
1859 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1860 ok(ret, "%u\n", GetLastError());
1861 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1863 SetLastError(0xdeadbeef);
1864 value = 0xbeefdead;
1865 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1866 ok(ret, "%u\n", GetLastError());
1868 SetLastError(0xdeadbeef);
1869 value = 0xdeadbeef;
1870 size = sizeof(DWORD);
1871 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1872 ok(ret, "%u\n", GetLastError());
1873 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1875 SetLastError(0xdeadbeef);
1876 value = 0xbeefdead;
1877 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1878 ok(ret, "%u\n", GetLastError());
1880 SetLastError(0xdeadbeef);
1881 value = 0xdeadbeef;
1882 size = sizeof(DWORD);
1883 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1884 ok(ret, "%u\n", GetLastError());
1885 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1887 /* Changing timeout values for session should not affect the values for a request,
1888 * neither should the other way around.
1890 SetLastError(0xdeadbeef);
1891 value = 0xbeefdead;
1892 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1893 ok(ret, "%u\n", GetLastError());
1895 SetLastError(0xdeadbeef);
1896 value = 0xdeadbeef;
1897 size = sizeof(DWORD);
1898 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1899 ok(ret, "%u\n", GetLastError());
1900 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1902 SetLastError(0xdeadbeef);
1903 value = 0xbeefdead;
1904 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1905 ok(ret, "%u\n", GetLastError());
1907 SetLastError(0xdeadbeef);
1908 value = 0xdeadbeef;
1909 size = sizeof(DWORD);
1910 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1911 ok(ret, "%u\n", GetLastError());
1912 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1914 SetLastError(0xdeadbeef);
1915 value = 0xbeefdead;
1916 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1917 ok(ret, "%u\n", GetLastError());
1919 SetLastError(0xdeadbeef);
1920 value = 0xdeadbeef;
1921 size = sizeof(DWORD);
1922 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1923 ok(ret, "%u\n", GetLastError());
1924 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1926 SetLastError(0xdeadbeef);
1927 value = 0xbeefdead;
1928 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1929 ok(ret, "%u\n", GetLastError());
1931 SetLastError(0xdeadbeef);
1932 value = 0xdeadbeef;
1933 size = sizeof(DWORD);
1934 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1935 ok(ret, "%u\n", GetLastError());
1936 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1938 SetLastError(0xdeadbeef);
1939 value = 0xbeef;
1940 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1941 ok(ret, "%u\n", GetLastError());
1943 SetLastError(0xdeadbeef);
1944 value = 0xdeadbeef;
1945 size = sizeof(DWORD);
1946 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1947 ok(ret, "%u\n", GetLastError());
1948 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1950 SetLastError(0xdeadbeef);
1951 value = 0xbeef;
1952 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1953 ok(ret, "%u\n", GetLastError());
1955 SetLastError(0xdeadbeef);
1956 value = 0xdeadbeef;
1957 size = sizeof(DWORD);
1958 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1959 ok(ret, "%u\n", GetLastError());
1960 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1962 SetLastError(0xdeadbeef);
1963 value = 0xbeef;
1964 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1965 ok(ret, "%u\n", GetLastError());
1967 SetLastError(0xdeadbeef);
1968 value = 0xdeadbeef;
1969 size = sizeof(DWORD);
1970 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1971 ok(ret, "%u\n", GetLastError());
1972 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1974 SetLastError(0xdeadbeef);
1975 value = 0xbeef;
1976 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1977 ok(ret, "%u\n", GetLastError());
1979 SetLastError(0xdeadbeef);
1980 value = 0xdeadbeef;
1981 size = sizeof(DWORD);
1982 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1983 ok(ret, "%u\n", GetLastError());
1984 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1986 /* response timeout */
1987 SetLastError(0xdeadbeef);
1988 value = 0xdeadbeef;
1989 size = sizeof(value);
1990 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
1991 ok(ret, "%u\n", GetLastError());
1992 ok(value == ~0u, "got %u\n", value);
1994 SetLastError(0xdeadbeef);
1995 value = 30000;
1996 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, sizeof(value));
1997 ok(ret, "%u\n", GetLastError());
1999 SetLastError(0xdeadbeef);
2000 value = 0xdeadbeef;
2001 size = sizeof(value);
2002 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
2003 ok(ret, "%u\n", GetLastError());
2004 todo_wine ok(value == 0xbeefdead, "got %u\n", value);
2006 SetLastError(0xdeadbeef);
2007 value = 0xdeadbeef;
2008 size = sizeof(value);
2009 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
2010 ok(ret, "%u\n", GetLastError());
2011 ok(value == ~0u, "got %u\n", value);
2013 SetLastError(0xdeadbeef);
2014 value = 30000;
2015 ret = WinHttpSetOption(con, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, sizeof(value));
2016 ok(!ret, "expected failure\n");
2017 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, "got %u\n", GetLastError());
2019 SetLastError(0xdeadbeef);
2020 value = 0xdeadbeef;
2021 size = sizeof(value);
2022 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
2023 ok(ret, "%u\n", GetLastError());
2024 ok(value == ~0u, "got %u\n", value);
2026 SetLastError(0xdeadbeef);
2027 value = 48878;
2028 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, sizeof(value));
2029 ok(ret, "%u\n", GetLastError());
2031 SetLastError(0xdeadbeef);
2032 value = 0xdeadbeef;
2033 size = sizeof(value);
2034 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
2035 ok(ret, "%u\n", GetLastError());
2036 todo_wine ok(value == 48879, "got %u\n", value);
2038 SetLastError(0xdeadbeef);
2039 value = 48880;
2040 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, sizeof(value));
2041 ok(ret, "%u\n", GetLastError());
2043 SetLastError(0xdeadbeef);
2044 value = 0xdeadbeef;
2045 size = sizeof(value);
2046 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
2047 ok(ret, "%u\n", GetLastError());
2048 ok(value == 48880, "got %u\n", value);
2050 WinHttpCloseHandle(req);
2051 WinHttpCloseHandle(con);
2052 WinHttpCloseHandle(ses);
2055 static void test_resolve_timeout(void)
2057 HINTERNET ses, con, req;
2058 DWORD timeout;
2059 BOOL ret;
2061 if (! proxy_active())
2063 ses = WinHttpOpen(L"winetest", 0, NULL, NULL, 0);
2064 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2066 timeout = 10000;
2067 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
2068 ok(ret, "failed to set resolve timeout %u\n", GetLastError());
2070 con = WinHttpConnect(ses, L"nxdomain.winehq.org", 0, 0);
2071 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2073 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
2074 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2076 SetLastError(0xdeadbeef);
2077 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2078 if (ret)
2080 skip("nxdomain returned success. Broken ISP redirects?\n");
2081 goto done;
2083 ok(GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED,
2084 "expected ERROR_WINHTTP_NAME_NOT_RESOLVED got %u\n", GetLastError());
2086 ret = WinHttpReceiveResponse( req, NULL );
2087 ok( !ret && (GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_STATE ||
2088 GetLastError() == ERROR_WINHTTP_OPERATION_CANCELLED /* < win7 */),
2089 "got %u\n", GetLastError() );
2091 WinHttpCloseHandle(req);
2092 WinHttpCloseHandle(con);
2093 WinHttpCloseHandle(ses);
2095 else
2096 skip("Skipping host resolution tests, host resolution performed by proxy\n");
2098 ses = WinHttpOpen(L"winetest", 0, NULL, NULL, 0);
2099 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2101 timeout = 10000;
2102 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
2103 ok(ret, "failed to set resolve timeout %u\n", GetLastError());
2105 con = WinHttpConnect(ses, L"test.winehq.org", 0, 0);
2106 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2108 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
2109 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2111 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2112 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
2114 skip("connection failed, skipping\n");
2115 goto done;
2117 ok(ret, "failed to send request\n");
2119 done:
2120 WinHttpCloseHandle(req);
2121 WinHttpCloseHandle(con);
2122 WinHttpCloseHandle(ses);
2125 static const char page1[] =
2126 "<HTML>\r\n"
2127 "<HEAD><TITLE>winhttp test page</TITLE></HEAD>\r\n"
2128 "<BODY>The quick brown fox jumped over the lazy dog<P></BODY>\r\n"
2129 "</HTML>\r\n\r\n";
2131 static const char okmsg[] =
2132 "HTTP/1.1 200 OK\r\n"
2133 "Server: winetest\r\n"
2134 "\r\n";
2136 static const char notokmsg[] =
2137 "HTTP/1.1 400 Bad Request\r\n"
2138 "\r\n";
2140 static const char cookiemsg[] =
2141 "HTTP/1.1 200 OK\r\n"
2142 "Set-Cookie: name = value \r\n"
2143 "Set-Cookie: NAME = value \r\n"
2144 "\r\n";
2146 static const char cookiemsg2[] =
2147 "HTTP/1.1 200 OK\r\n"
2148 "Set-Cookie: name2=value; Domain = localhost; Path=/cookie5;Expires=Wed, 13 Jan 2021 22:23:01 GMT; HttpOnly; \r\n"
2149 "\r\n";
2151 static const char nocontentmsg[] =
2152 "HTTP/1.1 204 No Content\r\n"
2153 "Server: winetest\r\n"
2154 "\r\n";
2156 static const char notmodified[] =
2157 "HTTP/1.1 304 Not Modified\r\n"
2158 "\r\n";
2160 static const char noauthmsg[] =
2161 "HTTP/1.1 401 Unauthorized\r\n"
2162 "Server: winetest\r\n"
2163 "Connection: close\r\n"
2164 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
2165 "Content-Length: 12\r\n"
2166 "Content-Type: text/plain\r\n"
2167 "\r\n";
2169 static const char okauthmsg[] =
2170 "HTTP/1.1 200 OK\r\n"
2171 "Server: winetest\r\n"
2172 "Connection: close\r\n"
2173 "Content-Length: 11\r\n"
2174 "Content-Type: text/plain\r\n"
2175 "\r\n";
2177 static const char headmsg[] =
2178 "HTTP/1.1 200 OK\r\n"
2179 "Content-Length: 100\r\n"
2180 "\r\n";
2182 static const char multiauth[] =
2183 "HTTP/1.1 401 Unauthorized\r\n"
2184 "Server: winetest\r\n"
2185 "WWW-Authenticate: Bearer\r\n"
2186 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
2187 "WWW-Authenticate: NTLM\r\n"
2188 "Content-Length: 10\r\n"
2189 "Content-Type: text/plain\r\n"
2190 "\r\n";
2192 static const char largeauth[] =
2193 "HTTP/1.1 401 Unauthorized\r\n"
2194 "Server: winetest\r\n"
2195 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
2196 "WWW-Authenticate: NTLM\r\n"
2197 "Content-Length: 10240\r\n"
2198 "Content-Type: text/plain\r\n"
2199 "\r\n";
2201 static const char passportauth[] =
2202 "HTTP/1.1 302 Found\r\n"
2203 "Content-Length: 0\r\n"
2204 "Location: /\r\n"
2205 "WWW-Authenticate: Passport1.4\r\n"
2206 "\r\n";
2208 static const char unauthorized[] = "Unauthorized";
2209 static const char hello_world[] = "Hello World";
2210 static const char auth_unseen[] = "Auth Unseen";
2212 struct server_info
2214 HANDLE event;
2215 int port;
2218 #define BIG_BUFFER_LEN 0x2250
2220 static DWORD CALLBACK server_thread(LPVOID param)
2222 struct server_info *si = param;
2223 int r, c = -1, i, on;
2224 SOCKET s;
2225 struct sockaddr_in sa;
2226 char buffer[0x100];
2227 WSADATA wsaData;
2228 int last_request = 0;
2230 WSAStartup(MAKEWORD(1,1), &wsaData);
2232 s = socket(AF_INET, SOCK_STREAM, 0);
2233 if (s == INVALID_SOCKET)
2234 return 1;
2236 on = 1;
2237 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof on);
2239 memset(&sa, 0, sizeof sa);
2240 sa.sin_family = AF_INET;
2241 sa.sin_port = htons(si->port);
2242 sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
2244 r = bind(s, (struct sockaddr *)&sa, sizeof(sa));
2245 if (r < 0)
2246 return 1;
2248 listen(s, 0);
2249 SetEvent(si->event);
2252 if (c == -1) c = accept(s, NULL, NULL);
2254 memset(buffer, 0, sizeof buffer);
2255 for(i = 0; i < sizeof buffer - 1; i++)
2257 r = recv(c, &buffer[i], 1, 0);
2258 if (r != 1)
2259 break;
2260 if (i < 4) continue;
2261 if (buffer[i - 2] == '\n' && buffer[i] == '\n' &&
2262 buffer[i - 3] == '\r' && buffer[i - 1] == '\r')
2263 break;
2265 if (strstr(buffer, "GET /basic"))
2267 send(c, okmsg, sizeof okmsg - 1, 0);
2268 send(c, page1, sizeof page1 - 1, 0);
2270 if (strstr(buffer, "/auth_with_creds"))
2272 send(c, okauthmsg, sizeof okauthmsg - 1, 0);
2273 if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
2274 send(c, hello_world, sizeof hello_world - 1, 0);
2275 else
2276 send(c, auth_unseen, sizeof auth_unseen - 1, 0);
2277 continue;
2279 if (strstr(buffer, "/auth"))
2281 if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
2283 send(c, okauthmsg, sizeof okauthmsg - 1, 0);
2284 send(c, hello_world, sizeof hello_world - 1, 0);
2286 else
2288 send(c, noauthmsg, sizeof noauthmsg - 1, 0);
2289 send(c, unauthorized, sizeof unauthorized - 1, 0);
2291 continue;
2293 if (strstr(buffer, "/big"))
2295 char msg[BIG_BUFFER_LEN];
2296 memset(msg, 'm', sizeof(msg));
2297 send(c, okmsg, sizeof(okmsg) - 1, 0);
2298 send(c, msg, sizeof(msg), 0);
2300 if (strstr(buffer, "/no_headers"))
2302 send(c, page1, sizeof page1 - 1, 0);
2304 if (strstr(buffer, "GET /no_content"))
2306 send(c, nocontentmsg, sizeof nocontentmsg - 1, 0);
2307 continue;
2309 if (strstr(buffer, "GET /not_modified"))
2311 if (strstr(buffer, "If-Modified-Since:")) send(c, notmodified, sizeof notmodified - 1, 0);
2312 else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2313 continue;
2315 if (strstr(buffer, "HEAD /head"))
2317 send(c, headmsg, sizeof headmsg - 1, 0);
2318 continue;
2320 if (strstr(buffer, "GET /multiauth"))
2322 send(c, multiauth, sizeof multiauth - 1, 0);
2324 if (strstr(buffer, "GET /largeauth"))
2326 if (strstr(buffer, "Authorization: NTLM"))
2327 send(c, okmsg, sizeof(okmsg) - 1, 0);
2328 else
2330 send(c, largeauth, sizeof largeauth - 1, 0);
2331 for (i = 0; i < 10240; i++) send(c, "A", 1, 0);
2332 continue;
2335 if (strstr(buffer, "GET /cookie5"))
2337 if (strstr(buffer, "Cookie: name2=value\r\n"))
2338 send(c, okmsg, sizeof(okmsg) - 1, 0);
2339 else
2340 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2342 if (strstr(buffer, "GET /cookie4"))
2344 send(c, cookiemsg2, sizeof(cookiemsg2) - 1, 0);
2346 if (strstr(buffer, "GET /cookie3"))
2348 if (strstr(buffer, "Cookie: name=value2; NAME=value; name=value\r\n") ||
2349 broken(strstr(buffer, "Cookie: name=value2; name=value; NAME=value\r\n") != NULL))
2350 send(c, okmsg, sizeof(okmsg) - 1, 0);
2351 else
2352 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2354 if (strstr(buffer, "GET /cookie2"))
2356 if (strstr(buffer, "Cookie: NAME=value; name=value\r\n") ||
2357 broken(strstr(buffer, "Cookie: name=value; NAME=value\r\n") != NULL))
2358 send(c, okmsg, sizeof(okmsg) - 1, 0);
2359 else
2360 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2362 else if (strstr(buffer, "GET /cookie"))
2364 if (!strstr(buffer, "Cookie: name=value\r\n")) send(c, cookiemsg, sizeof(cookiemsg) - 1, 0);
2365 else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2367 else if (strstr(buffer, "GET /escape"))
2369 static const char res[] = "%0D%0A%1F%7F%3C%20%one?%1F%7F%20!%22%23$%&'()*+,-./:;%3C=%3E?@%5B%5C%5D"
2370 "%5E_%60%7B%7C%7D~%0D%0A ";
2371 static const char res2[] = "%0D%0A%1F%7F%3C%20%25two?%1F%7F%20!%22%23$%25&'()*+,-./:;%3C=%3E?@%5B%5C%5D"
2372 "%5E_%60%7B%7C%7D~%0D%0A ";
2373 static const char res3[] = "\x1f\x7f<%20%three?\x1f\x7f%20!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ";
2374 static const char res4[] = "%0D%0A%1F%7F%3C%20%four?\x1f\x7f%20!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ";
2375 static const char res5[] = "&text=one%C2%80%7F~";
2376 static const char res6[] = "&text=two%C2%80\x7f~";
2377 static const char res7[] = "&text=%E5%90%9B%E3%81%AE%E5%90%8D%E3%81%AF";
2379 if (strstr(buffer + 11, res) || strstr(buffer + 11, res2) || strstr(buffer + 11, res3) ||
2380 strstr(buffer + 11, res4) || strstr(buffer + 11, res5) || strstr(buffer + 11, res6) ||
2381 strstr(buffer + 11, res7))
2383 send(c, okmsg, sizeof(okmsg) - 1, 0);
2385 else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2387 else if (strstr(buffer, "GET /passport"))
2389 send(c, passportauth, sizeof(passportauth) - 1, 0);
2391 if (strstr(buffer, "GET /quit"))
2393 send(c, okmsg, sizeof okmsg - 1, 0);
2394 send(c, page1, sizeof page1 - 1, 0);
2395 last_request = 1;
2397 shutdown(c, 2);
2398 closesocket(c);
2399 c = -1;
2401 } while (!last_request);
2403 closesocket(s);
2404 return 0;
2407 static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path)
2409 HINTERNET ses, con, req;
2410 char buffer[0x100];
2411 WCHAR buffer2[0x100];
2412 DWORD count, status, size, error, supported, first, target;
2413 BOOL ret;
2415 ses = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2416 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2418 SetLastError(0xdeadbeef);
2419 ret = WinHttpSetOption(ses, 0, buffer, sizeof(buffer));
2420 ok(!ret && GetLastError() == ERROR_WINHTTP_INVALID_OPTION, "got %u\n", GetLastError());
2422 SetLastError(0xdeadbeef);
2423 ret = WinHttpQueryOption(ses, 0, buffer, &size);
2424 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %u\n", GetLastError());
2426 con = WinHttpConnect(ses, L"localhost", port, 0);
2427 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2429 SetLastError(0xdeadbeef);
2430 ret = WinHttpSetOption(con, 0, buffer, sizeof(buffer));
2431 todo_wine ok(!ret && GetLastError() == ERROR_WINHTTP_INVALID_OPTION, "got %u\n", GetLastError());
2433 SetLastError(0xdeadbeef);
2434 ret = WinHttpQueryOption(con, 0, buffer, &size);
2435 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %u\n", GetLastError());
2437 req = WinHttpOpenRequest(con, verb, path, NULL, NULL, NULL, 0);
2438 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2440 SetLastError(0xdeadbeef);
2441 ret = WinHttpSetOption(req, 0, buffer, sizeof(buffer));
2442 ok(!ret && GetLastError() == ERROR_WINHTTP_INVALID_OPTION, "got %u\n", GetLastError());
2444 SetLastError(0xdeadbeef);
2445 ret = WinHttpQueryOption(req, 0, buffer, &size);
2446 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %u\n", GetLastError());
2448 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2449 ok(ret, "failed to send request %u\n", GetLastError());
2451 ret = WinHttpReceiveResponse(req, NULL);
2452 ok(ret, "failed to receive response %u\n", GetLastError());
2454 status = 0xdeadbeef;
2455 size = sizeof(status);
2456 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2457 ok(ret, "failed to query status code %u\n", GetLastError());
2458 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2460 supported = first = target = 0xdeadbeef;
2461 SetLastError(0xdeadbeef);
2462 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2463 error = GetLastError();
2464 ok(!ret, "unexpected success\n");
2465 ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
2466 ok(supported == 0xdeadbeef, "got %x\n", supported);
2467 ok(first == 0xdeadbeef, "got %x\n", first);
2468 ok(target == 0xdeadbeef, "got %x\n", target);
2470 size = sizeof(buffer2);
2471 memset(buffer2, 0, sizeof(buffer2));
2472 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, buffer2, &size, NULL);
2473 ok(ret, "failed to query for raw headers: %u\n", GetLastError());
2474 ok(!memcmp(buffer2 + lstrlenW(buffer2) - 4, L"\r\n\r\n", sizeof(L"\r\n\r\n")),
2475 "WinHttpQueryHeaders returned invalid end of header string\n");
2477 size = sizeof(buffer2);
2478 memset(buffer2, 0, sizeof(buffer2));
2479 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS, NULL, buffer2, &size, NULL);
2480 ok(ret, "failed to query for raw headers: %u\n", GetLastError());
2481 ok(!memcmp(buffer2 + (size / sizeof(WCHAR)) - 1, L"", sizeof(L"")),
2482 "WinHttpQueryHeaders returned invalid end of header string\n");
2483 ok(buffer2[(size / sizeof(WCHAR)) - 2] != 0, "returned string has too many NULL characters\n");
2485 count = 0;
2486 memset(buffer, 0, sizeof(buffer));
2487 ret = WinHttpReadData(req, buffer, sizeof buffer, &count);
2488 ok(ret, "failed to read data %u\n", GetLastError());
2489 ok(count == sizeof page1 - 1, "count was wrong\n");
2490 ok(!memcmp(buffer, page1, sizeof page1), "http data wrong\n");
2492 WinHttpCloseHandle(req);
2493 WinHttpCloseHandle(con);
2494 WinHttpCloseHandle(ses);
2497 static void test_basic_authentication(int port)
2499 HINTERNET ses, con, req;
2500 DWORD status, size, error, supported, first, target;
2501 char buffer[32];
2502 BOOL ret;
2504 ses = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2505 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2507 con = WinHttpConnect(ses, L"localhost", port, 0);
2508 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2510 req = WinHttpOpenRequest(con, NULL, L"/auth", NULL, NULL, NULL, 0);
2511 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2513 SetLastError(0xdeadbeef);
2514 ret = WinHttpQueryAuthSchemes(NULL, NULL, NULL, NULL);
2515 error = GetLastError();
2516 ok(!ret, "expected failure\n");
2517 ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
2519 SetLastError(0xdeadbeef);
2520 ret = WinHttpQueryAuthSchemes(req, NULL, NULL, NULL);
2521 error = GetLastError();
2522 ok(!ret, "expected failure\n");
2523 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2525 supported = 0xdeadbeef;
2526 SetLastError(0xdeadbeef);
2527 ret = WinHttpQueryAuthSchemes(req, &supported, NULL, NULL);
2528 error = GetLastError();
2529 ok(!ret, "expected failure\n");
2530 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2531 ok(supported == 0xdeadbeef, "got %x\n", supported);
2533 supported = first = 0xdeadbeef;
2534 SetLastError(0xdeadbeef);
2535 ret = WinHttpQueryAuthSchemes(req, &supported, &first, NULL);
2536 error = GetLastError();
2537 ok(!ret, "expected failure\n");
2538 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2539 ok(supported == 0xdeadbeef, "got %x\n", supported);
2540 ok(first == 0xdeadbeef, "got %x\n", first);
2542 supported = first = target = 0xdeadbeef;
2543 SetLastError(0xdeadbeef);
2544 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2545 error = GetLastError();
2546 ok(!ret, "expected failure\n");
2547 ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
2548 ok(supported == 0xdeadbeef, "got %x\n", supported);
2549 ok(first == 0xdeadbeef, "got %x\n", first);
2550 ok(target == 0xdeadbeef, "got %x\n", target);
2552 supported = first = target = 0xdeadbeef;
2553 SetLastError(0xdeadbeef);
2554 ret = WinHttpQueryAuthSchemes(NULL, &supported, &first, &target);
2555 error = GetLastError();
2556 ok(!ret, "expected failure\n");
2557 ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
2558 ok(supported == 0xdeadbeef, "got %x\n", supported);
2559 ok(first == 0xdeadbeef, "got %x\n", first);
2560 ok(target == 0xdeadbeef, "got %x\n", target);
2562 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2563 ok(ret, "failed to send request %u\n", GetLastError());
2565 ret = WinHttpReceiveResponse(req, NULL);
2566 ok(ret, "failed to receive response %u\n", GetLastError());
2568 status = 0xdeadbeef;
2569 size = sizeof(status);
2570 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2571 ok(ret, "failed to query status code %u\n", GetLastError());
2572 ok(status == HTTP_STATUS_DENIED, "request failed unexpectedly %u\n", status);
2574 size = 0;
2575 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
2576 error = GetLastError();
2577 ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError());
2578 if (ret)
2580 ok(size == 12, "expected 12, got %u\n", size);
2581 ok(!memcmp(buffer, unauthorized, 12), "got %s\n", buffer);
2584 supported = first = target = 0xdeadbeef;
2585 SetLastError(0xdeadbeef);
2586 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2587 error = GetLastError();
2588 ok(ret, "failed to query authentication schemes %u\n", error);
2589 ok(error == ERROR_SUCCESS || broken(error == 0xdeadbeef) /* < win7 */, "expected ERROR_SUCCESS, got %u\n", error);
2590 ok(supported == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", supported);
2591 ok(first == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", first);
2592 ok(target == WINHTTP_AUTH_TARGET_SERVER, "got %x\n", target);
2594 SetLastError(0xdeadbeef);
2595 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NTLM, NULL, NULL, NULL);
2596 error = GetLastError();
2597 ok(ret, "failed to set credentials %u\n", error);
2598 ok(error == ERROR_SUCCESS || broken(error == 0xdeadbeef) /* < win7 */, "expected ERROR_SUCCESS, got %u\n", error);
2600 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_PASSPORT, NULL, NULL, NULL);
2601 ok(ret, "failed to set credentials %u\n", GetLastError());
2603 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NEGOTIATE, NULL, NULL, NULL);
2604 ok(ret, "failed to set credentials %u\n", GetLastError());
2606 SetLastError(0xdeadbeef);
2607 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_DIGEST, NULL, NULL, NULL);
2608 error = GetLastError();
2609 ok(!ret, "expected failure\n");
2610 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2612 SetLastError(0xdeadbeef);
2613 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, NULL, NULL);
2614 error = GetLastError();
2615 ok(!ret, "expected failure\n");
2616 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2618 SetLastError(0xdeadbeef);
2619 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, L"user", NULL, NULL);
2620 error = GetLastError();
2621 ok(!ret, "expected failure\n");
2622 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2624 SetLastError(0xdeadbeef);
2625 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, L"pwd", NULL);
2626 error = GetLastError();
2627 ok(!ret, "expected failure\n");
2628 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2630 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, L"user", L"pwd", NULL);
2631 ok(ret, "failed to set credentials %u\n", GetLastError());
2633 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2634 ok(ret, "failed to send request %u\n", GetLastError());
2636 ret = WinHttpReceiveResponse(req, NULL);
2637 ok(ret, "failed to receive response %u\n", GetLastError());
2639 status = 0xdeadbeef;
2640 size = sizeof(status);
2641 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2642 ok(ret, "failed to query status code %u\n", GetLastError());
2643 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2645 size = 0;
2646 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
2647 error = GetLastError();
2648 ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError());
2649 if (ret)
2651 ok(size == 11, "expected 11, got %u\n", size);
2652 ok(!memcmp(buffer, hello_world, 11), "got %s\n", buffer);
2655 WinHttpCloseHandle(req);
2656 WinHttpCloseHandle(con);
2657 WinHttpCloseHandle(ses);
2659 /* now set the credentials first to show that they get sent with the first request */
2660 ses = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2661 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2663 con = WinHttpConnect(ses, L"localhost", port, 0);
2664 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2666 req = WinHttpOpenRequest(con, NULL, L"/auth_with_creds", NULL, NULL, NULL, 0);
2667 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2669 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, L"user", L"pwd", NULL);
2670 ok(ret, "failed to set credentials %u\n", GetLastError());
2672 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2673 ok(ret, "failed to send request %u\n", GetLastError());
2675 ret = WinHttpReceiveResponse(req, NULL);
2676 ok(ret, "failed to receive response %u\n", GetLastError());
2678 status = 0xdeadbeef;
2679 size = sizeof(status);
2680 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2681 ok(ret, "failed to query status code %u\n", GetLastError());
2682 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2684 size = 0;
2685 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
2686 error = GetLastError();
2687 ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError());
2688 if (ret)
2690 ok(size == 11, "expected 11, got %u\n", size);
2691 ok(!memcmp(buffer, hello_world, 11), "got %s\n", buffer);
2694 WinHttpCloseHandle(req);
2695 WinHttpCloseHandle(con);
2696 WinHttpCloseHandle(ses);
2698 /* credentials set with WinHttpSetCredentials take precedence over those set through options */
2700 ses = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2701 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2703 con = WinHttpConnect(ses, L"localhost", port, 0);
2704 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2706 req = WinHttpOpenRequest(con, NULL, L"/auth", NULL, NULL, NULL, 0);
2707 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2709 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, L"user", L"pwd", NULL);
2710 ok(ret, "failed to set credentials %u\n", GetLastError());
2712 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, (void *)L"user", lstrlenW(L"user"));
2713 ok(ret, "failed to set username %u\n", GetLastError());
2715 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, (void *)L"pwd2", lstrlenW(L"pwd2"));
2716 ok(ret, "failed to set password %u\n", GetLastError());
2718 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2719 ok(ret, "failed to send request %u\n", GetLastError());
2721 ret = WinHttpReceiveResponse(req, NULL);
2722 ok(ret, "failed to receive response %u\n", GetLastError());
2724 status = 0xdeadbeef;
2725 size = sizeof(status);
2726 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2727 ok(ret, "failed to query status code %u\n", GetLastError());
2728 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2730 WinHttpCloseHandle(req);
2731 WinHttpCloseHandle(con);
2732 WinHttpCloseHandle(ses);
2734 ses = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2735 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2737 con = WinHttpConnect(ses, L"localhost", port, 0);
2738 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2740 req = WinHttpOpenRequest(con, NULL, L"/auth", NULL, NULL, NULL, 0);
2741 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2743 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, (void *)L"user", lstrlenW(L"user"));
2744 ok(ret, "failed to set username %u\n", GetLastError());
2746 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, (void *)L"pwd", lstrlenW(L"pwd"));
2747 ok(ret, "failed to set password %u\n", GetLastError());
2749 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, L"user", L"pwd2", NULL);
2750 ok(ret, "failed to set credentials %u\n", GetLastError());
2752 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2753 ok(ret, "failed to send request %u\n", GetLastError());
2755 ret = WinHttpReceiveResponse(req, NULL);
2756 ok(ret, "failed to receive response %u\n", GetLastError());
2758 status = 0xdeadbeef;
2759 size = sizeof(status);
2760 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2761 ok(ret, "failed to query status code %u\n", GetLastError());
2762 ok(status == HTTP_STATUS_DENIED, "request failed unexpectedly %u\n", status);
2764 WinHttpCloseHandle(req);
2765 WinHttpCloseHandle(con);
2766 WinHttpCloseHandle(ses);
2769 static void test_multi_authentication(int port)
2771 HINTERNET ses, con, req;
2772 DWORD supported, first, target, size, index;
2773 WCHAR buf[512];
2774 BOOL ret;
2776 ses = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2777 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2779 con = WinHttpConnect(ses, L"localhost", port, 0);
2780 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2782 req = WinHttpOpenRequest(con, L"GET", L"/multiauth", NULL, NULL, NULL, 0);
2783 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2785 ret = WinHttpSendRequest(req, WINHTTP_NO_ADDITIONAL_HEADERS, 0,
2786 WINHTTP_NO_REQUEST_DATA,0, 0, 0 );
2787 ok(ret, "expected success\n");
2789 ret = WinHttpReceiveResponse(req, NULL);
2790 ok(ret, "expected success\n");
2792 supported = first = target = 0xdeadbeef;
2793 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2794 ok(ret, "expected success\n");
2795 ok(supported == (WINHTTP_AUTH_SCHEME_BASIC | WINHTTP_AUTH_SCHEME_NTLM), "got %x\n", supported);
2796 ok(target == WINHTTP_AUTH_TARGET_SERVER, "got %x\n", target);
2797 ok(first == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", first);
2799 index = 0;
2800 size = sizeof(buf);
2801 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CUSTOM, L"WWW-Authenticate", buf, &size, &index);
2802 ok(ret, "expected success\n");
2803 ok(!lstrcmpW(buf, L"Bearer"), "buf = %s\n", wine_dbgstr_w(buf));
2804 ok(size == lstrlenW(buf) * sizeof(WCHAR), "size = %u\n", size);
2805 ok(index == 1, "index = %u\n", index);
2807 index = 0;
2808 size = 0xdeadbeef;
2809 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CUSTOM, L"WWW-Authenticate", NULL, &size, &index);
2810 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2811 "WinHttpQueryHeaders returned %x(%u)\n", ret, GetLastError());
2812 ok(size == (lstrlenW(buf) + 1) * sizeof(WCHAR), "size = %u\n", size);
2813 ok(index == 0, "index = %u\n", index);
2815 WinHttpCloseHandle(req);
2816 WinHttpCloseHandle(con);
2817 WinHttpCloseHandle(ses);
2820 static void test_large_data_authentication(int port)
2822 HINTERNET ses, con, req;
2823 DWORD status, size;
2824 BOOL ret;
2826 ses = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2827 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2829 con = WinHttpConnect(ses, L"localhost", port, 0);
2830 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2832 req = WinHttpOpenRequest(con, L"GET", L"/largeauth", NULL, NULL, NULL, 0);
2833 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2835 ret = WinHttpSendRequest(req, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
2836 ok(ret, "expected success\n");
2838 ret = WinHttpReceiveResponse(req, NULL);
2839 ok(ret, "expected success\n");
2841 size = sizeof(status);
2842 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL,
2843 &status, &size, NULL);
2844 ok(ret, "expected success\n");
2845 ok(status == HTTP_STATUS_DENIED, "got %d\n", status);
2847 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NTLM, L"user", L"pwd", NULL);
2848 ok(ret, "expected success\n");
2850 ret = WinHttpSendRequest(req, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
2851 ok(ret, "expected success %d\n", GetLastError());
2853 ret = WinHttpReceiveResponse(req, NULL);
2854 ok(ret, "expected success\n");
2856 size = sizeof(status);
2857 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL,
2858 &status, &size, NULL);
2859 ok(ret, "expected success\n");
2860 ok(status == HTTP_STATUS_OK, "got %d\n", status);
2862 WinHttpCloseHandle(req);
2863 WinHttpCloseHandle(con);
2864 WinHttpCloseHandle(ses);
2867 static void test_no_headers(int port)
2869 HINTERNET ses, con, req;
2870 DWORD error;
2871 BOOL ret;
2873 ses = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2874 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2876 con = WinHttpConnect(ses, L"localhost", port, 0);
2877 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2879 req = WinHttpOpenRequest(con, NULL, L"/no_headers", NULL, NULL, NULL, 0);
2880 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2882 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2883 if (!ret)
2885 error = GetLastError();
2886 ok(error == ERROR_WINHTTP_INVALID_SERVER_RESPONSE, "got %u\n", error);
2888 else
2890 SetLastError(0xdeadbeef);
2891 ret = WinHttpReceiveResponse(req, NULL);
2892 error = GetLastError();
2893 ok(!ret, "expected failure\n");
2894 ok(error == ERROR_WINHTTP_INVALID_SERVER_RESPONSE, "got %u\n", error);
2897 WinHttpCloseHandle(req);
2898 WinHttpCloseHandle(con);
2899 WinHttpCloseHandle(ses);
2902 static void test_no_content(int port)
2904 HINTERNET ses, con, req;
2905 char buf[128];
2906 DWORD size, len = sizeof(buf), bytes_read, status;
2907 BOOL ret;
2909 ses = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2910 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2912 con = WinHttpConnect(ses, L"localhost", port, 0);
2913 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2915 req = WinHttpOpenRequest(con, NULL, L"/no_content", NULL, NULL, NULL, 0);
2916 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2918 size = 12345;
2919 SetLastError(0xdeadbeef);
2920 ret = WinHttpQueryDataAvailable(req, &size);
2921 todo_wine {
2922 ok(!ret, "expected error\n");
2923 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_STATE,
2924 "expected ERROR_WINHTTP_INCORRECT_HANDLE_STATE, got 0x%08x\n", GetLastError());
2925 ok(size == 12345 || broken(size == 0) /* Win <= 2003 */,
2926 "expected 12345, got %u\n", size);
2929 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2930 ok(ret, "expected success\n");
2932 ret = WinHttpReceiveResponse(req, NULL);
2933 ok(ret, "expected success\n");
2935 status = 0xdeadbeef;
2936 size = sizeof(status);
2937 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
2938 NULL, &status, &size, NULL);
2939 ok(ret, "expected success\n");
2940 ok(status == HTTP_STATUS_NO_CONTENT, "expected status 204, got %d\n", status);
2942 SetLastError(0xdeadbeef);
2943 size = sizeof(status);
2944 status = 12345;
2945 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
2946 NULL, &status, &size, 0);
2947 ok(!ret, "expected no content-length header\n");
2948 ok(GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND, "wrong error %u\n", GetLastError());
2949 ok(status == 12345, "expected 0, got %d\n", status);
2951 SetLastError(0xdeadbeef);
2952 size = 12345;
2953 ret = WinHttpQueryDataAvailable(req, &size);
2954 ok(ret, "expected success\n");
2955 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
2956 "wrong error %u\n", GetLastError());
2957 ok(!size, "expected 0, got %u\n", size);
2959 SetLastError(0xdeadbeef);
2960 ret = WinHttpReadData(req, buf, len, &bytes_read);
2961 ok(ret, "expected success\n");
2962 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
2963 "wrong error %u\n", GetLastError());
2964 ok(!bytes_read, "expected 0, got %u\n", bytes_read);
2966 size = 12345;
2967 ret = WinHttpQueryDataAvailable(req, &size);
2968 ok(ret, "expected success\n");
2969 ok(size == 0, "expected 0, got %d\n", size);
2971 WinHttpCloseHandle(req);
2973 size = 12345;
2974 SetLastError(0xdeadbeef);
2975 ret = WinHttpQueryDataAvailable(req, &size);
2976 ok(!ret, "expected error\n");
2977 ok(GetLastError() == ERROR_INVALID_HANDLE,
2978 "expected ERROR_INVALID_HANDLE, got 0x%08x\n", GetLastError());
2979 ok(size == 12345, "expected 12345, got %u\n", size);
2981 WinHttpCloseHandle(con);
2982 WinHttpCloseHandle(ses);
2985 static void test_head_request(int port)
2987 HINTERNET ses, con, req;
2988 char buf[128];
2989 DWORD size, len, count, status;
2990 BOOL ret;
2992 ses = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2993 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2995 con = WinHttpConnect(ses, L"localhost", port, 0);
2996 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2998 req = WinHttpOpenRequest(con, L"HEAD", L"/head", NULL, NULL, NULL, 0);
2999 ok(req != NULL, "failed to open a request %u\n", GetLastError());
3001 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
3002 ok(ret, "failed to send request %u\n", GetLastError());
3004 ret = WinHttpReceiveResponse(req, NULL);
3005 ok(ret, "failed to receive response %u\n", GetLastError());
3007 status = 0xdeadbeef;
3008 size = sizeof(status);
3009 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
3010 NULL, &status, &size, NULL);
3011 ok(ret, "failed to get status code %u\n", GetLastError());
3012 ok(status == HTTP_STATUS_OK, "got %u\n", status);
3014 len = 0xdeadbeef;
3015 size = sizeof(len);
3016 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
3017 NULL, &len, &size, 0);
3018 ok(ret, "failed to get content-length header %u\n", GetLastError());
3019 ok(len == HTTP_STATUS_CONTINUE, "got %u\n", len);
3021 count = 0xdeadbeef;
3022 ret = WinHttpQueryDataAvailable(req, &count);
3023 ok(ret, "failed to query data available %u\n", GetLastError());
3024 ok(!count, "got %u\n", count);
3026 len = sizeof(buf);
3027 count = 0xdeadbeef;
3028 ret = WinHttpReadData(req, buf, len, &count);
3029 ok(ret, "failed to read data %u\n", GetLastError());
3030 ok(!count, "got %u\n", count);
3032 count = 0xdeadbeef;
3033 ret = WinHttpQueryDataAvailable(req, &count);
3034 ok(ret, "failed to query data available %u\n", GetLastError());
3035 ok(!count, "got %u\n", count);
3037 WinHttpCloseHandle(req);
3038 WinHttpCloseHandle(con);
3039 WinHttpCloseHandle(ses);
3042 static void test_not_modified(int port)
3044 BOOL ret;
3045 HINTERNET session, request, connection;
3046 DWORD index, len, status, size, start = GetTickCount();
3047 SYSTEMTIME st;
3048 WCHAR today[(sizeof(L"If-Modified-Since: ") + WINHTTP_TIME_FORMAT_BUFSIZE)/sizeof(WCHAR) + 3], buffer[32];
3050 memcpy(today, L"If-Modified-Since: ", sizeof(L"If-Modified-Since: "));
3051 GetSystemTime(&st);
3052 WinHttpTimeFromSystemTime(&st, &today[ARRAY_SIZE(L"If-Modified-Since: ") - 1]);
3054 session = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY,
3055 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
3056 ok(session != NULL, "WinHttpOpen failed: %u\n", GetLastError());
3058 connection = WinHttpConnect(session, L"localhost", port, 0);
3059 ok(connection != NULL, "WinHttpConnect failed: %u\n", GetLastError());
3061 request = WinHttpOpenRequest(connection, NULL, L"/not_modified", NULL, WINHTTP_NO_REFERER,
3062 WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
3063 ok(request != NULL, "WinHttpOpenrequest failed: %u\n", GetLastError());
3065 ret = WinHttpSendRequest(request, today, 0, NULL, 0, 0, 0);
3066 ok(ret, "WinHttpSendRequest failed: %u\n", GetLastError());
3068 ret = WinHttpReceiveResponse(request, NULL);
3069 ok(ret, "WinHttpReceiveResponse failed: %u\n", GetLastError());
3071 index = 0;
3072 len = sizeof(buffer);
3073 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
3074 L"If-Modified-Since", buffer, &len, &index);
3075 ok(ret, "failed to get header %u\n", GetLastError());
3077 status = 0xdeadbeef;
3078 size = sizeof(status);
3079 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER,
3080 NULL, &status, &size, NULL);
3081 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
3082 ok(status == HTTP_STATUS_NOT_MODIFIED, "got %u\n", status);
3084 size = 0xdeadbeef;
3085 ret = WinHttpQueryDataAvailable(request, &size);
3086 ok(ret, "WinHttpQueryDataAvailable failed: %u\n", GetLastError());
3087 ok(!size, "got %u\n", size);
3089 WinHttpCloseHandle(request);
3090 WinHttpCloseHandle(connection);
3091 WinHttpCloseHandle(session);
3092 start = GetTickCount() - start;
3093 ok(start <= 2000, "Expected less than 2 seconds for the test, got %u ms\n", start);
3096 static void test_bad_header( int port )
3098 WCHAR buffer[32];
3099 HINTERNET ses, con, req;
3100 DWORD index, len;
3101 BOOL ret;
3103 ses = WinHttpOpen( L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3104 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3106 con = WinHttpConnect( ses, L"localhost", port, 0 );
3107 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3109 req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
3110 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3112 ret = WinHttpAddRequestHeaders( req, L"Content-Type: text/html\n\r", ~0u, WINHTTP_ADDREQ_FLAG_ADD );
3113 ok( ret, "failed to add header %u\n", GetLastError() );
3115 index = 0;
3116 buffer[0] = 0;
3117 len = sizeof(buffer);
3118 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_CUSTOM|WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
3119 L"Content-Type", buffer, &len, &index );
3120 ok( ret, "failed to query headers %u\n", GetLastError() );
3121 ok( !lstrcmpW( buffer, L"text/html" ), "got %s\n", wine_dbgstr_w(buffer) );
3122 ok( index == 1, "index = %u\n", index );
3124 WinHttpCloseHandle( req );
3125 WinHttpCloseHandle( con );
3126 WinHttpCloseHandle( ses );
3129 static void test_multiple_reads(int port)
3131 HINTERNET ses, con, req;
3132 DWORD total_len = 0;
3133 BOOL ret;
3135 ses = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
3136 ok(ses != NULL, "failed to open session %u\n", GetLastError());
3138 con = WinHttpConnect(ses, L"localhost", port, 0);
3139 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
3141 req = WinHttpOpenRequest(con, NULL, L"big", NULL, NULL, NULL, 0);
3142 ok(req != NULL, "failed to open a request %u\n", GetLastError());
3144 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
3145 ok(ret, "failed to send request %u\n", GetLastError());
3147 ret = WinHttpReceiveResponse(req, NULL);
3148 ok(ret == TRUE, "expected success\n");
3150 for (;;)
3152 DWORD len = 0xdeadbeef;
3153 ret = WinHttpQueryDataAvailable( req, &len );
3154 ok( ret, "WinHttpQueryDataAvailable failed with error %u\n", GetLastError() );
3155 if (ret) ok( len != 0xdeadbeef, "WinHttpQueryDataAvailable return wrong length\n" );
3156 if (len)
3158 DWORD bytes_read;
3159 char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 );
3161 ret = WinHttpReadData( req, buf, len, &bytes_read );
3162 ok(ret, "WinHttpReadData failed: %u.\n", GetLastError());
3163 ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len );
3165 HeapFree( GetProcessHeap(), 0, buf );
3166 if (!bytes_read) break;
3167 total_len += bytes_read;
3169 if (!len) break;
3171 ok(total_len == BIG_BUFFER_LEN, "got wrong length: 0x%x\n", total_len);
3173 WinHttpCloseHandle(req);
3174 WinHttpCloseHandle(con);
3175 WinHttpCloseHandle(ses);
3178 static void test_cookies( int port )
3180 HINTERNET ses, con, req;
3181 DWORD status, size;
3182 BOOL ret;
3184 ses = WinHttpOpen( L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3185 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3187 con = WinHttpConnect( ses, L"localhost", port, 0 );
3188 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3190 req = WinHttpOpenRequest( con, NULL, L"/cookie", NULL, NULL, NULL, 0 );
3191 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3193 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3194 ok( ret, "failed to send request %u\n", GetLastError() );
3196 ret = WinHttpReceiveResponse( req, NULL );
3197 ok( ret, "failed to receive response %u\n", GetLastError() );
3199 status = 0xdeadbeef;
3200 size = sizeof(status);
3201 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3202 ok( ret, "failed to query status code %u\n", GetLastError() );
3203 ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
3205 WinHttpCloseHandle( req );
3207 req = WinHttpOpenRequest( con, NULL, L"/cookie2", NULL, NULL, NULL, 0 );
3208 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3210 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3211 ok( ret, "failed to send request %u\n", GetLastError() );
3213 ret = WinHttpReceiveResponse( req, NULL );
3214 ok( ret, "failed to receive response %u\n", GetLastError() );
3216 status = 0xdeadbeef;
3217 size = sizeof(status);
3218 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3219 ok( ret, "failed to query status code %u\n", GetLastError() );
3220 ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
3222 WinHttpCloseHandle( req );
3223 WinHttpCloseHandle( con );
3225 con = WinHttpConnect( ses, L"localhost", port, 0 );
3226 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3228 req = WinHttpOpenRequest( con, NULL, L"/cookie2", NULL, NULL, NULL, 0 );
3229 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3231 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3232 ok( ret, "failed to send request %u\n", GetLastError() );
3234 ret = WinHttpReceiveResponse( req, NULL );
3235 ok( ret, "failed to receive response %u\n", GetLastError() );
3237 status = 0xdeadbeef;
3238 size = sizeof(status);
3239 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3240 ok( ret, "failed to query status code %u\n", GetLastError() );
3241 ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
3243 WinHttpCloseHandle( req );
3245 req = WinHttpOpenRequest( con, NULL, L"/cookie3", NULL, NULL, NULL, 0 );
3246 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3247 ret = WinHttpSendRequest( req, L"Cookie: name=value2\r\n", ~0u, NULL, 0, 0, 0 );
3248 ok( ret, "failed to send request %u\n", GetLastError() );
3250 ret = WinHttpReceiveResponse( req, NULL );
3251 ok( ret, "failed to receive response %u\n", GetLastError() );
3253 status = 0xdeadbeef;
3254 size = sizeof(status);
3255 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3256 ok( ret, "failed to query status code %u\n", GetLastError() );
3257 ok( status == HTTP_STATUS_OK || broken(status == HTTP_STATUS_BAD_REQUEST), "request failed unexpectedly %u\n", status );
3259 WinHttpCloseHandle( req );
3260 WinHttpCloseHandle( con );
3261 WinHttpCloseHandle( ses );
3263 ses = WinHttpOpen( L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3264 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3266 con = WinHttpConnect( ses, L"localhost", port, 0 );
3267 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3269 req = WinHttpOpenRequest( con, NULL, L"/cookie2", NULL, NULL, NULL, 0 );
3270 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3272 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3273 ok( ret, "failed to send request %u\n", GetLastError() );
3275 ret = WinHttpReceiveResponse( req, NULL );
3276 ok( ret, "failed to receive response %u\n", GetLastError() );
3278 status = 0xdeadbeef;
3279 size = sizeof(status);
3280 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3281 ok( ret, "failed to query status code %u\n", GetLastError() );
3282 ok( status == HTTP_STATUS_BAD_REQUEST, "request failed unexpectedly %u\n", status );
3284 WinHttpCloseHandle( req );
3285 WinHttpCloseHandle( con );
3286 WinHttpCloseHandle( ses );
3288 ses = WinHttpOpen( L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3289 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3291 con = WinHttpConnect( ses, L"localhost", port, 0 );
3292 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3294 req = WinHttpOpenRequest( con, NULL, L"/cookie4", NULL, NULL, NULL, 0 );
3295 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3297 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3298 ok( ret, "failed to send request %u\n", GetLastError() );
3300 ret = WinHttpReceiveResponse( req, NULL );
3301 ok( ret, "failed to receive response %u\n", GetLastError() );
3303 status = 0xdeadbeef;
3304 size = sizeof(status);
3305 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3306 ok( ret, "failed to query status code %u\n", GetLastError() );
3307 ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
3308 WinHttpCloseHandle( req );
3310 req = WinHttpOpenRequest( con, NULL, L"/cookie5", NULL, NULL, NULL, 0 );
3311 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3313 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3314 ok( ret, "failed to send request %u\n", GetLastError() );
3316 ret = WinHttpReceiveResponse( req, NULL );
3317 ok( ret, "failed to receive response %u\n", GetLastError() );
3319 status = 0xdeadbeef;
3320 size = sizeof(status);
3321 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3322 ok( ret, "failed to query status code %u\n", GetLastError() );
3323 ok( status == HTTP_STATUS_OK || broken(status == HTTP_STATUS_BAD_REQUEST) /* < win7 */,
3324 "request failed unexpectedly %u\n", status );
3326 WinHttpCloseHandle( req );
3327 WinHttpCloseHandle( con );
3328 WinHttpCloseHandle( ses );
3331 static void do_request( HINTERNET con, const WCHAR *obj, DWORD flags )
3333 HINTERNET req;
3334 DWORD status, size;
3335 BOOL ret;
3337 req = WinHttpOpenRequest( con, NULL, obj, NULL, NULL, NULL, flags );
3338 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3340 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3341 ok( ret, "failed to send request %u\n", GetLastError() );
3343 ret = WinHttpReceiveResponse( req, NULL );
3344 ok( ret, "failed to receive response %u\n", GetLastError() );
3346 status = 0xdeadbeef;
3347 size = sizeof(status);
3348 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3349 ok( ret, "failed to query status code %u\n", GetLastError() );
3350 ok( status == HTTP_STATUS_OK || broken(status == HTTP_STATUS_BAD_REQUEST) /* < win7 */,
3351 "request %s with flags %08x failed %u\n", wine_dbgstr_w(obj), flags, status );
3352 WinHttpCloseHandle( req );
3355 static void test_request_path_escapes( int port )
3357 static const WCHAR objW[] =
3358 {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','o','n','e','?',0x1f,0x7f,' ','!','"','#',
3359 '$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^','_','`',
3360 '{','|','}','~','\r','\n',0};
3361 static const WCHAR obj2W[] =
3362 {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','t','w','o','?',0x1f,0x7f,' ','!','"','#',
3363 '$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^','_','`',
3364 '{','|','}','~','\r','\n',0};
3365 static const WCHAR obj3W[] =
3366 {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','t','h','r','e','e','?',0x1f,0x7f,' ','!',
3367 '"','#','$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^',
3368 '_','`','{','|','}','~','\r','\n',0};
3369 static const WCHAR obj4W[] =
3370 {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','f','o','u','r','?',0x1f,0x7f,' ','!','"',
3371 '#','$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^','_',
3372 '`','{','|','}','~','\r','\n',0};
3373 static const WCHAR obj5W[] =
3374 {'/','e','s','c','a','p','e','&','t','e','x','t','=','o','n','e',0x80,0x7f,0x7e,0};
3375 static const WCHAR obj6W[] =
3376 {'/','e','s','c','a','p','e','&','t','e','x','t','=','t','w','o',0x80,0x7f,0x7e,0};
3377 static const WCHAR obj7W[] =
3378 {'/','e','s','c','a','p','e','&','t','e','x','t','=',0x541b,0x306e,0x540d,0x306f,0};
3379 HINTERNET ses, con;
3381 ses = WinHttpOpen( L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3382 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3384 con = WinHttpConnect( ses, L"localhost", port, 0 );
3385 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3387 do_request( con, objW, 0 );
3388 do_request( con, obj2W, WINHTTP_FLAG_ESCAPE_PERCENT );
3389 do_request( con, obj3W, WINHTTP_FLAG_ESCAPE_DISABLE );
3390 do_request( con, obj4W, WINHTTP_FLAG_ESCAPE_DISABLE_QUERY );
3391 do_request( con, obj5W, 0 );
3392 do_request( con, obj6W, WINHTTP_FLAG_ESCAPE_DISABLE );
3393 do_request( con, obj7W, WINHTTP_FLAG_ESCAPE_DISABLE );
3395 WinHttpCloseHandle( con );
3396 WinHttpCloseHandle( ses );
3399 static void test_connection_info( int port )
3401 HINTERNET ses, con, req;
3402 WINHTTP_CONNECTION_INFO info;
3403 DWORD size, error;
3404 BOOL ret;
3406 ses = WinHttpOpen( L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3407 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3409 con = WinHttpConnect( ses, L"localhost", port, 0 );
3410 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3412 req = WinHttpOpenRequest( con, NULL, L"/basic", NULL, NULL, NULL, 0 );
3413 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3415 size = sizeof(info);
3416 SetLastError( 0xdeadbeef );
3417 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3418 error = GetLastError();
3419 if (!ret && error == ERROR_INVALID_PARAMETER)
3421 win_skip( "WINHTTP_OPTION_CONNECTION_INFO not supported\n" );
3422 return;
3424 ok( !ret, "unexpected success\n" );
3425 ok( error == ERROR_WINHTTP_INCORRECT_HANDLE_STATE, "got %u\n", error );
3427 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3428 ok( ret, "failed to send request %u\n", GetLastError() );
3430 size = 0;
3431 SetLastError( 0xdeadbeef );
3432 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3433 error = GetLastError();
3434 ok( !ret, "unexpected success\n" );
3435 ok( error == ERROR_INSUFFICIENT_BUFFER, "got %u\n", error );
3437 size = sizeof(info);
3438 memset( &info, 0, sizeof(info) );
3439 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3440 ok( ret, "failed to retrieve connection info %u\n", GetLastError() );
3441 ok( info.cbSize == sizeof(info) || info.cbSize == sizeof(info) - sizeof(info.cbSize) /* Win7 */, "wrong size %u\n", info.cbSize );
3443 ret = WinHttpReceiveResponse( req, NULL );
3444 ok( ret, "failed to receive response %u\n", GetLastError() );
3446 size = sizeof(info);
3447 memset( &info, 0, sizeof(info) );
3448 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3449 ok( ret, "failed to retrieve connection info %u\n", GetLastError() );
3450 ok( info.cbSize == sizeof(info) || info.cbSize == sizeof(info) - sizeof(info.cbSize) /* Win7 */, "wrong size %u\n", info.cbSize );
3452 WinHttpCloseHandle( req );
3453 WinHttpCloseHandle( con );
3454 WinHttpCloseHandle( ses );
3457 static void test_passport_auth( int port )
3459 static const WCHAR headersW[] =
3460 L"HTTP/1.1 401 Found\r\nContent-Length: 0\r\nLocation: /\r\nWWW-Authenticate: Passport1.4\r\n\r\n";
3461 HINTERNET ses, con, req;
3462 DWORD status, size, option, err;
3463 WCHAR buf[128];
3464 BOOL ret;
3466 ses = WinHttpOpen( L"winetest", 0, NULL, NULL, 0 );
3467 ok( ses != NULL, "got %u\n", GetLastError() );
3469 option = WINHTTP_ENABLE_PASSPORT_AUTH;
3470 ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH, &option, sizeof(option) );
3471 ok( ret, "got %u\n", GetLastError() );
3473 con = WinHttpConnect( ses, L"localhost", port, 0 );
3474 ok( con != NULL, "got %u\n", GetLastError() );
3476 req = WinHttpOpenRequest( con, NULL, L"/passport", NULL, NULL, NULL, 0 );
3477 ok( req != NULL, "got %u\n", GetLastError() );
3479 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3480 ok( ret, "got %u\n", GetLastError() );
3482 ret = WinHttpReceiveResponse( req, NULL );
3483 err = GetLastError();
3484 ok( ret || broken(!ret && err == ERROR_WINHTTP_LOGIN_FAILURE) /* winxp */
3485 || broken(!ret && err == ERROR_WINHTTP_INVALID_SERVER_RESPONSE ), "got %u\n", err );
3486 if (!ret)
3488 win_skip("no support for Passport redirects\n");
3489 goto cleanup;
3492 status = 0xdeadbeef;
3493 size = sizeof(status);
3494 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3495 ok( ret, "got %u\n", GetLastError() );
3496 ok( status == HTTP_STATUS_DENIED, "got %u\n", status );
3498 buf[0] = 0;
3499 size = sizeof(buf);
3500 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_TEXT, NULL, buf, &size, NULL );
3501 ok( ret, "got %u\n", GetLastError() );
3502 ok( !lstrcmpW(L"Found", buf) || broken(!lstrcmpW(L"Unauthorized", buf)) /* < win7 */, "got %s\n",
3503 wine_dbgstr_w(buf) );
3505 buf[0] = 0;
3506 size = sizeof(buf);
3507 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, buf, &size, NULL );
3508 ok( ret || broken(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER) /* < win7 */, "got %u\n", GetLastError() );
3509 if (ret)
3511 ok( size == lstrlenW(headersW) * sizeof(WCHAR), "got %u\n", size );
3512 ok( !lstrcmpW(headersW, buf), "got %s\n", wine_dbgstr_w(buf) );
3515 cleanup:
3516 WinHttpCloseHandle( req );
3517 WinHttpCloseHandle( con );
3518 WinHttpCloseHandle( ses );
3521 static void test_credentials(void)
3523 static WCHAR userW[] = {'u','s','e','r',0};
3524 static WCHAR passW[] = {'p','a','s','s',0};
3525 static WCHAR proxy_userW[] = {'p','r','o','x','y','u','s','e','r',0};
3526 static WCHAR proxy_passW[] = {'p','r','o','x','y','p','a','s','s',0};
3527 HINTERNET ses, con, req;
3528 DWORD size, error;
3529 WCHAR buffer[32];
3530 BOOL ret;
3532 ses = WinHttpOpen(L"winetest", 0, proxy_userW, proxy_passW, 0);
3533 ok(ses != NULL, "failed to open session %u\n", GetLastError());
3535 con = WinHttpConnect(ses, L"localhost", 0, 0);
3536 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
3538 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
3539 ok(req != NULL, "failed to open a request %u\n", GetLastError());
3541 size = ARRAY_SIZE(buffer);
3542 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size);
3543 ok(ret, "failed to query proxy username %u\n", GetLastError());
3544 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3545 ok(!size, "expected 0, got %u\n", size);
3547 size = ARRAY_SIZE(buffer);
3548 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size);
3549 ok(ret, "failed to query proxy password %u\n", GetLastError());
3550 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3551 ok(!size, "expected 0, got %u\n", size);
3553 ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_USERNAME, proxy_userW, lstrlenW(proxy_userW));
3554 ok(ret, "failed to set username %u\n", GetLastError());
3556 size = ARRAY_SIZE(buffer);
3557 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size);
3558 ok(ret, "failed to query proxy username %u\n", GetLastError());
3559 ok(!wcscmp(buffer, proxy_userW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3560 ok(size == lstrlenW(proxy_userW) * sizeof(WCHAR), "unexpected result %u\n", size);
3562 size = ARRAY_SIZE(buffer);
3563 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
3564 ok(ret, "failed to query username %u\n", GetLastError());
3565 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3566 ok(!size, "expected 0, got %u\n", size);
3568 size = ARRAY_SIZE(buffer);
3569 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3570 ok(ret, "failed to query password %u\n", GetLastError());
3571 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3572 ok(!size, "expected 0, got %u\n", size);
3574 ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_PASSWORD, proxy_passW, lstrlenW(proxy_passW));
3575 ok(ret, "failed to set proxy password %u\n", GetLastError());
3577 size = ARRAY_SIZE(buffer);
3578 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size);
3579 ok(ret, "failed to query proxy password %u\n", GetLastError());
3580 ok(!wcscmp(buffer, proxy_passW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3581 ok(size == lstrlenW(proxy_passW) * sizeof(WCHAR), "unexpected result %u\n", size);
3583 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
3584 ok(ret, "failed to set username %u\n", GetLastError());
3586 size = ARRAY_SIZE(buffer);
3587 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
3588 ok(ret, "failed to query username %u\n", GetLastError());
3589 ok(!wcscmp(buffer, userW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3590 ok(size == lstrlenW(userW) * sizeof(WCHAR), "unexpected result %u\n", size);
3592 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, passW, lstrlenW(passW));
3593 ok(ret, "failed to set password %u\n", GetLastError());
3595 size = ARRAY_SIZE(buffer);
3596 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3597 ok(ret, "failed to query password %u\n", GetLastError());
3598 ok(!wcscmp(buffer, passW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3599 ok(size == lstrlenW(passW) * sizeof(WCHAR), "unexpected result %u\n", size);
3601 WinHttpCloseHandle(req);
3603 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
3604 ok(req != NULL, "failed to open a request %u\n", GetLastError());
3606 SetLastError(0xdeadbeef);
3607 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, NULL, NULL);
3608 error = GetLastError();
3609 ok(!ret, "expected failure\n");
3610 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
3612 SetLastError(0xdeadbeef);
3613 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, passW, NULL);
3614 error = GetLastError();
3615 ok(!ret, "expected failure\n");
3616 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
3618 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
3619 ok(ret, "failed to set credentials %u\n", GetLastError());
3621 size = ARRAY_SIZE(buffer);
3622 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
3623 ok(ret, "failed to query username %u\n", GetLastError());
3624 todo_wine {
3625 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3626 ok(!size, "expected 0, got %u\n", size);
3629 size = ARRAY_SIZE(buffer);
3630 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3631 ok(ret, "failed to query password %u\n", GetLastError());
3632 todo_wine {
3633 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3634 ok(!size, "expected 0, got %u\n", size);
3637 WinHttpCloseHandle(req);
3638 WinHttpCloseHandle(con);
3639 WinHttpCloseHandle(ses);
3642 static void test_IWinHttpRequest(int port)
3644 static const WCHAR data_start[] = {'<','!','D','O','C','T','Y','P','E',' ','h','t','m','l',' ','P','U','B','L','I','C'};
3645 HRESULT hr;
3646 IWinHttpRequest *req;
3647 BSTR method, url, username, password, response = NULL, status_text = NULL, headers = NULL;
3648 BSTR date, today, connection, value = NULL;
3649 VARIANT async, empty, timeout, body, body2, proxy_server, bypass_list, data, cp;
3650 VARIANT_BOOL succeeded;
3651 LONG status;
3652 WCHAR todayW[WINHTTP_TIME_FORMAT_BUFSIZE];
3653 SYSTEMTIME st;
3654 IStream *stream, *stream2;
3655 LARGE_INTEGER pos;
3656 char buf[128];
3657 WCHAR bufW[128];
3658 DWORD count;
3660 GetSystemTime( &st );
3661 WinHttpTimeFromSystemTime( &st, todayW );
3663 CoInitialize( NULL );
3664 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3665 ok( hr == S_OK, "got %08x\n", hr );
3667 V_VT( &empty ) = VT_ERROR;
3668 V_ERROR( &empty ) = 0xdeadbeef;
3670 V_VT( &async ) = VT_BOOL;
3671 V_BOOL( &async ) = VARIANT_FALSE;
3673 method = SysAllocString( L"POST" );
3674 url = SysAllocString( L"http://test.winehq.org/tests/post.php" );
3675 hr = IWinHttpRequest_Open( req, method, url, async );
3676 ok( hr == S_OK, "got %08x\n", hr );
3677 SysFreeString( method );
3678 SysFreeString( url );
3680 V_VT( &data ) = VT_BSTR;
3681 V_BSTR( &data ) = SysAllocString( L"testdata\x80" );
3682 hr = IWinHttpRequest_Send( req, data );
3683 ok( hr == S_OK || hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_INVALID_SERVER_RESPONSE ), "got %08x\n", hr );
3684 SysFreeString( V_BSTR( &data ) );
3685 if (hr != S_OK) goto done;
3687 hr = IWinHttpRequest_Open( req, NULL, NULL, empty );
3688 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3690 method = SysAllocString( L"GET" );
3691 hr = IWinHttpRequest_Open( req, method, NULL, empty );
3692 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3694 hr = IWinHttpRequest_Open( req, method, NULL, async );
3695 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3697 url = SysAllocString( L"http://test.winehq.org" );
3698 hr = IWinHttpRequest_Open( req, NULL, url, empty );
3699 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3701 hr = IWinHttpRequest_Abort( req );
3702 ok( hr == S_OK, "got %08x\n", hr );
3704 hr = IWinHttpRequest_Open( req, method, url, empty );
3705 ok( hr == S_OK, "got %08x\n", hr );
3707 hr = IWinHttpRequest_Abort( req );
3708 ok( hr == S_OK, "got %08x\n", hr );
3710 IWinHttpRequest_Release( req );
3712 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3713 ok( hr == S_OK, "got %08x\n", hr );
3715 SysFreeString( url );
3716 url = SysAllocString( L"test.winehq.org" );
3717 hr = IWinHttpRequest_Open( req, method, url, async );
3718 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ), "got %08x\n", hr );
3720 SysFreeString( method );
3721 method = SysAllocString( L"INVALID" );
3722 hr = IWinHttpRequest_Open( req, method, url, async );
3723 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ), "got %08x\n", hr );
3725 SysFreeString( method );
3726 method = SysAllocString( L"GET" );
3727 SysFreeString( url );
3728 url = SysAllocString( L"http://test.winehq.org" );
3729 V_VT( &async ) = VT_ERROR;
3730 V_ERROR( &async ) = DISP_E_PARAMNOTFOUND;
3731 hr = IWinHttpRequest_Open( req, method, url, async );
3732 ok( hr == S_OK, "got %08x\n", hr );
3734 V_VT( &cp ) = VT_ERROR;
3735 V_ERROR( &cp ) = 0xdeadbeef;
3736 hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3737 ok( hr == S_OK, "got %08x\n", hr );
3738 ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3739 ok( V_I4( &cp ) == CP_UTF8, "got %u\n", V_I4( &cp ) );
3741 V_VT( &cp ) = VT_UI4;
3742 V_UI4( &cp ) = CP_ACP;
3743 hr = IWinHttpRequest_put_Option( req, WinHttpRequestOption_URLCodePage, cp );
3744 ok( hr == S_OK, "got %08x\n", hr );
3746 V_VT( &cp ) = VT_ERROR;
3747 V_ERROR( &cp ) = 0xdeadbeef;
3748 hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3749 ok( hr == S_OK, "got %08x\n", hr );
3750 ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3751 ok( V_I4( &cp ) == CP_ACP, "got %u\n", V_I4( &cp ) );
3753 value = SysAllocString( L"utf-8" );
3754 V_VT( &cp ) = VT_BSTR;
3755 V_BSTR( &cp ) = value;
3756 hr = IWinHttpRequest_put_Option( req, WinHttpRequestOption_URLCodePage, cp );
3757 ok( hr == S_OK, "got %08x\n", hr );
3758 SysFreeString( value );
3760 V_VT( &cp ) = VT_ERROR;
3761 V_ERROR( &cp ) = 0xdeadbeef;
3762 hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3763 ok( hr == S_OK, "got %08x\n", hr );
3764 ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3765 ok( V_I4( &cp ) == CP_UTF8, "got %u\n", V_I4( &cp ) );
3767 hr = IWinHttpRequest_Abort( req );
3768 ok( hr == S_OK, "got %08x\n", hr );
3770 hr = IWinHttpRequest_Send( req, empty );
3771 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3773 hr = IWinHttpRequest_Abort( req );
3774 ok( hr == S_OK, "got %08x\n", hr );
3776 IWinHttpRequest_Release( req );
3778 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3779 ok( hr == S_OK, "got %08x\n", hr );
3781 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3782 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3784 hr = IWinHttpRequest_get_ResponseText( req, &response );
3785 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3787 hr = IWinHttpRequest_get_Status( req, NULL );
3788 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3790 hr = IWinHttpRequest_get_Status( req, &status );
3791 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3793 hr = IWinHttpRequest_get_StatusText( req, NULL );
3794 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3796 hr = IWinHttpRequest_get_StatusText( req, &status_text );
3797 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3799 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3800 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3802 hr = IWinHttpRequest_SetTimeouts( req, 10000, 10000, 10000, 10000 );
3803 ok( hr == S_OK, "got %08x\n", hr );
3805 hr = IWinHttpRequest_SetCredentials( req, NULL, NULL, 0xdeadbeef );
3806 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3808 VariantInit( &proxy_server );
3809 V_VT( &proxy_server ) = VT_ERROR;
3810 VariantInit( &bypass_list );
3811 V_VT( &bypass_list ) = VT_ERROR;
3812 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3813 ok( hr == S_OK, "got %08x\n", hr );
3815 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3816 ok( hr == S_OK, "got %08x\n", hr );
3818 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3819 ok( hr == S_OK, "got %08x\n", hr );
3821 hr = IWinHttpRequest_GetAllResponseHeaders( req, NULL );
3822 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3824 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3825 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3827 hr = IWinHttpRequest_GetResponseHeader( req, NULL, NULL );
3828 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3830 connection = SysAllocString( L"Connection" );
3831 hr = IWinHttpRequest_GetResponseHeader( req, connection, NULL );
3832 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3834 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3835 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3837 hr = IWinHttpRequest_SetRequestHeader( req, NULL, NULL );
3838 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3840 date = SysAllocString( L"Date" );
3841 hr = IWinHttpRequest_SetRequestHeader( req, date, NULL );
3842 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3844 today = SysAllocString( todayW );
3845 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3846 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3848 hr = IWinHttpRequest_SetAutoLogonPolicy( req, 0xdeadbeef );
3849 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3851 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3852 ok( hr == S_OK, "got %08x\n", hr );
3854 SysFreeString( method );
3855 method = SysAllocString( L"GET" );
3856 SysFreeString( url );
3857 url = SysAllocString( L"http://test.winehq.org" );
3858 hr = IWinHttpRequest_Open( req, method, url, async );
3859 ok( hr == S_OK, "got %08x\n", hr );
3861 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3862 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3864 hr = IWinHttpRequest_get_ResponseText( req, &response );
3865 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3867 hr = IWinHttpRequest_get_Status( req, &status );
3868 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3870 hr = IWinHttpRequest_get_StatusText( req, &status_text );
3871 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3873 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3874 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3876 hr = IWinHttpRequest_SetTimeouts( req, 10000, 10000, 10000, 10000 );
3877 ok( hr == S_OK, "got %08x\n", hr );
3879 hr = IWinHttpRequest_SetCredentials( req, NULL, NULL, 0xdeadbeef );
3880 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3882 username = SysAllocString( L"username" );
3883 hr = IWinHttpRequest_SetCredentials( req, username, NULL, 0xdeadbeef );
3884 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3886 password = SysAllocString( L"password" );
3887 hr = IWinHttpRequest_SetCredentials( req, NULL, password, 0xdeadbeef );
3888 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3890 hr = IWinHttpRequest_SetCredentials( req, username, password, 0xdeadbeef );
3891 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3893 hr = IWinHttpRequest_SetCredentials( req, NULL, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3894 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3896 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3897 ok( hr == S_OK, "got %08x\n", hr );
3899 V_VT( &proxy_server ) = VT_BSTR;
3900 V_BSTR( &proxy_server ) = SysAllocString( L"proxyserver" );
3901 V_VT( &bypass_list ) = VT_BSTR;
3902 V_BSTR( &bypass_list ) = SysAllocString( L"bypasslist" );
3903 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3904 ok( hr == S_OK, "got %08x\n", hr );
3906 hr = IWinHttpRequest_SetProxy( req, 0xdeadbeef, proxy_server, bypass_list );
3907 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3909 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3910 ok( hr == S_OK, "got %08x\n", hr );
3912 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3913 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3915 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3916 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3918 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3919 ok( hr == S_OK, "got %08x\n", hr );
3921 hr = IWinHttpRequest_SetRequestHeader( req, date, NULL );
3922 ok( hr == S_OK, "got %08x\n", hr );
3924 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3925 ok( hr == S_OK, "got %08x\n", hr );
3927 hr = IWinHttpRequest_Send( req, empty );
3928 ok( hr == S_OK, "got %08x\n", hr );
3930 hr = IWinHttpRequest_Send( req, empty );
3931 ok( hr == S_OK, "got %08x\n", hr );
3933 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3934 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3936 hr = IWinHttpRequest_get_ResponseText( req, &response );
3937 ok( hr == S_OK, "got %08x\n", hr );
3938 ok( !memcmp(response, data_start, sizeof(data_start)), "got %s\n", wine_dbgstr_wn(response, 32) );
3939 SysFreeString( response );
3941 hr = IWinHttpRequest_get_Status( req, NULL );
3942 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3944 status = 0;
3945 hr = IWinHttpRequest_get_Status( req, &status );
3946 ok( hr == S_OK, "got %08x\n", hr );
3947 trace("Status=%d\n", status);
3949 hr = IWinHttpRequest_get_StatusText( req, NULL );
3950 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3952 hr = IWinHttpRequest_get_StatusText( req, &status_text );
3953 ok( hr == S_OK, "got %08x\n", hr );
3954 trace("StatusText=%s\n", wine_dbgstr_w(status_text));
3955 SysFreeString( status_text );
3957 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3958 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3960 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3961 ok( hr == S_OK, "got %08x\n", hr );
3963 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3964 ok( hr == S_OK, "got %08x\n", hr );
3966 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3967 ok( hr == S_OK, "got %08x\n", hr );
3969 hr = IWinHttpRequest_GetAllResponseHeaders( req, NULL );
3970 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3972 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3973 ok( hr == S_OK, "got %08x\n", hr );
3974 SysFreeString( headers );
3976 hr = IWinHttpRequest_GetResponseHeader( req, NULL, NULL );
3977 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3979 hr = IWinHttpRequest_GetResponseHeader( req, connection, NULL );
3980 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3982 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3983 ok( hr == S_OK, "got %08x\n", hr );
3984 SysFreeString( value );
3986 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3987 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND ), "got %08x\n", hr );
3989 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3990 ok( hr == S_OK, "got %08x\n", hr );
3992 VariantInit( &timeout );
3993 V_VT( &timeout ) = VT_I4;
3994 V_I4( &timeout ) = 10;
3995 hr = IWinHttpRequest_WaitForResponse( req, timeout, &succeeded );
3996 ok( hr == S_OK, "got %08x\n", hr );
3998 hr = IWinHttpRequest_get_Status( req, &status );
3999 ok( hr == S_OK, "got %08x\n", hr );
4001 hr = IWinHttpRequest_get_StatusText( req, &status_text );
4002 ok( hr == S_OK, "got %08x\n", hr );
4003 SysFreeString( status_text );
4005 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
4006 ok( hr == S_OK, "got %08x\n", hr );
4008 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
4009 ok( hr == S_OK, "got %08x\n", hr );
4011 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
4012 ok( hr == S_OK, "got %08x\n", hr );
4014 hr = IWinHttpRequest_Send( req, empty );
4015 ok( hr == S_OK, "got %08x\n", hr );
4017 hr = IWinHttpRequest_get_ResponseText( req, NULL );
4018 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4020 hr = IWinHttpRequest_get_ResponseText( req, &response );
4021 ok( hr == S_OK, "got %08x\n", hr );
4022 SysFreeString( response );
4024 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
4025 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4027 VariantInit( &body );
4028 V_VT( &body ) = VT_ERROR;
4029 hr = IWinHttpRequest_get_ResponseBody( req, &body );
4030 ok( hr == S_OK, "got %08x\n", hr );
4031 ok( V_VT( &body ) == (VT_ARRAY|VT_UI1), "got %08x\n", V_VT( &body ) );
4033 hr = VariantClear( &body );
4034 ok( hr == S_OK, "got %08x\n", hr );
4036 VariantInit( &body );
4037 V_VT( &body ) = VT_ERROR;
4038 hr = IWinHttpRequest_get_ResponseStream( req, &body );
4039 ok( hr == S_OK, "got %08x\n", hr );
4040 ok( V_VT( &body ) == VT_UNKNOWN, "got %08x\n", V_VT( &body ) );
4042 hr = IUnknown_QueryInterface( V_UNKNOWN( &body ), &IID_IStream, (void **)&stream );
4043 ok( hr == S_OK, "got %08x\n", hr );
4044 ok( V_UNKNOWN( &body ) == (IUnknown *)stream, "got different interface pointer\n" );
4046 buf[0] = 0;
4047 count = 0xdeadbeef;
4048 hr = IStream_Read( stream, buf, 128, &count );
4049 ok( hr == S_OK, "got %08x\n", hr );
4050 ok( count != 0xdeadbeef, "count not set\n" );
4051 ok( buf[0], "no data\n" );
4053 VariantInit( &body2 );
4054 V_VT( &body2 ) = VT_ERROR;
4055 hr = IWinHttpRequest_get_ResponseStream( req, &body2 );
4056 ok( hr == S_OK, "got %08x\n", hr );
4057 ok( V_VT( &body2 ) == VT_UNKNOWN, "got %08x\n", V_VT( &body2 ) );
4058 ok( V_UNKNOWN( &body ) != V_UNKNOWN( &body2 ), "got same interface pointer\n" );
4060 hr = IUnknown_QueryInterface( V_UNKNOWN( &body2 ), &IID_IStream, (void **)&stream2 );
4061 ok( hr == S_OK, "got %08x\n", hr );
4062 ok( V_UNKNOWN( &body2 ) == (IUnknown *)stream2, "got different interface pointer\n" );
4063 IStream_Release( stream2 );
4065 hr = VariantClear( &body );
4066 ok( hr == S_OK, "got %08x\n", hr );
4068 hr = VariantClear( &body2 );
4069 ok( hr == S_OK, "got %08x\n", hr );
4071 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
4072 ok( hr == S_OK, "got %08x\n", hr );
4074 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
4075 ok( hr == S_OK, "got %08x\n", hr );
4077 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
4078 ok( hr == S_OK, "got %08x\n", hr );
4079 SysFreeString( headers );
4081 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
4082 ok( hr == S_OK, "got %08x\n", hr );
4083 SysFreeString( value );
4085 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
4086 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND ), "got %08x\n", hr );
4088 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
4089 ok( hr == S_OK, "got %08x\n", hr );
4091 hr = IWinHttpRequest_Send( req, empty );
4092 ok( hr == S_OK, "got %08x\n", hr );
4094 hr = IWinHttpRequest_Abort( req );
4095 ok( hr == S_OK, "got %08x\n", hr );
4097 hr = IWinHttpRequest_Abort( req );
4098 ok( hr == S_OK, "got %08x\n", hr );
4100 IWinHttpRequest_Release( req );
4102 pos.QuadPart = 0;
4103 hr = IStream_Seek( stream, pos, STREAM_SEEK_SET, NULL );
4104 ok( hr == S_OK, "got %08x\n", hr );
4106 buf[0] = 0;
4107 count = 0xdeadbeef;
4108 hr = IStream_Read( stream, buf, 128, &count );
4109 ok( hr == S_OK, "got %08x\n", hr );
4110 ok( count != 0xdeadbeef, "count not set\n" );
4111 ok( buf[0], "no data\n" );
4112 IStream_Release( stream );
4114 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
4115 ok( hr == S_OK, "got %08x\n", hr );
4117 V_VT( &async ) = VT_I4;
4118 V_I4( &async ) = 1;
4119 hr = IWinHttpRequest_Open( req, method, url, async );
4120 ok( hr == S_OK, "got %08x\n", hr );
4122 hr = IWinHttpRequest_Send( req, empty );
4123 ok( hr == S_OK, "got %08x\n", hr );
4125 hr = IWinHttpRequest_WaitForResponse( req, timeout, &succeeded );
4126 ok( hr == S_OK, "got %08x\n", hr );
4128 IWinHttpRequest_Release( req );
4130 SysFreeString( method );
4131 SysFreeString( url );
4132 SysFreeString( username );
4133 SysFreeString( password );
4134 SysFreeString( connection );
4135 SysFreeString( date );
4136 SysFreeString( today );
4137 VariantClear( &proxy_server );
4138 VariantClear( &bypass_list );
4140 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
4141 ok( hr == S_OK, "got %08x\n", hr );
4143 url = SysAllocString( L"https://test.winehq.org:443" );
4144 method = SysAllocString( L"POST" );
4145 V_VT( &async ) = VT_BOOL;
4146 V_BOOL( &async ) = VARIANT_FALSE;
4147 hr = IWinHttpRequest_Open( req, method, url, async );
4148 ok( hr == S_OK, "got %08x\n", hr );
4149 SysFreeString( method );
4150 SysFreeString( url );
4152 hr = IWinHttpRequest_Send( req, empty );
4153 ok( hr == S_OK || hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_INVALID_SERVER_RESPONSE ) ||
4154 hr == SEC_E_ILLEGAL_MESSAGE /* winxp */, "got %08x\n", hr );
4155 if (hr != S_OK) goto done;
4157 hr = IWinHttpRequest_get_ResponseText( req, &response );
4158 ok( hr == S_OK, "got %08x\n", hr );
4159 ok( !memcmp(response, data_start, sizeof(data_start)), "got %s\n", wine_dbgstr_wn(response, 32) );
4160 SysFreeString( response );
4162 IWinHttpRequest_Release( req );
4164 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
4165 ok( hr == S_OK, "got %08x\n", hr );
4167 sprintf( buf, "http://localhost:%d/auth", port );
4168 MultiByteToWideChar( CP_ACP, 0, buf, -1, bufW, ARRAY_SIZE( bufW ));
4169 url = SysAllocString( bufW );
4170 method = SysAllocString( L"POST" );
4171 V_VT( &async ) = VT_BOOL;
4172 V_BOOL( &async ) = VARIANT_FALSE;
4173 hr = IWinHttpRequest_Open( req, method, url, async );
4174 ok( hr == S_OK, "got %08x\n", hr );
4175 SysFreeString( method );
4176 SysFreeString( url );
4178 hr = IWinHttpRequest_get_Status( req, &status );
4179 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
4181 V_VT( &data ) = VT_BSTR;
4182 V_BSTR( &data ) = SysAllocString( L"testdata\x80" );
4183 hr = IWinHttpRequest_Send( req, data );
4184 ok( hr == S_OK, "got %08x\n", hr );
4185 SysFreeString( V_BSTR( &data ) );
4187 hr = IWinHttpRequest_get_ResponseText( req, &response );
4188 ok( hr == S_OK, "got %08x\n", hr );
4189 ok( !memcmp( response, L"Unauthorized", sizeof(L"Unauthorized") ), "got %s\n", wine_dbgstr_w(response) );
4190 SysFreeString( response );
4192 status = 0xdeadbeef;
4193 hr = IWinHttpRequest_get_Status( req, &status );
4194 ok( hr == S_OK, "got %08x\n", hr );
4195 ok( status == HTTP_STATUS_DENIED, "got %d\n", status );
4197 done:
4198 IWinHttpRequest_Release( req );
4199 CoUninitialize();
4202 static void request_get_property(IWinHttpRequest *request, int property, VARIANT *ret)
4204 DISPPARAMS params;
4205 VARIANT arg;
4206 HRESULT hr;
4208 memset(&params, 0, sizeof(params));
4209 params.cNamedArgs = 0;
4210 params.rgdispidNamedArgs = NULL;
4211 params.cArgs = 1;
4212 params.rgvarg = &arg;
4213 VariantInit(&arg);
4214 V_VT(&arg) = VT_I4;
4215 V_I4(&arg) = property;
4216 VariantInit(ret);
4217 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
4218 DISPATCH_PROPERTYGET, &params, ret, NULL, NULL);
4219 ok(hr == S_OK, "error %#x\n", hr);
4222 static void test_IWinHttpRequest_Invoke(void)
4224 WCHAR openW[] = {'O','p','e','n',0};
4225 WCHAR optionW[] = {'O','p','t','i','o','n',0};
4226 OLECHAR *open = openW, *option = optionW;
4227 BSTR utf8;
4228 CLSID clsid;
4229 IWinHttpRequest *request;
4230 IDispatch *dispatch;
4231 DISPID id;
4232 DISPPARAMS params;
4233 VARIANT arg[3], ret;
4234 UINT err;
4235 BOOL bret;
4236 HRESULT hr;
4238 CoInitialize(NULL);
4240 hr = CLSIDFromProgID(L"WinHttp.WinHttpRequest.5.1", &clsid);
4241 ok(hr == S_OK, "CLSIDFromProgID error %#x\n", hr);
4242 bret = IsEqualIID(&clsid, &CLSID_WinHttpRequest);
4243 ok(bret || broken(!bret) /* win2003 */, "not expected %s\n", wine_dbgstr_guid(&clsid));
4245 hr = CoCreateInstance(&CLSID_WinHttpRequest, 0, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&request);
4246 ok(hr == S_OK, "error %#x\n", hr);
4248 hr = IWinHttpRequest_QueryInterface(request, &IID_IDispatch, (void **)&dispatch);
4249 ok(hr == S_OK, "error %#x\n", hr);
4250 IDispatch_Release(dispatch);
4252 hr = IWinHttpRequest_GetIDsOfNames(request, &IID_NULL, &open, 1, 0x0409, &id);
4253 ok(hr == S_OK, "error %#x\n", hr);
4254 ok(id == DISPID_HTTPREQUEST_OPEN, "expected DISPID_HTTPREQUEST_OPEN, got %u\n", id);
4256 hr = IWinHttpRequest_GetIDsOfNames(request, &IID_NULL, &option, 1, 0x0409, &id);
4257 ok(hr == S_OK, "error %#x\n", hr);
4258 ok(id == DISPID_HTTPREQUEST_OPTION, "expected DISPID_HTTPREQUEST_OPTION, got %u\n", id);
4260 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4261 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4262 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4264 memset(&params, 0, sizeof(params));
4265 params.cArgs = 2;
4266 params.cNamedArgs = 0;
4267 params.rgvarg = arg;
4268 V_VT(&arg[0]) = VT_I4;
4269 V_I4(&arg[0]) = 1252;
4270 V_VT(&arg[1]) = VT_R8;
4271 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
4272 VariantInit(&ret);
4273 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
4274 DISPATCH_METHOD, &params, NULL, NULL, &err);
4275 ok(hr == S_OK, "error %#x\n", hr);
4277 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4278 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4279 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4281 memset(&params, 0, sizeof(params));
4282 params.cArgs = 2;
4283 params.cNamedArgs = 0;
4284 params.rgvarg = arg;
4285 V_VT(&arg[0]) = VT_I4;
4286 V_I4(&arg[0]) = 1252;
4287 V_VT(&arg[1]) = VT_R8;
4288 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
4289 VariantInit(&ret);
4290 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
4291 DISPATCH_METHOD | DISPATCH_PROPERTYPUT, &params, NULL, NULL, &err);
4292 ok(hr == S_OK, "error %#x\n", hr);
4294 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4295 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4296 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4298 memset(&params, 0, sizeof(params));
4299 params.cArgs = 2;
4300 params.cNamedArgs = 0;
4301 params.rgvarg = arg;
4302 V_VT(&arg[0]) = VT_I4;
4303 V_I4(&arg[0]) = 1252;
4304 V_VT(&arg[1]) = VT_R8;
4305 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
4306 VariantInit(&ret);
4307 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
4308 DISPATCH_PROPERTYPUT, &params, NULL, NULL, &err);
4309 ok(hr == S_OK, "error %#x\n", hr);
4311 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4312 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4313 ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
4315 memset(&params, 0, sizeof(params));
4316 params.cArgs = 2;
4317 params.cNamedArgs = 0;
4318 params.rgvarg = arg;
4319 V_VT(&arg[0]) = VT_BSTR;
4320 utf8 = SysAllocString(L"UTF-8");
4321 V_BSTR(&arg[0]) = utf8;
4322 V_VT(&arg[1]) = VT_R8;
4323 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
4324 hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_METHOD, &params, NULL, NULL, &err);
4325 ok(hr == S_OK, "error %#x\n", hr);
4327 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4328 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4329 ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
4331 VariantInit(&ret);
4332 hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_METHOD, &params, &ret, NULL, &err);
4333 ok(hr == S_OK, "error %#x\n", hr);
4335 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4336 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4337 ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
4339 VariantInit(&ret);
4340 hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
4341 ok(hr == S_OK, "error %#x\n", hr);
4343 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4344 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4345 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4347 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, NULL, NULL, NULL);
4348 ok(hr == S_OK, "error %#x\n", hr);
4350 hr = IWinHttpRequest_Invoke(request, 255, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, NULL, NULL, NULL);
4351 ok(hr == DISP_E_MEMBERNOTFOUND, "error %#x\n", hr);
4353 VariantInit(&ret);
4354 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
4355 ok(hr == DISP_E_UNKNOWNINTERFACE, "error %#x\n", hr);
4357 VariantInit(&ret);
4358 if (0) /* crashes */
4359 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, &ret, NULL, &err);
4361 params.cArgs = 1;
4362 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
4363 ok(hr == DISP_E_TYPEMISMATCH, "error %#x\n", hr);
4365 VariantInit(&arg[2]);
4366 params.cArgs = 3;
4367 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
4368 todo_wine
4369 ok(hr == S_OK, "error %#x\n", hr);
4371 VariantInit(&arg[0]);
4372 VariantInit(&arg[1]);
4373 VariantInit(&arg[2]);
4375 params.cArgs = 1;
4376 V_VT(&arg[0]) = VT_I4;
4377 V_I4(&arg[0]) = WinHttpRequestOption_URLCodePage;
4378 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4379 ok(hr == S_OK, "error %#x\n", hr);
4381 V_VT(&ret) = 0xdead;
4382 V_I4(&ret) = 0xbeef;
4383 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &params, &ret, NULL, NULL);
4384 ok(hr == S_OK, "error %#x\n", hr);
4385 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4386 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4388 V_VT(&ret) = 0xdead;
4389 V_I4(&ret) = 0xbeef;
4390 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD, &params, &ret, NULL, NULL);
4391 ok(hr == S_OK, "error %#x\n", hr);
4392 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4393 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4395 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4396 ok(hr == S_OK, "error %#x\n", hr);
4398 V_VT(&ret) = 0xdead;
4399 V_I4(&ret) = 0xbeef;
4400 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, 0, &params, &ret, NULL, NULL);
4401 ok(hr == S_OK, "error %#x\n", hr);
4402 ok(V_VT(&ret) == VT_EMPTY, "expected VT_EMPTY, got %d\n", V_VT(&ret));
4403 ok(V_I4(&ret) == 0xbeef || V_I4(&ret) == 0 /* Win8 */, "expected 0xdead, got %d\n", V_I4(&ret));
4405 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, 0, &params, NULL, NULL, NULL);
4406 ok(hr == S_OK, "error %#x\n", hr);
4408 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_IUnknown, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4409 ok(hr == DISP_E_UNKNOWNINTERFACE, "error %#x\n", hr);
4411 params.cArgs = 2;
4412 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4413 todo_wine
4414 ok(hr == S_OK, "error %#x\n", hr);
4416 params.cArgs = 0;
4417 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4418 ok(hr == DISP_E_PARAMNOTFOUND, "error %#x\n", hr);
4420 SysFreeString(utf8);
4422 params.cArgs = 1;
4423 V_VT(&arg[0]) = VT_I4;
4424 V_I4(&arg[0]) = AutoLogonPolicy_Never;
4425 VariantInit(&ret);
4426 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_SETAUTOLOGONPOLICY, &IID_NULL, 0,
4427 DISPATCH_METHOD, &params, &ret, NULL, NULL);
4428 ok(hr == S_OK, "error %#x\n", hr);
4430 IWinHttpRequest_Release(request);
4432 CoUninitialize();
4435 static void test_WinHttpDetectAutoProxyConfigUrl(void)
4437 BOOL ret;
4438 WCHAR *url;
4439 DWORD error;
4441 SetLastError(0xdeadbeef);
4442 ret = WinHttpDetectAutoProxyConfigUrl( 0, NULL );
4443 error = GetLastError();
4444 ok( !ret, "expected failure\n" );
4445 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4447 url = NULL;
4448 SetLastError(0xdeadbeef);
4449 ret = WinHttpDetectAutoProxyConfigUrl( 0, &url );
4450 error = GetLastError();
4451 ok( !ret, "expected failure\n" );
4452 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4454 SetLastError(0xdeadbeef);
4455 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, NULL );
4456 error = GetLastError();
4457 ok( !ret, "expected failure\n" );
4458 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4460 url = (WCHAR *)0xdeadbeef;
4461 SetLastError(0xdeadbeef);
4462 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, &url );
4463 error = GetLastError();
4464 if (!ret)
4466 ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED, "got %u\n", error );
4467 ok( !url || broken(url == (WCHAR *)0xdeadbeef), "got %p\n", url );
4469 else
4471 trace("%s\n", wine_dbgstr_w(url));
4472 GlobalFree( url );
4475 url = (WCHAR *)0xdeadbeef;
4476 SetLastError(0xdeadbeef);
4477 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DHCP, &url );
4478 error = GetLastError();
4479 if (!ret)
4481 ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED, "got %u\n", error );
4482 ok( !url || broken(url == (WCHAR *)0xdeadbeef), "got %p\n", url );
4484 else
4486 ok( error == ERROR_SUCCESS, "got %u\n", error );
4487 trace("%s\n", wine_dbgstr_w(url));
4488 GlobalFree( url );
4492 static void test_WinHttpGetIEProxyConfigForCurrentUser(void)
4494 BOOL ret;
4495 DWORD error;
4496 WINHTTP_CURRENT_USER_IE_PROXY_CONFIG cfg;
4498 memset( &cfg, 0, sizeof(cfg) );
4500 SetLastError(0xdeadbeef);
4501 ret = WinHttpGetIEProxyConfigForCurrentUser( NULL );
4502 error = GetLastError();
4503 ok( !ret, "expected failure\n" );
4504 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4506 SetLastError(0xdeadbeef);
4507 ret = WinHttpGetIEProxyConfigForCurrentUser( &cfg );
4508 error = GetLastError();
4509 ok( ret, "expected success\n" );
4510 ok( error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* < win7 */, "got %u\n", error );
4512 trace("IEProxy.AutoDetect=%d\n", cfg.fAutoDetect);
4513 trace("IEProxy.AutoConfigUrl=%s\n", wine_dbgstr_w(cfg.lpszAutoConfigUrl));
4514 trace("IEProxy.Proxy=%s\n", wine_dbgstr_w(cfg.lpszProxy));
4515 trace("IEProxy.ProxyBypass=%s\n", wine_dbgstr_w(cfg.lpszProxyBypass));
4516 GlobalFree( cfg.lpszAutoConfigUrl );
4517 GlobalFree( cfg.lpszProxy );
4518 GlobalFree( cfg.lpszProxyBypass );
4521 static void test_WinHttpGetProxyForUrl(void)
4523 BOOL ret;
4524 DWORD error;
4525 HINTERNET session;
4526 WINHTTP_AUTOPROXY_OPTIONS options;
4527 WINHTTP_PROXY_INFO info;
4529 memset( &options, 0, sizeof(options) );
4531 SetLastError(0xdeadbeef);
4532 ret = WinHttpGetProxyForUrl( NULL, NULL, NULL, NULL );
4533 error = GetLastError();
4534 ok( !ret, "expected failure\n" );
4535 ok( error == ERROR_INVALID_HANDLE, "got %u\n", error );
4537 session = WinHttpOpen( L"winetest", 0, NULL, NULL, 0 );
4538 ok( session != NULL, "failed to open session %u\n", GetLastError() );
4540 SetLastError(0xdeadbeef);
4541 ret = WinHttpGetProxyForUrl( session, NULL, NULL, NULL );
4542 error = GetLastError();
4543 ok( !ret, "expected failure\n" );
4544 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4546 SetLastError(0xdeadbeef);
4547 ret = WinHttpGetProxyForUrl( session, L"", NULL, NULL );
4548 error = GetLastError();
4549 ok( !ret, "expected failure\n" );
4550 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4552 SetLastError(0xdeadbeef);
4553 ret = WinHttpGetProxyForUrl( session, L"http://winehq.org", NULL, NULL );
4554 error = GetLastError();
4555 ok( !ret, "expected failure\n" );
4556 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4558 SetLastError(0xdeadbeef);
4559 ret = WinHttpGetProxyForUrl( session, L"http://winehq.org", &options, &info );
4560 error = GetLastError();
4561 ok( !ret, "expected failure\n" );
4562 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4564 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
4565 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
4567 SetLastError(0xdeadbeef);
4568 ret = WinHttpGetProxyForUrl( session, L"http://winehq.org", &options, NULL );
4569 error = GetLastError();
4570 ok( !ret, "expected failure\n" );
4571 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4573 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
4574 options.dwAutoDetectFlags = 0;
4576 SetLastError(0xdeadbeef);
4577 ret = WinHttpGetProxyForUrl( session, L"http://winehq.org", &options, &info );
4578 error = GetLastError();
4579 ok( !ret, "expected failure\n" );
4580 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4582 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT | WINHTTP_AUTOPROXY_CONFIG_URL;
4583 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
4585 SetLastError(0xdeadbeef);
4586 ret = WinHttpGetProxyForUrl( session, L"http://winehq.org", &options, &info );
4587 error = GetLastError();
4588 ok( !ret, "expected failure\n" );
4589 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4591 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
4592 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
4594 memset( &info, 0, sizeof(info) );
4595 SetLastError(0xdeadbeef);
4596 ret = WinHttpGetProxyForUrl( session, L"http://winehq.org", &options, &info );
4597 error = GetLastError();
4598 if (ret)
4600 ok( error == ERROR_SUCCESS, "got %u\n", error );
4601 trace("Proxy.AccessType=%u\n", info.dwAccessType);
4602 trace("Proxy.Proxy=%s\n", wine_dbgstr_w(info.lpszProxy));
4603 trace("Proxy.ProxyBypass=%s\n", wine_dbgstr_w(info.lpszProxyBypass));
4604 GlobalFree( info.lpszProxy );
4605 GlobalFree( info.lpszProxyBypass );
4608 options.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
4609 options.dwAutoDetectFlags = 0;
4610 options.lpszAutoConfigUrl = L"http://wpad/wpad.dat";
4612 memset( &info, 0, sizeof(info) );
4613 ret = WinHttpGetProxyForUrl( session, L"http://winehq.org", &options, &info );
4614 if (ret)
4616 trace("Proxy.AccessType=%u\n", info.dwAccessType);
4617 trace("Proxy.Proxy=%s\n", wine_dbgstr_w(info.lpszProxy));
4618 trace("Proxy.ProxyBypass=%s\n", wine_dbgstr_w(info.lpszProxyBypass));
4619 GlobalFree( info.lpszProxy );
4620 GlobalFree( info.lpszProxyBypass );
4622 WinHttpCloseHandle( session );
4625 static void test_chunked_read(void)
4627 WCHAR header[32];
4628 DWORD len, err;
4629 HINTERNET ses, con = NULL, req = NULL;
4630 BOOL ret;
4632 trace( "starting chunked read test\n" );
4634 ses = WinHttpOpen( L"winetest", 0, NULL, NULL, 0 );
4635 ok( ses != NULL, "WinHttpOpen failed with error %u\n", GetLastError() );
4636 if (!ses) goto done;
4638 con = WinHttpConnect( ses, L"test.winehq.org", 0, 0 );
4639 ok( con != NULL, "WinHttpConnect failed with error %u\n", GetLastError() );
4640 if (!con) goto done;
4642 req = WinHttpOpenRequest( con, NULL, L"/tests/chunked", NULL, NULL, NULL, 0 );
4643 ok( req != NULL, "WinHttpOpenRequest failed with error %u\n", GetLastError() );
4644 if (!req) goto done;
4646 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
4647 err = GetLastError();
4648 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
4650 skip("connection failed, skipping\n");
4651 goto done;
4653 ok( ret, "WinHttpSendRequest failed with error %u\n", GetLastError() );
4654 if (!ret) goto done;
4656 ret = WinHttpReceiveResponse( req, NULL );
4657 ok( ret, "WinHttpReceiveResponse failed with error %u\n", GetLastError() );
4658 if (!ret) goto done;
4660 header[0] = 0;
4661 len = sizeof(header);
4662 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, header, &len, 0 );
4663 ok( ret, "failed to get TRANSFER_ENCODING header (error %u)\n", GetLastError() );
4664 ok( !lstrcmpW( header, L"chunked" ), "wrong transfer encoding %s\n", wine_dbgstr_w(header) );
4665 trace( "transfer encoding: %s\n", wine_dbgstr_w(header) );
4667 header[0] = 0;
4668 len = sizeof(header);
4669 SetLastError( 0xdeadbeef );
4670 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_CONTENT_LENGTH, NULL, &header, &len, 0 );
4671 ok( !ret, "unexpected CONTENT_LENGTH header %s\n", wine_dbgstr_w(header) );
4672 ok( GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND, "wrong error %u\n", GetLastError() );
4674 trace( "entering query loop\n" );
4675 for (;;)
4677 len = 0xdeadbeef;
4678 ret = WinHttpQueryDataAvailable( req, &len );
4679 ok( ret, "WinHttpQueryDataAvailable failed with error %u\n", GetLastError() );
4680 if (ret) ok( len != 0xdeadbeef, "WinHttpQueryDataAvailable return wrong length\n" );
4681 trace( "got %u available\n", len );
4682 if (len)
4684 DWORD bytes_read;
4685 char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 );
4687 ret = WinHttpReadData( req, buf, len, &bytes_read );
4688 ok(ret, "WinHttpReadData failed: %u.\n", GetLastError());
4690 buf[bytes_read] = 0;
4691 trace( "WinHttpReadData -> %d %u\n", ret, bytes_read );
4692 ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len );
4693 ok( buf[bytes_read - 1] == '\n', "received partial line '%s'\n", buf );
4695 HeapFree( GetProcessHeap(), 0, buf );
4696 if (!bytes_read) break;
4698 if (!len) break;
4700 trace( "done\n" );
4702 done:
4703 if (req) WinHttpCloseHandle( req );
4704 if (con) WinHttpCloseHandle( con );
4705 if (ses) WinHttpCloseHandle( ses );
4708 START_TEST (winhttp)
4710 struct server_info si;
4711 HANDLE thread;
4712 DWORD ret;
4714 test_WinHttpOpenRequest();
4715 test_WinHttpSendRequest();
4716 test_WinHttpTimeFromSystemTime();
4717 test_WinHttpTimeToSystemTime();
4718 test_WinHttpAddHeaders();
4719 test_secure_connection();
4720 test_request_parameter_defaults();
4721 test_WinHttpQueryOption();
4722 test_set_default_proxy_config();
4723 test_empty_headers_param();
4724 test_timeouts();
4725 test_resolve_timeout();
4726 test_credentials();
4727 test_IWinHttpRequest_Invoke();
4728 test_WinHttpDetectAutoProxyConfigUrl();
4729 test_WinHttpGetIEProxyConfigForCurrentUser();
4730 test_WinHttpGetProxyForUrl();
4731 test_chunked_read();
4733 si.event = CreateEventW(NULL, 0, 0, NULL);
4734 si.port = 7532;
4736 thread = CreateThread(NULL, 0, server_thread, &si, 0, NULL);
4737 ok(thread != NULL, "failed to create thread %u\n", GetLastError());
4739 ret = WaitForSingleObject(si.event, 10000);
4740 ok(ret == WAIT_OBJECT_0, "failed to start winhttp test server %u\n", GetLastError());
4741 if (ret != WAIT_OBJECT_0)
4743 CloseHandle(thread);
4744 return;
4747 test_IWinHttpRequest(si.port);
4748 test_connection_info(si.port);
4749 test_basic_request(si.port, NULL, L"/basic");
4750 test_no_headers(si.port);
4751 test_no_content(si.port);
4752 test_head_request(si.port);
4753 test_not_modified(si.port);
4754 test_basic_authentication(si.port);
4755 test_multi_authentication(si.port);
4756 test_large_data_authentication(si.port);
4757 test_bad_header(si.port);
4758 test_multiple_reads(si.port);
4759 test_cookies(si.port);
4760 test_request_path_escapes(si.port);
4761 test_passport_auth(si.port);
4763 /* send the basic request again to shutdown the server thread */
4764 test_basic_request(si.port, NULL, L"/quit");
4766 WaitForSingleObject(thread, 3000);
4767 CloseHandle(thread);