kernel32/tests: A spelling fix in a comment.
[wine.git] / dlls / winhttp / tests / winhttp.c
blobd4406afb6b31a2096a218c7bcf175860913cea69
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;
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 con = WinHttpConnect(ses, test_winehq, 443, 0);
991 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
993 /* try without setting WINHTTP_FLAG_SECURE */
994 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
995 ok(req != NULL, "failed to open a request %u\n", GetLastError());
997 ret = WinHttpSetOption(req, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0);
998 err = GetLastError();
999 ok(!ret, "unexpected success\n");
1000 ok(err == ERROR_WINHTTP_INCORRECT_HANDLE_STATE || broken(err == ERROR_INVALID_PARAMETER) /* winxp */,
1001 "setting client cert context returned %u\n", err);
1003 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1004 err = GetLastError();
1005 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
1007 skip("Connection failed, skipping.\n");
1008 goto cleanup;
1010 ok(ret, "failed to send request %u\n", GetLastError());
1012 ret = WinHttpReceiveResponse(req, NULL);
1013 ok(ret, "failed to receive response %u\n", GetLastError());
1015 status = 0xdeadbeef;
1016 size = sizeof(status);
1017 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1018 ok(ret, "header query failed %u\n", GetLastError());
1019 ok(status == HTTP_STATUS_BAD_REQUEST, "got %u\n", status);
1021 WinHttpCloseHandle(req);
1023 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, WINHTTP_FLAG_SECURE);
1024 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1026 ret = WinHttpSetOption(req, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0);
1027 err = GetLastError();
1028 ok(ret || broken(!ret && err == ERROR_INVALID_PARAMETER) /* winxp */, "failed to set client cert context %u\n", err);
1030 WinHttpSetStatusCallback(req, cert_error, WINHTTP_CALLBACK_STATUS_SECURE_FAILURE, 0);
1032 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1033 err = GetLastError();
1034 if (!ret && (err == ERROR_WINHTTP_SECURE_FAILURE || err == ERROR_WINHTTP_CANNOT_CONNECT ||
1035 err == ERROR_WINHTTP_TIMEOUT))
1037 skip("secure connection failed, skipping remaining secure tests\n");
1038 goto cleanup;
1040 ok(ret, "failed to send request %u\n", GetLastError());
1042 size = sizeof(cert);
1043 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert, &size );
1044 ok(ret, "failed to retrieve certificate context %u\n", GetLastError());
1045 if (ret) CertFreeCertificateContext(cert);
1047 size = sizeof(bitness);
1048 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_KEY_BITNESS, &bitness, &size );
1049 ok(ret, "failed to retrieve key bitness %u\n", GetLastError());
1051 size = sizeof(info);
1052 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT, &info, &size );
1053 ok(ret, "failed to retrieve certificate info %u\n", GetLastError());
1055 if (ret)
1057 trace("lpszSubjectInfo %s\n", wine_dbgstr_w(info.lpszSubjectInfo));
1058 trace("lpszIssuerInfo %s\n", wine_dbgstr_w(info.lpszIssuerInfo));
1059 trace("lpszProtocolName %s\n", wine_dbgstr_w(info.lpszProtocolName));
1060 trace("lpszSignatureAlgName %s\n", wine_dbgstr_w(info.lpszSignatureAlgName));
1061 trace("lpszEncryptionAlgName %s\n", wine_dbgstr_w(info.lpszEncryptionAlgName));
1062 trace("dwKeySize %u\n", info.dwKeySize);
1063 LocalFree( info.lpszSubjectInfo );
1064 LocalFree( info.lpszIssuerInfo );
1067 ret = WinHttpReceiveResponse(req, NULL);
1068 ok(ret, "failed to receive response %u\n", GetLastError());
1070 available_size = 0;
1071 ret = WinHttpQueryDataAvailable(req, &available_size);
1072 ok(ret, "failed to query available data %u\n", GetLastError());
1073 ok(available_size > 2014, "available_size = %u\n", available_size);
1075 status = 0xdeadbeef;
1076 size = sizeof(status);
1077 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1078 ok(ret, "failed unexpectedly %u\n", GetLastError());
1079 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1081 size = 0;
1082 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL);
1083 ok(!ret, "succeeded unexpectedly\n");
1085 read_size = 0;
1086 for (;;)
1088 size = 0;
1089 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
1090 ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
1091 if (!size) break;
1092 read_size += size;
1094 if (read_size <= 32)
1095 ok(!memcmp(buffer, data_start, sizeof(data_start)-1), "not expected: %.32s\n", buffer);
1097 ok(read_size >= available_size, "read_size = %u, available_size = %u\n", read_size, available_size);
1099 cleanup:
1100 WinHttpCloseHandle(req);
1101 WinHttpCloseHandle(con);
1102 WinHttpCloseHandle(ses);
1105 static void test_request_parameter_defaults(void)
1107 static const WCHAR empty[] = {0};
1108 HINTERNET ses, con, req;
1109 DWORD size, status, error;
1110 WCHAR *version;
1111 BOOL ret;
1113 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1114 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1116 con = WinHttpConnect(ses, test_winehq, 0, 0);
1117 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1119 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1120 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1122 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1123 error = GetLastError();
1124 if (!ret && (error == ERROR_WINHTTP_CANNOT_CONNECT || error == ERROR_WINHTTP_TIMEOUT))
1126 skip("connection failed, skipping\n");
1127 goto done;
1129 ok(ret, "failed to send request %u\n", GetLastError());
1131 ret = WinHttpReceiveResponse(req, NULL);
1132 if (!ret && GetLastError() == ERROR_WINHTTP_INVALID_SERVER_RESPONSE) /* win2k */
1134 win_skip("invalid response\n");
1135 goto done;
1137 ok(ret, "failed to receive response %u\n", GetLastError());
1139 status = 0xdeadbeef;
1140 size = sizeof(status);
1141 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1142 ok(ret, "failed unexpectedly %u\n", GetLastError());
1143 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1145 WinHttpCloseHandle(req);
1147 req = WinHttpOpenRequest(con, empty, empty, empty, NULL, NULL, 0);
1148 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1150 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1151 error = GetLastError();
1152 if (!ret && (error == ERROR_WINHTTP_CANNOT_CONNECT || error == ERROR_WINHTTP_TIMEOUT))
1154 skip("connection failed, skipping\n");
1155 goto done;
1157 ok(ret, "failed to send request %u\n", GetLastError());
1159 ret = WinHttpReceiveResponse(req, NULL);
1160 ok(ret, "failed to receive response %u\n", GetLastError());
1162 size = 0;
1163 SetLastError(0xdeadbeef);
1164 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, NULL, &size, NULL);
1165 error = GetLastError();
1166 ok(!ret, "succeeded unexpectedly\n");
1167 ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error);
1169 version = HeapAlloc(GetProcessHeap(), 0, size);
1170 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, version, &size, NULL);
1171 ok(ret, "failed unexpectedly %u\n", GetLastError());
1172 ok(lstrlenW(version) == size / sizeof(WCHAR), "unexpected size %u\n", size);
1173 HeapFree(GetProcessHeap(), 0, version);
1175 status = 0xdeadbeef;
1176 size = sizeof(status);
1177 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1178 ok(ret, "failed unexpectedly %u\n", GetLastError());
1179 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1181 done:
1182 WinHttpCloseHandle(req);
1183 WinHttpCloseHandle(con);
1184 WinHttpCloseHandle(ses);
1187 static const WCHAR Connections[] = {
1188 'S','o','f','t','w','a','r','e','\\',
1189 'M','i','c','r','o','s','o','f','t','\\',
1190 'W','i','n','d','o','w','s','\\',
1191 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1192 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
1193 'C','o','n','n','e','c','t','i','o','n','s',0 };
1194 static const WCHAR WinHttpSettings[] = {
1195 'W','i','n','H','t','t','p','S','e','t','t','i','n','g','s',0 };
1197 static DWORD get_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD *type )
1199 LONG l;
1200 HKEY key;
1201 DWORD ret = 0;
1203 l = RegOpenKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, KEY_READ, &key );
1204 if (!l)
1206 DWORD size = 0;
1208 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, NULL, &size );
1209 if (!l)
1211 if (size <= len)
1212 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, buf,
1213 &size );
1214 if (!l)
1215 ret = size;
1217 RegCloseKey( key );
1219 return ret;
1222 static void set_proxy( REGSAM access, BYTE *buf, DWORD len, DWORD type )
1224 HKEY hkey;
1225 if (!RegCreateKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, NULL, 0, access, NULL, &hkey, NULL ))
1227 if (len) RegSetValueExW( hkey, WinHttpSettings, 0, type, buf, len );
1228 else RegDeleteValueW( hkey, WinHttpSettings );
1229 RegCloseKey( hkey );
1233 static void set_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD type )
1235 BOOL wow64;
1236 IsWow64Process( GetCurrentProcess(), &wow64 );
1237 if (sizeof(void *) > sizeof(int) || wow64)
1239 set_proxy( KEY_WRITE|KEY_WOW64_64KEY, buf, len, type );
1240 set_proxy( KEY_WRITE|KEY_WOW64_32KEY, buf, len, type );
1242 else
1243 set_proxy( KEY_WRITE, buf, len, type );
1246 static void test_set_default_proxy_config(void)
1248 static WCHAR wideString[] = { 0x226f, 0x575b, 0 };
1249 static WCHAR normalString[] = { 'f','o','o',0 };
1250 DWORD type, len;
1251 BYTE *saved_proxy_settings = NULL;
1252 WINHTTP_PROXY_INFO info;
1253 BOOL ret;
1255 /* FIXME: it would be simpler to read the current settings using
1256 * WinHttpGetDefaultProxyConfiguration and save them using
1257 * WinHttpSetDefaultProxyConfiguration, but they appear to have a bug.
1259 * If a proxy is configured in the registry, e.g. via 'proxcfg -p "foo"',
1260 * the access type reported by WinHttpGetDefaultProxyConfiguration is 1,
1261 * WINHTTP_ACCESS_TYPE_NO_PROXY, whereas it should be
1262 * WINHTTP_ACCESS_TYPE_NAMED_PROXY.
1263 * If WinHttpSetDefaultProxyConfiguration is called with dwAccessType = 1,
1264 * the lpszProxy and lpszProxyBypass values are ignored.
1265 * Thus, if a proxy is set with proxycfg, then calling
1266 * WinHttpGetDefaultProxyConfiguration followed by
1267 * WinHttpSetDefaultProxyConfiguration results in the proxy settings
1268 * getting deleted from the registry.
1270 * Instead I read the current registry value and restore it directly.
1272 len = get_default_proxy_reg_value( NULL, 0, &type );
1273 if (len)
1275 saved_proxy_settings = HeapAlloc( GetProcessHeap(), 0, len );
1276 len = get_default_proxy_reg_value( saved_proxy_settings, len, &type );
1279 if (0)
1281 /* Crashes on Vista and higher */
1282 SetLastError(0xdeadbeef);
1283 ret = WinHttpSetDefaultProxyConfiguration(NULL);
1284 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1285 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1288 /* test with invalid access type */
1289 info.dwAccessType = 0xdeadbeef;
1290 info.lpszProxy = info.lpszProxyBypass = NULL;
1291 SetLastError(0xdeadbeef);
1292 ret = WinHttpSetDefaultProxyConfiguration(&info);
1293 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1294 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1296 /* at a minimum, the proxy server must be set */
1297 info.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
1298 info.lpszProxy = info.lpszProxyBypass = NULL;
1299 SetLastError(0xdeadbeef);
1300 ret = WinHttpSetDefaultProxyConfiguration(&info);
1301 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1302 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1303 info.lpszProxyBypass = normalString;
1304 SetLastError(0xdeadbeef);
1305 ret = WinHttpSetDefaultProxyConfiguration(&info);
1306 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1307 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1309 /* the proxy server can't have wide characters */
1310 info.lpszProxy = wideString;
1311 SetLastError(0xdeadbeef);
1312 ret = WinHttpSetDefaultProxyConfiguration(&info);
1313 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1314 skip("couldn't set default proxy configuration: access denied\n");
1315 else
1316 ok((!ret && GetLastError() == ERROR_INVALID_PARAMETER) ||
1317 broken(ret), /* Earlier winhttp versions on W2K/XP */
1318 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1320 info.lpszProxy = normalString;
1321 SetLastError(0xdeadbeef);
1322 ret = WinHttpSetDefaultProxyConfiguration(&info);
1323 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1324 skip("couldn't set default proxy configuration: access denied\n");
1325 else
1327 ok(ret, "WinHttpSetDefaultProxyConfiguration failed: %u\n", GetLastError());
1328 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
1329 "got %u\n", GetLastError());
1331 set_default_proxy_reg_value( saved_proxy_settings, len, type );
1334 static void test_Timeouts (void)
1336 BOOL ret;
1337 DWORD value, size;
1338 HINTERNET ses, req, con;
1340 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1341 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1343 SetLastError(0xdeadbeef);
1344 ret = WinHttpSetTimeouts(ses, -2, 0, 0, 0);
1345 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1346 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1348 SetLastError(0xdeadbeef);
1349 ret = WinHttpSetTimeouts(ses, 0, -2, 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, 0, -2, 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, 0, -2);
1360 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1361 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1363 SetLastError(0xdeadbeef);
1364 ret = WinHttpSetTimeouts(ses, -1, -1, -1, -1);
1365 ok(ret, "%u\n", GetLastError());
1366 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
1367 "expected ERROR_SUCCESS, got %u\n", GetLastError());
1369 SetLastError(0xdeadbeef);
1370 ret = WinHttpSetTimeouts(ses, 0, 0, 0, 0);
1371 ok(ret, "%u\n", GetLastError());
1373 SetLastError(0xdeadbeef);
1374 ret = WinHttpSetTimeouts(ses, 0x0123, 0x4567, 0x89ab, 0xcdef);
1375 ok(ret, "%u\n", GetLastError());
1377 SetLastError(0xdeadbeef);
1378 value = 0xdeadbeef;
1379 size = sizeof(DWORD);
1380 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1381 ok(ret, "%u\n", GetLastError());
1382 ok(value == 0x0123, "Expected 0x0123, got %u\n", value);
1384 SetLastError(0xdeadbeef);
1385 value = 0xdeadbeef;
1386 size = sizeof(DWORD);
1387 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1388 ok(ret, "%u\n", GetLastError());
1389 ok(value == 0x4567, "Expected 0x4567, got %u\n", value);
1391 SetLastError(0xdeadbeef);
1392 value = 0xdeadbeef;
1393 size = sizeof(DWORD);
1394 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1395 ok(ret, "%u\n", GetLastError());
1396 ok(value == 0x89ab, "Expected 0x89ab, got %u\n", value);
1398 SetLastError(0xdeadbeef);
1399 value = 0xdeadbeef;
1400 size = sizeof(DWORD);
1401 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1402 ok(ret, "%u\n", GetLastError());
1403 ok(value == 0xcdef, "Expected 0xcdef, got %u\n", value);
1405 SetLastError(0xdeadbeef);
1406 value = 0;
1407 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1408 ok(ret, "%u\n", GetLastError());
1410 SetLastError(0xdeadbeef);
1411 value = 0xdeadbeef;
1412 size = sizeof(DWORD);
1413 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1414 ok(ret, "%u\n", GetLastError());
1415 ok(value == 0, "Expected 0, got %u\n", value);
1417 SetLastError(0xdeadbeef);
1418 value = 0;
1419 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1420 ok(ret, "%u\n", GetLastError());
1422 SetLastError(0xdeadbeef);
1423 value = 0xdeadbeef;
1424 size = sizeof(DWORD);
1425 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1426 ok(ret, "%u\n", GetLastError());
1427 ok(value == 0, "Expected 0, got %u\n", value);
1429 SetLastError(0xdeadbeef);
1430 value = 0;
1431 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1432 ok(ret, "%u\n", GetLastError());
1434 SetLastError(0xdeadbeef);
1435 value = 0xdeadbeef;
1436 size = sizeof(DWORD);
1437 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1438 ok(ret, "%u\n", GetLastError());
1439 ok(value == 0, "Expected 0, got %u\n", value);
1441 SetLastError(0xdeadbeef);
1442 value = 0;
1443 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1444 ok(ret, "%u\n", GetLastError());
1446 SetLastError(0xdeadbeef);
1447 value = 0xdeadbeef;
1448 size = sizeof(DWORD);
1449 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1450 ok(ret, "%u\n", GetLastError());
1451 ok(value == 0, "Expected 0, got %u\n", value);
1453 SetLastError(0xdeadbeef);
1454 value = 0xbeefdead;
1455 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1456 ok(ret, "%u\n", GetLastError());
1458 SetLastError(0xdeadbeef);
1459 value = 0xdeadbeef;
1460 size = sizeof(DWORD);
1461 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1462 ok(ret, "%u\n", GetLastError());
1463 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1465 SetLastError(0xdeadbeef);
1466 value = 0xbeefdead;
1467 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1468 ok(ret, "%u\n", GetLastError());
1470 SetLastError(0xdeadbeef);
1471 value = 0xdeadbeef;
1472 size = sizeof(DWORD);
1473 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1474 ok(ret, "%u\n", GetLastError());
1475 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1477 SetLastError(0xdeadbeef);
1478 value = 0xbeefdead;
1479 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1480 ok(ret, "%u\n", GetLastError());
1482 SetLastError(0xdeadbeef);
1483 value = 0xdeadbeef;
1484 size = sizeof(DWORD);
1485 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1486 ok(ret, "%u\n", GetLastError());
1487 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1489 SetLastError(0xdeadbeef);
1490 value = 0xbeefdead;
1491 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1492 ok(ret, "%u\n", GetLastError());
1494 SetLastError(0xdeadbeef);
1495 value = 0xdeadbeef;
1496 size = sizeof(DWORD);
1497 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1498 ok(ret, "%u\n", GetLastError());
1499 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1501 con = WinHttpConnect(ses, test_winehq, 0, 0);
1502 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1504 /* Timeout values should match the last one set for session */
1505 SetLastError(0xdeadbeef);
1506 value = 0xdeadbeef;
1507 size = sizeof(DWORD);
1508 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1509 ok(ret, "%u\n", GetLastError());
1510 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1512 SetLastError(0xdeadbeef);
1513 value = 0xdeadbeef;
1514 size = sizeof(DWORD);
1515 ret = WinHttpQueryOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1516 ok(ret, "%u\n", GetLastError());
1517 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1519 SetLastError(0xdeadbeef);
1520 value = 0xdeadbeef;
1521 size = sizeof(DWORD);
1522 ret = WinHttpQueryOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1523 ok(ret, "%u\n", GetLastError());
1524 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1526 SetLastError(0xdeadbeef);
1527 value = 0xdeadbeef;
1528 size = sizeof(DWORD);
1529 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1530 ok(ret, "%u\n", GetLastError());
1531 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1533 SetLastError(0xdeadbeef);
1534 ret = WinHttpSetTimeouts(con, -2, 0, 0, 0);
1535 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1536 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1538 SetLastError(0xdeadbeef);
1539 ret = WinHttpSetTimeouts(con, 0, -2, 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, 0, -2, 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, 0, -2);
1550 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1551 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1553 SetLastError(0xdeadbeef);
1554 ret = WinHttpSetTimeouts(con, -1, -1, -1, -1);
1555 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1556 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1558 SetLastError(0xdeadbeef);
1559 ret = WinHttpSetTimeouts(con, 0, 0, 0, 0);
1560 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1561 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1563 SetLastError(0xdeadbeef);
1564 value = 0;
1565 ret = WinHttpSetOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1566 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1567 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1569 SetLastError(0xdeadbeef);
1570 value = 0;
1571 ret = WinHttpSetOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1572 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1573 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1575 SetLastError(0xdeadbeef);
1576 value = 0;
1577 ret = WinHttpSetOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1578 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1579 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1581 SetLastError(0xdeadbeef);
1582 value = 0;
1583 ret = WinHttpSetOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1584 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1585 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1587 /* Changing timeout values for session should affect the values for connection */
1588 SetLastError(0xdeadbeef);
1589 value = 0xdead;
1590 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1591 ok(ret, "%u\n", GetLastError());
1593 SetLastError(0xdeadbeef);
1594 value = 0xdeadbeef;
1595 size = sizeof(DWORD);
1596 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1597 ok(ret, "%u\n", GetLastError());
1598 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1600 SetLastError(0xdeadbeef);
1601 value = 0xdead;
1602 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1603 ok(ret, "%u\n", GetLastError());
1605 SetLastError(0xdeadbeef);
1606 value = 0xdeadbeef;
1607 size = sizeof(DWORD);
1608 ret = WinHttpQueryOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1609 ok(ret, "%u\n", GetLastError());
1610 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1612 SetLastError(0xdeadbeef);
1613 value = 0xdead;
1614 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1615 ok(ret, "%u\n", GetLastError());
1617 SetLastError(0xdeadbeef);
1618 value = 0xdeadbeef;
1619 size = sizeof(DWORD);
1620 ret = WinHttpQueryOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1621 ok(ret, "%u\n", GetLastError());
1622 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1624 SetLastError(0xdeadbeef);
1625 value = 0xdead;
1626 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1627 ok(ret, "%u\n", GetLastError());
1629 SetLastError(0xdeadbeef);
1630 value = 0xdeadbeef;
1631 size = sizeof(DWORD);
1632 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1633 ok(ret, "%u\n", GetLastError());
1634 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1636 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1637 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1639 /* Timeout values should match the last one set for session */
1640 SetLastError(0xdeadbeef);
1641 value = 0xdeadbeef;
1642 size = sizeof(DWORD);
1643 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1644 ok(ret, "%u\n", GetLastError());
1645 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1647 SetLastError(0xdeadbeef);
1648 value = 0xdeadbeef;
1649 size = sizeof(DWORD);
1650 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1651 ok(ret, "%u\n", GetLastError());
1652 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1654 SetLastError(0xdeadbeef);
1655 value = 0xdeadbeef;
1656 size = sizeof(DWORD);
1657 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1658 ok(ret, "%u\n", GetLastError());
1659 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1661 SetLastError(0xdeadbeef);
1662 value = 0xdeadbeef;
1663 size = sizeof(DWORD);
1664 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1665 ok(ret, "%u\n", GetLastError());
1666 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1668 SetLastError(0xdeadbeef);
1669 ret = WinHttpSetTimeouts(req, -2, 0, 0, 0);
1670 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1671 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1673 SetLastError(0xdeadbeef);
1674 ret = WinHttpSetTimeouts(req, 0, -2, 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, 0, -2, 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, 0, -2);
1685 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1686 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1688 SetLastError(0xdeadbeef);
1689 ret = WinHttpSetTimeouts(req, -1, -1, -1, -1);
1690 ok(ret, "%u\n", GetLastError());
1692 SetLastError(0xdeadbeef);
1693 ret = WinHttpSetTimeouts(req, 0, 0, 0, 0);
1694 ok(ret, "%u\n", GetLastError());
1696 SetLastError(0xdeadbeef);
1697 ret = WinHttpSetTimeouts(req, 0xcdef, 0x89ab, 0x4567, 0x0123);
1698 ok(ret, "%u\n", GetLastError());
1700 SetLastError(0xdeadbeef);
1701 value = 0xdeadbeef;
1702 size = sizeof(DWORD);
1703 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1704 ok(ret, "%u\n", GetLastError());
1705 ok(value == 0xcdef, "Expected 0xcdef, got %u\n", value);
1707 SetLastError(0xdeadbeef);
1708 value = 0xdeadbeef;
1709 size = sizeof(DWORD);
1710 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1711 ok(ret, "%u\n", GetLastError());
1712 ok(value == 0x89ab, "Expected 0x89ab, got %u\n", value);
1714 SetLastError(0xdeadbeef);
1715 value = 0xdeadbeef;
1716 size = sizeof(DWORD);
1717 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1718 ok(ret, "%u\n", GetLastError());
1719 ok(value == 0x4567, "Expected 0x4567, got %u\n", value);
1721 SetLastError(0xdeadbeef);
1722 value = 0xdeadbeef;
1723 size = sizeof(DWORD);
1724 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1725 ok(ret, "%u\n", GetLastError());
1726 ok(value == 0x0123, "Expected 0x0123, got %u\n", value);
1728 SetLastError(0xdeadbeef);
1729 value = 0;
1730 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1731 ok(ret, "%u\n", GetLastError());
1733 SetLastError(0xdeadbeef);
1734 value = 0xdeadbeef;
1735 size = sizeof(DWORD);
1736 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1737 ok(ret, "%u\n", GetLastError());
1738 ok(value == 0, "Expected 0, got %u\n", value);
1740 SetLastError(0xdeadbeef);
1741 value = 0;
1742 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1743 ok(ret, "%u\n", GetLastError());
1745 SetLastError(0xdeadbeef);
1746 value = 0xdeadbeef;
1747 size = sizeof(DWORD);
1748 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1749 ok(ret, "%u\n", GetLastError());
1750 ok(value == 0, "Expected 0, got %u\n", value);
1752 SetLastError(0xdeadbeef);
1753 value = 0;
1754 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1755 ok(ret, "%u\n", GetLastError());
1757 SetLastError(0xdeadbeef);
1758 value = 0xdeadbeef;
1759 size = sizeof(DWORD);
1760 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1761 ok(ret, "%u\n", GetLastError());
1762 ok(value == 0, "Expected 0, got %u\n", value);
1764 SetLastError(0xdeadbeef);
1765 value = 0;
1766 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1767 ok(ret, "%u\n", GetLastError());
1769 SetLastError(0xdeadbeef);
1770 value = 0xdeadbeef;
1771 size = sizeof(DWORD);
1772 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1773 ok(ret, "%u\n", GetLastError());
1774 ok(value == 0, "Expected 0, got %u\n", value);
1776 SetLastError(0xdeadbeef);
1777 value = 0xbeefdead;
1778 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1779 ok(ret, "%u\n", GetLastError());
1781 SetLastError(0xdeadbeef);
1782 value = 0xdeadbeef;
1783 size = sizeof(DWORD);
1784 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1785 ok(ret, "%u\n", GetLastError());
1786 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1788 SetLastError(0xdeadbeef);
1789 value = 0xbeefdead;
1790 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1791 ok(ret, "%u\n", GetLastError());
1793 SetLastError(0xdeadbeef);
1794 value = 0xdeadbeef;
1795 size = sizeof(DWORD);
1796 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1797 ok(ret, "%u\n", GetLastError());
1798 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1800 SetLastError(0xdeadbeef);
1801 value = 0xbeefdead;
1802 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1803 ok(ret, "%u\n", GetLastError());
1805 SetLastError(0xdeadbeef);
1806 value = 0xdeadbeef;
1807 size = sizeof(DWORD);
1808 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1809 ok(ret, "%u\n", GetLastError());
1810 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1812 SetLastError(0xdeadbeef);
1813 value = 0xbeefdead;
1814 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1815 ok(ret, "%u\n", GetLastError());
1817 SetLastError(0xdeadbeef);
1818 value = 0xdeadbeef;
1819 size = sizeof(DWORD);
1820 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1821 ok(ret, "%u\n", GetLastError());
1822 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1824 /* Changing timeout values for session should not affect the values for a request,
1825 * neither should the other way around.
1827 SetLastError(0xdeadbeef);
1828 value = 0xbeefdead;
1829 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1830 ok(ret, "%u\n", GetLastError());
1832 SetLastError(0xdeadbeef);
1833 value = 0xdeadbeef;
1834 size = sizeof(DWORD);
1835 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1836 ok(ret, "%u\n", GetLastError());
1837 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1839 SetLastError(0xdeadbeef);
1840 value = 0xbeefdead;
1841 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1842 ok(ret, "%u\n", GetLastError());
1844 SetLastError(0xdeadbeef);
1845 value = 0xdeadbeef;
1846 size = sizeof(DWORD);
1847 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1848 ok(ret, "%u\n", GetLastError());
1849 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1851 SetLastError(0xdeadbeef);
1852 value = 0xbeefdead;
1853 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1854 ok(ret, "%u\n", GetLastError());
1856 SetLastError(0xdeadbeef);
1857 value = 0xdeadbeef;
1858 size = sizeof(DWORD);
1859 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1860 ok(ret, "%u\n", GetLastError());
1861 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1863 SetLastError(0xdeadbeef);
1864 value = 0xbeefdead;
1865 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1866 ok(ret, "%u\n", GetLastError());
1868 SetLastError(0xdeadbeef);
1869 value = 0xdeadbeef;
1870 size = sizeof(DWORD);
1871 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1872 ok(ret, "%u\n", GetLastError());
1873 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1875 SetLastError(0xdeadbeef);
1876 value = 0xbeef;
1877 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1878 ok(ret, "%u\n", GetLastError());
1880 SetLastError(0xdeadbeef);
1881 value = 0xdeadbeef;
1882 size = sizeof(DWORD);
1883 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1884 ok(ret, "%u\n", GetLastError());
1885 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1887 SetLastError(0xdeadbeef);
1888 value = 0xbeef;
1889 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1890 ok(ret, "%u\n", GetLastError());
1892 SetLastError(0xdeadbeef);
1893 value = 0xdeadbeef;
1894 size = sizeof(DWORD);
1895 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1896 ok(ret, "%u\n", GetLastError());
1897 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1899 SetLastError(0xdeadbeef);
1900 value = 0xbeef;
1901 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1902 ok(ret, "%u\n", GetLastError());
1904 SetLastError(0xdeadbeef);
1905 value = 0xdeadbeef;
1906 size = sizeof(DWORD);
1907 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1908 ok(ret, "%u\n", GetLastError());
1909 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1911 SetLastError(0xdeadbeef);
1912 value = 0xbeef;
1913 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1914 ok(ret, "%u\n", GetLastError());
1916 SetLastError(0xdeadbeef);
1917 value = 0xdeadbeef;
1918 size = sizeof(DWORD);
1919 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1920 ok(ret, "%u\n", GetLastError());
1921 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1923 WinHttpCloseHandle(req);
1924 WinHttpCloseHandle(con);
1925 WinHttpCloseHandle(ses);
1928 static void test_resolve_timeout(void)
1930 static const WCHAR nxdomain[] =
1931 {'n','x','d','o','m','a','i','n','.','w','i','n','e','h','q','.','o','r','g',0};
1932 HINTERNET ses, con, req;
1933 DWORD timeout;
1934 BOOL ret;
1936 if (! proxy_active())
1938 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1939 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1941 timeout = 10000;
1942 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
1943 ok(ret, "failed to set resolve timeout %u\n", GetLastError());
1945 con = WinHttpConnect(ses, nxdomain, 0, 0);
1946 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1948 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1949 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1951 SetLastError(0xdeadbeef);
1952 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1953 if (ret)
1955 skip("nxdomain returned success. Broken ISP redirects?\n");
1956 goto done;
1958 ok(GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED,
1959 "expected ERROR_WINHTTP_NAME_NOT_RESOLVED got %u\n", GetLastError());
1961 WinHttpCloseHandle(req);
1962 WinHttpCloseHandle(con);
1963 WinHttpCloseHandle(ses);
1965 else
1966 skip("Skipping host resolution tests, host resolution preformed by proxy\n");
1968 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1969 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1971 timeout = 10000;
1972 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
1973 ok(ret, "failed to set resolve timeout %u\n", GetLastError());
1975 con = WinHttpConnect(ses, test_winehq, 0, 0);
1976 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1978 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1979 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1981 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1982 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
1984 skip("connection failed, skipping\n");
1985 goto done;
1987 ok(ret, "failed to send request\n");
1989 done:
1990 WinHttpCloseHandle(req);
1991 WinHttpCloseHandle(con);
1992 WinHttpCloseHandle(ses);
1995 static const char page1[] =
1996 "<HTML>\r\n"
1997 "<HEAD><TITLE>winhttp test page</TITLE></HEAD>\r\n"
1998 "<BODY>The quick brown fox jumped over the lazy dog<P></BODY>\r\n"
1999 "</HTML>\r\n\r\n";
2001 static const char okmsg[] =
2002 "HTTP/1.1 200 OK\r\n"
2003 "Server: winetest\r\n"
2004 "\r\n";
2006 static const char notokmsg[] =
2007 "HTTP/1.1 400 Bad Request\r\n"
2008 "\r\n";
2010 static const char cookiemsg[] =
2011 "HTTP/1.1 200 OK\r\n"
2012 "Set-Cookie: name = value \r\n"
2013 "Set-Cookie: NAME = value \r\n"
2014 "\r\n";
2016 static const char cookiemsg2[] =
2017 "HTTP/1.1 200 OK\r\n"
2018 "Set-Cookie: name2=value; Domain = localhost; Path=/cookie5;Expires=Wed, 13 Jan 2021 22:23:01 GMT; HttpOnly; \r\n"
2019 "\r\n";
2021 static const char nocontentmsg[] =
2022 "HTTP/1.1 204 No Content\r\n"
2023 "Server: winetest\r\n"
2024 "\r\n";
2026 static const char notmodified[] =
2027 "HTTP/1.1 304 Not Modified\r\n"
2028 "\r\n";
2030 static const char noauthmsg[] =
2031 "HTTP/1.1 401 Unauthorized\r\n"
2032 "Server: winetest\r\n"
2033 "Connection: close\r\n"
2034 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
2035 "Content-Length: 12\r\n"
2036 "Content-Type: text/plain\r\n"
2037 "\r\n";
2039 static const char okauthmsg[] =
2040 "HTTP/1.1 200 OK\r\n"
2041 "Server: winetest\r\n"
2042 "Connection: close\r\n"
2043 "Content-Length: 11\r\n"
2044 "Content-Type: text/plain\r\n"
2045 "\r\n";
2047 static const char headmsg[] =
2048 "HTTP/1.1 200 OK\r\n"
2049 "Content-Length: 100\r\n"
2050 "\r\n";
2052 static const char unauthorized[] = "Unauthorized";
2053 static const char hello_world[] = "Hello World";
2055 struct server_info
2057 HANDLE event;
2058 int port;
2061 #define BIG_BUFFER_LEN 0x2250
2063 static DWORD CALLBACK server_thread(LPVOID param)
2065 struct server_info *si = param;
2066 int r, c = -1, i, on;
2067 SOCKET s;
2068 struct sockaddr_in sa;
2069 char buffer[0x100];
2070 WSADATA wsaData;
2071 int last_request = 0;
2073 WSAStartup(MAKEWORD(1,1), &wsaData);
2075 s = socket(AF_INET, SOCK_STREAM, 0);
2076 if (s == INVALID_SOCKET)
2077 return 1;
2079 on = 1;
2080 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof on);
2082 memset(&sa, 0, sizeof sa);
2083 sa.sin_family = AF_INET;
2084 sa.sin_port = htons(si->port);
2085 sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
2087 r = bind(s, (struct sockaddr *)&sa, sizeof(sa));
2088 if (r < 0)
2089 return 1;
2091 listen(s, 0);
2092 SetEvent(si->event);
2095 if (c == -1) c = accept(s, NULL, NULL);
2097 memset(buffer, 0, sizeof buffer);
2098 for(i = 0; i < sizeof buffer - 1; i++)
2100 r = recv(c, &buffer[i], 1, 0);
2101 if (r != 1)
2102 break;
2103 if (i < 4) continue;
2104 if (buffer[i - 2] == '\n' && buffer[i] == '\n' &&
2105 buffer[i - 3] == '\r' && buffer[i - 1] == '\r')
2106 break;
2108 if (strstr(buffer, "GET /basic"))
2110 send(c, okmsg, sizeof okmsg - 1, 0);
2111 send(c, page1, sizeof page1 - 1, 0);
2113 if (strstr(buffer, "/auth"))
2115 if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
2117 send(c, okauthmsg, sizeof okauthmsg - 1, 0);
2118 send(c, hello_world, sizeof hello_world - 1, 0);
2120 else
2122 send(c, noauthmsg, sizeof noauthmsg - 1, 0);
2123 send(c, unauthorized, sizeof unauthorized - 1, 0);
2125 continue;
2127 if (strstr(buffer, "/big"))
2129 char msg[BIG_BUFFER_LEN];
2130 memset(msg, 'm', sizeof(msg));
2131 send(c, okmsg, sizeof(okmsg) - 1, 0);
2132 send(c, msg, sizeof(msg), 0);
2134 if (strstr(buffer, "/no_headers"))
2136 send(c, page1, sizeof page1 - 1, 0);
2138 if (strstr(buffer, "GET /no_content"))
2140 send(c, nocontentmsg, sizeof nocontentmsg - 1, 0);
2141 continue;
2143 if (strstr(buffer, "GET /not_modified"))
2145 if (strstr(buffer, "If-Modified-Since:")) send(c, notmodified, sizeof notmodified - 1, 0);
2146 else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2147 continue;
2149 if (strstr(buffer, "HEAD /head"))
2151 send(c, headmsg, sizeof headmsg - 1, 0);
2152 continue;
2154 if (strstr(buffer, "GET /cookie5"))
2156 if (strstr(buffer, "Cookie: name2=value\r\n"))
2157 send(c, okmsg, sizeof(okmsg) - 1, 0);
2158 else
2159 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2161 if (strstr(buffer, "GET /cookie4"))
2163 send(c, cookiemsg2, sizeof(cookiemsg2) - 1, 0);
2165 if (strstr(buffer, "GET /cookie3"))
2167 if (strstr(buffer, "Cookie: name=value2; NAME=value; name=value\r\n") ||
2168 broken(strstr(buffer, "Cookie: name=value2; name=value; NAME=value\r\n") != NULL))
2169 send(c, okmsg, sizeof(okmsg) - 1, 0);
2170 else
2171 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2173 if (strstr(buffer, "GET /cookie2"))
2175 if (strstr(buffer, "Cookie: NAME=value; name=value\r\n") ||
2176 broken(strstr(buffer, "Cookie: name=value; NAME=value\r\n") != NULL))
2177 send(c, okmsg, sizeof(okmsg) - 1, 0);
2178 else
2179 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2181 else if (strstr(buffer, "GET /cookie"))
2183 if (!strstr(buffer, "Cookie: name=value\r\n")) send(c, cookiemsg, sizeof(cookiemsg) - 1, 0);
2184 else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2186 if (strstr(buffer, "GET /quit"))
2188 send(c, okmsg, sizeof okmsg - 1, 0);
2189 send(c, page1, sizeof page1 - 1, 0);
2190 last_request = 1;
2192 shutdown(c, 2);
2193 closesocket(c);
2194 c = -1;
2196 } while (!last_request);
2198 closesocket(s);
2199 return 0;
2202 static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path)
2204 static const WCHAR test_header_end_clrf[] = {'\r','\n','\r','\n',0};
2205 static const WCHAR test_header_end_raw[] = {0,0};
2206 HINTERNET ses, con, req;
2207 char buffer[0x100];
2208 WCHAR buffer2[0x100];
2209 DWORD count, status, size, error, supported, first, target;
2210 BOOL ret;
2212 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2213 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2215 con = WinHttpConnect(ses, localhostW, port, 0);
2216 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2218 req = WinHttpOpenRequest(con, verb, path, NULL, NULL, NULL, 0);
2219 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2221 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2222 ok(ret, "failed to send request %u\n", GetLastError());
2224 ret = WinHttpReceiveResponse(req, NULL);
2225 ok(ret, "failed to receive response %u\n", GetLastError());
2227 status = 0xdeadbeef;
2228 size = sizeof(status);
2229 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2230 ok(ret, "failed to query status code %u\n", GetLastError());
2231 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2233 supported = first = target = 0xdeadbeef;
2234 SetLastError(0xdeadbeef);
2235 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2236 error = GetLastError();
2237 ok(!ret, "unexpected success\n");
2238 todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
2239 ok(supported == 0xdeadbeef, "got %x\n", supported);
2240 ok(first == 0xdeadbeef, "got %x\n", first);
2241 ok(target == 0xdeadbeef, "got %x\n", target);
2243 size = sizeof(buffer2);
2244 memset(buffer2, 0, sizeof(buffer2));
2245 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, buffer2, &size, NULL);
2246 ok(ret, "failed to query for raw headers: %u\n", GetLastError());
2247 ok(!memcmp(buffer2 + lstrlenW(buffer2) - 4, test_header_end_clrf, sizeof(test_header_end_clrf)),
2248 "WinHttpQueryHeaders returned invalid end of header string\n");
2250 size = sizeof(buffer2);
2251 memset(buffer2, 0, sizeof(buffer2));
2252 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS, NULL, buffer2, &size, NULL);
2253 ok(ret, "failed to query for raw headers: %u\n", GetLastError());
2254 ok(!memcmp(buffer2 + (size / sizeof(WCHAR)) - 1, test_header_end_raw, sizeof(test_header_end_raw)),
2255 "WinHttpQueryHeaders returned invalid end of header string\n");
2256 ok(buffer2[(size / sizeof(WCHAR)) - 2] != 0, "returned string has too many NULL characters\n");
2258 count = 0;
2259 memset(buffer, 0, sizeof(buffer));
2260 ret = WinHttpReadData(req, buffer, sizeof buffer, &count);
2261 ok(ret, "failed to read data %u\n", GetLastError());
2262 ok(count == sizeof page1 - 1, "count was wrong\n");
2263 ok(!memcmp(buffer, page1, sizeof page1), "http data wrong\n");
2265 WinHttpCloseHandle(req);
2266 WinHttpCloseHandle(con);
2267 WinHttpCloseHandle(ses);
2270 static void test_basic_authentication(int port)
2272 static const WCHAR authW[] = {'/','a','u','t','h',0};
2273 static WCHAR userW[] = {'u','s','e','r',0};
2274 static WCHAR passW[] = {'p','w','d',0};
2275 static WCHAR pass2W[] = {'p','w','d','2',0};
2276 HINTERNET ses, con, req;
2277 DWORD status, size, error, supported, first, target;
2278 char buffer[32];
2279 BOOL ret;
2281 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2282 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2284 con = WinHttpConnect(ses, localhostW, port, 0);
2285 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2287 req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2288 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2290 SetLastError(0xdeadbeef);
2291 ret = WinHttpQueryAuthSchemes(NULL, NULL, NULL, NULL);
2292 error = GetLastError();
2293 ok(!ret, "expected failure\n");
2294 ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
2296 SetLastError(0xdeadbeef);
2297 ret = WinHttpQueryAuthSchemes(req, NULL, NULL, NULL);
2298 error = GetLastError();
2299 ok(!ret, "expected failure\n");
2300 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2302 supported = 0xdeadbeef;
2303 SetLastError(0xdeadbeef);
2304 ret = WinHttpQueryAuthSchemes(req, &supported, NULL, NULL);
2305 error = GetLastError();
2306 ok(!ret, "expected failure\n");
2307 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2308 ok(supported == 0xdeadbeef, "got %x\n", supported);
2310 supported = first = 0xdeadbeef;
2311 SetLastError(0xdeadbeef);
2312 ret = WinHttpQueryAuthSchemes(req, &supported, &first, NULL);
2313 error = GetLastError();
2314 ok(!ret, "expected failure\n");
2315 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2316 ok(supported == 0xdeadbeef, "got %x\n", supported);
2317 ok(first == 0xdeadbeef, "got %x\n", first);
2319 supported = first = target = 0xdeadbeef;
2320 SetLastError(0xdeadbeef);
2321 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2322 error = GetLastError();
2323 ok(!ret, "expected failure\n");
2324 todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
2325 ok(supported == 0xdeadbeef, "got %x\n", supported);
2326 ok(first == 0xdeadbeef, "got %x\n", first);
2327 ok(target == 0xdeadbeef, "got %x\n", target);
2329 supported = first = target = 0xdeadbeef;
2330 SetLastError(0xdeadbeef);
2331 ret = WinHttpQueryAuthSchemes(NULL, &supported, &first, &target);
2332 error = GetLastError();
2333 ok(!ret, "expected failure\n");
2334 ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
2335 ok(supported == 0xdeadbeef, "got %x\n", supported);
2336 ok(first == 0xdeadbeef, "got %x\n", first);
2337 ok(target == 0xdeadbeef, "got %x\n", target);
2339 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2340 ok(ret, "failed to send request %u\n", GetLastError());
2342 ret = WinHttpReceiveResponse(req, NULL);
2343 ok(ret, "failed to receive response %u\n", GetLastError());
2345 status = 0xdeadbeef;
2346 size = sizeof(status);
2347 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2348 ok(ret, "failed to query status code %u\n", GetLastError());
2349 ok(status == HTTP_STATUS_DENIED, "request failed unexpectedly %u\n", status);
2351 size = 0;
2352 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
2353 error = GetLastError();
2354 ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError());
2355 if (ret)
2357 ok(size == 12, "expected 12, got %u\n", size);
2358 ok(!memcmp(buffer, unauthorized, 12), "got %s\n", buffer);
2361 supported = first = target = 0xdeadbeef;
2362 SetLastError(0xdeadbeef);
2363 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2364 error = GetLastError();
2365 ok(ret, "failed to query authentication schemes %u\n", error);
2366 ok(error == ERROR_SUCCESS || broken(error == 0xdeadbeef) /* < win7 */, "expected ERROR_SUCCESS, got %u\n", error);
2367 ok(supported == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", supported);
2368 ok(first == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", first);
2369 ok(target == WINHTTP_AUTH_TARGET_SERVER, "got %x\n", target);
2371 SetLastError(0xdeadbeef);
2372 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NTLM, NULL, NULL, NULL);
2373 error = GetLastError();
2374 ok(ret, "failed to set credentials %u\n", error);
2375 ok(error == ERROR_SUCCESS || broken(error == 0xdeadbeef) /* < win7 */, "expected ERROR_SUCCESS, got %u\n", error);
2377 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_PASSPORT, NULL, NULL, NULL);
2378 ok(ret, "failed to set credentials %u\n", GetLastError());
2380 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NEGOTIATE, NULL, NULL, NULL);
2381 ok(ret, "failed to set credentials %u\n", GetLastError());
2383 SetLastError(0xdeadbeef);
2384 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_DIGEST, NULL, NULL, NULL);
2385 error = GetLastError();
2386 ok(!ret, "expected failure\n");
2387 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2389 SetLastError(0xdeadbeef);
2390 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, NULL, NULL);
2391 error = GetLastError();
2392 ok(!ret, "expected failure\n");
2393 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2395 SetLastError(0xdeadbeef);
2396 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, NULL, NULL);
2397 error = GetLastError();
2398 ok(!ret, "expected failure\n");
2399 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2401 SetLastError(0xdeadbeef);
2402 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, passW, NULL);
2403 error = GetLastError();
2404 ok(!ret, "expected failure\n");
2405 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2407 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
2408 ok(ret, "failed to set credentials %u\n", GetLastError());
2410 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2411 ok(ret, "failed to send request %u\n", GetLastError());
2413 ret = WinHttpReceiveResponse(req, NULL);
2414 ok(ret, "failed to receive response %u\n", GetLastError());
2416 status = 0xdeadbeef;
2417 size = sizeof(status);
2418 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2419 ok(ret, "failed to query status code %u\n", GetLastError());
2420 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2422 size = 0;
2423 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
2424 error = GetLastError();
2425 ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError());
2426 if (ret)
2428 ok(size == 11, "expected 11, got %u\n", size);
2429 ok(!memcmp(buffer, hello_world, 11), "got %s\n", buffer);
2432 WinHttpCloseHandle(req);
2433 WinHttpCloseHandle(con);
2434 WinHttpCloseHandle(ses);
2436 /* credentials set with WinHttpSetCredentials take precedence over those set through options */
2438 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2439 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2441 con = WinHttpConnect(ses, localhostW, port, 0);
2442 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2444 req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2445 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2447 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
2448 ok(ret, "failed to set credentials %u\n", GetLastError());
2450 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
2451 ok(ret, "failed to set username %u\n", GetLastError());
2453 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, pass2W, lstrlenW(pass2W));
2454 ok(ret, "failed to set password %u\n", GetLastError());
2456 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2457 ok(ret, "failed to send request %u\n", GetLastError());
2459 ret = WinHttpReceiveResponse(req, NULL);
2460 ok(ret, "failed to receive response %u\n", GetLastError());
2462 status = 0xdeadbeef;
2463 size = sizeof(status);
2464 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2465 ok(ret, "failed to query status code %u\n", GetLastError());
2466 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2468 WinHttpCloseHandle(req);
2469 WinHttpCloseHandle(con);
2470 WinHttpCloseHandle(ses);
2472 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2473 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2475 con = WinHttpConnect(ses, localhostW, port, 0);
2476 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2478 req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2479 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2481 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
2482 ok(ret, "failed to set username %u\n", GetLastError());
2484 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, passW, lstrlenW(passW));
2485 ok(ret, "failed to set password %u\n", GetLastError());
2487 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, pass2W, NULL);
2488 ok(ret, "failed to set credentials %u\n", GetLastError());
2490 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2491 ok(ret, "failed to send request %u\n", GetLastError());
2493 ret = WinHttpReceiveResponse(req, NULL);
2494 ok(ret, "failed to receive response %u\n", GetLastError());
2496 status = 0xdeadbeef;
2497 size = sizeof(status);
2498 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2499 ok(ret, "failed to query status code %u\n", GetLastError());
2500 ok(status == HTTP_STATUS_DENIED, "request failed unexpectedly %u\n", status);
2502 WinHttpCloseHandle(req);
2503 WinHttpCloseHandle(con);
2504 WinHttpCloseHandle(ses);
2507 static void test_no_headers(int port)
2509 static const WCHAR no_headersW[] = {'/','n','o','_','h','e','a','d','e','r','s',0};
2510 HINTERNET ses, con, req;
2511 DWORD error;
2512 BOOL ret;
2514 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2515 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2517 con = WinHttpConnect(ses, localhostW, port, 0);
2518 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2520 req = WinHttpOpenRequest(con, NULL, no_headersW, NULL, NULL, NULL, 0);
2521 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2523 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2524 if (!ret)
2526 error = GetLastError();
2527 ok(error == ERROR_WINHTTP_INVALID_SERVER_RESPONSE, "got %u\n", error);
2529 else
2531 SetLastError(0xdeadbeef);
2532 ret = WinHttpReceiveResponse(req, NULL);
2533 error = GetLastError();
2534 ok(!ret, "expected failure\n");
2535 ok(error == ERROR_WINHTTP_INVALID_SERVER_RESPONSE, "got %u\n", error);
2538 WinHttpCloseHandle(req);
2539 WinHttpCloseHandle(con);
2540 WinHttpCloseHandle(ses);
2543 static void test_no_content(int port)
2545 static const WCHAR no_contentW[] = {'/','n','o','_','c','o','n','t','e','n','t',0};
2546 HINTERNET ses, con, req;
2547 char buf[128];
2548 DWORD size, len = sizeof(buf), bytes_read, status;
2549 BOOL ret;
2551 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2552 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2554 con = WinHttpConnect(ses, localhostW, port, 0);
2555 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2557 req = WinHttpOpenRequest(con, NULL, no_contentW, NULL, NULL, NULL, 0);
2558 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2560 size = 12345;
2561 SetLastError(0xdeadbeef);
2562 ret = WinHttpQueryDataAvailable(req, &size);
2563 todo_wine {
2564 ok(!ret, "expected error\n");
2565 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_STATE,
2566 "expected ERROR_WINHTTP_INCORRECT_HANDLE_STATE, got 0x%08x\n", GetLastError());
2567 ok(size == 12345 || broken(size == 0) /* Win <= 2003 */,
2568 "expected 12345, got %u\n", size);
2571 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2572 ok(ret, "expected success\n");
2574 ret = WinHttpReceiveResponse(req, NULL);
2575 ok(ret, "expected success\n");
2577 status = 0xdeadbeef;
2578 size = sizeof(status);
2579 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
2580 NULL, &status, &size, NULL);
2581 ok(ret, "expected success\n");
2582 ok(status == HTTP_STATUS_NO_CONTENT, "expected status 204, got %d\n", status);
2584 SetLastError(0xdeadbeef);
2585 size = sizeof(status);
2586 status = 12345;
2587 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
2588 NULL, &status, &size, 0);
2589 ok(!ret, "expected no content-length header\n");
2590 ok(GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND, "wrong error %u\n", GetLastError());
2591 ok(status == 12345, "expected 0, got %d\n", status);
2593 SetLastError(0xdeadbeef);
2594 size = 12345;
2595 ret = WinHttpQueryDataAvailable(req, &size);
2596 ok(ret, "expected success\n");
2597 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
2598 "wrong error %u\n", GetLastError());
2599 ok(!size, "expected 0, got %u\n", size);
2601 SetLastError(0xdeadbeef);
2602 ret = WinHttpReadData(req, buf, len, &bytes_read);
2603 ok(ret, "expected success\n");
2604 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
2605 "wrong error %u\n", GetLastError());
2606 ok(!bytes_read, "expected 0, got %u\n", bytes_read);
2608 size = 12345;
2609 ret = WinHttpQueryDataAvailable(req, &size);
2610 ok(ret, "expected success\n");
2611 ok(size == 0, "expected 0, got %d\n", size);
2613 WinHttpCloseHandle(req);
2615 size = 12345;
2616 SetLastError(0xdeadbeef);
2617 ret = WinHttpQueryDataAvailable(req, &size);
2618 ok(!ret, "expected error\n");
2619 ok(GetLastError() == ERROR_INVALID_HANDLE,
2620 "expected ERROR_INVALID_HANDLE, got 0x%08x\n", GetLastError());
2621 ok(size == 12345, "expected 12345, got %u\n", size);
2623 WinHttpCloseHandle(con);
2624 WinHttpCloseHandle(ses);
2627 static void test_head_request(int port)
2629 static const WCHAR verbW[] = {'H','E','A','D',0};
2630 static const WCHAR headW[] = {'/','h','e','a','d',0};
2631 HINTERNET ses, con, req;
2632 char buf[128];
2633 DWORD size, len, count, status;
2634 BOOL ret;
2636 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2637 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2639 con = WinHttpConnect(ses, localhostW, port, 0);
2640 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2642 req = WinHttpOpenRequest(con, verbW, headW, NULL, NULL, NULL, 0);
2643 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2645 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2646 ok(ret, "failed to send request %u\n", GetLastError());
2648 ret = WinHttpReceiveResponse(req, NULL);
2649 ok(ret, "failed to receive response %u\n", GetLastError());
2651 status = 0xdeadbeef;
2652 size = sizeof(status);
2653 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
2654 NULL, &status, &size, NULL);
2655 ok(ret, "failed to get status code %u\n", GetLastError());
2656 ok(status == HTTP_STATUS_OK, "got %u\n", status);
2658 len = 0xdeadbeef;
2659 size = sizeof(len);
2660 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
2661 NULL, &len, &size, 0);
2662 ok(ret, "failed to get content-length header %u\n", GetLastError());
2663 ok(len == HTTP_STATUS_CONTINUE, "got %u\n", len);
2665 count = 0xdeadbeef;
2666 ret = WinHttpQueryDataAvailable(req, &count);
2667 ok(ret, "failed to query data available %u\n", GetLastError());
2668 ok(!count, "got %u\n", count);
2670 len = sizeof(buf);
2671 count = 0xdeadbeef;
2672 ret = WinHttpReadData(req, buf, len, &count);
2673 ok(ret, "failed to read data %u\n", GetLastError());
2674 ok(!count, "got %u\n", count);
2676 count = 0xdeadbeef;
2677 ret = WinHttpQueryDataAvailable(req, &count);
2678 ok(ret, "failed to query data available %u\n", GetLastError());
2679 ok(!count, "got %u\n", count);
2681 WinHttpCloseHandle(req);
2682 WinHttpCloseHandle(con);
2683 WinHttpCloseHandle(ses);
2686 static void test_not_modified(int port)
2688 static const WCHAR pathW[] = {'/','n','o','t','_','m','o','d','i','f','i','e','d',0};
2689 static const WCHAR ifmodifiedW[] = {'I','f','-','M','o','d','i','f','i','e','d','-','S','i','n','c','e',':',' '};
2690 static const WCHAR ifmodified2W[] = {'I','f','-','M','o','d','i','f','i','e','d','-','S','i','n','c','e',0};
2691 BOOL ret;
2692 HINTERNET session, request, connection;
2693 DWORD index, len, status, size, start = GetTickCount();
2694 SYSTEMTIME st;
2695 WCHAR today[(sizeof(ifmodifiedW) + WINHTTP_TIME_FORMAT_BUFSIZE)/sizeof(WCHAR) + 3], buffer[32];
2697 memcpy(today, ifmodifiedW, sizeof(ifmodifiedW));
2698 GetSystemTime(&st);
2699 WinHttpTimeFromSystemTime(&st, &today[sizeof(ifmodifiedW)/sizeof(WCHAR)]);
2701 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY,
2702 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
2703 ok(session != NULL, "WinHttpOpen failed: %u\n", GetLastError());
2705 connection = WinHttpConnect(session, localhostW, port, 0);
2706 ok(connection != NULL, "WinHttpConnect failed: %u\n", GetLastError());
2708 request = WinHttpOpenRequest(connection, NULL, pathW, NULL, WINHTTP_NO_REFERER,
2709 WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
2710 ok(request != NULL, "WinHttpOpenrequest failed: %u\n", GetLastError());
2712 ret = WinHttpSendRequest(request, today, 0, NULL, 0, 0, 0);
2713 ok(ret, "WinHttpSendRequest failed: %u\n", GetLastError());
2715 ret = WinHttpReceiveResponse(request, NULL);
2716 ok(ret, "WinHttpReceiveResponse failed: %u\n", GetLastError());
2718 index = 0;
2719 len = sizeof(buffer);
2720 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
2721 ifmodified2W, buffer, &len, &index);
2722 ok(ret, "failed to get header %u\n", GetLastError());
2724 status = 0xdeadbeef;
2725 size = sizeof(status);
2726 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER,
2727 NULL, &status, &size, NULL);
2728 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
2729 ok(status == HTTP_STATUS_NOT_MODIFIED, "got %u\n", status);
2731 size = 0xdeadbeef;
2732 ret = WinHttpQueryDataAvailable(request, &size);
2733 ok(ret, "WinHttpQueryDataAvailable failed: %u\n", GetLastError());
2734 ok(!size, "got %u\n", size);
2736 WinHttpCloseHandle(request);
2737 WinHttpCloseHandle(connection);
2738 WinHttpCloseHandle(session);
2739 start = GetTickCount() - start;
2740 ok(start <= 2000, "Expected less than 2 seconds for the test, got %u ms\n", start);
2743 static void test_bad_header( int port )
2745 static const WCHAR bad_headerW[] =
2746 {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ',
2747 't','e','x','t','/','h','t','m','l','\n','\r',0};
2748 static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
2749 static const WCHAR content_typeW[] = {'C','o','n','t','e','n','t','-','T','y','p','e',0};
2750 WCHAR buffer[32];
2751 HINTERNET ses, con, req;
2752 DWORD index, len;
2753 BOOL ret;
2755 ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
2756 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
2758 con = WinHttpConnect( ses, localhostW, port, 0 );
2759 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2761 req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
2762 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2764 ret = WinHttpAddRequestHeaders( req, bad_headerW, ~0u, WINHTTP_ADDREQ_FLAG_ADD );
2765 ok( ret, "failed to add header %u\n", GetLastError() );
2767 index = 0;
2768 buffer[0] = 0;
2769 len = sizeof(buffer);
2770 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_CUSTOM|WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
2771 content_typeW, buffer, &len, &index );
2772 ok( ret, "failed to query headers %u\n", GetLastError() );
2773 ok( !lstrcmpW( buffer, text_htmlW ), "got %s\n", wine_dbgstr_w(buffer) );
2775 WinHttpCloseHandle( req );
2776 WinHttpCloseHandle( con );
2777 WinHttpCloseHandle( ses );
2780 static void test_multiple_reads(int port)
2782 static const WCHAR bigW[] = {'b','i','g',0};
2783 HINTERNET ses, con, req;
2784 DWORD total_len = 0;
2785 BOOL ret;
2787 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2788 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2790 con = WinHttpConnect(ses, localhostW, port, 0);
2791 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2793 req = WinHttpOpenRequest(con, NULL, bigW, NULL, NULL, NULL, 0);
2794 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2796 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2797 ok(ret, "failed to send request %u\n", GetLastError());
2799 ret = WinHttpReceiveResponse(req, NULL);
2800 ok(ret == TRUE, "expected success\n");
2802 for (;;)
2804 DWORD len = 0xdeadbeef;
2805 ret = WinHttpQueryDataAvailable( req, &len );
2806 ok( ret, "WinHttpQueryDataAvailable failed with error %u\n", GetLastError() );
2807 if (ret) ok( len != 0xdeadbeef, "WinHttpQueryDataAvailable return wrong length\n" );
2808 if (len)
2810 DWORD bytes_read;
2811 char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 );
2813 ret = WinHttpReadData( req, buf, len, &bytes_read );
2814 ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len );
2816 HeapFree( GetProcessHeap(), 0, buf );
2817 if (!bytes_read) break;
2818 total_len += bytes_read;
2820 if (!len) break;
2822 ok(total_len == BIG_BUFFER_LEN, "got wrong length: 0x%x\n", total_len);
2824 WinHttpCloseHandle(req);
2825 WinHttpCloseHandle(con);
2826 WinHttpCloseHandle(ses);
2829 static void test_cookies( int port )
2831 static const WCHAR cookieW[] = {'/','c','o','o','k','i','e',0};
2832 static const WCHAR cookie2W[] = {'/','c','o','o','k','i','e','2',0};
2833 static const WCHAR cookie3W[] = {'/','c','o','o','k','i','e','3',0};
2834 static const WCHAR cookie4W[] = {'/','c','o','o','k','i','e','4',0};
2835 static const WCHAR cookie5W[] = {'/','c','o','o','k','i','e','5',0};
2836 static const WCHAR cookieheaderW[] =
2837 {'C','o','o','k','i','e',':',' ','n','a','m','e','=','v','a','l','u','e','2','\r','\n',0};
2838 HINTERNET ses, con, req;
2839 DWORD status, size;
2840 BOOL ret;
2842 ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
2843 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
2845 con = WinHttpConnect( ses, localhostW, port, 0 );
2846 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2848 req = WinHttpOpenRequest( con, NULL, cookieW, NULL, NULL, NULL, 0 );
2849 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2851 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2852 ok( ret, "failed to send request %u\n", GetLastError() );
2854 ret = WinHttpReceiveResponse( req, NULL );
2855 ok( ret, "failed to receive response %u\n", GetLastError() );
2857 status = 0xdeadbeef;
2858 size = sizeof(status);
2859 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
2860 ok( ret, "failed to query status code %u\n", GetLastError() );
2861 ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
2863 WinHttpCloseHandle( req );
2865 req = WinHttpOpenRequest( con, NULL, cookie2W, NULL, NULL, NULL, 0 );
2866 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2868 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2869 ok( ret, "failed to send request %u\n", GetLastError() );
2871 ret = WinHttpReceiveResponse( req, NULL );
2872 ok( ret, "failed to receive response %u\n", GetLastError() );
2874 status = 0xdeadbeef;
2875 size = sizeof(status);
2876 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
2877 ok( ret, "failed to query status code %u\n", GetLastError() );
2878 ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
2880 WinHttpCloseHandle( req );
2881 WinHttpCloseHandle( con );
2883 con = WinHttpConnect( ses, localhostW, port, 0 );
2884 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2886 req = WinHttpOpenRequest( con, NULL, cookie2W, NULL, NULL, NULL, 0 );
2887 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2889 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2890 ok( ret, "failed to send request %u\n", GetLastError() );
2892 ret = WinHttpReceiveResponse( req, NULL );
2893 ok( ret, "failed to receive response %u\n", GetLastError() );
2895 status = 0xdeadbeef;
2896 size = sizeof(status);
2897 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
2898 ok( ret, "failed to query status code %u\n", GetLastError() );
2899 ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
2901 WinHttpCloseHandle( req );
2903 req = WinHttpOpenRequest( con, NULL, cookie3W, NULL, NULL, NULL, 0 );
2904 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2906 ret = WinHttpSendRequest( req, cookieheaderW, ~0u, NULL, 0, 0, 0 );
2907 ok( ret, "failed to send request %u\n", GetLastError() );
2909 ret = WinHttpReceiveResponse( req, NULL );
2910 ok( ret, "failed to receive response %u\n", GetLastError() );
2912 status = 0xdeadbeef;
2913 size = sizeof(status);
2914 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
2915 ok( ret, "failed to query status code %u\n", GetLastError() );
2916 ok( status == HTTP_STATUS_OK || broken(status == HTTP_STATUS_BAD_REQUEST), "request failed unexpectedly %u\n", status );
2918 WinHttpCloseHandle( req );
2919 WinHttpCloseHandle( con );
2920 WinHttpCloseHandle( ses );
2922 ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
2923 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
2925 con = WinHttpConnect( ses, localhostW, port, 0 );
2926 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2928 req = WinHttpOpenRequest( con, NULL, cookie2W, NULL, NULL, NULL, 0 );
2929 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2931 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2932 ok( ret, "failed to send request %u\n", GetLastError() );
2934 ret = WinHttpReceiveResponse( req, NULL );
2935 ok( ret, "failed to receive response %u\n", GetLastError() );
2937 status = 0xdeadbeef;
2938 size = sizeof(status);
2939 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
2940 ok( ret, "failed to query status code %u\n", GetLastError() );
2941 ok( status == HTTP_STATUS_BAD_REQUEST, "request failed unexpectedly %u\n", status );
2943 WinHttpCloseHandle( req );
2944 WinHttpCloseHandle( con );
2945 WinHttpCloseHandle( ses );
2947 ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
2948 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
2950 con = WinHttpConnect( ses, localhostW, port, 0 );
2951 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2953 req = WinHttpOpenRequest( con, NULL, cookie4W, NULL, NULL, NULL, 0 );
2954 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2956 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2957 ok( ret, "failed to send request %u\n", GetLastError() );
2959 ret = WinHttpReceiveResponse( req, NULL );
2960 ok( ret, "failed to receive response %u\n", GetLastError() );
2962 status = 0xdeadbeef;
2963 size = sizeof(status);
2964 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
2965 ok( ret, "failed to query status code %u\n", GetLastError() );
2966 ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
2967 WinHttpCloseHandle( req );
2969 req = WinHttpOpenRequest( con, NULL, cookie5W, NULL, NULL, NULL, 0 );
2970 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2972 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2973 ok( ret, "failed to send request %u\n", GetLastError() );
2975 ret = WinHttpReceiveResponse( req, NULL );
2976 ok( ret, "failed to receive response %u\n", GetLastError() );
2978 status = 0xdeadbeef;
2979 size = sizeof(status);
2980 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
2981 ok( ret, "failed to query status code %u\n", GetLastError() );
2982 ok( status == HTTP_STATUS_OK || broken(status == HTTP_STATUS_BAD_REQUEST) /* < win7 */,
2983 "request failed unexpectedly %u\n", status );
2985 WinHttpCloseHandle( req );
2986 WinHttpCloseHandle( con );
2987 WinHttpCloseHandle( ses );
2990 static void test_connection_info( int port )
2992 static const WCHAR basicW[] = {'/','b','a','s','i','c',0};
2993 HINTERNET ses, con, req;
2994 WINHTTP_CONNECTION_INFO info;
2995 DWORD size, error;
2996 BOOL ret;
2998 ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
2999 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3001 con = WinHttpConnect( ses, localhostW, port, 0 );
3002 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3004 req = WinHttpOpenRequest( con, NULL, basicW, NULL, NULL, NULL, 0 );
3005 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3007 size = sizeof(info);
3008 SetLastError( 0xdeadbeef );
3009 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3010 error = GetLastError();
3011 if (!ret && error == ERROR_INVALID_PARAMETER)
3013 win_skip( "WINHTTP_OPTION_CONNECTION_INFO not supported\n" );
3014 return;
3016 ok( !ret, "unexpected success\n" );
3017 ok( error == ERROR_WINHTTP_INCORRECT_HANDLE_STATE, "got %u\n", error );
3019 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3020 ok( ret, "failed to send request %u\n", GetLastError() );
3022 size = 0;
3023 SetLastError( 0xdeadbeef );
3024 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3025 error = GetLastError();
3026 ok( !ret, "unexpected success\n" );
3027 ok( error == ERROR_INSUFFICIENT_BUFFER, "got %u\n", error );
3029 size = sizeof(info);
3030 memset( &info, 0, sizeof(info) );
3031 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3032 ok( ret, "failed to retrieve connection info %u\n", GetLastError() );
3033 ok( info.cbSize == sizeof(info) || info.cbSize == sizeof(info) - sizeof(info.cbSize) /* Win7 */, "wrong size %u\n", info.cbSize );
3035 ret = WinHttpReceiveResponse( req, NULL );
3036 ok( ret, "failed to receive response %u\n", GetLastError() );
3038 size = sizeof(info);
3039 memset( &info, 0, sizeof(info) );
3040 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3041 ok( ret, "failed to retrieve connection info %u\n", GetLastError() );
3042 ok( info.cbSize == sizeof(info) || info.cbSize == sizeof(info) - sizeof(info.cbSize) /* Win7 */, "wrong size %u\n", info.cbSize );
3044 WinHttpCloseHandle( req );
3045 WinHttpCloseHandle( con );
3046 WinHttpCloseHandle( ses );
3049 static void test_credentials(void)
3051 static WCHAR userW[] = {'u','s','e','r',0};
3052 static WCHAR passW[] = {'p','a','s','s',0};
3053 static WCHAR proxy_userW[] = {'p','r','o','x','y','u','s','e','r',0};
3054 static WCHAR proxy_passW[] = {'p','r','o','x','y','p','a','s','s',0};
3055 HINTERNET ses, con, req;
3056 DWORD size, error;
3057 WCHAR buffer[32];
3058 BOOL ret;
3060 ses = WinHttpOpen(test_useragent, 0, proxy_userW, proxy_passW, 0);
3061 ok(ses != NULL, "failed to open session %u\n", GetLastError());
3063 con = WinHttpConnect(ses, localhostW, 0, 0);
3064 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
3066 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
3067 ok(req != NULL, "failed to open a request %u\n", GetLastError());
3069 size = sizeof(buffer)/sizeof(WCHAR);
3070 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size);
3071 ok(ret, "failed to query proxy username %u\n", GetLastError());
3072 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3073 ok(!size, "expected 0, got %u\n", size);
3075 size = sizeof(buffer)/sizeof(WCHAR);
3076 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size);
3077 ok(ret, "failed to query proxy password %u\n", GetLastError());
3078 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3079 ok(!size, "expected 0, got %u\n", size);
3081 ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_USERNAME, proxy_userW, lstrlenW(proxy_userW));
3082 ok(ret, "failed to set username %u\n", GetLastError());
3084 size = sizeof(buffer)/sizeof(WCHAR);
3085 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size);
3086 ok(ret, "failed to query proxy username %u\n", GetLastError());
3087 ok(!winetest_strcmpW(buffer, proxy_userW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3088 ok(size == lstrlenW(proxy_userW) * sizeof(WCHAR), "unexpected result %u\n", size);
3090 size = sizeof(buffer)/sizeof(WCHAR);
3091 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
3092 ok(ret, "failed to query username %u\n", GetLastError());
3093 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3094 ok(!size, "expected 0, got %u\n", size);
3096 size = sizeof(buffer)/sizeof(WCHAR);
3097 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3098 ok(ret, "failed to query password %u\n", GetLastError());
3099 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3100 ok(!size, "expected 0, got %u\n", size);
3102 ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_PASSWORD, proxy_passW, lstrlenW(proxy_passW));
3103 ok(ret, "failed to set proxy password %u\n", GetLastError());
3105 size = sizeof(buffer)/sizeof(WCHAR);
3106 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size);
3107 ok(ret, "failed to query proxy password %u\n", GetLastError());
3108 ok(!winetest_strcmpW(buffer, proxy_passW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3109 ok(size == lstrlenW(proxy_passW) * sizeof(WCHAR), "unexpected result %u\n", size);
3111 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
3112 ok(ret, "failed to set username %u\n", GetLastError());
3114 size = sizeof(buffer)/sizeof(WCHAR);
3115 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
3116 ok(ret, "failed to query username %u\n", GetLastError());
3117 ok(!winetest_strcmpW(buffer, userW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3118 ok(size == lstrlenW(userW) * sizeof(WCHAR), "unexpected result %u\n", size);
3120 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, passW, lstrlenW(passW));
3121 ok(ret, "failed to set password %u\n", GetLastError());
3123 size = sizeof(buffer)/sizeof(WCHAR);
3124 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3125 ok(ret, "failed to query password %u\n", GetLastError());
3126 ok(!winetest_strcmpW(buffer, passW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3127 ok(size == lstrlenW(passW) * sizeof(WCHAR), "unexpected result %u\n", size);
3129 WinHttpCloseHandle(req);
3131 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
3132 ok(req != NULL, "failed to open a request %u\n", GetLastError());
3134 SetLastError(0xdeadbeef);
3135 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, NULL, NULL);
3136 error = GetLastError();
3137 ok(!ret, "expected failure\n");
3138 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
3140 SetLastError(0xdeadbeef);
3141 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, passW, NULL);
3142 error = GetLastError();
3143 ok(!ret, "expected failure\n");
3144 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
3146 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
3147 ok(ret, "failed to set credentials %u\n", GetLastError());
3149 size = sizeof(buffer)/sizeof(WCHAR);
3150 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
3151 ok(ret, "failed to query username %u\n", GetLastError());
3152 todo_wine {
3153 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3154 ok(!size, "expected 0, got %u\n", size);
3157 size = sizeof(buffer)/sizeof(WCHAR);
3158 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3159 ok(ret, "failed to query password %u\n", GetLastError());
3160 todo_wine {
3161 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3162 ok(!size, "expected 0, got %u\n", size);
3165 WinHttpCloseHandle(req);
3166 WinHttpCloseHandle(con);
3167 WinHttpCloseHandle(ses);
3170 static void test_IWinHttpRequest(int port)
3172 static const WCHAR data_start[] = {'<','!','D','O','C','T','Y','P','E',' ','h','t','m','l',' ','P','U','B','L','I','C'};
3173 static const WCHAR usernameW[] = {'u','s','e','r','n','a','m','e',0};
3174 static const WCHAR passwordW[] = {'p','a','s','s','w','o','r','d',0};
3175 static const WCHAR url1W[] = {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
3176 static const WCHAR url2W[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
3177 static const WCHAR url3W[] = {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.',
3178 'o','r','g','/','t','e','s','t','s','/','p','o','s','t','.','p','h','p',0};
3179 static const WCHAR method1W[] = {'G','E','T',0};
3180 static const WCHAR method2W[] = {'I','N','V','A','L','I','D',0};
3181 static const WCHAR method3W[] = {'P','O','S','T',0};
3182 static const WCHAR proxy_serverW[] = {'p','r','o','x','y','s','e','r','v','e','r',0};
3183 static const WCHAR bypas_listW[] = {'b','y','p','a','s','s','l','i','s','t',0};
3184 static const WCHAR connectionW[] = {'C','o','n','n','e','c','t','i','o','n',0};
3185 static const WCHAR dateW[] = {'D','a','t','e',0};
3186 static const WCHAR test_dataW[] = {'t','e','s','t','d','a','t','a',128,0};
3187 static const WCHAR utf8W[] = {'u','t','f','-','8',0};
3188 static const WCHAR unauthW[] = {'U','n','a','u','t','h','o','r','i','z','e','d',0};
3189 HRESULT hr;
3190 IWinHttpRequest *req;
3191 BSTR method, url, username, password, response = NULL, status_text = NULL, headers = NULL;
3192 BSTR date, today, connection, value = NULL;
3193 VARIANT async, empty, timeout, body, body2, proxy_server, bypass_list, data, cp;
3194 VARIANT_BOOL succeeded;
3195 LONG status;
3196 WCHAR todayW[WINHTTP_TIME_FORMAT_BUFSIZE];
3197 SYSTEMTIME st;
3198 IStream *stream, *stream2;
3199 LARGE_INTEGER pos;
3200 char buf[128];
3201 WCHAR bufW[128];
3202 DWORD count;
3204 GetSystemTime( &st );
3205 WinHttpTimeFromSystemTime( &st, todayW );
3207 CoInitialize( NULL );
3208 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3209 ok( hr == S_OK, "got %08x\n", hr );
3211 V_VT( &empty ) = VT_ERROR;
3212 V_ERROR( &empty ) = 0xdeadbeef;
3214 V_VT( &async ) = VT_BOOL;
3215 V_BOOL( &async ) = VARIANT_FALSE;
3217 method = SysAllocString( method3W );
3218 url = SysAllocString( url3W );
3219 hr = IWinHttpRequest_Open( req, method, url, async );
3220 ok( hr == S_OK, "got %08x\n", hr );
3221 SysFreeString( method );
3222 SysFreeString( url );
3224 V_VT( &data ) = VT_BSTR;
3225 V_BSTR( &data ) = SysAllocString( test_dataW );
3226 hr = IWinHttpRequest_Send( req, data );
3227 ok( hr == S_OK || broken(hr == HRESULT_FROM_WIN32(ERROR_WINHTTP_INVALID_SERVER_RESPONSE)),
3228 "got %08x\n", hr );
3229 SysFreeString( V_BSTR( &data ) );
3231 hr = IWinHttpRequest_Open( req, NULL, NULL, empty );
3232 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3234 method = SysAllocString( method1W );
3235 hr = IWinHttpRequest_Open( req, method, NULL, empty );
3236 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3238 hr = IWinHttpRequest_Open( req, method, NULL, async );
3239 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3241 url = SysAllocString( url1W );
3242 hr = IWinHttpRequest_Open( req, NULL, url, empty );
3243 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3245 hr = IWinHttpRequest_Abort( req );
3246 ok( hr == S_OK, "got %08x\n", hr );
3248 hr = IWinHttpRequest_Open( req, method, url, empty );
3249 ok( hr == S_OK, "got %08x\n", hr );
3251 hr = IWinHttpRequest_Abort( req );
3252 ok( hr == S_OK, "got %08x\n", hr );
3254 IWinHttpRequest_Release( req );
3256 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3257 ok( hr == S_OK, "got %08x\n", hr );
3259 SysFreeString( url );
3260 url = SysAllocString( url2W );
3261 hr = IWinHttpRequest_Open( req, method, url, async );
3262 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ), "got %08x\n", hr );
3264 SysFreeString( method );
3265 method = SysAllocString( method2W );
3266 hr = IWinHttpRequest_Open( req, method, url, async );
3267 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ), "got %08x\n", hr );
3269 SysFreeString( method );
3270 method = SysAllocString( method1W );
3271 SysFreeString( url );
3272 url = SysAllocString( url1W );
3273 V_VT( &async ) = VT_ERROR;
3274 V_ERROR( &async ) = DISP_E_PARAMNOTFOUND;
3275 hr = IWinHttpRequest_Open( req, method, url, async );
3276 ok( hr == S_OK, "got %08x\n", hr );
3278 V_VT( &cp ) = VT_ERROR;
3279 V_ERROR( &cp ) = 0xdeadbeef;
3280 hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3281 ok( hr == S_OK, "got %08x\n", hr );
3282 ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3283 ok( V_I4( &cp ) == CP_UTF8, "got %u\n", V_I4( &cp ) );
3285 V_VT( &cp ) = VT_UI4;
3286 V_UI4( &cp ) = CP_ACP;
3287 hr = IWinHttpRequest_put_Option( req, WinHttpRequestOption_URLCodePage, cp );
3288 ok( hr == S_OK, "got %08x\n", hr );
3290 V_VT( &cp ) = VT_ERROR;
3291 V_ERROR( &cp ) = 0xdeadbeef;
3292 hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3293 ok( hr == S_OK, "got %08x\n", hr );
3294 ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3295 ok( V_I4( &cp ) == CP_ACP, "got %u\n", V_I4( &cp ) );
3297 value = SysAllocString( utf8W );
3298 V_VT( &cp ) = VT_BSTR;
3299 V_BSTR( &cp ) = value;
3300 hr = IWinHttpRequest_put_Option( req, WinHttpRequestOption_URLCodePage, cp );
3301 ok( hr == S_OK, "got %08x\n", hr );
3302 SysFreeString( value );
3304 V_VT( &cp ) = VT_ERROR;
3305 V_ERROR( &cp ) = 0xdeadbeef;
3306 hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3307 ok( hr == S_OK, "got %08x\n", hr );
3308 ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3309 ok( V_I4( &cp ) == CP_UTF8, "got %u\n", V_I4( &cp ) );
3311 hr = IWinHttpRequest_Abort( req );
3312 ok( hr == S_OK, "got %08x\n", hr );
3314 hr = IWinHttpRequest_Send( req, empty );
3315 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3317 hr = IWinHttpRequest_Abort( req );
3318 ok( hr == S_OK, "got %08x\n", hr );
3320 IWinHttpRequest_Release( req );
3322 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3323 ok( hr == S_OK, "got %08x\n", hr );
3325 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3326 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3328 hr = IWinHttpRequest_get_ResponseText( req, &response );
3329 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3331 hr = IWinHttpRequest_get_Status( req, NULL );
3332 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3334 hr = IWinHttpRequest_get_Status( req, &status );
3335 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3337 hr = IWinHttpRequest_get_StatusText( req, NULL );
3338 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3340 hr = IWinHttpRequest_get_StatusText( req, &status_text );
3341 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3343 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3344 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3346 hr = IWinHttpRequest_SetTimeouts( req, 10000, 10000, 10000, 10000 );
3347 ok( hr == S_OK, "got %08x\n", hr );
3349 hr = IWinHttpRequest_SetCredentials( req, NULL, NULL, 0xdeadbeef );
3350 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3352 VariantInit( &proxy_server );
3353 V_VT( &proxy_server ) = VT_ERROR;
3354 VariantInit( &bypass_list );
3355 V_VT( &bypass_list ) = VT_ERROR;
3356 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3357 ok( hr == S_OK, "got %08x\n", hr );
3359 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3360 ok( hr == S_OK, "got %08x\n", hr );
3362 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3363 ok( hr == S_OK, "got %08x\n", hr );
3365 hr = IWinHttpRequest_GetAllResponseHeaders( req, NULL );
3366 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3368 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3369 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3371 hr = IWinHttpRequest_GetResponseHeader( req, NULL, NULL );
3372 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3374 connection = SysAllocString( connectionW );
3375 hr = IWinHttpRequest_GetResponseHeader( req, connection, NULL );
3376 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3378 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3379 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3381 hr = IWinHttpRequest_SetRequestHeader( req, NULL, NULL );
3382 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3384 date = SysAllocString( dateW );
3385 hr = IWinHttpRequest_SetRequestHeader( req, date, NULL );
3386 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3388 today = SysAllocString( todayW );
3389 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3390 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3392 hr = IWinHttpRequest_SetAutoLogonPolicy( req, 0xdeadbeef );
3393 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3395 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3396 ok( hr == S_OK, "got %08x\n", hr );
3398 SysFreeString( method );
3399 method = SysAllocString( method1W );
3400 SysFreeString( url );
3401 url = SysAllocString( url1W );
3402 hr = IWinHttpRequest_Open( req, method, url, async );
3403 ok( hr == S_OK, "got %08x\n", hr );
3405 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3406 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3408 hr = IWinHttpRequest_get_ResponseText( req, &response );
3409 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3411 hr = IWinHttpRequest_get_Status( req, &status );
3412 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3414 hr = IWinHttpRequest_get_StatusText( req, &status_text );
3415 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3417 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3418 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3420 hr = IWinHttpRequest_SetTimeouts( req, 10000, 10000, 10000, 10000 );
3421 ok( hr == S_OK, "got %08x\n", hr );
3423 hr = IWinHttpRequest_SetCredentials( req, NULL, NULL, 0xdeadbeef );
3424 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3426 username = SysAllocString( usernameW );
3427 hr = IWinHttpRequest_SetCredentials( req, username, NULL, 0xdeadbeef );
3428 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3430 password = SysAllocString( passwordW );
3431 hr = IWinHttpRequest_SetCredentials( req, NULL, password, 0xdeadbeef );
3432 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3434 hr = IWinHttpRequest_SetCredentials( req, username, password, 0xdeadbeef );
3435 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3437 hr = IWinHttpRequest_SetCredentials( req, NULL, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3438 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3440 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3441 ok( hr == S_OK, "got %08x\n", hr );
3443 V_VT( &proxy_server ) = VT_BSTR;
3444 V_BSTR( &proxy_server ) = SysAllocString( proxy_serverW );
3445 V_VT( &bypass_list ) = VT_BSTR;
3446 V_BSTR( &bypass_list ) = SysAllocString( bypas_listW );
3447 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3448 ok( hr == S_OK, "got %08x\n", hr );
3450 hr = IWinHttpRequest_SetProxy( req, 0xdeadbeef, proxy_server, bypass_list );
3451 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3453 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3454 ok( hr == S_OK, "got %08x\n", hr );
3456 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3457 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3459 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3460 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3462 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3463 ok( hr == S_OK, "got %08x\n", hr );
3465 hr = IWinHttpRequest_SetRequestHeader( req, date, NULL );
3466 ok( hr == S_OK, "got %08x\n", hr );
3468 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3469 ok( hr == S_OK, "got %08x\n", hr );
3471 hr = IWinHttpRequest_Send( req, empty );
3472 ok( hr == S_OK, "got %08x\n", hr );
3474 hr = IWinHttpRequest_Send( req, empty );
3475 ok( hr == S_OK, "got %08x\n", hr );
3477 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3478 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3480 hr = IWinHttpRequest_get_ResponseText( req, &response );
3481 ok( hr == S_OK, "got %08x\n", hr );
3482 ok( !memcmp(response, data_start, sizeof(data_start)), "got %s\n", wine_dbgstr_wn(response, 32) );
3483 SysFreeString( response );
3485 hr = IWinHttpRequest_get_Status( req, NULL );
3486 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3488 status = 0;
3489 hr = IWinHttpRequest_get_Status( req, &status );
3490 ok( hr == S_OK, "got %08x\n", hr );
3491 trace("Status=%d\n", status);
3493 hr = IWinHttpRequest_get_StatusText( req, NULL );
3494 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3496 hr = IWinHttpRequest_get_StatusText( req, &status_text );
3497 ok( hr == S_OK, "got %08x\n", hr );
3498 trace("StatusText=%s\n", wine_dbgstr_w(status_text));
3499 SysFreeString( status_text );
3501 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3502 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3504 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3505 ok( hr == S_OK, "got %08x\n", hr );
3507 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3508 ok( hr == S_OK, "got %08x\n", hr );
3510 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3511 ok( hr == S_OK, "got %08x\n", hr );
3513 hr = IWinHttpRequest_GetAllResponseHeaders( req, NULL );
3514 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3516 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3517 ok( hr == S_OK, "got %08x\n", hr );
3518 SysFreeString( headers );
3520 hr = IWinHttpRequest_GetResponseHeader( req, NULL, NULL );
3521 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3523 hr = IWinHttpRequest_GetResponseHeader( req, connection, NULL );
3524 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3526 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3527 ok( hr == S_OK, "got %08x\n", hr );
3528 SysFreeString( value );
3530 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3531 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND ), "got %08x\n", hr );
3533 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3534 ok( hr == S_OK, "got %08x\n", hr );
3536 VariantInit( &timeout );
3537 V_VT( &timeout ) = VT_I4;
3538 V_I4( &timeout ) = 10;
3539 hr = IWinHttpRequest_WaitForResponse( req, timeout, &succeeded );
3540 ok( hr == S_OK, "got %08x\n", hr );
3542 hr = IWinHttpRequest_get_Status( req, &status );
3543 ok( hr == S_OK, "got %08x\n", hr );
3545 hr = IWinHttpRequest_get_StatusText( req, &status_text );
3546 ok( hr == S_OK, "got %08x\n", hr );
3547 SysFreeString( status_text );
3549 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3550 ok( hr == S_OK, "got %08x\n", hr );
3552 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3553 ok( hr == S_OK, "got %08x\n", hr );
3555 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3556 ok( hr == S_OK, "got %08x\n", hr );
3558 hr = IWinHttpRequest_Send( req, empty );
3559 ok( hr == S_OK, "got %08x\n", hr );
3561 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3562 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3564 hr = IWinHttpRequest_get_ResponseText( req, &response );
3565 ok( hr == S_OK, "got %08x\n", hr );
3566 SysFreeString( response );
3568 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3569 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3571 VariantInit( &body );
3572 V_VT( &body ) = VT_ERROR;
3573 hr = IWinHttpRequest_get_ResponseBody( req, &body );
3574 ok( hr == S_OK, "got %08x\n", hr );
3575 ok( V_VT( &body ) == (VT_ARRAY|VT_UI1), "got %08x\n", V_VT( &body ) );
3577 hr = VariantClear( &body );
3578 ok( hr == S_OK, "got %08x\n", hr );
3580 VariantInit( &body );
3581 V_VT( &body ) = VT_ERROR;
3582 hr = IWinHttpRequest_get_ResponseStream( req, &body );
3583 ok( hr == S_OK, "got %08x\n", hr );
3584 ok( V_VT( &body ) == VT_UNKNOWN, "got %08x\n", V_VT( &body ) );
3586 hr = IUnknown_QueryInterface( V_UNKNOWN( &body ), &IID_IStream, (void **)&stream );
3587 ok( hr == S_OK, "got %08x\n", hr );
3588 ok( V_UNKNOWN( &body ) == (IUnknown *)stream, "got different interface pointer\n" );
3590 buf[0] = 0;
3591 count = 0xdeadbeef;
3592 hr = IStream_Read( stream, buf, 128, &count );
3593 ok( hr == S_OK, "got %08x\n", hr );
3594 ok( count != 0xdeadbeef, "count not set\n" );
3595 ok( buf[0], "no data\n" );
3597 VariantInit( &body2 );
3598 V_VT( &body2 ) = VT_ERROR;
3599 hr = IWinHttpRequest_get_ResponseStream( req, &body2 );
3600 ok( hr == S_OK, "got %08x\n", hr );
3601 ok( V_VT( &body2 ) == VT_UNKNOWN, "got %08x\n", V_VT( &body2 ) );
3602 ok( V_UNKNOWN( &body ) != V_UNKNOWN( &body2 ), "got same interface pointer\n" );
3604 hr = IUnknown_QueryInterface( V_UNKNOWN( &body2 ), &IID_IStream, (void **)&stream2 );
3605 ok( hr == S_OK, "got %08x\n", hr );
3606 ok( V_UNKNOWN( &body2 ) == (IUnknown *)stream2, "got different interface pointer\n" );
3607 IStream_Release( stream2 );
3609 hr = VariantClear( &body );
3610 ok( hr == S_OK, "got %08x\n", hr );
3612 hr = VariantClear( &body2 );
3613 ok( hr == S_OK, "got %08x\n", hr );
3615 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3616 ok( hr == S_OK, "got %08x\n", hr );
3618 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3619 ok( hr == S_OK, "got %08x\n", hr );
3621 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3622 ok( hr == S_OK, "got %08x\n", hr );
3623 SysFreeString( headers );
3625 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3626 ok( hr == S_OK, "got %08x\n", hr );
3627 SysFreeString( value );
3629 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3630 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND ), "got %08x\n", hr );
3632 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3633 ok( hr == S_OK, "got %08x\n", hr );
3635 hr = IWinHttpRequest_Send( req, empty );
3636 ok( hr == S_OK, "got %08x\n", hr );
3638 hr = IWinHttpRequest_Abort( req );
3639 ok( hr == S_OK, "got %08x\n", hr );
3641 hr = IWinHttpRequest_Abort( req );
3642 ok( hr == S_OK, "got %08x\n", hr );
3644 IWinHttpRequest_Release( req );
3646 pos.QuadPart = 0;
3647 hr = IStream_Seek( stream, pos, STREAM_SEEK_SET, NULL );
3648 ok( hr == S_OK, "got %08x\n", hr );
3650 buf[0] = 0;
3651 count = 0xdeadbeef;
3652 hr = IStream_Read( stream, buf, 128, &count );
3653 ok( hr == S_OK, "got %08x\n", hr );
3654 ok( count != 0xdeadbeef, "count not set\n" );
3655 ok( buf[0], "no data\n" );
3656 IStream_Release( stream );
3658 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3659 ok( hr == S_OK, "got %08x\n", hr );
3661 V_VT( &async ) = VT_I4;
3662 V_I4( &async ) = 1;
3663 hr = IWinHttpRequest_Open( req, method, url, async );
3664 ok( hr == S_OK, "got %08x\n", hr );
3666 hr = IWinHttpRequest_Send( req, empty );
3667 ok( hr == S_OK, "got %08x\n", hr );
3669 hr = IWinHttpRequest_WaitForResponse( req, timeout, &succeeded );
3670 ok( hr == S_OK, "got %08x\n", hr );
3672 IWinHttpRequest_Release( req );
3674 SysFreeString( method );
3675 SysFreeString( url );
3676 SysFreeString( username );
3677 SysFreeString( password );
3678 SysFreeString( connection );
3679 SysFreeString( date );
3680 SysFreeString( today );
3681 VariantClear( &proxy_server );
3682 VariantClear( &bypass_list );
3684 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3685 ok( hr == S_OK, "got %08x\n", hr );
3687 url = SysAllocString( test_winehq_https );
3688 method = SysAllocString( method3W );
3689 V_VT( &async ) = VT_BOOL;
3690 V_BOOL( &async ) = VARIANT_FALSE;
3691 hr = IWinHttpRequest_Open( req, method, url, async );
3692 ok( hr == S_OK, "got %08x\n", hr );
3693 SysFreeString( method );
3694 SysFreeString( url );
3696 hr = IWinHttpRequest_Send( req, empty );
3697 ok( hr == S_OK || broken(hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_INVALID_SERVER_RESPONSE )), "got %08x\n", hr );
3698 if (hr == S_OK)
3700 hr = IWinHttpRequest_get_ResponseText( req, &response );
3701 ok( hr == S_OK, "got %08x\n", hr );
3702 ok( !memcmp(response, data_start, sizeof(data_start)), "got %s\n", wine_dbgstr_wn(response, 32) );
3703 SysFreeString( response );
3706 IWinHttpRequest_Release( req );
3708 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3709 ok( hr == S_OK, "got %08x\n", hr );
3711 sprintf( buf, "http://localhost:%d/auth", port );
3712 MultiByteToWideChar( CP_ACP, 0, buf, -1, bufW, sizeof(bufW)/sizeof(bufW[0]) );
3713 url = SysAllocString( bufW );
3714 method = SysAllocString( method3W );
3715 V_VT( &async ) = VT_BOOL;
3716 V_BOOL( &async ) = VARIANT_FALSE;
3717 hr = IWinHttpRequest_Open( req, method, url, async );
3718 ok( hr == S_OK, "got %08x\n", hr );
3719 SysFreeString( method );
3720 SysFreeString( url );
3722 hr = IWinHttpRequest_get_Status( req, &status );
3723 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3725 V_VT( &data ) = VT_BSTR;
3726 V_BSTR( &data ) = SysAllocString( test_dataW );
3727 hr = IWinHttpRequest_Send( req, data );
3728 ok( hr == S_OK, "got %08x\n", hr );
3729 SysFreeString( V_BSTR( &data ) );
3731 hr = IWinHttpRequest_get_ResponseText( req, &response );
3732 ok( hr == S_OK, "got %08x\n", hr );
3733 ok( !memcmp( response, unauthW, sizeof(unauthW) ), "got %s\n", wine_dbgstr_w(response) );
3734 SysFreeString( response );
3736 status = 0xdeadbeef;
3737 hr = IWinHttpRequest_get_Status( req, &status );
3738 ok( hr == S_OK, "got %08x\n", hr );
3739 ok( status == HTTP_STATUS_DENIED, "got %d\n", status );
3741 IWinHttpRequest_Release( req );
3743 CoUninitialize();
3746 static void request_get_property(IWinHttpRequest *request, int property, VARIANT *ret)
3748 DISPPARAMS params;
3749 VARIANT arg;
3750 HRESULT hr;
3752 memset(&params, 0, sizeof(params));
3753 params.cNamedArgs = 0;
3754 params.rgdispidNamedArgs = NULL;
3755 params.cArgs = 1;
3756 params.rgvarg = &arg;
3757 VariantInit(&arg);
3758 V_VT(&arg) = VT_I4;
3759 V_I4(&arg) = property;
3760 VariantInit(ret);
3761 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
3762 DISPATCH_PROPERTYGET, &params, ret, NULL, NULL);
3763 ok(hr == S_OK, "error %#x\n", hr);
3766 static void test_IWinHttpRequest_Invoke(void)
3768 static const WCHAR utf8W[] = {'U','T','F','-','8',0};
3769 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};
3770 WCHAR openW[] = {'O','p','e','n',0};
3771 WCHAR optionW[] = {'O','p','t','i','o','n',0};
3772 OLECHAR *open = openW, *option = optionW;
3773 BSTR utf8;
3774 CLSID clsid;
3775 IWinHttpRequest *request;
3776 IDispatch *dispatch;
3777 DISPID id;
3778 DISPPARAMS params;
3779 VARIANT arg[3], ret;
3780 UINT err;
3781 BOOL bret;
3782 HRESULT hr;
3784 CoInitialize(NULL);
3786 hr = CLSIDFromProgID(regid, &clsid);
3787 ok(hr == S_OK, "CLSIDFromProgID error %#x\n", hr);
3788 bret = IsEqualIID(&clsid, &CLSID_WinHttpRequest);
3789 ok(bret || broken(!bret) /* win2003 */, "not expected %s\n", wine_dbgstr_guid(&clsid));
3791 hr = CoCreateInstance(&CLSID_WinHttpRequest, 0, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&request);
3792 ok(hr == S_OK, "error %#x\n", hr);
3794 hr = IWinHttpRequest_QueryInterface(request, &IID_IDispatch, (void **)&dispatch);
3795 ok(hr == S_OK, "error %#x\n", hr);
3796 IDispatch_Release(dispatch);
3798 hr = IWinHttpRequest_GetIDsOfNames(request, &IID_NULL, &open, 1, 0x0409, &id);
3799 ok(hr == S_OK, "error %#x\n", hr);
3800 ok(id == DISPID_HTTPREQUEST_OPEN, "expected DISPID_HTTPREQUEST_OPEN, got %u\n", id);
3802 hr = IWinHttpRequest_GetIDsOfNames(request, &IID_NULL, &option, 1, 0x0409, &id);
3803 ok(hr == S_OK, "error %#x\n", hr);
3804 ok(id == DISPID_HTTPREQUEST_OPTION, "expected DISPID_HTTPREQUEST_OPTION, got %u\n", id);
3806 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3807 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3808 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
3810 memset(&params, 0, sizeof(params));
3811 params.cArgs = 2;
3812 params.cNamedArgs = 0;
3813 params.rgvarg = arg;
3814 V_VT(&arg[0]) = VT_I4;
3815 V_I4(&arg[0]) = 1252;
3816 V_VT(&arg[1]) = VT_R8;
3817 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
3818 VariantInit(&ret);
3819 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
3820 DISPATCH_METHOD, &params, NULL, NULL, &err);
3821 ok(hr == S_OK, "error %#x\n", hr);
3823 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3824 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3825 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
3827 memset(&params, 0, sizeof(params));
3828 params.cArgs = 2;
3829 params.cNamedArgs = 0;
3830 params.rgvarg = arg;
3831 V_VT(&arg[0]) = VT_I4;
3832 V_I4(&arg[0]) = 1252;
3833 V_VT(&arg[1]) = VT_R8;
3834 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
3835 VariantInit(&ret);
3836 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
3837 DISPATCH_METHOD | DISPATCH_PROPERTYPUT, &params, NULL, NULL, &err);
3838 ok(hr == S_OK, "error %#x\n", hr);
3840 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3841 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3842 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
3844 memset(&params, 0, sizeof(params));
3845 params.cArgs = 2;
3846 params.cNamedArgs = 0;
3847 params.rgvarg = arg;
3848 V_VT(&arg[0]) = VT_I4;
3849 V_I4(&arg[0]) = 1252;
3850 V_VT(&arg[1]) = VT_R8;
3851 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
3852 VariantInit(&ret);
3853 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
3854 DISPATCH_PROPERTYPUT, &params, NULL, NULL, &err);
3855 ok(hr == S_OK, "error %#x\n", hr);
3857 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3858 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3859 ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
3861 memset(&params, 0, sizeof(params));
3862 params.cArgs = 2;
3863 params.cNamedArgs = 0;
3864 params.rgvarg = arg;
3865 V_VT(&arg[0]) = VT_BSTR;
3866 utf8 = SysAllocString(utf8W);
3867 V_BSTR(&arg[0]) = utf8;
3868 V_VT(&arg[1]) = VT_R8;
3869 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
3870 hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_METHOD, &params, NULL, NULL, &err);
3871 ok(hr == S_OK, "error %#x\n", hr);
3873 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3874 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3875 ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
3877 VariantInit(&ret);
3878 hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_METHOD, &params, &ret, NULL, &err);
3879 ok(hr == S_OK, "error %#x\n", hr);
3881 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3882 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3883 ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
3885 VariantInit(&ret);
3886 hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
3887 ok(hr == S_OK, "error %#x\n", hr);
3889 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3890 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3891 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
3893 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, NULL, NULL, NULL);
3894 ok(hr == S_OK, "error %#x\n", hr);
3896 hr = IWinHttpRequest_Invoke(request, 255, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, NULL, NULL, NULL);
3897 ok(hr == DISP_E_MEMBERNOTFOUND, "error %#x\n", hr);
3899 VariantInit(&ret);
3900 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
3901 ok(hr == DISP_E_UNKNOWNINTERFACE, "error %#x\n", hr);
3903 VariantInit(&ret);
3904 if (0) /* crashes */
3905 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, &ret, NULL, &err);
3907 params.cArgs = 1;
3908 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
3909 ok(hr == DISP_E_TYPEMISMATCH, "error %#x\n", hr);
3911 VariantInit(&arg[2]);
3912 params.cArgs = 3;
3913 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
3914 todo_wine
3915 ok(hr == S_OK, "error %#x\n", hr);
3917 VariantInit(&arg[0]);
3918 VariantInit(&arg[1]);
3919 VariantInit(&arg[2]);
3921 params.cArgs = 1;
3922 V_VT(&arg[0]) = VT_I4;
3923 V_I4(&arg[0]) = WinHttpRequestOption_URLCodePage;
3924 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
3925 ok(hr == S_OK, "error %#x\n", hr);
3927 V_VT(&ret) = 0xdead;
3928 V_I4(&ret) = 0xbeef;
3929 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &params, &ret, NULL, NULL);
3930 ok(hr == S_OK, "error %#x\n", hr);
3931 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3932 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
3934 V_VT(&ret) = 0xdead;
3935 V_I4(&ret) = 0xbeef;
3936 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD, &params, &ret, NULL, NULL);
3937 ok(hr == S_OK, "error %#x\n", hr);
3938 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3939 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
3941 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
3942 ok(hr == S_OK, "error %#x\n", hr);
3944 V_VT(&ret) = 0xdead;
3945 V_I4(&ret) = 0xbeef;
3946 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, 0, &params, &ret, NULL, NULL);
3947 ok(hr == S_OK, "error %#x\n", hr);
3948 ok(V_VT(&ret) == VT_EMPTY, "expected VT_EMPTY, got %d\n", V_VT(&ret));
3949 ok(V_I4(&ret) == 0xbeef || V_I4(&ret) == 0 /* Win8 */, "expected 0xdead, got %d\n", V_I4(&ret));
3951 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, 0, &params, NULL, NULL, NULL);
3952 ok(hr == S_OK, "error %#x\n", hr);
3954 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_IUnknown, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
3955 ok(hr == DISP_E_UNKNOWNINTERFACE, "error %#x\n", hr);
3957 params.cArgs = 2;
3958 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
3959 todo_wine
3960 ok(hr == S_OK, "error %#x\n", hr);
3962 params.cArgs = 0;
3963 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
3964 ok(hr == DISP_E_PARAMNOTFOUND, "error %#x\n", hr);
3966 SysFreeString(utf8);
3968 params.cArgs = 1;
3969 V_VT(&arg[0]) = VT_I4;
3970 V_I4(&arg[0]) = AutoLogonPolicy_Never;
3971 VariantInit(&ret);
3972 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_SETAUTOLOGONPOLICY, &IID_NULL, 0,
3973 DISPATCH_METHOD, &params, &ret, NULL, NULL);
3974 ok(hr == S_OK, "error %#x\n", hr);
3976 IWinHttpRequest_Release(request);
3978 CoUninitialize();
3981 static void test_WinHttpDetectAutoProxyConfigUrl(void)
3983 BOOL ret;
3984 WCHAR *url;
3985 DWORD error;
3987 if (0) /* crashes on some win2k systems */
3989 SetLastError(0xdeadbeef);
3990 ret = WinHttpDetectAutoProxyConfigUrl( 0, NULL );
3991 error = GetLastError();
3992 ok( !ret, "expected failure\n" );
3993 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3995 url = NULL;
3996 SetLastError(0xdeadbeef);
3997 ret = WinHttpDetectAutoProxyConfigUrl( 0, &url );
3998 error = GetLastError();
3999 ok( !ret, "expected failure\n" );
4000 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4002 if (0) /* crashes on some win2k systems */
4004 SetLastError(0xdeadbeef);
4005 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, NULL );
4006 error = GetLastError();
4007 ok( !ret, "expected failure\n" );
4008 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4010 url = (WCHAR *)0xdeadbeef;
4011 SetLastError(0xdeadbeef);
4012 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, &url );
4013 error = GetLastError();
4014 if (!ret)
4016 ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED, "got %u\n", error );
4017 ok( !url || broken(url == (WCHAR *)0xdeadbeef), "got %p\n", url );
4019 else
4021 trace("%s\n", wine_dbgstr_w(url));
4022 GlobalFree( url );
4025 url = (WCHAR *)0xdeadbeef;
4026 SetLastError(0xdeadbeef);
4027 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DHCP, &url );
4028 error = GetLastError();
4029 if (!ret)
4031 ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED, "got %u\n", error );
4032 ok( !url || broken(url == (WCHAR *)0xdeadbeef), "got %p\n", url );
4034 else
4036 ok( error == ERROR_SUCCESS, "got %u\n", error );
4037 trace("%s\n", wine_dbgstr_w(url));
4038 GlobalFree( url );
4042 static void test_WinHttpGetIEProxyConfigForCurrentUser(void)
4044 BOOL ret;
4045 DWORD error;
4046 WINHTTP_CURRENT_USER_IE_PROXY_CONFIG cfg;
4048 memset( &cfg, 0, sizeof(cfg) );
4050 SetLastError(0xdeadbeef);
4051 ret = WinHttpGetIEProxyConfigForCurrentUser( NULL );
4052 error = GetLastError();
4053 ok( !ret, "expected failure\n" );
4054 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4056 SetLastError(0xdeadbeef);
4057 ret = WinHttpGetIEProxyConfigForCurrentUser( &cfg );
4058 error = GetLastError();
4059 ok( ret, "expected success\n" );
4060 ok( error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* < win7 */, "got %u\n", error );
4062 trace("IEProxy.AutoDetect=%d\n", cfg.fAutoDetect);
4063 trace("IEProxy.AutoConfigUrl=%s\n", wine_dbgstr_w(cfg.lpszAutoConfigUrl));
4064 trace("IEProxy.Proxy=%s\n", wine_dbgstr_w(cfg.lpszProxy));
4065 trace("IEProxy.ProxyBypass=%s\n", wine_dbgstr_w(cfg.lpszProxyBypass));
4066 GlobalFree( cfg.lpszAutoConfigUrl );
4067 GlobalFree( cfg.lpszProxy );
4068 GlobalFree( cfg.lpszProxyBypass );
4071 static void test_WinHttpGetProxyForUrl(void)
4073 static const WCHAR urlW[] = {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0};
4074 static const WCHAR wpadW[] = {'h','t','t','p',':','/','/','w','p','a','d','/','w','p','a','d','.','d','a','t',0};
4075 static const WCHAR emptyW[] = {0};
4076 BOOL ret;
4077 DWORD error;
4078 HINTERNET session;
4079 WINHTTP_AUTOPROXY_OPTIONS options;
4080 WINHTTP_PROXY_INFO info;
4082 memset( &options, 0, sizeof(options) );
4084 SetLastError(0xdeadbeef);
4085 ret = WinHttpGetProxyForUrl( NULL, NULL, NULL, NULL );
4086 error = GetLastError();
4087 ok( !ret, "expected failure\n" );
4088 ok( error == ERROR_INVALID_HANDLE, "got %u\n", error );
4090 session = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
4091 ok( session != NULL, "failed to open session %u\n", GetLastError() );
4093 SetLastError(0xdeadbeef);
4094 ret = WinHttpGetProxyForUrl( session, NULL, NULL, NULL );
4095 error = GetLastError();
4096 ok( !ret, "expected failure\n" );
4097 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4099 SetLastError(0xdeadbeef);
4100 ret = WinHttpGetProxyForUrl( session, emptyW, NULL, NULL );
4101 error = GetLastError();
4102 ok( !ret, "expected failure\n" );
4103 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4105 SetLastError(0xdeadbeef);
4106 ret = WinHttpGetProxyForUrl( session, urlW, NULL, NULL );
4107 error = GetLastError();
4108 ok( !ret, "expected failure\n" );
4109 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4111 SetLastError(0xdeadbeef);
4112 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
4113 error = GetLastError();
4114 ok( !ret, "expected failure\n" );
4115 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4117 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
4118 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
4120 SetLastError(0xdeadbeef);
4121 ret = WinHttpGetProxyForUrl( session, urlW, &options, NULL );
4122 error = GetLastError();
4123 ok( !ret, "expected failure\n" );
4124 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4126 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
4127 options.dwAutoDetectFlags = 0;
4129 SetLastError(0xdeadbeef);
4130 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
4131 error = GetLastError();
4132 ok( !ret, "expected failure\n" );
4133 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4135 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT | WINHTTP_AUTOPROXY_CONFIG_URL;
4136 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
4138 SetLastError(0xdeadbeef);
4139 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
4140 error = GetLastError();
4141 ok( !ret, "expected failure\n" );
4142 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4144 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
4145 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
4147 memset( &info, 0, sizeof(info) );
4148 SetLastError(0xdeadbeef);
4149 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
4150 error = GetLastError();
4151 if (ret)
4153 ok( error == ERROR_SUCCESS, "got %u\n", error );
4154 trace("Proxy.AccessType=%u\n", info.dwAccessType);
4155 trace("Proxy.Proxy=%s\n", wine_dbgstr_w(info.lpszProxy));
4156 trace("Proxy.ProxyBypass=%s\n", wine_dbgstr_w(info.lpszProxyBypass));
4157 GlobalFree( info.lpszProxy );
4158 GlobalFree( info.lpszProxyBypass );
4161 options.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
4162 options.dwAutoDetectFlags = 0;
4163 options.lpszAutoConfigUrl = wpadW;
4165 memset( &info, 0, sizeof(info) );
4166 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
4167 if (ret)
4169 trace("Proxy.AccessType=%u\n", info.dwAccessType);
4170 trace("Proxy.Proxy=%s\n", wine_dbgstr_w(info.lpszProxy));
4171 trace("Proxy.ProxyBypass=%s\n", wine_dbgstr_w(info.lpszProxyBypass));
4172 GlobalFree( info.lpszProxy );
4173 GlobalFree( info.lpszProxyBypass );
4175 WinHttpCloseHandle( session );
4178 static void test_chunked_read(void)
4180 static const WCHAR verb[] = {'/','t','e','s','t','c','h','u','n','k','e','d',0};
4181 static const WCHAR chunked[] = {'c','h','u','n','k','e','d',0};
4182 WCHAR header[32];
4183 DWORD len, err;
4184 HINTERNET ses, con = NULL, req = NULL;
4185 BOOL ret;
4187 trace( "starting chunked read test\n" );
4189 ses = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
4190 ok( ses != NULL, "WinHttpOpen failed with error %u\n", GetLastError() );
4191 if (!ses) goto done;
4193 con = WinHttpConnect( ses, test_winehq, 0, 0 );
4194 ok( con != NULL, "WinHttpConnect failed with error %u\n", GetLastError() );
4195 if (!con) goto done;
4197 req = WinHttpOpenRequest( con, NULL, verb, NULL, NULL, NULL, 0 );
4198 ok( req != NULL, "WinHttpOpenRequest failed with error %u\n", GetLastError() );
4199 if (!req) goto done;
4201 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
4202 err = GetLastError();
4203 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
4205 skip("connection failed, skipping\n");
4206 goto done;
4208 ok( ret, "WinHttpSendRequest failed with error %u\n", GetLastError() );
4210 ret = WinHttpReceiveResponse( req, NULL );
4211 ok( ret, "WinHttpReceiveResponse failed with error %u\n", GetLastError() );
4213 header[0] = 0;
4214 len = sizeof(header);
4215 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, header, &len, 0 );
4216 ok( ret, "failed to get TRANSFER_ENCODING header (error %u)\n", GetLastError() );
4217 ok( !lstrcmpW( header, chunked ), "wrong transfer encoding %s\n", wine_dbgstr_w(header) );
4218 trace( "transfer encoding: %s\n", wine_dbgstr_w(header) );
4220 header[0] = 0;
4221 len = sizeof(header);
4222 SetLastError( 0xdeadbeef );
4223 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_CONTENT_LENGTH, NULL, &header, &len, 0 );
4224 ok( !ret, "unexpected CONTENT_LENGTH header %s\n", wine_dbgstr_w(header) );
4225 ok( GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND, "wrong error %u\n", GetLastError() );
4227 trace( "entering query loop\n" );
4228 for (;;)
4230 len = 0xdeadbeef;
4231 ret = WinHttpQueryDataAvailable( req, &len );
4232 ok( ret, "WinHttpQueryDataAvailable failed with error %u\n", GetLastError() );
4233 if (ret) ok( len != 0xdeadbeef, "WinHttpQueryDataAvailable return wrong length\n" );
4234 trace( "got %u available\n", len );
4235 if (len)
4237 DWORD bytes_read;
4238 char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 );
4240 ret = WinHttpReadData( req, buf, len, &bytes_read );
4242 buf[bytes_read] = 0;
4243 trace( "WinHttpReadData -> %d %u\n", ret, bytes_read );
4244 ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len );
4245 ok( buf[bytes_read - 1] == '\n', "received partial line '%s'\n", buf );
4247 HeapFree( GetProcessHeap(), 0, buf );
4248 if (!bytes_read) break;
4250 if (!len) break;
4252 trace( "done\n" );
4254 done:
4255 if (req) WinHttpCloseHandle( req );
4256 if (con) WinHttpCloseHandle( con );
4257 if (ses) WinHttpCloseHandle( ses );
4260 START_TEST (winhttp)
4262 static const WCHAR basicW[] = {'/','b','a','s','i','c',0};
4263 static const WCHAR quitW[] = {'/','q','u','i','t',0};
4264 struct server_info si;
4265 HANDLE thread;
4266 DWORD ret;
4268 test_OpenRequest();
4269 test_SendRequest();
4270 test_WinHttpTimeFromSystemTime();
4271 test_WinHttpTimeToSystemTime();
4272 test_WinHttpAddHeaders();
4273 test_secure_connection();
4274 test_request_parameter_defaults();
4275 test_QueryOption();
4276 test_set_default_proxy_config();
4277 test_empty_headers_param();
4278 test_Timeouts();
4279 test_resolve_timeout();
4280 test_credentials();
4281 test_IWinHttpRequest_Invoke();
4282 test_WinHttpDetectAutoProxyConfigUrl();
4283 test_WinHttpGetIEProxyConfigForCurrentUser();
4284 test_WinHttpGetProxyForUrl();
4285 test_chunked_read();
4287 si.event = CreateEventW(NULL, 0, 0, NULL);
4288 si.port = 7532;
4290 thread = CreateThread(NULL, 0, server_thread, (LPVOID)&si, 0, NULL);
4291 ok(thread != NULL, "failed to create thread %u\n", GetLastError());
4293 ret = WaitForSingleObject(si.event, 10000);
4294 ok(ret == WAIT_OBJECT_0, "failed to start winhttp test server %u\n", GetLastError());
4295 if (ret != WAIT_OBJECT_0)
4296 return;
4298 test_IWinHttpRequest(si.port);
4299 test_connection_info(si.port);
4300 test_basic_request(si.port, NULL, basicW);
4301 test_no_headers(si.port);
4302 test_no_content(si.port);
4303 test_head_request(si.port);
4304 test_not_modified(si.port);
4305 test_basic_authentication(si.port);
4306 test_bad_header(si.port);
4307 test_multiple_reads(si.port);
4308 test_cookies(si.port);
4310 /* send the basic request again to shutdown the server thread */
4311 test_basic_request(si.port, NULL, quitW);
4313 WaitForSingleObject(thread, 3000);