winhttp/tests: Add a test for IWinHttpRequest::Invoke.
[wine.git] / dlls / winhttp / tests / winhttp.c
blobc3a3f114476ac128ae93728170ddb76d0a4bae2a
1 /*
2 * WinHTTP - tests
4 * Copyright 2008 Google (Zac Brown)
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
22 #include <stdarg.h>
23 #include <windef.h>
24 #include <winsock2.h>
25 #include <ws2tcpip.h>
26 #include <winhttp.h>
27 #include <wincrypt.h>
28 #include <winreg.h>
29 #include <initguid.h>
30 #include <httprequest.h>
31 #include <httprequestid.h>
33 #include "wine/test.h"
35 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
37 static const WCHAR test_useragent[] =
38 {'W','i','n','e',' ','R','e','g','r','e','s','s','i','o','n',' ','T','e','s','t',0};
39 static const WCHAR test_winehq[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
40 static const WCHAR localhostW[] = {'l','o','c','a','l','h','o','s','t',0};
42 static BOOL proxy_active(void)
44 WINHTTP_PROXY_INFO proxy_info;
45 BOOL active = FALSE;
47 SetLastError(0xdeadbeef);
48 if (WinHttpGetDefaultProxyConfiguration(&proxy_info))
50 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
51 "got %u\n", GetLastError());
52 active = (proxy_info.lpszProxy != NULL);
53 if (active)
54 GlobalFree(proxy_info.lpszProxy);
55 if (proxy_info.lpszProxyBypass != NULL)
56 GlobalFree(proxy_info.lpszProxyBypass);
58 else
59 active = FALSE;
61 return active;
64 static void test_QueryOption(void)
66 BOOL ret;
67 HINTERNET session, request, connection;
68 DWORD feature, size;
70 SetLastError(0xdeadbeef);
71 session = WinHttpOpen(test_useragent, 0, 0, 0, 0);
72 ok(session != NULL, "WinHttpOpen failed to open session, error %u\n", GetLastError());
74 SetLastError(0xdeadbeef);
75 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, NULL);
76 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
77 ok(GetLastError() == ERROR_INVALID_PARAMETER,
78 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
80 size = 0xdeadbeef;
81 SetLastError(0xdeadbeef);
82 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, &size);
83 ok(!ret, "should fail to query option\n");
84 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
85 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
86 ok(size == 4, "expected 4, got %u\n", size);
88 feature = 0xdeadbeef;
89 size = sizeof(feature) - 1;
90 SetLastError(0xdeadbeef);
91 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
92 ok(!ret, "should fail to query option\n");
93 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
94 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
95 ok(size == 4, "expected 4, got %u\n", size);
97 feature = 0xdeadbeef;
98 size = sizeof(feature) + 1;
99 SetLastError(0xdeadbeef);
100 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
101 ok(ret, "failed to query option %u\n", GetLastError());
102 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
103 "got %u\n", GetLastError());
104 ok(size == sizeof(feature), "WinHttpQueryOption should set the size: %u\n", size);
105 ok(feature == WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP,
106 "expected WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP, got %#x\n", feature);
108 SetLastError(0xdeadbeef);
109 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, sizeof(feature));
110 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
111 ok(GetLastError() == ERROR_INVALID_PARAMETER,
112 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
114 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
115 SetLastError(0xdeadbeef);
116 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature) - 1);
117 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
118 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
119 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
121 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
122 SetLastError(0xdeadbeef);
123 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature) + 1);
124 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
125 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
126 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
128 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
129 SetLastError(0xdeadbeef);
130 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature));
131 ok(ret, "failed to set redirect policy %u\n", GetLastError());
133 feature = 0xdeadbeef;
134 size = sizeof(feature);
135 SetLastError(0xdeadbeef);
136 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
137 ok(ret, "failed to query option %u\n", GetLastError());
138 ok(feature == WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS,
139 "expected WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS, got %#x\n", feature);
141 feature = WINHTTP_DISABLE_COOKIES;
142 SetLastError(0xdeadbeef);
143 ret = WinHttpSetOption(session, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
144 ok(!ret, "should fail to set disable feature for a session\n");
145 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
146 "expected ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, got %u\n", GetLastError());
148 SetLastError(0xdeadbeef);
149 connection = WinHttpConnect(session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
150 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u\n", GetLastError());
152 feature = WINHTTP_DISABLE_COOKIES;
153 SetLastError(0xdeadbeef);
154 ret = WinHttpSetOption(connection, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
155 ok(!ret, "should fail to set disable feature for a connection\n");
156 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
157 "expected ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, got %u\n", GetLastError());
159 SetLastError(0xdeadbeef);
160 request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
161 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
162 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
164 skip("Network unreachable, skipping the test\n");
165 goto done;
168 feature = 0xdeadbeef;
169 size = sizeof(feature);
170 SetLastError(0xdeadbeef);
171 ret = WinHttpQueryOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, &size);
172 ok(!ret, "should fail to query disable feature for a request\n");
173 ok(GetLastError() == ERROR_INVALID_PARAMETER,
174 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
176 feature = 0;
177 size = sizeof(feature);
178 SetLastError(0xdeadbeef);
179 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
180 ok(ret, "failed to set feature %u\n", GetLastError());
182 feature = 0xffffffff;
183 size = sizeof(feature);
184 SetLastError(0xdeadbeef);
185 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
186 ok(ret, "failed to set feature %u\n", GetLastError());
188 feature = WINHTTP_DISABLE_COOKIES;
189 size = sizeof(feature);
190 SetLastError(0xdeadbeef);
191 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
192 ok(ret, "failed to set feature %u\n", GetLastError());
194 size = 0;
195 SetLastError(0xdeadbeef);
196 ret = WinHttpQueryOption(request, WINHTTP_OPTION_DISABLE_FEATURE, NULL, &size);
197 ok(!ret, "should fail to query disable feature for a request\n");
198 ok(GetLastError() == ERROR_INVALID_PARAMETER,
199 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
201 SetLastError(0xdeadbeef);
202 ret = WinHttpCloseHandle(request);
203 ok(ret, "WinHttpCloseHandle failed on closing request: %u\n", GetLastError());
205 done:
206 SetLastError(0xdeadbeef);
207 ret = WinHttpCloseHandle(connection);
208 ok(ret, "WinHttpCloseHandle failed on closing connection: %u\n", GetLastError());
209 SetLastError(0xdeadbeef);
210 ret = WinHttpCloseHandle(session);
211 ok(ret, "WinHttpCloseHandle failed on closing session: %u\n", GetLastError());
214 static void test_OpenRequest (void)
216 BOOL ret;
217 HINTERNET session, request, connection;
218 DWORD err;
220 SetLastError(0xdeadbeef);
221 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
222 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
223 err = GetLastError();
224 ok(session != NULL, "WinHttpOpen failed to open session.\n");
225 ok(err == ERROR_SUCCESS, "got %u\n", err);
227 /* Test with a bad server name */
228 SetLastError(0xdeadbeef);
229 connection = WinHttpConnect(session, NULL, INTERNET_DEFAULT_HTTP_PORT, 0);
230 err = GetLastError();
231 ok (connection == NULL, "WinHttpConnect succeeded in opening connection to NULL server argument.\n");
232 ok(err == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u.\n", err);
234 /* Test with a valid server name */
235 SetLastError(0xdeadbeef);
236 connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
237 err = GetLastError();
238 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", err);
239 ok(err == ERROR_SUCCESS || broken(err == WSAEINVAL) /* < win7 */, "got %u\n", err);
241 SetLastError(0xdeadbeef);
242 request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
243 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
244 err = GetLastError();
245 if (request == NULL && err == ERROR_WINHTTP_NAME_NOT_RESOLVED)
247 skip("Network unreachable, skipping.\n");
248 goto done;
250 ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", err);
251 ok(err == ERROR_SUCCESS, "got %u\n", err);
253 SetLastError(0xdeadbeef);
254 ret = WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, NULL, 0, 0, 0);
255 err = GetLastError();
256 if (!ret && err == ERROR_WINHTTP_CANNOT_CONNECT)
258 skip("Connection failed, skipping.\n");
259 goto done;
261 ok(ret, "WinHttpSendRequest failed: %u\n", err);
262 ok(err == ERROR_SUCCESS, "got %u\n", err);
264 SetLastError(0xdeadbeef);
265 ret = WinHttpCloseHandle(request);
266 err = GetLastError();
267 ok(ret, "WinHttpCloseHandle failed on closing request, got %u.\n", err);
268 ok(err == ERROR_SUCCESS, "got %u\n", err);
270 done:
271 ret = WinHttpCloseHandle(connection);
272 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
273 ret = WinHttpCloseHandle(session);
274 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
278 static void test_empty_headers_param(void)
280 static const WCHAR empty[] = {0};
281 HINTERNET ses, con, req;
282 BOOL ret;
284 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
285 ok(ses != NULL, "failed to open session %u\n", GetLastError());
287 con = WinHttpConnect(ses, test_winehq, 80, 0);
288 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
290 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
291 ok(req != NULL, "failed to open a request %u\n", GetLastError());
293 ret = WinHttpSendRequest(req, empty, 0, NULL, 0, 0, 0);
294 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
296 skip("connection failed, skipping\n");
297 goto done;
299 ok(ret, "failed to send request %u\n", GetLastError());
301 done:
302 WinHttpCloseHandle(req);
303 WinHttpCloseHandle(con);
304 WinHttpCloseHandle(ses);
307 static void test_SendRequest (void)
309 static const WCHAR content_type[] =
310 {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t','i','o','n',
311 '/','x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o','d','e','d',0};
312 static const WCHAR test_file[] = {'t','e','s','t','s','/','p','o','s','t','.','p','h','p',0};
313 static const WCHAR test_verb[] = {'P','O','S','T',0};
314 static CHAR post_data[] = "mode=Test";
315 static const char test_post[] = "mode => Test\0\n";
316 HINTERNET session, request, connection;
317 DWORD header_len, optional_len, total_len, bytes_rw, size;
318 DWORD_PTR context;
319 BOOL ret;
320 CHAR buffer[256];
321 int i;
323 header_len = -1L;
324 total_len = optional_len = sizeof(post_data);
325 memset(buffer, 0xff, sizeof(buffer));
327 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
328 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
329 ok(session != NULL, "WinHttpOpen failed to open session.\n");
331 connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
332 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
334 request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
335 WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
336 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
338 skip("Network unreachable, skipping.\n");
339 goto done;
341 ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError());
342 if (!request) goto done;
344 context = 0xdeadbeef;
345 ret = WinHttpSetOption(request, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(context));
346 ok(ret, "WinHttpSetOption failed: %u\n", GetLastError());
348 context++;
349 ret = WinHttpSendRequest(request, content_type, header_len, post_data, optional_len, total_len, context);
350 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
352 skip("connection failed, skipping\n");
353 goto done;
355 ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError());
357 context = 0;
358 size = sizeof(context);
359 ret = WinHttpQueryOption(request, WINHTTP_OPTION_CONTEXT_VALUE, &context, &size);
360 ok(ret, "WinHttpQueryOption failed: %u\n", GetLastError());
361 ok(context == 0xdeadbef0, "expected 0xdeadbef0, got %lx\n", context);
363 for (i = 3; post_data[i]; i++)
365 bytes_rw = -1;
366 SetLastError(0xdeadbeef);
367 ret = WinHttpWriteData(request, &post_data[i], 1, &bytes_rw);
368 if (ret)
370 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %u.\n", GetLastError());
371 ok(bytes_rw == 1, "WinHttpWriteData failed, wrote %u bytes instead of 1 byte.\n", bytes_rw);
373 else /* Since we already passed all optional data in WinHttpSendRequest Win7 fails our WinHttpWriteData call */
375 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER got %u.\n", GetLastError());
376 ok(bytes_rw == -1, "Expected bytes_rw to remain unchanged.\n");
380 SetLastError(0xdeadbeef);
381 ret = WinHttpReceiveResponse(request, NULL);
382 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == ERROR_NO_TOKEN) /* < win7 */,
383 "Expected ERROR_SUCCESS got %u.\n", GetLastError());
384 ok(ret == TRUE, "WinHttpReceiveResponse failed: %u.\n", GetLastError());
386 bytes_rw = -1;
387 ret = WinHttpReadData(request, buffer, sizeof(buffer) - 1, &bytes_rw);
388 ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
390 ok(bytes_rw == sizeof(test_post) - 1, "Read %u bytes\n", bytes_rw);
391 ok(!memcmp(buffer, test_post, sizeof(test_post) - 1), "Data read did not match.\n");
393 done:
394 ret = WinHttpCloseHandle(request);
395 ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
396 ret = WinHttpCloseHandle(connection);
397 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
398 ret = WinHttpCloseHandle(session);
399 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
402 static void test_WinHttpTimeFromSystemTime(void)
404 BOOL ret;
405 static const SYSTEMTIME time = {2008, 7, 1, 28, 10, 5, 52, 0};
406 static const WCHAR expected_string[] =
407 {'M','o','n',',',' ','2','8',' ','J','u','l',' ','2','0','0','8',' ',
408 '1','0',':','0','5',':','5','2',' ','G','M','T',0};
409 WCHAR time_string[WINHTTP_TIME_FORMAT_BUFSIZE+1];
410 DWORD err;
412 SetLastError(0xdeadbeef);
413 ret = WinHttpTimeFromSystemTime(&time, NULL);
414 err = GetLastError();
415 ok(!ret, "WinHttpTimeFromSystemTime succeeded\n");
416 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
418 SetLastError(0xdeadbeef);
419 ret = WinHttpTimeFromSystemTime(NULL, time_string);
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(&time, time_string);
426 err = GetLastError();
427 ok(ret, "WinHttpTimeFromSystemTime failed: %u\n", err);
428 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
429 ok(memcmp(time_string, expected_string, sizeof(expected_string)) == 0,
430 "Time string returned did not match expected time string.\n");
433 static void test_WinHttpTimeToSystemTime(void)
435 BOOL ret;
436 SYSTEMTIME time;
437 static const SYSTEMTIME expected_time = {2008, 7, 1, 28, 10, 5, 52, 0};
438 static const WCHAR time_string1[] =
439 {'M','o','n',',',' ','2','8',' ','J','u','l',' ','2','0','0','8',' ',
440 + '1','0',':','0','5',':','5','2',' ','G','M','T','\n',0};
441 static const WCHAR time_string2[] =
442 {' ','m','o','n',' ','2','8',' ','j','u','l',' ','2','0','0','8',' ',
443 '1','0',' ','0','5',' ','5','2','\n',0};
444 DWORD err;
446 SetLastError(0xdeadbeef);
447 ret = WinHttpTimeToSystemTime(time_string1, NULL);
448 err = GetLastError();
449 ok(!ret, "WinHttpTimeToSystemTime succeeded\n");
450 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
452 SetLastError(0xdeadbeef);
453 ret = WinHttpTimeToSystemTime(NULL, &time);
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(time_string1, &time);
460 err = GetLastError();
461 ok(ret, "WinHttpTimeToSystemTime failed: %u\n", err);
462 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
463 ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
464 "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
466 SetLastError(0xdeadbeef);
467 ret = WinHttpTimeToSystemTime(time_string2, &time);
468 err = GetLastError();
469 ok(ret, "WinHttpTimeToSystemTime failed: %u\n", err);
470 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
471 ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
472 "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
475 static void test_WinHttpAddHeaders(void)
477 HINTERNET session, request, connection;
478 BOOL ret, reverse;
479 WCHAR buffer[MAX_PATH];
480 WCHAR check_buffer[MAX_PATH];
481 DWORD err, index, len, oldlen;
483 static const WCHAR test_file[] = {'/','p','o','s','t','t','e','s','t','.','p','h','p',0};
484 static const WCHAR test_verb[] = {'P','O','S','T',0};
485 static const WCHAR test_header_begin[] =
486 {'P','O','S','T',' ','/','p','o','s','t','t','e','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
487 static const WCHAR full_path_test_header_begin[] =
488 {'P','O','S','T',' ','h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',':','8','0','/','p','o','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
489 static const WCHAR test_header_end[] = {'\r','\n','\r','\n',0};
490 static const WCHAR test_header_name[] = {'W','a','r','n','i','n','g',0};
491 static const WCHAR test_header_name2[] = {'n','a','m','e',0};
492 static const WCHAR test_header_name3[] = {'a',0};
493 static const WCHAR test_header_range[] = {'R','a','n','g','e',0};
494 static const WCHAR test_header_range_bytes[] = {'R','a','n','g','e',':',' ','b','y','t','e','s','=','0','-','7','7','3','\r','\n',0};
495 static const WCHAR test_header_bytes[] = {'b','y','t','e','s','=','0','-','7','7','3',0};
497 static const WCHAR test_flag_coalesce[] = {'t','e','s','t','2',',',' ','t','e','s','t','4',0};
498 static const WCHAR test_flag_coalesce_reverse[] = {'t','e','s','t','3',',',' ','t','e','s','t','4',0};
499 static const WCHAR test_flag_coalesce_comma[] =
500 {'t','e','s','t','2',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',0};
501 static const WCHAR test_flag_coalesce_comma_reverse[] =
502 {'t','e','s','t','3',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',0};
503 static const WCHAR test_flag_coalesce_semicolon[] =
504 {'t','e','s','t','2',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',';',' ','t','e','s','t','6',0};
505 static const WCHAR test_flag_coalesce_semicolon_reverse[] =
506 {'t','e','s','t','3',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',';',' ','t','e','s','t','6',0};
508 static const WCHAR field[] = {'f','i','e','l','d',0};
509 static const WCHAR value[] = {'v','a','l','u','e',' ',0};
510 static const WCHAR value_nospace[] = {'v','a','l','u','e',0};
511 static const WCHAR empty[] = {0};
513 static const WCHAR test_headers[][14] =
515 {'W','a','r','n','i','n','g',':','t','e','s','t','1',0},
516 {'W','a','r','n','i','n','g',':','t','e','s','t','2',0},
517 {'W','a','r','n','i','n','g',':','t','e','s','t','3',0},
518 {'W','a','r','n','i','n','g',':','t','e','s','t','4',0},
519 {'W','a','r','n','i','n','g',':','t','e','s','t','5',0},
520 {'W','a','r','n','i','n','g',':','t','e','s','t','6',0},
521 {'W','a','r','n','i','n','g',':','t','e','s','t','7',0},
522 {0},
523 {':',0},
524 {'a',':',0},
525 {':','b',0},
526 {'c','d',0},
527 {' ','e',' ',':','f',0},
528 {'f','i','e','l','d',':',' ','v','a','l','u','e',' ',0},
529 {'n','a','m','e',':',' ','v','a','l','u','e',0},
530 {'n','a','m','e',':',0}
532 static const WCHAR test_indices[][6] =
534 {'t','e','s','t','1',0},
535 {'t','e','s','t','2',0},
536 {'t','e','s','t','3',0},
537 {'t','e','s','t','4',0}
540 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
541 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
542 ok(session != NULL, "WinHttpOpen failed to open session.\n");
544 connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
545 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
547 request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
548 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
549 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
551 skip("Network unreachable, skipping.\n");
552 goto done;
554 ok(request != NULL, "WinHttpOpenRequest failed to open a request, error: %u.\n", GetLastError());
556 index = 0;
557 len = sizeof(buffer);
558 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
559 test_header_name, buffer, &len, &index);
560 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, found 'Warning' header.\n");
561 SetLastError(0xdeadbeef);
562 ret = WinHttpAddRequestHeaders(request, test_headers[0], -1L, WINHTTP_ADDREQ_FLAG_ADD);
563 err = GetLastError();
564 ok(ret, "WinHttpAddRequestHeader failed to add new header, got %d with error %u.\n", ret, err);
565 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
567 index = 0;
568 len = sizeof(buffer);
569 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
570 test_header_name, buffer, &len, &index);
571 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
572 ok(index == 1, "WinHttpQueryHeaders failed: header index not incremented\n");
573 ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders failed: incorrect string returned\n");
574 ok(len == 5*sizeof(WCHAR), "WinHttpQueryHeaders failed: invalid length returned, expected 5, got %d\n", len);
576 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
577 test_header_name, buffer, &len, &index);
578 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, second index should not exist.\n");
580 /* Try to fetch the header info with a buffer that's big enough to fit the
581 * string but not the NULL terminator.
583 index = 0;
584 len = 5*sizeof(WCHAR);
585 memset(check_buffer, 0xab, sizeof(check_buffer));
586 memcpy(buffer, check_buffer, sizeof(buffer));
587 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
588 test_header_name, buffer, &len, &index);
589 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded with a buffer that's too small.\n");
590 ok(memcmp(buffer, check_buffer, sizeof(buffer)) == 0,
591 "WinHttpQueryHeaders failed, modified the buffer when it should not have.\n");
592 ok(len == 6*sizeof(WCHAR), "WinHttpQueryHeaders returned invalid length, expected 12, got %d\n", len);
594 /* Try with a NULL buffer */
595 index = 0;
596 len = sizeof(buffer);
597 SetLastError(0xdeadbeef);
598 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
599 test_header_name, NULL, &len, &index);
600 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
601 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
602 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
603 ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
605 /* Try with a NULL buffer and a length that's too small */
606 index = 0;
607 len = 10;
608 SetLastError(0xdeadbeef);
609 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
610 test_header_name, NULL, &len, &index);
611 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
612 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
613 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICENT_BUFFER, go %u\n", GetLastError());
614 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
615 ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
617 index = 0;
618 len = 0;
619 SetLastError(0xdeadbeef);
620 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
621 test_header_name, NULL, &len, &index);
622 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
623 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
624 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
625 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
626 ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
628 /* valid query */
629 oldlen = len;
630 index = 0;
631 len = sizeof(buffer);
632 memset(buffer, 0xff, sizeof(buffer));
633 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
634 test_header_name, buffer, &len, &index);
635 ok(ret == TRUE, "WinHttpQueryHeaders failed: got %d\n", ret);
636 ok(len + sizeof(WCHAR) <= oldlen, "WinHttpQueryHeaders resulting length longer than advertized.\n");
637 ok((len < sizeof(buffer) - sizeof(WCHAR)) && buffer[len / sizeof(WCHAR)] == 0, "WinHttpQueryHeaders did not append NULL terminator\n");
638 ok(len == lstrlenW(buffer) * sizeof(WCHAR), "WinHttpQueryHeaders returned incorrect length.\n");
639 ok(memcmp(buffer, test_header_begin, sizeof(test_header_begin)) == 0 ||
640 memcmp(buffer, full_path_test_header_begin, sizeof(full_path_test_header_begin)) == 0,
641 "WinHttpQueryHeaders returned invalid beginning of header string.\n");
642 ok(memcmp(buffer + lstrlenW(buffer) - 4, test_header_end, sizeof(test_header_end)) == 0,
643 "WinHttpQueryHeaders returned invalid end of header string.\n");
644 ok(index == 0, "WinHttpQueryHeaders incremented header index.\n");
646 index = 0;
647 len = 0;
648 SetLastError(0xdeadbeef);
649 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
650 test_header_name, NULL, &len, &index);
651 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
652 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
653 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
654 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
655 ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
657 oldlen = len;
658 index = 0;
659 len = sizeof(buffer);
660 memset(buffer, 0xff, sizeof(buffer));
661 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
662 test_header_name, buffer, &len, &index);
663 ok(ret == TRUE, "WinHttpQueryHeaders failed %u\n", GetLastError());
664 ok(len + sizeof(WCHAR) <= oldlen, "resulting length longer than advertized\n");
665 ok((len < sizeof(buffer) - sizeof(WCHAR)) && !buffer[len / sizeof(WCHAR)] && !buffer[len / sizeof(WCHAR) - 1],
666 "no double NULL terminator\n");
667 ok(memcmp(buffer, test_header_begin, sizeof(test_header_begin)) == 0 ||
668 memcmp(buffer, full_path_test_header_begin, sizeof(full_path_test_header_begin)) == 0,
669 "invalid beginning of header string.\n");
670 ok(index == 0, "header index was incremented\n");
672 /* tests for more indices */
673 ret = WinHttpAddRequestHeaders(request, test_headers[1], -1L, WINHTTP_ADDREQ_FLAG_ADD);
674 ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header: %d\n", ret);
676 index = 0;
677 len = sizeof(buffer);
678 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
679 test_header_name, buffer, &len, &index);
680 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
681 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
682 ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
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 == 2, "WinHttpQueryHeaders failed to increment index.\n");
689 ok(memcmp(buffer, test_indices[1], sizeof(test_indices[1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
691 ret = WinHttpAddRequestHeaders(request, test_headers[2], -1L, WINHTTP_ADDREQ_FLAG_REPLACE);
692 ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header.\n");
694 index = 0;
695 len = sizeof(buffer);
696 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
697 test_header_name, buffer, &len, &index);
698 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
699 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
700 reverse = (memcmp(buffer, test_indices[1], sizeof(test_indices[1])) != 0); /* Win7 returns values in reverse order of adding */
701 ok(memcmp(buffer, test_indices[reverse ? 2 : 1], sizeof(test_indices[reverse ? 2 : 1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
703 len = sizeof(buffer);
704 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
705 test_header_name, buffer, &len, &index);
706 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
707 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
708 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
710 /* add if new flag */
711 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW);
712 ok(ret == FALSE, "WinHttpAddRequestHeaders incorrectly replaced existing header.\n");
714 index = 0;
715 len = sizeof(buffer);
716 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
717 test_header_name, buffer, &len, &index);
718 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
719 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
720 ok(memcmp(buffer, test_indices[reverse ? 2 : 1], sizeof(test_indices[reverse ? 2 : 1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
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 == 2, "WinHttpQueryHeaders failed to increment index.\n");
727 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 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 == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
734 /* coalesce flag */
735 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_COALESCE);
736 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE.\n");
738 index = 0;
739 len = sizeof(buffer);
740 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
741 test_header_name, buffer, &len, &index);
742 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
743 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
744 ok(memcmp(buffer, reverse ? test_flag_coalesce_reverse : test_flag_coalesce,
745 reverse ? sizeof(test_flag_coalesce_reverse) : sizeof(test_flag_coalesce)) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
747 len = sizeof(buffer);
748 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
749 test_header_name, buffer, &len, &index);
750 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
751 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
752 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 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 == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
759 /* coalesce with comma flag */
760 ret = WinHttpAddRequestHeaders(request, test_headers[4], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA);
761 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA.\n");
763 index = 0;
764 len = sizeof(buffer);
765 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
766 test_header_name, buffer, &len, &index);
767 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
768 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
769 ok(memcmp(buffer, reverse ? test_flag_coalesce_comma_reverse : test_flag_coalesce_comma,
770 reverse ? sizeof(test_flag_coalesce_comma_reverse) : sizeof(test_flag_coalesce_comma)) == 0,
771 "WinHttpQueryHeaders returned incorrect string.\n");
773 len = sizeof(buffer);
774 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
775 test_header_name, buffer, &len, &index);
776 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
777 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
778 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "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 == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
786 /* coalesce with semicolon flag */
787 ret = WinHttpAddRequestHeaders(request, test_headers[5], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON);
788 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON.\n");
790 index = 0;
791 len = sizeof(buffer);
792 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
793 test_header_name, buffer, &len, &index);
794 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
795 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
796 ok(memcmp(buffer, reverse ? test_flag_coalesce_semicolon_reverse : test_flag_coalesce_semicolon,
797 reverse ? sizeof(test_flag_coalesce_semicolon_reverse) : sizeof(test_flag_coalesce_semicolon)) == 0,
798 "WinHttpQueryHeaders returned incorrect string.\n");
800 len = sizeof(buffer);
801 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
802 test_header_name, buffer, &len, &index);
803 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
804 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
805 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "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 == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
812 /* add and replace flags */
813 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
814 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE.\n");
816 index = 0;
817 len = sizeof(buffer);
818 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
819 test_header_name, buffer, &len, &index);
820 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
821 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
822 ok(memcmp(buffer, test_indices[reverse ? 3 : 2], sizeof(test_indices[reverse ? 3 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
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 == 2, "WinHttpQueryHeaders failed to increment index.\n");
829 ok(memcmp(buffer, test_indices[reverse ? 1 : 3], sizeof(test_indices[reverse ? 1 : 3])) == 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 == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
836 ret = WinHttpAddRequestHeaders(request, test_headers[8], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
837 ok(!ret, "WinHttpAddRequestHeaders failed\n");
839 ret = WinHttpAddRequestHeaders(request, test_headers[9], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
840 ok(ret, "WinHttpAddRequestHeaders failed\n");
842 index = 0;
843 memset(buffer, 0xff, sizeof(buffer));
844 len = sizeof(buffer);
845 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
846 test_header_name3, buffer, &len, &index);
847 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
848 ok(!memcmp(buffer, empty, sizeof(empty)), "unexpected result\n");
850 ret = WinHttpAddRequestHeaders(request, test_headers[10], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
851 ok(!ret, "WinHttpAddRequestHeaders failed\n");
853 ret = WinHttpAddRequestHeaders(request, test_headers[11], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
854 ok(!ret, "WinHttpAddRequestHeaders failed\n");
856 ret = WinHttpAddRequestHeaders(request, test_headers[12], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
857 ok(!ret, "WinHttpAddRequestHeaders failed\n");
859 ret = WinHttpAddRequestHeaders(request, test_headers[13], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
860 ok(ret, "WinHttpAddRequestHeaders failed\n");
862 index = 0;
863 buffer[0] = 0;
864 len = sizeof(buffer);
865 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
866 field, buffer, &len, &index);
867 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
868 ok(!memcmp(buffer, value, sizeof(value)) || ! memcmp(buffer, value_nospace, sizeof(value_nospace)), "unexpected result\n");
870 SetLastError(0xdeadbeef);
871 ret = WinHttpAddRequestHeaders(request, test_header_range_bytes, 0,
872 WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
873 err = GetLastError();
874 ok(!ret, "unexpected success\n");
875 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
877 ret = WinHttpAddRequestHeaders(request, test_header_range_bytes, ~0u,
878 WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
879 ok(ret, "failed to add header: %u\n", GetLastError());
881 index = 0;
882 len = sizeof(buffer);
883 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
884 test_header_range, buffer, &len, &index);
885 ok(ret, "failed to get range header %u\n", GetLastError());
886 ok(!memcmp(buffer, test_header_bytes, sizeof(test_header_bytes)), "incorrect string returned\n");
887 ok(len == lstrlenW(test_header_bytes) * sizeof(WCHAR), "wrong length %u\n", len);
888 ok(index == 1, "wrong index %u\n", index);
890 index = 0;
891 len = sizeof(buffer);
892 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
893 test_header_name2, buffer, &len, &index);
894 ok(!ret, "unexpected success\n");
896 SetLastError(0xdeadbeef);
897 ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
898 err = GetLastError();
899 ok(!ret, "unexpected success\n");
900 ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
902 ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
903 ok(ret, "got %u\n", GetLastError());
905 index = 0;
906 len = sizeof(buffer);
907 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
908 test_header_name2, buffer, &len, &index);
909 ok(ret, "got %u\n", GetLastError());
910 ok(index == 1, "wrong index %u\n", index);
911 ok(!memcmp(buffer, value_nospace, sizeof(value_nospace)), "incorrect string\n");
913 ret = WinHttpAddRequestHeaders(request, test_headers[15], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
914 ok(ret, "got %u\n", GetLastError());
916 index = 0;
917 len = sizeof(buffer);
918 SetLastError(0xdeadbeef);
919 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
920 test_header_name2, buffer, &len, &index);
921 err = GetLastError();
922 ok(!ret, "unexpected success\n");
923 ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
925 ret = WinHttpAddRequestHeaders(request, test_headers[14], -1L, 0);
926 ok(ret, "got %u\n", GetLastError());
928 index = 0;
929 len = sizeof(buffer);
930 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
931 test_header_name2, buffer, &len, &index);
932 ok(ret, "got %u\n", GetLastError());
933 ok(index == 1, "wrong index %u\n", index);
934 ok(!memcmp(buffer, value_nospace, sizeof(value_nospace)), "incorrect string\n");
936 ret = WinHttpCloseHandle(request);
937 ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
938 done:
939 ret = WinHttpCloseHandle(connection);
940 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
941 ret = WinHttpCloseHandle(session);
942 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
946 static void CALLBACK cert_error(HINTERNET handle, DWORD_PTR ctx, DWORD status, LPVOID buf, DWORD len)
948 DWORD flags = *(DWORD *)buf;
950 if (!flags)
952 trace("WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR\n");
953 return;
955 #define X(x) if (flags & x) trace("%s\n", #x);
956 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED)
957 X(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT)
958 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED)
959 X(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA)
960 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID)
961 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID)
962 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE)
963 #undef X
966 static void test_secure_connection(void)
968 HINTERNET ses, con, req;
969 DWORD size, status, policy, bitness, read_size;
970 BOOL ret;
971 CERT_CONTEXT *cert;
972 WINHTTP_CERTIFICATE_INFO info;
973 char buffer[32];
975 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
976 ok(ses != NULL, "failed to open session %u\n", GetLastError());
978 policy = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
979 ret = WinHttpSetOption(ses, WINHTTP_OPTION_REDIRECT_POLICY, &policy, sizeof(policy));
980 ok(ret, "failed to set redirect policy %u\n", GetLastError());
982 con = WinHttpConnect(ses, test_winehq, 443, 0);
983 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
985 /* try without setting WINHTTP_FLAG_SECURE */
986 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
987 ok(req != NULL, "failed to open a request %u\n", GetLastError());
989 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
990 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
992 skip("Connection failed, skipping.\n");
993 goto cleanup;
995 ok(ret, "failed to send request %u\n", GetLastError());
997 ret = WinHttpReceiveResponse(req, NULL);
998 ok(!ret || proxy_active(), "succeeded unexpectedly\n");
1000 size = 0;
1001 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL);
1002 ok(!ret, "succeeded unexpectedly\n");
1004 WinHttpCloseHandle(req);
1006 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, WINHTTP_FLAG_SECURE);
1007 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1009 WinHttpSetStatusCallback(req, cert_error, WINHTTP_CALLBACK_STATUS_SECURE_FAILURE, 0);
1011 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1012 if (!ret && (GetLastError() == ERROR_WINHTTP_SECURE_FAILURE || GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT))
1014 skip("secure connection failed, skipping remaining secure tests\n");
1015 goto cleanup;
1017 ok(ret, "failed to send request %u\n", GetLastError());
1019 size = sizeof(cert);
1020 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert, &size );
1021 ok(ret, "failed to retrieve certificate context %u\n", GetLastError());
1022 if (ret) CertFreeCertificateContext(cert);
1024 size = sizeof(bitness);
1025 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_KEY_BITNESS, &bitness, &size );
1026 ok(ret, "failed to retrieve key bitness %u\n", GetLastError());
1028 size = sizeof(info);
1029 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT, &info, &size );
1030 ok(ret, "failed to retrieve certificate info %u\n", GetLastError());
1032 if (ret)
1034 trace("lpszSubjectInfo %s\n", wine_dbgstr_w(info.lpszSubjectInfo));
1035 trace("lpszIssuerInfo %s\n", wine_dbgstr_w(info.lpszIssuerInfo));
1036 trace("lpszProtocolName %s\n", wine_dbgstr_w(info.lpszProtocolName));
1037 trace("lpszSignatureAlgName %s\n", wine_dbgstr_w(info.lpszSignatureAlgName));
1038 trace("lpszEncryptionAlgName %s\n", wine_dbgstr_w(info.lpszEncryptionAlgName));
1039 trace("dwKeySize %u\n", info.dwKeySize);
1042 ret = WinHttpReceiveResponse(req, NULL);
1043 ok(ret, "failed to receive response %u\n", GetLastError());
1045 status = 0xdeadbeef;
1046 size = sizeof(status);
1047 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1048 ok(ret, "failed unexpectedly %u\n", GetLastError());
1049 ok(status == 200, "request failed unexpectedly %u\n", status);
1051 size = 0;
1052 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL);
1053 ok(!ret, "succeeded unexpectedly\n");
1055 read_size = 0;
1056 for (;;)
1058 size = 0;
1059 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
1060 ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
1061 if (!size) break;
1062 read_size += size;
1064 ok(read_size > 2014, "read_size = %u\n", read_size);
1066 cleanup:
1067 WinHttpCloseHandle(req);
1068 WinHttpCloseHandle(con);
1069 WinHttpCloseHandle(ses);
1072 static void test_request_parameter_defaults(void)
1074 static const WCHAR empty[] = {0};
1075 HINTERNET ses, con, req;
1076 DWORD size, status, error;
1077 WCHAR *version;
1078 BOOL ret;
1080 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1081 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1083 con = WinHttpConnect(ses, test_winehq, 0, 0);
1084 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1086 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1087 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1089 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1090 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
1092 skip("connection failed, skipping\n");
1093 goto done;
1095 ok(ret, "failed to send request %u\n", GetLastError());
1097 ret = WinHttpReceiveResponse(req, NULL);
1098 if (!ret && GetLastError() == ERROR_WINHTTP_INVALID_SERVER_RESPONSE) /* win2k */
1100 win_skip("invalid response\n");
1101 goto done;
1103 ok(ret, "failed to receive response %u\n", GetLastError());
1105 status = 0xdeadbeef;
1106 size = sizeof(status);
1107 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1108 ok(ret, "failed unexpectedly %u\n", GetLastError());
1109 ok(status == 200, "request failed unexpectedly %u\n", status);
1111 WinHttpCloseHandle(req);
1113 req = WinHttpOpenRequest(con, empty, empty, empty, NULL, NULL, 0);
1114 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1116 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1117 if (!ret && (GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT || GetLastError() == ERROR_WINHTTP_TIMEOUT))
1119 skip("connection failed, skipping\n");
1120 goto done;
1122 ok(ret, "failed to send request %u\n", GetLastError());
1124 ret = WinHttpReceiveResponse(req, NULL);
1125 ok(ret, "failed to receive response %u\n", GetLastError());
1127 size = 0;
1128 SetLastError(0xdeadbeef);
1129 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, NULL, &size, NULL);
1130 error = GetLastError();
1131 ok(!ret, "succeeded unexpectedly\n");
1132 ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error);
1134 version = HeapAlloc(GetProcessHeap(), 0, size);
1135 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, version, &size, NULL);
1136 ok(ret, "failed unexpectedly %u\n", GetLastError());
1137 ok(lstrlenW(version) == size / sizeof(WCHAR), "unexpected size %u\n", size);
1138 HeapFree(GetProcessHeap(), 0, version);
1140 status = 0xdeadbeef;
1141 size = sizeof(status);
1142 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1143 ok(ret, "failed unexpectedly %u\n", GetLastError());
1144 ok(status == 200, "request failed unexpectedly %u\n", status);
1146 done:
1147 WinHttpCloseHandle(req);
1148 WinHttpCloseHandle(con);
1149 WinHttpCloseHandle(ses);
1152 static const WCHAR Connections[] = {
1153 'S','o','f','t','w','a','r','e','\\',
1154 'M','i','c','r','o','s','o','f','t','\\',
1155 'W','i','n','d','o','w','s','\\',
1156 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1157 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
1158 'C','o','n','n','e','c','t','i','o','n','s',0 };
1159 static const WCHAR WinHttpSettings[] = {
1160 'W','i','n','H','t','t','p','S','e','t','t','i','n','g','s',0 };
1162 static DWORD get_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD *type )
1164 LONG l;
1165 HKEY key;
1166 DWORD ret = 0;
1168 l = RegOpenKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, KEY_READ, &key );
1169 if (!l)
1171 DWORD size = 0;
1173 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, NULL, &size );
1174 if (!l)
1176 if (size <= len)
1177 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, buf,
1178 &size );
1179 if (!l)
1180 ret = size;
1182 RegCloseKey( key );
1184 return ret;
1187 static void set_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD type )
1189 LONG l;
1190 HKEY key;
1192 l = RegCreateKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, NULL, 0,
1193 KEY_WRITE, NULL, &key, NULL );
1194 if (!l)
1196 if (len)
1197 RegSetValueExW( key, WinHttpSettings, 0, type, buf, len );
1198 else
1199 RegDeleteValueW( key, WinHttpSettings );
1200 RegCloseKey( key );
1204 static void test_set_default_proxy_config(void)
1206 static WCHAR wideString[] = { 0x226f, 0x575b, 0 };
1207 static WCHAR normalString[] = { 'f','o','o',0 };
1208 DWORD type, len;
1209 BYTE *saved_proxy_settings = NULL;
1210 WINHTTP_PROXY_INFO info;
1211 BOOL ret;
1213 /* FIXME: it would be simpler to read the current settings using
1214 * WinHttpGetDefaultProxyConfiguration and save them using
1215 * WinHttpSetDefaultProxyConfiguration, but they appear to have a bug.
1217 * If a proxy is configured in the registry, e.g. via 'proxcfg -p "foo"',
1218 * the access type reported by WinHttpGetDefaultProxyConfiguration is 1,
1219 * WINHTTP_ACCESS_TYPE_NO_PROXY, whereas it should be
1220 * WINHTTP_ACCESS_TYPE_NAMED_PROXY.
1221 * If WinHttpSetDefaultProxyConfiguration is called with dwAccessType = 1,
1222 * the lpszProxy and lpszProxyBypass values are ignored.
1223 * Thus, if a proxy is set with proxycfg, then calling
1224 * WinHttpGetDefaultProxyConfiguration followed by
1225 * WinHttpSetDefaultProxyConfiguration results in the proxy settings
1226 * getting deleted from the registry.
1228 * Instead I read the current registry value and restore it directly.
1230 len = get_default_proxy_reg_value( NULL, 0, &type );
1231 if (len)
1233 saved_proxy_settings = HeapAlloc( GetProcessHeap(), 0, len );
1234 len = get_default_proxy_reg_value( saved_proxy_settings, len, &type );
1237 if (0)
1239 /* Crashes on Vista and higher */
1240 SetLastError(0xdeadbeef);
1241 ret = WinHttpSetDefaultProxyConfiguration(NULL);
1242 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1243 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1246 /* test with invalid access type */
1247 info.dwAccessType = 0xdeadbeef;
1248 info.lpszProxy = info.lpszProxyBypass = NULL;
1249 SetLastError(0xdeadbeef);
1250 ret = WinHttpSetDefaultProxyConfiguration(&info);
1251 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1252 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1254 /* at a minimum, the proxy server must be set */
1255 info.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
1256 info.lpszProxy = info.lpszProxyBypass = NULL;
1257 SetLastError(0xdeadbeef);
1258 ret = WinHttpSetDefaultProxyConfiguration(&info);
1259 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1260 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1261 info.lpszProxyBypass = normalString;
1262 SetLastError(0xdeadbeef);
1263 ret = WinHttpSetDefaultProxyConfiguration(&info);
1264 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1265 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1267 /* the proxy server can't have wide characters */
1268 info.lpszProxy = wideString;
1269 SetLastError(0xdeadbeef);
1270 ret = WinHttpSetDefaultProxyConfiguration(&info);
1271 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1272 skip("couldn't set default proxy configuration: access denied\n");
1273 else
1274 ok((!ret && GetLastError() == ERROR_INVALID_PARAMETER) ||
1275 broken(ret), /* Earlier winhttp versions on W2K/XP */
1276 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1278 info.lpszProxy = normalString;
1279 SetLastError(0xdeadbeef);
1280 ret = WinHttpSetDefaultProxyConfiguration(&info);
1281 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1282 skip("couldn't set default proxy configuration: access denied\n");
1283 else
1285 ok(ret, "WinHttpSetDefaultProxyConfiguration failed: %u\n", GetLastError());
1286 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
1287 "got %u\n", GetLastError());
1289 set_default_proxy_reg_value( saved_proxy_settings, len, type );
1292 static void test_Timeouts (void)
1294 BOOL ret;
1295 DWORD value, size;
1296 HINTERNET ses, req, con;
1298 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1299 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1301 SetLastError(0xdeadbeef);
1302 ret = WinHttpSetTimeouts(ses, -2, 0, 0, 0);
1303 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1304 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1306 SetLastError(0xdeadbeef);
1307 ret = WinHttpSetTimeouts(ses, 0, -2, 0, 0);
1308 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1309 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1311 SetLastError(0xdeadbeef);
1312 ret = WinHttpSetTimeouts(ses, 0, 0, -2, 0);
1313 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1314 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1316 SetLastError(0xdeadbeef);
1317 ret = WinHttpSetTimeouts(ses, 0, 0, 0, -2);
1318 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1319 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1321 SetLastError(0xdeadbeef);
1322 ret = WinHttpSetTimeouts(ses, -1, -1, -1, -1);
1323 ok(ret, "%u\n", GetLastError());
1324 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
1325 "expected ERROR_SUCCESS, got %u\n", GetLastError());
1327 SetLastError(0xdeadbeef);
1328 ret = WinHttpSetTimeouts(ses, 0, 0, 0, 0);
1329 ok(ret, "%u\n", GetLastError());
1331 SetLastError(0xdeadbeef);
1332 ret = WinHttpSetTimeouts(ses, 0x0123, 0x4567, 0x89ab, 0xcdef);
1333 ok(ret, "%u\n", GetLastError());
1335 SetLastError(0xdeadbeef);
1336 value = 0xdeadbeef;
1337 size = sizeof(DWORD);
1338 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1339 ok(ret, "%u\n", GetLastError());
1340 ok(value == 0x0123, "Expected 0x0123, got %u\n", value);
1342 SetLastError(0xdeadbeef);
1343 value = 0xdeadbeef;
1344 size = sizeof(DWORD);
1345 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1346 ok(ret, "%u\n", GetLastError());
1347 ok(value == 0x4567, "Expected 0x4567, got %u\n", value);
1349 SetLastError(0xdeadbeef);
1350 value = 0xdeadbeef;
1351 size = sizeof(DWORD);
1352 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1353 ok(ret, "%u\n", GetLastError());
1354 ok(value == 0x89ab, "Expected 0x89ab, got %u\n", value);
1356 SetLastError(0xdeadbeef);
1357 value = 0xdeadbeef;
1358 size = sizeof(DWORD);
1359 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1360 ok(ret, "%u\n", GetLastError());
1361 ok(value == 0xcdef, "Expected 0xcdef, got %u\n", value);
1363 SetLastError(0xdeadbeef);
1364 value = 0;
1365 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1366 ok(ret, "%u\n", GetLastError());
1368 SetLastError(0xdeadbeef);
1369 value = 0xdeadbeef;
1370 size = sizeof(DWORD);
1371 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1372 ok(ret, "%u\n", GetLastError());
1373 ok(value == 0, "Expected 0, got %u\n", value);
1375 SetLastError(0xdeadbeef);
1376 value = 0;
1377 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1378 ok(ret, "%u\n", GetLastError());
1380 SetLastError(0xdeadbeef);
1381 value = 0xdeadbeef;
1382 size = sizeof(DWORD);
1383 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1384 ok(ret, "%u\n", GetLastError());
1385 ok(value == 0, "Expected 0, got %u\n", value);
1387 SetLastError(0xdeadbeef);
1388 value = 0;
1389 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1390 ok(ret, "%u\n", GetLastError());
1392 SetLastError(0xdeadbeef);
1393 value = 0xdeadbeef;
1394 size = sizeof(DWORD);
1395 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1396 ok(ret, "%u\n", GetLastError());
1397 ok(value == 0, "Expected 0, got %u\n", value);
1399 SetLastError(0xdeadbeef);
1400 value = 0;
1401 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1402 ok(ret, "%u\n", GetLastError());
1404 SetLastError(0xdeadbeef);
1405 value = 0xdeadbeef;
1406 size = sizeof(DWORD);
1407 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1408 ok(ret, "%u\n", GetLastError());
1409 ok(value == 0, "Expected 0, got %u\n", value);
1411 SetLastError(0xdeadbeef);
1412 value = 0xbeefdead;
1413 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1414 ok(ret, "%u\n", GetLastError());
1416 SetLastError(0xdeadbeef);
1417 value = 0xdeadbeef;
1418 size = sizeof(DWORD);
1419 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1420 ok(ret, "%u\n", GetLastError());
1421 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1423 SetLastError(0xdeadbeef);
1424 value = 0xbeefdead;
1425 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1426 ok(ret, "%u\n", GetLastError());
1428 SetLastError(0xdeadbeef);
1429 value = 0xdeadbeef;
1430 size = sizeof(DWORD);
1431 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1432 ok(ret, "%u\n", GetLastError());
1433 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1435 SetLastError(0xdeadbeef);
1436 value = 0xbeefdead;
1437 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1438 ok(ret, "%u\n", GetLastError());
1440 SetLastError(0xdeadbeef);
1441 value = 0xdeadbeef;
1442 size = sizeof(DWORD);
1443 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1444 ok(ret, "%u\n", GetLastError());
1445 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1447 SetLastError(0xdeadbeef);
1448 value = 0xbeefdead;
1449 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1450 ok(ret, "%u\n", GetLastError());
1452 SetLastError(0xdeadbeef);
1453 value = 0xdeadbeef;
1454 size = sizeof(DWORD);
1455 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1456 ok(ret, "%u\n", GetLastError());
1457 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1459 con = WinHttpConnect(ses, test_winehq, 0, 0);
1460 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1462 /* Timeout values should match the last one set for session */
1463 SetLastError(0xdeadbeef);
1464 value = 0xdeadbeef;
1465 size = sizeof(DWORD);
1466 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1467 ok(ret, "%u\n", GetLastError());
1468 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1470 SetLastError(0xdeadbeef);
1471 value = 0xdeadbeef;
1472 size = sizeof(DWORD);
1473 ret = WinHttpQueryOption(con, 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 = 0xdeadbeef;
1479 size = sizeof(DWORD);
1480 ret = WinHttpQueryOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1481 ok(ret, "%u\n", GetLastError());
1482 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1484 SetLastError(0xdeadbeef);
1485 value = 0xdeadbeef;
1486 size = sizeof(DWORD);
1487 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1488 ok(ret, "%u\n", GetLastError());
1489 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1491 SetLastError(0xdeadbeef);
1492 ret = WinHttpSetTimeouts(con, -2, 0, 0, 0);
1493 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1494 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1496 SetLastError(0xdeadbeef);
1497 ret = WinHttpSetTimeouts(con, 0, -2, 0, 0);
1498 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1499 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1501 SetLastError(0xdeadbeef);
1502 ret = WinHttpSetTimeouts(con, 0, 0, -2, 0);
1503 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1504 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1506 SetLastError(0xdeadbeef);
1507 ret = WinHttpSetTimeouts(con, 0, 0, 0, -2);
1508 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1509 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1511 SetLastError(0xdeadbeef);
1512 ret = WinHttpSetTimeouts(con, -1, -1, -1, -1);
1513 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1514 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1516 SetLastError(0xdeadbeef);
1517 ret = WinHttpSetTimeouts(con, 0, 0, 0, 0);
1518 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1519 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1521 SetLastError(0xdeadbeef);
1522 value = 0;
1523 ret = WinHttpSetOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1524 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1525 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1527 SetLastError(0xdeadbeef);
1528 value = 0;
1529 ret = WinHttpSetOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1530 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1531 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1533 SetLastError(0xdeadbeef);
1534 value = 0;
1535 ret = WinHttpSetOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1536 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1537 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1539 SetLastError(0xdeadbeef);
1540 value = 0;
1541 ret = WinHttpSetOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1542 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1543 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1545 /* Changing timeout values for session should affect the values for connection */
1546 SetLastError(0xdeadbeef);
1547 value = 0xdead;
1548 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1549 ok(ret, "%u\n", GetLastError());
1551 SetLastError(0xdeadbeef);
1552 value = 0xdeadbeef;
1553 size = sizeof(DWORD);
1554 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1555 ok(ret, "%u\n", GetLastError());
1556 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1558 SetLastError(0xdeadbeef);
1559 value = 0xdead;
1560 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1561 ok(ret, "%u\n", GetLastError());
1563 SetLastError(0xdeadbeef);
1564 value = 0xdeadbeef;
1565 size = sizeof(DWORD);
1566 ret = WinHttpQueryOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1567 ok(ret, "%u\n", GetLastError());
1568 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1570 SetLastError(0xdeadbeef);
1571 value = 0xdead;
1572 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1573 ok(ret, "%u\n", GetLastError());
1575 SetLastError(0xdeadbeef);
1576 value = 0xdeadbeef;
1577 size = sizeof(DWORD);
1578 ret = WinHttpQueryOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1579 ok(ret, "%u\n", GetLastError());
1580 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1582 SetLastError(0xdeadbeef);
1583 value = 0xdead;
1584 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1585 ok(ret, "%u\n", GetLastError());
1587 SetLastError(0xdeadbeef);
1588 value = 0xdeadbeef;
1589 size = sizeof(DWORD);
1590 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1591 ok(ret, "%u\n", GetLastError());
1592 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1594 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1595 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1597 /* Timeout values should match the last one set for session */
1598 SetLastError(0xdeadbeef);
1599 value = 0xdeadbeef;
1600 size = sizeof(DWORD);
1601 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1602 ok(ret, "%u\n", GetLastError());
1603 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1605 SetLastError(0xdeadbeef);
1606 value = 0xdeadbeef;
1607 size = sizeof(DWORD);
1608 ret = WinHttpQueryOption(req, 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 = 0xdeadbeef;
1614 size = sizeof(DWORD);
1615 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1616 ok(ret, "%u\n", GetLastError());
1617 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1619 SetLastError(0xdeadbeef);
1620 value = 0xdeadbeef;
1621 size = sizeof(DWORD);
1622 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1623 ok(ret, "%u\n", GetLastError());
1624 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1626 SetLastError(0xdeadbeef);
1627 ret = WinHttpSetTimeouts(req, -2, 0, 0, 0);
1628 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1629 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1631 SetLastError(0xdeadbeef);
1632 ret = WinHttpSetTimeouts(req, 0, -2, 0, 0);
1633 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1634 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1636 SetLastError(0xdeadbeef);
1637 ret = WinHttpSetTimeouts(req, 0, 0, -2, 0);
1638 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1639 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1641 SetLastError(0xdeadbeef);
1642 ret = WinHttpSetTimeouts(req, 0, 0, 0, -2);
1643 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1644 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1646 SetLastError(0xdeadbeef);
1647 ret = WinHttpSetTimeouts(req, -1, -1, -1, -1);
1648 ok(ret, "%u\n", GetLastError());
1650 SetLastError(0xdeadbeef);
1651 ret = WinHttpSetTimeouts(req, 0, 0, 0, 0);
1652 ok(ret, "%u\n", GetLastError());
1654 SetLastError(0xdeadbeef);
1655 ret = WinHttpSetTimeouts(req, 0xcdef, 0x89ab, 0x4567, 0x0123);
1656 ok(ret, "%u\n", GetLastError());
1658 SetLastError(0xdeadbeef);
1659 value = 0xdeadbeef;
1660 size = sizeof(DWORD);
1661 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1662 ok(ret, "%u\n", GetLastError());
1663 ok(value == 0xcdef, "Expected 0xcdef, got %u\n", value);
1665 SetLastError(0xdeadbeef);
1666 value = 0xdeadbeef;
1667 size = sizeof(DWORD);
1668 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1669 ok(ret, "%u\n", GetLastError());
1670 ok(value == 0x89ab, "Expected 0x89ab, got %u\n", value);
1672 SetLastError(0xdeadbeef);
1673 value = 0xdeadbeef;
1674 size = sizeof(DWORD);
1675 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1676 ok(ret, "%u\n", GetLastError());
1677 ok(value == 0x4567, "Expected 0x4567, got %u\n", value);
1679 SetLastError(0xdeadbeef);
1680 value = 0xdeadbeef;
1681 size = sizeof(DWORD);
1682 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1683 ok(ret, "%u\n", GetLastError());
1684 ok(value == 0x0123, "Expected 0x0123, got %u\n", value);
1686 SetLastError(0xdeadbeef);
1687 value = 0;
1688 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1689 ok(ret, "%u\n", GetLastError());
1691 SetLastError(0xdeadbeef);
1692 value = 0xdeadbeef;
1693 size = sizeof(DWORD);
1694 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1695 ok(ret, "%u\n", GetLastError());
1696 ok(value == 0, "Expected 0, got %u\n", value);
1698 SetLastError(0xdeadbeef);
1699 value = 0;
1700 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1701 ok(ret, "%u\n", GetLastError());
1703 SetLastError(0xdeadbeef);
1704 value = 0xdeadbeef;
1705 size = sizeof(DWORD);
1706 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1707 ok(ret, "%u\n", GetLastError());
1708 ok(value == 0, "Expected 0, got %u\n", value);
1710 SetLastError(0xdeadbeef);
1711 value = 0;
1712 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1713 ok(ret, "%u\n", GetLastError());
1715 SetLastError(0xdeadbeef);
1716 value = 0xdeadbeef;
1717 size = sizeof(DWORD);
1718 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1719 ok(ret, "%u\n", GetLastError());
1720 ok(value == 0, "Expected 0, got %u\n", value);
1722 SetLastError(0xdeadbeef);
1723 value = 0;
1724 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1725 ok(ret, "%u\n", GetLastError());
1727 SetLastError(0xdeadbeef);
1728 value = 0xdeadbeef;
1729 size = sizeof(DWORD);
1730 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1731 ok(ret, "%u\n", GetLastError());
1732 ok(value == 0, "Expected 0, got %u\n", value);
1734 SetLastError(0xdeadbeef);
1735 value = 0xbeefdead;
1736 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1737 ok(ret, "%u\n", GetLastError());
1739 SetLastError(0xdeadbeef);
1740 value = 0xdeadbeef;
1741 size = sizeof(DWORD);
1742 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1743 ok(ret, "%u\n", GetLastError());
1744 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1746 SetLastError(0xdeadbeef);
1747 value = 0xbeefdead;
1748 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1749 ok(ret, "%u\n", GetLastError());
1751 SetLastError(0xdeadbeef);
1752 value = 0xdeadbeef;
1753 size = sizeof(DWORD);
1754 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1755 ok(ret, "%u\n", GetLastError());
1756 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1758 SetLastError(0xdeadbeef);
1759 value = 0xbeefdead;
1760 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1761 ok(ret, "%u\n", GetLastError());
1763 SetLastError(0xdeadbeef);
1764 value = 0xdeadbeef;
1765 size = sizeof(DWORD);
1766 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1767 ok(ret, "%u\n", GetLastError());
1768 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1770 SetLastError(0xdeadbeef);
1771 value = 0xbeefdead;
1772 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1773 ok(ret, "%u\n", GetLastError());
1775 SetLastError(0xdeadbeef);
1776 value = 0xdeadbeef;
1777 size = sizeof(DWORD);
1778 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1779 ok(ret, "%u\n", GetLastError());
1780 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1782 /* Changing timeout values for session should not affect the values for a request,
1783 * neither should the other way around.
1785 SetLastError(0xdeadbeef);
1786 value = 0xbeefdead;
1787 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1788 ok(ret, "%u\n", GetLastError());
1790 SetLastError(0xdeadbeef);
1791 value = 0xdeadbeef;
1792 size = sizeof(DWORD);
1793 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1794 ok(ret, "%u\n", GetLastError());
1795 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1797 SetLastError(0xdeadbeef);
1798 value = 0xbeefdead;
1799 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1800 ok(ret, "%u\n", GetLastError());
1802 SetLastError(0xdeadbeef);
1803 value = 0xdeadbeef;
1804 size = sizeof(DWORD);
1805 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1806 ok(ret, "%u\n", GetLastError());
1807 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1809 SetLastError(0xdeadbeef);
1810 value = 0xbeefdead;
1811 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1812 ok(ret, "%u\n", GetLastError());
1814 SetLastError(0xdeadbeef);
1815 value = 0xdeadbeef;
1816 size = sizeof(DWORD);
1817 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1818 ok(ret, "%u\n", GetLastError());
1819 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1821 SetLastError(0xdeadbeef);
1822 value = 0xbeefdead;
1823 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1824 ok(ret, "%u\n", GetLastError());
1826 SetLastError(0xdeadbeef);
1827 value = 0xdeadbeef;
1828 size = sizeof(DWORD);
1829 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1830 ok(ret, "%u\n", GetLastError());
1831 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1833 SetLastError(0xdeadbeef);
1834 value = 0xbeef;
1835 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1836 ok(ret, "%u\n", GetLastError());
1838 SetLastError(0xdeadbeef);
1839 value = 0xdeadbeef;
1840 size = sizeof(DWORD);
1841 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1842 ok(ret, "%u\n", GetLastError());
1843 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1845 SetLastError(0xdeadbeef);
1846 value = 0xbeef;
1847 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1848 ok(ret, "%u\n", GetLastError());
1850 SetLastError(0xdeadbeef);
1851 value = 0xdeadbeef;
1852 size = sizeof(DWORD);
1853 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1854 ok(ret, "%u\n", GetLastError());
1855 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1857 SetLastError(0xdeadbeef);
1858 value = 0xbeef;
1859 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1860 ok(ret, "%u\n", GetLastError());
1862 SetLastError(0xdeadbeef);
1863 value = 0xdeadbeef;
1864 size = sizeof(DWORD);
1865 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1866 ok(ret, "%u\n", GetLastError());
1867 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1869 SetLastError(0xdeadbeef);
1870 value = 0xbeef;
1871 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1872 ok(ret, "%u\n", GetLastError());
1874 SetLastError(0xdeadbeef);
1875 value = 0xdeadbeef;
1876 size = sizeof(DWORD);
1877 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1878 ok(ret, "%u\n", GetLastError());
1879 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1881 WinHttpCloseHandle(req);
1882 WinHttpCloseHandle(con);
1883 WinHttpCloseHandle(ses);
1886 static void test_resolve_timeout(void)
1888 static const WCHAR nxdomain[] =
1889 {'n','x','d','o','m','a','i','n','.','w','i','n','e','h','q','.','o','r','g',0};
1890 HINTERNET ses, con, req;
1891 DWORD timeout;
1892 BOOL ret;
1894 if (! proxy_active())
1896 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1897 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1899 timeout = 10000;
1900 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
1901 ok(ret, "failed to set resolve timeout %u\n", GetLastError());
1903 con = WinHttpConnect(ses, nxdomain, 0, 0);
1904 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1906 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1907 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1909 SetLastError(0xdeadbeef);
1910 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1911 if (ret)
1913 skip("nxdomain returned success. Broken ISP redirects?\n");
1914 goto done;
1916 ok(GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED,
1917 "expected ERROR_WINHTTP_NAME_NOT_RESOLVED got %u\n", GetLastError());
1919 WinHttpCloseHandle(req);
1920 WinHttpCloseHandle(con);
1921 WinHttpCloseHandle(ses);
1923 else
1924 skip("Skipping host resolution tests, host resolution preformed by proxy\n");
1926 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1927 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1929 timeout = 10000;
1930 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
1931 ok(ret, "failed to set resolve timeout %u\n", GetLastError());
1933 con = WinHttpConnect(ses, test_winehq, 0, 0);
1934 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1936 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1937 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1939 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1940 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
1942 skip("connection failed, skipping\n");
1943 goto done;
1945 ok(ret, "failed to send request\n");
1947 done:
1948 WinHttpCloseHandle(req);
1949 WinHttpCloseHandle(con);
1950 WinHttpCloseHandle(ses);
1953 static const char page1[] =
1954 "<HTML>\r\n"
1955 "<HEAD><TITLE>winhttp test page</TITLE></HEAD>\r\n"
1956 "<BODY>The quick brown fox jumped over the lazy dog<P></BODY>\r\n"
1957 "</HTML>\r\n\r\n";
1959 static const char okmsg[] =
1960 "HTTP/1.1 200 OK\r\n"
1961 "Server: winetest\r\n"
1962 "\r\n";
1964 static const char notokmsg[] =
1965 "HTTP/1.1 400 Bad Request\r\n"
1966 "\r\n";
1968 static const char cookiemsg[] =
1969 "HTTP/1.1 200 OK\r\n"
1970 "Set-Cookie: name = value \r\n"
1971 "Set-Cookie: NAME = value \r\n"
1972 "\r\n";
1974 static const char nocontentmsg[] =
1975 "HTTP/1.1 204 No Content\r\n"
1976 "Server: winetest\r\n"
1977 "\r\n";
1979 static const char notmodified[] =
1980 "HTTP/1.1 304 Not Modified\r\n"
1981 "\r\n";
1983 static const char noauthmsg[] =
1984 "HTTP/1.1 401 Unauthorized\r\n"
1985 "Server: winetest\r\n"
1986 "Connection: close\r\n"
1987 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
1988 "\r\n";
1990 static const char okauthmsg[] =
1991 "HTTP/1.1 200 OK\r\n"
1992 "Server: winetest\r\n"
1993 "Connection: close\r\n"
1994 "\r\n";
1996 static const char headmsg[] =
1997 "HTTP/1.1 200 OK\r\n"
1998 "Content-Length: 100\r\n"
1999 "\r\n";
2001 struct server_info
2003 HANDLE event;
2004 int port;
2007 #define BIG_BUFFER_LEN 0x2250
2009 static DWORD CALLBACK server_thread(LPVOID param)
2011 struct server_info *si = param;
2012 int r, c = -1, i, on;
2013 SOCKET s;
2014 struct sockaddr_in sa;
2015 char buffer[0x100];
2016 WSADATA wsaData;
2017 int last_request = 0;
2019 WSAStartup(MAKEWORD(1,1), &wsaData);
2021 s = socket(AF_INET, SOCK_STREAM, 0);
2022 if (s == INVALID_SOCKET)
2023 return 1;
2025 on = 1;
2026 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof on);
2028 memset(&sa, 0, sizeof sa);
2029 sa.sin_family = AF_INET;
2030 sa.sin_port = htons(si->port);
2031 sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
2033 r = bind(s, (struct sockaddr *)&sa, sizeof(sa));
2034 if (r < 0)
2035 return 1;
2037 listen(s, 0);
2038 SetEvent(si->event);
2041 if (c == -1) c = accept(s, NULL, NULL);
2043 memset(buffer, 0, sizeof buffer);
2044 for(i = 0; i < sizeof buffer - 1; i++)
2046 r = recv(c, &buffer[i], 1, 0);
2047 if (r != 1)
2048 break;
2049 if (i < 4) continue;
2050 if (buffer[i - 2] == '\n' && buffer[i] == '\n' &&
2051 buffer[i - 3] == '\r' && buffer[i - 1] == '\r')
2052 break;
2054 if (strstr(buffer, "GET /basic"))
2056 send(c, okmsg, sizeof okmsg - 1, 0);
2057 send(c, page1, sizeof page1 - 1, 0);
2059 if (strstr(buffer, "/auth"))
2061 if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
2062 send(c, okauthmsg, sizeof okauthmsg - 1, 0);
2063 else
2064 send(c, noauthmsg, sizeof noauthmsg - 1, 0);
2066 if (strstr(buffer, "/big"))
2068 char msg[BIG_BUFFER_LEN];
2069 memset(msg, 'm', sizeof(msg));
2070 send(c, okmsg, sizeof(okmsg) - 1, 0);
2071 send(c, msg, sizeof(msg), 0);
2073 if (strstr(buffer, "/no_headers"))
2075 send(c, page1, sizeof page1 - 1, 0);
2077 if (strstr(buffer, "GET /no_content"))
2079 send(c, nocontentmsg, sizeof nocontentmsg - 1, 0);
2080 continue;
2082 if (strstr(buffer, "GET /not_modified"))
2084 if (strstr(buffer, "If-Modified-Since:")) send(c, notmodified, sizeof notmodified - 1, 0);
2085 else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2086 continue;
2088 if (strstr(buffer, "HEAD /head"))
2090 send(c, headmsg, sizeof headmsg - 1, 0);
2091 continue;
2093 if (strstr(buffer, "GET /cookie3"))
2095 if (strstr(buffer, "Cookie: name=value2; NAME=value; name=value\r\n") ||
2096 broken(strstr(buffer, "Cookie: name=value2; name=value; NAME=value\r\n") != NULL))
2097 send(c, okmsg, sizeof(okmsg) - 1, 0);
2098 else
2099 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2101 if (strstr(buffer, "GET /cookie2"))
2103 if (strstr(buffer, "Cookie: NAME=value; name=value\r\n") ||
2104 broken(strstr(buffer, "Cookie: name=value; NAME=value\r\n") != NULL))
2105 send(c, okmsg, sizeof(okmsg) - 1, 0);
2106 else
2107 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2109 else if (strstr(buffer, "GET /cookie"))
2111 if (!strstr(buffer, "Cookie: name=value\r\n")) send(c, cookiemsg, sizeof(cookiemsg) - 1, 0);
2112 else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2114 if (strstr(buffer, "GET /quit"))
2116 send(c, okmsg, sizeof okmsg - 1, 0);
2117 send(c, page1, sizeof page1 - 1, 0);
2118 last_request = 1;
2120 shutdown(c, 2);
2121 closesocket(c);
2122 c = -1;
2124 } while (!last_request);
2126 closesocket(s);
2127 return 0;
2130 static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path)
2132 static const WCHAR test_header_end_clrf[] = {'\r','\n','\r','\n',0};
2133 static const WCHAR test_header_end_raw[] = {0,0};
2134 HINTERNET ses, con, req;
2135 char buffer[0x100];
2136 WCHAR buffer2[0x100];
2137 DWORD count, status, size, error, supported, first, target;
2138 BOOL ret;
2140 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
2141 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2143 con = WinHttpConnect(ses, localhostW, port, 0);
2144 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2146 req = WinHttpOpenRequest(con, verb, path, NULL, NULL, NULL, 0);
2147 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2149 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2150 ok(ret, "failed to send request %u\n", GetLastError());
2152 ret = WinHttpReceiveResponse(req, NULL);
2153 ok(ret, "failed to receive response %u\n", GetLastError());
2155 status = 0xdeadbeef;
2156 size = sizeof(status);
2157 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2158 ok(ret, "failed to query status code %u\n", GetLastError());
2159 ok(status == 200, "request failed unexpectedly %u\n", status);
2161 supported = first = target = 0xdeadbeef;
2162 SetLastError(0xdeadbeef);
2163 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2164 error = GetLastError();
2165 ok(!ret, "unexpected success\n");
2166 todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
2167 ok(supported == 0xdeadbeef, "got %x\n", supported);
2168 ok(first == 0xdeadbeef, "got %x\n", first);
2169 ok(target == 0xdeadbeef, "got %x\n", target);
2171 size = sizeof(buffer2);
2172 memset(buffer2, 0, sizeof(buffer2));
2173 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, buffer2, &size, NULL);
2174 ok(ret, "failed to query for raw headers: %u\n", GetLastError());
2175 ok(!memcmp(buffer2 + lstrlenW(buffer2) - 4, test_header_end_clrf, sizeof(test_header_end_clrf)),
2176 "WinHttpQueryHeaders returned invalid end of header string\n");
2178 size = sizeof(buffer2);
2179 memset(buffer2, 0, sizeof(buffer2));
2180 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS, NULL, buffer2, &size, NULL);
2181 ok(ret, "failed to query for raw headers: %u\n", GetLastError());
2182 ok(!memcmp(buffer2 + (size / sizeof(WCHAR)) - 1, test_header_end_raw, sizeof(test_header_end_raw)),
2183 "WinHttpQueryHeaders returned invalid end of header string\n");
2184 ok(buffer2[(size / sizeof(WCHAR)) - 2] != 0, "returned string has too many NULL characters\n");
2186 count = 0;
2187 memset(buffer, 0, sizeof(buffer));
2188 ret = WinHttpReadData(req, buffer, sizeof buffer, &count);
2189 ok(ret, "failed to read data %u\n", GetLastError());
2190 ok(count == sizeof page1 - 1, "count was wrong\n");
2191 ok(!memcmp(buffer, page1, sizeof page1), "http data wrong\n");
2193 WinHttpCloseHandle(req);
2194 WinHttpCloseHandle(con);
2195 WinHttpCloseHandle(ses);
2198 static void test_basic_authentication(int port)
2200 static const WCHAR authW[] = {'/','a','u','t','h',0};
2201 static WCHAR userW[] = {'u','s','e','r',0};
2202 static WCHAR passW[] = {'p','w','d',0};
2203 static WCHAR pass2W[] = {'p','w','d','2',0};
2204 HINTERNET ses, con, req;
2205 DWORD status, size, error, supported, first, target;
2206 BOOL ret;
2208 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
2209 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2211 con = WinHttpConnect(ses, localhostW, port, 0);
2212 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2214 req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2215 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2217 SetLastError(0xdeadbeef);
2218 ret = WinHttpQueryAuthSchemes(NULL, NULL, NULL, NULL);
2219 error = GetLastError();
2220 ok(!ret, "expected failure\n");
2221 ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
2223 SetLastError(0xdeadbeef);
2224 ret = WinHttpQueryAuthSchemes(req, NULL, NULL, NULL);
2225 error = GetLastError();
2226 ok(!ret, "expected failure\n");
2227 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2229 supported = 0xdeadbeef;
2230 SetLastError(0xdeadbeef);
2231 ret = WinHttpQueryAuthSchemes(req, &supported, NULL, NULL);
2232 error = GetLastError();
2233 ok(!ret, "expected failure\n");
2234 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2235 ok(supported == 0xdeadbeef, "got %x\n", supported);
2237 supported = first = 0xdeadbeef;
2238 SetLastError(0xdeadbeef);
2239 ret = WinHttpQueryAuthSchemes(req, &supported, &first, NULL);
2240 error = GetLastError();
2241 ok(!ret, "expected failure\n");
2242 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2243 ok(supported == 0xdeadbeef, "got %x\n", supported);
2244 ok(first == 0xdeadbeef, "got %x\n", first);
2246 supported = first = target = 0xdeadbeef;
2247 SetLastError(0xdeadbeef);
2248 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2249 error = GetLastError();
2250 ok(!ret, "expected failure\n");
2251 todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
2252 ok(supported == 0xdeadbeef, "got %x\n", supported);
2253 ok(first == 0xdeadbeef, "got %x\n", first);
2254 ok(target == 0xdeadbeef, "got %x\n", target);
2256 supported = first = target = 0xdeadbeef;
2257 SetLastError(0xdeadbeef);
2258 ret = WinHttpQueryAuthSchemes(NULL, &supported, &first, &target);
2259 error = GetLastError();
2260 ok(!ret, "expected failure\n");
2261 ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
2262 ok(supported == 0xdeadbeef, "got %x\n", supported);
2263 ok(first == 0xdeadbeef, "got %x\n", first);
2264 ok(target == 0xdeadbeef, "got %x\n", target);
2266 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2267 ok(ret, "failed to send request %u\n", GetLastError());
2269 ret = WinHttpReceiveResponse(req, NULL);
2270 ok(ret, "failed to receive response %u\n", GetLastError());
2272 status = 0xdeadbeef;
2273 size = sizeof(status);
2274 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2275 ok(ret, "failed to query status code %u\n", GetLastError());
2276 ok(status == 401, "request failed unexpectedly %u\n", status);
2278 supported = first = target = 0xdeadbeef;
2279 SetLastError(0xdeadbeef);
2280 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2281 error = GetLastError();
2282 ok(ret, "failed to query authentication schemes %u\n", error);
2283 ok(error == ERROR_SUCCESS || broken(error == 0xdeadbeef) /* < win7 */, "expected ERROR_SUCCESS, got %u\n", error);
2284 ok(supported == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", supported);
2285 ok(first == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", first);
2286 ok(target == WINHTTP_AUTH_TARGET_SERVER, "got %x\n", target);
2288 SetLastError(0xdeadbeef);
2289 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NTLM, NULL, NULL, NULL);
2290 error = GetLastError();
2291 ok(ret, "failed to set credentials %u\n", error);
2292 ok(error == ERROR_SUCCESS || broken(error == 0xdeadbeef) /* < win7 */, "expected ERROR_SUCCESS, got %u\n", error);
2294 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_PASSPORT, NULL, NULL, NULL);
2295 ok(ret, "failed to set credentials %u\n", GetLastError());
2297 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NEGOTIATE, NULL, NULL, NULL);
2298 ok(ret, "failed to set credentials %u\n", GetLastError());
2300 SetLastError(0xdeadbeef);
2301 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_DIGEST, NULL, NULL, NULL);
2302 error = GetLastError();
2303 ok(!ret, "expected failure\n");
2304 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2306 SetLastError(0xdeadbeef);
2307 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, NULL, NULL);
2308 error = GetLastError();
2309 ok(!ret, "expected failure\n");
2310 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2312 SetLastError(0xdeadbeef);
2313 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, NULL, NULL);
2314 error = GetLastError();
2315 ok(!ret, "expected failure\n");
2316 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2318 SetLastError(0xdeadbeef);
2319 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, passW, NULL);
2320 error = GetLastError();
2321 ok(!ret, "expected failure\n");
2322 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2324 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
2325 ok(ret, "failed to set credentials %u\n", GetLastError());
2327 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2328 ok(ret, "failed to send request %u\n", GetLastError());
2330 ret = WinHttpReceiveResponse(req, NULL);
2331 ok(ret, "failed to receive response %u\n", GetLastError());
2333 status = 0xdeadbeef;
2334 size = sizeof(status);
2335 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2336 ok(ret, "failed to query status code %u\n", GetLastError());
2337 ok(status == 200, "request failed unexpectedly %u\n", status);
2339 WinHttpCloseHandle(req);
2340 WinHttpCloseHandle(con);
2341 WinHttpCloseHandle(ses);
2343 /* credentials set with WinHttpSetCredentials take precedence over those set through options */
2345 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
2346 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2348 con = WinHttpConnect(ses, localhostW, port, 0);
2349 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2351 req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2352 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2354 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
2355 ok(ret, "failed to set credentials %u\n", GetLastError());
2357 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
2358 ok(ret, "failed to set username %u\n", GetLastError());
2360 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, pass2W, lstrlenW(pass2W));
2361 ok(ret, "failed to set password %u\n", GetLastError());
2363 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2364 ok(ret, "failed to send request %u\n", GetLastError());
2366 ret = WinHttpReceiveResponse(req, NULL);
2367 ok(ret, "failed to receive response %u\n", GetLastError());
2369 status = 0xdeadbeef;
2370 size = sizeof(status);
2371 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2372 ok(ret, "failed to query status code %u\n", GetLastError());
2373 ok(status == 200, "request failed unexpectedly %u\n", status);
2375 WinHttpCloseHandle(req);
2376 WinHttpCloseHandle(con);
2377 WinHttpCloseHandle(ses);
2379 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
2380 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2382 con = WinHttpConnect(ses, localhostW, port, 0);
2383 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2385 req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2386 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2388 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
2389 ok(ret, "failed to set username %u\n", GetLastError());
2391 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, pass2W, lstrlenW(passW));
2392 ok(ret, "failed to set password %u\n", GetLastError());
2394 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, pass2W, NULL);
2395 ok(ret, "failed to set credentials %u\n", GetLastError());
2397 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2398 ok(ret, "failed to send request %u\n", GetLastError());
2400 ret = WinHttpReceiveResponse(req, NULL);
2401 ok(ret, "failed to receive response %u\n", GetLastError());
2403 status = 0xdeadbeef;
2404 size = sizeof(status);
2405 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2406 ok(ret, "failed to query status code %u\n", GetLastError());
2407 ok(status == 401, "request failed unexpectedly %u\n", status);
2409 WinHttpCloseHandle(req);
2410 WinHttpCloseHandle(con);
2411 WinHttpCloseHandle(ses);
2414 static void test_no_headers(int port)
2416 static const WCHAR no_headersW[] = {'/','n','o','_','h','e','a','d','e','r','s',0};
2417 HINTERNET ses, con, req;
2418 DWORD error;
2419 BOOL ret;
2421 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
2422 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2424 con = WinHttpConnect(ses, localhostW, port, 0);
2425 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2427 req = WinHttpOpenRequest(con, NULL, no_headersW, NULL, NULL, NULL, 0);
2428 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2430 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2431 if (!ret)
2433 error = GetLastError();
2434 ok(error == ERROR_WINHTTP_INVALID_SERVER_RESPONSE, "got %u\n", error);
2436 else
2438 SetLastError(0xdeadbeef);
2439 ret = WinHttpReceiveResponse(req, NULL);
2440 error = GetLastError();
2441 ok(!ret, "expected failure\n");
2442 ok(error == ERROR_WINHTTP_INVALID_SERVER_RESPONSE, "got %u\n", error);
2445 WinHttpCloseHandle(req);
2446 WinHttpCloseHandle(con);
2447 WinHttpCloseHandle(ses);
2450 static void test_no_content(int port)
2452 static const WCHAR no_contentW[] = {'/','n','o','_','c','o','n','t','e','n','t',0};
2453 HINTERNET ses, con, req;
2454 char buf[128];
2455 DWORD size, len = sizeof(buf), bytes_read, status;
2456 BOOL ret;
2458 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
2459 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2461 con = WinHttpConnect(ses, localhostW, port, 0);
2462 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2464 req = WinHttpOpenRequest(con, NULL, no_contentW, NULL, NULL, NULL, 0);
2465 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2467 size = 12345;
2468 SetLastError(0xdeadbeef);
2469 ret = WinHttpQueryDataAvailable(req, &size);
2470 todo_wine {
2471 ok(!ret, "expected error\n");
2472 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_STATE,
2473 "expected ERROR_WINHTTP_INCORRECT_HANDLE_STATE, got 0x%08x\n", GetLastError());
2474 ok(size == 12345 || broken(size == 0) /* Win <= 2003 */,
2475 "expected 12345, got %u\n", size);
2478 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2479 ok(ret, "expected success\n");
2481 ret = WinHttpReceiveResponse(req, NULL);
2482 ok(ret, "expected success\n");
2484 status = 0xdeadbeef;
2485 size = sizeof(status);
2486 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
2487 NULL, &status, &size, NULL);
2488 ok(ret, "expected success\n");
2489 ok(status == 204, "expected status 204, got %d\n", status);
2491 SetLastError(0xdeadbeef);
2492 size = sizeof(status);
2493 status = 12345;
2494 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
2495 NULL, &status, &size, 0);
2496 ok(!ret, "expected no content-length header\n");
2497 ok(GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND, "wrong error %u\n", GetLastError());
2498 ok(status == 12345, "expected 0, got %d\n", status);
2500 SetLastError(0xdeadbeef);
2501 size = 12345;
2502 ret = WinHttpQueryDataAvailable(req, &size);
2503 ok(ret, "expected success\n");
2504 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
2505 "wrong error %u\n", GetLastError());
2506 ok(!size, "expected 0, got %u\n", size);
2508 SetLastError(0xdeadbeef);
2509 ret = WinHttpReadData(req, buf, len, &bytes_read);
2510 ok(ret, "expected success\n");
2511 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
2512 "wrong error %u\n", GetLastError());
2513 ok(!bytes_read, "expected 0, got %u\n", bytes_read);
2515 size = 12345;
2516 ret = WinHttpQueryDataAvailable(req, &size);
2517 ok(ret, "expected success\n");
2518 ok(size == 0, "expected 0, got %d\n", size);
2520 WinHttpCloseHandle(req);
2522 size = 12345;
2523 SetLastError(0xdeadbeef);
2524 ret = WinHttpQueryDataAvailable(req, &size);
2525 ok(!ret, "expected error\n");
2526 ok(GetLastError() == ERROR_INVALID_HANDLE,
2527 "expected ERROR_INVALID_HANDLE, got 0x%08x\n", GetLastError());
2528 ok(size == 12345, "expected 12345, got %u\n", size);
2530 WinHttpCloseHandle(con);
2531 WinHttpCloseHandle(ses);
2534 static void test_head_request(int port)
2536 static const WCHAR verbW[] = {'H','E','A','D',0};
2537 static const WCHAR headW[] = {'/','h','e','a','d',0};
2538 HINTERNET ses, con, req;
2539 char buf[128];
2540 DWORD size, len, count, status;
2541 BOOL ret;
2543 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
2544 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2546 con = WinHttpConnect(ses, localhostW, port, 0);
2547 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2549 req = WinHttpOpenRequest(con, verbW, headW, NULL, NULL, NULL, 0);
2550 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2552 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2553 ok(ret, "failed to send request %u\n", GetLastError());
2555 ret = WinHttpReceiveResponse(req, NULL);
2556 ok(ret, "failed to receive response %u\n", GetLastError());
2558 status = 0xdeadbeef;
2559 size = sizeof(status);
2560 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
2561 NULL, &status, &size, NULL);
2562 ok(ret, "failed to get status code %u\n", GetLastError());
2563 ok(status == 200, "got %u\n", status);
2565 len = 0xdeadbeef;
2566 size = sizeof(len);
2567 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
2568 NULL, &len, &size, 0);
2569 ok(ret, "failed to get content-length header %u\n", GetLastError());
2570 ok(len == 100, "got %u\n", len);
2572 count = 0xdeadbeef;
2573 ret = WinHttpQueryDataAvailable(req, &count);
2574 ok(ret, "failed to query data available %u\n", GetLastError());
2575 ok(!count, "got %u\n", count);
2577 len = sizeof(buf);
2578 count = 0xdeadbeef;
2579 ret = WinHttpReadData(req, buf, len, &count);
2580 ok(ret, "failed to read data %u\n", GetLastError());
2581 ok(!count, "got %u\n", count);
2583 count = 0xdeadbeef;
2584 ret = WinHttpQueryDataAvailable(req, &count);
2585 ok(ret, "failed to query data available %u\n", GetLastError());
2586 ok(!count, "got %u\n", count);
2588 WinHttpCloseHandle(req);
2589 WinHttpCloseHandle(con);
2590 WinHttpCloseHandle(ses);
2593 static void test_not_modified(int port)
2595 static const WCHAR pathW[] = {'/','n','o','t','_','m','o','d','i','f','i','e','d',0};
2596 static const WCHAR ifmodifiedW[] = {'I','f','-','M','o','d','i','f','i','e','d','-','S','i','n','c','e',':',' '};
2597 static const WCHAR ifmodified2W[] = {'I','f','-','M','o','d','i','f','i','e','d','-','S','i','n','c','e',0};
2598 BOOL ret;
2599 HINTERNET session, request, connection;
2600 DWORD index, len, status, size, start = GetTickCount();
2601 SYSTEMTIME st;
2602 WCHAR today[(sizeof(ifmodifiedW) + WINHTTP_TIME_FORMAT_BUFSIZE)/sizeof(WCHAR) + 3], buffer[32];
2604 memcpy(today, ifmodifiedW, sizeof(ifmodifiedW));
2605 GetSystemTime(&st);
2606 WinHttpTimeFromSystemTime(&st, &today[sizeof(ifmodifiedW)/sizeof(WCHAR)]);
2608 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
2609 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
2610 ok(session != NULL, "WinHttpOpen failed: %u\n", GetLastError());
2612 connection = WinHttpConnect(session, localhostW, port, 0);
2613 ok(connection != NULL, "WinHttpConnect failed: %u\n", GetLastError());
2615 request = WinHttpOpenRequest(connection, NULL, pathW, NULL, WINHTTP_NO_REFERER,
2616 WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
2617 ok(request != NULL, "WinHttpOpenrequest failed: %u\n", GetLastError());
2619 ret = WinHttpSendRequest(request, today, 0, NULL, 0, 0, 0);
2620 ok(ret, "WinHttpSendRequest failed: %u\n", GetLastError());
2622 ret = WinHttpReceiveResponse(request, NULL);
2623 ok(ret, "WinHttpReceiveResponse failed: %u\n", GetLastError());
2625 index = 0;
2626 len = sizeof(buffer);
2627 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
2628 ifmodified2W, buffer, &len, &index);
2629 ok(ret, "failed to get header %u\n", GetLastError());
2631 status = 0xdeadbeef;
2632 size = sizeof(status);
2633 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER,
2634 NULL, &status, &size, NULL);
2635 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
2636 ok(status == HTTP_STATUS_NOT_MODIFIED, "got %u\n", status);
2638 size = 0xdeadbeef;
2639 ret = WinHttpQueryDataAvailable(request, &size);
2640 ok(ret, "WinHttpQueryDataAvailable failed: %u\n", GetLastError());
2641 ok(!size, "got %u\n", size);
2643 WinHttpCloseHandle(request);
2644 WinHttpCloseHandle(connection);
2645 WinHttpCloseHandle(session);
2646 start = GetTickCount() - start;
2647 ok(start <= 2000, "Expected less than 2 seconds for the test, got %u ms\n", start);
2650 static void test_bad_header( int port )
2652 static const WCHAR bad_headerW[] =
2653 {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ',
2654 't','e','x','t','/','h','t','m','l','\n','\r',0};
2655 static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
2656 static const WCHAR content_typeW[] = {'C','o','n','t','e','n','t','-','T','y','p','e',0};
2657 WCHAR buffer[32];
2658 HINTERNET ses, con, req;
2659 DWORD index, len;
2660 BOOL ret;
2662 ses = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
2663 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
2665 con = WinHttpConnect( ses, localhostW, port, 0 );
2666 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2668 req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
2669 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2671 ret = WinHttpAddRequestHeaders( req, bad_headerW, ~0u, WINHTTP_ADDREQ_FLAG_ADD );
2672 ok( ret, "failed to add header %u\n", GetLastError() );
2674 index = 0;
2675 buffer[0] = 0;
2676 len = sizeof(buffer);
2677 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_CUSTOM|WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
2678 content_typeW, buffer, &len, &index );
2679 ok( ret, "failed to query headers %u\n", GetLastError() );
2680 ok( !lstrcmpW( buffer, text_htmlW ), "got %s\n", wine_dbgstr_w(buffer) );
2682 WinHttpCloseHandle( req );
2683 WinHttpCloseHandle( con );
2684 WinHttpCloseHandle( ses );
2687 static void test_multiple_reads(int port)
2689 static const WCHAR bigW[] = {'b','i','g',0};
2690 HINTERNET ses, con, req;
2691 DWORD total_len = 0;
2692 BOOL ret;
2694 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
2695 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2697 con = WinHttpConnect(ses, localhostW, port, 0);
2698 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2700 req = WinHttpOpenRequest(con, NULL, bigW, NULL, NULL, NULL, 0);
2701 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2703 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2704 ok(ret, "failed to send request %u\n", GetLastError());
2706 ret = WinHttpReceiveResponse(req, NULL);
2707 ok(ret == TRUE, "expected success\n");
2709 for (;;)
2711 DWORD len = 0xdeadbeef;
2712 ret = WinHttpQueryDataAvailable( req, &len );
2713 ok( ret, "WinHttpQueryDataAvailable failed with error %u\n", GetLastError() );
2714 if (ret) ok( len != 0xdeadbeef, "WinHttpQueryDataAvailable return wrong length\n" );
2715 if (len)
2717 DWORD bytes_read;
2718 char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 );
2720 ret = WinHttpReadData( req, buf, len, &bytes_read );
2721 ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len );
2723 HeapFree( GetProcessHeap(), 0, buf );
2724 if (!bytes_read) break;
2725 total_len += bytes_read;
2727 if (!len) break;
2729 ok(total_len == BIG_BUFFER_LEN, "got wrong length: 0x%x\n", total_len);
2731 WinHttpCloseHandle(req);
2732 WinHttpCloseHandle(con);
2733 WinHttpCloseHandle(ses);
2736 static void test_cookies( int port )
2738 static const WCHAR cookieW[] = {'/','c','o','o','k','i','e',0};
2739 static const WCHAR cookie2W[] = {'/','c','o','o','k','i','e','2',0};
2740 static const WCHAR cookie3W[] = {'/','c','o','o','k','i','e','3',0};
2741 static const WCHAR cookieheaderW[] =
2742 {'C','o','o','k','i','e',':',' ','n','a','m','e','=','v','a','l','u','e','2','\r','\n',0};
2743 HINTERNET ses, con, req;
2744 DWORD status, size;
2745 BOOL ret;
2747 ses = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
2748 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
2750 con = WinHttpConnect( ses, localhostW, port, 0 );
2751 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2753 req = WinHttpOpenRequest( con, NULL, cookieW, NULL, NULL, NULL, 0 );
2754 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2756 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2757 ok( ret, "failed to send request %u\n", GetLastError() );
2759 ret = WinHttpReceiveResponse( req, NULL );
2760 ok( ret, "failed to receive response %u\n", GetLastError() );
2762 status = 0xdeadbeef;
2763 size = sizeof(status);
2764 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
2765 ok( ret, "failed to query status code %u\n", GetLastError() );
2766 ok( status == 200, "request failed unexpectedly %u\n", status );
2768 WinHttpCloseHandle( req );
2770 req = WinHttpOpenRequest( con, NULL, cookie2W, NULL, NULL, NULL, 0 );
2771 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2773 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2774 ok( ret, "failed to send request %u\n", GetLastError() );
2776 ret = WinHttpReceiveResponse( req, NULL );
2777 ok( ret, "failed to receive response %u\n", GetLastError() );
2779 status = 0xdeadbeef;
2780 size = sizeof(status);
2781 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
2782 ok( ret, "failed to query status code %u\n", GetLastError() );
2783 ok( status == 200, "request failed unexpectedly %u\n", status );
2785 WinHttpCloseHandle( req );
2786 WinHttpCloseHandle( con );
2788 con = WinHttpConnect( ses, localhostW, port, 0 );
2789 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2791 req = WinHttpOpenRequest( con, NULL, cookie2W, NULL, NULL, NULL, 0 );
2792 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2794 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2795 ok( ret, "failed to send request %u\n", GetLastError() );
2797 ret = WinHttpReceiveResponse( req, NULL );
2798 ok( ret, "failed to receive response %u\n", GetLastError() );
2800 status = 0xdeadbeef;
2801 size = sizeof(status);
2802 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
2803 ok( ret, "failed to query status code %u\n", GetLastError() );
2804 ok( status == 200, "request failed unexpectedly %u\n", status );
2806 WinHttpCloseHandle( req );
2808 req = WinHttpOpenRequest( con, NULL, cookie3W, NULL, NULL, NULL, 0 );
2809 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2811 ret = WinHttpSendRequest( req, cookieheaderW, ~0u, NULL, 0, 0, 0 );
2812 ok( ret, "failed to send request %u\n", GetLastError() );
2814 ret = WinHttpReceiveResponse( req, NULL );
2815 ok( ret, "failed to receive response %u\n", GetLastError() );
2817 status = 0xdeadbeef;
2818 size = sizeof(status);
2819 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
2820 ok( ret, "failed to query status code %u\n", GetLastError() );
2821 ok( status == 200 || broken(status == 400), "request failed unexpectedly %u\n", status );
2823 WinHttpCloseHandle( req );
2824 WinHttpCloseHandle( con );
2825 WinHttpCloseHandle( ses );
2827 ses = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
2828 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
2830 con = WinHttpConnect( ses, localhostW, port, 0 );
2831 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2833 req = WinHttpOpenRequest( con, NULL, cookie2W, NULL, NULL, NULL, 0 );
2834 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2836 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2837 ok( ret, "failed to send request %u\n", GetLastError() );
2839 ret = WinHttpReceiveResponse( req, NULL );
2840 ok( ret, "failed to receive response %u\n", GetLastError() );
2842 status = 0xdeadbeef;
2843 size = sizeof(status);
2844 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
2845 ok( ret, "failed to query status code %u\n", GetLastError() );
2846 ok( status == 400, "request failed unexpectedly %u\n", status );
2848 WinHttpCloseHandle( req );
2849 WinHttpCloseHandle( con );
2850 WinHttpCloseHandle( ses );
2853 static void test_connection_info( int port )
2855 static const WCHAR basicW[] = {'/','b','a','s','i','c',0};
2856 HINTERNET ses, con, req;
2857 WINHTTP_CONNECTION_INFO info;
2858 DWORD size, error;
2859 BOOL ret;
2861 ses = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
2862 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
2864 con = WinHttpConnect( ses, localhostW, port, 0 );
2865 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2867 req = WinHttpOpenRequest( con, NULL, basicW, NULL, NULL, NULL, 0 );
2868 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2870 size = sizeof(info);
2871 SetLastError( 0xdeadbeef );
2872 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
2873 error = GetLastError();
2874 if (!ret && error == ERROR_INVALID_PARAMETER)
2876 win_skip( "WINHTTP_OPTION_CONNECTION_INFO not supported\n" );
2877 return;
2879 ok( !ret, "unexpected success\n" );
2880 ok( error == ERROR_WINHTTP_INCORRECT_HANDLE_STATE, "got %u\n", error );
2882 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2883 ok( ret, "failed to send request %u\n", GetLastError() );
2885 size = 0;
2886 SetLastError( 0xdeadbeef );
2887 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
2888 error = GetLastError();
2889 ok( !ret, "unexpected success\n" );
2890 ok( error == ERROR_INSUFFICIENT_BUFFER, "got %u\n", error );
2892 size = sizeof(info);
2893 memset( &info, 0, sizeof(info) );
2894 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
2895 ok( ret, "failed to retrieve connection info %u\n", GetLastError() );
2896 ok( info.cbSize == sizeof(info), "wrong size %u\n", info.cbSize );
2898 ret = WinHttpReceiveResponse( req, NULL );
2899 ok( ret, "failed to receive response %u\n", GetLastError() );
2901 size = sizeof(info);
2902 memset( &info, 0, sizeof(info) );
2903 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
2904 ok( ret, "failed to retrieve connection info %u\n", GetLastError() );
2905 ok( info.cbSize == sizeof(info), "wrong size %u\n", info.cbSize );
2907 WinHttpCloseHandle( req );
2908 WinHttpCloseHandle( con );
2909 WinHttpCloseHandle( ses );
2912 static void test_credentials(void)
2914 static WCHAR userW[] = {'u','s','e','r',0};
2915 static WCHAR passW[] = {'p','a','s','s',0};
2916 static WCHAR proxy_userW[] = {'p','r','o','x','y','u','s','e','r',0};
2917 static WCHAR proxy_passW[] = {'p','r','o','x','y','p','a','s','s',0};
2918 HINTERNET ses, con, req;
2919 DWORD size, error;
2920 WCHAR buffer[32];
2921 BOOL ret;
2923 ses = WinHttpOpen(test_useragent, 0, proxy_userW, proxy_passW, 0);
2924 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2926 con = WinHttpConnect(ses, localhostW, 0, 0);
2927 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2929 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
2930 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2932 size = sizeof(buffer)/sizeof(WCHAR);
2933 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size);
2934 ok(ret, "failed to query proxy username %u\n", GetLastError());
2935 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
2936 ok(!size, "expected 0, got %u\n", size);
2938 size = sizeof(buffer)/sizeof(WCHAR);
2939 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size);
2940 ok(ret, "failed to query proxy password %u\n", GetLastError());
2941 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
2942 ok(!size, "expected 0, got %u\n", size);
2944 ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_USERNAME, proxy_userW, lstrlenW(proxy_userW));
2945 ok(ret, "failed to set username %u\n", GetLastError());
2947 size = sizeof(buffer)/sizeof(WCHAR);
2948 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size);
2949 ok(ret, "failed to query proxy username %u\n", GetLastError());
2950 ok(!winetest_strcmpW(buffer, proxy_userW), "unexpected result %s\n", wine_dbgstr_w(buffer));
2951 ok(size == lstrlenW(proxy_userW) * sizeof(WCHAR), "unexpected result %u\n", size);
2953 size = sizeof(buffer)/sizeof(WCHAR);
2954 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
2955 ok(ret, "failed to query username %u\n", GetLastError());
2956 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
2957 ok(!size, "expected 0, got %u\n", size);
2959 size = sizeof(buffer)/sizeof(WCHAR);
2960 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
2961 ok(ret, "failed to query password %u\n", GetLastError());
2962 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
2963 ok(!size, "expected 0, got %u\n", size);
2965 ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_PASSWORD, proxy_passW, lstrlenW(proxy_passW));
2966 ok(ret, "failed to set proxy password %u\n", GetLastError());
2968 size = sizeof(buffer)/sizeof(WCHAR);
2969 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size);
2970 ok(ret, "failed to query proxy password %u\n", GetLastError());
2971 ok(!winetest_strcmpW(buffer, proxy_passW), "unexpected result %s\n", wine_dbgstr_w(buffer));
2972 ok(size == lstrlenW(proxy_passW) * sizeof(WCHAR), "unexpected result %u\n", size);
2974 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
2975 ok(ret, "failed to set username %u\n", GetLastError());
2977 size = sizeof(buffer)/sizeof(WCHAR);
2978 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
2979 ok(ret, "failed to query username %u\n", GetLastError());
2980 ok(!winetest_strcmpW(buffer, userW), "unexpected result %s\n", wine_dbgstr_w(buffer));
2981 ok(size == lstrlenW(userW) * sizeof(WCHAR), "unexpected result %u\n", size);
2983 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, passW, lstrlenW(passW));
2984 ok(ret, "failed to set password %u\n", GetLastError());
2986 size = sizeof(buffer)/sizeof(WCHAR);
2987 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
2988 ok(ret, "failed to query password %u\n", GetLastError());
2989 ok(!winetest_strcmpW(buffer, passW), "unexpected result %s\n", wine_dbgstr_w(buffer));
2990 ok(size == lstrlenW(passW) * sizeof(WCHAR), "unexpected result %u\n", size);
2992 WinHttpCloseHandle(req);
2994 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
2995 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2997 SetLastError(0xdeadbeef);
2998 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, NULL, NULL);
2999 error = GetLastError();
3000 ok(!ret, "expected failure\n");
3001 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
3003 SetLastError(0xdeadbeef);
3004 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, passW, NULL);
3005 error = GetLastError();
3006 ok(!ret, "expected failure\n");
3007 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
3009 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
3010 ok(ret, "failed to set credentials %u\n", GetLastError());
3012 size = sizeof(buffer)/sizeof(WCHAR);
3013 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
3014 ok(ret, "failed to query username %u\n", GetLastError());
3015 todo_wine {
3016 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3017 ok(!size, "expected 0, got %u\n", size);
3020 size = sizeof(buffer)/sizeof(WCHAR);
3021 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3022 ok(ret, "failed to query password %u\n", GetLastError());
3023 todo_wine {
3024 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3025 ok(!size, "expected 0, got %u\n", size);
3028 WinHttpCloseHandle(req);
3029 WinHttpCloseHandle(con);
3030 WinHttpCloseHandle(ses);
3033 static void test_IWinHttpRequest(void)
3035 static const WCHAR usernameW[] = {'u','s','e','r','n','a','m','e',0};
3036 static const WCHAR passwordW[] = {'p','a','s','s','w','o','r','d',0};
3037 static const WCHAR url1W[] = {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
3038 static const WCHAR url2W[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
3039 static const WCHAR url3W[] = {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.',
3040 'o','r','g','/','t','e','s','t','s','/','p','o','s','t','.','p','h','p',0};
3041 static const WCHAR method1W[] = {'G','E','T',0};
3042 static const WCHAR method2W[] = {'I','N','V','A','L','I','D',0};
3043 static const WCHAR method3W[] = {'P','O','S','T',0};
3044 static const WCHAR proxy_serverW[] = {'p','r','o','x','y','s','e','r','v','e','r',0};
3045 static const WCHAR bypas_listW[] = {'b','y','p','a','s','s','l','i','s','t',0};
3046 static const WCHAR connectionW[] = {'C','o','n','n','e','c','t','i','o','n',0};
3047 static const WCHAR dateW[] = {'D','a','t','e',0};
3048 static const WCHAR test_dataW[] = {'t','e','s','t','d','a','t','a',128,0};
3049 static const WCHAR utf8W[] = {'u','t','f','-','8',0};
3050 HRESULT hr;
3051 IWinHttpRequest *req;
3052 BSTR method, url, username, password, response = NULL, status_text = NULL, headers = NULL;
3053 BSTR date, today, connection, value = NULL;
3054 VARIANT async, empty, timeout, body, body2, proxy_server, bypass_list, data, cp;
3055 VARIANT_BOOL succeeded;
3056 LONG status;
3057 WCHAR todayW[WINHTTP_TIME_FORMAT_BUFSIZE];
3058 SYSTEMTIME st;
3059 IStream *stream, *stream2;
3060 LARGE_INTEGER pos;
3061 char buf[128];
3062 DWORD count;
3064 GetSystemTime( &st );
3065 WinHttpTimeFromSystemTime( &st, todayW );
3067 CoInitialize( NULL );
3068 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3069 ok( hr == S_OK, "got %08x\n", hr );
3071 V_VT( &empty ) = VT_ERROR;
3072 V_ERROR( &empty ) = 0xdeadbeef;
3074 V_VT( &async ) = VT_BOOL;
3075 V_BOOL( &async ) = VARIANT_FALSE;
3077 method = SysAllocString( method3W );
3078 url = SysAllocString( url3W );
3079 hr = IWinHttpRequest_Open( req, method, url, async );
3080 ok( hr == S_OK, "got %08x\n", hr );
3081 SysFreeString( method );
3082 SysFreeString( url );
3084 V_VT( &data ) = VT_BSTR;
3085 V_BSTR( &data ) = SysAllocString( test_dataW );
3086 hr = IWinHttpRequest_Send( req, data );
3087 ok( hr == S_OK || broken(hr == HRESULT_FROM_WIN32(ERROR_WINHTTP_INVALID_SERVER_RESPONSE)),
3088 "got %08x\n", hr );
3089 SysFreeString( V_BSTR( &data ) );
3091 hr = IWinHttpRequest_Open( req, NULL, NULL, empty );
3092 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3094 method = SysAllocString( method1W );
3095 hr = IWinHttpRequest_Open( req, method, NULL, empty );
3096 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3098 hr = IWinHttpRequest_Open( req, method, NULL, async );
3099 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3101 url = SysAllocString( url1W );
3102 hr = IWinHttpRequest_Open( req, NULL, url, empty );
3103 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3105 hr = IWinHttpRequest_Abort( req );
3106 ok( hr == S_OK, "got %08x\n", hr );
3108 hr = IWinHttpRequest_Open( req, method, url, empty );
3109 ok( hr == S_OK, "got %08x\n", hr );
3111 hr = IWinHttpRequest_Abort( req );
3112 ok( hr == S_OK, "got %08x\n", hr );
3114 IWinHttpRequest_Release( req );
3116 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3117 ok( hr == S_OK, "got %08x\n", hr );
3119 SysFreeString( url );
3120 url = SysAllocString( url2W );
3121 hr = IWinHttpRequest_Open( req, method, url, async );
3122 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ), "got %08x\n", hr );
3124 SysFreeString( method );
3125 method = SysAllocString( method2W );
3126 hr = IWinHttpRequest_Open( req, method, url, async );
3127 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ), "got %08x\n", hr );
3129 SysFreeString( method );
3130 method = SysAllocString( method1W );
3131 SysFreeString( url );
3132 url = SysAllocString( url1W );
3133 V_VT( &async ) = VT_ERROR;
3134 V_ERROR( &async ) = DISP_E_PARAMNOTFOUND;
3135 hr = IWinHttpRequest_Open( req, method, url, async );
3136 ok( hr == S_OK, "got %08x\n", hr );
3138 V_VT( &cp ) = VT_ERROR;
3139 V_ERROR( &cp ) = 0xdeadbeef;
3140 hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3141 ok( hr == S_OK, "got %08x\n", hr );
3142 ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3143 ok( V_I4( &cp ) == CP_UTF8, "got %u\n", V_I4( &cp ) );
3145 V_VT( &cp ) = VT_UI4;
3146 V_UI4( &cp ) = CP_ACP;
3147 hr = IWinHttpRequest_put_Option( req, WinHttpRequestOption_URLCodePage, cp );
3148 ok( hr == S_OK, "got %08x\n", hr );
3150 V_VT( &cp ) = VT_ERROR;
3151 V_ERROR( &cp ) = 0xdeadbeef;
3152 hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3153 ok( hr == S_OK, "got %08x\n", hr );
3154 ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3155 ok( V_I4( &cp ) == CP_ACP, "got %u\n", V_I4( &cp ) );
3157 value = SysAllocString( utf8W );
3158 V_VT( &cp ) = VT_BSTR;
3159 V_BSTR( &cp ) = value;
3160 hr = IWinHttpRequest_put_Option( req, WinHttpRequestOption_URLCodePage, cp );
3161 ok( hr == S_OK, "got %08x\n", hr );
3162 SysFreeString( value );
3164 V_VT( &cp ) = VT_ERROR;
3165 V_ERROR( &cp ) = 0xdeadbeef;
3166 hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3167 ok( hr == S_OK, "got %08x\n", hr );
3168 ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3169 ok( V_I4( &cp ) == CP_UTF8, "got %u\n", V_I4( &cp ) );
3171 hr = IWinHttpRequest_Abort( req );
3172 ok( hr == S_OK, "got %08x\n", hr );
3174 hr = IWinHttpRequest_Send( req, empty );
3175 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3177 hr = IWinHttpRequest_Abort( req );
3178 ok( hr == S_OK, "got %08x\n", hr );
3180 IWinHttpRequest_Release( req );
3182 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3183 ok( hr == S_OK, "got %08x\n", hr );
3185 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3186 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3188 hr = IWinHttpRequest_get_ResponseText( req, &response );
3189 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3191 hr = IWinHttpRequest_get_Status( req, NULL );
3192 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3194 hr = IWinHttpRequest_get_Status( req, &status );
3195 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3197 hr = IWinHttpRequest_get_StatusText( req, NULL );
3198 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3200 hr = IWinHttpRequest_get_StatusText( req, &status_text );
3201 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3203 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3204 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3206 hr = IWinHttpRequest_SetTimeouts( req, 10000, 10000, 10000, 10000 );
3207 ok( hr == S_OK, "got %08x\n", hr );
3209 hr = IWinHttpRequest_SetCredentials( req, NULL, NULL, 0xdeadbeef );
3210 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3212 VariantInit( &proxy_server );
3213 V_VT( &proxy_server ) = VT_ERROR;
3214 VariantInit( &bypass_list );
3215 V_VT( &bypass_list ) = VT_ERROR;
3216 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3217 ok( hr == S_OK, "got %08x\n", hr );
3219 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3220 ok( hr == S_OK, "got %08x\n", hr );
3222 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3223 ok( hr == S_OK, "got %08x\n", hr );
3225 hr = IWinHttpRequest_GetAllResponseHeaders( req, NULL );
3226 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3228 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3229 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3231 hr = IWinHttpRequest_GetResponseHeader( req, NULL, NULL );
3232 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3234 connection = SysAllocString( connectionW );
3235 hr = IWinHttpRequest_GetResponseHeader( req, connection, NULL );
3236 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3238 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3239 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3241 hr = IWinHttpRequest_SetRequestHeader( req, NULL, NULL );
3242 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3244 date = SysAllocString( dateW );
3245 hr = IWinHttpRequest_SetRequestHeader( req, date, NULL );
3246 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3248 today = SysAllocString( todayW );
3249 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3250 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3252 hr = IWinHttpRequest_SetAutoLogonPolicy( req, 0xdeadbeef );
3253 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3255 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3256 ok( hr == S_OK, "got %08x\n", hr );
3258 SysFreeString( method );
3259 method = SysAllocString( method1W );
3260 SysFreeString( url );
3261 url = SysAllocString( url1W );
3262 hr = IWinHttpRequest_Open( req, method, url, async );
3263 ok( hr == S_OK, "got %08x\n", hr );
3265 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3266 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3268 hr = IWinHttpRequest_get_ResponseText( req, &response );
3269 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3271 hr = IWinHttpRequest_get_Status( req, &status );
3272 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3274 hr = IWinHttpRequest_get_StatusText( req, &status_text );
3275 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3277 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3278 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3280 hr = IWinHttpRequest_SetTimeouts( req, 10000, 10000, 10000, 10000 );
3281 ok( hr == S_OK, "got %08x\n", hr );
3283 hr = IWinHttpRequest_SetCredentials( req, NULL, NULL, 0xdeadbeef );
3284 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3286 username = SysAllocString( usernameW );
3287 hr = IWinHttpRequest_SetCredentials( req, username, NULL, 0xdeadbeef );
3288 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3290 password = SysAllocString( passwordW );
3291 hr = IWinHttpRequest_SetCredentials( req, NULL, password, 0xdeadbeef );
3292 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3294 hr = IWinHttpRequest_SetCredentials( req, username, password, 0xdeadbeef );
3295 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3297 hr = IWinHttpRequest_SetCredentials( req, NULL, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3298 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3300 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3301 ok( hr == S_OK, "got %08x\n", hr );
3303 V_VT( &proxy_server ) = VT_BSTR;
3304 V_BSTR( &proxy_server ) = SysAllocString( proxy_serverW );
3305 V_VT( &bypass_list ) = VT_BSTR;
3306 V_BSTR( &bypass_list ) = SysAllocString( bypas_listW );
3307 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3308 ok( hr == S_OK, "got %08x\n", hr );
3310 hr = IWinHttpRequest_SetProxy( req, 0xdeadbeef, proxy_server, bypass_list );
3311 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3313 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3314 ok( hr == S_OK, "got %08x\n", hr );
3316 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3317 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3319 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3320 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3322 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3323 ok( hr == S_OK, "got %08x\n", hr );
3325 hr = IWinHttpRequest_SetRequestHeader( req, date, NULL );
3326 ok( hr == S_OK, "got %08x\n", hr );
3328 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3329 ok( hr == S_OK, "got %08x\n", hr );
3331 hr = IWinHttpRequest_Send( req, empty );
3332 ok( hr == S_OK, "got %08x\n", hr );
3334 hr = IWinHttpRequest_Send( req, empty );
3335 ok( hr == S_OK, "got %08x\n", hr );
3337 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3338 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3340 hr = IWinHttpRequest_get_ResponseText( req, &response );
3341 ok( hr == S_OK, "got %08x\n", hr );
3342 SysFreeString( response );
3344 hr = IWinHttpRequest_get_Status( req, NULL );
3345 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3347 status = 0;
3348 hr = IWinHttpRequest_get_Status( req, &status );
3349 ok( hr == S_OK, "got %08x\n", hr );
3350 trace("Status=%d\n", status);
3352 hr = IWinHttpRequest_get_StatusText( req, NULL );
3353 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3355 hr = IWinHttpRequest_get_StatusText( req, &status_text );
3356 ok( hr == S_OK, "got %08x\n", hr );
3357 trace("StatusText=%s\n", wine_dbgstr_w(status_text));
3358 SysFreeString( status_text );
3360 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3361 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3363 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3364 ok( hr == S_OK, "got %08x\n", hr );
3366 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3367 ok( hr == S_OK, "got %08x\n", hr );
3369 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3370 ok( hr == S_OK, "got %08x\n", hr );
3372 hr = IWinHttpRequest_GetAllResponseHeaders( req, NULL );
3373 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3375 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3376 ok( hr == S_OK, "got %08x\n", hr );
3377 SysFreeString( headers );
3379 hr = IWinHttpRequest_GetResponseHeader( req, NULL, NULL );
3380 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3382 hr = IWinHttpRequest_GetResponseHeader( req, connection, NULL );
3383 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3385 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3386 ok( hr == S_OK, "got %08x\n", hr );
3387 SysFreeString( value );
3389 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3390 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND ), "got %08x\n", hr );
3392 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3393 ok( hr == S_OK, "got %08x\n", hr );
3395 VariantInit( &timeout );
3396 V_VT( &timeout ) = VT_I4;
3397 V_I4( &timeout ) = 10;
3398 hr = IWinHttpRequest_WaitForResponse( req, timeout, &succeeded );
3399 ok( hr == S_OK, "got %08x\n", hr );
3401 hr = IWinHttpRequest_get_Status( req, &status );
3402 ok( hr == S_OK, "got %08x\n", hr );
3404 hr = IWinHttpRequest_get_StatusText( req, &status_text );
3405 ok( hr == S_OK, "got %08x\n", hr );
3406 SysFreeString( status_text );
3408 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3409 ok( hr == S_OK, "got %08x\n", hr );
3411 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3412 ok( hr == S_OK, "got %08x\n", hr );
3414 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3415 ok( hr == S_OK, "got %08x\n", hr );
3417 hr = IWinHttpRequest_Send( req, empty );
3418 ok( hr == S_OK, "got %08x\n", hr );
3420 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3421 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3423 hr = IWinHttpRequest_get_ResponseText( req, &response );
3424 ok( hr == S_OK, "got %08x\n", hr );
3425 SysFreeString( response );
3427 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3428 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3430 VariantInit( &body );
3431 V_VT( &body ) = VT_ERROR;
3432 hr = IWinHttpRequest_get_ResponseBody( req, &body );
3433 ok( hr == S_OK, "got %08x\n", hr );
3434 ok( V_VT( &body ) == (VT_ARRAY|VT_UI1), "got %08x\n", V_VT( &body ) );
3436 hr = VariantClear( &body );
3437 ok( hr == S_OK, "got %08x\n", hr );
3439 VariantInit( &body );
3440 V_VT( &body ) = VT_ERROR;
3441 hr = IWinHttpRequest_get_ResponseStream( req, &body );
3442 ok( hr == S_OK, "got %08x\n", hr );
3443 ok( V_VT( &body ) == VT_UNKNOWN, "got %08x\n", V_VT( &body ) );
3445 hr = IUnknown_QueryInterface( V_UNKNOWN( &body ), &IID_IStream, (void **)&stream );
3446 ok( hr == S_OK, "got %08x\n", hr );
3447 ok( V_UNKNOWN( &body ) == (IUnknown *)stream, "got different interface pointer\n" );
3449 buf[0] = 0;
3450 count = 0xdeadbeef;
3451 hr = IStream_Read( stream, buf, 128, &count );
3452 ok( hr == S_OK, "got %08x\n", hr );
3453 ok( count != 0xdeadbeef, "count not set\n" );
3454 ok( buf[0], "no data\n" );
3456 VariantInit( &body2 );
3457 V_VT( &body2 ) = VT_ERROR;
3458 hr = IWinHttpRequest_get_ResponseStream( req, &body2 );
3459 ok( hr == S_OK, "got %08x\n", hr );
3460 ok( V_VT( &body2 ) == VT_UNKNOWN, "got %08x\n", V_VT( &body2 ) );
3461 ok( V_UNKNOWN( &body ) != V_UNKNOWN( &body2 ), "got same interface pointer\n" );
3463 hr = IUnknown_QueryInterface( V_UNKNOWN( &body2 ), &IID_IStream, (void **)&stream2 );
3464 ok( hr == S_OK, "got %08x\n", hr );
3465 ok( V_UNKNOWN( &body2 ) == (IUnknown *)stream2, "got different interface pointer\n" );
3466 IStream_Release( stream2 );
3468 hr = VariantClear( &body );
3469 ok( hr == S_OK, "got %08x\n", hr );
3471 hr = VariantClear( &body2 );
3472 ok( hr == S_OK, "got %08x\n", hr );
3474 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3475 ok( hr == S_OK, "got %08x\n", hr );
3477 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3478 ok( hr == S_OK, "got %08x\n", hr );
3480 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3481 ok( hr == S_OK, "got %08x\n", hr );
3482 SysFreeString( headers );
3484 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3485 ok( hr == S_OK, "got %08x\n", hr );
3486 SysFreeString( value );
3488 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3489 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND ), "got %08x\n", hr );
3491 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3492 ok( hr == S_OK, "got %08x\n", hr );
3494 hr = IWinHttpRequest_Send( req, empty );
3495 ok( hr == S_OK, "got %08x\n", hr );
3497 hr = IWinHttpRequest_Abort( req );
3498 ok( hr == S_OK, "got %08x\n", hr );
3500 hr = IWinHttpRequest_Abort( req );
3501 ok( hr == S_OK, "got %08x\n", hr );
3503 IWinHttpRequest_Release( req );
3505 pos.QuadPart = 0;
3506 hr = IStream_Seek( stream, pos, STREAM_SEEK_SET, NULL );
3507 ok( hr == S_OK, "got %08x\n", hr );
3509 buf[0] = 0;
3510 count = 0xdeadbeef;
3511 hr = IStream_Read( stream, buf, 128, &count );
3512 ok( hr == S_OK, "got %08x\n", hr );
3513 ok( count != 0xdeadbeef, "count not set\n" );
3514 ok( buf[0], "no data\n" );
3515 IStream_Release( stream );
3517 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3518 ok( hr == S_OK, "got %08x\n", hr );
3520 V_VT( &async ) = VT_I4;
3521 V_I4( &async ) = 1;
3522 hr = IWinHttpRequest_Open( req, method, url, async );
3523 ok( hr == S_OK, "got %08x\n", hr );
3525 hr = IWinHttpRequest_Send( req, empty );
3526 ok( hr == S_OK, "got %08x\n", hr );
3528 hr = IWinHttpRequest_WaitForResponse( req, timeout, &succeeded );
3529 ok( hr == S_OK, "got %08x\n", hr );
3531 IWinHttpRequest_Release( req );
3533 SysFreeString( method );
3534 SysFreeString( url );
3535 SysFreeString( username );
3536 SysFreeString( password );
3537 SysFreeString( connection );
3538 SysFreeString( date );
3539 SysFreeString( today );
3540 VariantClear( &proxy_server );
3541 VariantClear( &bypass_list );
3542 CoUninitialize();
3545 static void test_IWinHttpRequest_Invoke(void)
3547 static const WCHAR utf8W[] = {'U','T','F','-','8',0};
3548 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};
3549 WCHAR openW[] = {'O','p','e','n',0};
3550 WCHAR optionW[] = {'O','p','t','i','o','n',0};
3551 OLECHAR *open = openW, *option = optionW;
3552 BSTR utf8;
3553 CLSID clsid;
3554 IWinHttpRequest *request;
3555 IDispatch *dispatch;
3556 DISPID id;
3557 DISPPARAMS params;
3558 VARIANT arg[3], ret;
3559 UINT err;
3560 BOOL bret;
3561 HRESULT hr;
3563 CoInitialize(NULL);
3565 hr = CLSIDFromProgID(regid, &clsid);
3566 ok(hr == S_OK, "CLSIDFromProgID error %#x\n", hr);
3567 bret = IsEqualIID(&clsid, &CLSID_WinHttpRequest);
3568 ok(bret || broken(!bret) /* win2003 */, "not expected %s\n", wine_dbgstr_guid(&clsid));
3570 hr = CoCreateInstance(&CLSID_WinHttpRequest, 0, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&request);
3571 ok(hr == S_OK, "error %#x\n", hr);
3573 hr = IWinHttpRequest_QueryInterface(request, &IID_IDispatch, (void **)&dispatch);
3574 ok(hr == S_OK, "error %#x\n", hr);
3575 IDispatch_Release(dispatch);
3577 hr = IWinHttpRequest_GetIDsOfNames(request, &IID_NULL, &open, 1, 0x0409, &id);
3578 ok(hr == S_OK, "error %#x\n", hr);
3579 ok(id == DISPID_HTTPREQUEST_OPEN, "expected DISPID_HTTPREQUEST_OPEN, got %u\n", id);
3581 hr = IWinHttpRequest_GetIDsOfNames(request, &IID_NULL, &option, 1, 0x0409, &id);
3582 ok(hr == S_OK, "error %#x\n", hr);
3583 ok(id == DISPID_HTTPREQUEST_OPTION, "expected DISPID_HTTPREQUEST_OPTION, got %u\n", id);
3585 memset(&params, 0, sizeof(params));
3586 params.cArgs = 2;
3587 params.cNamedArgs = 0;
3588 params.rgvarg = arg;
3589 V_VT(&arg[0]) = VT_BSTR;
3590 utf8 = SysAllocString(utf8W);
3591 V_BSTR(&arg[0]) = utf8;
3592 V_VT(&arg[1]) = VT_R8;
3593 V_R8(&arg[1]) = 2.0;
3594 VariantInit(&ret);
3595 hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_METHOD, &params, NULL, NULL, &err);
3596 todo_wine
3597 ok(hr == S_OK, "error %#x\n", hr);
3599 VariantInit(&ret);
3600 hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_METHOD, &params, &ret, NULL, &err);
3601 todo_wine
3602 ok(hr == S_OK, "error %#x\n", hr);
3604 SysFreeString(utf8);
3605 IWinHttpRequest_Release(request);
3607 CoUninitialize();
3610 static void test_WinHttpDetectAutoProxyConfigUrl(void)
3612 BOOL ret;
3613 WCHAR *url;
3614 DWORD error;
3616 if (0) /* crashes on some win2k systems */
3618 SetLastError(0xdeadbeef);
3619 ret = WinHttpDetectAutoProxyConfigUrl( 0, NULL );
3620 error = GetLastError();
3621 ok( !ret, "expected failure\n" );
3622 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3624 url = NULL;
3625 SetLastError(0xdeadbeef);
3626 ret = WinHttpDetectAutoProxyConfigUrl( 0, &url );
3627 error = GetLastError();
3628 ok( !ret, "expected failure\n" );
3629 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3631 if (0) /* crashes on some win2k systems */
3633 SetLastError(0xdeadbeef);
3634 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, NULL );
3635 error = GetLastError();
3636 ok( !ret, "expected failure\n" );
3637 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3639 url = (WCHAR *)0xdeadbeef;
3640 SetLastError(0xdeadbeef);
3641 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, &url );
3642 error = GetLastError();
3643 if (!ret)
3645 ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED, "got %u\n", error );
3646 ok( !url || broken(url == (WCHAR *)0xdeadbeef), "got %p\n", url );
3648 else
3650 trace("%s\n", wine_dbgstr_w(url));
3651 GlobalFree( url );
3654 url = (WCHAR *)0xdeadbeef;
3655 SetLastError(0xdeadbeef);
3656 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DHCP, &url );
3657 error = GetLastError();
3658 if (!ret)
3660 ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED, "got %u\n", error );
3661 ok( !url || broken(url == (WCHAR *)0xdeadbeef), "got %p\n", url );
3663 else
3665 ok( error == ERROR_SUCCESS, "got %u\n", error );
3666 trace("%s\n", wine_dbgstr_w(url));
3667 GlobalFree( url );
3671 static void test_WinHttpGetIEProxyConfigForCurrentUser(void)
3673 BOOL ret;
3674 DWORD error;
3675 WINHTTP_CURRENT_USER_IE_PROXY_CONFIG cfg;
3677 memset( &cfg, 0, sizeof(cfg) );
3679 SetLastError(0xdeadbeef);
3680 ret = WinHttpGetIEProxyConfigForCurrentUser( NULL );
3681 error = GetLastError();
3682 ok( !ret, "expected failure\n" );
3683 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3685 SetLastError(0xdeadbeef);
3686 ret = WinHttpGetIEProxyConfigForCurrentUser( &cfg );
3687 error = GetLastError();
3688 ok( ret, "expected success\n" );
3689 ok( error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* < win7 */, "got %u\n", error );
3691 trace("IEProxy.AutoDetect=%d\n", cfg.fAutoDetect);
3692 trace("IEProxy.AutoConfigUrl=%s\n", wine_dbgstr_w(cfg.lpszAutoConfigUrl));
3693 trace("IEProxy.Proxy=%s\n", wine_dbgstr_w(cfg.lpszProxy));
3694 trace("IEProxy.ProxyBypass=%s\n", wine_dbgstr_w(cfg.lpszProxyBypass));
3695 GlobalFree( cfg.lpszAutoConfigUrl );
3696 GlobalFree( cfg.lpszProxy );
3697 GlobalFree( cfg.lpszProxyBypass );
3700 static void test_WinHttpGetProxyForUrl(void)
3702 static const WCHAR urlW[] = {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0};
3703 static const WCHAR wpadW[] = {'h','t','t','p',':','/','/','w','p','a','d','/','w','p','a','d','.','d','a','t',0};
3704 static const WCHAR emptyW[] = {0};
3705 BOOL ret;
3706 DWORD error;
3707 HINTERNET session;
3708 WINHTTP_AUTOPROXY_OPTIONS options;
3709 WINHTTP_PROXY_INFO info;
3711 memset( &options, 0, sizeof(options) );
3713 SetLastError(0xdeadbeef);
3714 ret = WinHttpGetProxyForUrl( NULL, NULL, NULL, NULL );
3715 error = GetLastError();
3716 ok( !ret, "expected failure\n" );
3717 ok( error == ERROR_INVALID_HANDLE, "got %u\n", error );
3719 session = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
3720 ok( session != NULL, "failed to open session %u\n", GetLastError() );
3722 SetLastError(0xdeadbeef);
3723 ret = WinHttpGetProxyForUrl( session, NULL, NULL, NULL );
3724 error = GetLastError();
3725 ok( !ret, "expected failure\n" );
3726 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3728 SetLastError(0xdeadbeef);
3729 ret = WinHttpGetProxyForUrl( session, emptyW, NULL, NULL );
3730 error = GetLastError();
3731 ok( !ret, "expected failure\n" );
3732 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3734 SetLastError(0xdeadbeef);
3735 ret = WinHttpGetProxyForUrl( session, urlW, NULL, NULL );
3736 error = GetLastError();
3737 ok( !ret, "expected failure\n" );
3738 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3740 SetLastError(0xdeadbeef);
3741 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
3742 error = GetLastError();
3743 ok( !ret, "expected failure\n" );
3744 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3746 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
3747 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
3749 SetLastError(0xdeadbeef);
3750 ret = WinHttpGetProxyForUrl( session, urlW, &options, NULL );
3751 error = GetLastError();
3752 ok( !ret, "expected failure\n" );
3753 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3755 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
3756 options.dwAutoDetectFlags = 0;
3758 SetLastError(0xdeadbeef);
3759 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
3760 error = GetLastError();
3761 ok( !ret, "expected failure\n" );
3762 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3764 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT | WINHTTP_AUTOPROXY_CONFIG_URL;
3765 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
3767 SetLastError(0xdeadbeef);
3768 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
3769 error = GetLastError();
3770 ok( !ret, "expected failure\n" );
3771 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3773 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
3774 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
3776 memset( &info, 0, sizeof(info) );
3777 SetLastError(0xdeadbeef);
3778 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
3779 error = GetLastError();
3780 if (ret)
3782 ok( error == ERROR_SUCCESS, "got %u\n", error );
3783 trace("Proxy.AccessType=%u\n", info.dwAccessType);
3784 trace("Proxy.Proxy=%s\n", wine_dbgstr_w(info.lpszProxy));
3785 trace("Proxy.ProxyBypass=%s\n", wine_dbgstr_w(info.lpszProxyBypass));
3786 GlobalFree( info.lpszProxy );
3787 GlobalFree( info.lpszProxyBypass );
3790 options.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
3791 options.dwAutoDetectFlags = 0;
3792 options.lpszAutoConfigUrl = wpadW;
3794 memset( &info, 0, sizeof(info) );
3795 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
3796 if (ret)
3798 trace("Proxy.AccessType=%u\n", info.dwAccessType);
3799 trace("Proxy.Proxy=%s\n", wine_dbgstr_w(info.lpszProxy));
3800 trace("Proxy.ProxyBypass=%s\n", wine_dbgstr_w(info.lpszProxyBypass));
3801 GlobalFree( info.lpszProxy );
3802 GlobalFree( info.lpszProxyBypass );
3804 WinHttpCloseHandle( session );
3807 static void test_chunked_read(void)
3809 static const WCHAR verb[] = {'/','t','e','s','t','c','h','u','n','k','e','d',0};
3810 static const WCHAR chunked[] = {'c','h','u','n','k','e','d',0};
3811 WCHAR header[32];
3812 DWORD len;
3813 HINTERNET ses, con = NULL, req = NULL;
3814 BOOL ret;
3816 trace( "starting chunked read test\n" );
3818 ses = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
3819 ok( ses != NULL, "WinHttpOpen failed with error %u\n", GetLastError() );
3820 if (!ses) goto done;
3822 con = WinHttpConnect( ses, test_winehq, 0, 0 );
3823 ok( con != NULL, "WinHttpConnect failed with error %u\n", GetLastError() );
3824 if (!con) goto done;
3826 req = WinHttpOpenRequest( con, NULL, verb, NULL, NULL, NULL, 0 );
3827 ok( req != NULL, "WinHttpOpenRequest failed with error %u\n", GetLastError() );
3828 if (!req) goto done;
3830 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3831 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
3833 skip("connection failed, skipping\n");
3834 goto done;
3836 ok( ret, "WinHttpSendRequest failed with error %u\n", GetLastError() );
3838 ret = WinHttpReceiveResponse( req, NULL );
3839 ok( ret, "WinHttpReceiveResponse failed with error %u\n", GetLastError() );
3841 header[0] = 0;
3842 len = sizeof(header);
3843 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, header, &len, 0 );
3844 ok( ret, "failed to get TRANSFER_ENCODING header (error %u)\n", GetLastError() );
3845 ok( !lstrcmpW( header, chunked ), "wrong transfer encoding %s\n", wine_dbgstr_w(header) );
3846 trace( "transfer encoding: %s\n", wine_dbgstr_w(header) );
3848 header[0] = 0;
3849 len = sizeof(header);
3850 SetLastError( 0xdeadbeef );
3851 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_CONTENT_LENGTH, NULL, &header, &len, 0 );
3852 ok( !ret, "unexpected CONTENT_LENGTH header %s\n", wine_dbgstr_w(header) );
3853 ok( GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND, "wrong error %u\n", GetLastError() );
3855 trace( "entering query loop\n" );
3856 for (;;)
3858 len = 0xdeadbeef;
3859 ret = WinHttpQueryDataAvailable( req, &len );
3860 ok( ret, "WinHttpQueryDataAvailable failed with error %u\n", GetLastError() );
3861 if (ret) ok( len != 0xdeadbeef, "WinHttpQueryDataAvailable return wrong length\n" );
3862 trace( "got %u available\n", len );
3863 if (len)
3865 DWORD bytes_read;
3866 char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 );
3868 ret = WinHttpReadData( req, buf, len, &bytes_read );
3870 buf[bytes_read] = 0;
3871 trace( "WinHttpReadData -> %d %u\n", ret, bytes_read );
3872 ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len );
3873 ok( buf[bytes_read - 1] == '\n', "received partial line '%s'\n", buf );
3875 HeapFree( GetProcessHeap(), 0, buf );
3876 if (!bytes_read) break;
3878 if (!len) break;
3880 trace( "done\n" );
3882 done:
3883 if (req) WinHttpCloseHandle( req );
3884 if (con) WinHttpCloseHandle( con );
3885 if (ses) WinHttpCloseHandle( ses );
3888 START_TEST (winhttp)
3890 static const WCHAR basicW[] = {'/','b','a','s','i','c',0};
3891 static const WCHAR quitW[] = {'/','q','u','i','t',0};
3892 struct server_info si;
3893 HANDLE thread;
3894 DWORD ret;
3896 test_OpenRequest();
3897 test_SendRequest();
3898 test_WinHttpTimeFromSystemTime();
3899 test_WinHttpTimeToSystemTime();
3900 test_WinHttpAddHeaders();
3901 test_secure_connection();
3902 test_request_parameter_defaults();
3903 test_QueryOption();
3904 test_set_default_proxy_config();
3905 test_empty_headers_param();
3906 test_Timeouts();
3907 test_resolve_timeout();
3908 test_credentials();
3909 test_IWinHttpRequest();
3910 test_IWinHttpRequest_Invoke();
3911 test_WinHttpDetectAutoProxyConfigUrl();
3912 test_WinHttpGetIEProxyConfigForCurrentUser();
3913 test_WinHttpGetProxyForUrl();
3914 test_chunked_read();
3916 si.event = CreateEventW(NULL, 0, 0, NULL);
3917 si.port = 7532;
3919 thread = CreateThread(NULL, 0, server_thread, (LPVOID)&si, 0, NULL);
3920 ok(thread != NULL, "failed to create thread %u\n", GetLastError());
3922 ret = WaitForSingleObject(si.event, 10000);
3923 ok(ret == WAIT_OBJECT_0, "failed to start winhttp test server %u\n", GetLastError());
3924 if (ret != WAIT_OBJECT_0)
3925 return;
3927 test_connection_info(si.port);
3928 test_basic_request(si.port, NULL, basicW);
3929 test_no_headers(si.port);
3930 test_no_content(si.port);
3931 test_head_request(si.port);
3932 test_not_modified(si.port);
3933 test_basic_authentication(si.port);
3934 test_bad_header(si.port);
3935 test_multiple_reads(si.port);
3936 test_cookies(si.port);
3938 /* send the basic request again to shutdown the server thread */
3939 test_basic_request(si.port, NULL, quitW);
3941 WaitForSingleObject(thread, 3000);