winhttp: Implement WINHTTP_OPTION_SECURE_PROTOCOLS.
[wine.git] / dlls / winhttp / tests / winhttp.c
blob2babe98c20f9f4de26169de272d40a0ff8e00d19
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"
37 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
39 static const WCHAR test_useragent[] =
40 {'W','i','n','e',' ','R','e','g','r','e','s','s','i','o','n',' ','T','e','s','t',0};
41 static const WCHAR test_winehq[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
42 static const WCHAR test_winehq_https[] = {'h','t','t','p','s',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',':','4','4','3',0};
43 static const WCHAR localhostW[] = {'l','o','c','a','l','h','o','s','t',0};
45 static BOOL proxy_active(void)
47 WINHTTP_PROXY_INFO proxy_info;
48 BOOL active = FALSE;
50 SetLastError(0xdeadbeef);
51 if (WinHttpGetDefaultProxyConfiguration(&proxy_info))
53 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
54 "got %u\n", GetLastError());
55 active = (proxy_info.lpszProxy != NULL);
56 if (active)
57 GlobalFree(proxy_info.lpszProxy);
58 if (proxy_info.lpszProxyBypass != NULL)
59 GlobalFree(proxy_info.lpszProxyBypass);
61 else
62 active = FALSE;
64 return active;
67 static void test_QueryOption(void)
69 BOOL ret;
70 HINTERNET session, request, connection;
71 DWORD feature, size;
73 SetLastError(0xdeadbeef);
74 session = WinHttpOpen(test_useragent, 0, 0, 0, 0);
75 ok(session != NULL, "WinHttpOpen failed to open session, error %u\n", GetLastError());
77 SetLastError(0xdeadbeef);
78 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, NULL);
79 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
80 ok(GetLastError() == ERROR_INVALID_PARAMETER,
81 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
83 size = 0xdeadbeef;
84 SetLastError(0xdeadbeef);
85 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, &size);
86 ok(!ret, "should fail to query option\n");
87 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
88 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
89 ok(size == 4, "expected 4, got %u\n", size);
91 feature = 0xdeadbeef;
92 size = sizeof(feature) - 1;
93 SetLastError(0xdeadbeef);
94 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
95 ok(!ret, "should fail to query option\n");
96 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
97 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
98 ok(size == 4, "expected 4, got %u\n", size);
100 feature = 0xdeadbeef;
101 size = sizeof(feature) + 1;
102 SetLastError(0xdeadbeef);
103 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
104 ok(ret, "failed to query option %u\n", GetLastError());
105 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
106 "got %u\n", GetLastError());
107 ok(size == sizeof(feature), "WinHttpQueryOption should set the size: %u\n", size);
108 ok(feature == WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP,
109 "expected WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP, got %#x\n", feature);
111 SetLastError(0xdeadbeef);
112 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, sizeof(feature));
113 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
114 ok(GetLastError() == ERROR_INVALID_PARAMETER,
115 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
117 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
118 SetLastError(0xdeadbeef);
119 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature) - 1);
120 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
121 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
122 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
124 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
125 SetLastError(0xdeadbeef);
126 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature) + 1);
127 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
128 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
129 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
131 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
132 SetLastError(0xdeadbeef);
133 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature));
134 ok(ret, "failed to set redirect policy %u\n", GetLastError());
136 feature = 0xdeadbeef;
137 size = sizeof(feature);
138 SetLastError(0xdeadbeef);
139 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
140 ok(ret, "failed to query option %u\n", GetLastError());
141 ok(feature == WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS,
142 "expected WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS, got %#x\n", feature);
144 feature = WINHTTP_DISABLE_COOKIES;
145 SetLastError(0xdeadbeef);
146 ret = WinHttpSetOption(session, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
147 ok(!ret, "should fail to set disable feature for a session\n");
148 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
149 "expected ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, got %u\n", GetLastError());
151 SetLastError(0xdeadbeef);
152 connection = WinHttpConnect(session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
153 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u\n", GetLastError());
155 feature = WINHTTP_DISABLE_COOKIES;
156 SetLastError(0xdeadbeef);
157 ret = WinHttpSetOption(connection, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
158 ok(!ret, "should fail to set disable feature for a connection\n");
159 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
160 "expected ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, got %u\n", GetLastError());
162 SetLastError(0xdeadbeef);
163 request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
164 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
165 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
167 skip("Network unreachable, skipping the test\n");
168 goto done;
171 feature = 0xdeadbeef;
172 size = sizeof(feature);
173 SetLastError(0xdeadbeef);
174 ret = WinHttpQueryOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, &size);
175 ok(!ret, "should fail to query disable feature for a request\n");
176 ok(GetLastError() == ERROR_INVALID_PARAMETER,
177 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
179 feature = 0;
180 size = sizeof(feature);
181 SetLastError(0xdeadbeef);
182 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
183 ok(ret, "failed to set feature %u\n", GetLastError());
185 feature = 0xffffffff;
186 size = sizeof(feature);
187 SetLastError(0xdeadbeef);
188 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
189 ok(ret, "failed to set feature %u\n", GetLastError());
191 feature = WINHTTP_DISABLE_COOKIES;
192 size = sizeof(feature);
193 SetLastError(0xdeadbeef);
194 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
195 ok(ret, "failed to set feature %u\n", GetLastError());
197 size = 0;
198 SetLastError(0xdeadbeef);
199 ret = WinHttpQueryOption(request, WINHTTP_OPTION_DISABLE_FEATURE, NULL, &size);
200 ok(!ret, "should fail to query disable feature for a request\n");
201 ok(GetLastError() == ERROR_INVALID_PARAMETER,
202 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
204 SetLastError(0xdeadbeef);
205 ret = WinHttpCloseHandle(request);
206 ok(ret, "WinHttpCloseHandle failed on closing request: %u\n", GetLastError());
208 done:
209 SetLastError(0xdeadbeef);
210 ret = WinHttpCloseHandle(connection);
211 ok(ret, "WinHttpCloseHandle failed on closing connection: %u\n", GetLastError());
212 SetLastError(0xdeadbeef);
213 ret = WinHttpCloseHandle(session);
214 ok(ret, "WinHttpCloseHandle failed on closing session: %u\n", GetLastError());
217 static void test_OpenRequest (void)
219 BOOL ret;
220 HINTERNET session, request, connection;
221 DWORD err;
223 SetLastError(0xdeadbeef);
224 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
225 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
226 err = GetLastError();
227 ok(session != NULL, "WinHttpOpen failed to open session.\n");
228 ok(err == ERROR_SUCCESS, "got %u\n", err);
230 /* Test with a bad server name */
231 SetLastError(0xdeadbeef);
232 connection = WinHttpConnect(session, NULL, INTERNET_DEFAULT_HTTP_PORT, 0);
233 err = GetLastError();
234 ok (connection == NULL, "WinHttpConnect succeeded in opening connection to NULL server argument.\n");
235 ok(err == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u.\n", err);
237 /* Test with a valid server name */
238 SetLastError(0xdeadbeef);
239 connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
240 err = GetLastError();
241 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", err);
242 ok(err == ERROR_SUCCESS || broken(err == WSAEINVAL) /* < win7 */, "got %u\n", err);
244 SetLastError(0xdeadbeef);
245 request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
246 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
247 err = GetLastError();
248 if (request == NULL && err == ERROR_WINHTTP_NAME_NOT_RESOLVED)
250 skip("Network unreachable, skipping.\n");
251 goto done;
253 ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", err);
254 ok(err == ERROR_SUCCESS, "got %u\n", err);
256 SetLastError(0xdeadbeef);
257 ret = WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, NULL, 0, 0, 0);
258 err = GetLastError();
259 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
261 skip("Connection failed, skipping.\n");
262 goto done;
264 ok(ret, "WinHttpSendRequest failed: %u\n", err);
265 ok(err == ERROR_SUCCESS, "got %u\n", err);
267 SetLastError(0xdeadbeef);
268 ret = WinHttpCloseHandle(request);
269 err = GetLastError();
270 ok(ret, "WinHttpCloseHandle failed on closing request, got %u.\n", err);
271 ok(err == ERROR_SUCCESS, "got %u\n", err);
273 done:
274 ret = WinHttpCloseHandle(connection);
275 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
276 ret = WinHttpCloseHandle(session);
277 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
281 static void test_empty_headers_param(void)
283 static const WCHAR empty[] = {0};
284 HINTERNET ses, con, req;
285 DWORD err;
286 BOOL ret;
288 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
289 ok(ses != NULL, "failed to open session %u\n", GetLastError());
291 con = WinHttpConnect(ses, test_winehq, 80, 0);
292 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
294 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
295 ok(req != NULL, "failed to open a request %u\n", GetLastError());
297 ret = WinHttpSendRequest(req, empty, 0, NULL, 0, 0, 0);
298 err = GetLastError();
299 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
301 skip("connection failed, skipping\n");
302 goto done;
304 ok(ret, "failed to send request %u\n", GetLastError());
306 done:
307 WinHttpCloseHandle(req);
308 WinHttpCloseHandle(con);
309 WinHttpCloseHandle(ses);
312 static void test_SendRequest (void)
314 static const WCHAR content_type[] =
315 {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t','i','o','n',
316 '/','x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o','d','e','d',0};
317 static const WCHAR test_file[] = {'t','e','s','t','s','/','p','o','s','t','.','p','h','p',0};
318 static const WCHAR test_verb[] = {'P','O','S','T',0};
319 static CHAR post_data[] = "mode=Test";
320 static const char test_post[] = "mode => Test\0\n";
321 HINTERNET session, request, connection;
322 DWORD header_len, optional_len, total_len, bytes_rw, size, err;
323 DWORD_PTR context;
324 BOOL ret;
325 CHAR buffer[256];
326 int i;
328 header_len = -1L;
329 total_len = optional_len = sizeof(post_data);
330 memset(buffer, 0xff, sizeof(buffer));
332 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
333 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
334 ok(session != NULL, "WinHttpOpen failed to open session.\n");
336 connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
337 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
339 request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
340 WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
341 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
343 skip("Network unreachable, skipping.\n");
344 goto done;
346 ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError());
347 if (!request) goto done;
349 context = 0xdeadbeef;
350 ret = WinHttpSetOption(request, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(context));
351 ok(ret, "WinHttpSetOption failed: %u\n", GetLastError());
353 context++;
354 ret = WinHttpSendRequest(request, content_type, header_len, post_data, optional_len, total_len, context);
355 err = GetLastError();
356 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
358 skip("connection failed, skipping\n");
359 goto done;
361 ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError());
363 context = 0;
364 size = sizeof(context);
365 ret = WinHttpQueryOption(request, WINHTTP_OPTION_CONTEXT_VALUE, &context, &size);
366 ok(ret, "WinHttpQueryOption failed: %u\n", GetLastError());
367 ok(context == 0xdeadbef0, "expected 0xdeadbef0, got %lx\n", context);
369 for (i = 3; post_data[i]; i++)
371 bytes_rw = -1;
372 SetLastError(0xdeadbeef);
373 ret = WinHttpWriteData(request, &post_data[i], 1, &bytes_rw);
374 if (ret)
376 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %u.\n", GetLastError());
377 ok(bytes_rw == 1, "WinHttpWriteData failed, wrote %u bytes instead of 1 byte.\n", bytes_rw);
379 else /* Since we already passed all optional data in WinHttpSendRequest Win7 fails our WinHttpWriteData call */
381 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER got %u.\n", GetLastError());
382 ok(bytes_rw == -1, "Expected bytes_rw to remain unchanged.\n");
386 SetLastError(0xdeadbeef);
387 ret = WinHttpReceiveResponse(request, NULL);
388 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == ERROR_NO_TOKEN) /* < win7 */,
389 "Expected ERROR_SUCCESS got %u.\n", GetLastError());
390 ok(ret == TRUE, "WinHttpReceiveResponse failed: %u.\n", GetLastError());
392 bytes_rw = -1;
393 ret = WinHttpReadData(request, buffer, sizeof(buffer) - 1, &bytes_rw);
394 ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
396 ok(bytes_rw == sizeof(test_post) - 1, "Read %u bytes\n", bytes_rw);
397 ok(!memcmp(buffer, test_post, sizeof(test_post) - 1), "Data read did not match.\n");
399 done:
400 ret = WinHttpCloseHandle(request);
401 ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
402 ret = WinHttpCloseHandle(connection);
403 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
404 ret = WinHttpCloseHandle(session);
405 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
408 static void test_WinHttpTimeFromSystemTime(void)
410 BOOL ret;
411 static const SYSTEMTIME time = {2008, 7, 1, 28, 10, 5, 52, 0};
412 static const WCHAR expected_string[] =
413 {'M','o','n',',',' ','2','8',' ','J','u','l',' ','2','0','0','8',' ',
414 '1','0',':','0','5',':','5','2',' ','G','M','T',0};
415 WCHAR time_string[WINHTTP_TIME_FORMAT_BUFSIZE+1];
416 DWORD err;
418 SetLastError(0xdeadbeef);
419 ret = WinHttpTimeFromSystemTime(&time, NULL);
420 err = GetLastError();
421 ok(!ret, "WinHttpTimeFromSystemTime succeeded\n");
422 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
424 SetLastError(0xdeadbeef);
425 ret = WinHttpTimeFromSystemTime(NULL, time_string);
426 err = GetLastError();
427 ok(!ret, "WinHttpTimeFromSystemTime succeeded\n");
428 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
430 SetLastError(0xdeadbeef);
431 ret = WinHttpTimeFromSystemTime(&time, time_string);
432 err = GetLastError();
433 ok(ret, "WinHttpTimeFromSystemTime failed: %u\n", err);
434 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
435 ok(memcmp(time_string, expected_string, sizeof(expected_string)) == 0,
436 "Time string returned did not match expected time string.\n");
439 static void test_WinHttpTimeToSystemTime(void)
441 BOOL ret;
442 SYSTEMTIME time;
443 static const SYSTEMTIME expected_time = {2008, 7, 1, 28, 10, 5, 52, 0};
444 static const WCHAR time_string1[] =
445 {'M','o','n',',',' ','2','8',' ','J','u','l',' ','2','0','0','8',' ',
446 + '1','0',':','0','5',':','5','2',' ','G','M','T','\n',0};
447 static const WCHAR time_string2[] =
448 {' ','m','o','n',' ','2','8',' ','j','u','l',' ','2','0','0','8',' ',
449 '1','0',' ','0','5',' ','5','2','\n',0};
450 DWORD err;
452 SetLastError(0xdeadbeef);
453 ret = WinHttpTimeToSystemTime(time_string1, NULL);
454 err = GetLastError();
455 ok(!ret, "WinHttpTimeToSystemTime succeeded\n");
456 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
458 SetLastError(0xdeadbeef);
459 ret = WinHttpTimeToSystemTime(NULL, &time);
460 err = GetLastError();
461 ok(!ret, "WinHttpTimeToSystemTime succeeded\n");
462 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
464 SetLastError(0xdeadbeef);
465 ret = WinHttpTimeToSystemTime(time_string1, &time);
466 err = GetLastError();
467 ok(ret, "WinHttpTimeToSystemTime failed: %u\n", err);
468 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
469 ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
470 "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
472 SetLastError(0xdeadbeef);
473 ret = WinHttpTimeToSystemTime(time_string2, &time);
474 err = GetLastError();
475 ok(ret, "WinHttpTimeToSystemTime failed: %u\n", err);
476 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
477 ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
478 "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
481 static void test_WinHttpAddHeaders(void)
483 HINTERNET session, request, connection;
484 BOOL ret, reverse;
485 WCHAR buffer[MAX_PATH];
486 WCHAR check_buffer[MAX_PATH];
487 DWORD err, index, len, oldlen;
489 static const WCHAR test_file[] = {'/','p','o','s','t','t','e','s','t','.','p','h','p',0};
490 static const WCHAR test_verb[] = {'P','O','S','T',0};
491 static const WCHAR test_header_begin[] =
492 {'P','O','S','T',' ','/','p','o','s','t','t','e','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
493 static const WCHAR full_path_test_header_begin[] =
494 {'P','O','S','T',' ','h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',':','8','0',
495 '/','p','o','s','t','t','e','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
496 static const WCHAR test_header_end[] = {'\r','\n','\r','\n',0};
497 static const WCHAR test_header_name[] = {'W','a','r','n','i','n','g',0};
498 static const WCHAR test_header_name2[] = {'n','a','m','e',0};
499 static const WCHAR test_header_name3[] = {'a',0};
500 static const WCHAR test_header_range[] = {'R','a','n','g','e',0};
501 static const WCHAR test_header_range_bytes[] = {'R','a','n','g','e',':',' ','b','y','t','e','s','=','0','-','7','7','3','\r','\n',0};
502 static const WCHAR test_header_bytes[] = {'b','y','t','e','s','=','0','-','7','7','3',0};
504 static const WCHAR test_flag_coalesce[] = {'t','e','s','t','2',',',' ','t','e','s','t','4',0};
505 static const WCHAR test_flag_coalesce_reverse[] = {'t','e','s','t','3',',',' ','t','e','s','t','4',0};
506 static const WCHAR test_flag_coalesce_comma[] =
507 {'t','e','s','t','2',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',0};
508 static const WCHAR test_flag_coalesce_comma_reverse[] =
509 {'t','e','s','t','3',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',0};
510 static const WCHAR test_flag_coalesce_semicolon[] =
511 {'t','e','s','t','2',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',';',' ','t','e','s','t','6',0};
512 static const WCHAR test_flag_coalesce_semicolon_reverse[] =
513 {'t','e','s','t','3',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',';',' ','t','e','s','t','6',0};
515 static const WCHAR field[] = {'f','i','e','l','d',0};
516 static const WCHAR value[] = {'v','a','l','u','e',' ',0};
517 static const WCHAR value_nospace[] = {'v','a','l','u','e',0};
518 static const WCHAR empty[] = {0};
520 static const WCHAR test_headers[][14] =
522 {'W','a','r','n','i','n','g',':','t','e','s','t','1',0},
523 {'W','a','r','n','i','n','g',':','t','e','s','t','2',0},
524 {'W','a','r','n','i','n','g',':','t','e','s','t','3',0},
525 {'W','a','r','n','i','n','g',':','t','e','s','t','4',0},
526 {'W','a','r','n','i','n','g',':','t','e','s','t','5',0},
527 {'W','a','r','n','i','n','g',':','t','e','s','t','6',0},
528 {'W','a','r','n','i','n','g',':','t','e','s','t','7',0},
529 {0},
530 {':',0},
531 {'a',':',0},
532 {':','b',0},
533 {'c','d',0},
534 {' ','e',' ',':','f',0},
535 {'f','i','e','l','d',':',' ','v','a','l','u','e',' ',0},
536 {'n','a','m','e',':',' ','v','a','l','u','e',0},
537 {'n','a','m','e',':',0}
539 static const WCHAR test_indices[][6] =
541 {'t','e','s','t','1',0},
542 {'t','e','s','t','2',0},
543 {'t','e','s','t','3',0},
544 {'t','e','s','t','4',0}
547 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
548 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
549 ok(session != NULL, "WinHttpOpen failed to open session.\n");
551 connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
552 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
554 request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
555 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
556 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
558 skip("Network unreachable, skipping.\n");
559 goto done;
561 ok(request != NULL, "WinHttpOpenRequest failed to open a request, error: %u.\n", GetLastError());
563 index = 0;
564 len = sizeof(buffer);
565 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
566 test_header_name, buffer, &len, &index);
567 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, found 'Warning' header.\n");
568 SetLastError(0xdeadbeef);
569 ret = WinHttpAddRequestHeaders(request, test_headers[0], -1L, WINHTTP_ADDREQ_FLAG_ADD);
570 err = GetLastError();
571 ok(ret, "WinHttpAddRequestHeader failed to add new header, got %d with error %u.\n", ret, err);
572 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
574 index = 0;
575 len = sizeof(buffer);
576 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
577 test_header_name, buffer, &len, &index);
578 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
579 ok(index == 1, "WinHttpQueryHeaders failed: header index not incremented\n");
580 ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders failed: incorrect string returned\n");
581 ok(len == 5*sizeof(WCHAR), "WinHttpQueryHeaders failed: invalid length returned, expected 5, got %d\n", len);
583 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
584 test_header_name, buffer, &len, &index);
585 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, second index should not exist.\n");
587 /* Try to fetch the header info with a buffer that's big enough to fit the
588 * string but not the NULL terminator.
590 index = 0;
591 len = 5*sizeof(WCHAR);
592 memset(check_buffer, 0xab, sizeof(check_buffer));
593 memcpy(buffer, check_buffer, sizeof(buffer));
594 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
595 test_header_name, buffer, &len, &index);
596 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded with a buffer that's too small.\n");
597 ok(memcmp(buffer, check_buffer, sizeof(buffer)) == 0,
598 "WinHttpQueryHeaders failed, modified the buffer when it should not have.\n");
599 ok(len == 6*sizeof(WCHAR), "WinHttpQueryHeaders returned invalid length, expected 12, got %d\n", len);
601 /* Try with a NULL buffer */
602 index = 0;
603 len = sizeof(buffer);
604 SetLastError(0xdeadbeef);
605 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
606 test_header_name, NULL, &len, &index);
607 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
608 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
609 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
610 ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
612 /* Try with a NULL buffer and a length that's too small */
613 index = 0;
614 len = 10;
615 SetLastError(0xdeadbeef);
616 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
617 test_header_name, NULL, &len, &index);
618 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
619 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
620 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICENT_BUFFER, got %u\n", GetLastError());
621 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
622 ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
624 index = 0;
625 len = 0;
626 SetLastError(0xdeadbeef);
627 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
628 test_header_name, NULL, &len, &index);
629 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
630 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
631 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
632 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
633 ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
635 /* valid query */
636 oldlen = len;
637 index = 0;
638 len = sizeof(buffer);
639 memset(buffer, 0xff, sizeof(buffer));
640 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
641 test_header_name, buffer, &len, &index);
642 ok(ret == TRUE, "WinHttpQueryHeaders failed: got %d\n", ret);
643 ok(len + sizeof(WCHAR) <= oldlen, "WinHttpQueryHeaders resulting length longer than advertized.\n");
644 ok((len < sizeof(buffer) - sizeof(WCHAR)) && buffer[len / sizeof(WCHAR)] == 0, "WinHttpQueryHeaders did not append NULL terminator\n");
645 ok(len == lstrlenW(buffer) * sizeof(WCHAR), "WinHttpQueryHeaders returned incorrect length.\n");
646 ok(memcmp(buffer, test_header_begin, sizeof(test_header_begin)) == 0 ||
647 memcmp(buffer, full_path_test_header_begin, sizeof(full_path_test_header_begin)) == 0,
648 "WinHttpQueryHeaders returned invalid beginning of header string.\n");
649 ok(memcmp(buffer + lstrlenW(buffer) - 4, test_header_end, sizeof(test_header_end)) == 0,
650 "WinHttpQueryHeaders returned invalid end of header string.\n");
651 ok(index == 0, "WinHttpQueryHeaders incremented header index.\n");
653 index = 0;
654 len = 0;
655 SetLastError(0xdeadbeef);
656 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
657 test_header_name, NULL, &len, &index);
658 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
659 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
660 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
661 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
662 ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
664 oldlen = len;
665 index = 0;
666 len = sizeof(buffer);
667 memset(buffer, 0xff, sizeof(buffer));
668 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
669 test_header_name, buffer, &len, &index);
670 ok(ret == TRUE, "WinHttpQueryHeaders failed %u\n", GetLastError());
671 ok(len + sizeof(WCHAR) <= oldlen, "resulting length longer than advertized\n");
672 ok((len < sizeof(buffer) - sizeof(WCHAR)) && !buffer[len / sizeof(WCHAR)] && !buffer[len / sizeof(WCHAR) - 1],
673 "no double NULL terminator\n");
674 ok(memcmp(buffer, test_header_begin, sizeof(test_header_begin)) == 0 ||
675 memcmp(buffer, full_path_test_header_begin, sizeof(full_path_test_header_begin)) == 0,
676 "invalid beginning of header string.\n");
677 ok(index == 0, "header index was incremented\n");
679 /* tests for more indices */
680 ret = WinHttpAddRequestHeaders(request, test_headers[1], -1L, WINHTTP_ADDREQ_FLAG_ADD);
681 ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header: %d\n", ret);
683 index = 0;
684 len = sizeof(buffer);
685 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
686 test_header_name, buffer, &len, &index);
687 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
688 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
689 ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
691 len = sizeof(buffer);
692 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
693 test_header_name, buffer, &len, &index);
694 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
695 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
696 ok(memcmp(buffer, test_indices[1], sizeof(test_indices[1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
698 ret = WinHttpAddRequestHeaders(request, test_headers[2], -1L, WINHTTP_ADDREQ_FLAG_REPLACE);
699 ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header.\n");
701 index = 0;
702 len = sizeof(buffer);
703 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
704 test_header_name, buffer, &len, &index);
705 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
706 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
707 reverse = (memcmp(buffer, test_indices[1], sizeof(test_indices[1])) != 0); /* Win7 returns values in reverse order of adding */
708 ok(memcmp(buffer, test_indices[reverse ? 2 : 1], sizeof(test_indices[reverse ? 2 : 1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
710 len = sizeof(buffer);
711 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
712 test_header_name, buffer, &len, &index);
713 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
714 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
715 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
717 /* add if new flag */
718 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW);
719 ok(ret == FALSE, "WinHttpAddRequestHeaders incorrectly replaced existing header.\n");
721 index = 0;
722 len = sizeof(buffer);
723 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
724 test_header_name, buffer, &len, &index);
725 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
726 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
727 ok(memcmp(buffer, test_indices[reverse ? 2 : 1], sizeof(test_indices[reverse ? 2 : 1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
729 len = sizeof(buffer);
730 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
731 test_header_name, buffer, &len, &index);
732 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
733 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
734 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
736 len = sizeof(buffer);
737 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
738 test_header_name, buffer, &len, &index);
739 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
741 /* coalesce flag */
742 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_COALESCE);
743 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE.\n");
745 index = 0;
746 len = sizeof(buffer);
747 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
748 test_header_name, buffer, &len, &index);
749 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
750 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
751 ok(memcmp(buffer, reverse ? test_flag_coalesce_reverse : test_flag_coalesce,
752 reverse ? sizeof(test_flag_coalesce_reverse) : sizeof(test_flag_coalesce)) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
754 len = sizeof(buffer);
755 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
756 test_header_name, buffer, &len, &index);
757 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
758 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
759 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
761 len = sizeof(buffer);
762 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
763 test_header_name, buffer, &len, &index);
764 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
766 /* coalesce with comma flag */
767 ret = WinHttpAddRequestHeaders(request, test_headers[4], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA);
768 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA.\n");
770 index = 0;
771 len = sizeof(buffer);
772 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
773 test_header_name, buffer, &len, &index);
774 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
775 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
776 ok(memcmp(buffer, reverse ? test_flag_coalesce_comma_reverse : test_flag_coalesce_comma,
777 reverse ? sizeof(test_flag_coalesce_comma_reverse) : sizeof(test_flag_coalesce_comma)) == 0,
778 "WinHttpQueryHeaders returned incorrect string.\n");
780 len = sizeof(buffer);
781 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
782 test_header_name, buffer, &len, &index);
783 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
784 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
785 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
787 len = sizeof(buffer);
788 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
789 test_header_name, buffer, &len, &index);
790 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
793 /* coalesce with semicolon flag */
794 ret = WinHttpAddRequestHeaders(request, test_headers[5], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON);
795 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON.\n");
797 index = 0;
798 len = sizeof(buffer);
799 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
800 test_header_name, buffer, &len, &index);
801 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
802 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
803 ok(memcmp(buffer, reverse ? test_flag_coalesce_semicolon_reverse : test_flag_coalesce_semicolon,
804 reverse ? sizeof(test_flag_coalesce_semicolon_reverse) : sizeof(test_flag_coalesce_semicolon)) == 0,
805 "WinHttpQueryHeaders returned incorrect string.\n");
807 len = sizeof(buffer);
808 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
809 test_header_name, buffer, &len, &index);
810 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
811 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
812 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
814 len = sizeof(buffer);
815 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
816 test_header_name, buffer, &len, &index);
817 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
819 /* add and replace flags */
820 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
821 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE.\n");
823 index = 0;
824 len = sizeof(buffer);
825 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
826 test_header_name, buffer, &len, &index);
827 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
828 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
829 ok(memcmp(buffer, test_indices[reverse ? 3 : 2], sizeof(test_indices[reverse ? 3 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
831 len = sizeof(buffer);
832 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
833 test_header_name, buffer, &len, &index);
834 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
835 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
836 ok(memcmp(buffer, test_indices[reverse ? 1 : 3], sizeof(test_indices[reverse ? 1 : 3])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
838 len = sizeof(buffer);
839 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
840 test_header_name, buffer, &len, &index);
841 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
843 ret = WinHttpAddRequestHeaders(request, test_headers[8], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
844 ok(!ret, "WinHttpAddRequestHeaders failed\n");
846 ret = WinHttpAddRequestHeaders(request, test_headers[9], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
847 ok(ret, "WinHttpAddRequestHeaders failed\n");
849 index = 0;
850 memset(buffer, 0xff, sizeof(buffer));
851 len = sizeof(buffer);
852 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
853 test_header_name3, buffer, &len, &index);
854 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
855 ok(!memcmp(buffer, empty, sizeof(empty)), "unexpected result\n");
857 ret = WinHttpAddRequestHeaders(request, test_headers[10], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
858 ok(!ret, "WinHttpAddRequestHeaders failed\n");
860 ret = WinHttpAddRequestHeaders(request, test_headers[11], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
861 ok(!ret, "WinHttpAddRequestHeaders failed\n");
863 ret = WinHttpAddRequestHeaders(request, test_headers[12], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
864 ok(!ret, "WinHttpAddRequestHeaders failed\n");
866 ret = WinHttpAddRequestHeaders(request, test_headers[13], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
867 ok(ret, "WinHttpAddRequestHeaders failed\n");
869 index = 0;
870 buffer[0] = 0;
871 len = sizeof(buffer);
872 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
873 field, buffer, &len, &index);
874 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
875 ok(!memcmp(buffer, value, sizeof(value)) || ! memcmp(buffer, value_nospace, sizeof(value_nospace)), "unexpected result\n");
877 SetLastError(0xdeadbeef);
878 ret = WinHttpAddRequestHeaders(request, test_header_range_bytes, 0,
879 WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
880 err = GetLastError();
881 ok(!ret, "unexpected success\n");
882 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
884 ret = WinHttpAddRequestHeaders(request, test_header_range_bytes, ~0u,
885 WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
886 ok(ret, "failed to add header: %u\n", GetLastError());
888 index = 0;
889 len = sizeof(buffer);
890 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
891 test_header_range, buffer, &len, &index);
892 ok(ret, "failed to get range header %u\n", GetLastError());
893 ok(!memcmp(buffer, test_header_bytes, sizeof(test_header_bytes)), "incorrect string returned\n");
894 ok(len == lstrlenW(test_header_bytes) * sizeof(WCHAR), "wrong length %u\n", len);
895 ok(index == 1, "wrong index %u\n", index);
897 index = 0;
898 len = sizeof(buffer);
899 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
900 test_header_name2, buffer, &len, &index);
901 ok(!ret, "unexpected success\n");
903 SetLastError(0xdeadbeef);
904 ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
905 err = GetLastError();
906 ok(!ret, "unexpected success\n");
907 ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
909 ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
910 ok(ret, "got %u\n", GetLastError());
912 index = 0;
913 len = sizeof(buffer);
914 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
915 test_header_name2, buffer, &len, &index);
916 ok(ret, "got %u\n", GetLastError());
917 ok(index == 1, "wrong index %u\n", index);
918 ok(!memcmp(buffer, value_nospace, sizeof(value_nospace)), "incorrect string\n");
920 ret = WinHttpAddRequestHeaders(request, test_headers[15], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
921 ok(ret, "got %u\n", GetLastError());
923 index = 0;
924 len = sizeof(buffer);
925 SetLastError(0xdeadbeef);
926 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
927 test_header_name2, buffer, &len, &index);
928 err = GetLastError();
929 ok(!ret, "unexpected success\n");
930 ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
932 ret = WinHttpAddRequestHeaders(request, test_headers[14], -1L, 0);
933 ok(ret, "got %u\n", GetLastError());
935 index = 0;
936 len = sizeof(buffer);
937 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
938 test_header_name2, buffer, &len, &index);
939 ok(ret, "got %u\n", GetLastError());
940 ok(index == 1, "wrong index %u\n", index);
941 ok(!memcmp(buffer, value_nospace, sizeof(value_nospace)), "incorrect string\n");
943 ret = WinHttpCloseHandle(request);
944 ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
945 done:
946 ret = WinHttpCloseHandle(connection);
947 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
948 ret = WinHttpCloseHandle(session);
949 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
953 static void CALLBACK cert_error(HINTERNET handle, DWORD_PTR ctx, DWORD status, LPVOID buf, DWORD len)
955 DWORD flags = *(DWORD *)buf;
957 if (!flags)
959 trace("WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR\n");
960 return;
962 #define X(x) if (flags & x) trace("%s\n", #x);
963 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED)
964 X(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT)
965 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED)
966 X(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA)
967 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID)
968 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID)
969 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE)
970 #undef X
973 static void test_secure_connection(void)
975 static const char data_start[] = "<!DOCTYPE html PUBLIC";
976 HINTERNET ses, con, req;
977 DWORD size, status, policy, bitness, read_size, err, available_size, protocols;
978 BOOL ret;
979 CERT_CONTEXT *cert;
980 WINHTTP_CERTIFICATE_INFO info;
981 char buffer[32];
983 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
984 ok(ses != NULL, "failed to open session %u\n", GetLastError());
986 policy = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
987 ret = WinHttpSetOption(ses, WINHTTP_OPTION_REDIRECT_POLICY, &policy, sizeof(policy));
988 ok(ret, "failed to set redirect policy %u\n", GetLastError());
990 protocols = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;
991 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SECURE_PROTOCOLS, &protocols, sizeof(protocols));
992 err = GetLastError();
993 ok(ret || (!ret && err == ERROR_INVALID_PARAMETER) /* < win7 */, "failed to set protocols %u\n", err);
995 con = WinHttpConnect(ses, test_winehq, 443, 0);
996 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
998 /* try without setting WINHTTP_FLAG_SECURE */
999 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1000 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1002 ret = WinHttpSetOption(req, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0);
1003 err = GetLastError();
1004 ok(!ret, "unexpected success\n");
1005 ok(err == ERROR_WINHTTP_INCORRECT_HANDLE_STATE || broken(err == ERROR_INVALID_PARAMETER) /* winxp */,
1006 "setting client cert context returned %u\n", err);
1008 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1009 err = GetLastError();
1010 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
1012 skip("Connection failed, skipping.\n");
1013 goto cleanup;
1015 ok(ret, "failed to send request %u\n", GetLastError());
1017 ret = WinHttpReceiveResponse(req, NULL);
1018 ok(ret, "failed to receive response %u\n", GetLastError());
1020 status = 0xdeadbeef;
1021 size = sizeof(status);
1022 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1023 ok(ret, "header query failed %u\n", GetLastError());
1024 ok(status == HTTP_STATUS_BAD_REQUEST, "got %u\n", status);
1026 WinHttpCloseHandle(req);
1028 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, WINHTTP_FLAG_SECURE);
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 || broken(!ret && err == ERROR_INVALID_PARAMETER) /* winxp */, "failed to set client cert context %u\n", err);
1035 WinHttpSetStatusCallback(req, cert_error, WINHTTP_CALLBACK_STATUS_SECURE_FAILURE, 0);
1037 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1038 err = GetLastError();
1039 if (!ret && (err == ERROR_WINHTTP_SECURE_FAILURE || err == ERROR_WINHTTP_CANNOT_CONNECT ||
1040 err == ERROR_WINHTTP_TIMEOUT))
1042 skip("secure connection failed, skipping remaining secure tests\n");
1043 goto cleanup;
1045 ok(ret, "failed to send request %u\n", GetLastError());
1047 size = sizeof(cert);
1048 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert, &size );
1049 ok(ret, "failed to retrieve certificate context %u\n", GetLastError());
1050 if (ret) CertFreeCertificateContext(cert);
1052 size = sizeof(bitness);
1053 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_KEY_BITNESS, &bitness, &size );
1054 ok(ret, "failed to retrieve key bitness %u\n", GetLastError());
1056 size = sizeof(info);
1057 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT, &info, &size );
1058 ok(ret, "failed to retrieve certificate info %u\n", GetLastError());
1060 if (ret)
1062 trace("lpszSubjectInfo %s\n", wine_dbgstr_w(info.lpszSubjectInfo));
1063 trace("lpszIssuerInfo %s\n", wine_dbgstr_w(info.lpszIssuerInfo));
1064 trace("lpszProtocolName %s\n", wine_dbgstr_w(info.lpszProtocolName));
1065 trace("lpszSignatureAlgName %s\n", wine_dbgstr_w(info.lpszSignatureAlgName));
1066 trace("lpszEncryptionAlgName %s\n", wine_dbgstr_w(info.lpszEncryptionAlgName));
1067 trace("dwKeySize %u\n", info.dwKeySize);
1068 LocalFree( info.lpszSubjectInfo );
1069 LocalFree( info.lpszIssuerInfo );
1072 ret = WinHttpReceiveResponse(req, NULL);
1073 ok(ret, "failed to receive response %u\n", GetLastError());
1075 available_size = 0;
1076 ret = WinHttpQueryDataAvailable(req, &available_size);
1077 ok(ret, "failed to query available data %u\n", GetLastError());
1078 ok(available_size > 2014, "available_size = %u\n", available_size);
1080 status = 0xdeadbeef;
1081 size = sizeof(status);
1082 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1083 ok(ret, "failed unexpectedly %u\n", GetLastError());
1084 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1086 size = 0;
1087 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL);
1088 ok(!ret, "succeeded unexpectedly\n");
1090 read_size = 0;
1091 for (;;)
1093 size = 0;
1094 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
1095 ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
1096 if (!size) break;
1097 read_size += size;
1099 if (read_size <= 32)
1100 ok(!memcmp(buffer, data_start, sizeof(data_start)-1), "not expected: %.32s\n", buffer);
1102 ok(read_size >= available_size, "read_size = %u, available_size = %u\n", read_size, available_size);
1104 cleanup:
1105 WinHttpCloseHandle(req);
1106 WinHttpCloseHandle(con);
1107 WinHttpCloseHandle(ses);
1110 static void test_request_parameter_defaults(void)
1112 static const WCHAR empty[] = {0};
1113 HINTERNET ses, con, req;
1114 DWORD size, status, error;
1115 WCHAR *version;
1116 BOOL ret;
1118 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1119 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1121 con = WinHttpConnect(ses, test_winehq, 0, 0);
1122 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1124 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1125 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1127 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1128 error = GetLastError();
1129 if (!ret && (error == ERROR_WINHTTP_CANNOT_CONNECT || error == ERROR_WINHTTP_TIMEOUT))
1131 skip("connection failed, skipping\n");
1132 goto done;
1134 ok(ret, "failed to send request %u\n", GetLastError());
1136 ret = WinHttpReceiveResponse(req, NULL);
1137 if (!ret && GetLastError() == ERROR_WINHTTP_INVALID_SERVER_RESPONSE) /* win2k */
1139 win_skip("invalid response\n");
1140 goto done;
1142 ok(ret, "failed to receive response %u\n", GetLastError());
1144 status = 0xdeadbeef;
1145 size = sizeof(status);
1146 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1147 ok(ret, "failed unexpectedly %u\n", GetLastError());
1148 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1150 WinHttpCloseHandle(req);
1152 req = WinHttpOpenRequest(con, empty, empty, empty, NULL, NULL, 0);
1153 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1155 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1156 error = GetLastError();
1157 if (!ret && (error == ERROR_WINHTTP_CANNOT_CONNECT || error == ERROR_WINHTTP_TIMEOUT))
1159 skip("connection failed, skipping\n");
1160 goto done;
1162 ok(ret, "failed to send request %u\n", GetLastError());
1164 ret = WinHttpReceiveResponse(req, NULL);
1165 ok(ret, "failed to receive response %u\n", GetLastError());
1167 size = 0;
1168 SetLastError(0xdeadbeef);
1169 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, NULL, &size, NULL);
1170 error = GetLastError();
1171 ok(!ret, "succeeded unexpectedly\n");
1172 ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error);
1174 version = HeapAlloc(GetProcessHeap(), 0, size);
1175 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, version, &size, NULL);
1176 ok(ret, "failed unexpectedly %u\n", GetLastError());
1177 ok(lstrlenW(version) == size / sizeof(WCHAR), "unexpected size %u\n", size);
1178 HeapFree(GetProcessHeap(), 0, version);
1180 status = 0xdeadbeef;
1181 size = sizeof(status);
1182 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1183 ok(ret, "failed unexpectedly %u\n", GetLastError());
1184 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1186 done:
1187 WinHttpCloseHandle(req);
1188 WinHttpCloseHandle(con);
1189 WinHttpCloseHandle(ses);
1192 static const WCHAR Connections[] = {
1193 'S','o','f','t','w','a','r','e','\\',
1194 'M','i','c','r','o','s','o','f','t','\\',
1195 'W','i','n','d','o','w','s','\\',
1196 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1197 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
1198 'C','o','n','n','e','c','t','i','o','n','s',0 };
1199 static const WCHAR WinHttpSettings[] = {
1200 'W','i','n','H','t','t','p','S','e','t','t','i','n','g','s',0 };
1202 static DWORD get_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD *type )
1204 LONG l;
1205 HKEY key;
1206 DWORD ret = 0;
1208 l = RegOpenKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, KEY_READ, &key );
1209 if (!l)
1211 DWORD size = 0;
1213 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, NULL, &size );
1214 if (!l)
1216 if (size <= len)
1217 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, buf,
1218 &size );
1219 if (!l)
1220 ret = size;
1222 RegCloseKey( key );
1224 return ret;
1227 static void set_proxy( REGSAM access, BYTE *buf, DWORD len, DWORD type )
1229 HKEY hkey;
1230 if (!RegCreateKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, NULL, 0, access, NULL, &hkey, NULL ))
1232 if (len) RegSetValueExW( hkey, WinHttpSettings, 0, type, buf, len );
1233 else RegDeleteValueW( hkey, WinHttpSettings );
1234 RegCloseKey( hkey );
1238 static void set_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD type )
1240 BOOL wow64;
1241 IsWow64Process( GetCurrentProcess(), &wow64 );
1242 if (sizeof(void *) > sizeof(int) || wow64)
1244 set_proxy( KEY_WRITE|KEY_WOW64_64KEY, buf, len, type );
1245 set_proxy( KEY_WRITE|KEY_WOW64_32KEY, buf, len, type );
1247 else
1248 set_proxy( KEY_WRITE, buf, len, type );
1251 static void test_set_default_proxy_config(void)
1253 static WCHAR wideString[] = { 0x226f, 0x575b, 0 };
1254 static WCHAR normalString[] = { 'f','o','o',0 };
1255 DWORD type, len;
1256 BYTE *saved_proxy_settings = NULL;
1257 WINHTTP_PROXY_INFO info;
1258 BOOL ret;
1260 /* FIXME: it would be simpler to read the current settings using
1261 * WinHttpGetDefaultProxyConfiguration and save them using
1262 * WinHttpSetDefaultProxyConfiguration, but they appear to have a bug.
1264 * If a proxy is configured in the registry, e.g. via 'proxcfg -p "foo"',
1265 * the access type reported by WinHttpGetDefaultProxyConfiguration is 1,
1266 * WINHTTP_ACCESS_TYPE_NO_PROXY, whereas it should be
1267 * WINHTTP_ACCESS_TYPE_NAMED_PROXY.
1268 * If WinHttpSetDefaultProxyConfiguration is called with dwAccessType = 1,
1269 * the lpszProxy and lpszProxyBypass values are ignored.
1270 * Thus, if a proxy is set with proxycfg, then calling
1271 * WinHttpGetDefaultProxyConfiguration followed by
1272 * WinHttpSetDefaultProxyConfiguration results in the proxy settings
1273 * getting deleted from the registry.
1275 * Instead I read the current registry value and restore it directly.
1277 len = get_default_proxy_reg_value( NULL, 0, &type );
1278 if (len)
1280 saved_proxy_settings = HeapAlloc( GetProcessHeap(), 0, len );
1281 len = get_default_proxy_reg_value( saved_proxy_settings, len, &type );
1284 if (0)
1286 /* Crashes on Vista and higher */
1287 SetLastError(0xdeadbeef);
1288 ret = WinHttpSetDefaultProxyConfiguration(NULL);
1289 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1290 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1293 /* test with invalid access type */
1294 info.dwAccessType = 0xdeadbeef;
1295 info.lpszProxy = info.lpszProxyBypass = NULL;
1296 SetLastError(0xdeadbeef);
1297 ret = WinHttpSetDefaultProxyConfiguration(&info);
1298 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1299 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1301 /* at a minimum, the proxy server must be set */
1302 info.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
1303 info.lpszProxy = info.lpszProxyBypass = NULL;
1304 SetLastError(0xdeadbeef);
1305 ret = WinHttpSetDefaultProxyConfiguration(&info);
1306 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1307 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1308 info.lpszProxyBypass = normalString;
1309 SetLastError(0xdeadbeef);
1310 ret = WinHttpSetDefaultProxyConfiguration(&info);
1311 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1312 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1314 /* the proxy server can't have wide characters */
1315 info.lpszProxy = wideString;
1316 SetLastError(0xdeadbeef);
1317 ret = WinHttpSetDefaultProxyConfiguration(&info);
1318 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1319 skip("couldn't set default proxy configuration: access denied\n");
1320 else
1321 ok((!ret && GetLastError() == ERROR_INVALID_PARAMETER) ||
1322 broken(ret), /* Earlier winhttp versions on W2K/XP */
1323 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1325 info.lpszProxy = normalString;
1326 SetLastError(0xdeadbeef);
1327 ret = WinHttpSetDefaultProxyConfiguration(&info);
1328 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1329 skip("couldn't set default proxy configuration: access denied\n");
1330 else
1332 ok(ret, "WinHttpSetDefaultProxyConfiguration failed: %u\n", GetLastError());
1333 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
1334 "got %u\n", GetLastError());
1336 set_default_proxy_reg_value( saved_proxy_settings, len, type );
1339 static void test_Timeouts (void)
1341 BOOL ret;
1342 DWORD value, size;
1343 HINTERNET ses, req, con;
1345 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1346 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1348 SetLastError(0xdeadbeef);
1349 ret = WinHttpSetTimeouts(ses, -2, 0, 0, 0);
1350 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1351 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1353 SetLastError(0xdeadbeef);
1354 ret = WinHttpSetTimeouts(ses, 0, -2, 0, 0);
1355 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1356 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1358 SetLastError(0xdeadbeef);
1359 ret = WinHttpSetTimeouts(ses, 0, 0, -2, 0);
1360 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1361 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1363 SetLastError(0xdeadbeef);
1364 ret = WinHttpSetTimeouts(ses, 0, 0, 0, -2);
1365 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1366 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1368 SetLastError(0xdeadbeef);
1369 ret = WinHttpSetTimeouts(ses, -1, -1, -1, -1);
1370 ok(ret, "%u\n", GetLastError());
1371 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
1372 "expected ERROR_SUCCESS, got %u\n", GetLastError());
1374 SetLastError(0xdeadbeef);
1375 ret = WinHttpSetTimeouts(ses, 0, 0, 0, 0);
1376 ok(ret, "%u\n", GetLastError());
1378 SetLastError(0xdeadbeef);
1379 ret = WinHttpSetTimeouts(ses, 0x0123, 0x4567, 0x89ab, 0xcdef);
1380 ok(ret, "%u\n", GetLastError());
1382 SetLastError(0xdeadbeef);
1383 value = 0xdeadbeef;
1384 size = sizeof(DWORD);
1385 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1386 ok(ret, "%u\n", GetLastError());
1387 ok(value == 0x0123, "Expected 0x0123, got %u\n", value);
1389 SetLastError(0xdeadbeef);
1390 value = 0xdeadbeef;
1391 size = sizeof(DWORD);
1392 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1393 ok(ret, "%u\n", GetLastError());
1394 ok(value == 0x4567, "Expected 0x4567, got %u\n", value);
1396 SetLastError(0xdeadbeef);
1397 value = 0xdeadbeef;
1398 size = sizeof(DWORD);
1399 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1400 ok(ret, "%u\n", GetLastError());
1401 ok(value == 0x89ab, "Expected 0x89ab, got %u\n", value);
1403 SetLastError(0xdeadbeef);
1404 value = 0xdeadbeef;
1405 size = sizeof(DWORD);
1406 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1407 ok(ret, "%u\n", GetLastError());
1408 ok(value == 0xcdef, "Expected 0xcdef, got %u\n", value);
1410 SetLastError(0xdeadbeef);
1411 value = 0;
1412 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1413 ok(ret, "%u\n", GetLastError());
1415 SetLastError(0xdeadbeef);
1416 value = 0xdeadbeef;
1417 size = sizeof(DWORD);
1418 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1419 ok(ret, "%u\n", GetLastError());
1420 ok(value == 0, "Expected 0, got %u\n", value);
1422 SetLastError(0xdeadbeef);
1423 value = 0;
1424 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1425 ok(ret, "%u\n", GetLastError());
1427 SetLastError(0xdeadbeef);
1428 value = 0xdeadbeef;
1429 size = sizeof(DWORD);
1430 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1431 ok(ret, "%u\n", GetLastError());
1432 ok(value == 0, "Expected 0, got %u\n", value);
1434 SetLastError(0xdeadbeef);
1435 value = 0;
1436 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1437 ok(ret, "%u\n", GetLastError());
1439 SetLastError(0xdeadbeef);
1440 value = 0xdeadbeef;
1441 size = sizeof(DWORD);
1442 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1443 ok(ret, "%u\n", GetLastError());
1444 ok(value == 0, "Expected 0, got %u\n", value);
1446 SetLastError(0xdeadbeef);
1447 value = 0;
1448 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1449 ok(ret, "%u\n", GetLastError());
1451 SetLastError(0xdeadbeef);
1452 value = 0xdeadbeef;
1453 size = sizeof(DWORD);
1454 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1455 ok(ret, "%u\n", GetLastError());
1456 ok(value == 0, "Expected 0, got %u\n", value);
1458 SetLastError(0xdeadbeef);
1459 value = 0xbeefdead;
1460 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1461 ok(ret, "%u\n", GetLastError());
1463 SetLastError(0xdeadbeef);
1464 value = 0xdeadbeef;
1465 size = sizeof(DWORD);
1466 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1467 ok(ret, "%u\n", GetLastError());
1468 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1470 SetLastError(0xdeadbeef);
1471 value = 0xbeefdead;
1472 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_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_CONNECT_TIMEOUT, &value, &size);
1479 ok(ret, "%u\n", GetLastError());
1480 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1482 SetLastError(0xdeadbeef);
1483 value = 0xbeefdead;
1484 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_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_SEND_TIMEOUT, &value, &size);
1491 ok(ret, "%u\n", GetLastError());
1492 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1494 SetLastError(0xdeadbeef);
1495 value = 0xbeefdead;
1496 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_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_RECEIVE_TIMEOUT, &value, &size);
1503 ok(ret, "%u\n", GetLastError());
1504 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1506 con = WinHttpConnect(ses, test_winehq, 0, 0);
1507 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1509 /* Timeout values should match the last one set for session */
1510 SetLastError(0xdeadbeef);
1511 value = 0xdeadbeef;
1512 size = sizeof(DWORD);
1513 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1514 ok(ret, "%u\n", GetLastError());
1515 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1517 SetLastError(0xdeadbeef);
1518 value = 0xdeadbeef;
1519 size = sizeof(DWORD);
1520 ret = WinHttpQueryOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1521 ok(ret, "%u\n", GetLastError());
1522 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1524 SetLastError(0xdeadbeef);
1525 value = 0xdeadbeef;
1526 size = sizeof(DWORD);
1527 ret = WinHttpQueryOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1528 ok(ret, "%u\n", GetLastError());
1529 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1531 SetLastError(0xdeadbeef);
1532 value = 0xdeadbeef;
1533 size = sizeof(DWORD);
1534 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1535 ok(ret, "%u\n", GetLastError());
1536 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1538 SetLastError(0xdeadbeef);
1539 ret = WinHttpSetTimeouts(con, -2, 0, 0, 0);
1540 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1541 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1543 SetLastError(0xdeadbeef);
1544 ret = WinHttpSetTimeouts(con, 0, -2, 0, 0);
1545 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1546 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1548 SetLastError(0xdeadbeef);
1549 ret = WinHttpSetTimeouts(con, 0, 0, -2, 0);
1550 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1551 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1553 SetLastError(0xdeadbeef);
1554 ret = WinHttpSetTimeouts(con, 0, 0, 0, -2);
1555 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1556 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1558 SetLastError(0xdeadbeef);
1559 ret = WinHttpSetTimeouts(con, -1, -1, -1, -1);
1560 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1561 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1563 SetLastError(0xdeadbeef);
1564 ret = WinHttpSetTimeouts(con, 0, 0, 0, 0);
1565 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1566 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1568 SetLastError(0xdeadbeef);
1569 value = 0;
1570 ret = WinHttpSetOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1571 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1572 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1574 SetLastError(0xdeadbeef);
1575 value = 0;
1576 ret = WinHttpSetOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1577 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1578 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1580 SetLastError(0xdeadbeef);
1581 value = 0;
1582 ret = WinHttpSetOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1583 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1584 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1586 SetLastError(0xdeadbeef);
1587 value = 0;
1588 ret = WinHttpSetOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1589 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1590 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1592 /* Changing timeout values for session should affect the values for connection */
1593 SetLastError(0xdeadbeef);
1594 value = 0xdead;
1595 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1596 ok(ret, "%u\n", GetLastError());
1598 SetLastError(0xdeadbeef);
1599 value = 0xdeadbeef;
1600 size = sizeof(DWORD);
1601 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1602 ok(ret, "%u\n", GetLastError());
1603 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1605 SetLastError(0xdeadbeef);
1606 value = 0xdead;
1607 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1608 ok(ret, "%u\n", GetLastError());
1610 SetLastError(0xdeadbeef);
1611 value = 0xdeadbeef;
1612 size = sizeof(DWORD);
1613 ret = WinHttpQueryOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1614 ok(ret, "%u\n", GetLastError());
1615 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1617 SetLastError(0xdeadbeef);
1618 value = 0xdead;
1619 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1620 ok(ret, "%u\n", GetLastError());
1622 SetLastError(0xdeadbeef);
1623 value = 0xdeadbeef;
1624 size = sizeof(DWORD);
1625 ret = WinHttpQueryOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1626 ok(ret, "%u\n", GetLastError());
1627 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1629 SetLastError(0xdeadbeef);
1630 value = 0xdead;
1631 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1632 ok(ret, "%u\n", GetLastError());
1634 SetLastError(0xdeadbeef);
1635 value = 0xdeadbeef;
1636 size = sizeof(DWORD);
1637 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1638 ok(ret, "%u\n", GetLastError());
1639 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1641 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1642 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1644 /* Timeout values should match the last one set for session */
1645 SetLastError(0xdeadbeef);
1646 value = 0xdeadbeef;
1647 size = sizeof(DWORD);
1648 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1649 ok(ret, "%u\n", GetLastError());
1650 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1652 SetLastError(0xdeadbeef);
1653 value = 0xdeadbeef;
1654 size = sizeof(DWORD);
1655 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1656 ok(ret, "%u\n", GetLastError());
1657 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1659 SetLastError(0xdeadbeef);
1660 value = 0xdeadbeef;
1661 size = sizeof(DWORD);
1662 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1663 ok(ret, "%u\n", GetLastError());
1664 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1666 SetLastError(0xdeadbeef);
1667 value = 0xdeadbeef;
1668 size = sizeof(DWORD);
1669 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1670 ok(ret, "%u\n", GetLastError());
1671 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1673 SetLastError(0xdeadbeef);
1674 ret = WinHttpSetTimeouts(req, -2, 0, 0, 0);
1675 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1676 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1678 SetLastError(0xdeadbeef);
1679 ret = WinHttpSetTimeouts(req, 0, -2, 0, 0);
1680 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1681 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1683 SetLastError(0xdeadbeef);
1684 ret = WinHttpSetTimeouts(req, 0, 0, -2, 0);
1685 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1686 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1688 SetLastError(0xdeadbeef);
1689 ret = WinHttpSetTimeouts(req, 0, 0, 0, -2);
1690 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1691 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1693 SetLastError(0xdeadbeef);
1694 ret = WinHttpSetTimeouts(req, -1, -1, -1, -1);
1695 ok(ret, "%u\n", GetLastError());
1697 SetLastError(0xdeadbeef);
1698 ret = WinHttpSetTimeouts(req, 0, 0, 0, 0);
1699 ok(ret, "%u\n", GetLastError());
1701 SetLastError(0xdeadbeef);
1702 ret = WinHttpSetTimeouts(req, 0xcdef, 0x89ab, 0x4567, 0x0123);
1703 ok(ret, "%u\n", GetLastError());
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 == 0xcdef, "Expected 0xcdef, 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 == 0x89ab, "Expected 0x89ab, 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 == 0x4567, "Expected 0x4567, 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 == 0x0123, "Expected 0x0123, got %u\n", value);
1733 SetLastError(0xdeadbeef);
1734 value = 0;
1735 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1736 ok(ret, "%u\n", GetLastError());
1738 SetLastError(0xdeadbeef);
1739 value = 0xdeadbeef;
1740 size = sizeof(DWORD);
1741 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1742 ok(ret, "%u\n", GetLastError());
1743 ok(value == 0, "Expected 0, got %u\n", value);
1745 SetLastError(0xdeadbeef);
1746 value = 0;
1747 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1748 ok(ret, "%u\n", GetLastError());
1750 SetLastError(0xdeadbeef);
1751 value = 0xdeadbeef;
1752 size = sizeof(DWORD);
1753 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1754 ok(ret, "%u\n", GetLastError());
1755 ok(value == 0, "Expected 0, got %u\n", value);
1757 SetLastError(0xdeadbeef);
1758 value = 0;
1759 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1760 ok(ret, "%u\n", GetLastError());
1762 SetLastError(0xdeadbeef);
1763 value = 0xdeadbeef;
1764 size = sizeof(DWORD);
1765 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1766 ok(ret, "%u\n", GetLastError());
1767 ok(value == 0, "Expected 0, got %u\n", value);
1769 SetLastError(0xdeadbeef);
1770 value = 0;
1771 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1772 ok(ret, "%u\n", GetLastError());
1774 SetLastError(0xdeadbeef);
1775 value = 0xdeadbeef;
1776 size = sizeof(DWORD);
1777 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1778 ok(ret, "%u\n", GetLastError());
1779 ok(value == 0, "Expected 0, got %u\n", value);
1781 SetLastError(0xdeadbeef);
1782 value = 0xbeefdead;
1783 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1784 ok(ret, "%u\n", GetLastError());
1786 SetLastError(0xdeadbeef);
1787 value = 0xdeadbeef;
1788 size = sizeof(DWORD);
1789 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1790 ok(ret, "%u\n", GetLastError());
1791 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1793 SetLastError(0xdeadbeef);
1794 value = 0xbeefdead;
1795 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_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_CONNECT_TIMEOUT, &value, &size);
1802 ok(ret, "%u\n", GetLastError());
1803 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1805 SetLastError(0xdeadbeef);
1806 value = 0xbeefdead;
1807 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_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_SEND_TIMEOUT, &value, &size);
1814 ok(ret, "%u\n", GetLastError());
1815 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1817 SetLastError(0xdeadbeef);
1818 value = 0xbeefdead;
1819 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_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_RECEIVE_TIMEOUT, &value, &size);
1826 ok(ret, "%u\n", GetLastError());
1827 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1829 /* Changing timeout values for session should not affect the values for a request,
1830 * neither should the other way around.
1832 SetLastError(0xdeadbeef);
1833 value = 0xbeefdead;
1834 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1835 ok(ret, "%u\n", GetLastError());
1837 SetLastError(0xdeadbeef);
1838 value = 0xdeadbeef;
1839 size = sizeof(DWORD);
1840 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1841 ok(ret, "%u\n", GetLastError());
1842 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1844 SetLastError(0xdeadbeef);
1845 value = 0xbeefdead;
1846 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1847 ok(ret, "%u\n", GetLastError());
1849 SetLastError(0xdeadbeef);
1850 value = 0xdeadbeef;
1851 size = sizeof(DWORD);
1852 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1853 ok(ret, "%u\n", GetLastError());
1854 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1856 SetLastError(0xdeadbeef);
1857 value = 0xbeefdead;
1858 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1859 ok(ret, "%u\n", GetLastError());
1861 SetLastError(0xdeadbeef);
1862 value = 0xdeadbeef;
1863 size = sizeof(DWORD);
1864 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1865 ok(ret, "%u\n", GetLastError());
1866 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1868 SetLastError(0xdeadbeef);
1869 value = 0xbeefdead;
1870 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1871 ok(ret, "%u\n", GetLastError());
1873 SetLastError(0xdeadbeef);
1874 value = 0xdeadbeef;
1875 size = sizeof(DWORD);
1876 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1877 ok(ret, "%u\n", GetLastError());
1878 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1880 SetLastError(0xdeadbeef);
1881 value = 0xbeef;
1882 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1883 ok(ret, "%u\n", GetLastError());
1885 SetLastError(0xdeadbeef);
1886 value = 0xdeadbeef;
1887 size = sizeof(DWORD);
1888 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1889 ok(ret, "%u\n", GetLastError());
1890 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1892 SetLastError(0xdeadbeef);
1893 value = 0xbeef;
1894 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1895 ok(ret, "%u\n", GetLastError());
1897 SetLastError(0xdeadbeef);
1898 value = 0xdeadbeef;
1899 size = sizeof(DWORD);
1900 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1901 ok(ret, "%u\n", GetLastError());
1902 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1904 SetLastError(0xdeadbeef);
1905 value = 0xbeef;
1906 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1907 ok(ret, "%u\n", GetLastError());
1909 SetLastError(0xdeadbeef);
1910 value = 0xdeadbeef;
1911 size = sizeof(DWORD);
1912 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1913 ok(ret, "%u\n", GetLastError());
1914 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1916 SetLastError(0xdeadbeef);
1917 value = 0xbeef;
1918 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1919 ok(ret, "%u\n", GetLastError());
1921 SetLastError(0xdeadbeef);
1922 value = 0xdeadbeef;
1923 size = sizeof(DWORD);
1924 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1925 ok(ret, "%u\n", GetLastError());
1926 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1928 WinHttpCloseHandle(req);
1929 WinHttpCloseHandle(con);
1930 WinHttpCloseHandle(ses);
1933 static void test_resolve_timeout(void)
1935 static const WCHAR nxdomain[] =
1936 {'n','x','d','o','m','a','i','n','.','w','i','n','e','h','q','.','o','r','g',0};
1937 HINTERNET ses, con, req;
1938 DWORD timeout;
1939 BOOL ret;
1941 if (! proxy_active())
1943 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1944 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1946 timeout = 10000;
1947 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
1948 ok(ret, "failed to set resolve timeout %u\n", GetLastError());
1950 con = WinHttpConnect(ses, nxdomain, 0, 0);
1951 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1953 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1954 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1956 SetLastError(0xdeadbeef);
1957 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1958 if (ret)
1960 skip("nxdomain returned success. Broken ISP redirects?\n");
1961 goto done;
1963 ok(GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED,
1964 "expected ERROR_WINHTTP_NAME_NOT_RESOLVED got %u\n", GetLastError());
1966 WinHttpCloseHandle(req);
1967 WinHttpCloseHandle(con);
1968 WinHttpCloseHandle(ses);
1970 else
1971 skip("Skipping host resolution tests, host resolution preformed by proxy\n");
1973 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1974 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1976 timeout = 10000;
1977 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
1978 ok(ret, "failed to set resolve timeout %u\n", GetLastError());
1980 con = WinHttpConnect(ses, test_winehq, 0, 0);
1981 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1983 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1984 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1986 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1987 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
1989 skip("connection failed, skipping\n");
1990 goto done;
1992 ok(ret, "failed to send request\n");
1994 done:
1995 WinHttpCloseHandle(req);
1996 WinHttpCloseHandle(con);
1997 WinHttpCloseHandle(ses);
2000 static const char page1[] =
2001 "<HTML>\r\n"
2002 "<HEAD><TITLE>winhttp test page</TITLE></HEAD>\r\n"
2003 "<BODY>The quick brown fox jumped over the lazy dog<P></BODY>\r\n"
2004 "</HTML>\r\n\r\n";
2006 static const char okmsg[] =
2007 "HTTP/1.1 200 OK\r\n"
2008 "Server: winetest\r\n"
2009 "\r\n";
2011 static const char notokmsg[] =
2012 "HTTP/1.1 400 Bad Request\r\n"
2013 "\r\n";
2015 static const char cookiemsg[] =
2016 "HTTP/1.1 200 OK\r\n"
2017 "Set-Cookie: name = value \r\n"
2018 "Set-Cookie: NAME = value \r\n"
2019 "\r\n";
2021 static const char cookiemsg2[] =
2022 "HTTP/1.1 200 OK\r\n"
2023 "Set-Cookie: name2=value; Domain = localhost; Path=/cookie5;Expires=Wed, 13 Jan 2021 22:23:01 GMT; HttpOnly; \r\n"
2024 "\r\n";
2026 static const char nocontentmsg[] =
2027 "HTTP/1.1 204 No Content\r\n"
2028 "Server: winetest\r\n"
2029 "\r\n";
2031 static const char notmodified[] =
2032 "HTTP/1.1 304 Not Modified\r\n"
2033 "\r\n";
2035 static const char noauthmsg[] =
2036 "HTTP/1.1 401 Unauthorized\r\n"
2037 "Server: winetest\r\n"
2038 "Connection: close\r\n"
2039 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
2040 "Content-Length: 12\r\n"
2041 "Content-Type: text/plain\r\n"
2042 "\r\n";
2044 static const char okauthmsg[] =
2045 "HTTP/1.1 200 OK\r\n"
2046 "Server: winetest\r\n"
2047 "Connection: close\r\n"
2048 "Content-Length: 11\r\n"
2049 "Content-Type: text/plain\r\n"
2050 "\r\n";
2052 static const char headmsg[] =
2053 "HTTP/1.1 200 OK\r\n"
2054 "Content-Length: 100\r\n"
2055 "\r\n";
2057 static const char multiauth[] =
2058 "HTTP/1.1 401 Unauthorized\r\n"
2059 "Server: winetest\r\n"
2060 "WWW-Authenticate: Bearer\r\n"
2061 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
2062 "WWW-Authenticate: NTLM\r\n"
2063 "Content-Length: 10\r\n"
2064 "Content-Type: text/plain\r\n"
2065 "\r\n";
2067 static const char largeauth[] =
2068 "HTTP/1.1 401 Unauthorized\r\n"
2069 "Server: winetest\r\n"
2070 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
2071 "WWW-Authenticate: NTLM\r\n"
2072 "Content-Length: 10240\r\n"
2073 "Content-Type: text/plain\r\n"
2074 "\r\n";
2076 static const char unauthorized[] = "Unauthorized";
2077 static const char hello_world[] = "Hello World";
2079 struct server_info
2081 HANDLE event;
2082 int port;
2085 #define BIG_BUFFER_LEN 0x2250
2087 static DWORD CALLBACK server_thread(LPVOID param)
2089 struct server_info *si = param;
2090 int r, c = -1, i, on;
2091 SOCKET s;
2092 struct sockaddr_in sa;
2093 char buffer[0x100];
2094 WSADATA wsaData;
2095 int last_request = 0;
2097 WSAStartup(MAKEWORD(1,1), &wsaData);
2099 s = socket(AF_INET, SOCK_STREAM, 0);
2100 if (s == INVALID_SOCKET)
2101 return 1;
2103 on = 1;
2104 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof on);
2106 memset(&sa, 0, sizeof sa);
2107 sa.sin_family = AF_INET;
2108 sa.sin_port = htons(si->port);
2109 sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
2111 r = bind(s, (struct sockaddr *)&sa, sizeof(sa));
2112 if (r < 0)
2113 return 1;
2115 listen(s, 0);
2116 SetEvent(si->event);
2119 if (c == -1) c = accept(s, NULL, NULL);
2121 memset(buffer, 0, sizeof buffer);
2122 for(i = 0; i < sizeof buffer - 1; i++)
2124 r = recv(c, &buffer[i], 1, 0);
2125 if (r != 1)
2126 break;
2127 if (i < 4) continue;
2128 if (buffer[i - 2] == '\n' && buffer[i] == '\n' &&
2129 buffer[i - 3] == '\r' && buffer[i - 1] == '\r')
2130 break;
2132 if (strstr(buffer, "GET /basic"))
2134 send(c, okmsg, sizeof okmsg - 1, 0);
2135 send(c, page1, sizeof page1 - 1, 0);
2137 if (strstr(buffer, "/auth"))
2139 if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
2141 send(c, okauthmsg, sizeof okauthmsg - 1, 0);
2142 send(c, hello_world, sizeof hello_world - 1, 0);
2144 else
2146 send(c, noauthmsg, sizeof noauthmsg - 1, 0);
2147 send(c, unauthorized, sizeof unauthorized - 1, 0);
2149 continue;
2151 if (strstr(buffer, "/big"))
2153 char msg[BIG_BUFFER_LEN];
2154 memset(msg, 'm', sizeof(msg));
2155 send(c, okmsg, sizeof(okmsg) - 1, 0);
2156 send(c, msg, sizeof(msg), 0);
2158 if (strstr(buffer, "/no_headers"))
2160 send(c, page1, sizeof page1 - 1, 0);
2162 if (strstr(buffer, "GET /no_content"))
2164 send(c, nocontentmsg, sizeof nocontentmsg - 1, 0);
2165 continue;
2167 if (strstr(buffer, "GET /not_modified"))
2169 if (strstr(buffer, "If-Modified-Since:")) send(c, notmodified, sizeof notmodified - 1, 0);
2170 else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2171 continue;
2173 if (strstr(buffer, "HEAD /head"))
2175 send(c, headmsg, sizeof headmsg - 1, 0);
2176 continue;
2178 if (strstr(buffer, "GET /multiauth"))
2180 send(c, multiauth, sizeof multiauth - 1, 0);
2182 if (strstr(buffer, "GET /largeauth"))
2184 if (strstr(buffer, "Authorization: NTLM"))
2185 send(c, okmsg, sizeof(okmsg) - 1, 0);
2186 else
2188 send(c, largeauth, sizeof largeauth - 1, 0);
2189 for (i = 0; i < 10240; i++) send(c, "A", 1, 0);
2190 continue;
2193 if (strstr(buffer, "GET /cookie5"))
2195 if (strstr(buffer, "Cookie: name2=value\r\n"))
2196 send(c, okmsg, sizeof(okmsg) - 1, 0);
2197 else
2198 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2200 if (strstr(buffer, "GET /cookie4"))
2202 send(c, cookiemsg2, sizeof(cookiemsg2) - 1, 0);
2204 if (strstr(buffer, "GET /cookie3"))
2206 if (strstr(buffer, "Cookie: name=value2; NAME=value; name=value\r\n") ||
2207 broken(strstr(buffer, "Cookie: name=value2; name=value; NAME=value\r\n") != NULL))
2208 send(c, okmsg, sizeof(okmsg) - 1, 0);
2209 else
2210 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2212 if (strstr(buffer, "GET /cookie2"))
2214 if (strstr(buffer, "Cookie: NAME=value; name=value\r\n") ||
2215 broken(strstr(buffer, "Cookie: name=value; NAME=value\r\n") != NULL))
2216 send(c, okmsg, sizeof(okmsg) - 1, 0);
2217 else
2218 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2220 else if (strstr(buffer, "GET /cookie"))
2222 if (!strstr(buffer, "Cookie: name=value\r\n")) send(c, cookiemsg, sizeof(cookiemsg) - 1, 0);
2223 else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2225 if (strstr(buffer, "GET /quit"))
2227 send(c, okmsg, sizeof okmsg - 1, 0);
2228 send(c, page1, sizeof page1 - 1, 0);
2229 last_request = 1;
2231 shutdown(c, 2);
2232 closesocket(c);
2233 c = -1;
2235 } while (!last_request);
2237 closesocket(s);
2238 return 0;
2241 static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path)
2243 static const WCHAR test_header_end_clrf[] = {'\r','\n','\r','\n',0};
2244 static const WCHAR test_header_end_raw[] = {0,0};
2245 HINTERNET ses, con, req;
2246 char buffer[0x100];
2247 WCHAR buffer2[0x100];
2248 DWORD count, status, size, error, supported, first, target;
2249 BOOL ret;
2251 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2252 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2254 con = WinHttpConnect(ses, localhostW, port, 0);
2255 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2257 req = WinHttpOpenRequest(con, verb, path, NULL, NULL, NULL, 0);
2258 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2260 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2261 ok(ret, "failed to send request %u\n", GetLastError());
2263 ret = WinHttpReceiveResponse(req, NULL);
2264 ok(ret, "failed to receive response %u\n", GetLastError());
2266 status = 0xdeadbeef;
2267 size = sizeof(status);
2268 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2269 ok(ret, "failed to query status code %u\n", GetLastError());
2270 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2272 supported = first = target = 0xdeadbeef;
2273 SetLastError(0xdeadbeef);
2274 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2275 error = GetLastError();
2276 ok(!ret, "unexpected success\n");
2277 todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
2278 ok(supported == 0xdeadbeef, "got %x\n", supported);
2279 ok(first == 0xdeadbeef, "got %x\n", first);
2280 ok(target == 0xdeadbeef, "got %x\n", target);
2282 size = sizeof(buffer2);
2283 memset(buffer2, 0, sizeof(buffer2));
2284 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, buffer2, &size, NULL);
2285 ok(ret, "failed to query for raw headers: %u\n", GetLastError());
2286 ok(!memcmp(buffer2 + lstrlenW(buffer2) - 4, test_header_end_clrf, sizeof(test_header_end_clrf)),
2287 "WinHttpQueryHeaders returned invalid end of header string\n");
2289 size = sizeof(buffer2);
2290 memset(buffer2, 0, sizeof(buffer2));
2291 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS, NULL, buffer2, &size, NULL);
2292 ok(ret, "failed to query for raw headers: %u\n", GetLastError());
2293 ok(!memcmp(buffer2 + (size / sizeof(WCHAR)) - 1, test_header_end_raw, sizeof(test_header_end_raw)),
2294 "WinHttpQueryHeaders returned invalid end of header string\n");
2295 ok(buffer2[(size / sizeof(WCHAR)) - 2] != 0, "returned string has too many NULL characters\n");
2297 count = 0;
2298 memset(buffer, 0, sizeof(buffer));
2299 ret = WinHttpReadData(req, buffer, sizeof buffer, &count);
2300 ok(ret, "failed to read data %u\n", GetLastError());
2301 ok(count == sizeof page1 - 1, "count was wrong\n");
2302 ok(!memcmp(buffer, page1, sizeof page1), "http data wrong\n");
2304 WinHttpCloseHandle(req);
2305 WinHttpCloseHandle(con);
2306 WinHttpCloseHandle(ses);
2309 static void test_basic_authentication(int port)
2311 static const WCHAR authW[] = {'/','a','u','t','h',0};
2312 static WCHAR userW[] = {'u','s','e','r',0};
2313 static WCHAR passW[] = {'p','w','d',0};
2314 static WCHAR pass2W[] = {'p','w','d','2',0};
2315 HINTERNET ses, con, req;
2316 DWORD status, size, error, supported, first, target;
2317 char buffer[32];
2318 BOOL ret;
2320 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2321 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2323 con = WinHttpConnect(ses, localhostW, port, 0);
2324 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2326 req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2327 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2329 SetLastError(0xdeadbeef);
2330 ret = WinHttpQueryAuthSchemes(NULL, NULL, NULL, NULL);
2331 error = GetLastError();
2332 ok(!ret, "expected failure\n");
2333 ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
2335 SetLastError(0xdeadbeef);
2336 ret = WinHttpQueryAuthSchemes(req, NULL, NULL, NULL);
2337 error = GetLastError();
2338 ok(!ret, "expected failure\n");
2339 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2341 supported = 0xdeadbeef;
2342 SetLastError(0xdeadbeef);
2343 ret = WinHttpQueryAuthSchemes(req, &supported, NULL, NULL);
2344 error = GetLastError();
2345 ok(!ret, "expected failure\n");
2346 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2347 ok(supported == 0xdeadbeef, "got %x\n", supported);
2349 supported = first = 0xdeadbeef;
2350 SetLastError(0xdeadbeef);
2351 ret = WinHttpQueryAuthSchemes(req, &supported, &first, NULL);
2352 error = GetLastError();
2353 ok(!ret, "expected failure\n");
2354 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2355 ok(supported == 0xdeadbeef, "got %x\n", supported);
2356 ok(first == 0xdeadbeef, "got %x\n", first);
2358 supported = first = target = 0xdeadbeef;
2359 SetLastError(0xdeadbeef);
2360 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2361 error = GetLastError();
2362 ok(!ret, "expected failure\n");
2363 todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
2364 ok(supported == 0xdeadbeef, "got %x\n", supported);
2365 ok(first == 0xdeadbeef, "got %x\n", first);
2366 ok(target == 0xdeadbeef, "got %x\n", target);
2368 supported = first = target = 0xdeadbeef;
2369 SetLastError(0xdeadbeef);
2370 ret = WinHttpQueryAuthSchemes(NULL, &supported, &first, &target);
2371 error = GetLastError();
2372 ok(!ret, "expected failure\n");
2373 ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
2374 ok(supported == 0xdeadbeef, "got %x\n", supported);
2375 ok(first == 0xdeadbeef, "got %x\n", first);
2376 ok(target == 0xdeadbeef, "got %x\n", target);
2378 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2379 ok(ret, "failed to send request %u\n", GetLastError());
2381 ret = WinHttpReceiveResponse(req, NULL);
2382 ok(ret, "failed to receive response %u\n", GetLastError());
2384 status = 0xdeadbeef;
2385 size = sizeof(status);
2386 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2387 ok(ret, "failed to query status code %u\n", GetLastError());
2388 ok(status == HTTP_STATUS_DENIED, "request failed unexpectedly %u\n", status);
2390 size = 0;
2391 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
2392 error = GetLastError();
2393 ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError());
2394 if (ret)
2396 ok(size == 12, "expected 12, got %u\n", size);
2397 ok(!memcmp(buffer, unauthorized, 12), "got %s\n", buffer);
2400 supported = first = target = 0xdeadbeef;
2401 SetLastError(0xdeadbeef);
2402 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2403 error = GetLastError();
2404 ok(ret, "failed to query authentication schemes %u\n", error);
2405 ok(error == ERROR_SUCCESS || broken(error == 0xdeadbeef) /* < win7 */, "expected ERROR_SUCCESS, got %u\n", error);
2406 ok(supported == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", supported);
2407 ok(first == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", first);
2408 ok(target == WINHTTP_AUTH_TARGET_SERVER, "got %x\n", target);
2410 SetLastError(0xdeadbeef);
2411 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NTLM, NULL, NULL, NULL);
2412 error = GetLastError();
2413 ok(ret, "failed to set credentials %u\n", error);
2414 ok(error == ERROR_SUCCESS || broken(error == 0xdeadbeef) /* < win7 */, "expected ERROR_SUCCESS, got %u\n", error);
2416 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_PASSPORT, NULL, NULL, NULL);
2417 ok(ret, "failed to set credentials %u\n", GetLastError());
2419 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NEGOTIATE, NULL, NULL, NULL);
2420 ok(ret, "failed to set credentials %u\n", GetLastError());
2422 SetLastError(0xdeadbeef);
2423 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_DIGEST, NULL, NULL, NULL);
2424 error = GetLastError();
2425 ok(!ret, "expected failure\n");
2426 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2428 SetLastError(0xdeadbeef);
2429 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, NULL, NULL);
2430 error = GetLastError();
2431 ok(!ret, "expected failure\n");
2432 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2434 SetLastError(0xdeadbeef);
2435 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, NULL, NULL);
2436 error = GetLastError();
2437 ok(!ret, "expected failure\n");
2438 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2440 SetLastError(0xdeadbeef);
2441 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, passW, NULL);
2442 error = GetLastError();
2443 ok(!ret, "expected failure\n");
2444 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2446 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
2447 ok(ret, "failed to set credentials %u\n", GetLastError());
2449 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2450 ok(ret, "failed to send request %u\n", GetLastError());
2452 ret = WinHttpReceiveResponse(req, NULL);
2453 ok(ret, "failed to receive response %u\n", GetLastError());
2455 status = 0xdeadbeef;
2456 size = sizeof(status);
2457 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2458 ok(ret, "failed to query status code %u\n", GetLastError());
2459 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2461 size = 0;
2462 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
2463 error = GetLastError();
2464 ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError());
2465 if (ret)
2467 ok(size == 11, "expected 11, got %u\n", size);
2468 ok(!memcmp(buffer, hello_world, 11), "got %s\n", buffer);
2471 WinHttpCloseHandle(req);
2472 WinHttpCloseHandle(con);
2473 WinHttpCloseHandle(ses);
2475 /* credentials set with WinHttpSetCredentials take precedence over those set through options */
2477 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2478 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2480 con = WinHttpConnect(ses, localhostW, port, 0);
2481 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2483 req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2484 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2486 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
2487 ok(ret, "failed to set credentials %u\n", GetLastError());
2489 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
2490 ok(ret, "failed to set username %u\n", GetLastError());
2492 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, pass2W, lstrlenW(pass2W));
2493 ok(ret, "failed to set password %u\n", GetLastError());
2495 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2496 ok(ret, "failed to send request %u\n", GetLastError());
2498 ret = WinHttpReceiveResponse(req, NULL);
2499 ok(ret, "failed to receive response %u\n", GetLastError());
2501 status = 0xdeadbeef;
2502 size = sizeof(status);
2503 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2504 ok(ret, "failed to query status code %u\n", GetLastError());
2505 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2507 WinHttpCloseHandle(req);
2508 WinHttpCloseHandle(con);
2509 WinHttpCloseHandle(ses);
2511 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2512 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2514 con = WinHttpConnect(ses, localhostW, port, 0);
2515 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2517 req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2518 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2520 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
2521 ok(ret, "failed to set username %u\n", GetLastError());
2523 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, passW, lstrlenW(passW));
2524 ok(ret, "failed to set password %u\n", GetLastError());
2526 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, pass2W, NULL);
2527 ok(ret, "failed to set credentials %u\n", GetLastError());
2529 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2530 ok(ret, "failed to send request %u\n", GetLastError());
2532 ret = WinHttpReceiveResponse(req, NULL);
2533 ok(ret, "failed to receive response %u\n", GetLastError());
2535 status = 0xdeadbeef;
2536 size = sizeof(status);
2537 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2538 ok(ret, "failed to query status code %u\n", GetLastError());
2539 ok(status == HTTP_STATUS_DENIED, "request failed unexpectedly %u\n", status);
2541 WinHttpCloseHandle(req);
2542 WinHttpCloseHandle(con);
2543 WinHttpCloseHandle(ses);
2546 static void test_multi_authentication(int port)
2548 static const WCHAR multiauthW[] = {'/','m','u','l','t','i','a','u','t','h',0};
2549 static const WCHAR getW[] = {'G','E','T',0};
2550 HINTERNET ses, con, req;
2551 DWORD supported, first, target;
2552 BOOL ret;
2554 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2555 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2557 con = WinHttpConnect(ses, localhostW, port, 0);
2558 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2560 req = WinHttpOpenRequest(con, getW, multiauthW, NULL, NULL, NULL, 0);
2561 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2563 ret = WinHttpSendRequest(req, WINHTTP_NO_ADDITIONAL_HEADERS, 0,
2564 WINHTTP_NO_REQUEST_DATA,0, 0, 0 );
2565 ok(ret, "expected success\n");
2567 ret = WinHttpReceiveResponse(req, NULL);
2568 ok(ret, "expected success\n");
2570 supported = first = target = 0xdeadbeef;
2571 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2572 ok(ret, "expected success\n");
2573 ok(supported == (WINHTTP_AUTH_SCHEME_BASIC | WINHTTP_AUTH_SCHEME_NTLM), "got %x\n", supported);
2574 ok(target == WINHTTP_AUTH_TARGET_SERVER, "got %x\n", target);
2575 ok(first == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", first);
2577 WinHttpCloseHandle(req);
2578 WinHttpCloseHandle(con);
2579 WinHttpCloseHandle(ses);
2582 static void test_large_data_authentication(int port)
2584 static const WCHAR largeauthW[] = {'/','l','a','r','g','e','a','u','t','h',0};
2585 static const WCHAR getW[] = {'G','E','T',0};
2586 static WCHAR userW[] = {'u','s','e','r',0};
2587 static WCHAR passW[] = {'p','w','d',0};
2588 HINTERNET ses, con, req;
2589 DWORD status, size;
2590 BOOL ret;
2592 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2593 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2595 con = WinHttpConnect(ses, localhostW, port, 0);
2596 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2598 req = WinHttpOpenRequest(con, getW, largeauthW, NULL, NULL, NULL, 0);
2599 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2601 ret = WinHttpSendRequest(req, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
2602 ok(ret, "expected success\n");
2604 ret = WinHttpReceiveResponse(req, NULL);
2605 ok(ret, "expected success\n");
2607 size = sizeof(status);
2608 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL,
2609 &status, &size, NULL);
2610 ok(ret, "expected success\n");
2611 ok(status == HTTP_STATUS_DENIED, "got %d\n", status);
2613 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NTLM, userW, passW, NULL);
2614 ok(ret, "expected success\n");
2616 ret = WinHttpSendRequest(req, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
2617 ok(ret, "expected success %d\n", GetLastError());
2619 ret = WinHttpReceiveResponse(req, NULL);
2620 ok(ret, "expected success\n");
2622 size = sizeof(status);
2623 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL,
2624 &status, &size, NULL);
2625 ok(ret, "expected success\n");
2626 ok(status == HTTP_STATUS_OK, "got %d\n", status);
2628 WinHttpCloseHandle(req);
2629 WinHttpCloseHandle(con);
2630 WinHttpCloseHandle(ses);
2633 static void test_no_headers(int port)
2635 static const WCHAR no_headersW[] = {'/','n','o','_','h','e','a','d','e','r','s',0};
2636 HINTERNET ses, con, req;
2637 DWORD error;
2638 BOOL ret;
2640 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2641 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2643 con = WinHttpConnect(ses, localhostW, port, 0);
2644 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2646 req = WinHttpOpenRequest(con, NULL, no_headersW, NULL, NULL, NULL, 0);
2647 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2649 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2650 if (!ret)
2652 error = GetLastError();
2653 ok(error == ERROR_WINHTTP_INVALID_SERVER_RESPONSE, "got %u\n", error);
2655 else
2657 SetLastError(0xdeadbeef);
2658 ret = WinHttpReceiveResponse(req, NULL);
2659 error = GetLastError();
2660 ok(!ret, "expected failure\n");
2661 ok(error == ERROR_WINHTTP_INVALID_SERVER_RESPONSE, "got %u\n", error);
2664 WinHttpCloseHandle(req);
2665 WinHttpCloseHandle(con);
2666 WinHttpCloseHandle(ses);
2669 static void test_no_content(int port)
2671 static const WCHAR no_contentW[] = {'/','n','o','_','c','o','n','t','e','n','t',0};
2672 HINTERNET ses, con, req;
2673 char buf[128];
2674 DWORD size, len = sizeof(buf), bytes_read, status;
2675 BOOL ret;
2677 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2678 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2680 con = WinHttpConnect(ses, localhostW, port, 0);
2681 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2683 req = WinHttpOpenRequest(con, NULL, no_contentW, NULL, NULL, NULL, 0);
2684 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2686 size = 12345;
2687 SetLastError(0xdeadbeef);
2688 ret = WinHttpQueryDataAvailable(req, &size);
2689 todo_wine {
2690 ok(!ret, "expected error\n");
2691 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_STATE,
2692 "expected ERROR_WINHTTP_INCORRECT_HANDLE_STATE, got 0x%08x\n", GetLastError());
2693 ok(size == 12345 || broken(size == 0) /* Win <= 2003 */,
2694 "expected 12345, got %u\n", size);
2697 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2698 ok(ret, "expected success\n");
2700 ret = WinHttpReceiveResponse(req, NULL);
2701 ok(ret, "expected success\n");
2703 status = 0xdeadbeef;
2704 size = sizeof(status);
2705 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
2706 NULL, &status, &size, NULL);
2707 ok(ret, "expected success\n");
2708 ok(status == HTTP_STATUS_NO_CONTENT, "expected status 204, got %d\n", status);
2710 SetLastError(0xdeadbeef);
2711 size = sizeof(status);
2712 status = 12345;
2713 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
2714 NULL, &status, &size, 0);
2715 ok(!ret, "expected no content-length header\n");
2716 ok(GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND, "wrong error %u\n", GetLastError());
2717 ok(status == 12345, "expected 0, got %d\n", status);
2719 SetLastError(0xdeadbeef);
2720 size = 12345;
2721 ret = WinHttpQueryDataAvailable(req, &size);
2722 ok(ret, "expected success\n");
2723 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
2724 "wrong error %u\n", GetLastError());
2725 ok(!size, "expected 0, got %u\n", size);
2727 SetLastError(0xdeadbeef);
2728 ret = WinHttpReadData(req, buf, len, &bytes_read);
2729 ok(ret, "expected success\n");
2730 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
2731 "wrong error %u\n", GetLastError());
2732 ok(!bytes_read, "expected 0, got %u\n", bytes_read);
2734 size = 12345;
2735 ret = WinHttpQueryDataAvailable(req, &size);
2736 ok(ret, "expected success\n");
2737 ok(size == 0, "expected 0, got %d\n", size);
2739 WinHttpCloseHandle(req);
2741 size = 12345;
2742 SetLastError(0xdeadbeef);
2743 ret = WinHttpQueryDataAvailable(req, &size);
2744 ok(!ret, "expected error\n");
2745 ok(GetLastError() == ERROR_INVALID_HANDLE,
2746 "expected ERROR_INVALID_HANDLE, got 0x%08x\n", GetLastError());
2747 ok(size == 12345, "expected 12345, got %u\n", size);
2749 WinHttpCloseHandle(con);
2750 WinHttpCloseHandle(ses);
2753 static void test_head_request(int port)
2755 static const WCHAR verbW[] = {'H','E','A','D',0};
2756 static const WCHAR headW[] = {'/','h','e','a','d',0};
2757 HINTERNET ses, con, req;
2758 char buf[128];
2759 DWORD size, len, count, status;
2760 BOOL ret;
2762 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2763 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2765 con = WinHttpConnect(ses, localhostW, port, 0);
2766 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2768 req = WinHttpOpenRequest(con, verbW, headW, NULL, NULL, NULL, 0);
2769 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2771 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2772 ok(ret, "failed to send request %u\n", GetLastError());
2774 ret = WinHttpReceiveResponse(req, NULL);
2775 ok(ret, "failed to receive response %u\n", GetLastError());
2777 status = 0xdeadbeef;
2778 size = sizeof(status);
2779 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
2780 NULL, &status, &size, NULL);
2781 ok(ret, "failed to get status code %u\n", GetLastError());
2782 ok(status == HTTP_STATUS_OK, "got %u\n", status);
2784 len = 0xdeadbeef;
2785 size = sizeof(len);
2786 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
2787 NULL, &len, &size, 0);
2788 ok(ret, "failed to get content-length header %u\n", GetLastError());
2789 ok(len == HTTP_STATUS_CONTINUE, "got %u\n", len);
2791 count = 0xdeadbeef;
2792 ret = WinHttpQueryDataAvailable(req, &count);
2793 ok(ret, "failed to query data available %u\n", GetLastError());
2794 ok(!count, "got %u\n", count);
2796 len = sizeof(buf);
2797 count = 0xdeadbeef;
2798 ret = WinHttpReadData(req, buf, len, &count);
2799 ok(ret, "failed to read data %u\n", GetLastError());
2800 ok(!count, "got %u\n", count);
2802 count = 0xdeadbeef;
2803 ret = WinHttpQueryDataAvailable(req, &count);
2804 ok(ret, "failed to query data available %u\n", GetLastError());
2805 ok(!count, "got %u\n", count);
2807 WinHttpCloseHandle(req);
2808 WinHttpCloseHandle(con);
2809 WinHttpCloseHandle(ses);
2812 static void test_not_modified(int port)
2814 static const WCHAR pathW[] = {'/','n','o','t','_','m','o','d','i','f','i','e','d',0};
2815 static const WCHAR ifmodifiedW[] = {'I','f','-','M','o','d','i','f','i','e','d','-','S','i','n','c','e',':',' '};
2816 static const WCHAR ifmodified2W[] = {'I','f','-','M','o','d','i','f','i','e','d','-','S','i','n','c','e',0};
2817 BOOL ret;
2818 HINTERNET session, request, connection;
2819 DWORD index, len, status, size, start = GetTickCount();
2820 SYSTEMTIME st;
2821 WCHAR today[(sizeof(ifmodifiedW) + WINHTTP_TIME_FORMAT_BUFSIZE)/sizeof(WCHAR) + 3], buffer[32];
2823 memcpy(today, ifmodifiedW, sizeof(ifmodifiedW));
2824 GetSystemTime(&st);
2825 WinHttpTimeFromSystemTime(&st, &today[sizeof(ifmodifiedW)/sizeof(WCHAR)]);
2827 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY,
2828 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
2829 ok(session != NULL, "WinHttpOpen failed: %u\n", GetLastError());
2831 connection = WinHttpConnect(session, localhostW, port, 0);
2832 ok(connection != NULL, "WinHttpConnect failed: %u\n", GetLastError());
2834 request = WinHttpOpenRequest(connection, NULL, pathW, NULL, WINHTTP_NO_REFERER,
2835 WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
2836 ok(request != NULL, "WinHttpOpenrequest failed: %u\n", GetLastError());
2838 ret = WinHttpSendRequest(request, today, 0, NULL, 0, 0, 0);
2839 ok(ret, "WinHttpSendRequest failed: %u\n", GetLastError());
2841 ret = WinHttpReceiveResponse(request, NULL);
2842 ok(ret, "WinHttpReceiveResponse failed: %u\n", GetLastError());
2844 index = 0;
2845 len = sizeof(buffer);
2846 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
2847 ifmodified2W, buffer, &len, &index);
2848 ok(ret, "failed to get header %u\n", GetLastError());
2850 status = 0xdeadbeef;
2851 size = sizeof(status);
2852 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER,
2853 NULL, &status, &size, NULL);
2854 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
2855 ok(status == HTTP_STATUS_NOT_MODIFIED, "got %u\n", status);
2857 size = 0xdeadbeef;
2858 ret = WinHttpQueryDataAvailable(request, &size);
2859 ok(ret, "WinHttpQueryDataAvailable failed: %u\n", GetLastError());
2860 ok(!size, "got %u\n", size);
2862 WinHttpCloseHandle(request);
2863 WinHttpCloseHandle(connection);
2864 WinHttpCloseHandle(session);
2865 start = GetTickCount() - start;
2866 ok(start <= 2000, "Expected less than 2 seconds for the test, got %u ms\n", start);
2869 static void test_bad_header( int port )
2871 static const WCHAR bad_headerW[] =
2872 {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ',
2873 't','e','x','t','/','h','t','m','l','\n','\r',0};
2874 static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
2875 static const WCHAR content_typeW[] = {'C','o','n','t','e','n','t','-','T','y','p','e',0};
2876 WCHAR buffer[32];
2877 HINTERNET ses, con, req;
2878 DWORD index, len;
2879 BOOL ret;
2881 ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
2882 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
2884 con = WinHttpConnect( ses, localhostW, port, 0 );
2885 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2887 req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
2888 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2890 ret = WinHttpAddRequestHeaders( req, bad_headerW, ~0u, WINHTTP_ADDREQ_FLAG_ADD );
2891 ok( ret, "failed to add header %u\n", GetLastError() );
2893 index = 0;
2894 buffer[0] = 0;
2895 len = sizeof(buffer);
2896 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_CUSTOM|WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
2897 content_typeW, buffer, &len, &index );
2898 ok( ret, "failed to query headers %u\n", GetLastError() );
2899 ok( !lstrcmpW( buffer, text_htmlW ), "got %s\n", wine_dbgstr_w(buffer) );
2901 WinHttpCloseHandle( req );
2902 WinHttpCloseHandle( con );
2903 WinHttpCloseHandle( ses );
2906 static void test_multiple_reads(int port)
2908 static const WCHAR bigW[] = {'b','i','g',0};
2909 HINTERNET ses, con, req;
2910 DWORD total_len = 0;
2911 BOOL ret;
2913 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2914 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2916 con = WinHttpConnect(ses, localhostW, port, 0);
2917 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2919 req = WinHttpOpenRequest(con, NULL, bigW, NULL, NULL, NULL, 0);
2920 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2922 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2923 ok(ret, "failed to send request %u\n", GetLastError());
2925 ret = WinHttpReceiveResponse(req, NULL);
2926 ok(ret == TRUE, "expected success\n");
2928 for (;;)
2930 DWORD len = 0xdeadbeef;
2931 ret = WinHttpQueryDataAvailable( req, &len );
2932 ok( ret, "WinHttpQueryDataAvailable failed with error %u\n", GetLastError() );
2933 if (ret) ok( len != 0xdeadbeef, "WinHttpQueryDataAvailable return wrong length\n" );
2934 if (len)
2936 DWORD bytes_read;
2937 char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 );
2939 ret = WinHttpReadData( req, buf, len, &bytes_read );
2940 ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len );
2942 HeapFree( GetProcessHeap(), 0, buf );
2943 if (!bytes_read) break;
2944 total_len += bytes_read;
2946 if (!len) break;
2948 ok(total_len == BIG_BUFFER_LEN, "got wrong length: 0x%x\n", total_len);
2950 WinHttpCloseHandle(req);
2951 WinHttpCloseHandle(con);
2952 WinHttpCloseHandle(ses);
2955 static void test_cookies( int port )
2957 static const WCHAR cookieW[] = {'/','c','o','o','k','i','e',0};
2958 static const WCHAR cookie2W[] = {'/','c','o','o','k','i','e','2',0};
2959 static const WCHAR cookie3W[] = {'/','c','o','o','k','i','e','3',0};
2960 static const WCHAR cookie4W[] = {'/','c','o','o','k','i','e','4',0};
2961 static const WCHAR cookie5W[] = {'/','c','o','o','k','i','e','5',0};
2962 static const WCHAR cookieheaderW[] =
2963 {'C','o','o','k','i','e',':',' ','n','a','m','e','=','v','a','l','u','e','2','\r','\n',0};
2964 HINTERNET ses, con, req;
2965 DWORD status, size;
2966 BOOL ret;
2968 ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
2969 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
2971 con = WinHttpConnect( ses, localhostW, port, 0 );
2972 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2974 req = WinHttpOpenRequest( con, NULL, cookieW, NULL, NULL, NULL, 0 );
2975 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2977 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2978 ok( ret, "failed to send request %u\n", GetLastError() );
2980 ret = WinHttpReceiveResponse( req, NULL );
2981 ok( ret, "failed to receive response %u\n", GetLastError() );
2983 status = 0xdeadbeef;
2984 size = sizeof(status);
2985 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
2986 ok( ret, "failed to query status code %u\n", GetLastError() );
2987 ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
2989 WinHttpCloseHandle( req );
2991 req = WinHttpOpenRequest( con, NULL, cookie2W, NULL, NULL, NULL, 0 );
2992 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2994 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2995 ok( ret, "failed to send request %u\n", GetLastError() );
2997 ret = WinHttpReceiveResponse( req, NULL );
2998 ok( ret, "failed to receive response %u\n", GetLastError() );
3000 status = 0xdeadbeef;
3001 size = sizeof(status);
3002 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3003 ok( ret, "failed to query status code %u\n", GetLastError() );
3004 ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
3006 WinHttpCloseHandle( req );
3007 WinHttpCloseHandle( con );
3009 con = WinHttpConnect( ses, localhostW, port, 0 );
3010 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3012 req = WinHttpOpenRequest( con, NULL, cookie2W, NULL, NULL, NULL, 0 );
3013 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3015 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3016 ok( ret, "failed to send request %u\n", GetLastError() );
3018 ret = WinHttpReceiveResponse( req, NULL );
3019 ok( ret, "failed to receive response %u\n", GetLastError() );
3021 status = 0xdeadbeef;
3022 size = sizeof(status);
3023 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3024 ok( ret, "failed to query status code %u\n", GetLastError() );
3025 ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
3027 WinHttpCloseHandle( req );
3029 req = WinHttpOpenRequest( con, NULL, cookie3W, NULL, NULL, NULL, 0 );
3030 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3032 ret = WinHttpSendRequest( req, cookieheaderW, ~0u, NULL, 0, 0, 0 );
3033 ok( ret, "failed to send request %u\n", GetLastError() );
3035 ret = WinHttpReceiveResponse( req, NULL );
3036 ok( ret, "failed to receive response %u\n", GetLastError() );
3038 status = 0xdeadbeef;
3039 size = sizeof(status);
3040 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3041 ok( ret, "failed to query status code %u\n", GetLastError() );
3042 ok( status == HTTP_STATUS_OK || broken(status == HTTP_STATUS_BAD_REQUEST), "request failed unexpectedly %u\n", status );
3044 WinHttpCloseHandle( req );
3045 WinHttpCloseHandle( con );
3046 WinHttpCloseHandle( ses );
3048 ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3049 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3051 con = WinHttpConnect( ses, localhostW, port, 0 );
3052 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3054 req = WinHttpOpenRequest( con, NULL, cookie2W, 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, NULL, &status, &size, NULL );
3066 ok( ret, "failed to query status code %u\n", GetLastError() );
3067 ok( status == HTTP_STATUS_BAD_REQUEST, "request failed unexpectedly %u\n", status );
3069 WinHttpCloseHandle( req );
3070 WinHttpCloseHandle( con );
3071 WinHttpCloseHandle( ses );
3073 ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3074 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3076 con = WinHttpConnect( ses, localhostW, port, 0 );
3077 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3079 req = WinHttpOpenRequest( con, NULL, cookie4W, NULL, NULL, NULL, 0 );
3080 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3082 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3083 ok( ret, "failed to send request %u\n", GetLastError() );
3085 ret = WinHttpReceiveResponse( req, NULL );
3086 ok( ret, "failed to receive response %u\n", GetLastError() );
3088 status = 0xdeadbeef;
3089 size = sizeof(status);
3090 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3091 ok( ret, "failed to query status code %u\n", GetLastError() );
3092 ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
3093 WinHttpCloseHandle( req );
3095 req = WinHttpOpenRequest( con, NULL, cookie5W, NULL, NULL, NULL, 0 );
3096 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3098 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3099 ok( ret, "failed to send request %u\n", GetLastError() );
3101 ret = WinHttpReceiveResponse( req, NULL );
3102 ok( ret, "failed to receive response %u\n", GetLastError() );
3104 status = 0xdeadbeef;
3105 size = sizeof(status);
3106 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3107 ok( ret, "failed to query status code %u\n", GetLastError() );
3108 ok( status == HTTP_STATUS_OK || broken(status == HTTP_STATUS_BAD_REQUEST) /* < win7 */,
3109 "request failed unexpectedly %u\n", status );
3111 WinHttpCloseHandle( req );
3112 WinHttpCloseHandle( con );
3113 WinHttpCloseHandle( ses );
3116 static void test_connection_info( int port )
3118 static const WCHAR basicW[] = {'/','b','a','s','i','c',0};
3119 HINTERNET ses, con, req;
3120 WINHTTP_CONNECTION_INFO info;
3121 DWORD size, error;
3122 BOOL ret;
3124 ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3125 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3127 con = WinHttpConnect( ses, localhostW, port, 0 );
3128 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3130 req = WinHttpOpenRequest( con, NULL, basicW, NULL, NULL, NULL, 0 );
3131 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3133 size = sizeof(info);
3134 SetLastError( 0xdeadbeef );
3135 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3136 error = GetLastError();
3137 if (!ret && error == ERROR_INVALID_PARAMETER)
3139 win_skip( "WINHTTP_OPTION_CONNECTION_INFO not supported\n" );
3140 return;
3142 ok( !ret, "unexpected success\n" );
3143 ok( error == ERROR_WINHTTP_INCORRECT_HANDLE_STATE, "got %u\n", error );
3145 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3146 ok( ret, "failed to send request %u\n", GetLastError() );
3148 size = 0;
3149 SetLastError( 0xdeadbeef );
3150 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3151 error = GetLastError();
3152 ok( !ret, "unexpected success\n" );
3153 ok( error == ERROR_INSUFFICIENT_BUFFER, "got %u\n", error );
3155 size = sizeof(info);
3156 memset( &info, 0, sizeof(info) );
3157 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3158 ok( ret, "failed to retrieve connection info %u\n", GetLastError() );
3159 ok( info.cbSize == sizeof(info) || info.cbSize == sizeof(info) - sizeof(info.cbSize) /* Win7 */, "wrong size %u\n", info.cbSize );
3161 ret = WinHttpReceiveResponse( req, NULL );
3162 ok( ret, "failed to receive response %u\n", GetLastError() );
3164 size = sizeof(info);
3165 memset( &info, 0, sizeof(info) );
3166 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3167 ok( ret, "failed to retrieve connection info %u\n", GetLastError() );
3168 ok( info.cbSize == sizeof(info) || info.cbSize == sizeof(info) - sizeof(info.cbSize) /* Win7 */, "wrong size %u\n", info.cbSize );
3170 WinHttpCloseHandle( req );
3171 WinHttpCloseHandle( con );
3172 WinHttpCloseHandle( ses );
3175 static void test_credentials(void)
3177 static WCHAR userW[] = {'u','s','e','r',0};
3178 static WCHAR passW[] = {'p','a','s','s',0};
3179 static WCHAR proxy_userW[] = {'p','r','o','x','y','u','s','e','r',0};
3180 static WCHAR proxy_passW[] = {'p','r','o','x','y','p','a','s','s',0};
3181 HINTERNET ses, con, req;
3182 DWORD size, error;
3183 WCHAR buffer[32];
3184 BOOL ret;
3186 ses = WinHttpOpen(test_useragent, 0, proxy_userW, proxy_passW, 0);
3187 ok(ses != NULL, "failed to open session %u\n", GetLastError());
3189 con = WinHttpConnect(ses, localhostW, 0, 0);
3190 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
3192 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
3193 ok(req != NULL, "failed to open a request %u\n", GetLastError());
3195 size = sizeof(buffer)/sizeof(WCHAR);
3196 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size);
3197 ok(ret, "failed to query proxy username %u\n", GetLastError());
3198 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3199 ok(!size, "expected 0, got %u\n", size);
3201 size = sizeof(buffer)/sizeof(WCHAR);
3202 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size);
3203 ok(ret, "failed to query proxy password %u\n", GetLastError());
3204 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3205 ok(!size, "expected 0, got %u\n", size);
3207 ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_USERNAME, proxy_userW, lstrlenW(proxy_userW));
3208 ok(ret, "failed to set username %u\n", GetLastError());
3210 size = sizeof(buffer)/sizeof(WCHAR);
3211 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size);
3212 ok(ret, "failed to query proxy username %u\n", GetLastError());
3213 ok(!winetest_strcmpW(buffer, proxy_userW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3214 ok(size == lstrlenW(proxy_userW) * sizeof(WCHAR), "unexpected result %u\n", size);
3216 size = sizeof(buffer)/sizeof(WCHAR);
3217 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
3218 ok(ret, "failed to query username %u\n", GetLastError());
3219 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3220 ok(!size, "expected 0, got %u\n", size);
3222 size = sizeof(buffer)/sizeof(WCHAR);
3223 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3224 ok(ret, "failed to query password %u\n", GetLastError());
3225 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3226 ok(!size, "expected 0, got %u\n", size);
3228 ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_PASSWORD, proxy_passW, lstrlenW(proxy_passW));
3229 ok(ret, "failed to set proxy password %u\n", GetLastError());
3231 size = sizeof(buffer)/sizeof(WCHAR);
3232 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size);
3233 ok(ret, "failed to query proxy password %u\n", GetLastError());
3234 ok(!winetest_strcmpW(buffer, proxy_passW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3235 ok(size == lstrlenW(proxy_passW) * sizeof(WCHAR), "unexpected result %u\n", size);
3237 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
3238 ok(ret, "failed to set username %u\n", GetLastError());
3240 size = sizeof(buffer)/sizeof(WCHAR);
3241 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
3242 ok(ret, "failed to query username %u\n", GetLastError());
3243 ok(!winetest_strcmpW(buffer, userW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3244 ok(size == lstrlenW(userW) * sizeof(WCHAR), "unexpected result %u\n", size);
3246 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, passW, lstrlenW(passW));
3247 ok(ret, "failed to set password %u\n", GetLastError());
3249 size = sizeof(buffer)/sizeof(WCHAR);
3250 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3251 ok(ret, "failed to query password %u\n", GetLastError());
3252 ok(!winetest_strcmpW(buffer, passW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3253 ok(size == lstrlenW(passW) * sizeof(WCHAR), "unexpected result %u\n", size);
3255 WinHttpCloseHandle(req);
3257 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
3258 ok(req != NULL, "failed to open a request %u\n", GetLastError());
3260 SetLastError(0xdeadbeef);
3261 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, NULL, NULL);
3262 error = GetLastError();
3263 ok(!ret, "expected failure\n");
3264 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
3266 SetLastError(0xdeadbeef);
3267 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, passW, NULL);
3268 error = GetLastError();
3269 ok(!ret, "expected failure\n");
3270 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
3272 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
3273 ok(ret, "failed to set credentials %u\n", GetLastError());
3275 size = sizeof(buffer)/sizeof(WCHAR);
3276 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
3277 ok(ret, "failed to query username %u\n", GetLastError());
3278 todo_wine {
3279 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3280 ok(!size, "expected 0, got %u\n", size);
3283 size = sizeof(buffer)/sizeof(WCHAR);
3284 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3285 ok(ret, "failed to query password %u\n", GetLastError());
3286 todo_wine {
3287 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3288 ok(!size, "expected 0, got %u\n", size);
3291 WinHttpCloseHandle(req);
3292 WinHttpCloseHandle(con);
3293 WinHttpCloseHandle(ses);
3296 static void test_IWinHttpRequest(int port)
3298 static const WCHAR data_start[] = {'<','!','D','O','C','T','Y','P','E',' ','h','t','m','l',' ','P','U','B','L','I','C'};
3299 static const WCHAR usernameW[] = {'u','s','e','r','n','a','m','e',0};
3300 static const WCHAR passwordW[] = {'p','a','s','s','w','o','r','d',0};
3301 static const WCHAR url1W[] = {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
3302 static const WCHAR url2W[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
3303 static const WCHAR url3W[] = {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.',
3304 'o','r','g','/','t','e','s','t','s','/','p','o','s','t','.','p','h','p',0};
3305 static const WCHAR method1W[] = {'G','E','T',0};
3306 static const WCHAR method2W[] = {'I','N','V','A','L','I','D',0};
3307 static const WCHAR method3W[] = {'P','O','S','T',0};
3308 static const WCHAR proxy_serverW[] = {'p','r','o','x','y','s','e','r','v','e','r',0};
3309 static const WCHAR bypas_listW[] = {'b','y','p','a','s','s','l','i','s','t',0};
3310 static const WCHAR connectionW[] = {'C','o','n','n','e','c','t','i','o','n',0};
3311 static const WCHAR dateW[] = {'D','a','t','e',0};
3312 static const WCHAR test_dataW[] = {'t','e','s','t','d','a','t','a',128,0};
3313 static const WCHAR utf8W[] = {'u','t','f','-','8',0};
3314 static const WCHAR unauthW[] = {'U','n','a','u','t','h','o','r','i','z','e','d',0};
3315 HRESULT hr;
3316 IWinHttpRequest *req;
3317 BSTR method, url, username, password, response = NULL, status_text = NULL, headers = NULL;
3318 BSTR date, today, connection, value = NULL;
3319 VARIANT async, empty, timeout, body, body2, proxy_server, bypass_list, data, cp;
3320 VARIANT_BOOL succeeded;
3321 LONG status;
3322 WCHAR todayW[WINHTTP_TIME_FORMAT_BUFSIZE];
3323 SYSTEMTIME st;
3324 IStream *stream, *stream2;
3325 LARGE_INTEGER pos;
3326 char buf[128];
3327 WCHAR bufW[128];
3328 DWORD count;
3330 GetSystemTime( &st );
3331 WinHttpTimeFromSystemTime( &st, todayW );
3333 CoInitialize( NULL );
3334 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3335 ok( hr == S_OK, "got %08x\n", hr );
3337 V_VT( &empty ) = VT_ERROR;
3338 V_ERROR( &empty ) = 0xdeadbeef;
3340 V_VT( &async ) = VT_BOOL;
3341 V_BOOL( &async ) = VARIANT_FALSE;
3343 method = SysAllocString( method3W );
3344 url = SysAllocString( url3W );
3345 hr = IWinHttpRequest_Open( req, method, url, async );
3346 ok( hr == S_OK, "got %08x\n", hr );
3347 SysFreeString( method );
3348 SysFreeString( url );
3350 V_VT( &data ) = VT_BSTR;
3351 V_BSTR( &data ) = SysAllocString( test_dataW );
3352 hr = IWinHttpRequest_Send( req, data );
3353 ok( hr == S_OK || broken(hr == HRESULT_FROM_WIN32(ERROR_WINHTTP_INVALID_SERVER_RESPONSE)),
3354 "got %08x\n", hr );
3355 SysFreeString( V_BSTR( &data ) );
3357 hr = IWinHttpRequest_Open( req, NULL, NULL, empty );
3358 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3360 method = SysAllocString( method1W );
3361 hr = IWinHttpRequest_Open( req, method, NULL, empty );
3362 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3364 hr = IWinHttpRequest_Open( req, method, NULL, async );
3365 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3367 url = SysAllocString( url1W );
3368 hr = IWinHttpRequest_Open( req, NULL, url, empty );
3369 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3371 hr = IWinHttpRequest_Abort( req );
3372 ok( hr == S_OK, "got %08x\n", hr );
3374 hr = IWinHttpRequest_Open( req, method, url, empty );
3375 ok( hr == S_OK, "got %08x\n", hr );
3377 hr = IWinHttpRequest_Abort( req );
3378 ok( hr == S_OK, "got %08x\n", hr );
3380 IWinHttpRequest_Release( req );
3382 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3383 ok( hr == S_OK, "got %08x\n", hr );
3385 SysFreeString( url );
3386 url = SysAllocString( url2W );
3387 hr = IWinHttpRequest_Open( req, method, url, async );
3388 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ), "got %08x\n", hr );
3390 SysFreeString( method );
3391 method = SysAllocString( method2W );
3392 hr = IWinHttpRequest_Open( req, method, url, async );
3393 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ), "got %08x\n", hr );
3395 SysFreeString( method );
3396 method = SysAllocString( method1W );
3397 SysFreeString( url );
3398 url = SysAllocString( url1W );
3399 V_VT( &async ) = VT_ERROR;
3400 V_ERROR( &async ) = DISP_E_PARAMNOTFOUND;
3401 hr = IWinHttpRequest_Open( req, method, url, async );
3402 ok( hr == S_OK, "got %08x\n", hr );
3404 V_VT( &cp ) = VT_ERROR;
3405 V_ERROR( &cp ) = 0xdeadbeef;
3406 hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3407 ok( hr == S_OK, "got %08x\n", hr );
3408 ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3409 ok( V_I4( &cp ) == CP_UTF8, "got %u\n", V_I4( &cp ) );
3411 V_VT( &cp ) = VT_UI4;
3412 V_UI4( &cp ) = CP_ACP;
3413 hr = IWinHttpRequest_put_Option( req, WinHttpRequestOption_URLCodePage, cp );
3414 ok( hr == S_OK, "got %08x\n", hr );
3416 V_VT( &cp ) = VT_ERROR;
3417 V_ERROR( &cp ) = 0xdeadbeef;
3418 hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3419 ok( hr == S_OK, "got %08x\n", hr );
3420 ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3421 ok( V_I4( &cp ) == CP_ACP, "got %u\n", V_I4( &cp ) );
3423 value = SysAllocString( utf8W );
3424 V_VT( &cp ) = VT_BSTR;
3425 V_BSTR( &cp ) = value;
3426 hr = IWinHttpRequest_put_Option( req, WinHttpRequestOption_URLCodePage, cp );
3427 ok( hr == S_OK, "got %08x\n", hr );
3428 SysFreeString( value );
3430 V_VT( &cp ) = VT_ERROR;
3431 V_ERROR( &cp ) = 0xdeadbeef;
3432 hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3433 ok( hr == S_OK, "got %08x\n", hr );
3434 ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3435 ok( V_I4( &cp ) == CP_UTF8, "got %u\n", V_I4( &cp ) );
3437 hr = IWinHttpRequest_Abort( req );
3438 ok( hr == S_OK, "got %08x\n", hr );
3440 hr = IWinHttpRequest_Send( req, empty );
3441 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3443 hr = IWinHttpRequest_Abort( req );
3444 ok( hr == S_OK, "got %08x\n", hr );
3446 IWinHttpRequest_Release( req );
3448 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3449 ok( hr == S_OK, "got %08x\n", hr );
3451 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3452 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3454 hr = IWinHttpRequest_get_ResponseText( req, &response );
3455 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3457 hr = IWinHttpRequest_get_Status( req, NULL );
3458 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3460 hr = IWinHttpRequest_get_Status( req, &status );
3461 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3463 hr = IWinHttpRequest_get_StatusText( req, NULL );
3464 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3466 hr = IWinHttpRequest_get_StatusText( req, &status_text );
3467 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3469 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3470 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3472 hr = IWinHttpRequest_SetTimeouts( req, 10000, 10000, 10000, 10000 );
3473 ok( hr == S_OK, "got %08x\n", hr );
3475 hr = IWinHttpRequest_SetCredentials( req, NULL, NULL, 0xdeadbeef );
3476 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3478 VariantInit( &proxy_server );
3479 V_VT( &proxy_server ) = VT_ERROR;
3480 VariantInit( &bypass_list );
3481 V_VT( &bypass_list ) = VT_ERROR;
3482 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3483 ok( hr == S_OK, "got %08x\n", hr );
3485 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3486 ok( hr == S_OK, "got %08x\n", hr );
3488 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3489 ok( hr == S_OK, "got %08x\n", hr );
3491 hr = IWinHttpRequest_GetAllResponseHeaders( req, NULL );
3492 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3494 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3495 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3497 hr = IWinHttpRequest_GetResponseHeader( req, NULL, NULL );
3498 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3500 connection = SysAllocString( connectionW );
3501 hr = IWinHttpRequest_GetResponseHeader( req, connection, NULL );
3502 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3504 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3505 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3507 hr = IWinHttpRequest_SetRequestHeader( req, NULL, NULL );
3508 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3510 date = SysAllocString( dateW );
3511 hr = IWinHttpRequest_SetRequestHeader( req, date, NULL );
3512 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3514 today = SysAllocString( todayW );
3515 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3516 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3518 hr = IWinHttpRequest_SetAutoLogonPolicy( req, 0xdeadbeef );
3519 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3521 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3522 ok( hr == S_OK, "got %08x\n", hr );
3524 SysFreeString( method );
3525 method = SysAllocString( method1W );
3526 SysFreeString( url );
3527 url = SysAllocString( url1W );
3528 hr = IWinHttpRequest_Open( req, method, url, async );
3529 ok( hr == S_OK, "got %08x\n", hr );
3531 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3532 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3534 hr = IWinHttpRequest_get_ResponseText( req, &response );
3535 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3537 hr = IWinHttpRequest_get_Status( req, &status );
3538 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3540 hr = IWinHttpRequest_get_StatusText( req, &status_text );
3541 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3543 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3544 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3546 hr = IWinHttpRequest_SetTimeouts( req, 10000, 10000, 10000, 10000 );
3547 ok( hr == S_OK, "got %08x\n", hr );
3549 hr = IWinHttpRequest_SetCredentials( req, NULL, NULL, 0xdeadbeef );
3550 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3552 username = SysAllocString( usernameW );
3553 hr = IWinHttpRequest_SetCredentials( req, username, NULL, 0xdeadbeef );
3554 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3556 password = SysAllocString( passwordW );
3557 hr = IWinHttpRequest_SetCredentials( req, NULL, password, 0xdeadbeef );
3558 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3560 hr = IWinHttpRequest_SetCredentials( req, username, password, 0xdeadbeef );
3561 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3563 hr = IWinHttpRequest_SetCredentials( req, NULL, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3564 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3566 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3567 ok( hr == S_OK, "got %08x\n", hr );
3569 V_VT( &proxy_server ) = VT_BSTR;
3570 V_BSTR( &proxy_server ) = SysAllocString( proxy_serverW );
3571 V_VT( &bypass_list ) = VT_BSTR;
3572 V_BSTR( &bypass_list ) = SysAllocString( bypas_listW );
3573 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3574 ok( hr == S_OK, "got %08x\n", hr );
3576 hr = IWinHttpRequest_SetProxy( req, 0xdeadbeef, proxy_server, bypass_list );
3577 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3579 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3580 ok( hr == S_OK, "got %08x\n", hr );
3582 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3583 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3585 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3586 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3588 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3589 ok( hr == S_OK, "got %08x\n", hr );
3591 hr = IWinHttpRequest_SetRequestHeader( req, date, NULL );
3592 ok( hr == S_OK, "got %08x\n", hr );
3594 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3595 ok( hr == S_OK, "got %08x\n", hr );
3597 hr = IWinHttpRequest_Send( req, empty );
3598 ok( hr == S_OK, "got %08x\n", hr );
3600 hr = IWinHttpRequest_Send( req, empty );
3601 ok( hr == S_OK, "got %08x\n", hr );
3603 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3604 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3606 hr = IWinHttpRequest_get_ResponseText( req, &response );
3607 ok( hr == S_OK, "got %08x\n", hr );
3608 ok( !memcmp(response, data_start, sizeof(data_start)), "got %s\n", wine_dbgstr_wn(response, 32) );
3609 SysFreeString( response );
3611 hr = IWinHttpRequest_get_Status( req, NULL );
3612 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3614 status = 0;
3615 hr = IWinHttpRequest_get_Status( req, &status );
3616 ok( hr == S_OK, "got %08x\n", hr );
3617 trace("Status=%d\n", status);
3619 hr = IWinHttpRequest_get_StatusText( req, NULL );
3620 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3622 hr = IWinHttpRequest_get_StatusText( req, &status_text );
3623 ok( hr == S_OK, "got %08x\n", hr );
3624 trace("StatusText=%s\n", wine_dbgstr_w(status_text));
3625 SysFreeString( status_text );
3627 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3628 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3630 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3631 ok( hr == S_OK, "got %08x\n", hr );
3633 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3634 ok( hr == S_OK, "got %08x\n", hr );
3636 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3637 ok( hr == S_OK, "got %08x\n", hr );
3639 hr = IWinHttpRequest_GetAllResponseHeaders( req, NULL );
3640 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3642 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3643 ok( hr == S_OK, "got %08x\n", hr );
3644 SysFreeString( headers );
3646 hr = IWinHttpRequest_GetResponseHeader( req, NULL, NULL );
3647 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3649 hr = IWinHttpRequest_GetResponseHeader( req, connection, NULL );
3650 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3652 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3653 ok( hr == S_OK, "got %08x\n", hr );
3654 SysFreeString( value );
3656 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3657 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND ), "got %08x\n", hr );
3659 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3660 ok( hr == S_OK, "got %08x\n", hr );
3662 VariantInit( &timeout );
3663 V_VT( &timeout ) = VT_I4;
3664 V_I4( &timeout ) = 10;
3665 hr = IWinHttpRequest_WaitForResponse( req, timeout, &succeeded );
3666 ok( hr == S_OK, "got %08x\n", hr );
3668 hr = IWinHttpRequest_get_Status( req, &status );
3669 ok( hr == S_OK, "got %08x\n", hr );
3671 hr = IWinHttpRequest_get_StatusText( req, &status_text );
3672 ok( hr == S_OK, "got %08x\n", hr );
3673 SysFreeString( status_text );
3675 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3676 ok( hr == S_OK, "got %08x\n", hr );
3678 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3679 ok( hr == S_OK, "got %08x\n", hr );
3681 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3682 ok( hr == S_OK, "got %08x\n", hr );
3684 hr = IWinHttpRequest_Send( req, empty );
3685 ok( hr == S_OK, "got %08x\n", hr );
3687 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3688 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3690 hr = IWinHttpRequest_get_ResponseText( req, &response );
3691 ok( hr == S_OK, "got %08x\n", hr );
3692 SysFreeString( response );
3694 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3695 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3697 VariantInit( &body );
3698 V_VT( &body ) = VT_ERROR;
3699 hr = IWinHttpRequest_get_ResponseBody( req, &body );
3700 ok( hr == S_OK, "got %08x\n", hr );
3701 ok( V_VT( &body ) == (VT_ARRAY|VT_UI1), "got %08x\n", V_VT( &body ) );
3703 hr = VariantClear( &body );
3704 ok( hr == S_OK, "got %08x\n", hr );
3706 VariantInit( &body );
3707 V_VT( &body ) = VT_ERROR;
3708 hr = IWinHttpRequest_get_ResponseStream( req, &body );
3709 ok( hr == S_OK, "got %08x\n", hr );
3710 ok( V_VT( &body ) == VT_UNKNOWN, "got %08x\n", V_VT( &body ) );
3712 hr = IUnknown_QueryInterface( V_UNKNOWN( &body ), &IID_IStream, (void **)&stream );
3713 ok( hr == S_OK, "got %08x\n", hr );
3714 ok( V_UNKNOWN( &body ) == (IUnknown *)stream, "got different interface pointer\n" );
3716 buf[0] = 0;
3717 count = 0xdeadbeef;
3718 hr = IStream_Read( stream, buf, 128, &count );
3719 ok( hr == S_OK, "got %08x\n", hr );
3720 ok( count != 0xdeadbeef, "count not set\n" );
3721 ok( buf[0], "no data\n" );
3723 VariantInit( &body2 );
3724 V_VT( &body2 ) = VT_ERROR;
3725 hr = IWinHttpRequest_get_ResponseStream( req, &body2 );
3726 ok( hr == S_OK, "got %08x\n", hr );
3727 ok( V_VT( &body2 ) == VT_UNKNOWN, "got %08x\n", V_VT( &body2 ) );
3728 ok( V_UNKNOWN( &body ) != V_UNKNOWN( &body2 ), "got same interface pointer\n" );
3730 hr = IUnknown_QueryInterface( V_UNKNOWN( &body2 ), &IID_IStream, (void **)&stream2 );
3731 ok( hr == S_OK, "got %08x\n", hr );
3732 ok( V_UNKNOWN( &body2 ) == (IUnknown *)stream2, "got different interface pointer\n" );
3733 IStream_Release( stream2 );
3735 hr = VariantClear( &body );
3736 ok( hr == S_OK, "got %08x\n", hr );
3738 hr = VariantClear( &body2 );
3739 ok( hr == S_OK, "got %08x\n", hr );
3741 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3742 ok( hr == S_OK, "got %08x\n", hr );
3744 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3745 ok( hr == S_OK, "got %08x\n", hr );
3747 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3748 ok( hr == S_OK, "got %08x\n", hr );
3749 SysFreeString( headers );
3751 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3752 ok( hr == S_OK, "got %08x\n", hr );
3753 SysFreeString( value );
3755 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3756 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND ), "got %08x\n", hr );
3758 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3759 ok( hr == S_OK, "got %08x\n", hr );
3761 hr = IWinHttpRequest_Send( req, empty );
3762 ok( hr == S_OK, "got %08x\n", hr );
3764 hr = IWinHttpRequest_Abort( req );
3765 ok( hr == S_OK, "got %08x\n", hr );
3767 hr = IWinHttpRequest_Abort( req );
3768 ok( hr == S_OK, "got %08x\n", hr );
3770 IWinHttpRequest_Release( req );
3772 pos.QuadPart = 0;
3773 hr = IStream_Seek( stream, pos, STREAM_SEEK_SET, NULL );
3774 ok( hr == S_OK, "got %08x\n", hr );
3776 buf[0] = 0;
3777 count = 0xdeadbeef;
3778 hr = IStream_Read( stream, buf, 128, &count );
3779 ok( hr == S_OK, "got %08x\n", hr );
3780 ok( count != 0xdeadbeef, "count not set\n" );
3781 ok( buf[0], "no data\n" );
3782 IStream_Release( stream );
3784 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3785 ok( hr == S_OK, "got %08x\n", hr );
3787 V_VT( &async ) = VT_I4;
3788 V_I4( &async ) = 1;
3789 hr = IWinHttpRequest_Open( req, method, url, async );
3790 ok( hr == S_OK, "got %08x\n", hr );
3792 hr = IWinHttpRequest_Send( req, empty );
3793 ok( hr == S_OK, "got %08x\n", hr );
3795 hr = IWinHttpRequest_WaitForResponse( req, timeout, &succeeded );
3796 ok( hr == S_OK, "got %08x\n", hr );
3798 IWinHttpRequest_Release( req );
3800 SysFreeString( method );
3801 SysFreeString( url );
3802 SysFreeString( username );
3803 SysFreeString( password );
3804 SysFreeString( connection );
3805 SysFreeString( date );
3806 SysFreeString( today );
3807 VariantClear( &proxy_server );
3808 VariantClear( &bypass_list );
3810 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3811 ok( hr == S_OK, "got %08x\n", hr );
3813 url = SysAllocString( test_winehq_https );
3814 method = SysAllocString( method3W );
3815 V_VT( &async ) = VT_BOOL;
3816 V_BOOL( &async ) = VARIANT_FALSE;
3817 hr = IWinHttpRequest_Open( req, method, url, async );
3818 ok( hr == S_OK, "got %08x\n", hr );
3819 SysFreeString( method );
3820 SysFreeString( url );
3822 hr = IWinHttpRequest_Send( req, empty );
3823 ok( hr == S_OK || broken(hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_INVALID_SERVER_RESPONSE )), "got %08x\n", hr );
3824 if (hr == S_OK)
3826 hr = IWinHttpRequest_get_ResponseText( req, &response );
3827 ok( hr == S_OK, "got %08x\n", hr );
3828 ok( !memcmp(response, data_start, sizeof(data_start)), "got %s\n", wine_dbgstr_wn(response, 32) );
3829 SysFreeString( response );
3832 IWinHttpRequest_Release( req );
3834 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3835 ok( hr == S_OK, "got %08x\n", hr );
3837 sprintf( buf, "http://localhost:%d/auth", port );
3838 MultiByteToWideChar( CP_ACP, 0, buf, -1, bufW, sizeof(bufW)/sizeof(bufW[0]) );
3839 url = SysAllocString( bufW );
3840 method = SysAllocString( method3W );
3841 V_VT( &async ) = VT_BOOL;
3842 V_BOOL( &async ) = VARIANT_FALSE;
3843 hr = IWinHttpRequest_Open( req, method, url, async );
3844 ok( hr == S_OK, "got %08x\n", hr );
3845 SysFreeString( method );
3846 SysFreeString( url );
3848 hr = IWinHttpRequest_get_Status( req, &status );
3849 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3851 V_VT( &data ) = VT_BSTR;
3852 V_BSTR( &data ) = SysAllocString( test_dataW );
3853 hr = IWinHttpRequest_Send( req, data );
3854 ok( hr == S_OK, "got %08x\n", hr );
3855 SysFreeString( V_BSTR( &data ) );
3857 hr = IWinHttpRequest_get_ResponseText( req, &response );
3858 ok( hr == S_OK, "got %08x\n", hr );
3859 ok( !memcmp( response, unauthW, sizeof(unauthW) ), "got %s\n", wine_dbgstr_w(response) );
3860 SysFreeString( response );
3862 status = 0xdeadbeef;
3863 hr = IWinHttpRequest_get_Status( req, &status );
3864 ok( hr == S_OK, "got %08x\n", hr );
3865 ok( status == HTTP_STATUS_DENIED, "got %d\n", status );
3867 IWinHttpRequest_Release( req );
3869 CoUninitialize();
3872 static void request_get_property(IWinHttpRequest *request, int property, VARIANT *ret)
3874 DISPPARAMS params;
3875 VARIANT arg;
3876 HRESULT hr;
3878 memset(&params, 0, sizeof(params));
3879 params.cNamedArgs = 0;
3880 params.rgdispidNamedArgs = NULL;
3881 params.cArgs = 1;
3882 params.rgvarg = &arg;
3883 VariantInit(&arg);
3884 V_VT(&arg) = VT_I4;
3885 V_I4(&arg) = property;
3886 VariantInit(ret);
3887 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
3888 DISPATCH_PROPERTYGET, &params, ret, NULL, NULL);
3889 ok(hr == S_OK, "error %#x\n", hr);
3892 static void test_IWinHttpRequest_Invoke(void)
3894 static const WCHAR utf8W[] = {'U','T','F','-','8',0};
3895 static const WCHAR regid[] = {'W','i','n','H','t','t','p','.','W','i','n','H','t','t','p','R','e','q','u','e','s','t','.','5','.','1',0};
3896 WCHAR openW[] = {'O','p','e','n',0};
3897 WCHAR optionW[] = {'O','p','t','i','o','n',0};
3898 OLECHAR *open = openW, *option = optionW;
3899 BSTR utf8;
3900 CLSID clsid;
3901 IWinHttpRequest *request;
3902 IDispatch *dispatch;
3903 DISPID id;
3904 DISPPARAMS params;
3905 VARIANT arg[3], ret;
3906 UINT err;
3907 BOOL bret;
3908 HRESULT hr;
3910 CoInitialize(NULL);
3912 hr = CLSIDFromProgID(regid, &clsid);
3913 ok(hr == S_OK, "CLSIDFromProgID error %#x\n", hr);
3914 bret = IsEqualIID(&clsid, &CLSID_WinHttpRequest);
3915 ok(bret || broken(!bret) /* win2003 */, "not expected %s\n", wine_dbgstr_guid(&clsid));
3917 hr = CoCreateInstance(&CLSID_WinHttpRequest, 0, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&request);
3918 ok(hr == S_OK, "error %#x\n", hr);
3920 hr = IWinHttpRequest_QueryInterface(request, &IID_IDispatch, (void **)&dispatch);
3921 ok(hr == S_OK, "error %#x\n", hr);
3922 IDispatch_Release(dispatch);
3924 hr = IWinHttpRequest_GetIDsOfNames(request, &IID_NULL, &open, 1, 0x0409, &id);
3925 ok(hr == S_OK, "error %#x\n", hr);
3926 ok(id == DISPID_HTTPREQUEST_OPEN, "expected DISPID_HTTPREQUEST_OPEN, got %u\n", id);
3928 hr = IWinHttpRequest_GetIDsOfNames(request, &IID_NULL, &option, 1, 0x0409, &id);
3929 ok(hr == S_OK, "error %#x\n", hr);
3930 ok(id == DISPID_HTTPREQUEST_OPTION, "expected DISPID_HTTPREQUEST_OPTION, got %u\n", id);
3932 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3933 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3934 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
3936 memset(&params, 0, sizeof(params));
3937 params.cArgs = 2;
3938 params.cNamedArgs = 0;
3939 params.rgvarg = arg;
3940 V_VT(&arg[0]) = VT_I4;
3941 V_I4(&arg[0]) = 1252;
3942 V_VT(&arg[1]) = VT_R8;
3943 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
3944 VariantInit(&ret);
3945 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
3946 DISPATCH_METHOD, &params, NULL, NULL, &err);
3947 ok(hr == S_OK, "error %#x\n", hr);
3949 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3950 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3951 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
3953 memset(&params, 0, sizeof(params));
3954 params.cArgs = 2;
3955 params.cNamedArgs = 0;
3956 params.rgvarg = arg;
3957 V_VT(&arg[0]) = VT_I4;
3958 V_I4(&arg[0]) = 1252;
3959 V_VT(&arg[1]) = VT_R8;
3960 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
3961 VariantInit(&ret);
3962 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
3963 DISPATCH_METHOD | DISPATCH_PROPERTYPUT, &params, NULL, NULL, &err);
3964 ok(hr == S_OK, "error %#x\n", hr);
3966 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3967 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3968 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
3970 memset(&params, 0, sizeof(params));
3971 params.cArgs = 2;
3972 params.cNamedArgs = 0;
3973 params.rgvarg = arg;
3974 V_VT(&arg[0]) = VT_I4;
3975 V_I4(&arg[0]) = 1252;
3976 V_VT(&arg[1]) = VT_R8;
3977 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
3978 VariantInit(&ret);
3979 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
3980 DISPATCH_PROPERTYPUT, &params, NULL, NULL, &err);
3981 ok(hr == S_OK, "error %#x\n", hr);
3983 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3984 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3985 ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
3987 memset(&params, 0, sizeof(params));
3988 params.cArgs = 2;
3989 params.cNamedArgs = 0;
3990 params.rgvarg = arg;
3991 V_VT(&arg[0]) = VT_BSTR;
3992 utf8 = SysAllocString(utf8W);
3993 V_BSTR(&arg[0]) = utf8;
3994 V_VT(&arg[1]) = VT_R8;
3995 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
3996 hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_METHOD, &params, NULL, NULL, &err);
3997 ok(hr == S_OK, "error %#x\n", hr);
3999 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4000 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4001 ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
4003 VariantInit(&ret);
4004 hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_METHOD, &params, &ret, NULL, &err);
4005 ok(hr == S_OK, "error %#x\n", hr);
4007 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4008 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4009 ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
4011 VariantInit(&ret);
4012 hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
4013 ok(hr == S_OK, "error %#x\n", hr);
4015 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4016 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4017 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4019 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, NULL, NULL, NULL);
4020 ok(hr == S_OK, "error %#x\n", hr);
4022 hr = IWinHttpRequest_Invoke(request, 255, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, NULL, NULL, NULL);
4023 ok(hr == DISP_E_MEMBERNOTFOUND, "error %#x\n", hr);
4025 VariantInit(&ret);
4026 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
4027 ok(hr == DISP_E_UNKNOWNINTERFACE, "error %#x\n", hr);
4029 VariantInit(&ret);
4030 if (0) /* crashes */
4031 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, &ret, NULL, &err);
4033 params.cArgs = 1;
4034 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
4035 ok(hr == DISP_E_TYPEMISMATCH, "error %#x\n", hr);
4037 VariantInit(&arg[2]);
4038 params.cArgs = 3;
4039 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
4040 todo_wine
4041 ok(hr == S_OK, "error %#x\n", hr);
4043 VariantInit(&arg[0]);
4044 VariantInit(&arg[1]);
4045 VariantInit(&arg[2]);
4047 params.cArgs = 1;
4048 V_VT(&arg[0]) = VT_I4;
4049 V_I4(&arg[0]) = WinHttpRequestOption_URLCodePage;
4050 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4051 ok(hr == S_OK, "error %#x\n", hr);
4053 V_VT(&ret) = 0xdead;
4054 V_I4(&ret) = 0xbeef;
4055 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &params, &ret, NULL, NULL);
4056 ok(hr == S_OK, "error %#x\n", hr);
4057 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4058 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4060 V_VT(&ret) = 0xdead;
4061 V_I4(&ret) = 0xbeef;
4062 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD, &params, &ret, NULL, NULL);
4063 ok(hr == S_OK, "error %#x\n", hr);
4064 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4065 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4067 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4068 ok(hr == S_OK, "error %#x\n", hr);
4070 V_VT(&ret) = 0xdead;
4071 V_I4(&ret) = 0xbeef;
4072 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, 0, &params, &ret, NULL, NULL);
4073 ok(hr == S_OK, "error %#x\n", hr);
4074 ok(V_VT(&ret) == VT_EMPTY, "expected VT_EMPTY, got %d\n", V_VT(&ret));
4075 ok(V_I4(&ret) == 0xbeef || V_I4(&ret) == 0 /* Win8 */, "expected 0xdead, got %d\n", V_I4(&ret));
4077 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, 0, &params, NULL, NULL, NULL);
4078 ok(hr == S_OK, "error %#x\n", hr);
4080 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_IUnknown, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4081 ok(hr == DISP_E_UNKNOWNINTERFACE, "error %#x\n", hr);
4083 params.cArgs = 2;
4084 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4085 todo_wine
4086 ok(hr == S_OK, "error %#x\n", hr);
4088 params.cArgs = 0;
4089 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4090 ok(hr == DISP_E_PARAMNOTFOUND, "error %#x\n", hr);
4092 SysFreeString(utf8);
4094 params.cArgs = 1;
4095 V_VT(&arg[0]) = VT_I4;
4096 V_I4(&arg[0]) = AutoLogonPolicy_Never;
4097 VariantInit(&ret);
4098 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_SETAUTOLOGONPOLICY, &IID_NULL, 0,
4099 DISPATCH_METHOD, &params, &ret, NULL, NULL);
4100 ok(hr == S_OK, "error %#x\n", hr);
4102 IWinHttpRequest_Release(request);
4104 CoUninitialize();
4107 static void test_WinHttpDetectAutoProxyConfigUrl(void)
4109 BOOL ret;
4110 WCHAR *url;
4111 DWORD error;
4113 if (0) /* crashes on some win2k systems */
4115 SetLastError(0xdeadbeef);
4116 ret = WinHttpDetectAutoProxyConfigUrl( 0, NULL );
4117 error = GetLastError();
4118 ok( !ret, "expected failure\n" );
4119 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4121 url = NULL;
4122 SetLastError(0xdeadbeef);
4123 ret = WinHttpDetectAutoProxyConfigUrl( 0, &url );
4124 error = GetLastError();
4125 ok( !ret, "expected failure\n" );
4126 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4128 if (0) /* crashes on some win2k systems */
4130 SetLastError(0xdeadbeef);
4131 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, NULL );
4132 error = GetLastError();
4133 ok( !ret, "expected failure\n" );
4134 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4136 url = (WCHAR *)0xdeadbeef;
4137 SetLastError(0xdeadbeef);
4138 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, &url );
4139 error = GetLastError();
4140 if (!ret)
4142 ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED, "got %u\n", error );
4143 ok( !url || broken(url == (WCHAR *)0xdeadbeef), "got %p\n", url );
4145 else
4147 trace("%s\n", wine_dbgstr_w(url));
4148 GlobalFree( url );
4151 url = (WCHAR *)0xdeadbeef;
4152 SetLastError(0xdeadbeef);
4153 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DHCP, &url );
4154 error = GetLastError();
4155 if (!ret)
4157 ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED, "got %u\n", error );
4158 ok( !url || broken(url == (WCHAR *)0xdeadbeef), "got %p\n", url );
4160 else
4162 ok( error == ERROR_SUCCESS, "got %u\n", error );
4163 trace("%s\n", wine_dbgstr_w(url));
4164 GlobalFree( url );
4168 static void test_WinHttpGetIEProxyConfigForCurrentUser(void)
4170 BOOL ret;
4171 DWORD error;
4172 WINHTTP_CURRENT_USER_IE_PROXY_CONFIG cfg;
4174 memset( &cfg, 0, sizeof(cfg) );
4176 SetLastError(0xdeadbeef);
4177 ret = WinHttpGetIEProxyConfigForCurrentUser( NULL );
4178 error = GetLastError();
4179 ok( !ret, "expected failure\n" );
4180 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4182 SetLastError(0xdeadbeef);
4183 ret = WinHttpGetIEProxyConfigForCurrentUser( &cfg );
4184 error = GetLastError();
4185 ok( ret, "expected success\n" );
4186 ok( error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* < win7 */, "got %u\n", error );
4188 trace("IEProxy.AutoDetect=%d\n", cfg.fAutoDetect);
4189 trace("IEProxy.AutoConfigUrl=%s\n", wine_dbgstr_w(cfg.lpszAutoConfigUrl));
4190 trace("IEProxy.Proxy=%s\n", wine_dbgstr_w(cfg.lpszProxy));
4191 trace("IEProxy.ProxyBypass=%s\n", wine_dbgstr_w(cfg.lpszProxyBypass));
4192 GlobalFree( cfg.lpszAutoConfigUrl );
4193 GlobalFree( cfg.lpszProxy );
4194 GlobalFree( cfg.lpszProxyBypass );
4197 static void test_WinHttpGetProxyForUrl(void)
4199 static const WCHAR urlW[] = {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0};
4200 static const WCHAR wpadW[] = {'h','t','t','p',':','/','/','w','p','a','d','/','w','p','a','d','.','d','a','t',0};
4201 static const WCHAR emptyW[] = {0};
4202 BOOL ret;
4203 DWORD error;
4204 HINTERNET session;
4205 WINHTTP_AUTOPROXY_OPTIONS options;
4206 WINHTTP_PROXY_INFO info;
4208 memset( &options, 0, sizeof(options) );
4210 SetLastError(0xdeadbeef);
4211 ret = WinHttpGetProxyForUrl( NULL, NULL, NULL, NULL );
4212 error = GetLastError();
4213 ok( !ret, "expected failure\n" );
4214 ok( error == ERROR_INVALID_HANDLE, "got %u\n", error );
4216 session = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
4217 ok( session != NULL, "failed to open session %u\n", GetLastError() );
4219 SetLastError(0xdeadbeef);
4220 ret = WinHttpGetProxyForUrl( session, NULL, NULL, NULL );
4221 error = GetLastError();
4222 ok( !ret, "expected failure\n" );
4223 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4225 SetLastError(0xdeadbeef);
4226 ret = WinHttpGetProxyForUrl( session, emptyW, NULL, NULL );
4227 error = GetLastError();
4228 ok( !ret, "expected failure\n" );
4229 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4231 SetLastError(0xdeadbeef);
4232 ret = WinHttpGetProxyForUrl( session, urlW, NULL, NULL );
4233 error = GetLastError();
4234 ok( !ret, "expected failure\n" );
4235 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4237 SetLastError(0xdeadbeef);
4238 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
4239 error = GetLastError();
4240 ok( !ret, "expected failure\n" );
4241 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4243 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
4244 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
4246 SetLastError(0xdeadbeef);
4247 ret = WinHttpGetProxyForUrl( session, urlW, &options, NULL );
4248 error = GetLastError();
4249 ok( !ret, "expected failure\n" );
4250 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4252 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
4253 options.dwAutoDetectFlags = 0;
4255 SetLastError(0xdeadbeef);
4256 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
4257 error = GetLastError();
4258 ok( !ret, "expected failure\n" );
4259 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4261 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT | WINHTTP_AUTOPROXY_CONFIG_URL;
4262 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
4264 SetLastError(0xdeadbeef);
4265 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
4266 error = GetLastError();
4267 ok( !ret, "expected failure\n" );
4268 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4270 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
4271 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
4273 memset( &info, 0, sizeof(info) );
4274 SetLastError(0xdeadbeef);
4275 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
4276 error = GetLastError();
4277 if (ret)
4279 ok( error == ERROR_SUCCESS, "got %u\n", error );
4280 trace("Proxy.AccessType=%u\n", info.dwAccessType);
4281 trace("Proxy.Proxy=%s\n", wine_dbgstr_w(info.lpszProxy));
4282 trace("Proxy.ProxyBypass=%s\n", wine_dbgstr_w(info.lpszProxyBypass));
4283 GlobalFree( info.lpszProxy );
4284 GlobalFree( info.lpszProxyBypass );
4287 options.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
4288 options.dwAutoDetectFlags = 0;
4289 options.lpszAutoConfigUrl = wpadW;
4291 memset( &info, 0, sizeof(info) );
4292 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
4293 if (ret)
4295 trace("Proxy.AccessType=%u\n", info.dwAccessType);
4296 trace("Proxy.Proxy=%s\n", wine_dbgstr_w(info.lpszProxy));
4297 trace("Proxy.ProxyBypass=%s\n", wine_dbgstr_w(info.lpszProxyBypass));
4298 GlobalFree( info.lpszProxy );
4299 GlobalFree( info.lpszProxyBypass );
4301 WinHttpCloseHandle( session );
4304 static void test_chunked_read(void)
4306 static const WCHAR verb[] = {'/','t','e','s','t','c','h','u','n','k','e','d',0};
4307 static const WCHAR chunked[] = {'c','h','u','n','k','e','d',0};
4308 WCHAR header[32];
4309 DWORD len, err;
4310 HINTERNET ses, con = NULL, req = NULL;
4311 BOOL ret;
4313 trace( "starting chunked read test\n" );
4315 ses = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
4316 ok( ses != NULL, "WinHttpOpen failed with error %u\n", GetLastError() );
4317 if (!ses) goto done;
4319 con = WinHttpConnect( ses, test_winehq, 0, 0 );
4320 ok( con != NULL, "WinHttpConnect failed with error %u\n", GetLastError() );
4321 if (!con) goto done;
4323 req = WinHttpOpenRequest( con, NULL, verb, NULL, NULL, NULL, 0 );
4324 ok( req != NULL, "WinHttpOpenRequest failed with error %u\n", GetLastError() );
4325 if (!req) goto done;
4327 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
4328 err = GetLastError();
4329 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
4331 skip("connection failed, skipping\n");
4332 goto done;
4334 ok( ret, "WinHttpSendRequest failed with error %u\n", GetLastError() );
4336 ret = WinHttpReceiveResponse( req, NULL );
4337 ok( ret, "WinHttpReceiveResponse failed with error %u\n", GetLastError() );
4339 header[0] = 0;
4340 len = sizeof(header);
4341 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, header, &len, 0 );
4342 ok( ret, "failed to get TRANSFER_ENCODING header (error %u)\n", GetLastError() );
4343 ok( !lstrcmpW( header, chunked ), "wrong transfer encoding %s\n", wine_dbgstr_w(header) );
4344 trace( "transfer encoding: %s\n", wine_dbgstr_w(header) );
4346 header[0] = 0;
4347 len = sizeof(header);
4348 SetLastError( 0xdeadbeef );
4349 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_CONTENT_LENGTH, NULL, &header, &len, 0 );
4350 ok( !ret, "unexpected CONTENT_LENGTH header %s\n", wine_dbgstr_w(header) );
4351 ok( GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND, "wrong error %u\n", GetLastError() );
4353 trace( "entering query loop\n" );
4354 for (;;)
4356 len = 0xdeadbeef;
4357 ret = WinHttpQueryDataAvailable( req, &len );
4358 ok( ret, "WinHttpQueryDataAvailable failed with error %u\n", GetLastError() );
4359 if (ret) ok( len != 0xdeadbeef, "WinHttpQueryDataAvailable return wrong length\n" );
4360 trace( "got %u available\n", len );
4361 if (len)
4363 DWORD bytes_read;
4364 char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 );
4366 ret = WinHttpReadData( req, buf, len, &bytes_read );
4368 buf[bytes_read] = 0;
4369 trace( "WinHttpReadData -> %d %u\n", ret, bytes_read );
4370 ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len );
4371 ok( buf[bytes_read - 1] == '\n', "received partial line '%s'\n", buf );
4373 HeapFree( GetProcessHeap(), 0, buf );
4374 if (!bytes_read) break;
4376 if (!len) break;
4378 trace( "done\n" );
4380 done:
4381 if (req) WinHttpCloseHandle( req );
4382 if (con) WinHttpCloseHandle( con );
4383 if (ses) WinHttpCloseHandle( ses );
4386 START_TEST (winhttp)
4388 static const WCHAR basicW[] = {'/','b','a','s','i','c',0};
4389 static const WCHAR quitW[] = {'/','q','u','i','t',0};
4390 struct server_info si;
4391 HANDLE thread;
4392 DWORD ret;
4394 test_OpenRequest();
4395 test_SendRequest();
4396 test_WinHttpTimeFromSystemTime();
4397 test_WinHttpTimeToSystemTime();
4398 test_WinHttpAddHeaders();
4399 test_secure_connection();
4400 test_request_parameter_defaults();
4401 test_QueryOption();
4402 test_set_default_proxy_config();
4403 test_empty_headers_param();
4404 test_Timeouts();
4405 test_resolve_timeout();
4406 test_credentials();
4407 test_IWinHttpRequest_Invoke();
4408 test_WinHttpDetectAutoProxyConfigUrl();
4409 test_WinHttpGetIEProxyConfigForCurrentUser();
4410 test_WinHttpGetProxyForUrl();
4411 test_chunked_read();
4413 si.event = CreateEventW(NULL, 0, 0, NULL);
4414 si.port = 7532;
4416 thread = CreateThread(NULL, 0, server_thread, (LPVOID)&si, 0, NULL);
4417 ok(thread != NULL, "failed to create thread %u\n", GetLastError());
4419 ret = WaitForSingleObject(si.event, 10000);
4420 ok(ret == WAIT_OBJECT_0, "failed to start winhttp test server %u\n", GetLastError());
4421 if (ret != WAIT_OBJECT_0)
4422 return;
4424 test_IWinHttpRequest(si.port);
4425 test_connection_info(si.port);
4426 test_basic_request(si.port, NULL, basicW);
4427 test_no_headers(si.port);
4428 test_no_content(si.port);
4429 test_head_request(si.port);
4430 test_not_modified(si.port);
4431 test_basic_authentication(si.port);
4432 test_multi_authentication(si.port);
4433 test_large_data_authentication(si.port);
4434 test_bad_header(si.port);
4435 test_multiple_reads(si.port);
4436 test_cookies(si.port);
4438 /* send the basic request again to shutdown the server thread */
4439 test_basic_request(si.port, NULL, quitW);
4441 WaitForSingleObject(thread, 3000);