libport: Remove support for PPC32.
[wine.git] / dlls / winhttp / tests / winhttp.c
blob8083c4825b28e41397df88c24fc654ffe8c0cd8c
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 HINTERNET (WINAPI *pWinHttpWebSocketCompleteUpgrade)(HINTERNET,DWORD_PTR);
42 static BOOL proxy_active(void)
44 WINHTTP_PROXY_INFO proxy_info;
45 BOOL active = FALSE;
47 SetLastError(0xdeadbeef);
48 if (WinHttpGetDefaultProxyConfiguration(&proxy_info))
50 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
51 "got %u\n", GetLastError());
52 active = (proxy_info.lpszProxy != NULL);
53 if (active)
54 GlobalFree(proxy_info.lpszProxy);
55 if (proxy_info.lpszProxyBypass != NULL)
56 GlobalFree(proxy_info.lpszProxyBypass);
58 else
59 active = FALSE;
61 return active;
64 static void test_WinHttpQueryOption(void)
66 BOOL ret;
67 HINTERNET session, request, connection;
68 DWORD feature, size;
70 SetLastError(0xdeadbeef);
71 session = WinHttpOpen(L"winetest", 0, 0, 0, 0);
72 ok(session != NULL, "WinHttpOpen failed to open session, error %u\n", GetLastError());
74 SetLastError(0xdeadbeef);
75 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, NULL);
76 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
77 ok(GetLastError() == ERROR_INVALID_PARAMETER,
78 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
80 size = 0xdeadbeef;
81 SetLastError(0xdeadbeef);
82 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, &size);
83 ok(!ret, "should fail to query option\n");
84 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
85 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
86 ok(size == 4, "expected 4, got %u\n", size);
88 feature = 0xdeadbeef;
89 size = sizeof(feature) - 1;
90 SetLastError(0xdeadbeef);
91 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
92 ok(!ret, "should fail to query option\n");
93 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
94 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
95 ok(size == 4, "expected 4, got %u\n", size);
97 feature = 0xdeadbeef;
98 size = sizeof(feature) + 1;
99 SetLastError(0xdeadbeef);
100 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
101 ok(ret, "failed to query option %u\n", GetLastError());
102 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
103 "got %u\n", GetLastError());
104 ok(size == sizeof(feature), "WinHttpQueryOption should set the size: %u\n", size);
105 ok(feature == WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP,
106 "expected WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP, got %#x\n", feature);
108 SetLastError(0xdeadbeef);
109 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, sizeof(feature));
110 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
111 ok(GetLastError() == ERROR_INVALID_PARAMETER,
112 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
114 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
115 SetLastError(0xdeadbeef);
116 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature) - 1);
117 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
118 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
119 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
121 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
122 SetLastError(0xdeadbeef);
123 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature) + 1);
124 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
125 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
126 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
128 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
129 SetLastError(0xdeadbeef);
130 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature));
131 ok(ret, "failed to set redirect policy %u\n", GetLastError());
133 feature = 0xdeadbeef;
134 size = sizeof(feature);
135 SetLastError(0xdeadbeef);
136 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
137 ok(ret, "failed to query option %u\n", GetLastError());
138 ok(feature == WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS,
139 "expected WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS, got %#x\n", feature);
141 feature = WINHTTP_DISABLE_COOKIES;
142 SetLastError(0xdeadbeef);
143 ret = WinHttpSetOption(session, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
144 ok(!ret, "should fail to set disable feature for a session\n");
145 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
146 "expected ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, got %u\n", GetLastError());
148 SetLastError(0xdeadbeef);
149 connection = WinHttpConnect(session, L"test.winehq.org", INTERNET_DEFAULT_HTTP_PORT, 0);
150 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u\n", GetLastError());
152 feature = WINHTTP_DISABLE_COOKIES;
153 SetLastError(0xdeadbeef);
154 ret = WinHttpSetOption(connection, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
155 ok(!ret, "should fail to set disable feature for a connection\n");
156 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
157 "expected ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, got %u\n", GetLastError());
159 SetLastError(0xdeadbeef);
160 request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
161 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
162 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
164 skip("Network unreachable, skipping the test\n");
165 goto done;
168 feature = 0xdeadbeef;
169 size = sizeof(feature);
170 SetLastError(0xdeadbeef);
171 ret = WinHttpQueryOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, &size);
172 ok(!ret, "should fail to query disable feature for a request\n");
173 ok(GetLastError() == ERROR_INVALID_PARAMETER,
174 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
176 feature = 0;
177 size = sizeof(feature);
178 SetLastError(0xdeadbeef);
179 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
180 ok(ret, "failed to set feature %u\n", GetLastError());
182 feature = 0xffffffff;
183 size = sizeof(feature);
184 SetLastError(0xdeadbeef);
185 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
186 ok(ret, "failed to set feature %u\n", GetLastError());
188 feature = WINHTTP_DISABLE_COOKIES;
189 size = sizeof(feature);
190 SetLastError(0xdeadbeef);
191 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
192 ok(ret, "failed to set feature %u\n", GetLastError());
194 size = 0;
195 SetLastError(0xdeadbeef);
196 ret = WinHttpQueryOption(request, WINHTTP_OPTION_DISABLE_FEATURE, NULL, &size);
197 ok(!ret, "should fail to query disable feature for a request\n");
198 ok(GetLastError() == ERROR_INVALID_PARAMETER,
199 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
201 feature = 0xdeadbeef;
202 size = sizeof(feature);
203 SetLastError(0xdeadbeef);
204 ret = WinHttpQueryOption(request, WINHTTP_OPTION_ENABLE_FEATURE, &feature, &size);
205 ok(!ret, "should fail to query enabled features for a request\n");
206 ok(feature == 0xdeadbeef, "expect feature 0xdeadbeef, got %u\n", feature);
207 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
209 feature = WINHTTP_ENABLE_SSL_REVOCATION;
210 SetLastError(0xdeadbeef);
211 ret = WinHttpSetOption(request, WINHTTP_OPTION_ENABLE_FEATURE, 0, sizeof(feature));
212 ok(!ret, "should fail to enable WINHTTP_ENABLE_SSL_REVOCATION with invalid parameters\n");
213 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
215 SetLastError(0xdeadbeef);
216 ret = WinHttpSetOption(request, WINHTTP_OPTION_ENABLE_FEATURE, &feature, 0);
217 ok(!ret, "should fail to enable WINHTTP_ENABLE_SSL_REVOCATION with invalid parameters\n");
218 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
220 SetLastError(0xdeadbeef);
221 ret = WinHttpSetOption(request, WINHTTP_OPTION_ENABLE_FEATURE, &feature, sizeof(feature));
222 ok(ret, "failed to set feature\n");
223 ok(GetLastError() == NO_ERROR || broken(GetLastError() == 0xdeadbeef), /* Doesn't set error code on Vista or older */
224 "expected NO_ERROR, got %u\n", GetLastError());
226 feature = 0xdeadbeef;
227 SetLastError(0xdeadbeef);
228 ret = WinHttpSetOption(request, WINHTTP_OPTION_ENABLE_FEATURE, &feature, sizeof(feature));
229 ok(!ret, "should fail to enable WINHTTP_ENABLE_SSL_REVOCATION with invalid parameters\n");
230 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
232 feature = 6;
233 size = sizeof(feature);
234 ret = WinHttpSetOption(request, WINHTTP_OPTION_CONNECT_RETRIES, &feature, sizeof(feature));
235 ok(ret, "failed to set WINHTTP_OPTION_CONNECT_RETRIES %u\n", GetLastError());
237 SetLastError(0xdeadbeef);
238 ret = WinHttpCloseHandle(request);
239 ok(ret, "WinHttpCloseHandle failed on closing request: %u\n", GetLastError());
241 done:
242 SetLastError(0xdeadbeef);
243 ret = WinHttpCloseHandle(connection);
244 ok(ret, "WinHttpCloseHandle failed on closing connection: %u\n", GetLastError());
245 SetLastError(0xdeadbeef);
246 ret = WinHttpCloseHandle(session);
247 ok(ret, "WinHttpCloseHandle failed on closing session: %u\n", GetLastError());
250 static void test_WinHttpOpenRequest (void)
252 BOOL ret;
253 HINTERNET session, request, connection;
254 DWORD err;
256 SetLastError(0xdeadbeef);
257 session = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
258 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
259 err = GetLastError();
260 ok(session != NULL, "WinHttpOpen failed to open session.\n");
261 ok(err == ERROR_SUCCESS, "got %u\n", err);
263 /* Test with a bad server name */
264 SetLastError(0xdeadbeef);
265 connection = WinHttpConnect(session, NULL, INTERNET_DEFAULT_HTTP_PORT, 0);
266 err = GetLastError();
267 ok (connection == NULL, "WinHttpConnect succeeded in opening connection to NULL server argument.\n");
268 ok(err == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u.\n", err);
270 /* Test with a valid server name */
271 SetLastError(0xdeadbeef);
272 connection = WinHttpConnect (session, L"test.winehq.org", INTERNET_DEFAULT_HTTP_PORT, 0);
273 err = GetLastError();
274 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", err);
275 ok(err == ERROR_SUCCESS || broken(err == WSAEINVAL) /* < win7 */, "got %u\n", err);
277 SetLastError(0xdeadbeef);
278 request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
279 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
280 err = GetLastError();
281 if (request == NULL && err == ERROR_WINHTTP_NAME_NOT_RESOLVED)
283 skip("Network unreachable, skipping.\n");
284 goto done;
286 ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", err);
287 ok(err == ERROR_SUCCESS, "got %u\n", err);
289 SetLastError(0xdeadbeef);
290 ret = WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, NULL, 0, 0, 0);
291 err = GetLastError();
292 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
294 skip("Connection failed, skipping.\n");
295 goto done;
297 ok(ret, "WinHttpSendRequest failed: %u\n", err);
298 ok(err == ERROR_SUCCESS, "got %u\n", err);
300 SetLastError(0xdeadbeef);
301 ret = WinHttpCloseHandle(request);
302 err = GetLastError();
303 ok(ret, "WinHttpCloseHandle failed on closing request, got %u.\n", err);
304 ok(err == ERROR_SUCCESS, "got %u\n", err);
306 done:
307 ret = WinHttpCloseHandle(connection);
308 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
309 ret = WinHttpCloseHandle(session);
310 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
314 static void test_empty_headers_param(void)
316 HINTERNET ses, con, req;
317 DWORD err;
318 BOOL ret;
320 ses = WinHttpOpen(L"winetest", 0, NULL, NULL, 0);
321 ok(ses != NULL, "failed to open session %u\n", GetLastError());
323 con = WinHttpConnect(ses, L"test.winehq.org", 80, 0);
324 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
326 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
327 ok(req != NULL, "failed to open a request %u\n", GetLastError());
329 ret = WinHttpSendRequest(req, L"", 0, NULL, 0, 0, 0);
330 err = GetLastError();
331 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
333 skip("connection failed, skipping\n");
334 goto done;
336 ok(ret, "failed to send request %u\n", GetLastError());
338 done:
339 WinHttpCloseHandle(req);
340 WinHttpCloseHandle(con);
341 WinHttpCloseHandle(ses);
344 static void test_WinHttpSendRequest (void)
346 static const WCHAR content_type[] = L"Content-Type: application/x-www-form-urlencoded";
347 static char post_data[] = "mode=Test";
348 static const char test_post[] = "mode => Test\0\n";
349 HINTERNET session, request, connection;
350 DWORD header_len, optional_len, total_len, bytes_rw, size, err, disable, len;
351 DWORD_PTR context;
352 BOOL ret;
353 CHAR buffer[256];
354 WCHAR method[8];
355 int i;
357 header_len = -1L;
358 total_len = optional_len = sizeof(post_data);
359 memset(buffer, 0xff, sizeof(buffer));
361 session = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
362 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
363 ok(session != NULL, "WinHttpOpen failed to open session.\n");
365 connection = WinHttpConnect (session, L"test.winehq.org", INTERNET_DEFAULT_HTTP_PORT, 0);
366 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
368 request = WinHttpOpenRequest(connection, L"POST", L"tests/post.php", NULL, WINHTTP_NO_REFERER,
369 WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
370 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
372 skip("Network unreachable, skipping.\n");
373 goto done;
375 ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError());
376 if (!request) goto done;
378 method[0] = 0;
379 len = sizeof(method);
380 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_REQUEST_METHOD, NULL, method, &len, NULL);
381 ok(ret, "got %u\n", GetLastError());
382 ok(len == lstrlenW(L"POST") * sizeof(WCHAR), "got %u\n", len);
383 ok(!lstrcmpW(method, L"POST"), "got %s\n", wine_dbgstr_w(method));
385 context = 0xdeadbeef;
386 ret = WinHttpSetOption(request, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(context));
387 ok(ret, "WinHttpSetOption failed: %u\n", GetLastError());
389 /* writing more data than promised by the content-length header causes an error when the connection
390 is reused, so disable keep-alive */
391 disable = WINHTTP_DISABLE_KEEP_ALIVE;
392 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &disable, sizeof(disable));
393 ok(ret, "WinHttpSetOption failed: %u\n", GetLastError());
395 context++;
396 ret = WinHttpSendRequest(request, content_type, header_len, post_data, optional_len, total_len, context);
397 err = GetLastError();
398 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
400 skip("connection failed, skipping\n");
401 goto done;
403 ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError());
405 context = 0;
406 size = sizeof(context);
407 ret = WinHttpQueryOption(request, WINHTTP_OPTION_CONTEXT_VALUE, &context, &size);
408 ok(ret, "WinHttpQueryOption failed: %u\n", GetLastError());
409 ok(context == 0xdeadbef0, "expected 0xdeadbef0, got %lx\n", context);
411 for (i = 3; post_data[i]; i++)
413 bytes_rw = -1;
414 SetLastError(0xdeadbeef);
415 ret = WinHttpWriteData(request, &post_data[i], 1, &bytes_rw);
416 if (ret)
418 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %u.\n", GetLastError());
419 ok(bytes_rw == 1, "WinHttpWriteData failed, wrote %u bytes instead of 1 byte.\n", bytes_rw);
421 else /* Since we already passed all optional data in WinHttpSendRequest Win7 fails our WinHttpWriteData call */
423 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER got %u.\n", GetLastError());
424 ok(bytes_rw == -1, "Expected bytes_rw to remain unchanged.\n");
428 SetLastError(0xdeadbeef);
429 ret = WinHttpReceiveResponse(request, NULL);
430 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == ERROR_NO_TOKEN) /* < win7 */,
431 "Expected ERROR_SUCCESS got %u.\n", GetLastError());
432 ok(ret == TRUE, "WinHttpReceiveResponse failed: %u.\n", GetLastError());
434 SetLastError(0xdeadbeef);
435 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_ORIG_URI, NULL, NULL, &len, NULL);
436 ok(!ret && GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", GetLastError());
438 SetLastError(0xdeadbeef);
439 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_MAX + 1, NULL, NULL, &len, NULL);
440 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %u\n", GetLastError());
442 bytes_rw = -1;
443 ret = WinHttpReadData(request, buffer, sizeof(buffer) - 1, &bytes_rw);
444 ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
446 ok(bytes_rw == sizeof(test_post) - 1, "Read %u bytes\n", bytes_rw);
447 ok(!memcmp(buffer, test_post, sizeof(test_post) - 1), "Data read did not match.\n");
449 done:
450 ret = WinHttpCloseHandle(request);
451 ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
452 ret = WinHttpCloseHandle(connection);
453 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
454 ret = WinHttpCloseHandle(session);
455 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
458 static void test_WinHttpTimeFromSystemTime(void)
460 BOOL ret;
461 static const SYSTEMTIME time = {2008, 7, 1, 28, 10, 5, 52, 0};
462 WCHAR time_string[WINHTTP_TIME_FORMAT_BUFSIZE+1];
463 DWORD err;
465 SetLastError(0xdeadbeef);
466 ret = WinHttpTimeFromSystemTime(&time, NULL);
467 err = GetLastError();
468 ok(!ret, "WinHttpTimeFromSystemTime succeeded\n");
469 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
471 SetLastError(0xdeadbeef);
472 ret = WinHttpTimeFromSystemTime(NULL, time_string);
473 err = GetLastError();
474 ok(!ret, "WinHttpTimeFromSystemTime succeeded\n");
475 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
477 SetLastError(0xdeadbeef);
478 ret = WinHttpTimeFromSystemTime(&time, time_string);
479 err = GetLastError();
480 ok(ret, "WinHttpTimeFromSystemTime failed: %u\n", err);
481 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
482 ok(!memcmp(time_string, L"Mon, 28 Jul 2008 10:05:52 GMT", sizeof(L"Mon, 28 Jul 2008 10:05:52 GMT")),
483 "Time string returned did not match expected time string.\n");
486 static void test_WinHttpTimeToSystemTime(void)
488 BOOL ret;
489 SYSTEMTIME time;
490 static const SYSTEMTIME expected_time = {2008, 7, 1, 28, 10, 5, 52, 0};
491 DWORD err;
493 SetLastError(0xdeadbeef);
494 ret = WinHttpTimeToSystemTime(L"Mon, 28 Jul 2008 10:05:52 GMT\n", NULL);
495 err = GetLastError();
496 ok(!ret, "WinHttpTimeToSystemTime succeeded\n");
497 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
499 SetLastError(0xdeadbeef);
500 ret = WinHttpTimeToSystemTime(NULL, &time);
501 err = GetLastError();
502 ok(!ret, "WinHttpTimeToSystemTime succeeded\n");
503 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
505 SetLastError(0xdeadbeef);
506 ret = WinHttpTimeToSystemTime(L"Mon, 28 Jul 2008 10:05:52 GMT\n", &time);
507 err = GetLastError();
508 ok(ret, "WinHttpTimeToSystemTime failed: %u\n", err);
509 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
510 ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
511 "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
513 SetLastError(0xdeadbeef);
514 ret = WinHttpTimeToSystemTime(L" mon 28 jul 2008 10 05 52\n", &time);
515 err = GetLastError();
516 ok(ret, "WinHttpTimeToSystemTime failed: %u\n", err);
517 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
518 ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
519 "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
522 static void test_WinHttpAddHeaders(void)
524 static const WCHAR test_header_begin[] =
525 {'P','O','S','T',' ','/','p','o','s','t','t','e','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
526 HINTERNET session, request, connection;
527 BOOL ret, reverse;
528 WCHAR buffer[MAX_PATH];
529 WCHAR check_buffer[MAX_PATH];
530 DWORD err, index, len, oldlen;
532 static const WCHAR test_headers[][14] =
534 L"Warning:test1",
535 L"Warning:test2",
536 L"Warning:test3",
537 L"Warning:test4",
538 L"Warning:test5",
539 L"Warning:test6",
540 L"Warning:test7",
541 L"",
542 L":",
543 L"a:",
544 L":b",
545 L"cd",
546 L" e :f",
547 L"field: value ",
548 L"name: value",
549 L"name:",
551 static const WCHAR test_indices[][6] =
553 L"test1",
554 L"test2",
555 L"test3",
556 L"test4",
559 session = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
560 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
561 ok(session != NULL, "WinHttpOpen failed to open session.\n");
563 connection = WinHttpConnect (session, L"test.winehq.org", INTERNET_DEFAULT_HTTP_PORT, 0);
564 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
566 request = WinHttpOpenRequest(connection, L"POST", L"/posttest.php", NULL, WINHTTP_NO_REFERER,
567 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
568 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
570 skip("Network unreachable, skipping.\n");
571 goto done;
573 ok(request != NULL, "WinHttpOpenRequest failed to open a request, error: %u.\n", GetLastError());
575 index = 0;
576 len = sizeof(buffer);
577 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
578 L"Warning", buffer, &len, &index);
579 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, found 'Warning' header.\n");
580 SetLastError(0xdeadbeef);
581 ret = WinHttpAddRequestHeaders(request, test_headers[0], -1L, WINHTTP_ADDREQ_FLAG_ADD);
582 err = GetLastError();
583 ok(ret, "WinHttpAddRequestHeaders failed to add new header, got %d with error %u.\n", ret, err);
584 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
586 index = 0;
587 len = sizeof(buffer);
588 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
589 L"Warning", buffer, &len, &index);
590 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
591 ok(index == 1, "WinHttpQueryHeaders failed: header index not incremented\n");
592 ok(!memcmp(buffer, test_indices[0], sizeof(test_indices[0])),
593 "WinHttpQueryHeaders failed: incorrect string returned\n");
594 ok(len == 5*sizeof(WCHAR), "WinHttpQueryHeaders failed: invalid length returned, expected 5, got %d\n", len);
596 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
597 L"Warning", buffer, &len, &index);
598 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, second index should not exist.\n");
600 /* Try to fetch the header info with a buffer that's big enough to fit the
601 * string but not the NULL terminator.
603 index = 0;
604 len = 5*sizeof(WCHAR);
605 memset(check_buffer, 0xab, sizeof(check_buffer));
606 memcpy(buffer, check_buffer, sizeof(buffer));
607 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
608 L"Warning", buffer, &len, &index);
609 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded with a buffer that's too small.\n");
610 ok(memcmp(buffer, check_buffer, sizeof(buffer)) == 0,
611 "WinHttpQueryHeaders failed, modified the buffer when it should not have.\n");
612 ok(len == 6*sizeof(WCHAR), "WinHttpQueryHeaders returned invalid length, expected 12, got %d\n", len);
614 /* Try with a NULL buffer */
615 index = 0;
616 len = sizeof(buffer);
617 SetLastError(0xdeadbeef);
618 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
619 L"Warning", NULL, &len, &index);
620 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
621 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
622 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
623 ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
625 /* Try with a NULL buffer and a length that's too small */
626 index = 0;
627 len = 10;
628 SetLastError(0xdeadbeef);
629 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
630 L"Warning", NULL, &len, &index);
631 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
632 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
633 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
634 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
635 ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
637 index = 0;
638 len = 0;
639 SetLastError(0xdeadbeef);
640 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
641 L"Warning", NULL, &len, &index);
642 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
643 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
644 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
645 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
646 ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
648 /* valid query */
649 oldlen = len;
650 index = 0;
651 len = sizeof(buffer);
652 memset(buffer, 0xff, sizeof(buffer));
653 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
654 L"Warning", buffer, &len, &index);
655 ok(ret == TRUE, "WinHttpQueryHeaders failed: got %d\n", ret);
656 ok(len + sizeof(WCHAR) <= oldlen, "WinHttpQueryHeaders resulting length longer than advertized.\n");
657 ok((len < sizeof(buffer) - sizeof(WCHAR)) && !buffer[len / sizeof(WCHAR)],
658 "WinHttpQueryHeaders did not append NULL terminator\n");
659 ok(len == lstrlenW(buffer) * sizeof(WCHAR), "WinHttpQueryHeaders returned incorrect length.\n");
660 ok(!memcmp(buffer, test_header_begin, sizeof(test_header_begin)), "invalid beginning of header string.\n");
661 ok(!memcmp(buffer + lstrlenW(buffer) - 4, L"\r\n\r\n", sizeof(L"\r\n\r\n")),
662 "WinHttpQueryHeaders returned invalid end of header string.\n");
663 ok(index == 0, "WinHttpQueryHeaders incremented header index.\n");
665 index = 0;
666 len = 0;
667 SetLastError(0xdeadbeef);
668 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
669 L"Warning", NULL, &len, &index);
670 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
671 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
672 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
673 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
674 ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
676 oldlen = len;
677 index = 0;
678 len = sizeof(buffer);
679 memset(buffer, 0xff, sizeof(buffer));
680 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
681 L"Warning", buffer, &len, &index);
682 ok(ret == TRUE, "WinHttpQueryHeaders failed %u\n", GetLastError());
683 ok(len + sizeof(WCHAR) <= oldlen, "resulting length longer than advertized\n");
684 ok((len < sizeof(buffer) - sizeof(WCHAR)) && !buffer[len / sizeof(WCHAR)] && !buffer[len / sizeof(WCHAR) - 1],
685 "no double NULL terminator\n");
686 ok(!memcmp(buffer, test_header_begin, sizeof(test_header_begin)), "invalid beginning of header string.\n");
687 ok(index == 0, "header index was incremented\n");
689 /* tests for more indices */
690 ret = WinHttpAddRequestHeaders(request, test_headers[1], -1L, WINHTTP_ADDREQ_FLAG_ADD);
691 ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header: %d\n", ret);
693 index = 0;
694 len = sizeof(buffer);
695 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
696 L"Warning", buffer, &len, &index);
697 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
698 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
699 ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
701 len = sizeof(buffer);
702 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
703 L"Warning", buffer, &len, &index);
704 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
705 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
706 ok(memcmp(buffer, test_indices[1], sizeof(test_indices[1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
708 ret = WinHttpAddRequestHeaders(request, test_headers[2], -1L, WINHTTP_ADDREQ_FLAG_REPLACE);
709 ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header.\n");
711 index = 0;
712 len = sizeof(buffer);
713 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
714 L"Warning", buffer, &len, &index);
715 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
716 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
717 reverse = (memcmp(buffer, test_indices[1], sizeof(test_indices[1])) != 0); /* Win7 returns values in reverse order of adding */
718 ok(!memcmp(buffer, test_indices[reverse ? 2 : 1], sizeof(test_indices[reverse ? 2 : 1])),
719 "WinHttpQueryHeaders returned incorrect string.\n");
721 len = sizeof(buffer);
722 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
723 L"Warning", buffer, &len, &index);
724 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
725 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
726 ok(!memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])),
727 "WinHttpQueryHeaders returned incorrect string.\n");
729 /* add if new flag */
730 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW);
731 ok(ret == FALSE, "WinHttpAddRequestHeaders incorrectly replaced existing header.\n");
733 index = 0;
734 len = sizeof(buffer);
735 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
736 L"Warning", buffer, &len, &index);
737 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
738 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
739 ok(!memcmp(buffer, test_indices[reverse ? 2 : 1], sizeof(test_indices[reverse ? 2 : 1])),
740 "WinHttpQueryHeaders returned incorrect string.\n");
742 len = sizeof(buffer);
743 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
744 L"Warning", buffer, &len, &index);
745 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
746 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
747 ok(!memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])),
748 "WinHttpQueryHeaders returned incorrect string.\n");
750 len = sizeof(buffer);
751 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
752 L"Warning", buffer, &len, &index);
753 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
755 /* coalesce flag */
756 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_COALESCE);
757 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE.\n");
759 index = 0;
760 len = sizeof(buffer);
761 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
762 L"Warning", buffer, &len, &index);
763 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
764 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
765 ok(!memcmp(buffer, reverse ? L"test3, test4" : L"test2, test4",
766 reverse ? sizeof(L"test3, test4") : sizeof(L"test2, test4")),
767 "WinHttpQueryHeaders returned incorrect string.\n");
769 len = sizeof(buffer);
770 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
771 L"Warning", buffer, &len, &index);
772 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
773 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
774 ok(!memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])),
775 "WinHttpQueryHeaders returned incorrect string.\n");
777 len = sizeof(buffer);
778 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
779 L"Warning", buffer, &len, &index);
780 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
782 /* coalesce with comma flag */
783 ret = WinHttpAddRequestHeaders(request, test_headers[4], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA);
784 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA.\n");
786 index = 0;
787 len = sizeof(buffer);
788 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
789 L"Warning", buffer, &len, &index);
790 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
791 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
793 ok(!memcmp(buffer, reverse ? L"test3, test4, test5" : L"test2, test4, test5",
794 reverse ? sizeof(L"test3, test4, test5") : sizeof(L"test2, test4, test5")),
795 "WinHttpQueryHeaders returned incorrect string.\n");
797 len = sizeof(buffer);
798 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
799 L"Warning", buffer, &len, &index);
800 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
801 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
802 ok(!memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])),
803 "WinHttpQueryHeaders returned incorrect string.\n");
805 len = sizeof(buffer);
806 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
807 L"Warning", buffer, &len, &index);
808 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
811 /* coalesce with semicolon flag */
812 ret = WinHttpAddRequestHeaders(request, test_headers[5], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON);
813 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON.\n");
815 index = 0;
816 len = sizeof(buffer);
817 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
818 L"Warning", buffer, &len, &index);
819 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
820 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
822 ok(!memcmp(buffer, reverse ? L"test3, test4, test5; test6" : L"test2, test4, test5; test6",
823 reverse ? sizeof(L"test3, test4, test5; test6") : sizeof(L"test2, test4, test5; test6")),
824 "WinHttpQueryHeaders returned incorrect string.\n");
826 len = sizeof(buffer);
827 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
828 L"Warning", buffer, &len, &index);
829 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
830 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
831 ok(!memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])),
832 "WinHttpQueryHeaders returned incorrect string.\n");
834 len = sizeof(buffer);
835 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
836 L"Warning", buffer, &len, &index);
837 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
839 /* add and replace flags */
840 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
841 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE.\n");
843 index = 0;
844 len = sizeof(buffer);
845 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
846 L"Warning", buffer, &len, &index);
847 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
848 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
849 ok(!memcmp(buffer, test_indices[reverse ? 3 : 2], sizeof(test_indices[reverse ? 3 : 2])),
850 "WinHttpQueryHeaders returned incorrect string.\n");
852 len = sizeof(buffer);
853 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
854 L"Warning", buffer, &len, &index);
855 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
856 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
857 ok(!memcmp(buffer, test_indices[reverse ? 1 : 3], sizeof(test_indices[reverse ? 1 : 3])),
858 "WinHttpQueryHeaders returned incorrect string.\n");
860 len = sizeof(buffer);
861 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
862 L"Warning", buffer, &len, &index);
863 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
865 ret = WinHttpAddRequestHeaders(request, test_headers[8], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
866 ok(!ret, "WinHttpAddRequestHeaders failed\n");
868 ret = WinHttpAddRequestHeaders(request, test_headers[9], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
869 ok(ret, "WinHttpAddRequestHeaders failed\n");
871 index = 0;
872 memset(buffer, 0xff, sizeof(buffer));
873 len = sizeof(buffer);
874 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
875 L"a", buffer, &len, &index);
876 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
877 ok(!memcmp(buffer, L"", sizeof(L"")), "unexpected result\n");
879 ret = WinHttpAddRequestHeaders(request, test_headers[10], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
880 ok(!ret, "WinHttpAddRequestHeaders failed\n");
882 ret = WinHttpAddRequestHeaders(request, test_headers[11], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
883 ok(!ret, "WinHttpAddRequestHeaders failed\n");
885 ret = WinHttpAddRequestHeaders(request, test_headers[12], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
886 ok(!ret, "WinHttpAddRequestHeaders failed\n");
888 ret = WinHttpAddRequestHeaders(request, test_headers[13], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
889 ok(ret, "WinHttpAddRequestHeaders failed\n");
891 index = 0;
892 buffer[0] = 0;
893 len = sizeof(buffer);
894 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
895 L"field", buffer, &len, &index);
896 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
897 ok(!memcmp(buffer, L"value ", sizeof(L"value ")) || !memcmp(buffer, L"value", sizeof(L"value")),
898 "unexpected result\n");
900 SetLastError(0xdeadbeef);
901 ret = WinHttpAddRequestHeaders(request, L"Range: bytes=0-773\r\n", 0,
902 WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
903 err = GetLastError();
904 ok(!ret, "unexpected success\n");
905 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
907 ret = WinHttpAddRequestHeaders(request, L"Range: bytes=0-773\r\n", ~0u,
908 WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
909 ok(ret, "failed to add header: %u\n", GetLastError());
911 index = 0;
912 len = sizeof(buffer);
913 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
914 L"Range", buffer, &len, &index);
915 ok(ret, "failed to get range header %u\n", GetLastError());
916 ok(!memcmp(buffer, L"bytes=0-773", sizeof(L"bytes=0-773")), "incorrect string returned\n");
917 ok(len == lstrlenW(L"bytes=0-773") * sizeof(WCHAR), "wrong length %u\n", len);
918 ok(index == 1, "wrong index %u\n", index);
919 index = 0;
920 len = sizeof(buffer);
921 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
922 L"name", buffer, &len, &index);
923 ok(!ret, "unexpected success\n");
925 SetLastError(0xdeadbeef);
926 ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
927 err = GetLastError();
928 ok(!ret, "unexpected success\n");
929 ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
931 ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
932 ok(ret, "got %u\n", GetLastError());
934 index = 0;
935 len = sizeof(buffer);
936 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
937 L"name", buffer, &len, &index);
938 ok(ret, "got %u\n", GetLastError());
939 ok(index == 1, "wrong index %u\n", index);
940 ok(!memcmp(buffer, L"value", sizeof(L"value")), "incorrect string\n");
942 ret = WinHttpAddRequestHeaders(request, test_headers[15], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
943 ok(ret, "got %u\n", GetLastError());
945 index = 0;
946 len = sizeof(buffer);
947 SetLastError(0xdeadbeef);
948 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
949 L"name", buffer, &len, &index);
950 err = GetLastError();
951 ok(!ret, "unexpected success\n");
952 ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
954 ret = WinHttpAddRequestHeaders(request, test_headers[14], -1L, 0);
955 ok(ret, "got %u\n", GetLastError());
957 index = 0;
958 len = sizeof(buffer);
959 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
960 L"name", buffer, &len, &index);
961 ok(ret, "got %u\n", GetLastError());
962 ok(index == 1, "wrong index %u\n", index);
963 ok(!memcmp(buffer, L"value", sizeof(L"value")), "incorrect string\n");
965 ret = WinHttpCloseHandle(request);
966 ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
967 done:
968 ret = WinHttpCloseHandle(connection);
969 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
970 ret = WinHttpCloseHandle(session);
971 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
975 static void CALLBACK cert_error(HINTERNET handle, DWORD_PTR ctx, DWORD status, LPVOID buf, DWORD len)
977 DWORD flags = *(DWORD *)buf;
979 if (!flags)
981 trace("WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR\n");
982 return;
984 #define X(x) if (flags & x) trace("%s\n", #x);
985 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED)
986 X(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT)
987 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED)
988 X(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA)
989 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID)
990 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID)
991 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE)
992 #undef X
995 static void test_secure_connection(void)
997 static const char data_start[] = "<!DOCTYPE html PUBLIC";
998 HINTERNET ses, con, req;
999 DWORD size, status, policy, bitness, read_size, err, available_size, protocols, flags;
1000 BOOL ret;
1001 CERT_CONTEXT *cert;
1002 WINHTTP_CERTIFICATE_INFO info;
1003 char buffer[32];
1005 ses = WinHttpOpen(L"winetest", 0, NULL, NULL, 0);
1006 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1008 policy = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
1009 ret = WinHttpSetOption(ses, WINHTTP_OPTION_REDIRECT_POLICY, &policy, sizeof(policy));
1010 ok(ret, "failed to set redirect policy %u\n", GetLastError());
1012 protocols = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;
1013 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SECURE_PROTOCOLS, &protocols, sizeof(protocols));
1014 err = GetLastError();
1015 ok(ret || err == ERROR_INVALID_PARAMETER /* < win7 */, "failed to set protocols %u\n", err);
1017 con = WinHttpConnect(ses, L"test.winehq.org", 443, 0);
1018 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1020 SetLastError( 0xdeadbeef );
1021 protocols = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;
1022 ret = WinHttpSetOption(con, WINHTTP_OPTION_SECURE_PROTOCOLS, &protocols, sizeof(protocols));
1023 err = GetLastError();
1024 ok(!ret, "unexpected success\n");
1025 ok(err == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, "got %u\n", err);
1027 /* try without setting WINHTTP_FLAG_SECURE */
1028 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1029 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1031 ret = WinHttpSetOption(req, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0);
1032 err = GetLastError();
1033 ok(!ret, "unexpected success\n");
1034 ok(err == ERROR_WINHTTP_INCORRECT_HANDLE_STATE || broken(err == ERROR_INVALID_PARAMETER) /* winxp */,
1035 "setting client cert context returned %u\n", err);
1037 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1038 err = GetLastError();
1039 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
1041 skip("Connection failed, skipping.\n");
1042 goto cleanup;
1044 ok(ret, "failed to send request %u\n", GetLastError());
1046 ret = WinHttpReceiveResponse(req, NULL);
1047 ok(ret, "failed to receive response %u\n", GetLastError());
1049 status = 0xdeadbeef;
1050 size = sizeof(status);
1051 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1052 ok(ret, "header query failed %u\n", GetLastError());
1053 ok(status == HTTP_STATUS_BAD_REQUEST, "got %u\n", status);
1055 WinHttpCloseHandle(req);
1057 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, WINHTTP_FLAG_SECURE);
1058 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1060 flags = 0xdeadbeef;
1061 size = sizeof(flags);
1062 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, &size);
1063 ok(ret, "failed to query security flags %u\n", GetLastError());
1064 ok(!flags, "got %08x\n", flags);
1066 flags = SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE;
1067 ret = WinHttpSetOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
1068 ok(ret, "failed to set security flags %u\n", GetLastError());
1070 flags = SECURITY_FLAG_SECURE;
1071 ret = WinHttpSetOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
1072 ok(!ret, "success\n");
1074 flags = SECURITY_FLAG_STRENGTH_STRONG;
1075 ret = WinHttpSetOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
1076 ok(!ret, "success\n");
1078 flags = SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
1079 SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
1080 ret = WinHttpSetOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
1081 ok(ret, "failed to set security flags %u\n", GetLastError());
1083 flags = 0;
1084 ret = WinHttpSetOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
1085 ok(ret, "failed to set security flags %u\n", GetLastError());
1087 ret = WinHttpSetOption(req, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0);
1088 err = GetLastError();
1089 ok(ret || broken(!ret && err == ERROR_INVALID_PARAMETER) /* winxp */, "failed to set client cert context %u\n", err);
1091 WinHttpSetStatusCallback(req, cert_error, WINHTTP_CALLBACK_STATUS_SECURE_FAILURE, 0);
1093 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1094 err = GetLastError();
1095 if (!ret && (err == ERROR_WINHTTP_SECURE_FAILURE || err == ERROR_WINHTTP_CANNOT_CONNECT ||
1096 err == ERROR_WINHTTP_TIMEOUT || err == SEC_E_ILLEGAL_MESSAGE))
1098 skip("secure connection failed, skipping remaining secure tests\n");
1099 goto cleanup;
1101 ok(ret, "failed to send request %u\n", GetLastError());
1103 size = sizeof(cert);
1104 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert, &size );
1105 ok(ret, "failed to retrieve certificate context %u\n", GetLastError());
1106 if (ret) CertFreeCertificateContext(cert);
1108 size = sizeof(bitness);
1109 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_KEY_BITNESS, &bitness, &size );
1110 ok(ret, "failed to retrieve key bitness %u\n", GetLastError());
1112 size = sizeof(info);
1113 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT, &info, &size );
1114 ok(ret, "failed to retrieve certificate info %u\n", GetLastError());
1116 if (ret)
1118 trace("lpszSubjectInfo %s\n", wine_dbgstr_w(info.lpszSubjectInfo));
1119 trace("lpszIssuerInfo %s\n", wine_dbgstr_w(info.lpszIssuerInfo));
1120 trace("lpszProtocolName %s\n", wine_dbgstr_w(info.lpszProtocolName));
1121 trace("lpszSignatureAlgName %s\n", wine_dbgstr_w(info.lpszSignatureAlgName));
1122 trace("lpszEncryptionAlgName %s\n", wine_dbgstr_w(info.lpszEncryptionAlgName));
1123 trace("dwKeySize %u\n", info.dwKeySize);
1124 LocalFree( info.lpszSubjectInfo );
1125 LocalFree( info.lpszIssuerInfo );
1128 ret = WinHttpReceiveResponse(req, NULL);
1129 if (!ret && GetLastError() == ERROR_WINHTTP_CONNECTION_ERROR)
1131 skip("connection error, skipping remaining secure tests\n");
1132 goto cleanup;
1134 ok(ret, "failed to receive response %u\n", GetLastError());
1136 available_size = 0;
1137 ret = WinHttpQueryDataAvailable(req, &available_size);
1138 ok(ret, "failed to query available data %u\n", GetLastError());
1139 ok(available_size > 2014, "available_size = %u\n", available_size);
1141 status = 0xdeadbeef;
1142 size = sizeof(status);
1143 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1144 ok(ret, "failed unexpectedly %u\n", GetLastError());
1145 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1147 size = 0;
1148 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL);
1149 ok(!ret, "succeeded unexpectedly\n");
1151 read_size = 0;
1152 for (;;)
1154 size = 0;
1155 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
1156 ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
1157 if (!size) break;
1158 read_size += size;
1160 if (read_size <= 32)
1161 ok(!memcmp(buffer, data_start, sizeof(data_start)-1), "not expected: %.32s\n", buffer);
1163 ok(read_size >= available_size, "read_size = %u, available_size = %u\n", read_size, available_size);
1165 size = sizeof(cert);
1166 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert, &size);
1167 ok(ret, "failed to retrieve certificate context %u\n", GetLastError());
1168 if (ret) CertFreeCertificateContext(cert);
1170 cleanup:
1171 WinHttpCloseHandle(req);
1172 WinHttpCloseHandle(con);
1173 WinHttpCloseHandle(ses);
1176 static void test_request_parameter_defaults(void)
1178 HINTERNET ses, con, req;
1179 DWORD size, status, error;
1180 WCHAR *version;
1181 BOOL ret;
1183 ses = WinHttpOpen(L"winetest", 0, NULL, NULL, 0);
1184 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1186 con = WinHttpConnect(ses, L"test.winehq.org", 0, 0);
1187 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1189 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1190 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1192 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1193 error = GetLastError();
1194 if (!ret && (error == ERROR_WINHTTP_CANNOT_CONNECT || error == ERROR_WINHTTP_TIMEOUT))
1196 skip("connection failed, skipping\n");
1197 goto done;
1199 ok(ret, "failed to send request %u\n", GetLastError());
1201 ret = WinHttpReceiveResponse(req, NULL);
1202 ok(ret, "failed to receive response %u\n", GetLastError());
1204 status = 0xdeadbeef;
1205 size = sizeof(status);
1206 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1207 ok(ret, "failed unexpectedly %u\n", GetLastError());
1208 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1210 WinHttpCloseHandle(req);
1212 req = WinHttpOpenRequest(con, L"", L"", L"", NULL, NULL, 0);
1213 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1215 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1216 error = GetLastError();
1217 if (!ret && (error == ERROR_WINHTTP_CANNOT_CONNECT || error == ERROR_WINHTTP_TIMEOUT))
1219 skip("connection failed, skipping\n");
1220 goto done;
1222 ok(ret, "failed to send request %u\n", GetLastError());
1224 ret = WinHttpReceiveResponse(req, NULL);
1225 ok(ret, "failed to receive response %u\n", GetLastError());
1227 size = 0;
1228 SetLastError(0xdeadbeef);
1229 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, NULL, &size, NULL);
1230 error = GetLastError();
1231 ok(!ret, "succeeded unexpectedly\n");
1232 ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error);
1234 version = HeapAlloc(GetProcessHeap(), 0, size);
1235 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, version, &size, NULL);
1236 ok(ret, "failed unexpectedly %u\n", GetLastError());
1237 ok(lstrlenW(version) == size / sizeof(WCHAR), "unexpected size %u\n", size);
1238 HeapFree(GetProcessHeap(), 0, version);
1240 status = 0xdeadbeef;
1241 size = sizeof(status);
1242 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1243 ok(ret, "failed unexpectedly %u\n", GetLastError());
1244 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1246 done:
1247 WinHttpCloseHandle(req);
1248 WinHttpCloseHandle(con);
1249 WinHttpCloseHandle(ses);
1252 static const WCHAR Connections[] = {
1253 'S','o','f','t','w','a','r','e','\\',
1254 'M','i','c','r','o','s','o','f','t','\\',
1255 'W','i','n','d','o','w','s','\\',
1256 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1257 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
1258 'C','o','n','n','e','c','t','i','o','n','s',0 };
1259 static const WCHAR WinHttpSettings[] = {
1260 'W','i','n','H','t','t','p','S','e','t','t','i','n','g','s',0 };
1262 static DWORD get_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD *type )
1264 LONG l;
1265 HKEY key;
1266 DWORD ret = 0;
1268 l = RegOpenKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, KEY_READ, &key );
1269 if (!l)
1271 DWORD size = 0;
1273 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, NULL, &size );
1274 if (!l)
1276 if (size <= len)
1277 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, buf,
1278 &size );
1279 if (!l)
1280 ret = size;
1282 RegCloseKey( key );
1284 return ret;
1287 static void set_proxy( REGSAM access, BYTE *buf, DWORD len, DWORD type )
1289 HKEY hkey;
1290 if (!RegCreateKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, NULL, 0, access, NULL, &hkey, NULL ))
1292 if (len) RegSetValueExW( hkey, WinHttpSettings, 0, type, buf, len );
1293 else RegDeleteValueW( hkey, WinHttpSettings );
1294 RegCloseKey( hkey );
1298 static void set_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD type )
1300 BOOL wow64;
1301 IsWow64Process( GetCurrentProcess(), &wow64 );
1302 if (sizeof(void *) > sizeof(int) || wow64)
1304 set_proxy( KEY_WRITE|KEY_WOW64_64KEY, buf, len, type );
1305 set_proxy( KEY_WRITE|KEY_WOW64_32KEY, buf, len, type );
1307 else
1308 set_proxy( KEY_WRITE, buf, len, type );
1311 static void test_set_default_proxy_config(void)
1313 static WCHAR wideString[] = { 0x226f, 0x575b, 0 };
1314 static WCHAR normalString[] = { 'f','o','o',0 };
1315 DWORD type, len;
1316 BYTE *saved_proxy_settings = NULL;
1317 WINHTTP_PROXY_INFO info;
1318 BOOL ret;
1320 /* FIXME: it would be simpler to read the current settings using
1321 * WinHttpGetDefaultProxyConfiguration and save them using
1322 * WinHttpSetDefaultProxyConfiguration, but they appear to have a bug.
1324 * If a proxy is configured in the registry, e.g. via 'proxcfg -p "foo"',
1325 * the access type reported by WinHttpGetDefaultProxyConfiguration is 1,
1326 * WINHTTP_ACCESS_TYPE_NO_PROXY, whereas it should be
1327 * WINHTTP_ACCESS_TYPE_NAMED_PROXY.
1328 * If WinHttpSetDefaultProxyConfiguration is called with dwAccessType = 1,
1329 * the lpszProxy and lpszProxyBypass values are ignored.
1330 * Thus, if a proxy is set with proxycfg, then calling
1331 * WinHttpGetDefaultProxyConfiguration followed by
1332 * WinHttpSetDefaultProxyConfiguration results in the proxy settings
1333 * getting deleted from the registry.
1335 * Instead I read the current registry value and restore it directly.
1337 len = get_default_proxy_reg_value( NULL, 0, &type );
1338 if (len)
1340 saved_proxy_settings = HeapAlloc( GetProcessHeap(), 0, len );
1341 len = get_default_proxy_reg_value( saved_proxy_settings, len, &type );
1344 if (0)
1346 /* Crashes on Vista and higher */
1347 SetLastError(0xdeadbeef);
1348 ret = WinHttpSetDefaultProxyConfiguration(NULL);
1349 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1350 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1353 /* test with invalid access type */
1354 info.dwAccessType = 0xdeadbeef;
1355 info.lpszProxy = info.lpszProxyBypass = NULL;
1356 SetLastError(0xdeadbeef);
1357 ret = WinHttpSetDefaultProxyConfiguration(&info);
1358 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1359 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1361 /* at a minimum, the proxy server must be set */
1362 info.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
1363 info.lpszProxy = info.lpszProxyBypass = NULL;
1364 SetLastError(0xdeadbeef);
1365 ret = WinHttpSetDefaultProxyConfiguration(&info);
1366 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1367 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1368 info.lpszProxyBypass = normalString;
1369 SetLastError(0xdeadbeef);
1370 ret = WinHttpSetDefaultProxyConfiguration(&info);
1371 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1372 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1374 /* the proxy server can't have wide characters */
1375 info.lpszProxy = wideString;
1376 SetLastError(0xdeadbeef);
1377 ret = WinHttpSetDefaultProxyConfiguration(&info);
1378 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1379 skip("couldn't set default proxy configuration: access denied\n");
1380 else
1381 ok((!ret && GetLastError() == ERROR_INVALID_PARAMETER) ||
1382 broken(ret), /* Earlier winhttp versions on W2K/XP */
1383 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1385 info.lpszProxy = normalString;
1386 SetLastError(0xdeadbeef);
1387 ret = WinHttpSetDefaultProxyConfiguration(&info);
1388 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1389 skip("couldn't set default proxy configuration: access denied\n");
1390 else
1392 ok(ret, "WinHttpSetDefaultProxyConfiguration failed: %u\n", GetLastError());
1393 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
1394 "got %u\n", GetLastError());
1396 set_default_proxy_reg_value( saved_proxy_settings, len, type );
1399 static void test_timeouts(void)
1401 BOOL ret;
1402 DWORD value, size;
1403 HINTERNET ses, req, con;
1405 ses = WinHttpOpen(L"winetest", 0, NULL, NULL, 0);
1406 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1408 SetLastError(0xdeadbeef);
1409 ret = WinHttpSetTimeouts(ses, -2, 0, 0, 0);
1410 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1411 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1413 SetLastError(0xdeadbeef);
1414 ret = WinHttpSetTimeouts(ses, 0, -2, 0, 0);
1415 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1416 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1418 SetLastError(0xdeadbeef);
1419 ret = WinHttpSetTimeouts(ses, 0, 0, -2, 0);
1420 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1421 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1423 SetLastError(0xdeadbeef);
1424 ret = WinHttpSetTimeouts(ses, 0, 0, 0, -2);
1425 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1426 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1428 SetLastError(0xdeadbeef);
1429 ret = WinHttpSetTimeouts(ses, -1, -1, -1, -1);
1430 ok(ret, "%u\n", GetLastError());
1431 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
1432 "expected ERROR_SUCCESS, got %u\n", GetLastError());
1434 SetLastError(0xdeadbeef);
1435 ret = WinHttpSetTimeouts(ses, 0, 0, 0, 0);
1436 ok(ret, "%u\n", GetLastError());
1438 SetLastError(0xdeadbeef);
1439 ret = WinHttpSetTimeouts(ses, 0x0123, 0x4567, 0x89ab, 0xcdef);
1440 ok(ret, "%u\n", GetLastError());
1442 SetLastError(0xdeadbeef);
1443 value = 0xdeadbeef;
1444 size = sizeof(DWORD);
1445 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1446 ok(ret, "%u\n", GetLastError());
1447 ok(value == 0x0123, "Expected 0x0123, got %u\n", value);
1449 SetLastError(0xdeadbeef);
1450 value = 0xdeadbeef;
1451 size = sizeof(DWORD);
1452 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1453 ok(ret, "%u\n", GetLastError());
1454 ok(value == 0x4567, "Expected 0x4567, got %u\n", value);
1456 SetLastError(0xdeadbeef);
1457 value = 0xdeadbeef;
1458 size = sizeof(DWORD);
1459 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1460 ok(ret, "%u\n", GetLastError());
1461 ok(value == 0x89ab, "Expected 0x89ab, got %u\n", value);
1463 SetLastError(0xdeadbeef);
1464 value = 0xdeadbeef;
1465 size = sizeof(DWORD);
1466 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1467 ok(ret, "%u\n", GetLastError());
1468 ok(value == 0xcdef, "Expected 0xcdef, got %u\n", value);
1470 SetLastError(0xdeadbeef);
1471 value = 0;
1472 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1473 ok(ret, "%u\n", GetLastError());
1475 SetLastError(0xdeadbeef);
1476 value = 0xdeadbeef;
1477 size = sizeof(DWORD);
1478 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1479 ok(ret, "%u\n", GetLastError());
1480 ok(value == 0, "Expected 0, got %u\n", value);
1482 SetLastError(0xdeadbeef);
1483 value = 0;
1484 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1485 ok(ret, "%u\n", GetLastError());
1487 SetLastError(0xdeadbeef);
1488 value = 0xdeadbeef;
1489 size = sizeof(DWORD);
1490 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1491 ok(ret, "%u\n", GetLastError());
1492 ok(value == 0, "Expected 0, got %u\n", value);
1494 SetLastError(0xdeadbeef);
1495 value = 0;
1496 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1497 ok(ret, "%u\n", GetLastError());
1499 SetLastError(0xdeadbeef);
1500 value = 0xdeadbeef;
1501 size = sizeof(DWORD);
1502 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1503 ok(ret, "%u\n", GetLastError());
1504 ok(value == 0, "Expected 0, got %u\n", value);
1506 SetLastError(0xdeadbeef);
1507 value = 0;
1508 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1509 ok(ret, "%u\n", GetLastError());
1511 SetLastError(0xdeadbeef);
1512 value = 0xdeadbeef;
1513 size = sizeof(DWORD);
1514 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1515 ok(ret, "%u\n", GetLastError());
1516 ok(value == 0, "Expected 0, got %u\n", value);
1518 SetLastError(0xdeadbeef);
1519 value = 0xbeefdead;
1520 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1521 ok(ret, "%u\n", GetLastError());
1523 SetLastError(0xdeadbeef);
1524 value = 0xdeadbeef;
1525 size = sizeof(DWORD);
1526 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1527 ok(ret, "%u\n", GetLastError());
1528 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1530 SetLastError(0xdeadbeef);
1531 value = 0xbeefdead;
1532 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1533 ok(ret, "%u\n", GetLastError());
1535 SetLastError(0xdeadbeef);
1536 value = 0xdeadbeef;
1537 size = sizeof(DWORD);
1538 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1539 ok(ret, "%u\n", GetLastError());
1540 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1542 SetLastError(0xdeadbeef);
1543 value = 0xbeefdead;
1544 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1545 ok(ret, "%u\n", GetLastError());
1547 SetLastError(0xdeadbeef);
1548 value = 0xdeadbeef;
1549 size = sizeof(DWORD);
1550 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1551 ok(ret, "%u\n", GetLastError());
1552 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1554 SetLastError(0xdeadbeef);
1555 value = 0xbeefdead;
1556 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1557 ok(ret, "%u\n", GetLastError());
1559 SetLastError(0xdeadbeef);
1560 value = 0xdeadbeef;
1561 size = sizeof(DWORD);
1562 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1563 ok(ret, "%u\n", GetLastError());
1564 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1566 con = WinHttpConnect(ses, L"test.winehq.org", 0, 0);
1567 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1569 /* Timeout values should match the last one set for session */
1570 SetLastError(0xdeadbeef);
1571 value = 0xdeadbeef;
1572 size = sizeof(DWORD);
1573 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1574 ok(ret, "%u\n", GetLastError());
1575 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1577 SetLastError(0xdeadbeef);
1578 value = 0xdeadbeef;
1579 size = sizeof(DWORD);
1580 ret = WinHttpQueryOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1581 ok(ret, "%u\n", GetLastError());
1582 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1584 SetLastError(0xdeadbeef);
1585 value = 0xdeadbeef;
1586 size = sizeof(DWORD);
1587 ret = WinHttpQueryOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1588 ok(ret, "%u\n", GetLastError());
1589 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1591 SetLastError(0xdeadbeef);
1592 value = 0xdeadbeef;
1593 size = sizeof(DWORD);
1594 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1595 ok(ret, "%u\n", GetLastError());
1596 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1598 SetLastError(0xdeadbeef);
1599 ret = WinHttpSetTimeouts(con, -2, 0, 0, 0);
1600 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1601 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1603 SetLastError(0xdeadbeef);
1604 ret = WinHttpSetTimeouts(con, 0, -2, 0, 0);
1605 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1606 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1608 SetLastError(0xdeadbeef);
1609 ret = WinHttpSetTimeouts(con, 0, 0, -2, 0);
1610 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1611 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1613 SetLastError(0xdeadbeef);
1614 ret = WinHttpSetTimeouts(con, 0, 0, 0, -2);
1615 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1616 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1618 SetLastError(0xdeadbeef);
1619 ret = WinHttpSetTimeouts(con, -1, -1, -1, -1);
1620 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1621 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1623 SetLastError(0xdeadbeef);
1624 ret = WinHttpSetTimeouts(con, 0, 0, 0, 0);
1625 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1626 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1628 SetLastError(0xdeadbeef);
1629 value = 0;
1630 ret = WinHttpSetOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1631 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1632 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1634 SetLastError(0xdeadbeef);
1635 value = 0;
1636 ret = WinHttpSetOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1637 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1638 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1640 SetLastError(0xdeadbeef);
1641 value = 0;
1642 ret = WinHttpSetOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1643 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1644 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1646 SetLastError(0xdeadbeef);
1647 value = 0;
1648 ret = WinHttpSetOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1649 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1650 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1652 /* Changing timeout values for session should affect the values for connection */
1653 SetLastError(0xdeadbeef);
1654 value = 0xdead;
1655 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1656 ok(ret, "%u\n", GetLastError());
1658 SetLastError(0xdeadbeef);
1659 value = 0xdeadbeef;
1660 size = sizeof(DWORD);
1661 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1662 ok(ret, "%u\n", GetLastError());
1663 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1665 SetLastError(0xdeadbeef);
1666 value = 0xdead;
1667 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1668 ok(ret, "%u\n", GetLastError());
1670 SetLastError(0xdeadbeef);
1671 value = 0xdeadbeef;
1672 size = sizeof(DWORD);
1673 ret = WinHttpQueryOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1674 ok(ret, "%u\n", GetLastError());
1675 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1677 SetLastError(0xdeadbeef);
1678 value = 0xdead;
1679 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1680 ok(ret, "%u\n", GetLastError());
1682 SetLastError(0xdeadbeef);
1683 value = 0xdeadbeef;
1684 size = sizeof(DWORD);
1685 ret = WinHttpQueryOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1686 ok(ret, "%u\n", GetLastError());
1687 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1689 SetLastError(0xdeadbeef);
1690 value = 0xdead;
1691 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1692 ok(ret, "%u\n", GetLastError());
1694 SetLastError(0xdeadbeef);
1695 value = 0xdeadbeef;
1696 size = sizeof(DWORD);
1697 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1698 ok(ret, "%u\n", GetLastError());
1699 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1701 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1702 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1704 /* Timeout values should match the last one set for session */
1705 SetLastError(0xdeadbeef);
1706 value = 0xdeadbeef;
1707 size = sizeof(DWORD);
1708 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1709 ok(ret, "%u\n", GetLastError());
1710 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1712 SetLastError(0xdeadbeef);
1713 value = 0xdeadbeef;
1714 size = sizeof(DWORD);
1715 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1716 ok(ret, "%u\n", GetLastError());
1717 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1719 SetLastError(0xdeadbeef);
1720 value = 0xdeadbeef;
1721 size = sizeof(DWORD);
1722 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1723 ok(ret, "%u\n", GetLastError());
1724 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1726 SetLastError(0xdeadbeef);
1727 value = 0xdeadbeef;
1728 size = sizeof(DWORD);
1729 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1730 ok(ret, "%u\n", GetLastError());
1731 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1733 SetLastError(0xdeadbeef);
1734 ret = WinHttpSetTimeouts(req, -2, 0, 0, 0);
1735 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1736 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1738 SetLastError(0xdeadbeef);
1739 ret = WinHttpSetTimeouts(req, 0, -2, 0, 0);
1740 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1741 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1743 SetLastError(0xdeadbeef);
1744 ret = WinHttpSetTimeouts(req, 0, 0, -2, 0);
1745 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1746 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1748 SetLastError(0xdeadbeef);
1749 ret = WinHttpSetTimeouts(req, 0, 0, 0, -2);
1750 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1751 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1753 SetLastError(0xdeadbeef);
1754 ret = WinHttpSetTimeouts(req, -1, -1, -1, -1);
1755 ok(ret, "%u\n", GetLastError());
1757 SetLastError(0xdeadbeef);
1758 ret = WinHttpSetTimeouts(req, 0, 0, 0, 0);
1759 ok(ret, "%u\n", GetLastError());
1761 SetLastError(0xdeadbeef);
1762 ret = WinHttpSetTimeouts(req, 0xcdef, 0x89ab, 0x4567, 0x0123);
1763 ok(ret, "%u\n", GetLastError());
1765 SetLastError(0xdeadbeef);
1766 value = 0xdeadbeef;
1767 size = sizeof(DWORD);
1768 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1769 ok(ret, "%u\n", GetLastError());
1770 ok(value == 0xcdef, "Expected 0xcdef, got %u\n", value);
1772 SetLastError(0xdeadbeef);
1773 value = 0xdeadbeef;
1774 size = sizeof(DWORD);
1775 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1776 ok(ret, "%u\n", GetLastError());
1777 ok(value == 0x89ab, "Expected 0x89ab, got %u\n", value);
1779 SetLastError(0xdeadbeef);
1780 value = 0xdeadbeef;
1781 size = sizeof(DWORD);
1782 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1783 ok(ret, "%u\n", GetLastError());
1784 ok(value == 0x4567, "Expected 0x4567, got %u\n", value);
1786 SetLastError(0xdeadbeef);
1787 value = 0xdeadbeef;
1788 size = sizeof(DWORD);
1789 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1790 ok(ret, "%u\n", GetLastError());
1791 ok(value == 0x0123, "Expected 0x0123, got %u\n", value);
1793 SetLastError(0xdeadbeef);
1794 value = 0;
1795 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1796 ok(ret, "%u\n", GetLastError());
1798 SetLastError(0xdeadbeef);
1799 value = 0xdeadbeef;
1800 size = sizeof(DWORD);
1801 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1802 ok(ret, "%u\n", GetLastError());
1803 ok(value == 0, "Expected 0, got %u\n", value);
1805 SetLastError(0xdeadbeef);
1806 value = 0;
1807 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1808 ok(ret, "%u\n", GetLastError());
1810 SetLastError(0xdeadbeef);
1811 value = 0xdeadbeef;
1812 size = sizeof(DWORD);
1813 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1814 ok(ret, "%u\n", GetLastError());
1815 ok(value == 0, "Expected 0, got %u\n", value);
1817 SetLastError(0xdeadbeef);
1818 value = 0;
1819 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1820 ok(ret, "%u\n", GetLastError());
1822 SetLastError(0xdeadbeef);
1823 value = 0xdeadbeef;
1824 size = sizeof(DWORD);
1825 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1826 ok(ret, "%u\n", GetLastError());
1827 ok(value == 0, "Expected 0, got %u\n", value);
1829 SetLastError(0xdeadbeef);
1830 value = 0;
1831 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1832 ok(ret, "%u\n", GetLastError());
1834 SetLastError(0xdeadbeef);
1835 value = 0xdeadbeef;
1836 size = sizeof(DWORD);
1837 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1838 ok(ret, "%u\n", GetLastError());
1839 ok(value == 0, "Expected 0, got %u\n", value);
1841 SetLastError(0xdeadbeef);
1842 value = 0xbeefdead;
1843 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1844 ok(ret, "%u\n", GetLastError());
1846 SetLastError(0xdeadbeef);
1847 value = 0xdeadbeef;
1848 size = sizeof(DWORD);
1849 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1850 ok(ret, "%u\n", GetLastError());
1851 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1853 SetLastError(0xdeadbeef);
1854 value = 0xbeefdead;
1855 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1856 ok(ret, "%u\n", GetLastError());
1858 SetLastError(0xdeadbeef);
1859 value = 0xdeadbeef;
1860 size = sizeof(DWORD);
1861 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1862 ok(ret, "%u\n", GetLastError());
1863 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1865 SetLastError(0xdeadbeef);
1866 value = 0xbeefdead;
1867 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1868 ok(ret, "%u\n", GetLastError());
1870 SetLastError(0xdeadbeef);
1871 value = 0xdeadbeef;
1872 size = sizeof(DWORD);
1873 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1874 ok(ret, "%u\n", GetLastError());
1875 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1877 SetLastError(0xdeadbeef);
1878 value = 0xbeefdead;
1879 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1880 ok(ret, "%u\n", GetLastError());
1882 SetLastError(0xdeadbeef);
1883 value = 0xdeadbeef;
1884 size = sizeof(DWORD);
1885 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1886 ok(ret, "%u\n", GetLastError());
1887 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1889 /* Changing timeout values for session should not affect the values for a request,
1890 * neither should the other way around.
1892 SetLastError(0xdeadbeef);
1893 value = 0xbeefdead;
1894 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1895 ok(ret, "%u\n", GetLastError());
1897 SetLastError(0xdeadbeef);
1898 value = 0xdeadbeef;
1899 size = sizeof(DWORD);
1900 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1901 ok(ret, "%u\n", GetLastError());
1902 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1904 SetLastError(0xdeadbeef);
1905 value = 0xbeefdead;
1906 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1907 ok(ret, "%u\n", GetLastError());
1909 SetLastError(0xdeadbeef);
1910 value = 0xdeadbeef;
1911 size = sizeof(DWORD);
1912 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1913 ok(ret, "%u\n", GetLastError());
1914 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1916 SetLastError(0xdeadbeef);
1917 value = 0xbeefdead;
1918 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1919 ok(ret, "%u\n", GetLastError());
1921 SetLastError(0xdeadbeef);
1922 value = 0xdeadbeef;
1923 size = sizeof(DWORD);
1924 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1925 ok(ret, "%u\n", GetLastError());
1926 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1928 SetLastError(0xdeadbeef);
1929 value = 0xbeefdead;
1930 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1931 ok(ret, "%u\n", GetLastError());
1933 SetLastError(0xdeadbeef);
1934 value = 0xdeadbeef;
1935 size = sizeof(DWORD);
1936 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1937 ok(ret, "%u\n", GetLastError());
1938 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1940 SetLastError(0xdeadbeef);
1941 value = 0xbeef;
1942 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1943 ok(ret, "%u\n", GetLastError());
1945 SetLastError(0xdeadbeef);
1946 value = 0xdeadbeef;
1947 size = sizeof(DWORD);
1948 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1949 ok(ret, "%u\n", GetLastError());
1950 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1952 SetLastError(0xdeadbeef);
1953 value = 0xbeef;
1954 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1955 ok(ret, "%u\n", GetLastError());
1957 SetLastError(0xdeadbeef);
1958 value = 0xdeadbeef;
1959 size = sizeof(DWORD);
1960 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1961 ok(ret, "%u\n", GetLastError());
1962 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1964 SetLastError(0xdeadbeef);
1965 value = 0xbeef;
1966 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1967 ok(ret, "%u\n", GetLastError());
1969 SetLastError(0xdeadbeef);
1970 value = 0xdeadbeef;
1971 size = sizeof(DWORD);
1972 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1973 ok(ret, "%u\n", GetLastError());
1974 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1976 SetLastError(0xdeadbeef);
1977 value = 0xbeef;
1978 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1979 ok(ret, "%u\n", GetLastError());
1981 SetLastError(0xdeadbeef);
1982 value = 0xdeadbeef;
1983 size = sizeof(DWORD);
1984 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1985 ok(ret, "%u\n", GetLastError());
1986 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1988 /* response timeout */
1989 SetLastError(0xdeadbeef);
1990 value = 0xdeadbeef;
1991 size = sizeof(value);
1992 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
1993 ok(ret, "%u\n", GetLastError());
1994 ok(value == ~0u, "got %u\n", value);
1996 SetLastError(0xdeadbeef);
1997 value = 30000;
1998 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, sizeof(value));
1999 ok(ret, "%u\n", GetLastError());
2001 SetLastError(0xdeadbeef);
2002 value = 0xdeadbeef;
2003 size = sizeof(value);
2004 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
2005 ok(ret, "%u\n", GetLastError());
2006 todo_wine ok(value == 0xbeefdead, "got %u\n", value);
2008 SetLastError(0xdeadbeef);
2009 value = 0xdeadbeef;
2010 size = sizeof(value);
2011 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
2012 ok(ret, "%u\n", GetLastError());
2013 ok(value == ~0u, "got %u\n", value);
2015 SetLastError(0xdeadbeef);
2016 value = 30000;
2017 ret = WinHttpSetOption(con, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, sizeof(value));
2018 ok(!ret, "expected failure\n");
2019 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, "got %u\n", GetLastError());
2021 SetLastError(0xdeadbeef);
2022 value = 0xdeadbeef;
2023 size = sizeof(value);
2024 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
2025 ok(ret, "%u\n", GetLastError());
2026 ok(value == ~0u, "got %u\n", value);
2028 SetLastError(0xdeadbeef);
2029 value = 48878;
2030 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, sizeof(value));
2031 ok(ret, "%u\n", GetLastError());
2033 SetLastError(0xdeadbeef);
2034 value = 0xdeadbeef;
2035 size = sizeof(value);
2036 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
2037 ok(ret, "%u\n", GetLastError());
2038 todo_wine ok(value == 48879, "got %u\n", value);
2040 SetLastError(0xdeadbeef);
2041 value = 48880;
2042 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, sizeof(value));
2043 ok(ret, "%u\n", GetLastError());
2045 SetLastError(0xdeadbeef);
2046 value = 0xdeadbeef;
2047 size = sizeof(value);
2048 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
2049 ok(ret, "%u\n", GetLastError());
2050 ok(value == 48880, "got %u\n", value);
2052 WinHttpCloseHandle(req);
2053 WinHttpCloseHandle(con);
2054 WinHttpCloseHandle(ses);
2057 static void test_resolve_timeout(void)
2059 HINTERNET ses, con, req;
2060 DWORD timeout;
2061 BOOL ret;
2063 if (! proxy_active())
2065 ses = WinHttpOpen(L"winetest", 0, NULL, NULL, 0);
2066 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2068 timeout = 10000;
2069 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
2070 ok(ret, "failed to set resolve timeout %u\n", GetLastError());
2072 con = WinHttpConnect(ses, L"nxdomain.winehq.org", 0, 0);
2073 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2075 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
2076 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2078 SetLastError(0xdeadbeef);
2079 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2080 if (ret)
2082 skip("nxdomain returned success. Broken ISP redirects?\n");
2083 goto done;
2085 ok(GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED,
2086 "expected ERROR_WINHTTP_NAME_NOT_RESOLVED got %u\n", GetLastError());
2088 ret = WinHttpReceiveResponse( req, NULL );
2089 ok( !ret && (GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_STATE ||
2090 GetLastError() == ERROR_WINHTTP_OPERATION_CANCELLED /* < win7 */),
2091 "got %u\n", GetLastError() );
2093 WinHttpCloseHandle(req);
2094 WinHttpCloseHandle(con);
2095 WinHttpCloseHandle(ses);
2097 else
2098 skip("Skipping host resolution tests, host resolution performed by proxy\n");
2100 ses = WinHttpOpen(L"winetest", 0, NULL, NULL, 0);
2101 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2103 timeout = 10000;
2104 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
2105 ok(ret, "failed to set resolve timeout %u\n", GetLastError());
2107 con = WinHttpConnect(ses, L"test.winehq.org", 0, 0);
2108 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2110 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
2111 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2113 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2114 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
2116 skip("connection failed, skipping\n");
2117 goto done;
2119 ok(ret, "failed to send request\n");
2121 done:
2122 WinHttpCloseHandle(req);
2123 WinHttpCloseHandle(con);
2124 WinHttpCloseHandle(ses);
2127 static const char page1[] =
2128 "<HTML>\r\n"
2129 "<HEAD><TITLE>winhttp test page</TITLE></HEAD>\r\n"
2130 "<BODY>The quick brown fox jumped over the lazy dog<P></BODY>\r\n"
2131 "</HTML>\r\n\r\n";
2133 static const char okmsg[] =
2134 "HTTP/1.1 200 OK\r\n"
2135 "Server: winetest\r\n"
2136 "\r\n";
2138 static const char notokmsg[] =
2139 "HTTP/1.1 400 Bad Request\r\n"
2140 "\r\n";
2142 static const char cookiemsg[] =
2143 "HTTP/1.1 200 OK\r\n"
2144 "Set-Cookie: name = value \r\n"
2145 "Set-Cookie: NAME = value \r\n"
2146 "\r\n";
2148 static const char cookiemsg2[] =
2149 "HTTP/1.1 200 OK\r\n"
2150 "Set-Cookie: name2=value; Domain = localhost; Path=/cookie5;Expires=Wed, 13 Jan 2021 22:23:01 GMT; HttpOnly; \r\n"
2151 "\r\n";
2153 static const char nocontentmsg[] =
2154 "HTTP/1.1 204 No Content\r\n"
2155 "Server: winetest\r\n"
2156 "\r\n";
2158 static const char notmodified[] =
2159 "HTTP/1.1 304 Not Modified\r\n"
2160 "\r\n";
2162 static const char noauthmsg[] =
2163 "HTTP/1.1 401 Unauthorized\r\n"
2164 "Server: winetest\r\n"
2165 "Connection: close\r\n"
2166 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
2167 "Content-Length: 12\r\n"
2168 "Content-Type: text/plain\r\n"
2169 "\r\n";
2171 static const char okauthmsg[] =
2172 "HTTP/1.1 200 OK\r\n"
2173 "Server: winetest\r\n"
2174 "Connection: close\r\n"
2175 "Content-Length: 11\r\n"
2176 "Content-Type: text/plain\r\n"
2177 "\r\n";
2179 static const char headmsg[] =
2180 "HTTP/1.1 200 OK\r\n"
2181 "Content-Length: 100\r\n"
2182 "\r\n";
2184 static const char multiauth[] =
2185 "HTTP/1.1 401 Unauthorized\r\n"
2186 "Server: winetest\r\n"
2187 "WWW-Authenticate: Bearer\r\n"
2188 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
2189 "WWW-Authenticate: NTLM\r\n"
2190 "Content-Length: 10\r\n"
2191 "Content-Type: text/plain\r\n"
2192 "\r\n";
2194 static const char largeauth[] =
2195 "HTTP/1.1 401 Unauthorized\r\n"
2196 "Server: winetest\r\n"
2197 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
2198 "WWW-Authenticate: NTLM\r\n"
2199 "Content-Length: 10240\r\n"
2200 "Content-Type: text/plain\r\n"
2201 "\r\n";
2203 static const char passportauth[] =
2204 "HTTP/1.1 302 Found\r\n"
2205 "Content-Length: 0\r\n"
2206 "Location: /\r\n"
2207 "WWW-Authenticate: Passport1.4\r\n"
2208 "\r\n";
2210 static const char switchprotocols[] =
2211 "HTTP/1.1 101 Switching Protocols\r\n"
2212 "Server: winetest\r\n"
2213 "Upgrade: websocket\r\n"
2214 "Connection: Upgrade\r\n";
2216 static const char unauthorized[] = "Unauthorized";
2217 static const char hello_world[] = "Hello World";
2218 static const char auth_unseen[] = "Auth Unseen";
2220 struct server_info
2222 HANDLE event;
2223 int port;
2226 #define BIG_BUFFER_LEN 0x2250
2228 static void create_websocket_accept(const char *key, char *buf, unsigned int buflen)
2230 HCRYPTPROV provider;
2231 HCRYPTHASH hash;
2232 BYTE sha1[20];
2233 char data[128];
2234 DWORD len;
2236 strcpy(data, key);
2237 strcat(data, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
2239 CryptAcquireContextW(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
2240 CryptCreateHash(provider, CALG_SHA1, 0, 0, &hash);
2241 CryptHashData(hash, (BYTE *)data, strlen(data), 0);
2243 len = sizeof(sha1);
2244 CryptGetHashParam(hash, HP_HASHVAL, sha1, &len, 0);
2245 CryptDestroyHash(hash);
2246 CryptReleaseContext(provider, 0);
2248 buf[0] = 0;
2249 len = buflen;
2250 CryptBinaryToStringA( (BYTE *)sha1, sizeof(sha1), CRYPT_STRING_BASE64, buf, &len);
2253 static DWORD CALLBACK server_thread(LPVOID param)
2255 struct server_info *si = param;
2256 int r, c = -1, i, on;
2257 SOCKET s;
2258 struct sockaddr_in sa;
2259 char buffer[0x100];
2260 WSADATA wsaData;
2261 int last_request = 0;
2263 WSAStartup(MAKEWORD(1,1), &wsaData);
2265 s = socket(AF_INET, SOCK_STREAM, 0);
2266 if (s == INVALID_SOCKET)
2267 return 1;
2269 on = 1;
2270 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof on);
2272 memset(&sa, 0, sizeof sa);
2273 sa.sin_family = AF_INET;
2274 sa.sin_port = htons(si->port);
2275 sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
2277 r = bind(s, (struct sockaddr *)&sa, sizeof(sa));
2278 if (r < 0)
2279 return 1;
2281 listen(s, 0);
2282 SetEvent(si->event);
2285 if (c == -1) c = accept(s, NULL, NULL);
2287 memset(buffer, 0, sizeof buffer);
2288 for(i = 0; i < sizeof buffer - 1; i++)
2290 r = recv(c, &buffer[i], 1, 0);
2291 if (r != 1)
2292 break;
2293 if (i < 4) continue;
2294 if (buffer[i - 2] == '\n' && buffer[i] == '\n' &&
2295 buffer[i - 3] == '\r' && buffer[i - 1] == '\r')
2296 break;
2298 if (strstr(buffer, "GET /basic"))
2300 send(c, okmsg, sizeof okmsg - 1, 0);
2301 send(c, page1, sizeof page1 - 1, 0);
2303 if (strstr(buffer, "/auth_with_creds"))
2305 send(c, okauthmsg, sizeof okauthmsg - 1, 0);
2306 if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
2307 send(c, hello_world, sizeof hello_world - 1, 0);
2308 else
2309 send(c, auth_unseen, sizeof auth_unseen - 1, 0);
2310 continue;
2312 if (strstr(buffer, "/auth"))
2314 if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
2316 send(c, okauthmsg, sizeof okauthmsg - 1, 0);
2317 send(c, hello_world, sizeof hello_world - 1, 0);
2319 else
2321 send(c, noauthmsg, sizeof noauthmsg - 1, 0);
2322 send(c, unauthorized, sizeof unauthorized - 1, 0);
2324 continue;
2326 if (strstr(buffer, "/big"))
2328 char msg[BIG_BUFFER_LEN];
2329 memset(msg, 'm', sizeof(msg));
2330 send(c, okmsg, sizeof(okmsg) - 1, 0);
2331 send(c, msg, sizeof(msg), 0);
2333 if (strstr(buffer, "/no_headers"))
2335 send(c, page1, sizeof page1 - 1, 0);
2337 if (strstr(buffer, "GET /no_content"))
2339 send(c, nocontentmsg, sizeof nocontentmsg - 1, 0);
2340 continue;
2342 if (strstr(buffer, "GET /not_modified"))
2344 if (strstr(buffer, "If-Modified-Since:")) send(c, notmodified, sizeof notmodified - 1, 0);
2345 else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2346 continue;
2348 if (strstr(buffer, "HEAD /head"))
2350 send(c, headmsg, sizeof headmsg - 1, 0);
2351 continue;
2353 if (strstr(buffer, "GET /multiauth"))
2355 send(c, multiauth, sizeof multiauth - 1, 0);
2357 if (strstr(buffer, "GET /largeauth"))
2359 if (strstr(buffer, "Authorization: NTLM"))
2360 send(c, okmsg, sizeof(okmsg) - 1, 0);
2361 else
2363 send(c, largeauth, sizeof largeauth - 1, 0);
2364 for (i = 0; i < 10240; i++) send(c, "A", 1, 0);
2365 continue;
2368 if (strstr(buffer, "GET /cookie5"))
2370 if (strstr(buffer, "Cookie: name2=value\r\n"))
2371 send(c, okmsg, sizeof(okmsg) - 1, 0);
2372 else
2373 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2375 if (strstr(buffer, "GET /cookie4"))
2377 send(c, cookiemsg2, sizeof(cookiemsg2) - 1, 0);
2379 if (strstr(buffer, "GET /cookie3"))
2381 if (strstr(buffer, "Cookie: name=value2; NAME=value; name=value\r\n") ||
2382 broken(strstr(buffer, "Cookie: name=value2; name=value; NAME=value\r\n") != NULL))
2383 send(c, okmsg, sizeof(okmsg) - 1, 0);
2384 else
2385 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2387 if (strstr(buffer, "GET /cookie2"))
2389 if (strstr(buffer, "Cookie: NAME=value; name=value\r\n") ||
2390 broken(strstr(buffer, "Cookie: name=value; NAME=value\r\n") != NULL))
2391 send(c, okmsg, sizeof(okmsg) - 1, 0);
2392 else
2393 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2395 else if (strstr(buffer, "GET /cookie"))
2397 if (!strstr(buffer, "Cookie: name=value\r\n")) send(c, cookiemsg, sizeof(cookiemsg) - 1, 0);
2398 else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2400 else if (strstr(buffer, "GET /escape"))
2402 static const char res[] = "%0D%0A%1F%7F%3C%20%one?%1F%7F%20!%22%23$%&'()*+,-./:;%3C=%3E?@%5B%5C%5D"
2403 "%5E_%60%7B%7C%7D~%0D%0A ";
2404 static const char res2[] = "%0D%0A%1F%7F%3C%20%25two?%1F%7F%20!%22%23$%25&'()*+,-./:;%3C=%3E?@%5B%5C%5D"
2405 "%5E_%60%7B%7C%7D~%0D%0A ";
2406 static const char res3[] = "\x1f\x7f<%20%three?\x1f\x7f%20!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ";
2407 static const char res4[] = "%0D%0A%1F%7F%3C%20%four?\x1f\x7f%20!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ";
2408 static const char res5[] = "&text=one%C2%80%7F~";
2409 static const char res6[] = "&text=two%C2%80\x7f~";
2410 static const char res7[] = "&text=%E5%90%9B%E3%81%AE%E5%90%8D%E3%81%AF";
2412 if (strstr(buffer + 11, res) || strstr(buffer + 11, res2) || strstr(buffer + 11, res3) ||
2413 strstr(buffer + 11, res4) || strstr(buffer + 11, res5) || strstr(buffer + 11, res6) ||
2414 strstr(buffer + 11, res7))
2416 send(c, okmsg, sizeof(okmsg) - 1, 0);
2418 else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2420 else if (strstr(buffer, "GET /passport"))
2422 send(c, passportauth, sizeof(passportauth) - 1, 0);
2424 else if (strstr(buffer, "GET /websocket"))
2426 char headers[256], key[32], accept[64];
2427 const char *pos = strstr(buffer, "Sec-WebSocket-Key: ");
2428 if (pos && strstr(buffer, "Connection: Upgrade\r\n") &&
2429 (strstr(buffer, "Upgrade: websocket\r\n") || strstr(buffer, "Upgrade: Websocket\r\n")) &&
2430 strstr(buffer, "Host: ") && strstr(buffer, "Sec-WebSocket-Version: 13\r\n"))
2432 memcpy(headers, switchprotocols, sizeof(switchprotocols));
2433 memcpy(key, pos + 19, 24);
2434 key[24] = 0;
2436 create_websocket_accept(key, accept, sizeof(accept));
2438 strcat(headers, "Sec-WebSocket-Accept: ");
2439 strcat(headers, accept);
2440 strcat(headers, "\r\n\r\n");
2442 send(c, headers, strlen(headers), 0);
2444 else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2445 continue;
2447 if (strstr(buffer, "GET /quit"))
2449 send(c, okmsg, sizeof okmsg - 1, 0);
2450 send(c, page1, sizeof page1 - 1, 0);
2451 last_request = 1;
2453 shutdown(c, 2);
2454 closesocket(c);
2455 c = -1;
2457 } while (!last_request);
2459 closesocket(s);
2460 return 0;
2463 static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path)
2465 HINTERNET ses, con, req;
2466 char buffer[0x100];
2467 WCHAR buffer2[0x100];
2468 DWORD count, status, size, error, supported, first, target;
2469 BOOL ret;
2471 ses = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2472 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2474 SetLastError(0xdeadbeef);
2475 ret = WinHttpSetOption(ses, 0, buffer, sizeof(buffer));
2476 ok(!ret && GetLastError() == ERROR_WINHTTP_INVALID_OPTION, "got %u\n", GetLastError());
2478 SetLastError(0xdeadbeef);
2479 ret = WinHttpQueryOption(ses, 0, buffer, &size);
2480 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %u\n", GetLastError());
2482 con = WinHttpConnect(ses, L"localhost", port, 0);
2483 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2485 SetLastError(0xdeadbeef);
2486 ret = WinHttpSetOption(con, 0, buffer, sizeof(buffer));
2487 todo_wine ok(!ret && GetLastError() == ERROR_WINHTTP_INVALID_OPTION, "got %u\n", GetLastError());
2489 SetLastError(0xdeadbeef);
2490 ret = WinHttpQueryOption(con, 0, buffer, &size);
2491 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %u\n", GetLastError());
2493 req = WinHttpOpenRequest(con, verb, path, NULL, NULL, NULL, 0);
2494 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2496 SetLastError(0xdeadbeef);
2497 ret = WinHttpSetOption(req, 0, buffer, sizeof(buffer));
2498 ok(!ret && GetLastError() == ERROR_WINHTTP_INVALID_OPTION, "got %u\n", GetLastError());
2500 SetLastError(0xdeadbeef);
2501 ret = WinHttpQueryOption(req, 0, buffer, &size);
2502 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %u\n", GetLastError());
2504 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2505 ok(ret, "failed to send request %u\n", GetLastError());
2507 ret = WinHttpReceiveResponse(req, NULL);
2508 ok(ret, "failed to receive response %u\n", GetLastError());
2510 status = 0xdeadbeef;
2511 size = sizeof(status);
2512 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2513 ok(ret, "failed to query status code %u\n", GetLastError());
2514 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2516 supported = first = target = 0xdeadbeef;
2517 SetLastError(0xdeadbeef);
2518 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2519 error = GetLastError();
2520 ok(!ret, "unexpected success\n");
2521 ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
2522 ok(supported == 0xdeadbeef, "got %x\n", supported);
2523 ok(first == 0xdeadbeef, "got %x\n", first);
2524 ok(target == 0xdeadbeef, "got %x\n", target);
2526 size = sizeof(buffer2);
2527 memset(buffer2, 0, sizeof(buffer2));
2528 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, buffer2, &size, NULL);
2529 ok(ret, "failed to query for raw headers: %u\n", GetLastError());
2530 ok(!memcmp(buffer2 + lstrlenW(buffer2) - 4, L"\r\n\r\n", sizeof(L"\r\n\r\n")),
2531 "WinHttpQueryHeaders returned invalid end of header string\n");
2533 size = sizeof(buffer2);
2534 memset(buffer2, 0, sizeof(buffer2));
2535 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS, NULL, buffer2, &size, NULL);
2536 ok(ret, "failed to query for raw headers: %u\n", GetLastError());
2537 ok(!memcmp(buffer2 + (size / sizeof(WCHAR)) - 1, L"", sizeof(L"")),
2538 "WinHttpQueryHeaders returned invalid end of header string\n");
2539 ok(buffer2[(size / sizeof(WCHAR)) - 2] != 0, "returned string has too many NULL characters\n");
2541 count = 0;
2542 memset(buffer, 0, sizeof(buffer));
2543 ret = WinHttpReadData(req, buffer, sizeof buffer, &count);
2544 ok(ret, "failed to read data %u\n", GetLastError());
2545 ok(count == sizeof page1 - 1, "count was wrong\n");
2546 ok(!memcmp(buffer, page1, sizeof page1), "http data wrong\n");
2548 WinHttpCloseHandle(req);
2549 WinHttpCloseHandle(con);
2550 WinHttpCloseHandle(ses);
2553 static void test_basic_authentication(int port)
2555 HINTERNET ses, con, req;
2556 DWORD status, size, error, supported, first, target;
2557 char buffer[32];
2558 BOOL ret;
2560 ses = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2561 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2563 con = WinHttpConnect(ses, L"localhost", port, 0);
2564 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2566 req = WinHttpOpenRequest(con, NULL, L"/auth", NULL, NULL, NULL, 0);
2567 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2569 SetLastError(0xdeadbeef);
2570 ret = WinHttpQueryAuthSchemes(NULL, NULL, NULL, NULL);
2571 error = GetLastError();
2572 ok(!ret, "expected failure\n");
2573 ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
2575 SetLastError(0xdeadbeef);
2576 ret = WinHttpQueryAuthSchemes(req, NULL, NULL, NULL);
2577 error = GetLastError();
2578 ok(!ret, "expected failure\n");
2579 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2581 supported = 0xdeadbeef;
2582 SetLastError(0xdeadbeef);
2583 ret = WinHttpQueryAuthSchemes(req, &supported, NULL, NULL);
2584 error = GetLastError();
2585 ok(!ret, "expected failure\n");
2586 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2587 ok(supported == 0xdeadbeef, "got %x\n", supported);
2589 supported = first = 0xdeadbeef;
2590 SetLastError(0xdeadbeef);
2591 ret = WinHttpQueryAuthSchemes(req, &supported, &first, NULL);
2592 error = GetLastError();
2593 ok(!ret, "expected failure\n");
2594 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2595 ok(supported == 0xdeadbeef, "got %x\n", supported);
2596 ok(first == 0xdeadbeef, "got %x\n", first);
2598 supported = first = target = 0xdeadbeef;
2599 SetLastError(0xdeadbeef);
2600 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2601 error = GetLastError();
2602 ok(!ret, "expected failure\n");
2603 ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
2604 ok(supported == 0xdeadbeef, "got %x\n", supported);
2605 ok(first == 0xdeadbeef, "got %x\n", first);
2606 ok(target == 0xdeadbeef, "got %x\n", target);
2608 supported = first = target = 0xdeadbeef;
2609 SetLastError(0xdeadbeef);
2610 ret = WinHttpQueryAuthSchemes(NULL, &supported, &first, &target);
2611 error = GetLastError();
2612 ok(!ret, "expected failure\n");
2613 ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
2614 ok(supported == 0xdeadbeef, "got %x\n", supported);
2615 ok(first == 0xdeadbeef, "got %x\n", first);
2616 ok(target == 0xdeadbeef, "got %x\n", target);
2618 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2619 ok(ret, "failed to send request %u\n", GetLastError());
2621 ret = WinHttpReceiveResponse(req, NULL);
2622 ok(ret, "failed to receive response %u\n", GetLastError());
2624 status = 0xdeadbeef;
2625 size = sizeof(status);
2626 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2627 ok(ret, "failed to query status code %u\n", GetLastError());
2628 ok(status == HTTP_STATUS_DENIED, "request failed unexpectedly %u\n", status);
2630 size = 0;
2631 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
2632 error = GetLastError();
2633 ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError());
2634 if (ret)
2636 ok(size == 12, "expected 12, got %u\n", size);
2637 ok(!memcmp(buffer, unauthorized, 12), "got %s\n", buffer);
2640 supported = first = target = 0xdeadbeef;
2641 SetLastError(0xdeadbeef);
2642 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2643 error = GetLastError();
2644 ok(ret, "failed to query authentication schemes %u\n", error);
2645 ok(error == ERROR_SUCCESS || broken(error == 0xdeadbeef) /* < win7 */, "expected ERROR_SUCCESS, got %u\n", error);
2646 ok(supported == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", supported);
2647 ok(first == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", first);
2648 ok(target == WINHTTP_AUTH_TARGET_SERVER, "got %x\n", target);
2650 SetLastError(0xdeadbeef);
2651 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NTLM, NULL, NULL, NULL);
2652 error = GetLastError();
2653 ok(ret, "failed to set credentials %u\n", error);
2654 ok(error == ERROR_SUCCESS || broken(error == 0xdeadbeef) /* < win7 */, "expected ERROR_SUCCESS, got %u\n", error);
2656 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_PASSPORT, NULL, NULL, NULL);
2657 ok(ret, "failed to set credentials %u\n", GetLastError());
2659 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NEGOTIATE, NULL, NULL, NULL);
2660 ok(ret, "failed to set credentials %u\n", GetLastError());
2662 SetLastError(0xdeadbeef);
2663 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_DIGEST, NULL, NULL, NULL);
2664 error = GetLastError();
2665 ok(!ret, "expected failure\n");
2666 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2668 SetLastError(0xdeadbeef);
2669 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, NULL, NULL);
2670 error = GetLastError();
2671 ok(!ret, "expected failure\n");
2672 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2674 SetLastError(0xdeadbeef);
2675 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, L"user", NULL, NULL);
2676 error = GetLastError();
2677 ok(!ret, "expected failure\n");
2678 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2680 SetLastError(0xdeadbeef);
2681 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, L"pwd", NULL);
2682 error = GetLastError();
2683 ok(!ret, "expected failure\n");
2684 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2686 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, L"user", L"pwd", NULL);
2687 ok(ret, "failed to set credentials %u\n", GetLastError());
2689 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2690 ok(ret, "failed to send request %u\n", GetLastError());
2692 ret = WinHttpReceiveResponse(req, NULL);
2693 ok(ret, "failed to receive response %u\n", GetLastError());
2695 status = 0xdeadbeef;
2696 size = sizeof(status);
2697 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2698 ok(ret, "failed to query status code %u\n", GetLastError());
2699 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2701 size = 0;
2702 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
2703 error = GetLastError();
2704 ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError());
2705 if (ret)
2707 ok(size == 11, "expected 11, got %u\n", size);
2708 ok(!memcmp(buffer, hello_world, 11), "got %s\n", buffer);
2711 WinHttpCloseHandle(req);
2712 WinHttpCloseHandle(con);
2713 WinHttpCloseHandle(ses);
2715 /* now set the credentials first to show that they get sent with the first request */
2716 ses = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2717 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2719 con = WinHttpConnect(ses, L"localhost", port, 0);
2720 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2722 req = WinHttpOpenRequest(con, NULL, L"/auth_with_creds", NULL, NULL, NULL, 0);
2723 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2725 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, L"user", L"pwd", NULL);
2726 ok(ret, "failed to set credentials %u\n", GetLastError());
2728 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2729 ok(ret, "failed to send request %u\n", GetLastError());
2731 ret = WinHttpReceiveResponse(req, NULL);
2732 ok(ret, "failed to receive response %u\n", GetLastError());
2734 status = 0xdeadbeef;
2735 size = sizeof(status);
2736 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2737 ok(ret, "failed to query status code %u\n", GetLastError());
2738 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2740 size = 0;
2741 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
2742 error = GetLastError();
2743 ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError());
2744 if (ret)
2746 ok(size == 11, "expected 11, got %u\n", size);
2747 ok(!memcmp(buffer, hello_world, 11), "got %s\n", buffer);
2750 WinHttpCloseHandle(req);
2751 WinHttpCloseHandle(con);
2752 WinHttpCloseHandle(ses);
2754 /* credentials set with WinHttpSetCredentials take precedence over those set through options */
2756 ses = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2757 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2759 con = WinHttpConnect(ses, L"localhost", port, 0);
2760 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2762 req = WinHttpOpenRequest(con, NULL, L"/auth", NULL, NULL, NULL, 0);
2763 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2765 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, L"user", L"pwd", NULL);
2766 ok(ret, "failed to set credentials %u\n", GetLastError());
2768 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, (void *)L"user", lstrlenW(L"user"));
2769 ok(ret, "failed to set username %u\n", GetLastError());
2771 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, (void *)L"pwd2", lstrlenW(L"pwd2"));
2772 ok(ret, "failed to set password %u\n", GetLastError());
2774 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2775 ok(ret, "failed to send request %u\n", GetLastError());
2777 ret = WinHttpReceiveResponse(req, NULL);
2778 ok(ret, "failed to receive response %u\n", GetLastError());
2780 status = 0xdeadbeef;
2781 size = sizeof(status);
2782 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2783 ok(ret, "failed to query status code %u\n", GetLastError());
2784 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2786 WinHttpCloseHandle(req);
2787 WinHttpCloseHandle(con);
2788 WinHttpCloseHandle(ses);
2790 ses = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2791 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2793 con = WinHttpConnect(ses, L"localhost", port, 0);
2794 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2796 req = WinHttpOpenRequest(con, NULL, L"/auth", NULL, NULL, NULL, 0);
2797 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2799 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, (void *)L"user", lstrlenW(L"user"));
2800 ok(ret, "failed to set username %u\n", GetLastError());
2802 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, (void *)L"pwd", lstrlenW(L"pwd"));
2803 ok(ret, "failed to set password %u\n", GetLastError());
2805 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, L"user", L"pwd2", NULL);
2806 ok(ret, "failed to set credentials %u\n", GetLastError());
2808 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2809 ok(ret, "failed to send request %u\n", GetLastError());
2811 ret = WinHttpReceiveResponse(req, NULL);
2812 ok(ret, "failed to receive response %u\n", GetLastError());
2814 status = 0xdeadbeef;
2815 size = sizeof(status);
2816 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2817 ok(ret, "failed to query status code %u\n", GetLastError());
2818 ok(status == HTTP_STATUS_DENIED, "request failed unexpectedly %u\n", status);
2820 WinHttpCloseHandle(req);
2821 WinHttpCloseHandle(con);
2822 WinHttpCloseHandle(ses);
2825 static void test_multi_authentication(int port)
2827 HINTERNET ses, con, req;
2828 DWORD supported, first, target, size, index;
2829 WCHAR buf[512];
2830 BOOL ret;
2832 ses = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2833 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2835 con = WinHttpConnect(ses, L"localhost", port, 0);
2836 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2838 req = WinHttpOpenRequest(con, L"GET", L"/multiauth", NULL, NULL, NULL, 0);
2839 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2841 ret = WinHttpSendRequest(req, WINHTTP_NO_ADDITIONAL_HEADERS, 0,
2842 WINHTTP_NO_REQUEST_DATA,0, 0, 0 );
2843 ok(ret, "expected success\n");
2845 ret = WinHttpReceiveResponse(req, NULL);
2846 ok(ret, "expected success\n");
2848 supported = first = target = 0xdeadbeef;
2849 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2850 ok(ret, "expected success\n");
2851 ok(supported == (WINHTTP_AUTH_SCHEME_BASIC | WINHTTP_AUTH_SCHEME_NTLM), "got %x\n", supported);
2852 ok(target == WINHTTP_AUTH_TARGET_SERVER, "got %x\n", target);
2853 ok(first == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", first);
2855 index = 0;
2856 size = sizeof(buf);
2857 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CUSTOM, L"WWW-Authenticate", buf, &size, &index);
2858 ok(ret, "expected success\n");
2859 ok(!lstrcmpW(buf, L"Bearer"), "buf = %s\n", wine_dbgstr_w(buf));
2860 ok(size == lstrlenW(buf) * sizeof(WCHAR), "size = %u\n", size);
2861 ok(index == 1, "index = %u\n", index);
2863 index = 0;
2864 size = 0xdeadbeef;
2865 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CUSTOM, L"WWW-Authenticate", NULL, &size, &index);
2866 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2867 "WinHttpQueryHeaders returned %x(%u)\n", ret, GetLastError());
2868 ok(size == (lstrlenW(buf) + 1) * sizeof(WCHAR), "size = %u\n", size);
2869 ok(index == 0, "index = %u\n", index);
2871 WinHttpCloseHandle(req);
2872 WinHttpCloseHandle(con);
2873 WinHttpCloseHandle(ses);
2876 static void test_large_data_authentication(int port)
2878 HINTERNET ses, con, req;
2879 DWORD status, size;
2880 BOOL ret;
2882 ses = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2883 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2885 con = WinHttpConnect(ses, L"localhost", port, 0);
2886 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2888 req = WinHttpOpenRequest(con, L"GET", L"/largeauth", NULL, NULL, NULL, 0);
2889 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2891 ret = WinHttpSendRequest(req, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
2892 ok(ret, "expected success\n");
2894 ret = WinHttpReceiveResponse(req, NULL);
2895 ok(ret, "expected success\n");
2897 size = sizeof(status);
2898 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL,
2899 &status, &size, NULL);
2900 ok(ret, "expected success\n");
2901 ok(status == HTTP_STATUS_DENIED, "got %d\n", status);
2903 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NTLM, L"user", L"pwd", NULL);
2904 ok(ret, "expected success\n");
2906 ret = WinHttpSendRequest(req, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
2907 ok(ret, "expected success %d\n", GetLastError());
2909 ret = WinHttpReceiveResponse(req, NULL);
2910 ok(ret, "expected success\n");
2912 size = sizeof(status);
2913 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL,
2914 &status, &size, NULL);
2915 ok(ret, "expected success\n");
2916 ok(status == HTTP_STATUS_OK, "got %d\n", status);
2918 WinHttpCloseHandle(req);
2919 WinHttpCloseHandle(con);
2920 WinHttpCloseHandle(ses);
2923 static void test_no_headers(int port)
2925 HINTERNET ses, con, req;
2926 DWORD error;
2927 BOOL ret;
2929 ses = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2930 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2932 con = WinHttpConnect(ses, L"localhost", port, 0);
2933 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2935 req = WinHttpOpenRequest(con, NULL, L"/no_headers", NULL, NULL, NULL, 0);
2936 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2938 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2939 if (!ret)
2941 error = GetLastError();
2942 ok(error == ERROR_WINHTTP_INVALID_SERVER_RESPONSE, "got %u\n", error);
2944 else
2946 SetLastError(0xdeadbeef);
2947 ret = WinHttpReceiveResponse(req, NULL);
2948 error = GetLastError();
2949 ok(!ret, "expected failure\n");
2950 ok(error == ERROR_WINHTTP_INVALID_SERVER_RESPONSE, "got %u\n", error);
2953 WinHttpCloseHandle(req);
2954 WinHttpCloseHandle(con);
2955 WinHttpCloseHandle(ses);
2958 static void test_no_content(int port)
2960 HINTERNET ses, con, req;
2961 char buf[128];
2962 DWORD size, len = sizeof(buf), bytes_read, status;
2963 BOOL ret;
2965 ses = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2966 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2968 con = WinHttpConnect(ses, L"localhost", port, 0);
2969 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2971 req = WinHttpOpenRequest(con, NULL, L"/no_content", NULL, NULL, NULL, 0);
2972 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2974 size = 12345;
2975 SetLastError(0xdeadbeef);
2976 ret = WinHttpQueryDataAvailable(req, &size);
2977 todo_wine {
2978 ok(!ret, "expected error\n");
2979 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_STATE,
2980 "expected ERROR_WINHTTP_INCORRECT_HANDLE_STATE, got 0x%08x\n", GetLastError());
2981 ok(size == 12345 || broken(size == 0) /* Win <= 2003 */,
2982 "expected 12345, got %u\n", size);
2985 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2986 ok(ret, "expected success\n");
2988 ret = WinHttpReceiveResponse(req, NULL);
2989 ok(ret, "expected success\n");
2991 status = 0xdeadbeef;
2992 size = sizeof(status);
2993 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
2994 NULL, &status, &size, NULL);
2995 ok(ret, "expected success\n");
2996 ok(status == HTTP_STATUS_NO_CONTENT, "expected status 204, got %d\n", status);
2998 SetLastError(0xdeadbeef);
2999 size = sizeof(status);
3000 status = 12345;
3001 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
3002 NULL, &status, &size, 0);
3003 ok(!ret, "expected no content-length header\n");
3004 ok(GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND, "wrong error %u\n", GetLastError());
3005 ok(status == 12345, "expected 0, got %d\n", status);
3007 SetLastError(0xdeadbeef);
3008 size = 12345;
3009 ret = WinHttpQueryDataAvailable(req, &size);
3010 ok(ret, "expected success\n");
3011 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
3012 "wrong error %u\n", GetLastError());
3013 ok(!size, "expected 0, got %u\n", size);
3015 SetLastError(0xdeadbeef);
3016 ret = WinHttpReadData(req, buf, len, &bytes_read);
3017 ok(ret, "expected success\n");
3018 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
3019 "wrong error %u\n", GetLastError());
3020 ok(!bytes_read, "expected 0, got %u\n", bytes_read);
3022 size = 12345;
3023 ret = WinHttpQueryDataAvailable(req, &size);
3024 ok(ret, "expected success\n");
3025 ok(size == 0, "expected 0, got %d\n", size);
3027 WinHttpCloseHandle(req);
3029 size = 12345;
3030 SetLastError(0xdeadbeef);
3031 ret = WinHttpQueryDataAvailable(req, &size);
3032 ok(!ret, "expected error\n");
3033 ok(GetLastError() == ERROR_INVALID_HANDLE,
3034 "expected ERROR_INVALID_HANDLE, got 0x%08x\n", GetLastError());
3035 ok(size == 12345, "expected 12345, got %u\n", size);
3037 WinHttpCloseHandle(con);
3038 WinHttpCloseHandle(ses);
3041 static void test_head_request(int port)
3043 HINTERNET ses, con, req;
3044 char buf[128];
3045 DWORD size, len, count, status;
3046 BOOL ret;
3048 ses = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
3049 ok(ses != NULL, "failed to open session %u\n", GetLastError());
3051 con = WinHttpConnect(ses, L"localhost", port, 0);
3052 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
3054 req = WinHttpOpenRequest(con, L"HEAD", L"/head", NULL, NULL, NULL, 0);
3055 ok(req != NULL, "failed to open a request %u\n", GetLastError());
3057 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
3058 ok(ret, "failed to send request %u\n", GetLastError());
3060 ret = WinHttpReceiveResponse(req, NULL);
3061 ok(ret, "failed to receive response %u\n", GetLastError());
3063 status = 0xdeadbeef;
3064 size = sizeof(status);
3065 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
3066 NULL, &status, &size, NULL);
3067 ok(ret, "failed to get status code %u\n", GetLastError());
3068 ok(status == HTTP_STATUS_OK, "got %u\n", status);
3070 len = 0xdeadbeef;
3071 size = sizeof(len);
3072 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
3073 NULL, &len, &size, 0);
3074 ok(ret, "failed to get content-length header %u\n", GetLastError());
3075 ok(len == HTTP_STATUS_CONTINUE, "got %u\n", len);
3077 count = 0xdeadbeef;
3078 ret = WinHttpQueryDataAvailable(req, &count);
3079 ok(ret, "failed to query data available %u\n", GetLastError());
3080 ok(!count, "got %u\n", count);
3082 len = sizeof(buf);
3083 count = 0xdeadbeef;
3084 ret = WinHttpReadData(req, buf, len, &count);
3085 ok(ret, "failed to read data %u\n", GetLastError());
3086 ok(!count, "got %u\n", count);
3088 count = 0xdeadbeef;
3089 ret = WinHttpQueryDataAvailable(req, &count);
3090 ok(ret, "failed to query data available %u\n", GetLastError());
3091 ok(!count, "got %u\n", count);
3093 WinHttpCloseHandle(req);
3094 WinHttpCloseHandle(con);
3095 WinHttpCloseHandle(ses);
3098 static void test_websocket(int port)
3100 HINTERNET session, connection, request, socket;
3101 DWORD size, len, count, status, index, error;
3102 WCHAR header[32];
3103 char buf[128];
3104 BOOL ret;
3106 if (!pWinHttpWebSocketCompleteUpgrade)
3108 win_skip("WinHttpWebSocketCompleteUpgrade not supported\n");
3109 return;
3112 session = WinHttpOpen(L"winetest", 0, NULL, NULL, 0);
3113 ok(session != NULL, "got %u\n", GetLastError());
3115 connection = WinHttpConnect(session, L"localhost", port, 0);
3116 ok(connection != NULL, "got %u\n", GetLastError());
3118 request = WinHttpOpenRequest(connection, L"GET", L"/websocket", NULL, NULL, NULL, 0);
3119 ok(request != NULL, "got %u\n", GetLastError());
3121 ret = WinHttpSetOption(request, WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET, NULL, 0);
3122 ok(ret, "got %u\n", GetLastError());
3124 size = sizeof(header);
3125 SetLastError(0xdeadbeef);
3126 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_UPGRADE, NULL, &header, &size, NULL);
3127 error = GetLastError();
3128 ok(!ret, "success\n");
3129 todo_wine ok(error == ERROR_WINHTTP_INCORRECT_HANDLE_STATE, "got %u\n", error);
3131 size = sizeof(header);
3132 SetLastError(0xdeadbeef);
3133 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CONNECTION, NULL, &header, &size, NULL);
3134 error = GetLastError();
3135 ok(!ret, "success\n");
3136 todo_wine ok(error == ERROR_WINHTTP_INCORRECT_HANDLE_STATE, "got %u\n", error);
3138 index = 0;
3139 size = sizeof(buf);
3140 SetLastError(0xdeadbeef);
3141 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
3142 L"Sec-WebSocket-Key", buf, &size, &index);
3143 error = GetLastError();
3144 ok(!ret, "success\n");
3145 ok(error == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", error);
3147 index = 0;
3148 size = sizeof(buf);
3149 SetLastError(0xdeadbeef);
3150 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
3151 L"Sec-WebSocket-Version", buf, &size, &index);
3152 error = GetLastError();
3153 ok(!ret, "success\n");
3154 ok(error == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", error);
3156 ret = WinHttpSendRequest(request, NULL, 0, NULL, 0, 0, 0);
3157 ok(ret, "got %u\n", GetLastError());
3159 size = sizeof(header);
3160 SetLastError(0xdeadbeef);
3161 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_UPGRADE, NULL, &header, &size, NULL);
3162 error = GetLastError();
3163 ok(!ret, "success\n");
3164 todo_wine ok(error == ERROR_WINHTTP_INCORRECT_HANDLE_STATE, "got %u\n", error);
3166 size = sizeof(header);
3167 SetLastError(0xdeadbeef);
3168 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CONNECTION, NULL, &header, &size, NULL);
3169 error = GetLastError();
3170 ok(!ret, "success\n");
3171 todo_wine ok(error == ERROR_WINHTTP_INCORRECT_HANDLE_STATE, "got %u\n", error);
3173 index = 0;
3174 buf[0] = 0;
3175 size = sizeof(buf);
3176 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
3177 L"Sec-WebSocket-Key", buf, &size, &index);
3178 ok(ret, "got %u\n", GetLastError());
3180 index = 0;
3181 buf[0] = 0;
3182 size = sizeof(buf);
3183 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
3184 L"Sec-WebSocket-Version", buf, &size, &index);
3185 ok(ret, "got %u\n", GetLastError());
3187 ret = WinHttpReceiveResponse(request, NULL);
3188 ok(ret, "got %u\n", GetLastError());
3190 count = 0xdeadbeef;
3191 ret = WinHttpQueryDataAvailable(request, &count);
3192 ok(ret, "got %u\n", GetLastError());
3193 ok(!count, "got %u\n", count);
3195 header[0] = 0;
3196 size = sizeof(header);
3197 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_UPGRADE, NULL, &header, &size, NULL);
3198 ok(ret, "got %u\n", GetLastError());
3199 ok(!wcscmp( header, L"websocket" ), "got %s\n", wine_dbgstr_w(header));
3201 header[0] = 0;
3202 size = sizeof(header);
3203 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CONNECTION, NULL, &header, &size, NULL);
3204 ok(ret, "got %u\n", GetLastError());
3205 ok(!wcscmp( header, L"Upgrade" ), "got %s\n", wine_dbgstr_w(header));
3207 status = 0xdeadbeef;
3208 size = sizeof(status);
3209 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status,
3210 &size, NULL);
3211 ok(ret, "got %u\n", GetLastError());
3212 ok(status == HTTP_STATUS_SWITCH_PROTOCOLS, "got %u\n", status);
3214 len = 0xdeadbeef;
3215 size = sizeof(len);
3216 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER, NULL, &len,
3217 &size, 0);
3218 ok(!ret, "success\n");
3220 index = 0;
3221 size = sizeof(buf);
3222 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM, L"Sec-WebSocket-Accept", buf, &size, &index);
3223 ok(ret, "got %u\n", GetLastError());
3225 socket = pWinHttpWebSocketCompleteUpgrade(request, 0);
3226 ok(socket != NULL, "got %u\n", GetLastError());
3228 header[0] = 0;
3229 size = sizeof(header);
3230 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_UPGRADE, NULL, &header, &size, NULL);
3231 ok(ret, "got %u\n", GetLastError());
3232 ok(!wcscmp( header, L"websocket" ), "got %s\n", wine_dbgstr_w(header));
3234 header[0] = 0;
3235 size = sizeof(header);
3236 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CONNECTION, NULL, &header, &size, NULL);
3237 ok(ret, "got %u\n", GetLastError());
3238 ok(!wcscmp( header, L"Upgrade" ), "got %s\n", wine_dbgstr_w(header));
3240 index = 0;
3241 size = sizeof(buf);
3242 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM, L"Sec-WebSocket-Accept", buf, &size, &index);
3243 ok(ret, "got %u\n", GetLastError());
3245 /* Send/Receive on websock */
3247 WinHttpCloseHandle(request);
3248 WinHttpCloseHandle(socket);
3249 WinHttpCloseHandle(connection);
3250 WinHttpCloseHandle(session);
3253 static void test_not_modified(int port)
3255 BOOL ret;
3256 HINTERNET session, request, connection;
3257 DWORD index, len, status, size, start = GetTickCount();
3258 SYSTEMTIME st;
3259 WCHAR today[(sizeof(L"If-Modified-Since: ") + WINHTTP_TIME_FORMAT_BUFSIZE)/sizeof(WCHAR) + 3], buffer[32];
3261 memcpy(today, L"If-Modified-Since: ", sizeof(L"If-Modified-Since: "));
3262 GetSystemTime(&st);
3263 WinHttpTimeFromSystemTime(&st, &today[ARRAY_SIZE(L"If-Modified-Since: ") - 1]);
3265 session = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY,
3266 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
3267 ok(session != NULL, "WinHttpOpen failed: %u\n", GetLastError());
3269 connection = WinHttpConnect(session, L"localhost", port, 0);
3270 ok(connection != NULL, "WinHttpConnect failed: %u\n", GetLastError());
3272 request = WinHttpOpenRequest(connection, NULL, L"/not_modified", NULL, WINHTTP_NO_REFERER,
3273 WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
3274 ok(request != NULL, "WinHttpOpenrequest failed: %u\n", GetLastError());
3276 ret = WinHttpSendRequest(request, today, 0, NULL, 0, 0, 0);
3277 ok(ret, "WinHttpSendRequest failed: %u\n", GetLastError());
3279 ret = WinHttpReceiveResponse(request, NULL);
3280 ok(ret, "WinHttpReceiveResponse failed: %u\n", GetLastError());
3282 index = 0;
3283 len = sizeof(buffer);
3284 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
3285 L"If-Modified-Since", buffer, &len, &index);
3286 ok(ret, "failed to get header %u\n", GetLastError());
3288 status = 0xdeadbeef;
3289 size = sizeof(status);
3290 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER,
3291 NULL, &status, &size, NULL);
3292 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
3293 ok(status == HTTP_STATUS_NOT_MODIFIED, "got %u\n", status);
3295 size = 0xdeadbeef;
3296 ret = WinHttpQueryDataAvailable(request, &size);
3297 ok(ret, "WinHttpQueryDataAvailable failed: %u\n", GetLastError());
3298 ok(!size, "got %u\n", size);
3300 WinHttpCloseHandle(request);
3301 WinHttpCloseHandle(connection);
3302 WinHttpCloseHandle(session);
3303 start = GetTickCount() - start;
3304 ok(start <= 2000, "Expected less than 2 seconds for the test, got %u ms\n", start);
3307 static void test_bad_header( int port )
3309 WCHAR buffer[32];
3310 HINTERNET ses, con, req;
3311 DWORD index, len;
3312 BOOL ret;
3314 ses = WinHttpOpen( L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3315 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3317 con = WinHttpConnect( ses, L"localhost", port, 0 );
3318 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3320 req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
3321 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3323 ret = WinHttpAddRequestHeaders( req, L"Content-Type: text/html\n\r", ~0u, WINHTTP_ADDREQ_FLAG_ADD );
3324 ok( ret, "failed to add header %u\n", GetLastError() );
3326 index = 0;
3327 buffer[0] = 0;
3328 len = sizeof(buffer);
3329 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_CUSTOM|WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
3330 L"Content-Type", buffer, &len, &index );
3331 ok( ret, "failed to query headers %u\n", GetLastError() );
3332 ok( !lstrcmpW( buffer, L"text/html" ), "got %s\n", wine_dbgstr_w(buffer) );
3333 ok( index == 1, "index = %u\n", index );
3335 WinHttpCloseHandle( req );
3336 WinHttpCloseHandle( con );
3337 WinHttpCloseHandle( ses );
3340 static void test_multiple_reads(int port)
3342 HINTERNET ses, con, req;
3343 DWORD total_len = 0;
3344 BOOL ret;
3346 ses = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
3347 ok(ses != NULL, "failed to open session %u\n", GetLastError());
3349 con = WinHttpConnect(ses, L"localhost", port, 0);
3350 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
3352 req = WinHttpOpenRequest(con, NULL, L"big", NULL, NULL, NULL, 0);
3353 ok(req != NULL, "failed to open a request %u\n", GetLastError());
3355 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
3356 ok(ret, "failed to send request %u\n", GetLastError());
3358 ret = WinHttpReceiveResponse(req, NULL);
3359 ok(ret == TRUE, "expected success\n");
3361 for (;;)
3363 DWORD len = 0xdeadbeef;
3364 ret = WinHttpQueryDataAvailable( req, &len );
3365 ok( ret, "WinHttpQueryDataAvailable failed with error %u\n", GetLastError() );
3366 if (ret) ok( len != 0xdeadbeef, "WinHttpQueryDataAvailable return wrong length\n" );
3367 if (len)
3369 DWORD bytes_read;
3370 char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 );
3372 ret = WinHttpReadData( req, buf, len, &bytes_read );
3373 ok(ret, "WinHttpReadData failed: %u.\n", GetLastError());
3374 ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len );
3376 HeapFree( GetProcessHeap(), 0, buf );
3377 if (!bytes_read) break;
3378 total_len += bytes_read;
3380 if (!len) break;
3382 ok(total_len == BIG_BUFFER_LEN, "got wrong length: 0x%x\n", total_len);
3384 WinHttpCloseHandle(req);
3385 WinHttpCloseHandle(con);
3386 WinHttpCloseHandle(ses);
3389 static void test_cookies( int port )
3391 HINTERNET ses, con, req;
3392 DWORD status, size;
3393 BOOL ret;
3395 ses = WinHttpOpen( L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3396 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3398 con = WinHttpConnect( ses, L"localhost", port, 0 );
3399 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3401 req = WinHttpOpenRequest( con, NULL, L"/cookie", NULL, NULL, NULL, 0 );
3402 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3404 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3405 ok( ret, "failed to send request %u\n", GetLastError() );
3407 ret = WinHttpReceiveResponse( req, NULL );
3408 ok( ret, "failed to receive response %u\n", GetLastError() );
3410 status = 0xdeadbeef;
3411 size = sizeof(status);
3412 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3413 ok( ret, "failed to query status code %u\n", GetLastError() );
3414 ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
3416 WinHttpCloseHandle( req );
3418 req = WinHttpOpenRequest( con, NULL, L"/cookie2", NULL, NULL, NULL, 0 );
3419 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3421 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3422 ok( ret, "failed to send request %u\n", GetLastError() );
3424 ret = WinHttpReceiveResponse( req, NULL );
3425 ok( ret, "failed to receive response %u\n", GetLastError() );
3427 status = 0xdeadbeef;
3428 size = sizeof(status);
3429 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3430 ok( ret, "failed to query status code %u\n", GetLastError() );
3431 ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
3433 WinHttpCloseHandle( req );
3434 WinHttpCloseHandle( con );
3436 con = WinHttpConnect( ses, L"localhost", port, 0 );
3437 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3439 req = WinHttpOpenRequest( con, NULL, L"/cookie2", NULL, NULL, NULL, 0 );
3440 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3442 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3443 ok( ret, "failed to send request %u\n", GetLastError() );
3445 ret = WinHttpReceiveResponse( req, NULL );
3446 ok( ret, "failed to receive response %u\n", GetLastError() );
3448 status = 0xdeadbeef;
3449 size = sizeof(status);
3450 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3451 ok( ret, "failed to query status code %u\n", GetLastError() );
3452 ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
3454 WinHttpCloseHandle( req );
3456 req = WinHttpOpenRequest( con, NULL, L"/cookie3", NULL, NULL, NULL, 0 );
3457 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3458 ret = WinHttpSendRequest( req, L"Cookie: name=value2\r\n", ~0u, NULL, 0, 0, 0 );
3459 ok( ret, "failed to send request %u\n", GetLastError() );
3461 ret = WinHttpReceiveResponse( req, NULL );
3462 ok( ret, "failed to receive response %u\n", GetLastError() );
3464 status = 0xdeadbeef;
3465 size = sizeof(status);
3466 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3467 ok( ret, "failed to query status code %u\n", GetLastError() );
3468 ok( status == HTTP_STATUS_OK || broken(status == HTTP_STATUS_BAD_REQUEST), "request failed unexpectedly %u\n", status );
3470 WinHttpCloseHandle( req );
3471 WinHttpCloseHandle( con );
3472 WinHttpCloseHandle( ses );
3474 ses = WinHttpOpen( L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3475 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3477 con = WinHttpConnect( ses, L"localhost", port, 0 );
3478 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3480 req = WinHttpOpenRequest( con, NULL, L"/cookie2", NULL, NULL, NULL, 0 );
3481 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3483 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3484 ok( ret, "failed to send request %u\n", GetLastError() );
3486 ret = WinHttpReceiveResponse( req, NULL );
3487 ok( ret, "failed to receive response %u\n", GetLastError() );
3489 status = 0xdeadbeef;
3490 size = sizeof(status);
3491 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3492 ok( ret, "failed to query status code %u\n", GetLastError() );
3493 ok( status == HTTP_STATUS_BAD_REQUEST, "request failed unexpectedly %u\n", status );
3495 WinHttpCloseHandle( req );
3496 WinHttpCloseHandle( con );
3497 WinHttpCloseHandle( ses );
3499 ses = WinHttpOpen( L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3500 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3502 con = WinHttpConnect( ses, L"localhost", port, 0 );
3503 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3505 req = WinHttpOpenRequest( con, NULL, L"/cookie4", NULL, NULL, NULL, 0 );
3506 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3508 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3509 ok( ret, "failed to send request %u\n", GetLastError() );
3511 ret = WinHttpReceiveResponse( req, NULL );
3512 ok( ret, "failed to receive response %u\n", GetLastError() );
3514 status = 0xdeadbeef;
3515 size = sizeof(status);
3516 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3517 ok( ret, "failed to query status code %u\n", GetLastError() );
3518 ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
3519 WinHttpCloseHandle( req );
3521 req = WinHttpOpenRequest( con, NULL, L"/cookie5", NULL, NULL, NULL, 0 );
3522 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3524 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3525 ok( ret, "failed to send request %u\n", GetLastError() );
3527 ret = WinHttpReceiveResponse( req, NULL );
3528 ok( ret, "failed to receive response %u\n", GetLastError() );
3530 status = 0xdeadbeef;
3531 size = sizeof(status);
3532 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3533 ok( ret, "failed to query status code %u\n", GetLastError() );
3534 ok( status == HTTP_STATUS_OK || broken(status == HTTP_STATUS_BAD_REQUEST) /* < win7 */,
3535 "request failed unexpectedly %u\n", status );
3537 WinHttpCloseHandle( req );
3538 WinHttpCloseHandle( con );
3539 WinHttpCloseHandle( ses );
3542 static void do_request( HINTERNET con, const WCHAR *obj, DWORD flags )
3544 HINTERNET req;
3545 DWORD status, size;
3546 BOOL ret;
3548 req = WinHttpOpenRequest( con, NULL, obj, NULL, NULL, NULL, flags );
3549 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3551 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3552 ok( ret, "failed to send request %u\n", GetLastError() );
3554 ret = WinHttpReceiveResponse( req, NULL );
3555 ok( ret, "failed to receive response %u\n", GetLastError() );
3557 status = 0xdeadbeef;
3558 size = sizeof(status);
3559 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3560 ok( ret, "failed to query status code %u\n", GetLastError() );
3561 ok( status == HTTP_STATUS_OK || broken(status == HTTP_STATUS_BAD_REQUEST) /* < win7 */,
3562 "request %s with flags %08x failed %u\n", wine_dbgstr_w(obj), flags, status );
3563 WinHttpCloseHandle( req );
3566 static void test_request_path_escapes( int port )
3568 static const WCHAR objW[] =
3569 {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','o','n','e','?',0x1f,0x7f,' ','!','"','#',
3570 '$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^','_','`',
3571 '{','|','}','~','\r','\n',0};
3572 static const WCHAR obj2W[] =
3573 {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','t','w','o','?',0x1f,0x7f,' ','!','"','#',
3574 '$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^','_','`',
3575 '{','|','}','~','\r','\n',0};
3576 static const WCHAR obj3W[] =
3577 {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','t','h','r','e','e','?',0x1f,0x7f,' ','!',
3578 '"','#','$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^',
3579 '_','`','{','|','}','~','\r','\n',0};
3580 static const WCHAR obj4W[] =
3581 {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','f','o','u','r','?',0x1f,0x7f,' ','!','"',
3582 '#','$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^','_',
3583 '`','{','|','}','~','\r','\n',0};
3584 static const WCHAR obj5W[] =
3585 {'/','e','s','c','a','p','e','&','t','e','x','t','=','o','n','e',0x80,0x7f,0x7e,0};
3586 static const WCHAR obj6W[] =
3587 {'/','e','s','c','a','p','e','&','t','e','x','t','=','t','w','o',0x80,0x7f,0x7e,0};
3588 static const WCHAR obj7W[] =
3589 {'/','e','s','c','a','p','e','&','t','e','x','t','=',0x541b,0x306e,0x540d,0x306f,0};
3590 HINTERNET ses, con;
3592 ses = WinHttpOpen( L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3593 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3595 con = WinHttpConnect( ses, L"localhost", port, 0 );
3596 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3598 do_request( con, objW, 0 );
3599 do_request( con, obj2W, WINHTTP_FLAG_ESCAPE_PERCENT );
3600 do_request( con, obj3W, WINHTTP_FLAG_ESCAPE_DISABLE );
3601 do_request( con, obj4W, WINHTTP_FLAG_ESCAPE_DISABLE_QUERY );
3602 do_request( con, obj5W, 0 );
3603 do_request( con, obj6W, WINHTTP_FLAG_ESCAPE_DISABLE );
3604 do_request( con, obj7W, WINHTTP_FLAG_ESCAPE_DISABLE );
3606 WinHttpCloseHandle( con );
3607 WinHttpCloseHandle( ses );
3610 static void test_connection_info( int port )
3612 HINTERNET ses, con, req;
3613 WINHTTP_CONNECTION_INFO info;
3614 DWORD size, error;
3615 BOOL ret;
3617 ses = WinHttpOpen( L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3618 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3620 con = WinHttpConnect( ses, L"localhost", port, 0 );
3621 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3623 req = WinHttpOpenRequest( con, NULL, L"/basic", NULL, NULL, NULL, 0 );
3624 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3626 size = sizeof(info);
3627 SetLastError( 0xdeadbeef );
3628 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3629 error = GetLastError();
3630 if (!ret && error == ERROR_INVALID_PARAMETER)
3632 win_skip( "WINHTTP_OPTION_CONNECTION_INFO not supported\n" );
3633 return;
3635 ok( !ret, "unexpected success\n" );
3636 ok( error == ERROR_WINHTTP_INCORRECT_HANDLE_STATE, "got %u\n", error );
3638 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3639 ok( ret, "failed to send request %u\n", GetLastError() );
3641 size = 0;
3642 SetLastError( 0xdeadbeef );
3643 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3644 error = GetLastError();
3645 ok( !ret, "unexpected success\n" );
3646 ok( error == ERROR_INSUFFICIENT_BUFFER, "got %u\n", error );
3648 size = sizeof(info);
3649 memset( &info, 0, sizeof(info) );
3650 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3651 ok( ret, "failed to retrieve connection info %u\n", GetLastError() );
3652 ok( info.cbSize == sizeof(info) || info.cbSize == sizeof(info) - sizeof(info.cbSize) /* Win7 */, "wrong size %u\n", info.cbSize );
3654 ret = WinHttpReceiveResponse( req, NULL );
3655 ok( ret, "failed to receive response %u\n", GetLastError() );
3657 size = sizeof(info);
3658 memset( &info, 0, sizeof(info) );
3659 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3660 ok( ret, "failed to retrieve connection info %u\n", GetLastError() );
3661 ok( info.cbSize == sizeof(info) || info.cbSize == sizeof(info) - sizeof(info.cbSize) /* Win7 */, "wrong size %u\n", info.cbSize );
3663 WinHttpCloseHandle( req );
3664 WinHttpCloseHandle( con );
3665 WinHttpCloseHandle( ses );
3668 static void test_passport_auth( int port )
3670 static const WCHAR headersW[] =
3671 L"HTTP/1.1 401 Found\r\nContent-Length: 0\r\nLocation: /\r\nWWW-Authenticate: Passport1.4\r\n\r\n";
3672 HINTERNET ses, con, req;
3673 DWORD status, size, option, err;
3674 WCHAR buf[128];
3675 BOOL ret;
3677 ses = WinHttpOpen( L"winetest", 0, NULL, NULL, 0 );
3678 ok( ses != NULL, "got %u\n", GetLastError() );
3680 option = WINHTTP_ENABLE_PASSPORT_AUTH;
3681 ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH, &option, sizeof(option) );
3682 ok( ret, "got %u\n", GetLastError() );
3684 con = WinHttpConnect( ses, L"localhost", port, 0 );
3685 ok( con != NULL, "got %u\n", GetLastError() );
3687 req = WinHttpOpenRequest( con, NULL, L"/passport", NULL, NULL, NULL, 0 );
3688 ok( req != NULL, "got %u\n", GetLastError() );
3690 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3691 ok( ret, "got %u\n", GetLastError() );
3693 ret = WinHttpReceiveResponse( req, NULL );
3694 err = GetLastError();
3695 ok( ret || broken(!ret && err == ERROR_WINHTTP_LOGIN_FAILURE) /* winxp */
3696 || broken(!ret && err == ERROR_WINHTTP_INVALID_SERVER_RESPONSE ), "got %u\n", err );
3697 if (!ret)
3699 win_skip("no support for Passport redirects\n");
3700 goto cleanup;
3703 status = 0xdeadbeef;
3704 size = sizeof(status);
3705 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3706 ok( ret, "got %u\n", GetLastError() );
3707 ok( status == HTTP_STATUS_DENIED, "got %u\n", status );
3709 buf[0] = 0;
3710 size = sizeof(buf);
3711 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_TEXT, NULL, buf, &size, NULL );
3712 ok( ret, "got %u\n", GetLastError() );
3713 ok( !lstrcmpW(L"Found", buf) || broken(!lstrcmpW(L"Unauthorized", buf)) /* < win7 */, "got %s\n",
3714 wine_dbgstr_w(buf) );
3716 buf[0] = 0;
3717 size = sizeof(buf);
3718 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, buf, &size, NULL );
3719 ok( ret || broken(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER) /* < win7 */, "got %u\n", GetLastError() );
3720 if (ret)
3722 ok( size == lstrlenW(headersW) * sizeof(WCHAR), "got %u\n", size );
3723 ok( !lstrcmpW(headersW, buf), "got %s\n", wine_dbgstr_w(buf) );
3726 cleanup:
3727 WinHttpCloseHandle( req );
3728 WinHttpCloseHandle( con );
3729 WinHttpCloseHandle( ses );
3732 static void test_credentials(void)
3734 static WCHAR userW[] = {'u','s','e','r',0};
3735 static WCHAR passW[] = {'p','a','s','s',0};
3736 static WCHAR proxy_userW[] = {'p','r','o','x','y','u','s','e','r',0};
3737 static WCHAR proxy_passW[] = {'p','r','o','x','y','p','a','s','s',0};
3738 HINTERNET ses, con, req;
3739 DWORD size, error;
3740 WCHAR buffer[32];
3741 BOOL ret;
3743 ses = WinHttpOpen(L"winetest", 0, proxy_userW, proxy_passW, 0);
3744 ok(ses != NULL, "failed to open session %u\n", GetLastError());
3746 con = WinHttpConnect(ses, L"localhost", 0, 0);
3747 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
3749 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
3750 ok(req != NULL, "failed to open a request %u\n", GetLastError());
3752 size = ARRAY_SIZE(buffer);
3753 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size);
3754 ok(ret, "failed to query proxy username %u\n", GetLastError());
3755 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3756 ok(!size, "expected 0, got %u\n", size);
3758 size = ARRAY_SIZE(buffer);
3759 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size);
3760 ok(ret, "failed to query proxy password %u\n", GetLastError());
3761 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3762 ok(!size, "expected 0, got %u\n", size);
3764 ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_USERNAME, proxy_userW, lstrlenW(proxy_userW));
3765 ok(ret, "failed to set username %u\n", GetLastError());
3767 size = ARRAY_SIZE(buffer);
3768 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size);
3769 ok(ret, "failed to query proxy username %u\n", GetLastError());
3770 ok(!wcscmp(buffer, proxy_userW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3771 ok(size == lstrlenW(proxy_userW) * sizeof(WCHAR), "unexpected result %u\n", size);
3773 size = ARRAY_SIZE(buffer);
3774 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
3775 ok(ret, "failed to query username %u\n", GetLastError());
3776 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3777 ok(!size, "expected 0, got %u\n", size);
3779 size = ARRAY_SIZE(buffer);
3780 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3781 ok(ret, "failed to query password %u\n", GetLastError());
3782 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3783 ok(!size, "expected 0, got %u\n", size);
3785 ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_PASSWORD, proxy_passW, lstrlenW(proxy_passW));
3786 ok(ret, "failed to set proxy password %u\n", GetLastError());
3788 size = ARRAY_SIZE(buffer);
3789 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size);
3790 ok(ret, "failed to query proxy password %u\n", GetLastError());
3791 ok(!wcscmp(buffer, proxy_passW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3792 ok(size == lstrlenW(proxy_passW) * sizeof(WCHAR), "unexpected result %u\n", size);
3794 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
3795 ok(ret, "failed to set username %u\n", GetLastError());
3797 size = ARRAY_SIZE(buffer);
3798 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
3799 ok(ret, "failed to query username %u\n", GetLastError());
3800 ok(!wcscmp(buffer, userW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3801 ok(size == lstrlenW(userW) * sizeof(WCHAR), "unexpected result %u\n", size);
3803 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, passW, lstrlenW(passW));
3804 ok(ret, "failed to set password %u\n", GetLastError());
3806 size = ARRAY_SIZE(buffer);
3807 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3808 ok(ret, "failed to query password %u\n", GetLastError());
3809 ok(!wcscmp(buffer, passW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3810 ok(size == lstrlenW(passW) * sizeof(WCHAR), "unexpected result %u\n", size);
3812 WinHttpCloseHandle(req);
3814 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
3815 ok(req != NULL, "failed to open a request %u\n", GetLastError());
3817 SetLastError(0xdeadbeef);
3818 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, NULL, NULL);
3819 error = GetLastError();
3820 ok(!ret, "expected failure\n");
3821 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
3823 SetLastError(0xdeadbeef);
3824 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, passW, NULL);
3825 error = GetLastError();
3826 ok(!ret, "expected failure\n");
3827 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
3829 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
3830 ok(ret, "failed to set credentials %u\n", GetLastError());
3832 size = ARRAY_SIZE(buffer);
3833 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
3834 ok(ret, "failed to query username %u\n", GetLastError());
3835 todo_wine {
3836 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3837 ok(!size, "expected 0, got %u\n", size);
3840 size = ARRAY_SIZE(buffer);
3841 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3842 ok(ret, "failed to query password %u\n", GetLastError());
3843 todo_wine {
3844 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3845 ok(!size, "expected 0, got %u\n", size);
3848 WinHttpCloseHandle(req);
3849 WinHttpCloseHandle(con);
3850 WinHttpCloseHandle(ses);
3853 static void test_IWinHttpRequest(int port)
3855 static const WCHAR data_start[] = {'<','!','D','O','C','T','Y','P','E',' ','h','t','m','l',' ','P','U','B','L','I','C'};
3856 HRESULT hr;
3857 IWinHttpRequest *req;
3858 BSTR method, url, username, password, response = NULL, status_text = NULL, headers = NULL;
3859 BSTR date, today, connection, value = NULL;
3860 VARIANT async, empty, timeout, body, body2, proxy_server, bypass_list, data, cp;
3861 VARIANT_BOOL succeeded;
3862 LONG status;
3863 WCHAR todayW[WINHTTP_TIME_FORMAT_BUFSIZE];
3864 SYSTEMTIME st;
3865 IStream *stream, *stream2;
3866 LARGE_INTEGER pos;
3867 char buf[128];
3868 WCHAR bufW[128];
3869 DWORD count;
3871 GetSystemTime( &st );
3872 WinHttpTimeFromSystemTime( &st, todayW );
3874 CoInitialize( NULL );
3875 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3876 ok( hr == S_OK, "got %08x\n", hr );
3878 V_VT( &empty ) = VT_ERROR;
3879 V_ERROR( &empty ) = 0xdeadbeef;
3881 V_VT( &async ) = VT_BOOL;
3882 V_BOOL( &async ) = VARIANT_FALSE;
3884 method = SysAllocString( L"POST" );
3885 url = SysAllocString( L"http://test.winehq.org/tests/post.php" );
3886 hr = IWinHttpRequest_Open( req, method, url, async );
3887 ok( hr == S_OK, "got %08x\n", hr );
3888 SysFreeString( method );
3889 SysFreeString( url );
3891 V_VT( &data ) = VT_BSTR;
3892 V_BSTR( &data ) = SysAllocString( L"testdata\x80" );
3893 hr = IWinHttpRequest_Send( req, data );
3894 ok( hr == S_OK || hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_INVALID_SERVER_RESPONSE ), "got %08x\n", hr );
3895 SysFreeString( V_BSTR( &data ) );
3896 if (hr != S_OK) goto done;
3898 hr = IWinHttpRequest_Open( req, NULL, NULL, empty );
3899 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3901 method = SysAllocString( L"GET" );
3902 hr = IWinHttpRequest_Open( req, method, NULL, empty );
3903 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3905 hr = IWinHttpRequest_Open( req, method, NULL, async );
3906 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3908 url = SysAllocString( L"http://test.winehq.org" );
3909 hr = IWinHttpRequest_Open( req, NULL, url, empty );
3910 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3912 hr = IWinHttpRequest_Abort( req );
3913 ok( hr == S_OK, "got %08x\n", hr );
3915 hr = IWinHttpRequest_Open( req, method, url, empty );
3916 ok( hr == S_OK, "got %08x\n", hr );
3918 hr = IWinHttpRequest_Abort( req );
3919 ok( hr == S_OK, "got %08x\n", hr );
3921 IWinHttpRequest_Release( req );
3923 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3924 ok( hr == S_OK, "got %08x\n", hr );
3926 SysFreeString( url );
3927 url = SysAllocString( L"test.winehq.org" );
3928 hr = IWinHttpRequest_Open( req, method, url, async );
3929 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ), "got %08x\n", hr );
3931 SysFreeString( method );
3932 method = SysAllocString( L"INVALID" );
3933 hr = IWinHttpRequest_Open( req, method, url, async );
3934 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ), "got %08x\n", hr );
3936 SysFreeString( method );
3937 method = SysAllocString( L"GET" );
3938 SysFreeString( url );
3939 url = SysAllocString( L"http://test.winehq.org" );
3940 V_VT( &async ) = VT_ERROR;
3941 V_ERROR( &async ) = DISP_E_PARAMNOTFOUND;
3942 hr = IWinHttpRequest_Open( req, method, url, async );
3943 ok( hr == S_OK, "got %08x\n", hr );
3945 V_VT( &cp ) = VT_ERROR;
3946 V_ERROR( &cp ) = 0xdeadbeef;
3947 hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3948 ok( hr == S_OK, "got %08x\n", hr );
3949 ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3950 ok( V_I4( &cp ) == CP_UTF8, "got %u\n", V_I4( &cp ) );
3952 V_VT( &cp ) = VT_UI4;
3953 V_UI4( &cp ) = CP_ACP;
3954 hr = IWinHttpRequest_put_Option( req, WinHttpRequestOption_URLCodePage, cp );
3955 ok( hr == S_OK, "got %08x\n", hr );
3957 V_VT( &cp ) = VT_ERROR;
3958 V_ERROR( &cp ) = 0xdeadbeef;
3959 hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3960 ok( hr == S_OK, "got %08x\n", hr );
3961 ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3962 ok( V_I4( &cp ) == CP_ACP, "got %u\n", V_I4( &cp ) );
3964 value = SysAllocString( L"utf-8" );
3965 V_VT( &cp ) = VT_BSTR;
3966 V_BSTR( &cp ) = value;
3967 hr = IWinHttpRequest_put_Option( req, WinHttpRequestOption_URLCodePage, cp );
3968 ok( hr == S_OK, "got %08x\n", hr );
3969 SysFreeString( value );
3971 V_VT( &cp ) = VT_ERROR;
3972 V_ERROR( &cp ) = 0xdeadbeef;
3973 hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3974 ok( hr == S_OK, "got %08x\n", hr );
3975 ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3976 ok( V_I4( &cp ) == CP_UTF8, "got %u\n", V_I4( &cp ) );
3978 hr = IWinHttpRequest_Abort( req );
3979 ok( hr == S_OK, "got %08x\n", hr );
3981 hr = IWinHttpRequest_Send( req, empty );
3982 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3984 hr = IWinHttpRequest_Abort( req );
3985 ok( hr == S_OK, "got %08x\n", hr );
3987 IWinHttpRequest_Release( req );
3989 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3990 ok( hr == S_OK, "got %08x\n", hr );
3992 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3993 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3995 hr = IWinHttpRequest_get_ResponseText( req, &response );
3996 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3998 hr = IWinHttpRequest_get_Status( req, NULL );
3999 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4001 hr = IWinHttpRequest_get_Status( req, &status );
4002 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
4004 hr = IWinHttpRequest_get_StatusText( req, NULL );
4005 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4007 hr = IWinHttpRequest_get_StatusText( req, &status_text );
4008 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
4010 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
4011 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4013 hr = IWinHttpRequest_SetTimeouts( req, 10000, 10000, 10000, 10000 );
4014 ok( hr == S_OK, "got %08x\n", hr );
4016 hr = IWinHttpRequest_SetCredentials( req, NULL, NULL, 0xdeadbeef );
4017 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
4019 VariantInit( &proxy_server );
4020 V_VT( &proxy_server ) = VT_ERROR;
4021 VariantInit( &bypass_list );
4022 V_VT( &bypass_list ) = VT_ERROR;
4023 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
4024 ok( hr == S_OK, "got %08x\n", hr );
4026 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
4027 ok( hr == S_OK, "got %08x\n", hr );
4029 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
4030 ok( hr == S_OK, "got %08x\n", hr );
4032 hr = IWinHttpRequest_GetAllResponseHeaders( req, NULL );
4033 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4035 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
4036 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
4038 hr = IWinHttpRequest_GetResponseHeader( req, NULL, NULL );
4039 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
4041 connection = SysAllocString( L"Connection" );
4042 hr = IWinHttpRequest_GetResponseHeader( req, connection, NULL );
4043 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
4045 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
4046 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
4048 hr = IWinHttpRequest_SetRequestHeader( req, NULL, NULL );
4049 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4051 date = SysAllocString( L"Date" );
4052 hr = IWinHttpRequest_SetRequestHeader( req, date, NULL );
4053 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
4055 today = SysAllocString( todayW );
4056 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
4057 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
4059 hr = IWinHttpRequest_SetAutoLogonPolicy( req, 0xdeadbeef );
4060 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4062 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
4063 ok( hr == S_OK, "got %08x\n", hr );
4065 SysFreeString( method );
4066 method = SysAllocString( L"GET" );
4067 SysFreeString( url );
4068 url = SysAllocString( L"http://test.winehq.org" );
4069 hr = IWinHttpRequest_Open( req, method, url, async );
4070 ok( hr == S_OK, "got %08x\n", hr );
4072 hr = IWinHttpRequest_get_ResponseText( req, NULL );
4073 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4075 hr = IWinHttpRequest_get_ResponseText( req, &response );
4076 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
4078 hr = IWinHttpRequest_get_Status( req, &status );
4079 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
4081 hr = IWinHttpRequest_get_StatusText( req, &status_text );
4082 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
4084 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
4085 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4087 hr = IWinHttpRequest_SetTimeouts( req, 10000, 10000, 10000, 10000 );
4088 ok( hr == S_OK, "got %08x\n", hr );
4090 hr = IWinHttpRequest_SetCredentials( req, NULL, NULL, 0xdeadbeef );
4091 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4093 username = SysAllocString( L"username" );
4094 hr = IWinHttpRequest_SetCredentials( req, username, NULL, 0xdeadbeef );
4095 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4097 password = SysAllocString( L"password" );
4098 hr = IWinHttpRequest_SetCredentials( req, NULL, password, 0xdeadbeef );
4099 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4101 hr = IWinHttpRequest_SetCredentials( req, username, password, 0xdeadbeef );
4102 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4104 hr = IWinHttpRequest_SetCredentials( req, NULL, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
4105 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4107 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
4108 ok( hr == S_OK, "got %08x\n", hr );
4110 V_VT( &proxy_server ) = VT_BSTR;
4111 V_BSTR( &proxy_server ) = SysAllocString( L"proxyserver" );
4112 V_VT( &bypass_list ) = VT_BSTR;
4113 V_BSTR( &bypass_list ) = SysAllocString( L"bypasslist" );
4114 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
4115 ok( hr == S_OK, "got %08x\n", hr );
4117 hr = IWinHttpRequest_SetProxy( req, 0xdeadbeef, proxy_server, bypass_list );
4118 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4120 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
4121 ok( hr == S_OK, "got %08x\n", hr );
4123 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
4124 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
4126 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
4127 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
4129 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
4130 ok( hr == S_OK, "got %08x\n", hr );
4132 hr = IWinHttpRequest_SetRequestHeader( req, date, NULL );
4133 ok( hr == S_OK, "got %08x\n", hr );
4135 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
4136 ok( hr == S_OK, "got %08x\n", hr );
4138 hr = IWinHttpRequest_Send( req, empty );
4139 ok( hr == S_OK, "got %08x\n", hr );
4141 hr = IWinHttpRequest_Send( req, empty );
4142 ok( hr == S_OK, "got %08x\n", hr );
4144 hr = IWinHttpRequest_get_ResponseText( req, NULL );
4145 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4147 hr = IWinHttpRequest_get_ResponseText( req, &response );
4148 ok( hr == S_OK, "got %08x\n", hr );
4149 ok( !memcmp(response, data_start, sizeof(data_start)), "got %s\n", wine_dbgstr_wn(response, 32) );
4150 SysFreeString( response );
4152 hr = IWinHttpRequest_get_Status( req, NULL );
4153 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4155 status = 0;
4156 hr = IWinHttpRequest_get_Status( req, &status );
4157 ok( hr == S_OK, "got %08x\n", hr );
4158 trace("Status=%d\n", status);
4160 hr = IWinHttpRequest_get_StatusText( req, NULL );
4161 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4163 hr = IWinHttpRequest_get_StatusText( req, &status_text );
4164 ok( hr == S_OK, "got %08x\n", hr );
4165 trace("StatusText=%s\n", wine_dbgstr_w(status_text));
4166 SysFreeString( status_text );
4168 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
4169 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4171 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
4172 ok( hr == S_OK, "got %08x\n", hr );
4174 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
4175 ok( hr == S_OK, "got %08x\n", hr );
4177 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
4178 ok( hr == S_OK, "got %08x\n", hr );
4180 hr = IWinHttpRequest_GetAllResponseHeaders( req, NULL );
4181 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4183 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
4184 ok( hr == S_OK, "got %08x\n", hr );
4185 SysFreeString( headers );
4187 hr = IWinHttpRequest_GetResponseHeader( req, NULL, NULL );
4188 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4190 hr = IWinHttpRequest_GetResponseHeader( req, connection, NULL );
4191 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4193 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
4194 ok( hr == S_OK, "got %08x\n", hr );
4195 SysFreeString( value );
4197 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
4198 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND ), "got %08x\n", hr );
4200 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
4201 ok( hr == S_OK, "got %08x\n", hr );
4203 VariantInit( &timeout );
4204 V_VT( &timeout ) = VT_I4;
4205 V_I4( &timeout ) = 10;
4206 hr = IWinHttpRequest_WaitForResponse( req, timeout, &succeeded );
4207 ok( hr == S_OK, "got %08x\n", hr );
4209 hr = IWinHttpRequest_get_Status( req, &status );
4210 ok( hr == S_OK, "got %08x\n", hr );
4212 hr = IWinHttpRequest_get_StatusText( req, &status_text );
4213 ok( hr == S_OK, "got %08x\n", hr );
4214 SysFreeString( status_text );
4216 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
4217 ok( hr == S_OK, "got %08x\n", hr );
4219 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
4220 ok( hr == S_OK, "got %08x\n", hr );
4222 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
4223 ok( hr == S_OK, "got %08x\n", hr );
4225 hr = IWinHttpRequest_Send( req, empty );
4226 ok( hr == S_OK, "got %08x\n", hr );
4228 hr = IWinHttpRequest_get_ResponseText( req, NULL );
4229 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4231 hr = IWinHttpRequest_get_ResponseText( req, &response );
4232 ok( hr == S_OK, "got %08x\n", hr );
4233 SysFreeString( response );
4235 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
4236 ok( hr == E_INVALIDARG, "got %08x\n", hr );
4238 VariantInit( &body );
4239 V_VT( &body ) = VT_ERROR;
4240 hr = IWinHttpRequest_get_ResponseBody( req, &body );
4241 ok( hr == S_OK, "got %08x\n", hr );
4242 ok( V_VT( &body ) == (VT_ARRAY|VT_UI1), "got %08x\n", V_VT( &body ) );
4244 hr = VariantClear( &body );
4245 ok( hr == S_OK, "got %08x\n", hr );
4247 VariantInit( &body );
4248 V_VT( &body ) = VT_ERROR;
4249 hr = IWinHttpRequest_get_ResponseStream( req, &body );
4250 ok( hr == S_OK, "got %08x\n", hr );
4251 ok( V_VT( &body ) == VT_UNKNOWN, "got %08x\n", V_VT( &body ) );
4253 hr = IUnknown_QueryInterface( V_UNKNOWN( &body ), &IID_IStream, (void **)&stream );
4254 ok( hr == S_OK, "got %08x\n", hr );
4255 ok( V_UNKNOWN( &body ) == (IUnknown *)stream, "got different interface pointer\n" );
4257 buf[0] = 0;
4258 count = 0xdeadbeef;
4259 hr = IStream_Read( stream, buf, 128, &count );
4260 ok( hr == S_OK, "got %08x\n", hr );
4261 ok( count != 0xdeadbeef, "count not set\n" );
4262 ok( buf[0], "no data\n" );
4264 VariantInit( &body2 );
4265 V_VT( &body2 ) = VT_ERROR;
4266 hr = IWinHttpRequest_get_ResponseStream( req, &body2 );
4267 ok( hr == S_OK, "got %08x\n", hr );
4268 ok( V_VT( &body2 ) == VT_UNKNOWN, "got %08x\n", V_VT( &body2 ) );
4269 ok( V_UNKNOWN( &body ) != V_UNKNOWN( &body2 ), "got same interface pointer\n" );
4271 hr = IUnknown_QueryInterface( V_UNKNOWN( &body2 ), &IID_IStream, (void **)&stream2 );
4272 ok( hr == S_OK, "got %08x\n", hr );
4273 ok( V_UNKNOWN( &body2 ) == (IUnknown *)stream2, "got different interface pointer\n" );
4274 IStream_Release( stream2 );
4276 hr = VariantClear( &body );
4277 ok( hr == S_OK, "got %08x\n", hr );
4279 hr = VariantClear( &body2 );
4280 ok( hr == S_OK, "got %08x\n", hr );
4282 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
4283 ok( hr == S_OK, "got %08x\n", hr );
4285 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
4286 ok( hr == S_OK, "got %08x\n", hr );
4288 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
4289 ok( hr == S_OK, "got %08x\n", hr );
4290 SysFreeString( headers );
4292 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
4293 ok( hr == S_OK, "got %08x\n", hr );
4294 SysFreeString( value );
4296 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
4297 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND ), "got %08x\n", hr );
4299 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
4300 ok( hr == S_OK, "got %08x\n", hr );
4302 hr = IWinHttpRequest_Send( req, empty );
4303 ok( hr == S_OK, "got %08x\n", hr );
4305 hr = IWinHttpRequest_Abort( req );
4306 ok( hr == S_OK, "got %08x\n", hr );
4308 hr = IWinHttpRequest_Abort( req );
4309 ok( hr == S_OK, "got %08x\n", hr );
4311 IWinHttpRequest_Release( req );
4313 pos.QuadPart = 0;
4314 hr = IStream_Seek( stream, pos, STREAM_SEEK_SET, NULL );
4315 ok( hr == S_OK, "got %08x\n", hr );
4317 buf[0] = 0;
4318 count = 0xdeadbeef;
4319 hr = IStream_Read( stream, buf, 128, &count );
4320 ok( hr == S_OK, "got %08x\n", hr );
4321 ok( count != 0xdeadbeef, "count not set\n" );
4322 ok( buf[0], "no data\n" );
4323 IStream_Release( stream );
4325 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
4326 ok( hr == S_OK, "got %08x\n", hr );
4328 V_VT( &async ) = VT_I4;
4329 V_I4( &async ) = 1;
4330 hr = IWinHttpRequest_Open( req, method, url, async );
4331 ok( hr == S_OK, "got %08x\n", hr );
4333 hr = IWinHttpRequest_Send( req, empty );
4334 ok( hr == S_OK, "got %08x\n", hr );
4336 hr = IWinHttpRequest_WaitForResponse( req, timeout, &succeeded );
4337 ok( hr == S_OK, "got %08x\n", hr );
4339 IWinHttpRequest_Release( req );
4341 SysFreeString( method );
4342 SysFreeString( url );
4343 SysFreeString( username );
4344 SysFreeString( password );
4345 SysFreeString( connection );
4346 SysFreeString( date );
4347 SysFreeString( today );
4348 VariantClear( &proxy_server );
4349 VariantClear( &bypass_list );
4351 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
4352 ok( hr == S_OK, "got %08x\n", hr );
4354 url = SysAllocString( L"https://test.winehq.org:443" );
4355 method = SysAllocString( L"POST" );
4356 V_VT( &async ) = VT_BOOL;
4357 V_BOOL( &async ) = VARIANT_FALSE;
4358 hr = IWinHttpRequest_Open( req, method, url, async );
4359 ok( hr == S_OK, "got %08x\n", hr );
4360 SysFreeString( method );
4361 SysFreeString( url );
4363 hr = IWinHttpRequest_Send( req, empty );
4364 ok( hr == S_OK || hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_INVALID_SERVER_RESPONSE ) ||
4365 hr == SEC_E_ILLEGAL_MESSAGE /* winxp */, "got %08x\n", hr );
4366 if (hr != S_OK) goto done;
4368 hr = IWinHttpRequest_get_ResponseText( req, &response );
4369 ok( hr == S_OK, "got %08x\n", hr );
4370 ok( !memcmp(response, data_start, sizeof(data_start)), "got %s\n", wine_dbgstr_wn(response, 32) );
4371 SysFreeString( response );
4373 IWinHttpRequest_Release( req );
4375 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
4376 ok( hr == S_OK, "got %08x\n", hr );
4378 sprintf( buf, "http://localhost:%d/auth", port );
4379 MultiByteToWideChar( CP_ACP, 0, buf, -1, bufW, ARRAY_SIZE( bufW ));
4380 url = SysAllocString( bufW );
4381 method = SysAllocString( L"POST" );
4382 V_VT( &async ) = VT_BOOL;
4383 V_BOOL( &async ) = VARIANT_FALSE;
4384 hr = IWinHttpRequest_Open( req, method, url, async );
4385 ok( hr == S_OK, "got %08x\n", hr );
4386 SysFreeString( method );
4387 SysFreeString( url );
4389 hr = IWinHttpRequest_get_Status( req, &status );
4390 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
4392 V_VT( &data ) = VT_BSTR;
4393 V_BSTR( &data ) = SysAllocString( L"testdata\x80" );
4394 hr = IWinHttpRequest_Send( req, data );
4395 ok( hr == S_OK, "got %08x\n", hr );
4396 SysFreeString( V_BSTR( &data ) );
4398 hr = IWinHttpRequest_get_ResponseText( req, &response );
4399 ok( hr == S_OK, "got %08x\n", hr );
4400 ok( !memcmp( response, L"Unauthorized", sizeof(L"Unauthorized") ), "got %s\n", wine_dbgstr_w(response) );
4401 SysFreeString( response );
4403 status = 0xdeadbeef;
4404 hr = IWinHttpRequest_get_Status( req, &status );
4405 ok( hr == S_OK, "got %08x\n", hr );
4406 ok( status == HTTP_STATUS_DENIED, "got %d\n", status );
4408 done:
4409 IWinHttpRequest_Release( req );
4410 CoUninitialize();
4413 static void request_get_property(IWinHttpRequest *request, int property, VARIANT *ret)
4415 DISPPARAMS params;
4416 VARIANT arg;
4417 HRESULT hr;
4419 memset(&params, 0, sizeof(params));
4420 params.cNamedArgs = 0;
4421 params.rgdispidNamedArgs = NULL;
4422 params.cArgs = 1;
4423 params.rgvarg = &arg;
4424 VariantInit(&arg);
4425 V_VT(&arg) = VT_I4;
4426 V_I4(&arg) = property;
4427 VariantInit(ret);
4428 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
4429 DISPATCH_PROPERTYGET, &params, ret, NULL, NULL);
4430 ok(hr == S_OK, "error %#x\n", hr);
4433 static void test_IWinHttpRequest_Invoke(void)
4435 WCHAR openW[] = {'O','p','e','n',0};
4436 WCHAR optionW[] = {'O','p','t','i','o','n',0};
4437 OLECHAR *open = openW, *option = optionW;
4438 BSTR utf8;
4439 CLSID clsid;
4440 IWinHttpRequest *request;
4441 IDispatch *dispatch;
4442 DISPID id;
4443 DISPPARAMS params;
4444 VARIANT arg[3], ret;
4445 UINT err;
4446 BOOL bret;
4447 HRESULT hr;
4449 CoInitialize(NULL);
4451 hr = CLSIDFromProgID(L"WinHttp.WinHttpRequest.5.1", &clsid);
4452 ok(hr == S_OK, "CLSIDFromProgID error %#x\n", hr);
4453 bret = IsEqualIID(&clsid, &CLSID_WinHttpRequest);
4454 ok(bret || broken(!bret) /* win2003 */, "not expected %s\n", wine_dbgstr_guid(&clsid));
4456 hr = CoCreateInstance(&CLSID_WinHttpRequest, 0, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&request);
4457 ok(hr == S_OK, "error %#x\n", hr);
4459 hr = IWinHttpRequest_QueryInterface(request, &IID_IDispatch, (void **)&dispatch);
4460 ok(hr == S_OK, "error %#x\n", hr);
4461 IDispatch_Release(dispatch);
4463 hr = IWinHttpRequest_GetIDsOfNames(request, &IID_NULL, &open, 1, 0x0409, &id);
4464 ok(hr == S_OK, "error %#x\n", hr);
4465 ok(id == DISPID_HTTPREQUEST_OPEN, "expected DISPID_HTTPREQUEST_OPEN, got %u\n", id);
4467 hr = IWinHttpRequest_GetIDsOfNames(request, &IID_NULL, &option, 1, 0x0409, &id);
4468 ok(hr == S_OK, "error %#x\n", hr);
4469 ok(id == DISPID_HTTPREQUEST_OPTION, "expected DISPID_HTTPREQUEST_OPTION, got %u\n", id);
4471 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4472 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4473 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4475 memset(&params, 0, sizeof(params));
4476 params.cArgs = 2;
4477 params.cNamedArgs = 0;
4478 params.rgvarg = arg;
4479 V_VT(&arg[0]) = VT_I4;
4480 V_I4(&arg[0]) = 1252;
4481 V_VT(&arg[1]) = VT_R8;
4482 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
4483 VariantInit(&ret);
4484 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
4485 DISPATCH_METHOD, &params, NULL, NULL, &err);
4486 ok(hr == S_OK, "error %#x\n", hr);
4488 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4489 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4490 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4492 memset(&params, 0, sizeof(params));
4493 params.cArgs = 2;
4494 params.cNamedArgs = 0;
4495 params.rgvarg = arg;
4496 V_VT(&arg[0]) = VT_I4;
4497 V_I4(&arg[0]) = 1252;
4498 V_VT(&arg[1]) = VT_R8;
4499 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
4500 VariantInit(&ret);
4501 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
4502 DISPATCH_METHOD | DISPATCH_PROPERTYPUT, &params, NULL, NULL, &err);
4503 ok(hr == S_OK, "error %#x\n", hr);
4505 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4506 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4507 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4509 memset(&params, 0, sizeof(params));
4510 params.cArgs = 2;
4511 params.cNamedArgs = 0;
4512 params.rgvarg = arg;
4513 V_VT(&arg[0]) = VT_I4;
4514 V_I4(&arg[0]) = 1252;
4515 V_VT(&arg[1]) = VT_R8;
4516 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
4517 VariantInit(&ret);
4518 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
4519 DISPATCH_PROPERTYPUT, &params, NULL, NULL, &err);
4520 ok(hr == S_OK, "error %#x\n", hr);
4522 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4523 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4524 ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
4526 memset(&params, 0, sizeof(params));
4527 params.cArgs = 2;
4528 params.cNamedArgs = 0;
4529 params.rgvarg = arg;
4530 V_VT(&arg[0]) = VT_BSTR;
4531 utf8 = SysAllocString(L"UTF-8");
4532 V_BSTR(&arg[0]) = utf8;
4533 V_VT(&arg[1]) = VT_R8;
4534 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
4535 hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_METHOD, &params, NULL, NULL, &err);
4536 ok(hr == S_OK, "error %#x\n", hr);
4538 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4539 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4540 ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
4542 VariantInit(&ret);
4543 hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_METHOD, &params, &ret, NULL, &err);
4544 ok(hr == S_OK, "error %#x\n", hr);
4546 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4547 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4548 ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
4550 VariantInit(&ret);
4551 hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
4552 ok(hr == S_OK, "error %#x\n", hr);
4554 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4555 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4556 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4558 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, NULL, NULL, NULL);
4559 ok(hr == S_OK, "error %#x\n", hr);
4561 hr = IWinHttpRequest_Invoke(request, 255, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, NULL, NULL, NULL);
4562 ok(hr == DISP_E_MEMBERNOTFOUND, "error %#x\n", hr);
4564 VariantInit(&ret);
4565 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
4566 ok(hr == DISP_E_UNKNOWNINTERFACE, "error %#x\n", hr);
4568 VariantInit(&ret);
4569 if (0) /* crashes */
4570 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, &ret, NULL, &err);
4572 params.cArgs = 1;
4573 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
4574 ok(hr == DISP_E_TYPEMISMATCH, "error %#x\n", hr);
4576 VariantInit(&arg[2]);
4577 params.cArgs = 3;
4578 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
4579 todo_wine
4580 ok(hr == S_OK, "error %#x\n", hr);
4582 VariantInit(&arg[0]);
4583 VariantInit(&arg[1]);
4584 VariantInit(&arg[2]);
4586 params.cArgs = 1;
4587 V_VT(&arg[0]) = VT_I4;
4588 V_I4(&arg[0]) = WinHttpRequestOption_URLCodePage;
4589 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4590 ok(hr == S_OK, "error %#x\n", hr);
4592 V_VT(&ret) = 0xdead;
4593 V_I4(&ret) = 0xbeef;
4594 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &params, &ret, NULL, NULL);
4595 ok(hr == S_OK, "error %#x\n", hr);
4596 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4597 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4599 V_VT(&ret) = 0xdead;
4600 V_I4(&ret) = 0xbeef;
4601 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD, &params, &ret, NULL, NULL);
4602 ok(hr == S_OK, "error %#x\n", hr);
4603 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4604 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4606 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4607 ok(hr == S_OK, "error %#x\n", hr);
4609 V_VT(&ret) = 0xdead;
4610 V_I4(&ret) = 0xbeef;
4611 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, 0, &params, &ret, NULL, NULL);
4612 ok(hr == S_OK, "error %#x\n", hr);
4613 ok(V_VT(&ret) == VT_EMPTY, "expected VT_EMPTY, got %d\n", V_VT(&ret));
4614 ok(V_I4(&ret) == 0xbeef || V_I4(&ret) == 0 /* Win8 */, "expected 0xdead, got %d\n", V_I4(&ret));
4616 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, 0, &params, NULL, NULL, NULL);
4617 ok(hr == S_OK, "error %#x\n", hr);
4619 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_IUnknown, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4620 ok(hr == DISP_E_UNKNOWNINTERFACE, "error %#x\n", hr);
4622 params.cArgs = 2;
4623 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4624 todo_wine
4625 ok(hr == S_OK, "error %#x\n", hr);
4627 params.cArgs = 0;
4628 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4629 ok(hr == DISP_E_PARAMNOTFOUND, "error %#x\n", hr);
4631 SysFreeString(utf8);
4633 params.cArgs = 1;
4634 V_VT(&arg[0]) = VT_I4;
4635 V_I4(&arg[0]) = AutoLogonPolicy_Never;
4636 VariantInit(&ret);
4637 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_SETAUTOLOGONPOLICY, &IID_NULL, 0,
4638 DISPATCH_METHOD, &params, &ret, NULL, NULL);
4639 ok(hr == S_OK, "error %#x\n", hr);
4641 IWinHttpRequest_Release(request);
4643 CoUninitialize();
4646 static void test_WinHttpDetectAutoProxyConfigUrl(void)
4648 BOOL ret;
4649 WCHAR *url;
4650 DWORD error;
4652 SetLastError(0xdeadbeef);
4653 ret = WinHttpDetectAutoProxyConfigUrl( 0, NULL );
4654 error = GetLastError();
4655 ok( !ret, "expected failure\n" );
4656 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4658 url = NULL;
4659 SetLastError(0xdeadbeef);
4660 ret = WinHttpDetectAutoProxyConfigUrl( 0, &url );
4661 error = GetLastError();
4662 ok( !ret, "expected failure\n" );
4663 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4665 SetLastError(0xdeadbeef);
4666 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, NULL );
4667 error = GetLastError();
4668 ok( !ret, "expected failure\n" );
4669 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4671 url = (WCHAR *)0xdeadbeef;
4672 SetLastError(0xdeadbeef);
4673 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, &url );
4674 error = GetLastError();
4675 if (!ret)
4677 ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED, "got %u\n", error );
4678 ok( !url || broken(url == (WCHAR *)0xdeadbeef), "got %p\n", url );
4680 else
4682 trace("%s\n", wine_dbgstr_w(url));
4683 GlobalFree( url );
4686 url = (WCHAR *)0xdeadbeef;
4687 SetLastError(0xdeadbeef);
4688 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DHCP, &url );
4689 error = GetLastError();
4690 if (!ret)
4692 ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED, "got %u\n", error );
4693 ok( !url || broken(url == (WCHAR *)0xdeadbeef), "got %p\n", url );
4695 else
4697 ok( error == ERROR_SUCCESS, "got %u\n", error );
4698 trace("%s\n", wine_dbgstr_w(url));
4699 GlobalFree( url );
4703 static void test_WinHttpGetIEProxyConfigForCurrentUser(void)
4705 BOOL ret;
4706 DWORD error;
4707 WINHTTP_CURRENT_USER_IE_PROXY_CONFIG cfg;
4709 memset( &cfg, 0, sizeof(cfg) );
4711 SetLastError(0xdeadbeef);
4712 ret = WinHttpGetIEProxyConfigForCurrentUser( NULL );
4713 error = GetLastError();
4714 ok( !ret, "expected failure\n" );
4715 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4717 SetLastError(0xdeadbeef);
4718 ret = WinHttpGetIEProxyConfigForCurrentUser( &cfg );
4719 error = GetLastError();
4720 ok( ret, "expected success\n" );
4721 ok( error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* < win7 */, "got %u\n", error );
4723 trace("IEProxy.AutoDetect=%d\n", cfg.fAutoDetect);
4724 trace("IEProxy.AutoConfigUrl=%s\n", wine_dbgstr_w(cfg.lpszAutoConfigUrl));
4725 trace("IEProxy.Proxy=%s\n", wine_dbgstr_w(cfg.lpszProxy));
4726 trace("IEProxy.ProxyBypass=%s\n", wine_dbgstr_w(cfg.lpszProxyBypass));
4727 GlobalFree( cfg.lpszAutoConfigUrl );
4728 GlobalFree( cfg.lpszProxy );
4729 GlobalFree( cfg.lpszProxyBypass );
4732 static void test_WinHttpGetProxyForUrl(void)
4734 BOOL ret;
4735 DWORD error;
4736 HINTERNET session;
4737 WINHTTP_AUTOPROXY_OPTIONS options;
4738 WINHTTP_PROXY_INFO info;
4740 memset( &options, 0, sizeof(options) );
4742 SetLastError(0xdeadbeef);
4743 ret = WinHttpGetProxyForUrl( NULL, NULL, NULL, NULL );
4744 error = GetLastError();
4745 ok( !ret, "expected failure\n" );
4746 ok( error == ERROR_INVALID_HANDLE, "got %u\n", error );
4748 session = WinHttpOpen( L"winetest", 0, NULL, NULL, 0 );
4749 ok( session != NULL, "failed to open session %u\n", GetLastError() );
4751 SetLastError(0xdeadbeef);
4752 ret = WinHttpGetProxyForUrl( session, NULL, NULL, NULL );
4753 error = GetLastError();
4754 ok( !ret, "expected failure\n" );
4755 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4757 SetLastError(0xdeadbeef);
4758 ret = WinHttpGetProxyForUrl( session, L"", NULL, NULL );
4759 error = GetLastError();
4760 ok( !ret, "expected failure\n" );
4761 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4763 SetLastError(0xdeadbeef);
4764 ret = WinHttpGetProxyForUrl( session, L"http://winehq.org", NULL, NULL );
4765 error = GetLastError();
4766 ok( !ret, "expected failure\n" );
4767 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4769 SetLastError(0xdeadbeef);
4770 ret = WinHttpGetProxyForUrl( session, L"http://winehq.org", &options, &info );
4771 error = GetLastError();
4772 ok( !ret, "expected failure\n" );
4773 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4775 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
4776 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
4778 SetLastError(0xdeadbeef);
4779 ret = WinHttpGetProxyForUrl( session, L"http://winehq.org", &options, NULL );
4780 error = GetLastError();
4781 ok( !ret, "expected failure\n" );
4782 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4784 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
4785 options.dwAutoDetectFlags = 0;
4787 SetLastError(0xdeadbeef);
4788 ret = WinHttpGetProxyForUrl( session, L"http://winehq.org", &options, &info );
4789 error = GetLastError();
4790 ok( !ret, "expected failure\n" );
4791 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4793 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT | WINHTTP_AUTOPROXY_CONFIG_URL;
4794 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
4796 SetLastError(0xdeadbeef);
4797 ret = WinHttpGetProxyForUrl( session, L"http://winehq.org", &options, &info );
4798 error = GetLastError();
4799 ok( !ret, "expected failure\n" );
4800 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4802 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
4803 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
4805 memset( &info, 0, sizeof(info) );
4806 SetLastError(0xdeadbeef);
4807 ret = WinHttpGetProxyForUrl( session, L"http://winehq.org", &options, &info );
4808 error = GetLastError();
4809 if (ret)
4811 ok( error == ERROR_SUCCESS, "got %u\n", error );
4812 trace("Proxy.AccessType=%u\n", info.dwAccessType);
4813 trace("Proxy.Proxy=%s\n", wine_dbgstr_w(info.lpszProxy));
4814 trace("Proxy.ProxyBypass=%s\n", wine_dbgstr_w(info.lpszProxyBypass));
4815 GlobalFree( info.lpszProxy );
4816 GlobalFree( info.lpszProxyBypass );
4819 options.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
4820 options.dwAutoDetectFlags = 0;
4821 options.lpszAutoConfigUrl = L"http://wpad/wpad.dat";
4823 memset( &info, 0, sizeof(info) );
4824 ret = WinHttpGetProxyForUrl( session, L"http://winehq.org", &options, &info );
4825 if (ret)
4827 trace("Proxy.AccessType=%u\n", info.dwAccessType);
4828 trace("Proxy.Proxy=%s\n", wine_dbgstr_w(info.lpszProxy));
4829 trace("Proxy.ProxyBypass=%s\n", wine_dbgstr_w(info.lpszProxyBypass));
4830 GlobalFree( info.lpszProxy );
4831 GlobalFree( info.lpszProxyBypass );
4833 WinHttpCloseHandle( session );
4836 static void test_chunked_read(void)
4838 WCHAR header[32];
4839 DWORD len, err;
4840 HINTERNET ses, con = NULL, req = NULL;
4841 BOOL ret;
4843 trace( "starting chunked read test\n" );
4845 ses = WinHttpOpen( L"winetest", 0, NULL, NULL, 0 );
4846 ok( ses != NULL, "WinHttpOpen failed with error %u\n", GetLastError() );
4847 if (!ses) goto done;
4849 con = WinHttpConnect( ses, L"test.winehq.org", 0, 0 );
4850 ok( con != NULL, "WinHttpConnect failed with error %u\n", GetLastError() );
4851 if (!con) goto done;
4853 req = WinHttpOpenRequest( con, NULL, L"/tests/chunked", NULL, NULL, NULL, 0 );
4854 ok( req != NULL, "WinHttpOpenRequest failed with error %u\n", GetLastError() );
4855 if (!req) goto done;
4857 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
4858 err = GetLastError();
4859 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
4861 skip("connection failed, skipping\n");
4862 goto done;
4864 ok( ret, "WinHttpSendRequest failed with error %u\n", GetLastError() );
4865 if (!ret) goto done;
4867 ret = WinHttpReceiveResponse( req, NULL );
4868 ok( ret, "WinHttpReceiveResponse failed with error %u\n", GetLastError() );
4869 if (!ret) goto done;
4871 header[0] = 0;
4872 len = sizeof(header);
4873 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, header, &len, 0 );
4874 ok( ret, "failed to get TRANSFER_ENCODING header (error %u)\n", GetLastError() );
4875 ok( !lstrcmpW( header, L"chunked" ), "wrong transfer encoding %s\n", wine_dbgstr_w(header) );
4876 trace( "transfer encoding: %s\n", wine_dbgstr_w(header) );
4878 header[0] = 0;
4879 len = sizeof(header);
4880 SetLastError( 0xdeadbeef );
4881 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_CONTENT_LENGTH, NULL, &header, &len, 0 );
4882 ok( !ret, "unexpected CONTENT_LENGTH header %s\n", wine_dbgstr_w(header) );
4883 ok( GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND, "wrong error %u\n", GetLastError() );
4885 trace( "entering query loop\n" );
4886 for (;;)
4888 len = 0xdeadbeef;
4889 ret = WinHttpQueryDataAvailable( req, &len );
4890 ok( ret, "WinHttpQueryDataAvailable failed with error %u\n", GetLastError() );
4891 if (ret) ok( len != 0xdeadbeef, "WinHttpQueryDataAvailable return wrong length\n" );
4892 trace( "got %u available\n", len );
4893 if (len)
4895 DWORD bytes_read;
4896 char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 );
4898 ret = WinHttpReadData( req, buf, len, &bytes_read );
4899 ok(ret, "WinHttpReadData failed: %u.\n", GetLastError());
4901 buf[bytes_read] = 0;
4902 trace( "WinHttpReadData -> %d %u\n", ret, bytes_read );
4903 ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len );
4904 ok( buf[bytes_read - 1] == '\n', "received partial line '%s'\n", buf );
4906 HeapFree( GetProcessHeap(), 0, buf );
4907 if (!bytes_read) break;
4909 if (!len) break;
4911 trace( "done\n" );
4913 done:
4914 if (req) WinHttpCloseHandle( req );
4915 if (con) WinHttpCloseHandle( con );
4916 if (ses) WinHttpCloseHandle( ses );
4919 START_TEST (winhttp)
4921 struct server_info si;
4922 HANDLE thread;
4923 DWORD ret;
4924 HMODULE mod = GetModuleHandleA("winhttp.dll");
4926 pWinHttpWebSocketCompleteUpgrade = (void *)GetProcAddress(mod, "WinHttpWebSocketCompleteUpgrade");
4928 test_WinHttpOpenRequest();
4929 test_WinHttpSendRequest();
4930 test_WinHttpTimeFromSystemTime();
4931 test_WinHttpTimeToSystemTime();
4932 test_WinHttpAddHeaders();
4933 test_secure_connection();
4934 test_request_parameter_defaults();
4935 test_WinHttpQueryOption();
4936 test_set_default_proxy_config();
4937 test_empty_headers_param();
4938 test_timeouts();
4939 test_resolve_timeout();
4940 test_credentials();
4941 test_IWinHttpRequest_Invoke();
4942 test_WinHttpDetectAutoProxyConfigUrl();
4943 test_WinHttpGetIEProxyConfigForCurrentUser();
4944 test_WinHttpGetProxyForUrl();
4945 test_chunked_read();
4947 si.event = CreateEventW(NULL, 0, 0, NULL);
4948 si.port = 7532;
4950 thread = CreateThread(NULL, 0, server_thread, &si, 0, NULL);
4951 ok(thread != NULL, "failed to create thread %u\n", GetLastError());
4953 ret = WaitForSingleObject(si.event, 10000);
4954 ok(ret == WAIT_OBJECT_0, "failed to start winhttp test server %u\n", GetLastError());
4955 if (ret != WAIT_OBJECT_0)
4957 CloseHandle(thread);
4958 return;
4961 test_IWinHttpRequest(si.port);
4962 test_connection_info(si.port);
4963 test_basic_request(si.port, NULL, L"/basic");
4964 test_no_headers(si.port);
4965 test_no_content(si.port);
4966 test_head_request(si.port);
4967 test_not_modified(si.port);
4968 test_basic_authentication(si.port);
4969 test_multi_authentication(si.port);
4970 test_large_data_authentication(si.port);
4971 test_bad_header(si.port);
4972 test_multiple_reads(si.port);
4973 test_cookies(si.port);
4974 test_request_path_escapes(si.port);
4975 test_passport_auth(si.port);
4976 test_websocket(si.port);
4978 /* send the basic request again to shutdown the server thread */
4979 test_basic_request(si.port, NULL, L"/quit");
4981 WaitForSingleObject(thread, 3000);
4982 CloseHandle(thread);