[WINHTTP_WINETEST] Sync with Wine Staging 1.9.4. CORE-10912
[reactos.git] / rostests / winetests / winhttp / winhttp.c
1 /*
2 * WinHTTP - tests
3 *
4 * Copyright 2008 Google (Zac Brown)
5 * Copyright 2015 Dmitry Timoshkov
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #define WIN32_NO_STATUS
23 #define _INC_WINDOWS
24 #define COM_NO_WINDOWS_H
25
26 #define COBJMACROS
27 #include <stdarg.h>
28 #include <windef.h>
29 #include <winbase.h>
30 #include <winnls.h>
31 #include <ole2.h>
32 #include <winsock2.h>
33 //#include <ws2tcpip.h>
34 #include <winhttp.h>
35 #include <wincrypt.h>
36 #include <winreg.h>
37 #include <stdio.h>
38 //#include "initguid.h"
39 #include <httprequest.h>
40 #include <httprequestid.h>
41
42 #include <wine/test.h>
43
44 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
45
46 static const WCHAR test_useragent[] =
47 {'W','i','n','e',' ','R','e','g','r','e','s','s','i','o','n',' ','T','e','s','t',0};
48 static const WCHAR test_winehq[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
49 static const WCHAR test_winehq_https[] = {'h','t','t','p','s',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',':','4','4','3',0};
50 static const WCHAR localhostW[] = {'l','o','c','a','l','h','o','s','t',0};
51
52 static BOOL proxy_active(void)
53 {
54 WINHTTP_PROXY_INFO proxy_info;
55 BOOL active = FALSE;
56
57 SetLastError(0xdeadbeef);
58 if (WinHttpGetDefaultProxyConfiguration(&proxy_info))
59 {
60 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
61 "got %u\n", GetLastError());
62 active = (proxy_info.lpszProxy != NULL);
63 if (active)
64 GlobalFree(proxy_info.lpszProxy);
65 if (proxy_info.lpszProxyBypass != NULL)
66 GlobalFree(proxy_info.lpszProxyBypass);
67 }
68 else
69 active = FALSE;
70
71 return active;
72 }
73
74 static void test_QueryOption(void)
75 {
76 BOOL ret;
77 HINTERNET session, request, connection;
78 DWORD feature, size;
79
80 SetLastError(0xdeadbeef);
81 session = WinHttpOpen(test_useragent, 0, 0, 0, 0);
82 ok(session != NULL, "WinHttpOpen failed to open session, error %u\n", GetLastError());
83
84 SetLastError(0xdeadbeef);
85 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, NULL);
86 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
87 ok(GetLastError() == ERROR_INVALID_PARAMETER,
88 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
89
90 size = 0xdeadbeef;
91 SetLastError(0xdeadbeef);
92 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, &size);
93 ok(!ret, "should fail to query option\n");
94 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
95 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
96 ok(size == 4, "expected 4, got %u\n", size);
97
98 feature = 0xdeadbeef;
99 size = sizeof(feature) - 1;
100 SetLastError(0xdeadbeef);
101 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
102 ok(!ret, "should fail to query option\n");
103 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
104 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
105 ok(size == 4, "expected 4, got %u\n", size);
106
107 feature = 0xdeadbeef;
108 size = sizeof(feature) + 1;
109 SetLastError(0xdeadbeef);
110 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
111 ok(ret, "failed to query option %u\n", GetLastError());
112 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
113 "got %u\n", GetLastError());
114 ok(size == sizeof(feature), "WinHttpQueryOption should set the size: %u\n", size);
115 ok(feature == WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP,
116 "expected WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP, got %#x\n", feature);
117
118 SetLastError(0xdeadbeef);
119 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, sizeof(feature));
120 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
121 ok(GetLastError() == ERROR_INVALID_PARAMETER,
122 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
123
124 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
125 SetLastError(0xdeadbeef);
126 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature) - 1);
127 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
128 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
129 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
130
131 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
132 SetLastError(0xdeadbeef);
133 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature) + 1);
134 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
135 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
136 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
137
138 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
139 SetLastError(0xdeadbeef);
140 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature));
141 ok(ret, "failed to set redirect policy %u\n", GetLastError());
142
143 feature = 0xdeadbeef;
144 size = sizeof(feature);
145 SetLastError(0xdeadbeef);
146 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
147 ok(ret, "failed to query option %u\n", GetLastError());
148 ok(feature == WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS,
149 "expected WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS, got %#x\n", feature);
150
151 feature = WINHTTP_DISABLE_COOKIES;
152 SetLastError(0xdeadbeef);
153 ret = WinHttpSetOption(session, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
154 ok(!ret, "should fail to set disable feature for a session\n");
155 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
156 "expected ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, got %u\n", GetLastError());
157
158 SetLastError(0xdeadbeef);
159 connection = WinHttpConnect(session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
160 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u\n", GetLastError());
161
162 feature = WINHTTP_DISABLE_COOKIES;
163 SetLastError(0xdeadbeef);
164 ret = WinHttpSetOption(connection, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
165 ok(!ret, "should fail to set disable feature for a connection\n");
166 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
167 "expected ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, got %u\n", GetLastError());
168
169 SetLastError(0xdeadbeef);
170 request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
171 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
172 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
173 {
174 skip("Network unreachable, skipping the test\n");
175 goto done;
176 }
177
178 feature = 0xdeadbeef;
179 size = sizeof(feature);
180 SetLastError(0xdeadbeef);
181 ret = WinHttpQueryOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, &size);
182 ok(!ret, "should fail to query disable feature for a request\n");
183 ok(GetLastError() == ERROR_INVALID_PARAMETER,
184 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
185
186 feature = 0;
187 size = sizeof(feature);
188 SetLastError(0xdeadbeef);
189 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
190 ok(ret, "failed to set feature %u\n", GetLastError());
191
192 feature = 0xffffffff;
193 size = sizeof(feature);
194 SetLastError(0xdeadbeef);
195 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
196 ok(ret, "failed to set feature %u\n", GetLastError());
197
198 feature = WINHTTP_DISABLE_COOKIES;
199 size = sizeof(feature);
200 SetLastError(0xdeadbeef);
201 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
202 ok(ret, "failed to set feature %u\n", GetLastError());
203
204 size = 0;
205 SetLastError(0xdeadbeef);
206 ret = WinHttpQueryOption(request, WINHTTP_OPTION_DISABLE_FEATURE, NULL, &size);
207 ok(!ret, "should fail to query disable feature for a request\n");
208 ok(GetLastError() == ERROR_INVALID_PARAMETER,
209 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
210
211 SetLastError(0xdeadbeef);
212 ret = WinHttpCloseHandle(request);
213 ok(ret, "WinHttpCloseHandle failed on closing request: %u\n", GetLastError());
214
215 done:
216 SetLastError(0xdeadbeef);
217 ret = WinHttpCloseHandle(connection);
218 ok(ret, "WinHttpCloseHandle failed on closing connection: %u\n", GetLastError());
219 SetLastError(0xdeadbeef);
220 ret = WinHttpCloseHandle(session);
221 ok(ret, "WinHttpCloseHandle failed on closing session: %u\n", GetLastError());
222 }
223
224 static void test_OpenRequest (void)
225 {
226 BOOL ret;
227 HINTERNET session, request, connection;
228 DWORD err;
229
230 SetLastError(0xdeadbeef);
231 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
232 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
233 err = GetLastError();
234 ok(session != NULL, "WinHttpOpen failed to open session.\n");
235 ok(err == ERROR_SUCCESS, "got %u\n", err);
236
237 /* Test with a bad server name */
238 SetLastError(0xdeadbeef);
239 connection = WinHttpConnect(session, NULL, INTERNET_DEFAULT_HTTP_PORT, 0);
240 err = GetLastError();
241 ok (connection == NULL, "WinHttpConnect succeeded in opening connection to NULL server argument.\n");
242 ok(err == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u.\n", err);
243
244 /* Test with a valid server name */
245 SetLastError(0xdeadbeef);
246 connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
247 err = GetLastError();
248 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", err);
249 ok(err == ERROR_SUCCESS || broken(err == WSAEINVAL) /* < win7 */, "got %u\n", err);
250
251 SetLastError(0xdeadbeef);
252 request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
253 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
254 err = GetLastError();
255 if (request == NULL && err == ERROR_WINHTTP_NAME_NOT_RESOLVED)
256 {
257 skip("Network unreachable, skipping.\n");
258 goto done;
259 }
260 ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", err);
261 ok(err == ERROR_SUCCESS, "got %u\n", err);
262
263 SetLastError(0xdeadbeef);
264 ret = WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, NULL, 0, 0, 0);
265 err = GetLastError();
266 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
267 {
268 skip("Connection failed, skipping.\n");
269 goto done;
270 }
271 ok(ret, "WinHttpSendRequest failed: %u\n", err);
272 ok(err == ERROR_SUCCESS, "got %u\n", err);
273
274 SetLastError(0xdeadbeef);
275 ret = WinHttpCloseHandle(request);
276 err = GetLastError();
277 ok(ret, "WinHttpCloseHandle failed on closing request, got %u.\n", err);
278 ok(err == ERROR_SUCCESS, "got %u\n", err);
279
280 done:
281 ret = WinHttpCloseHandle(connection);
282 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
283 ret = WinHttpCloseHandle(session);
284 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
285
286 }
287
288 static void test_empty_headers_param(void)
289 {
290 static const WCHAR empty[] = {0};
291 HINTERNET ses, con, req;
292 DWORD err;
293 BOOL ret;
294
295 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
296 ok(ses != NULL, "failed to open session %u\n", GetLastError());
297
298 con = WinHttpConnect(ses, test_winehq, 80, 0);
299 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
300
301 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
302 ok(req != NULL, "failed to open a request %u\n", GetLastError());
303
304 ret = WinHttpSendRequest(req, empty, 0, NULL, 0, 0, 0);
305 err = GetLastError();
306 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
307 {
308 skip("connection failed, skipping\n");
309 goto done;
310 }
311 ok(ret, "failed to send request %u\n", GetLastError());
312
313 done:
314 WinHttpCloseHandle(req);
315 WinHttpCloseHandle(con);
316 WinHttpCloseHandle(ses);
317 }
318
319 static void test_SendRequest (void)
320 {
321 static const WCHAR content_type[] =
322 {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t','i','o','n',
323 '/','x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o','d','e','d',0};
324 static const WCHAR test_file[] = {'t','e','s','t','s','/','p','o','s','t','.','p','h','p',0};
325 static const WCHAR test_verb[] = {'P','O','S','T',0};
326 static CHAR post_data[] = "mode=Test";
327 static const char test_post[] = "mode => Test\0\n";
328 HINTERNET session, request, connection;
329 DWORD header_len, optional_len, total_len, bytes_rw, size, err;
330 DWORD_PTR context;
331 BOOL ret;
332 CHAR buffer[256];
333 int i;
334
335 header_len = -1L;
336 total_len = optional_len = sizeof(post_data);
337 memset(buffer, 0xff, sizeof(buffer));
338
339 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
340 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
341 ok(session != NULL, "WinHttpOpen failed to open session.\n");
342
343 connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
344 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
345
346 request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
347 WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
348 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
349 {
350 skip("Network unreachable, skipping.\n");
351 goto done;
352 }
353 ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError());
354 if (!request) goto done;
355
356 context = 0xdeadbeef;
357 ret = WinHttpSetOption(request, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(context));
358 ok(ret, "WinHttpSetOption failed: %u\n", GetLastError());
359
360 context++;
361 ret = WinHttpSendRequest(request, content_type, header_len, post_data, optional_len, total_len, context);
362 err = GetLastError();
363 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
364 {
365 skip("connection failed, skipping\n");
366 goto done;
367 }
368 ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError());
369
370 context = 0;
371 size = sizeof(context);
372 ret = WinHttpQueryOption(request, WINHTTP_OPTION_CONTEXT_VALUE, &context, &size);
373 ok(ret, "WinHttpQueryOption failed: %u\n", GetLastError());
374 ok(context == 0xdeadbef0, "expected 0xdeadbef0, got %lx\n", context);
375
376 for (i = 3; post_data[i]; i++)
377 {
378 bytes_rw = -1;
379 SetLastError(0xdeadbeef);
380 ret = WinHttpWriteData(request, &post_data[i], 1, &bytes_rw);
381 if (ret)
382 {
383 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %u.\n", GetLastError());
384 ok(bytes_rw == 1, "WinHttpWriteData failed, wrote %u bytes instead of 1 byte.\n", bytes_rw);
385 }
386 else /* Since we already passed all optional data in WinHttpSendRequest Win7 fails our WinHttpWriteData call */
387 {
388 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER got %u.\n", GetLastError());
389 ok(bytes_rw == -1, "Expected bytes_rw to remain unchanged.\n");
390 }
391 }
392
393 SetLastError(0xdeadbeef);
394 ret = WinHttpReceiveResponse(request, NULL);
395 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == ERROR_NO_TOKEN) /* < win7 */,
396 "Expected ERROR_SUCCESS got %u.\n", GetLastError());
397 ok(ret == TRUE, "WinHttpReceiveResponse failed: %u.\n", GetLastError());
398
399 bytes_rw = -1;
400 ret = WinHttpReadData(request, buffer, sizeof(buffer) - 1, &bytes_rw);
401 ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
402
403 ok(bytes_rw == sizeof(test_post) - 1, "Read %u bytes\n", bytes_rw);
404 ok(!memcmp(buffer, test_post, sizeof(test_post) - 1), "Data read did not match.\n");
405
406 done:
407 ret = WinHttpCloseHandle(request);
408 ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
409 ret = WinHttpCloseHandle(connection);
410 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
411 ret = WinHttpCloseHandle(session);
412 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
413 }
414
415 static void test_WinHttpTimeFromSystemTime(void)
416 {
417 BOOL ret;
418 static const SYSTEMTIME time = {2008, 7, 1, 28, 10, 5, 52, 0};
419 static const WCHAR expected_string[] =
420 {'M','o','n',',',' ','2','8',' ','J','u','l',' ','2','0','0','8',' ',
421 '1','0',':','0','5',':','5','2',' ','G','M','T',0};
422 WCHAR time_string[WINHTTP_TIME_FORMAT_BUFSIZE+1];
423 DWORD err;
424
425 SetLastError(0xdeadbeef);
426 ret = WinHttpTimeFromSystemTime(&time, NULL);
427 err = GetLastError();
428 ok(!ret, "WinHttpTimeFromSystemTime succeeded\n");
429 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
430
431 SetLastError(0xdeadbeef);
432 ret = WinHttpTimeFromSystemTime(NULL, time_string);
433 err = GetLastError();
434 ok(!ret, "WinHttpTimeFromSystemTime succeeded\n");
435 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
436
437 SetLastError(0xdeadbeef);
438 ret = WinHttpTimeFromSystemTime(&time, time_string);
439 err = GetLastError();
440 ok(ret, "WinHttpTimeFromSystemTime failed: %u\n", err);
441 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
442 ok(memcmp(time_string, expected_string, sizeof(expected_string)) == 0,
443 "Time string returned did not match expected time string.\n");
444 }
445
446 static void test_WinHttpTimeToSystemTime(void)
447 {
448 BOOL ret;
449 SYSTEMTIME time;
450 static const SYSTEMTIME expected_time = {2008, 7, 1, 28, 10, 5, 52, 0};
451 static const WCHAR time_string1[] =
452 {'M','o','n',',',' ','2','8',' ','J','u','l',' ','2','0','0','8',' ',
453 + '1','0',':','0','5',':','5','2',' ','G','M','T','\n',0};
454 static const WCHAR time_string2[] =
455 {' ','m','o','n',' ','2','8',' ','j','u','l',' ','2','0','0','8',' ',
456 '1','0',' ','0','5',' ','5','2','\n',0};
457 DWORD err;
458
459 SetLastError(0xdeadbeef);
460 ret = WinHttpTimeToSystemTime(time_string1, NULL);
461 err = GetLastError();
462 ok(!ret, "WinHttpTimeToSystemTime succeeded\n");
463 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
464
465 SetLastError(0xdeadbeef);
466 ret = WinHttpTimeToSystemTime(NULL, &time);
467 err = GetLastError();
468 ok(!ret, "WinHttpTimeToSystemTime succeeded\n");
469 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
470
471 SetLastError(0xdeadbeef);
472 ret = WinHttpTimeToSystemTime(time_string1, &time);
473 err = GetLastError();
474 ok(ret, "WinHttpTimeToSystemTime failed: %u\n", err);
475 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
476 ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
477 "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
478
479 SetLastError(0xdeadbeef);
480 ret = WinHttpTimeToSystemTime(time_string2, &time);
481 err = GetLastError();
482 ok(ret, "WinHttpTimeToSystemTime failed: %u\n", err);
483 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
484 ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
485 "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
486 }
487
488 static void test_WinHttpAddHeaders(void)
489 {
490 HINTERNET session, request, connection;
491 BOOL ret, reverse;
492 WCHAR buffer[MAX_PATH];
493 WCHAR check_buffer[MAX_PATH];
494 DWORD err, index, len, oldlen;
495
496 static const WCHAR test_file[] = {'/','p','o','s','t','t','e','s','t','.','p','h','p',0};
497 static const WCHAR test_verb[] = {'P','O','S','T',0};
498 static const WCHAR test_header_begin[] =
499 {'P','O','S','T',' ','/','p','o','s','t','t','e','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
500 static const WCHAR full_path_test_header_begin[] =
501 {'P','O','S','T',' ','h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',':','8','0',
502 '/','p','o','s','t','t','e','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
503 static const WCHAR test_header_end[] = {'\r','\n','\r','\n',0};
504 static const WCHAR test_header_name[] = {'W','a','r','n','i','n','g',0};
505 static const WCHAR test_header_name2[] = {'n','a','m','e',0};
506 static const WCHAR test_header_name3[] = {'a',0};
507 static const WCHAR test_header_range[] = {'R','a','n','g','e',0};
508 static const WCHAR test_header_range_bytes[] = {'R','a','n','g','e',':',' ','b','y','t','e','s','=','0','-','7','7','3','\r','\n',0};
509 static const WCHAR test_header_bytes[] = {'b','y','t','e','s','=','0','-','7','7','3',0};
510
511 static const WCHAR test_flag_coalesce[] = {'t','e','s','t','2',',',' ','t','e','s','t','4',0};
512 static const WCHAR test_flag_coalesce_reverse[] = {'t','e','s','t','3',',',' ','t','e','s','t','4',0};
513 static const WCHAR test_flag_coalesce_comma[] =
514 {'t','e','s','t','2',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',0};
515 static const WCHAR test_flag_coalesce_comma_reverse[] =
516 {'t','e','s','t','3',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',0};
517 static const WCHAR test_flag_coalesce_semicolon[] =
518 {'t','e','s','t','2',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',';',' ','t','e','s','t','6',0};
519 static const WCHAR test_flag_coalesce_semicolon_reverse[] =
520 {'t','e','s','t','3',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',';',' ','t','e','s','t','6',0};
521
522 static const WCHAR field[] = {'f','i','e','l','d',0};
523 static const WCHAR value[] = {'v','a','l','u','e',' ',0};
524 static const WCHAR value_nospace[] = {'v','a','l','u','e',0};
525 static const WCHAR empty[] = {0};
526
527 static const WCHAR test_headers[][14] =
528 {
529 {'W','a','r','n','i','n','g',':','t','e','s','t','1',0},
530 {'W','a','r','n','i','n','g',':','t','e','s','t','2',0},
531 {'W','a','r','n','i','n','g',':','t','e','s','t','3',0},
532 {'W','a','r','n','i','n','g',':','t','e','s','t','4',0},
533 {'W','a','r','n','i','n','g',':','t','e','s','t','5',0},
534 {'W','a','r','n','i','n','g',':','t','e','s','t','6',0},
535 {'W','a','r','n','i','n','g',':','t','e','s','t','7',0},
536 {0},
537 {':',0},
538 {'a',':',0},
539 {':','b',0},
540 {'c','d',0},
541 {' ','e',' ',':','f',0},
542 {'f','i','e','l','d',':',' ','v','a','l','u','e',' ',0},
543 {'n','a','m','e',':',' ','v','a','l','u','e',0},
544 {'n','a','m','e',':',0}
545 };
546 static const WCHAR test_indices[][6] =
547 {
548 {'t','e','s','t','1',0},
549 {'t','e','s','t','2',0},
550 {'t','e','s','t','3',0},
551 {'t','e','s','t','4',0}
552 };
553
554 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
555 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
556 ok(session != NULL, "WinHttpOpen failed to open session.\n");
557
558 connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
559 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
560
561 request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
562 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
563 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
564 {
565 skip("Network unreachable, skipping.\n");
566 goto done;
567 }
568 ok(request != NULL, "WinHttpOpenRequest failed to open a request, error: %u.\n", GetLastError());
569
570 index = 0;
571 len = sizeof(buffer);
572 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
573 test_header_name, buffer, &len, &index);
574 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, found 'Warning' header.\n");
575 SetLastError(0xdeadbeef);
576 ret = WinHttpAddRequestHeaders(request, test_headers[0], -1L, WINHTTP_ADDREQ_FLAG_ADD);
577 err = GetLastError();
578 ok(ret, "WinHttpAddRequestHeader failed to add new header, got %d with error %u.\n", ret, err);
579 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
580
581 index = 0;
582 len = sizeof(buffer);
583 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
584 test_header_name, buffer, &len, &index);
585 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
586 ok(index == 1, "WinHttpQueryHeaders failed: header index not incremented\n");
587 ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders failed: incorrect string returned\n");
588 ok(len == 5*sizeof(WCHAR), "WinHttpQueryHeaders failed: invalid length returned, expected 5, got %d\n", len);
589
590 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
591 test_header_name, buffer, &len, &index);
592 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, second index should not exist.\n");
593
594 /* Try to fetch the header info with a buffer that's big enough to fit the
595 * string but not the NULL terminator.
596 */
597 index = 0;
598 len = 5*sizeof(WCHAR);
599 memset(check_buffer, 0xab, sizeof(check_buffer));
600 memcpy(buffer, check_buffer, sizeof(buffer));
601 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
602 test_header_name, buffer, &len, &index);
603 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded with a buffer that's too small.\n");
604 ok(memcmp(buffer, check_buffer, sizeof(buffer)) == 0,
605 "WinHttpQueryHeaders failed, modified the buffer when it should not have.\n");
606 ok(len == 6*sizeof(WCHAR), "WinHttpQueryHeaders returned invalid length, expected 12, got %d\n", len);
607
608 /* Try with a NULL buffer */
609 index = 0;
610 len = sizeof(buffer);
611 SetLastError(0xdeadbeef);
612 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
613 test_header_name, NULL, &len, &index);
614 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
615 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
616 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
617 ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
618
619 /* Try with a NULL buffer and a length that's too small */
620 index = 0;
621 len = 10;
622 SetLastError(0xdeadbeef);
623 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
624 test_header_name, NULL, &len, &index);
625 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
626 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
627 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICENT_BUFFER, go %u\n", GetLastError());
628 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
629 ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
630
631 index = 0;
632 len = 0;
633 SetLastError(0xdeadbeef);
634 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
635 test_header_name, NULL, &len, &index);
636 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
637 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
638 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
639 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
640 ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
641
642 /* valid query */
643 oldlen = len;
644 index = 0;
645 len = sizeof(buffer);
646 memset(buffer, 0xff, sizeof(buffer));
647 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
648 test_header_name, buffer, &len, &index);
649 ok(ret == TRUE, "WinHttpQueryHeaders failed: got %d\n", ret);
650 ok(len + sizeof(WCHAR) <= oldlen, "WinHttpQueryHeaders resulting length longer than advertized.\n");
651 ok((len < sizeof(buffer) - sizeof(WCHAR)) && buffer[len / sizeof(WCHAR)] == 0, "WinHttpQueryHeaders did not append NULL terminator\n");
652 ok(len == lstrlenW(buffer) * sizeof(WCHAR), "WinHttpQueryHeaders returned incorrect length.\n");
653 ok(memcmp(buffer, test_header_begin, sizeof(test_header_begin)) == 0 ||
654 memcmp(buffer, full_path_test_header_begin, sizeof(full_path_test_header_begin)) == 0,
655 "WinHttpQueryHeaders returned invalid beginning of header string.\n");
656 ok(memcmp(buffer + lstrlenW(buffer) - 4, test_header_end, sizeof(test_header_end)) == 0,
657 "WinHttpQueryHeaders returned invalid end of header string.\n");
658 ok(index == 0, "WinHttpQueryHeaders incremented header index.\n");
659
660 index = 0;
661 len = 0;
662 SetLastError(0xdeadbeef);
663 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
664 test_header_name, NULL, &len, &index);
665 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
666 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
667 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
668 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
669 ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
670
671 oldlen = len;
672 index = 0;
673 len = sizeof(buffer);
674 memset(buffer, 0xff, sizeof(buffer));
675 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
676 test_header_name, buffer, &len, &index);
677 ok(ret == TRUE, "WinHttpQueryHeaders failed %u\n", GetLastError());
678 ok(len + sizeof(WCHAR) <= oldlen, "resulting length longer than advertized\n");
679 ok((len < sizeof(buffer) - sizeof(WCHAR)) && !buffer[len / sizeof(WCHAR)] && !buffer[len / sizeof(WCHAR) - 1],
680 "no double NULL terminator\n");
681 ok(memcmp(buffer, test_header_begin, sizeof(test_header_begin)) == 0 ||
682 memcmp(buffer, full_path_test_header_begin, sizeof(full_path_test_header_begin)) == 0,
683 "invalid beginning of header string.\n");
684 ok(index == 0, "header index was incremented\n");
685
686 /* tests for more indices */
687 ret = WinHttpAddRequestHeaders(request, test_headers[1], -1L, WINHTTP_ADDREQ_FLAG_ADD);
688 ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header: %d\n", ret);
689
690 index = 0;
691 len = sizeof(buffer);
692 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
693 test_header_name, buffer, &len, &index);
694 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
695 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
696 ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
697
698 len = sizeof(buffer);
699 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
700 test_header_name, buffer, &len, &index);
701 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
702 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
703 ok(memcmp(buffer, test_indices[1], sizeof(test_indices[1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
704
705 ret = WinHttpAddRequestHeaders(request, test_headers[2], -1L, WINHTTP_ADDREQ_FLAG_REPLACE);
706 ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header.\n");
707
708 index = 0;
709 len = sizeof(buffer);
710 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
711 test_header_name, buffer, &len, &index);
712 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
713 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
714 reverse = (memcmp(buffer, test_indices[1], sizeof(test_indices[1])) != 0); /* Win7 returns values in reverse order of adding */
715 ok(memcmp(buffer, test_indices[reverse ? 2 : 1], sizeof(test_indices[reverse ? 2 : 1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
716
717 len = sizeof(buffer);
718 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
719 test_header_name, buffer, &len, &index);
720 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
721 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
722 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
723
724 /* add if new flag */
725 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW);
726 ok(ret == FALSE, "WinHttpAddRequestHeaders incorrectly replaced existing header.\n");
727
728 index = 0;
729 len = sizeof(buffer);
730 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
731 test_header_name, buffer, &len, &index);
732 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
733 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
734 ok(memcmp(buffer, test_indices[reverse ? 2 : 1], sizeof(test_indices[reverse ? 2 : 1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
735
736 len = sizeof(buffer);
737 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
738 test_header_name, buffer, &len, &index);
739 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
740 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
741 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
742
743 len = sizeof(buffer);
744 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
745 test_header_name, buffer, &len, &index);
746 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
747
748 /* coalesce flag */
749 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_COALESCE);
750 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE.\n");
751
752 index = 0;
753 len = sizeof(buffer);
754 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
755 test_header_name, buffer, &len, &index);
756 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
757 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
758 ok(memcmp(buffer, reverse ? test_flag_coalesce_reverse : test_flag_coalesce,
759 reverse ? sizeof(test_flag_coalesce_reverse) : sizeof(test_flag_coalesce)) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
760
761 len = sizeof(buffer);
762 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
763 test_header_name, buffer, &len, &index);
764 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
765 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
766 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
767
768 len = sizeof(buffer);
769 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
770 test_header_name, buffer, &len, &index);
771 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
772
773 /* coalesce with comma flag */
774 ret = WinHttpAddRequestHeaders(request, test_headers[4], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA);
775 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA.\n");
776
777 index = 0;
778 len = sizeof(buffer);
779 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
780 test_header_name, buffer, &len, &index);
781 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
782 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
783 ok(memcmp(buffer, reverse ? test_flag_coalesce_comma_reverse : test_flag_coalesce_comma,
784 reverse ? sizeof(test_flag_coalesce_comma_reverse) : sizeof(test_flag_coalesce_comma)) == 0,
785 "WinHttpQueryHeaders returned incorrect string.\n");
786
787 len = sizeof(buffer);
788 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
789 test_header_name, buffer, &len, &index);
790 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
791 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
792 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
793
794 len = sizeof(buffer);
795 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
796 test_header_name, buffer, &len, &index);
797 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
798
799
800 /* coalesce with semicolon flag */
801 ret = WinHttpAddRequestHeaders(request, test_headers[5], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON);
802 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON.\n");
803
804 index = 0;
805 len = sizeof(buffer);
806 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
807 test_header_name, buffer, &len, &index);
808 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
809 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
810 ok(memcmp(buffer, reverse ? test_flag_coalesce_semicolon_reverse : test_flag_coalesce_semicolon,
811 reverse ? sizeof(test_flag_coalesce_semicolon_reverse) : sizeof(test_flag_coalesce_semicolon)) == 0,
812 "WinHttpQueryHeaders returned incorrect string.\n");
813
814 len = sizeof(buffer);
815 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
816 test_header_name, buffer, &len, &index);
817 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
818 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
819 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
820
821 len = sizeof(buffer);
822 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
823 test_header_name, buffer, &len, &index);
824 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
825
826 /* add and replace flags */
827 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
828 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE.\n");
829
830 index = 0;
831 len = sizeof(buffer);
832 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
833 test_header_name, buffer, &len, &index);
834 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
835 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
836 ok(memcmp(buffer, test_indices[reverse ? 3 : 2], sizeof(test_indices[reverse ? 3 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
837
838 len = sizeof(buffer);
839 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
840 test_header_name, buffer, &len, &index);
841 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
842 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
843 ok(memcmp(buffer, test_indices[reverse ? 1 : 3], sizeof(test_indices[reverse ? 1 : 3])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
844
845 len = sizeof(buffer);
846 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
847 test_header_name, buffer, &len, &index);
848 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
849
850 ret = WinHttpAddRequestHeaders(request, test_headers[8], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
851 ok(!ret, "WinHttpAddRequestHeaders failed\n");
852
853 ret = WinHttpAddRequestHeaders(request, test_headers[9], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
854 ok(ret, "WinHttpAddRequestHeaders failed\n");
855
856 index = 0;
857 memset(buffer, 0xff, sizeof(buffer));
858 len = sizeof(buffer);
859 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
860 test_header_name3, buffer, &len, &index);
861 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
862 ok(!memcmp(buffer, empty, sizeof(empty)), "unexpected result\n");
863
864 ret = WinHttpAddRequestHeaders(request, test_headers[10], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
865 ok(!ret, "WinHttpAddRequestHeaders failed\n");
866
867 ret = WinHttpAddRequestHeaders(request, test_headers[11], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
868 ok(!ret, "WinHttpAddRequestHeaders failed\n");
869
870 ret = WinHttpAddRequestHeaders(request, test_headers[12], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
871 ok(!ret, "WinHttpAddRequestHeaders failed\n");
872
873 ret = WinHttpAddRequestHeaders(request, test_headers[13], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
874 ok(ret, "WinHttpAddRequestHeaders failed\n");
875
876 index = 0;
877 buffer[0] = 0;
878 len = sizeof(buffer);
879 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
880 field, buffer, &len, &index);
881 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
882 ok(!memcmp(buffer, value, sizeof(value)) || ! memcmp(buffer, value_nospace, sizeof(value_nospace)), "unexpected result\n");
883
884 SetLastError(0xdeadbeef);
885 ret = WinHttpAddRequestHeaders(request, test_header_range_bytes, 0,
886 WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
887 err = GetLastError();
888 ok(!ret, "unexpected success\n");
889 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
890
891 ret = WinHttpAddRequestHeaders(request, test_header_range_bytes, ~0u,
892 WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
893 ok(ret, "failed to add header: %u\n", GetLastError());
894
895 index = 0;
896 len = sizeof(buffer);
897 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
898 test_header_range, buffer, &len, &index);
899 ok(ret, "failed to get range header %u\n", GetLastError());
900 ok(!memcmp(buffer, test_header_bytes, sizeof(test_header_bytes)), "incorrect string returned\n");
901 ok(len == lstrlenW(test_header_bytes) * sizeof(WCHAR), "wrong length %u\n", len);
902 ok(index == 1, "wrong index %u\n", index);
903
904 index = 0;
905 len = sizeof(buffer);
906 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
907 test_header_name2, buffer, &len, &index);
908 ok(!ret, "unexpected success\n");
909
910 SetLastError(0xdeadbeef);
911 ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
912 err = GetLastError();
913 ok(!ret, "unexpected success\n");
914 ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
915
916 ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
917 ok(ret, "got %u\n", GetLastError());
918
919 index = 0;
920 len = sizeof(buffer);
921 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
922 test_header_name2, buffer, &len, &index);
923 ok(ret, "got %u\n", GetLastError());
924 ok(index == 1, "wrong index %u\n", index);
925 ok(!memcmp(buffer, value_nospace, sizeof(value_nospace)), "incorrect string\n");
926
927 ret = WinHttpAddRequestHeaders(request, test_headers[15], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
928 ok(ret, "got %u\n", GetLastError());
929
930 index = 0;
931 len = sizeof(buffer);
932 SetLastError(0xdeadbeef);
933 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
934 test_header_name2, buffer, &len, &index);
935 err = GetLastError();
936 ok(!ret, "unexpected success\n");
937 ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
938
939 ret = WinHttpAddRequestHeaders(request, test_headers[14], -1L, 0);
940 ok(ret, "got %u\n", GetLastError());
941
942 index = 0;
943 len = sizeof(buffer);
944 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
945 test_header_name2, buffer, &len, &index);
946 ok(ret, "got %u\n", GetLastError());
947 ok(index == 1, "wrong index %u\n", index);
948 ok(!memcmp(buffer, value_nospace, sizeof(value_nospace)), "incorrect string\n");
949
950 ret = WinHttpCloseHandle(request);
951 ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
952 done:
953 ret = WinHttpCloseHandle(connection);
954 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
955 ret = WinHttpCloseHandle(session);
956 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
957
958 }
959
960 static void CALLBACK cert_error(HINTERNET handle, DWORD_PTR ctx, DWORD status, LPVOID buf, DWORD len)
961 {
962 DWORD flags = *(DWORD *)buf;
963
964 if (!flags)
965 {
966 trace("WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR\n");
967 return;
968 }
969 #define X(x) if (flags & x) trace("%s\n", #x);
970 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED)
971 X(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT)
972 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED)
973 X(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA)
974 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID)
975 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID)
976 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE)
977 #undef X
978 }
979
980 static void test_secure_connection(void)
981 {
982 static const char data_start[] = "<!DOCTYPE html PUBLIC";
983 HINTERNET ses, con, req;
984 DWORD size, status, policy, bitness, read_size, err, available_size;
985 BOOL ret;
986 CERT_CONTEXT *cert;
987 WINHTTP_CERTIFICATE_INFO info;
988 char buffer[32];
989
990 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
991 ok(ses != NULL, "failed to open session %u\n", GetLastError());
992
993 policy = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
994 ret = WinHttpSetOption(ses, WINHTTP_OPTION_REDIRECT_POLICY, &policy, sizeof(policy));
995 ok(ret, "failed to set redirect policy %u\n", GetLastError());
996
997 con = WinHttpConnect(ses, test_winehq, 443, 0);
998 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
999
1000 /* try without setting WINHTTP_FLAG_SECURE */
1001 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1002 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1003
1004 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1005 err = GetLastError();
1006 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
1007 {
1008 skip("Connection failed, skipping.\n");
1009 goto cleanup;
1010 }
1011 ok(ret, "failed to send request %u\n", GetLastError());
1012
1013 ret = WinHttpReceiveResponse(req, NULL);
1014 ok(!ret || proxy_active(), "succeeded unexpectedly\n");
1015
1016 size = 0;
1017 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL);
1018 ok(!ret, "succeeded unexpectedly\n");
1019
1020 WinHttpCloseHandle(req);
1021
1022 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, WINHTTP_FLAG_SECURE);
1023 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1024
1025 WinHttpSetStatusCallback(req, cert_error, WINHTTP_CALLBACK_STATUS_SECURE_FAILURE, 0);
1026
1027 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1028 err = GetLastError();
1029 if (!ret && (err == ERROR_WINHTTP_SECURE_FAILURE || err == ERROR_WINHTTP_CANNOT_CONNECT ||
1030 err == ERROR_WINHTTP_TIMEOUT))
1031 {
1032 skip("secure connection failed, skipping remaining secure tests\n");
1033 goto cleanup;
1034 }
1035 ok(ret, "failed to send request %u\n", GetLastError());
1036
1037 size = sizeof(cert);
1038 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert, &size );
1039 ok(ret, "failed to retrieve certificate context %u\n", GetLastError());
1040 if (ret) CertFreeCertificateContext(cert);
1041
1042 size = sizeof(bitness);
1043 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_KEY_BITNESS, &bitness, &size );
1044 ok(ret, "failed to retrieve key bitness %u\n", GetLastError());
1045
1046 size = sizeof(info);
1047 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT, &info, &size );
1048 ok(ret, "failed to retrieve certificate info %u\n", GetLastError());
1049
1050 if (ret)
1051 {
1052 trace("lpszSubjectInfo %s\n", wine_dbgstr_w(info.lpszSubjectInfo));
1053 trace("lpszIssuerInfo %s\n", wine_dbgstr_w(info.lpszIssuerInfo));
1054 trace("lpszProtocolName %s\n", wine_dbgstr_w(info.lpszProtocolName));
1055 trace("lpszSignatureAlgName %s\n", wine_dbgstr_w(info.lpszSignatureAlgName));
1056 trace("lpszEncryptionAlgName %s\n", wine_dbgstr_w(info.lpszEncryptionAlgName));
1057 trace("dwKeySize %u\n", info.dwKeySize);
1058 }
1059
1060 ret = WinHttpReceiveResponse(req, NULL);
1061 ok(ret, "failed to receive response %u\n", GetLastError());
1062
1063 available_size = 0;
1064 ret = WinHttpQueryDataAvailable(req, &available_size);
1065 ok(ret, "failed to query available data %u\n", GetLastError());
1066 ok(available_size > 2014, "available_size = %u\n", available_size);
1067
1068 status = 0xdeadbeef;
1069 size = sizeof(status);
1070 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1071 ok(ret, "failed unexpectedly %u\n", GetLastError());
1072 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1073
1074 size = 0;
1075 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL);
1076 ok(!ret, "succeeded unexpectedly\n");
1077
1078 read_size = 0;
1079 for (;;)
1080 {
1081 size = 0;
1082 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
1083 ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
1084 if (!size) break;
1085 read_size += size;
1086
1087 if (read_size <= 32)
1088 ok(!memcmp(buffer, data_start, sizeof(data_start)-1), "not expected: %.32s\n", buffer);
1089 }
1090 ok(read_size >= available_size, "read_size = %u, available_size = %u\n", read_size, available_size);
1091
1092 cleanup:
1093 WinHttpCloseHandle(req);
1094 WinHttpCloseHandle(con);
1095 WinHttpCloseHandle(ses);
1096 }
1097
1098 static void test_request_parameter_defaults(void)
1099 {
1100 static const WCHAR empty[] = {0};
1101 HINTERNET ses, con, req;
1102 DWORD size, status, error;
1103 WCHAR *version;
1104 BOOL ret;
1105
1106 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1107 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1108
1109 con = WinHttpConnect(ses, test_winehq, 0, 0);
1110 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1111
1112 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1113 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1114
1115 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1116 error = GetLastError();
1117 if (!ret && (error == ERROR_WINHTTP_CANNOT_CONNECT || error == ERROR_WINHTTP_TIMEOUT))
1118 {
1119 skip("connection failed, skipping\n");
1120 goto done;
1121 }
1122 ok(ret, "failed to send request %u\n", GetLastError());
1123
1124 ret = WinHttpReceiveResponse(req, NULL);
1125 if (!ret && GetLastError() == ERROR_WINHTTP_INVALID_SERVER_RESPONSE) /* win2k */
1126 {
1127 win_skip("invalid response\n");
1128 goto done;
1129 }
1130 ok(ret, "failed to receive response %u\n", GetLastError());
1131
1132 status = 0xdeadbeef;
1133 size = sizeof(status);
1134 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1135 ok(ret, "failed unexpectedly %u\n", GetLastError());
1136 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1137
1138 WinHttpCloseHandle(req);
1139
1140 req = WinHttpOpenRequest(con, empty, empty, empty, NULL, NULL, 0);
1141 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1142
1143 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1144 error = GetLastError();
1145 if (!ret && (error == ERROR_WINHTTP_CANNOT_CONNECT || error == ERROR_WINHTTP_TIMEOUT))
1146 {
1147 skip("connection failed, skipping\n");
1148 goto done;
1149 }
1150 ok(ret, "failed to send request %u\n", GetLastError());
1151
1152 ret = WinHttpReceiveResponse(req, NULL);
1153 ok(ret, "failed to receive response %u\n", GetLastError());
1154
1155 size = 0;
1156 SetLastError(0xdeadbeef);
1157 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, NULL, &size, NULL);
1158 error = GetLastError();
1159 ok(!ret, "succeeded unexpectedly\n");
1160 ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error);
1161
1162 version = HeapAlloc(GetProcessHeap(), 0, size);
1163 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, version, &size, NULL);
1164 ok(ret, "failed unexpectedly %u\n", GetLastError());
1165 ok(lstrlenW(version) == size / sizeof(WCHAR), "unexpected size %u\n", size);
1166 HeapFree(GetProcessHeap(), 0, version);
1167
1168 status = 0xdeadbeef;
1169 size = sizeof(status);
1170 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1171 ok(ret, "failed unexpectedly %u\n", GetLastError());
1172 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1173
1174 done:
1175 WinHttpCloseHandle(req);
1176 WinHttpCloseHandle(con);
1177 WinHttpCloseHandle(ses);
1178 }
1179
1180 static const WCHAR Connections[] = {
1181 'S','o','f','t','w','a','r','e','\\',
1182 'M','i','c','r','o','s','o','f','t','\\',
1183 'W','i','n','d','o','w','s','\\',
1184 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1185 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
1186 'C','o','n','n','e','c','t','i','o','n','s',0 };
1187 static const WCHAR WinHttpSettings[] = {
1188 'W','i','n','H','t','t','p','S','e','t','t','i','n','g','s',0 };
1189
1190 static DWORD get_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD *type )
1191 {
1192 LONG l;
1193 HKEY key;
1194 DWORD ret = 0;
1195
1196 l = RegOpenKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, KEY_READ, &key );
1197 if (!l)
1198 {
1199 DWORD size = 0;
1200
1201 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, NULL, &size );
1202 if (!l)
1203 {
1204 if (size <= len)
1205 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, buf,
1206 &size );
1207 if (!l)
1208 ret = size;
1209 }
1210 RegCloseKey( key );
1211 }
1212 return ret;
1213 }
1214
1215 static void set_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD type )
1216 {
1217 LONG l;
1218 HKEY key;
1219
1220 l = RegCreateKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, NULL, 0,
1221 KEY_WRITE, NULL, &key, NULL );
1222 if (!l)
1223 {
1224 if (len)
1225 RegSetValueExW( key, WinHttpSettings, 0, type, buf, len );
1226 else
1227 RegDeleteValueW( key, WinHttpSettings );
1228 RegCloseKey( key );
1229 }
1230 }
1231
1232 static void test_set_default_proxy_config(void)
1233 {
1234 static WCHAR wideString[] = { 0x226f, 0x575b, 0 };
1235 static WCHAR normalString[] = { 'f','o','o',0 };
1236 DWORD type, len;
1237 BYTE *saved_proxy_settings = NULL;
1238 WINHTTP_PROXY_INFO info;
1239 BOOL ret;
1240
1241 /* FIXME: it would be simpler to read the current settings using
1242 * WinHttpGetDefaultProxyConfiguration and save them using
1243 * WinHttpSetDefaultProxyConfiguration, but they appear to have a bug.
1244 *
1245 * If a proxy is configured in the registry, e.g. via 'proxcfg -p "foo"',
1246 * the access type reported by WinHttpGetDefaultProxyConfiguration is 1,
1247 * WINHTTP_ACCESS_TYPE_NO_PROXY, whereas it should be
1248 * WINHTTP_ACCESS_TYPE_NAMED_PROXY.
1249 * If WinHttpSetDefaultProxyConfiguration is called with dwAccessType = 1,
1250 * the lpszProxy and lpszProxyBypass values are ignored.
1251 * Thus, if a proxy is set with proxycfg, then calling
1252 * WinHttpGetDefaultProxyConfiguration followed by
1253 * WinHttpSetDefaultProxyConfiguration results in the proxy settings
1254 * getting deleted from the registry.
1255 *
1256 * Instead I read the current registry value and restore it directly.
1257 */
1258 len = get_default_proxy_reg_value( NULL, 0, &type );
1259 if (len)
1260 {
1261 saved_proxy_settings = HeapAlloc( GetProcessHeap(), 0, len );
1262 len = get_default_proxy_reg_value( saved_proxy_settings, len, &type );
1263 }
1264
1265 if (0)
1266 {
1267 /* Crashes on Vista and higher */
1268 SetLastError(0xdeadbeef);
1269 ret = WinHttpSetDefaultProxyConfiguration(NULL);
1270 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1271 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1272 }
1273
1274 /* test with invalid access type */
1275 info.dwAccessType = 0xdeadbeef;
1276 info.lpszProxy = info.lpszProxyBypass = NULL;
1277 SetLastError(0xdeadbeef);
1278 ret = WinHttpSetDefaultProxyConfiguration(&info);
1279 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1280 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1281
1282 /* at a minimum, the proxy server must be set */
1283 info.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
1284 info.lpszProxy = info.lpszProxyBypass = NULL;
1285 SetLastError(0xdeadbeef);
1286 ret = WinHttpSetDefaultProxyConfiguration(&info);
1287 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1288 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1289 info.lpszProxyBypass = normalString;
1290 SetLastError(0xdeadbeef);
1291 ret = WinHttpSetDefaultProxyConfiguration(&info);
1292 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1293 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1294
1295 /* the proxy server can't have wide characters */
1296 info.lpszProxy = wideString;
1297 SetLastError(0xdeadbeef);
1298 ret = WinHttpSetDefaultProxyConfiguration(&info);
1299 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1300 skip("couldn't set default proxy configuration: access denied\n");
1301 else
1302 ok((!ret && GetLastError() == ERROR_INVALID_PARAMETER) ||
1303 broken(ret), /* Earlier winhttp versions on W2K/XP */
1304 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1305
1306 info.lpszProxy = normalString;
1307 SetLastError(0xdeadbeef);
1308 ret = WinHttpSetDefaultProxyConfiguration(&info);
1309 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1310 skip("couldn't set default proxy configuration: access denied\n");
1311 else
1312 {
1313 ok(ret, "WinHttpSetDefaultProxyConfiguration failed: %u\n", GetLastError());
1314 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
1315 "got %u\n", GetLastError());
1316 }
1317 set_default_proxy_reg_value( saved_proxy_settings, len, type );
1318 }
1319
1320 static void test_Timeouts (void)
1321 {
1322 BOOL ret;
1323 DWORD value, size;
1324 HINTERNET ses, req, con;
1325
1326 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1327 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1328
1329 SetLastError(0xdeadbeef);
1330 ret = WinHttpSetTimeouts(ses, -2, 0, 0, 0);
1331 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1332 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1333
1334 SetLastError(0xdeadbeef);
1335 ret = WinHttpSetTimeouts(ses, 0, -2, 0, 0);
1336 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1337 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1338
1339 SetLastError(0xdeadbeef);
1340 ret = WinHttpSetTimeouts(ses, 0, 0, -2, 0);
1341 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1342 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1343
1344 SetLastError(0xdeadbeef);
1345 ret = WinHttpSetTimeouts(ses, 0, 0, 0, -2);
1346 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1347 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1348
1349 SetLastError(0xdeadbeef);
1350 ret = WinHttpSetTimeouts(ses, -1, -1, -1, -1);
1351 ok(ret, "%u\n", GetLastError());
1352 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
1353 "expected ERROR_SUCCESS, got %u\n", GetLastError());
1354
1355 SetLastError(0xdeadbeef);
1356 ret = WinHttpSetTimeouts(ses, 0, 0, 0, 0);
1357 ok(ret, "%u\n", GetLastError());
1358
1359 SetLastError(0xdeadbeef);
1360 ret = WinHttpSetTimeouts(ses, 0x0123, 0x4567, 0x89ab, 0xcdef);
1361 ok(ret, "%u\n", GetLastError());
1362
1363 SetLastError(0xdeadbeef);
1364 value = 0xdeadbeef;
1365 size = sizeof(DWORD);
1366 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1367 ok(ret, "%u\n", GetLastError());
1368 ok(value == 0x0123, "Expected 0x0123, got %u\n", value);
1369
1370 SetLastError(0xdeadbeef);
1371 value = 0xdeadbeef;
1372 size = sizeof(DWORD);
1373 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1374 ok(ret, "%u\n", GetLastError());
1375 ok(value == 0x4567, "Expected 0x4567, got %u\n", value);
1376
1377 SetLastError(0xdeadbeef);
1378 value = 0xdeadbeef;
1379 size = sizeof(DWORD);
1380 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1381 ok(ret, "%u\n", GetLastError());
1382 ok(value == 0x89ab, "Expected 0x89ab, got %u\n", value);
1383
1384 SetLastError(0xdeadbeef);
1385 value = 0xdeadbeef;
1386 size = sizeof(DWORD);
1387 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1388 ok(ret, "%u\n", GetLastError());
1389 ok(value == 0xcdef, "Expected 0xcdef, got %u\n", value);
1390
1391 SetLastError(0xdeadbeef);
1392 value = 0;
1393 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1394 ok(ret, "%u\n", GetLastError());
1395
1396 SetLastError(0xdeadbeef);
1397 value = 0xdeadbeef;
1398 size = sizeof(DWORD);
1399 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1400 ok(ret, "%u\n", GetLastError());
1401 ok(value == 0, "Expected 0, got %u\n", value);
1402
1403 SetLastError(0xdeadbeef);
1404 value = 0;
1405 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1406 ok(ret, "%u\n", GetLastError());
1407
1408 SetLastError(0xdeadbeef);
1409 value = 0xdeadbeef;
1410 size = sizeof(DWORD);
1411 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1412 ok(ret, "%u\n", GetLastError());
1413 ok(value == 0, "Expected 0, got %u\n", value);
1414
1415 SetLastError(0xdeadbeef);
1416 value = 0;
1417 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1418 ok(ret, "%u\n", GetLastError());
1419
1420 SetLastError(0xdeadbeef);
1421 value = 0xdeadbeef;
1422 size = sizeof(DWORD);
1423 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1424 ok(ret, "%u\n", GetLastError());
1425 ok(value == 0, "Expected 0, got %u\n", value);
1426
1427 SetLastError(0xdeadbeef);
1428 value = 0;
1429 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1430 ok(ret, "%u\n", GetLastError());
1431
1432 SetLastError(0xdeadbeef);
1433 value = 0xdeadbeef;
1434 size = sizeof(DWORD);
1435 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1436 ok(ret, "%u\n", GetLastError());
1437 ok(value == 0, "Expected 0, got %u\n", value);
1438
1439 SetLastError(0xdeadbeef);
1440 value = 0xbeefdead;
1441 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1442 ok(ret, "%u\n", GetLastError());
1443
1444 SetLastError(0xdeadbeef);
1445 value = 0xdeadbeef;
1446 size = sizeof(DWORD);
1447 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1448 ok(ret, "%u\n", GetLastError());
1449 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1450
1451 SetLastError(0xdeadbeef);
1452 value = 0xbeefdead;
1453 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1454 ok(ret, "%u\n", GetLastError());
1455
1456 SetLastError(0xdeadbeef);
1457 value = 0xdeadbeef;
1458 size = sizeof(DWORD);
1459 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1460 ok(ret, "%u\n", GetLastError());
1461 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1462
1463 SetLastError(0xdeadbeef);
1464 value = 0xbeefdead;
1465 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1466 ok(ret, "%u\n", GetLastError());
1467
1468 SetLastError(0xdeadbeef);
1469 value = 0xdeadbeef;
1470 size = sizeof(DWORD);
1471 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1472 ok(ret, "%u\n", GetLastError());
1473 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1474
1475 SetLastError(0xdeadbeef);
1476 value = 0xbeefdead;
1477 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1478 ok(ret, "%u\n", GetLastError());
1479
1480 SetLastError(0xdeadbeef);
1481 value = 0xdeadbeef;
1482 size = sizeof(DWORD);
1483 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1484 ok(ret, "%u\n", GetLastError());
1485 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1486
1487 con = WinHttpConnect(ses, test_winehq, 0, 0);
1488 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1489
1490 /* Timeout values should match the last one set for session */
1491 SetLastError(0xdeadbeef);
1492 value = 0xdeadbeef;
1493 size = sizeof(DWORD);
1494 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1495 ok(ret, "%u\n", GetLastError());
1496 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1497
1498 SetLastError(0xdeadbeef);
1499 value = 0xdeadbeef;
1500 size = sizeof(DWORD);
1501 ret = WinHttpQueryOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1502 ok(ret, "%u\n", GetLastError());
1503 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1504
1505 SetLastError(0xdeadbeef);
1506 value = 0xdeadbeef;
1507 size = sizeof(DWORD);
1508 ret = WinHttpQueryOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1509 ok(ret, "%u\n", GetLastError());
1510 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1511
1512 SetLastError(0xdeadbeef);
1513 value = 0xdeadbeef;
1514 size = sizeof(DWORD);
1515 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1516 ok(ret, "%u\n", GetLastError());
1517 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1518
1519 SetLastError(0xdeadbeef);
1520 ret = WinHttpSetTimeouts(con, -2, 0, 0, 0);
1521 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1522 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1523
1524 SetLastError(0xdeadbeef);
1525 ret = WinHttpSetTimeouts(con, 0, -2, 0, 0);
1526 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1527 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1528
1529 SetLastError(0xdeadbeef);
1530 ret = WinHttpSetTimeouts(con, 0, 0, -2, 0);
1531 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1532 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1533
1534 SetLastError(0xdeadbeef);
1535 ret = WinHttpSetTimeouts(con, 0, 0, 0, -2);
1536 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1537 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1538
1539 SetLastError(0xdeadbeef);
1540 ret = WinHttpSetTimeouts(con, -1, -1, -1, -1);
1541 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1542 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1543
1544 SetLastError(0xdeadbeef);
1545 ret = WinHttpSetTimeouts(con, 0, 0, 0, 0);
1546 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1547 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1548
1549 SetLastError(0xdeadbeef);
1550 value = 0;
1551 ret = WinHttpSetOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1552 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1553 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1554
1555 SetLastError(0xdeadbeef);
1556 value = 0;
1557 ret = WinHttpSetOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1558 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1559 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1560
1561 SetLastError(0xdeadbeef);
1562 value = 0;
1563 ret = WinHttpSetOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1564 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1565 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1566
1567 SetLastError(0xdeadbeef);
1568 value = 0;
1569 ret = WinHttpSetOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1570 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1571 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1572
1573 /* Changing timeout values for session should affect the values for connection */
1574 SetLastError(0xdeadbeef);
1575 value = 0xdead;
1576 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1577 ok(ret, "%u\n", GetLastError());
1578
1579 SetLastError(0xdeadbeef);
1580 value = 0xdeadbeef;
1581 size = sizeof(DWORD);
1582 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1583 ok(ret, "%u\n", GetLastError());
1584 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1585
1586 SetLastError(0xdeadbeef);
1587 value = 0xdead;
1588 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1589 ok(ret, "%u\n", GetLastError());
1590
1591 SetLastError(0xdeadbeef);
1592 value = 0xdeadbeef;
1593 size = sizeof(DWORD);
1594 ret = WinHttpQueryOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1595 ok(ret, "%u\n", GetLastError());
1596 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1597
1598 SetLastError(0xdeadbeef);
1599 value = 0xdead;
1600 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1601 ok(ret, "%u\n", GetLastError());
1602
1603 SetLastError(0xdeadbeef);
1604 value = 0xdeadbeef;
1605 size = sizeof(DWORD);
1606 ret = WinHttpQueryOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1607 ok(ret, "%u\n", GetLastError());
1608 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1609
1610 SetLastError(0xdeadbeef);
1611 value = 0xdead;
1612 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1613 ok(ret, "%u\n", GetLastError());
1614
1615 SetLastError(0xdeadbeef);
1616 value = 0xdeadbeef;
1617 size = sizeof(DWORD);
1618 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1619 ok(ret, "%u\n", GetLastError());
1620 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1621
1622 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1623 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1624
1625 /* Timeout values should match the last one set for session */
1626 SetLastError(0xdeadbeef);
1627 value = 0xdeadbeef;
1628 size = sizeof(DWORD);
1629 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1630 ok(ret, "%u\n", GetLastError());
1631 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1632
1633 SetLastError(0xdeadbeef);
1634 value = 0xdeadbeef;
1635 size = sizeof(DWORD);
1636 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1637 ok(ret, "%u\n", GetLastError());
1638 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1639
1640 SetLastError(0xdeadbeef);
1641 value = 0xdeadbeef;
1642 size = sizeof(DWORD);
1643 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1644 ok(ret, "%u\n", GetLastError());
1645 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1646
1647 SetLastError(0xdeadbeef);
1648 value = 0xdeadbeef;
1649 size = sizeof(DWORD);
1650 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1651 ok(ret, "%u\n", GetLastError());
1652 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1653
1654 SetLastError(0xdeadbeef);
1655 ret = WinHttpSetTimeouts(req, -2, 0, 0, 0);
1656 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1657 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1658
1659 SetLastError(0xdeadbeef);
1660 ret = WinHttpSetTimeouts(req, 0, -2, 0, 0);
1661 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1662 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1663
1664 SetLastError(0xdeadbeef);
1665 ret = WinHttpSetTimeouts(req, 0, 0, -2, 0);
1666 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1667 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1668
1669 SetLastError(0xdeadbeef);
1670 ret = WinHttpSetTimeouts(req, 0, 0, 0, -2);
1671 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1672 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1673
1674 SetLastError(0xdeadbeef);
1675 ret = WinHttpSetTimeouts(req, -1, -1, -1, -1);
1676 ok(ret, "%u\n", GetLastError());
1677
1678 SetLastError(0xdeadbeef);
1679 ret = WinHttpSetTimeouts(req, 0, 0, 0, 0);
1680 ok(ret, "%u\n", GetLastError());
1681
1682 SetLastError(0xdeadbeef);
1683 ret = WinHttpSetTimeouts(req, 0xcdef, 0x89ab, 0x4567, 0x0123);
1684 ok(ret, "%u\n", GetLastError());
1685
1686 SetLastError(0xdeadbeef);
1687 value = 0xdeadbeef;
1688 size = sizeof(DWORD);
1689 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1690 ok(ret, "%u\n", GetLastError());
1691 ok(value == 0xcdef, "Expected 0xcdef, got %u\n", value);
1692
1693 SetLastError(0xdeadbeef);
1694 value = 0xdeadbeef;
1695 size = sizeof(DWORD);
1696 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1697 ok(ret, "%u\n", GetLastError());
1698 ok(value == 0x89ab, "Expected 0x89ab, got %u\n", value);
1699
1700 SetLastError(0xdeadbeef);
1701 value = 0xdeadbeef;
1702 size = sizeof(DWORD);
1703 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1704 ok(ret, "%u\n", GetLastError());
1705 ok(value == 0x4567, "Expected 0x4567, got %u\n", value);
1706
1707 SetLastError(0xdeadbeef);
1708 value = 0xdeadbeef;
1709 size = sizeof(DWORD);
1710 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1711 ok(ret, "%u\n", GetLastError());
1712 ok(value == 0x0123, "Expected 0x0123, got %u\n", value);
1713
1714 SetLastError(0xdeadbeef);
1715 value = 0;
1716 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1717 ok(ret, "%u\n", GetLastError());
1718
1719 SetLastError(0xdeadbeef);
1720 value = 0xdeadbeef;
1721 size = sizeof(DWORD);
1722 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1723 ok(ret, "%u\n", GetLastError());
1724 ok(value == 0, "Expected 0, got %u\n", value);
1725
1726 SetLastError(0xdeadbeef);
1727 value = 0;
1728 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1729 ok(ret, "%u\n", GetLastError());
1730
1731 SetLastError(0xdeadbeef);
1732 value = 0xdeadbeef;
1733 size = sizeof(DWORD);
1734 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1735 ok(ret, "%u\n", GetLastError());
1736 ok(value == 0, "Expected 0, got %u\n", value);
1737
1738 SetLastError(0xdeadbeef);
1739 value = 0;
1740 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1741 ok(ret, "%u\n", GetLastError());
1742
1743 SetLastError(0xdeadbeef);
1744 value = 0xdeadbeef;
1745 size = sizeof(DWORD);
1746 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1747 ok(ret, "%u\n", GetLastError());
1748 ok(value == 0, "Expected 0, got %u\n", value);
1749
1750 SetLastError(0xdeadbeef);
1751 value = 0;
1752 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1753 ok(ret, "%u\n", GetLastError());
1754
1755 SetLastError(0xdeadbeef);
1756 value = 0xdeadbeef;
1757 size = sizeof(DWORD);
1758 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1759 ok(ret, "%u\n", GetLastError());
1760 ok(value == 0, "Expected 0, got %u\n", value);
1761
1762 SetLastError(0xdeadbeef);
1763 value = 0xbeefdead;
1764 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1765 ok(ret, "%u\n", GetLastError());
1766
1767 SetLastError(0xdeadbeef);
1768 value = 0xdeadbeef;
1769 size = sizeof(DWORD);
1770 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1771 ok(ret, "%u\n", GetLastError());
1772 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1773
1774 SetLastError(0xdeadbeef);
1775 value = 0xbeefdead;
1776 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1777 ok(ret, "%u\n", GetLastError());
1778
1779 SetLastError(0xdeadbeef);
1780 value = 0xdeadbeef;
1781 size = sizeof(DWORD);
1782 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1783 ok(ret, "%u\n", GetLastError());
1784 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1785
1786 SetLastError(0xdeadbeef);
1787 value = 0xbeefdead;
1788 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1789 ok(ret, "%u\n", GetLastError());
1790
1791 SetLastError(0xdeadbeef);
1792 value = 0xdeadbeef;
1793 size = sizeof(DWORD);
1794 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1795 ok(ret, "%u\n", GetLastError());
1796 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1797
1798 SetLastError(0xdeadbeef);
1799 value = 0xbeefdead;
1800 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1801 ok(ret, "%u\n", GetLastError());
1802
1803 SetLastError(0xdeadbeef);
1804 value = 0xdeadbeef;
1805 size = sizeof(DWORD);
1806 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1807 ok(ret, "%u\n", GetLastError());
1808 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1809
1810 /* Changing timeout values for session should not affect the values for a request,
1811 * neither should the other way around.
1812 */
1813 SetLastError(0xdeadbeef);
1814 value = 0xbeefdead;
1815 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1816 ok(ret, "%u\n", GetLastError());
1817
1818 SetLastError(0xdeadbeef);
1819 value = 0xdeadbeef;
1820 size = sizeof(DWORD);
1821 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1822 ok(ret, "%u\n", GetLastError());
1823 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1824
1825 SetLastError(0xdeadbeef);
1826 value = 0xbeefdead;
1827 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1828 ok(ret, "%u\n", GetLastError());
1829
1830 SetLastError(0xdeadbeef);
1831 value = 0xdeadbeef;
1832 size = sizeof(DWORD);
1833 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1834 ok(ret, "%u\n", GetLastError());
1835 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1836
1837 SetLastError(0xdeadbeef);
1838 value = 0xbeefdead;
1839 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1840 ok(ret, "%u\n", GetLastError());
1841
1842 SetLastError(0xdeadbeef);
1843 value = 0xdeadbeef;
1844 size = sizeof(DWORD);
1845 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1846 ok(ret, "%u\n", GetLastError());
1847 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1848
1849 SetLastError(0xdeadbeef);
1850 value = 0xbeefdead;
1851 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1852 ok(ret, "%u\n", GetLastError());
1853
1854 SetLastError(0xdeadbeef);
1855 value = 0xdeadbeef;
1856 size = sizeof(DWORD);
1857 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1858 ok(ret, "%u\n", GetLastError());
1859 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1860
1861 SetLastError(0xdeadbeef);
1862 value = 0xbeef;
1863 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1864 ok(ret, "%u\n", GetLastError());
1865
1866 SetLastError(0xdeadbeef);
1867 value = 0xdeadbeef;
1868 size = sizeof(DWORD);
1869 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1870 ok(ret, "%u\n", GetLastError());
1871 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1872
1873 SetLastError(0xdeadbeef);
1874 value = 0xbeef;
1875 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1876 ok(ret, "%u\n", GetLastError());
1877
1878 SetLastError(0xdeadbeef);
1879 value = 0xdeadbeef;
1880 size = sizeof(DWORD);
1881 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1882 ok(ret, "%u\n", GetLastError());
1883 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1884
1885 SetLastError(0xdeadbeef);
1886 value = 0xbeef;
1887 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1888 ok(ret, "%u\n", GetLastError());
1889
1890 SetLastError(0xdeadbeef);
1891 value = 0xdeadbeef;
1892 size = sizeof(DWORD);
1893 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1894 ok(ret, "%u\n", GetLastError());
1895 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1896
1897 SetLastError(0xdeadbeef);
1898 value = 0xbeef;
1899 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1900 ok(ret, "%u\n", GetLastError());
1901
1902 SetLastError(0xdeadbeef);
1903 value = 0xdeadbeef;
1904 size = sizeof(DWORD);
1905 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1906 ok(ret, "%u\n", GetLastError());
1907 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1908
1909 WinHttpCloseHandle(req);
1910 WinHttpCloseHandle(con);
1911 WinHttpCloseHandle(ses);
1912 }
1913
1914 static void test_resolve_timeout(void)
1915 {
1916 static const WCHAR nxdomain[] =
1917 {'n','x','d','o','m','a','i','n','.','w','i','n','e','h','q','.','o','r','g',0};
1918 HINTERNET ses, con, req;
1919 DWORD timeout;
1920 BOOL ret;
1921
1922 if (! proxy_active())
1923 {
1924 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1925 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1926
1927 timeout = 10000;
1928 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
1929 ok(ret, "failed to set resolve timeout %u\n", GetLastError());
1930
1931 con = WinHttpConnect(ses, nxdomain, 0, 0);
1932 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1933
1934 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1935 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1936
1937 SetLastError(0xdeadbeef);
1938 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1939 if (ret)
1940 {
1941 skip("nxdomain returned success. Broken ISP redirects?\n");
1942 goto done;
1943 }
1944 ok(GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED,
1945 "expected ERROR_WINHTTP_NAME_NOT_RESOLVED got %u\n", GetLastError());
1946
1947 WinHttpCloseHandle(req);
1948 WinHttpCloseHandle(con);
1949 WinHttpCloseHandle(ses);
1950 }
1951 else
1952 skip("Skipping host resolution tests, host resolution preformed by proxy\n");
1953
1954 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1955 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1956
1957 timeout = 10000;
1958 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
1959 ok(ret, "failed to set resolve timeout %u\n", GetLastError());
1960
1961 con = WinHttpConnect(ses, test_winehq, 0, 0);
1962 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1963
1964 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1965 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1966
1967 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1968 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
1969 {
1970 skip("connection failed, skipping\n");
1971 goto done;
1972 }
1973 ok(ret, "failed to send request\n");
1974
1975 done:
1976 WinHttpCloseHandle(req);
1977 WinHttpCloseHandle(con);
1978 WinHttpCloseHandle(ses);
1979 }
1980
1981 static const char page1[] =
1982 "<HTML>\r\n"
1983 "<HEAD><TITLE>winhttp test page</TITLE></HEAD>\r\n"
1984 "<BODY>The quick brown fox jumped over the lazy dog<P></BODY>\r\n"
1985 "</HTML>\r\n\r\n";
1986
1987 static const char okmsg[] =
1988 "HTTP/1.1 200 OK\r\n"
1989 "Server: winetest\r\n"
1990 "\r\n";
1991
1992 static const char notokmsg[] =
1993 "HTTP/1.1 400 Bad Request\r\n"
1994 "\r\n";
1995
1996 static const char cookiemsg[] =
1997 "HTTP/1.1 200 OK\r\n"
1998 "Set-Cookie: name = value \r\n"
1999 "Set-Cookie: NAME = value \r\n"
2000 "\r\n";
2001
2002 static const char nocontentmsg[] =
2003 "HTTP/1.1 204 No Content\r\n"
2004 "Server: winetest\r\n"
2005 "\r\n";
2006
2007 static const char notmodified[] =
2008 "HTTP/1.1 304 Not Modified\r\n"
2009 "\r\n";
2010
2011 static const char noauthmsg[] =
2012 "HTTP/1.1 401 Unauthorized\r\n"
2013 "Server: winetest\r\n"
2014 "Connection: close\r\n"
2015 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
2016 "Content-Length: 12\r\n"
2017 "Content-Type: text/plain\r\n"
2018 "\r\n";
2019
2020 static const char okauthmsg[] =
2021 "HTTP/1.1 200 OK\r\n"
2022 "Server: winetest\r\n"
2023 "Connection: close\r\n"
2024 "Content-Length: 11\r\n"
2025 "Content-Type: text/plain\r\n"
2026 "\r\n";
2027
2028 static const char headmsg[] =
2029 "HTTP/1.1 200 OK\r\n"
2030 "Content-Length: 100\r\n"
2031 "\r\n";
2032
2033 static const char unauthorized[] = "Unauthorized";
2034 static const char hello_world[] = "Hello World";
2035
2036 struct server_info
2037 {
2038 HANDLE event;
2039 int port;
2040 };
2041
2042 #define BIG_BUFFER_LEN 0x2250
2043
2044 static DWORD CALLBACK server_thread(LPVOID param)
2045 {
2046 struct server_info *si = param;
2047 int r, c = -1, i, on;
2048 SOCKET s;
2049 struct sockaddr_in sa;
2050 char buffer[0x100];
2051 WSADATA wsaData;
2052 int last_request = 0;
2053
2054 WSAStartup(MAKEWORD(1,1), &wsaData);
2055
2056 s = socket(AF_INET, SOCK_STREAM, 0);
2057 if (s == INVALID_SOCKET)
2058 return 1;
2059
2060 on = 1;
2061 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof on);
2062
2063 memset(&sa, 0, sizeof sa);
2064 sa.sin_family = AF_INET;
2065 sa.sin_port = htons(si->port);
2066 sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
2067
2068 r = bind(s, (struct sockaddr *)&sa, sizeof(sa));
2069 if (r < 0)
2070 return 1;
2071
2072 listen(s, 0);
2073 SetEvent(si->event);
2074 do
2075 {
2076 if (c == -1) c = accept(s, NULL, NULL);
2077
2078 memset(buffer, 0, sizeof buffer);
2079 for(i = 0; i < sizeof buffer - 1; i++)
2080 {
2081 r = recv(c, &buffer[i], 1, 0);
2082 if (r != 1)
2083 break;
2084 if (i < 4) continue;
2085 if (buffer[i - 2] == '\n' && buffer[i] == '\n' &&
2086 buffer[i - 3] == '\r' && buffer[i - 1] == '\r')
2087 break;
2088 }
2089 if (strstr(buffer, "GET /basic"))
2090 {
2091 send(c, okmsg, sizeof okmsg - 1, 0);
2092 send(c, page1, sizeof page1 - 1, 0);
2093 }
2094 if (strstr(buffer, "/auth"))
2095 {
2096 if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
2097 {
2098 send(c, okauthmsg, sizeof okauthmsg - 1, 0);
2099 send(c, hello_world, sizeof hello_world - 1, 0);
2100 }
2101 else
2102 {
2103 send(c, noauthmsg, sizeof noauthmsg - 1, 0);
2104 send(c, unauthorized, sizeof unauthorized - 1, 0);
2105 }
2106 continue;
2107 }
2108 if (strstr(buffer, "/big"))
2109 {
2110 char msg[BIG_BUFFER_LEN];
2111 memset(msg, 'm', sizeof(msg));
2112 send(c, okmsg, sizeof(okmsg) - 1, 0);
2113 send(c, msg, sizeof(msg), 0);
2114 }
2115 if (strstr(buffer, "/no_headers"))
2116 {
2117 send(c, page1, sizeof page1 - 1, 0);
2118 }
2119 if (strstr(buffer, "GET /no_content"))
2120 {
2121 send(c, nocontentmsg, sizeof nocontentmsg - 1, 0);
2122 continue;
2123 }
2124 if (strstr(buffer, "GET /not_modified"))
2125 {
2126 if (strstr(buffer, "If-Modified-Since:")) send(c, notmodified, sizeof notmodified - 1, 0);
2127 else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2128 continue;
2129 }
2130 if (strstr(buffer, "HEAD /head"))
2131 {
2132 send(c, headmsg, sizeof headmsg - 1, 0);
2133 continue;
2134 }
2135 if (strstr(buffer, "GET /cookie3"))
2136 {
2137 if (strstr(buffer, "Cookie: name=value2; NAME=value; name=value\r\n") ||
2138 broken(strstr(buffer, "Cookie: name=value2; name=value; NAME=value\r\n") != NULL))
2139 send(c, okmsg, sizeof(okmsg) - 1, 0);
2140 else
2141 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2142 }
2143 if (strstr(buffer, "GET /cookie2"))
2144 {
2145 if (strstr(buffer, "Cookie: NAME=value; name=value\r\n") ||
2146 broken(strstr(buffer, "Cookie: name=value; NAME=value\r\n") != NULL))
2147 send(c, okmsg, sizeof(okmsg) - 1, 0);
2148 else
2149 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2150 }
2151 else if (strstr(buffer, "GET /cookie"))
2152 {
2153 if (!strstr(buffer, "Cookie: name=value\r\n")) send(c, cookiemsg, sizeof(cookiemsg) - 1, 0);
2154 else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2155 }
2156 if (strstr(buffer, "GET /quit"))
2157 {
2158 send(c, okmsg, sizeof okmsg - 1, 0);
2159 send(c, page1, sizeof page1 - 1, 0);
2160 last_request = 1;
2161 }
2162 shutdown(c, 2);
2163 closesocket(c);
2164 c = -1;
2165
2166 } while (!last_request);
2167
2168 closesocket(s);
2169 return 0;
2170 }
2171
2172 static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path)
2173 {
2174 static const WCHAR test_header_end_clrf[] = {'\r','\n','\r','\n',0};
2175 static const WCHAR test_header_end_raw[] = {0,0};
2176 HINTERNET ses, con, req;
2177 char buffer[0x100];
2178 WCHAR buffer2[0x100];
2179 DWORD count, status, size, error, supported, first, target;
2180 BOOL ret;
2181
2182 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2183 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2184
2185 con = WinHttpConnect(ses, localhostW, port, 0);
2186 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2187
2188 req = WinHttpOpenRequest(con, verb, path, NULL, NULL, NULL, 0);
2189 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2190
2191 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2192 ok(ret, "failed to send request %u\n", GetLastError());
2193
2194 ret = WinHttpReceiveResponse(req, NULL);
2195 ok(ret, "failed to receive response %u\n", GetLastError());
2196
2197 status = 0xdeadbeef;
2198 size = sizeof(status);
2199 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2200 ok(ret, "failed to query status code %u\n", GetLastError());
2201 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2202
2203 supported = first = target = 0xdeadbeef;
2204 SetLastError(0xdeadbeef);
2205 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2206 error = GetLastError();
2207 ok(!ret, "unexpected success\n");
2208 todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
2209 ok(supported == 0xdeadbeef, "got %x\n", supported);
2210 ok(first == 0xdeadbeef, "got %x\n", first);
2211 ok(target == 0xdeadbeef, "got %x\n", target);
2212
2213 size = sizeof(buffer2);
2214 memset(buffer2, 0, sizeof(buffer2));
2215 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, buffer2, &size, NULL);
2216 ok(ret, "failed to query for raw headers: %u\n", GetLastError());
2217 ok(!memcmp(buffer2 + lstrlenW(buffer2) - 4, test_header_end_clrf, sizeof(test_header_end_clrf)),
2218 "WinHttpQueryHeaders returned invalid end of header string\n");
2219
2220 size = sizeof(buffer2);
2221 memset(buffer2, 0, sizeof(buffer2));
2222 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS, NULL, buffer2, &size, NULL);
2223 ok(ret, "failed to query for raw headers: %u\n", GetLastError());
2224 ok(!memcmp(buffer2 + (size / sizeof(WCHAR)) - 1, test_header_end_raw, sizeof(test_header_end_raw)),
2225 "WinHttpQueryHeaders returned invalid end of header string\n");
2226 ok(buffer2[(size / sizeof(WCHAR)) - 2] != 0, "returned string has too many NULL characters\n");
2227
2228 count = 0;
2229 memset(buffer, 0, sizeof(buffer));
2230 ret = WinHttpReadData(req, buffer, sizeof buffer, &count);
2231 ok(ret, "failed to read data %u\n", GetLastError());
2232 ok(count == sizeof page1 - 1, "count was wrong\n");
2233 ok(!memcmp(buffer, page1, sizeof page1), "http data wrong\n");
2234
2235 WinHttpCloseHandle(req);
2236 WinHttpCloseHandle(con);
2237 WinHttpCloseHandle(ses);
2238 }
2239
2240 static void test_basic_authentication(int port)
2241 {
2242 static const WCHAR authW[] = {'/','a','u','t','h',0};
2243 static WCHAR userW[] = {'u','s','e','r',0};
2244 static WCHAR passW[] = {'p','w','d',0};
2245 static WCHAR pass2W[] = {'p','w','d','2',0};
2246 HINTERNET ses, con, req;
2247 DWORD status, size, error, supported, first, target;
2248 char buffer[32];
2249 BOOL ret;
2250
2251 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2252 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2253
2254 con = WinHttpConnect(ses, localhostW, port, 0);
2255 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2256
2257 req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2258 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2259
2260 SetLastError(0xdeadbeef);
2261 ret = WinHttpQueryAuthSchemes(NULL, NULL, NULL, NULL);
2262 error = GetLastError();
2263 ok(!ret, "expected failure\n");
2264 ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
2265
2266 SetLastError(0xdeadbeef);
2267 ret = WinHttpQueryAuthSchemes(req, NULL, NULL, NULL);
2268 error = GetLastError();
2269 ok(!ret, "expected failure\n");
2270 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2271
2272 supported = 0xdeadbeef;
2273 SetLastError(0xdeadbeef);
2274 ret = WinHttpQueryAuthSchemes(req, &supported, NULL, NULL);
2275 error = GetLastError();
2276 ok(!ret, "expected failure\n");
2277 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2278 ok(supported == 0xdeadbeef, "got %x\n", supported);
2279
2280 supported = first = 0xdeadbeef;
2281 SetLastError(0xdeadbeef);
2282 ret = WinHttpQueryAuthSchemes(req, &supported, &first, NULL);
2283 error = GetLastError();
2284 ok(!ret, "expected failure\n");
2285 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2286 ok(supported == 0xdeadbeef, "got %x\n", supported);
2287 ok(first == 0xdeadbeef, "got %x\n", first);
2288
2289 supported = first = target = 0xdeadbeef;
2290 SetLastError(0xdeadbeef);
2291 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2292 error = GetLastError();
2293 ok(!ret, "expected failure\n");
2294 todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
2295 ok(supported == 0xdeadbeef, "got %x\n", supported);
2296 ok(first == 0xdeadbeef, "got %x\n", first);
2297 ok(target == 0xdeadbeef, "got %x\n", target);
2298
2299 supported = first = target = 0xdeadbeef;
2300 SetLastError(0xdeadbeef);
2301 ret = WinHttpQueryAuthSchemes(NULL, &supported, &first, &target);
2302 error = GetLastError();
2303 ok(!ret, "expected failure\n");
2304 ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
2305 ok(supported == 0xdeadbeef, "got %x\n", supported);
2306 ok(first == 0xdeadbeef, "got %x\n", first);
2307 ok(target == 0xdeadbeef, "got %x\n", target);
2308
2309 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2310 ok(ret, "failed to send request %u\n", GetLastError());
2311
2312 ret = WinHttpReceiveResponse(req, NULL);
2313 ok(ret, "failed to receive response %u\n", GetLastError());
2314
2315 status = 0xdeadbeef;
2316 size = sizeof(status);
2317 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2318 ok(ret, "failed to query status code %u\n", GetLastError());
2319 ok(status == HTTP_STATUS_DENIED, "request failed unexpectedly %u\n", status);
2320
2321 size = 0;
2322 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
2323 error = GetLastError();
2324 ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError());
2325 if (ret)
2326 {
2327 ok(size == 12, "expected 12, got %u\n", size);
2328 ok(!memcmp(buffer, unauthorized, 12), "got %s\n", buffer);
2329 }
2330
2331 supported = first = target = 0xdeadbeef;
2332 SetLastError(0xdeadbeef);
2333 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2334 error = GetLastError();
2335 ok(ret, "failed to query authentication schemes %u\n", error);
2336 ok(error == ERROR_SUCCESS || broken(error == 0xdeadbeef) /* < win7 */, "expected ERROR_SUCCESS, got %u\n", error);
2337 ok(supported == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", supported);
2338 ok(first == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", first);
2339 ok(target == WINHTTP_AUTH_TARGET_SERVER, "got %x\n", target);
2340
2341 SetLastError(0xdeadbeef);
2342 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NTLM, NULL, NULL, NULL);
2343 error = GetLastError();
2344 ok(ret, "failed to set credentials %u\n", error);
2345 ok(error == ERROR_SUCCESS || broken(error == 0xdeadbeef) /* < win7 */, "expected ERROR_SUCCESS, got %u\n", error);
2346
2347 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_PASSPORT, NULL, NULL, NULL);
2348 ok(ret, "failed to set credentials %u\n", GetLastError());
2349
2350 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NEGOTIATE, NULL, NULL, NULL);
2351 ok(ret, "failed to set credentials %u\n", GetLastError());
2352
2353 SetLastError(0xdeadbeef);
2354 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_DIGEST, NULL, NULL, NULL);
2355 error = GetLastError();
2356 ok(!ret, "expected failure\n");
2357 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2358
2359 SetLastError(0xdeadbeef);
2360 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, NULL, NULL);
2361 error = GetLastError();
2362 ok(!ret, "expected failure\n");
2363 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2364
2365 SetLastError(0xdeadbeef);
2366 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, NULL, NULL);
2367 error = GetLastError();
2368 ok(!ret, "expected failure\n");
2369 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2370
2371 SetLastError(0xdeadbeef);
2372 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, passW, NULL);
2373 error = GetLastError();
2374 ok(!ret, "expected failure\n");
2375 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2376
2377 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
2378 ok(ret, "failed to set credentials %u\n", GetLastError());
2379
2380 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2381 ok(ret, "failed to send request %u\n", GetLastError());
2382
2383 ret = WinHttpReceiveResponse(req, NULL);
2384 ok(ret, "failed to receive response %u\n", GetLastError());
2385
2386 status = 0xdeadbeef;
2387 size = sizeof(status);
2388 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2389 ok(ret, "failed to query status code %u\n", GetLastError());
2390 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2391
2392 size = 0;
2393 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
2394 error = GetLastError();
2395 ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError());
2396 if (ret)
2397 {
2398 ok(size == 11, "expected 11, got %u\n", size);
2399 ok(!memcmp(buffer, hello_world, 11), "got %s\n", buffer);
2400 }
2401
2402 WinHttpCloseHandle(req);
2403 WinHttpCloseHandle(con);
2404 WinHttpCloseHandle(ses);
2405
2406 /* credentials set with WinHttpSetCredentials take precedence over those set through options */
2407
2408 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2409 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2410
2411 con = WinHttpConnect(ses, localhostW, port, 0);
2412 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2413
2414 req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2415 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2416
2417 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
2418 ok(ret, "failed to set credentials %u\n", GetLastError());
2419
2420 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
2421 ok(ret, "failed to set username %u\n", GetLastError());
2422
2423 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, pass2W, lstrlenW(pass2W));
2424 ok(ret, "failed to set password %u\n", GetLastError());
2425
2426 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2427 ok(ret, "failed to send request %u\n", GetLastError());
2428
2429 ret = WinHttpReceiveResponse(req, NULL);
2430 ok(ret, "failed to receive response %u\n", GetLastError());
2431
2432 status = 0xdeadbeef;
2433 size = sizeof(status);
2434 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2435 ok(ret, "failed to query status code %u\n", GetLastError());
2436 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2437
2438 WinHttpCloseHandle(req);
2439 WinHttpCloseHandle(con);
2440 WinHttpCloseHandle(ses);
2441
2442 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2443 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2444
2445 con = WinHttpConnect(ses, localhostW, port, 0);
2446 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2447
2448 req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2449 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2450
2451 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
2452 ok(ret, "failed to set username %u\n", GetLastError());
2453
2454 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, passW, lstrlenW(passW));
2455 ok(ret, "failed to set password %u\n", GetLastError());
2456
2457 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, pass2W, NULL);
2458 ok(ret, "failed to set credentials %u\n", GetLastError());
2459
2460 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2461 ok(ret, "failed to send request %u\n", GetLastError());
2462
2463 ret = WinHttpReceiveResponse(req, NULL);
2464 ok(ret, "failed to receive response %u\n", GetLastError());
2465
2466 status = 0xdeadbeef;
2467 size = sizeof(status);
2468 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2469 ok(ret, "failed to query status code %u\n", GetLastError());
2470 ok(status == HTTP_STATUS_DENIED, "request failed unexpectedly %u\n", status);
2471
2472 WinHttpCloseHandle(req);
2473 WinHttpCloseHandle(con);
2474 WinHttpCloseHandle(ses);
2475 }
2476
2477 static void test_no_headers(int port)
2478 {
2479 static const WCHAR no_headersW[] = {'/','n','o','_','h','e','a','d','e','r','s',0};
2480 HINTERNET ses, con, req;
2481 DWORD error;
2482 BOOL ret;
2483
2484 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2485 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2486
2487 con = WinHttpConnect(ses, localhostW, port, 0);
2488 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2489
2490 req = WinHttpOpenRequest(con, NULL, no_headersW, NULL, NULL, NULL, 0);
2491 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2492
2493 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2494 if (!ret)
2495 {
2496 error = GetLastError();
2497 ok(error == ERROR_WINHTTP_INVALID_SERVER_RESPONSE, "got %u\n", error);
2498 }
2499 else
2500 {
2501 SetLastError(0xdeadbeef);
2502 ret = WinHttpReceiveResponse(req, NULL);
2503 error = GetLastError();
2504 ok(!ret, "expected failure\n");
2505 ok(error == ERROR_WINHTTP_INVALID_SERVER_RESPONSE, "got %u\n", error);
2506 }
2507
2508 WinHttpCloseHandle(req);
2509 WinHttpCloseHandle(con);
2510 WinHttpCloseHandle(ses);
2511 }
2512
2513 static void test_no_content(int port)
2514 {
2515 static const WCHAR no_contentW[] = {'/','n','o','_','c','o','n','t','e','n','t',0};
2516 HINTERNET ses, con, req;
2517 char buf[128];
2518 DWORD size, len = sizeof(buf), bytes_read, status;
2519 BOOL ret;
2520
2521 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2522 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2523
2524 con = WinHttpConnect(ses, localhostW, port, 0);
2525 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2526
2527 req = WinHttpOpenRequest(con, NULL, no_contentW, NULL, NULL, NULL, 0);
2528 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2529
2530 size = 12345;
2531 SetLastError(0xdeadbeef);
2532 ret = WinHttpQueryDataAvailable(req, &size);
2533 todo_wine {
2534 ok(!ret, "expected error\n");
2535 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_STATE,
2536 "expected ERROR_WINHTTP_INCORRECT_HANDLE_STATE, got 0x%08x\n", GetLastError());
2537 ok(size == 12345 || broken(size == 0) /* Win <= 2003 */,
2538 "expected 12345, got %u\n", size);
2539 }
2540
2541 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2542 ok(ret, "expected success\n");
2543
2544 ret = WinHttpReceiveResponse(req, NULL);
2545 ok(ret, "expected success\n");
2546
2547 status = 0xdeadbeef;
2548 size = sizeof(status);
2549 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
2550 NULL, &status, &size, NULL);
2551 ok(ret, "expected success\n");
2552 ok(status == HTTP_STATUS_NO_CONTENT, "expected status 204, got %d\n", status);
2553
2554 SetLastError(0xdeadbeef);
2555 size = sizeof(status);
2556 status = 12345;
2557 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
2558 NULL, &status, &size, 0);
2559 ok(!ret, "expected no content-length header\n");
2560 ok(GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND, "wrong error %u\n", GetLastError());
2561 ok(status == 12345, "expected 0, got %d\n", status);
2562
2563 SetLastError(0xdeadbeef);
2564 size = 12345;
2565 ret = WinHttpQueryDataAvailable(req, &size);
2566 ok(ret, "expected success\n");
2567 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
2568 "wrong error %u\n", GetLastError());
2569 ok(!size, "expected 0, got %u\n", size);
2570
2571 SetLastError(0xdeadbeef);
2572 ret = WinHttpReadData(req, buf, len, &bytes_read);
2573 ok(ret, "expected success\n");
2574 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
2575 "wrong error %u\n", GetLastError());
2576 ok(!bytes_read, "expected 0, got %u\n", bytes_read);
2577
2578 size = 12345;
2579 ret = WinHttpQueryDataAvailable(req, &size);
2580 ok(ret, "expected success\n");
2581 ok(size == 0, "expected 0, got %d\n", size);
2582
2583 WinHttpCloseHandle(req);
2584
2585 size = 12345;
2586 SetLastError(0xdeadbeef);
2587 ret = WinHttpQueryDataAvailable(req, &size);
2588 ok(!ret, "expected error\n");
2589 ok(GetLastError() == ERROR_INVALID_HANDLE,
2590 "expected ERROR_INVALID_HANDLE, got 0x%08x\n", GetLastError());
2591 ok(size == 12345, "expected 12345, got %u\n", size);
2592
2593 WinHttpCloseHandle(con);
2594 WinHttpCloseHandle(ses);
2595 }
2596
2597 static void test_head_request(int port)
2598 {
2599 static const WCHAR verbW[] = {'H','E','A','D',0};
2600 static const WCHAR headW[] = {'/','h','e','a','d',0};
2601 HINTERNET ses, con, req;
2602 char buf[128];
2603 DWORD size, len, count, status;
2604 BOOL ret;
2605
2606 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2607 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2608
2609 con = WinHttpConnect(ses, localhostW, port, 0);
2610 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2611
2612 req = WinHttpOpenRequest(con, verbW, headW, NULL, NULL, NULL, 0);
2613 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2614
2615 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2616 ok(ret, "failed to send request %u\n", GetLastError());
2617
2618 ret = WinHttpReceiveResponse(req, NULL);
2619 ok(ret, "failed to receive response %u\n", GetLastError());
2620
2621 status = 0xdeadbeef;
2622 size = sizeof(status);
2623 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
2624 NULL, &status, &size, NULL);
2625 ok(ret, "failed to get status code %u\n", GetLastError());
2626 ok(status == HTTP_STATUS_OK, "got %u\n", status);
2627
2628 len = 0xdeadbeef;
2629 size = sizeof(len);
2630 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
2631 NULL, &len, &size, 0);
2632 ok(ret, "failed to get content-length header %u\n", GetLastError());
2633 ok(len == HTTP_STATUS_CONTINUE, "got %u\n", len);
2634
2635 count = 0xdeadbeef;
2636 ret = WinHttpQueryDataAvailable(req, &count);
2637 ok(ret, "failed to query data available %u\n", GetLastError());
2638 ok(!count, "got %u\n", count);
2639
2640 len = sizeof(buf);
2641 count = 0xdeadbeef;
2642 ret = WinHttpReadData(req, buf, len, &count);
2643 ok(ret, "failed to read data %u\n", GetLastError());
2644 ok(!count, "got %u\n", count);
2645
2646 count = 0xdeadbeef;
2647 ret = WinHttpQueryDataAvailable(req, &count);
2648 ok(ret, "failed to query data available %u\n", GetLastError());
2649 ok(!count, "got %u\n", count);
2650
2651 WinHttpCloseHandle(req);
2652 WinHttpCloseHandle(con);
2653 WinHttpCloseHandle(ses);
2654 }
2655
2656 static void test_not_modified(int port)
2657 {
2658 static const WCHAR pathW[] = {'/','n','o','t','_','m','o','d','i','f','i','e','d',0};
2659 static const WCHAR ifmodifiedW[] = {'I','f','-','M','o','d','i','f','i','e','d','-','S','i','n','c','e',':',' '};
2660 static const WCHAR ifmodified2W[] = {'I','f','-','M','o','d','i','f','i','e','d','-','S','i','n','c','e',0};
2661 BOOL ret;
2662 HINTERNET session, request, connection;
2663 DWORD index, len, status, size, start = GetTickCount();
2664 SYSTEMTIME st;
2665 WCHAR today[(sizeof(ifmodifiedW) + WINHTTP_TIME_FORMAT_BUFSIZE)/sizeof(WCHAR) + 3], buffer[32];
2666
2667 memcpy(today, ifmodifiedW, sizeof(ifmodifiedW));
2668 GetSystemTime(&st);
2669 WinHttpTimeFromSystemTime(&st, &today[sizeof(ifmodifiedW)/sizeof(WCHAR)]);
2670
2671 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY,
2672 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
2673 ok(session != NULL, "WinHttpOpen failed: %u\n", GetLastError());
2674
2675 connection = WinHttpConnect(session, localhostW, port, 0);
2676 ok(connection != NULL, "WinHttpConnect failed: %u\n", GetLastError());
2677
2678 request = WinHttpOpenRequest(connection, NULL, pathW, NULL, WINHTTP_NO_REFERER,
2679 WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
2680 ok(request != NULL, "WinHttpOpenrequest failed: %u\n", GetLastError());
2681
2682 ret = WinHttpSendRequest(request, today, 0, NULL, 0, 0, 0);
2683 ok(ret, "WinHttpSendRequest failed: %u\n", GetLastError());
2684
2685 ret = WinHttpReceiveResponse(request, NULL);
2686 ok(ret, "WinHttpReceiveResponse failed: %u\n", GetLastError());
2687
2688 index = 0;
2689 len = sizeof(buffer);
2690 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
2691 ifmodified2W, buffer, &len, &index);
2692 ok(ret, "failed to get header %u\n", GetLastError());
2693
2694 status = 0xdeadbeef;
2695 size = sizeof(status);
2696 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER,
2697 NULL, &status, &size, NULL);
2698 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
2699 ok(status == HTTP_STATUS_NOT_MODIFIED, "got %u\n", status);
2700
2701 size = 0xdeadbeef;
2702 ret = WinHttpQueryDataAvailable(request, &size);
2703 ok(ret, "WinHttpQueryDataAvailable failed: %u\n", GetLastError());
2704 ok(!size, "got %u\n", size);
2705
2706 WinHttpCloseHandle(request);
2707 WinHttpCloseHandle(connection);
2708 WinHttpCloseHandle(session);
2709 start = GetTickCount() - start;
2710 ok(start <= 2000, "Expected less than 2 seconds for the test, got %u ms\n", start);
2711 }
2712
2713 static void test_bad_header( int port )
2714 {
2715 static const WCHAR bad_headerW[] =
2716 {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ',
2717 't','e','x','t','/','h','t','m','l','\n','\r',0};
2718 static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
2719 static const WCHAR content_typeW[] = {'C','o','n','t','e','n','t','-','T','y','p','e',0};
2720 WCHAR buffer[32];
2721 HINTERNET ses, con, req;
2722 DWORD index, len;
2723 BOOL ret;
2724
2725 ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
2726 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
2727
2728 con = WinHttpConnect( ses, localhostW, port, 0 );
2729 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2730
2731 req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
2732 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2733
2734 ret = WinHttpAddRequestHeaders( req, bad_headerW, ~0u, WINHTTP_ADDREQ_FLAG_ADD );
2735 ok( ret, "failed to add header %u\n", GetLastError() );
2736
2737 index = 0;
2738 buffer[0] = 0;
2739 len = sizeof(buffer);
2740 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_CUSTOM|WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
2741 content_typeW, buffer, &len, &index );
2742 ok( ret, "failed to query headers %u\n", GetLastError() );
2743 ok( !lstrcmpW( buffer, text_htmlW ), "got %s\n", wine_dbgstr_w(buffer) );
2744
2745 WinHttpCloseHandle( req );
2746 WinHttpCloseHandle( con );
2747 WinHttpCloseHandle( ses );
2748 }
2749
2750 static void test_multiple_reads(int port)
2751 {
2752 static const WCHAR bigW[] = {'b','i','g',0};
2753 HINTERNET ses, con, req;
2754 DWORD total_len = 0;
2755 BOOL ret;
2756
2757 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2758 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2759
2760 con = WinHttpConnect(ses, localhostW, port, 0);
2761 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2762
2763 req = WinHttpOpenRequest(con, NULL, bigW, NULL, NULL, NULL, 0);
2764 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2765
2766 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2767 ok(ret, "failed to send request %u\n", GetLastError());
2768
2769 ret = WinHttpReceiveResponse(req, NULL);
2770 ok(ret == TRUE, "expected success\n");
2771
2772 for (;;)
2773 {
2774 DWORD len = 0xdeadbeef;
2775 ret = WinHttpQueryDataAvailable( req, &len );
2776 ok( ret, "WinHttpQueryDataAvailable failed with error %u\n", GetLastError() );
2777 if (ret) ok( len != 0xdeadbeef, "WinHttpQueryDataAvailable return wrong length\n" );
2778 if (len)
2779 {
2780 DWORD bytes_read;
2781 char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 );
2782
2783 ret = WinHttpReadData( req, buf, len, &bytes_read );
2784 ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len );
2785
2786 HeapFree( GetProcessHeap(), 0, buf );
2787 if (!bytes_read) break;
2788 total_len += bytes_read;
2789 }
2790 if (!len) break;
2791 }
2792 ok(total_len == BIG_BUFFER_LEN, "got wrong length: 0x%x\n", total_len);
2793
2794 WinHttpCloseHandle(req);
2795 WinHttpCloseHandle(con);
2796 WinHttpCloseHandle(ses);
2797 }
2798
2799 static void test_cookies( int port )
2800 {
2801 static const WCHAR cookieW[] = {'/','c','o','o','k','i','e',0};
2802 static const WCHAR cookie2W[] = {'/','c','o','o','k','i','e','2',0};
2803 static const WCHAR cookie3W[] = {'/','c','o','o','k','i','e','3',0};
2804 static const WCHAR cookieheaderW[] =
2805 {'C','o','o','k','i','e',':',' ','n','a','m','e','=','v','a','l','u','e','2','\r','\n',0};
2806 HINTERNET ses, con, req;
2807 DWORD status, size;
2808 BOOL ret;
2809
2810 ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
2811 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
2812
2813 con = WinHttpConnect( ses, localhostW, port, 0 );
2814 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2815
2816 req = WinHttpOpenRequest( con, NULL, cookieW, NULL, NULL, NULL, 0 );
2817 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2818
2819 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2820 ok( ret, "failed to send request %u\n", GetLastError() );
2821
2822 ret = WinHttpReceiveResponse( req, NULL );
2823 ok( ret, "failed to receive response %u\n", GetLastError() );
2824
2825 status = 0xdeadbeef;
2826 size = sizeof(status);
2827 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
2828 ok( ret, "failed to query status code %u\n", GetLastError() );
2829 ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
2830
2831 WinHttpCloseHandle( req );
2832
2833 req = WinHttpOpenRequest( con, NULL, cookie2W, NULL, NULL, NULL, 0 );
2834 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2835
2836 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2837 ok( ret, "failed to send request %u\n", GetLastError() );
2838
2839 ret = WinHttpReceiveResponse( req, NULL );
2840 ok( ret, "failed to receive response %u\n", GetLastError() );
2841
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 == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
2847
2848 WinHttpCloseHandle( req );
2849 WinHttpCloseHandle( con );
2850
2851 con = WinHttpConnect( ses, localhostW, port, 0 );
2852 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2853
2854 req = WinHttpOpenRequest( con, NULL, cookie2W, NULL, NULL, NULL, 0 );
2855 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2856
2857 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2858 ok( ret, "failed to send request %u\n", GetLastError() );
2859
2860 ret = WinHttpReceiveResponse( req, NULL );
2861 ok( ret, "failed to receive response %u\n", GetLastError() );
2862
2863 status = 0xdeadbeef;
2864 size = sizeof(status);
2865 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
2866 ok( ret, "failed to query status code %u\n", GetLastError() );
2867 ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
2868
2869 WinHttpCloseHandle( req );
2870
2871 req = WinHttpOpenRequest( con, NULL, cookie3W, NULL, NULL, NULL, 0 );
2872 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2873
2874 ret = WinHttpSendRequest( req, cookieheaderW, ~0u, NULL, 0, 0, 0 );
2875 ok( ret, "failed to send request %u\n", GetLastError() );
2876
2877 ret = WinHttpReceiveResponse( req, NULL );
2878 ok( ret, "failed to receive response %u\n", GetLastError() );
2879
2880 status = 0xdeadbeef;
2881 size = sizeof(status);
2882 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
2883 ok( ret, "failed to query status code %u\n", GetLastError() );
2884 ok( status == HTTP_STATUS_OK || broken(status == HTTP_STATUS_BAD_REQUEST), "request failed unexpectedly %u\n", status );
2885
2886 WinHttpCloseHandle( req );
2887 WinHttpCloseHandle( con );
2888 WinHttpCloseHandle( ses );
2889
2890 ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
2891 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
2892
2893 con = WinHttpConnect( ses, localhostW, port, 0 );
2894 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2895
2896 req = WinHttpOpenRequest( con, NULL, cookie2W, NULL, NULL, NULL, 0 );
2897 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2898
2899 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2900 ok( ret, "failed to send request %u\n", GetLastError() );
2901
2902 ret = WinHttpReceiveResponse( req, NULL );
2903 ok( ret, "failed to receive response %u\n", GetLastError() );
2904
2905 status = 0xdeadbeef;
2906 size = sizeof(status);
2907 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
2908 ok( ret, "failed to query status code %u\n", GetLastError() );
2909 ok( status == HTTP_STATUS_BAD_REQUEST, "request failed unexpectedly %u\n", status );
2910
2911 WinHttpCloseHandle( req );
2912 WinHttpCloseHandle( con );
2913 WinHttpCloseHandle( ses );
2914 }
2915
2916 static void test_connection_info( int port )
2917 {
2918 static const WCHAR basicW[] = {'/','b','a','s','i','c',0};
2919 HINTERNET ses, con, req;
2920 WINHTTP_CONNECTION_INFO info;
2921 DWORD size, error;
2922 BOOL ret;
2923
2924 ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
2925 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
2926
2927 con = WinHttpConnect( ses, localhostW, port, 0 );
2928 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2929
2930 req = WinHttpOpenRequest( con, NULL, basicW, NULL, NULL, NULL, 0 );
2931 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2932
2933 size = sizeof(info);
2934 SetLastError( 0xdeadbeef );
2935 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
2936 error = GetLastError();
2937 if (!ret && error == ERROR_INVALID_PARAMETER)
2938 {
2939 win_skip( "WINHTTP_OPTION_CONNECTION_INFO not supported\n" );
2940 return;
2941 }
2942 ok( !ret, "unexpected success\n" );
2943 ok( error == ERROR_WINHTTP_INCORRECT_HANDLE_STATE, "got %u\n", error );
2944
2945 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2946 ok( ret, "failed to send request %u\n", GetLastError() );
2947
2948 size = 0;
2949 SetLastError( 0xdeadbeef );
2950 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
2951 error = GetLastError();
2952 ok( !ret, "unexpected success\n" );
2953 ok( error == ERROR_INSUFFICIENT_BUFFER, "got %u\n", error );
2954
2955 size = sizeof(info);
2956 memset( &info, 0, sizeof(info) );
2957 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
2958 ok( ret, "failed to retrieve connection info %u\n", GetLastError() );
2959 ok( info.cbSize == sizeof(info) || info.cbSize == sizeof(info) - sizeof(info.cbSize) /* Win7 */, "wrong size %u\n", info.cbSize );
2960
2961 ret = WinHttpReceiveResponse( req, NULL );
2962 ok( ret, "failed to receive response %u\n", GetLastError() );
2963
2964 size = sizeof(info);
2965 memset( &info, 0, sizeof(info) );
2966 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
2967 ok( ret, "failed to retrieve connection info %u\n", GetLastError() );
2968 ok( info.cbSize == sizeof(info) || info.cbSize == sizeof(info) - sizeof(info.cbSize) /* Win7 */, "wrong size %u\n", info.cbSize );
2969
2970 WinHttpCloseHandle( req );
2971 WinHttpCloseHandle( con );
2972 WinHttpCloseHandle( ses );
2973 }
2974
2975 static void test_credentials(void)
2976 {
2977 static WCHAR userW[] = {'u','s','e','r',0};
2978 static WCHAR passW[] = {'p','a','s','s',0};
2979 static WCHAR proxy_userW[] = {'p','r','o','x','y','u','s','e','r',0};
2980 static WCHAR proxy_passW[] = {'p','r','o','x','y','p','a','s','s',0};
2981 HINTERNET ses, con, req;
2982 DWORD size, error;
2983 WCHAR buffer[32];
2984 BOOL ret;
2985
2986 ses = WinHttpOpen(test_useragent, 0, proxy_userW, proxy_passW, 0);
2987 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2988
2989 con = WinHttpConnect(ses, localhostW, 0, 0);
2990 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2991
2992 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
2993 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2994
2995 size = sizeof(buffer)/sizeof(WCHAR);
2996 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size);
2997 ok(ret, "failed to query proxy username %u\n", GetLastError());
2998 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
2999 ok(!size, "expected 0, got %u\n", size);
3000
3001 size = sizeof(buffer)/sizeof(WCHAR);
3002 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size);
3003 ok(ret, "failed to query proxy password %u\n", GetLastError());
3004 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3005 ok(!size, "expected 0, got %u\n", size);
3006
3007 ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_USERNAME, proxy_userW, lstrlenW(proxy_userW));
3008 ok(ret, "failed to set username %u\n", GetLastError());
3009
3010 size = sizeof(buffer)/sizeof(WCHAR);
3011 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size);
3012 ok(ret, "failed to query proxy username %u\n", GetLastError());
3013 ok(!winetest_strcmpW(buffer, proxy_userW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3014 ok(size == lstrlenW(proxy_userW) * sizeof(WCHAR), "unexpected result %u\n", size);
3015
3016 size = sizeof(buffer)/sizeof(WCHAR);
3017 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
3018 ok(ret, "failed to query username %u\n", GetLastError());
3019 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3020 ok(!size, "expected 0, got %u\n", size);
3021
3022 size = sizeof(buffer)/sizeof(WCHAR);
3023 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3024 ok(ret, "failed to query password %u\n", GetLastError());
3025 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3026 ok(!size, "expected 0, got %u\n", size);
3027
3028 ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_PASSWORD, proxy_passW, lstrlenW(proxy_passW));
3029 ok(ret, "failed to set proxy password %u\n", GetLastError());
3030
3031 size = sizeof(buffer)/sizeof(WCHAR);
3032 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size);
3033 ok(ret, "failed to query proxy password %u\n", GetLastError());
3034 ok(!winetest_strcmpW(buffer, proxy_passW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3035 ok(size == lstrlenW(proxy_passW) * sizeof(WCHAR), "unexpected result %u\n", size);
3036
3037 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
3038 ok(ret, "failed to set username %u\n", GetLastError());
3039
3040 size = sizeof(buffer)/sizeof(WCHAR);
3041 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
3042 ok(ret, "failed to query username %u\n", GetLastError());
3043 ok(!winetest_strcmpW(buffer, userW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3044 ok(size == lstrlenW(userW) * sizeof(WCHAR), "unexpected result %u\n", size);
3045
3046 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, passW, lstrlenW(passW));
3047 ok(ret, "failed to set password %u\n", GetLastError());
3048
3049 size = sizeof(buffer)/sizeof(WCHAR);
3050 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3051 ok(ret, "failed to query password %u\n", GetLastError());
3052 ok(!winetest_strcmpW(buffer, passW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3053 ok(size == lstrlenW(passW) * sizeof(WCHAR), "unexpected result %u\n", size);
3054
3055 WinHttpCloseHandle(req);
3056
3057 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
3058 ok(req != NULL, "failed to open a request %u\n", GetLastError());
3059
3060 SetLastError(0xdeadbeef);
3061 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, NULL, NULL);
3062 error = GetLastError();
3063 ok(!ret, "expected failure\n");
3064 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
3065
3066 SetLastError(0xdeadbeef);
3067 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, passW, NULL);
3068 error = GetLastError();
3069 ok(!ret, "expected failure\n");
3070 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
3071
3072 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
3073 ok(ret, "failed to set credentials %u\n", GetLastError());
3074
3075 size = sizeof(buffer)/sizeof(WCHAR);
3076 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
3077 ok(ret, "failed to query username %u\n", GetLastError());
3078 todo_wine {
3079 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3080 ok(!size, "expected 0, got %u\n", size);
3081 }
3082
3083 size = sizeof(buffer)/sizeof(WCHAR);
3084 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3085 ok(ret, "failed to query password %u\n", GetLastError());
3086 todo_wine {
3087 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3088 ok(!size, "expected 0, got %u\n", size);
3089 }
3090
3091 WinHttpCloseHandle(req);
3092 WinHttpCloseHandle(con);
3093 WinHttpCloseHandle(ses);
3094 }
3095
3096 static void test_IWinHttpRequest(int port)
3097 {
3098 static const WCHAR data_start[] = {'<','!','D','O','C','T','Y','P','E',' ','h','t','m','l',' ','P','U','B','L','I','C'};
3099 static const WCHAR usernameW[] = {'u','s','e','r','n','a','m','e',0};
3100 static const WCHAR passwordW[] = {'p','a','s','s','w','o','r','d',0};
3101 static const WCHAR url1W[] = {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
3102 static const WCHAR url2W[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
3103 static const WCHAR url3W[] = {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.',
3104 'o','r','g','/','t','e','s','t','s','/','p','o','s','t','.','p','h','p',0};
3105 static const WCHAR method1W[] = {'G','E','T',0};
3106 static const WCHAR method2W[] = {'I','N','V','A','L','I','D',0};
3107 static const WCHAR method3W[] = {'P','O','S','T',0};
3108 static const WCHAR proxy_serverW[] = {'p','r','o','x','y','s','e','r','v','e','r',0};
3109 static const WCHAR bypas_listW[] = {'b','y','p','a','s','s','l','i','s','t',0};
3110 static const WCHAR connectionW[] = {'C','o','n','n','e','c','t','i','o','n',0};
3111 static const WCHAR dateW[] = {'D','a','t','e',0};
3112 static const WCHAR test_dataW[] = {'t','e','s','t','d','a','t','a',128,0};
3113 static const WCHAR utf8W[] = {'u','t','f','-','8',0};
3114 static const WCHAR unauthW[] = {'U','n','a','u','t','h','o','r','i','z','e','d',0};
3115 HRESULT hr;
3116 IWinHttpRequest *req;
3117 BSTR method, url, username, password, response = NULL, status_text = NULL, headers = NULL;
3118 BSTR date, today, connection, value = NULL;
3119 VARIANT async, empty, timeout, body, body2, proxy_server, bypass_list, data, cp;
3120 VARIANT_BOOL succeeded;
3121 LONG status;
3122 WCHAR todayW[WINHTTP_TIME_FORMAT_BUFSIZE];
3123 SYSTEMTIME st;
3124 IStream *stream, *stream2;
3125 LARGE_INTEGER pos;
3126 char buf[128];
3127 WCHAR bufW[128];
3128 DWORD count;
3129
3130 GetSystemTime( &st );
3131 WinHttpTimeFromSystemTime( &st, todayW );
3132
3133 CoInitialize( NULL );
3134 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3135 ok( hr == S_OK, "got %08x\n", hr );
3136
3137 V_VT( &empty ) = VT_ERROR;
3138 V_ERROR( &empty ) = 0xdeadbeef;
3139
3140 V_VT( &async ) = VT_BOOL;
3141 V_BOOL( &async ) = VARIANT_FALSE;
3142
3143 method = SysAllocString( method3W );
3144 url = SysAllocString( url3W );
3145 hr = IWinHttpRequest_Open( req, method, url, async );
3146 ok( hr == S_OK, "got %08x\n", hr );
3147 SysFreeString( method );
3148 SysFreeString( url );
3149
3150 V_VT( &data ) = VT_BSTR;
3151 V_BSTR( &data ) = SysAllocString( test_dataW );
3152 hr = IWinHttpRequest_Send( req, data );
3153 ok( hr == S_OK || broken(hr == HRESULT_FROM_WIN32(ERROR_WINHTTP_INVALID_SERVER_RESPONSE)),
3154 "got %08x\n", hr );
3155 SysFreeString( V_BSTR( &data ) );
3156
3157 hr = IWinHttpRequest_Open( req, NULL, NULL, empty );
3158 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3159
3160 method = SysAllocString( method1W );
3161 hr = IWinHttpRequest_Open( req, method, NULL, empty );
3162 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3163
3164 hr = IWinHttpRequest_Open( req, method, NULL, async );
3165 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3166
3167 url = SysAllocString( url1W );
3168 hr = IWinHttpRequest_Open( req, NULL, url, empty );
3169 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3170
3171 hr = IWinHttpRequest_Abort( req );
3172 ok( hr == S_OK, "got %08x\n", hr );
3173
3174 hr = IWinHttpRequest_Open( req, method, url, empty );
3175 ok( hr == S_OK, "got %08x\n", hr );
3176
3177 hr = IWinHttpRequest_Abort( req );
3178 ok( hr == S_OK, "got %08x\n", hr );
3179
3180 IWinHttpRequest_Release( req );
3181
3182 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3183 ok( hr == S_OK, "got %08x\n", hr );
3184
3185 SysFreeString( url );
3186 url = SysAllocString( url2W );
3187 hr = IWinHttpRequest_Open( req, method, url, async );
3188 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ), "got %08x\n", hr );
3189
3190 SysFreeString( method );
3191 method = SysAllocString( method2W );
3192 hr = IWinHttpRequest_Open( req, method, url, async );
3193 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ), "got %08x\n", hr );
3194
3195 SysFreeString( method );
3196 method = SysAllocString( method1W );
3197 SysFreeString( url );
3198 url = SysAllocString( url1W );
3199 V_VT( &async ) = VT_ERROR;
3200 V_ERROR( &async ) = DISP_E_PARAMNOTFOUND;
3201 hr = IWinHttpRequest_Open( req, method, url, async );
3202 ok( hr == S_OK, "got %08x\n", hr );
3203
3204 V_VT( &cp ) = VT_ERROR;
3205 V_ERROR( &cp ) = 0xdeadbeef;
3206 hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3207 ok( hr == S_OK, "got %08x\n", hr );
3208 ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3209 ok( V_I4( &cp ) == CP_UTF8, "got %u\n", V_I4( &cp ) );
3210
3211 V_VT( &cp ) = VT_UI4;
3212 V_UI4( &cp ) = CP_ACP;
3213 hr = IWinHttpRequest_put_Option( req, WinHttpRequestOption_URLCodePage, cp );
3214 ok( hr == S_OK, "got %08x\n", hr );
3215
3216 V_VT( &cp ) = VT_ERROR;
3217 V_ERROR( &cp ) = 0xdeadbeef;
3218 hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3219 ok( hr == S_OK, "got %08x\n", hr );
3220 ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3221 ok( V_I4( &cp ) == CP_ACP, "got %u\n", V_I4( &cp ) );
3222
3223 value = SysAllocString( utf8W );
3224 V_VT( &cp ) = VT_BSTR;
3225 V_BSTR( &cp ) = value;
3226 hr = IWinHttpRequest_put_Option( req, WinHttpRequestOption_URLCodePage, cp );
3227 ok( hr == S_OK, "got %08x\n", hr );
3228 SysFreeString( value );
3229
3230 V_VT( &cp ) = VT_ERROR;
3231 V_ERROR( &cp ) = 0xdeadbeef;
3232 hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3233 ok( hr == S_OK, "got %08x\n", hr );
3234 ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3235 ok( V_I4( &cp ) == CP_UTF8, "got %u\n", V_I4( &cp ) );
3236
3237 hr = IWinHttpRequest_Abort( req );
3238 ok( hr == S_OK, "got %08x\n", hr );
3239
3240 hr = IWinHttpRequest_Send( req, empty );
3241 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3242
3243 hr = IWinHttpRequest_Abort( req );
3244 ok( hr == S_OK, "got %08x\n", hr );
3245
3246 IWinHttpRequest_Release( req );
3247
3248 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3249 ok( hr == S_OK, "got %08x\n", hr );
3250
3251 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3252 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3253
3254 hr = IWinHttpRequest_get_ResponseText( req, &response );
3255 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3256
3257 hr = IWinHttpRequest_get_Status( req, NULL );
3258 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3259
3260 hr = IWinHttpRequest_get_Status( req, &status );
3261 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3262
3263 hr = IWinHttpRequest_get_StatusText( req, NULL );
3264 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3265
3266 hr = IWinHttpRequest_get_StatusText( req, &status_text );
3267 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3268
3269 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3270 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3271
3272 hr = IWinHttpRequest_SetTimeouts( req, 10000, 10000, 10000, 10000 );
3273 ok( hr == S_OK, "got %08x\n", hr );
3274
3275 hr = IWinHttpRequest_SetCredentials( req, NULL, NULL, 0xdeadbeef );
3276 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3277
3278 VariantInit( &proxy_server );
3279 V_VT( &proxy_server ) = VT_ERROR;
3280 VariantInit( &bypass_list );
3281 V_VT( &bypass_list ) = VT_ERROR;
3282 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3283 ok( hr == S_OK, "got %08x\n", hr );
3284
3285 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3286 ok( hr == S_OK, "got %08x\n", hr );
3287
3288 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3289 ok( hr == S_OK, "got %08x\n", hr );
3290
3291 hr = IWinHttpRequest_GetAllResponseHeaders( req, NULL );
3292 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3293
3294 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3295 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3296
3297 hr = IWinHttpRequest_GetResponseHeader( req, NULL, NULL );
3298 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3299
3300 connection = SysAllocString( connectionW );
3301 hr = IWinHttpRequest_GetResponseHeader( req, connection, NULL );
3302 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3303
3304 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3305 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3306
3307 hr = IWinHttpRequest_SetRequestHeader( req, NULL, NULL );
3308 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3309
3310 date = SysAllocString( dateW );
3311 hr = IWinHttpRequest_SetRequestHeader( req, date, NULL );
3312 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3313
3314 today = SysAllocString( todayW );
3315 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3316 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3317
3318 hr = IWinHttpRequest_SetAutoLogonPolicy( req, 0xdeadbeef );
3319 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3320
3321 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3322 ok( hr == S_OK, "got %08x\n", hr );
3323
3324 SysFreeString( method );
3325 method = SysAllocString( method1W );
3326 SysFreeString( url );
3327 url = SysAllocString( url1W );
3328 hr = IWinHttpRequest_Open( req, method, url, async );
3329 ok( hr == S_OK, "got %08x\n", hr );
3330
3331 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3332 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3333
3334 hr = IWinHttpRequest_get_ResponseText( req, &response );
3335 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3336
3337 hr = IWinHttpRequest_get_Status( req, &status );
3338 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3339
3340 hr = IWinHttpRequest_get_StatusText( req, &status_text );
3341 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3342
3343 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3344 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3345
3346 hr = IWinHttpRequest_SetTimeouts( req, 10000, 10000, 10000, 10000 );
3347 ok( hr == S_OK, "got %08x\n", hr );
3348
3349 hr = IWinHttpRequest_SetCredentials( req, NULL, NULL, 0xdeadbeef );
3350 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3351
3352 username = SysAllocString( usernameW );
3353 hr = IWinHttpRequest_SetCredentials( req, username, NULL, 0xdeadbeef );
3354 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3355
3356 password = SysAllocString( passwordW );
3357 hr = IWinHttpRequest_SetCredentials( req, NULL, password, 0xdeadbeef );
3358 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3359
3360 hr = IWinHttpRequest_SetCredentials( req, username, password, 0xdeadbeef );
3361 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3362
3363 hr = IWinHttpRequest_SetCredentials( req, NULL, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3364 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3365
3366 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3367 ok( hr == S_OK, "got %08x\n", hr );
3368
3369 V_VT( &proxy_server ) = VT_BSTR;
3370 V_BSTR( &proxy_server ) = SysAllocString( proxy_serverW );
3371 V_VT( &bypass_list ) = VT_BSTR;
3372 V_BSTR( &bypass_list ) = SysAllocString( bypas_listW );
3373 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3374 ok( hr == S_OK, "got %08x\n", hr );
3375
3376 hr = IWinHttpRequest_SetProxy( req, 0xdeadbeef, proxy_server, bypass_list );
3377 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3378
3379 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3380 ok( hr == S_OK, "got %08x\n", hr );
3381
3382 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3383 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3384
3385 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3386 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3387
3388 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3389 ok( hr == S_OK, "got %08x\n", hr );
3390
3391 hr = IWinHttpRequest_SetRequestHeader( req, date, NULL );
3392 ok( hr == S_OK, "got %08x\n", hr );
3393
3394 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3395 ok( hr == S_OK, "got %08x\n", hr );
3396
3397 hr = IWinHttpRequest_Send( req, empty );
3398 ok( hr == S_OK, "got %08x\n", hr );
3399
3400 hr = IWinHttpRequest_Send( req, empty );
3401 ok( hr == S_OK, "got %08x\n", hr );
3402
3403 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3404 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3405
3406 hr = IWinHttpRequest_get_ResponseText( req, &response );
3407 ok( hr == S_OK, "got %08x\n", hr );
3408 ok( !memcmp(response, data_start, sizeof(data_start)), "got %s\n", wine_dbgstr_wn(response, 32) );
3409 SysFreeString( response );
3410
3411 hr = IWinHttpRequest_get_Status( req, NULL );
3412 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3413
3414 status = 0;
3415 hr = IWinHttpRequest_get_Status( req, &status );
3416 ok( hr == S_OK, "got %08x\n", hr );
3417 trace("Status=%d\n", status);
3418
3419 hr = IWinHttpRequest_get_StatusText( req, NULL );
3420 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3421
3422 hr = IWinHttpRequest_get_StatusText( req, &status_text );
3423 ok( hr == S_OK, "got %08x\n", hr );
3424 trace("StatusText=%s\n", wine_dbgstr_w(status_text));
3425 SysFreeString( status_text );
3426
3427 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3428 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3429
3430 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3431 ok( hr == S_OK, "got %08x\n", hr );
3432
3433 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3434 ok( hr == S_OK, "got %08x\n", hr );
3435
3436 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3437 ok( hr == S_OK, "got %08x\n", hr );
3438
3439 hr = IWinHttpRequest_GetAllResponseHeaders( req, NULL );
3440 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3441
3442 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3443 ok( hr == S_OK, "got %08x\n", hr );
3444 SysFreeString( headers );
3445
3446 hr = IWinHttpRequest_GetResponseHeader( req, NULL, NULL );
3447 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3448
3449 hr = IWinHttpRequest_GetResponseHeader( req, connection, NULL );
3450 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3451
3452 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3453 ok( hr == S_OK, "got %08x\n", hr );
3454 SysFreeString( value );
3455
3456 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3457 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND ), "got %08x\n", hr );
3458
3459 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3460 ok( hr == S_OK, "got %08x\n", hr );
3461
3462 VariantInit( &timeout );
3463 V_VT( &timeout ) = VT_I4;
3464 V_I4( &timeout ) = 10;
3465 hr = IWinHttpRequest_WaitForResponse( req, timeout, &succeeded );
3466 ok( hr == S_OK, "got %08x\n", hr );
3467
3468 hr = IWinHttpRequest_get_Status( req, &status );
3469 ok( hr == S_OK, "got %08x\n", hr );
3470
3471 hr = IWinHttpRequest_get_StatusText( req, &status_text );
3472 ok( hr == S_OK, "got %08x\n", hr );
3473 SysFreeString( status_text );
3474
3475 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3476 ok( hr == S_OK, "got %08x\n", hr );
3477
3478 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3479 ok( hr == S_OK, "got %08x\n", hr );
3480
3481 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3482 ok( hr == S_OK, "got %08x\n", hr );
3483
3484 hr = IWinHttpRequest_Send( req, empty );
3485 ok( hr == S_OK, "got %08x\n", hr );
3486
3487 hr = IWinHttpRequest_get_ResponseText( req, NULL );
3488 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3489
3490 hr = IWinHttpRequest_get_ResponseText( req, &response );
3491 ok( hr == S_OK, "got %08x\n", hr );
3492 SysFreeString( response );
3493
3494 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3495 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3496
3497 VariantInit( &body );
3498 V_VT( &body ) = VT_ERROR;
3499 hr = IWinHttpRequest_get_ResponseBody( req, &body );
3500 ok( hr == S_OK, "got %08x\n", hr );
3501 ok( V_VT( &body ) == (VT_ARRAY|VT_UI1), "got %08x\n", V_VT( &body ) );
3502
3503 hr = VariantClear( &body );
3504 ok( hr == S_OK, "got %08x\n", hr );
3505
3506 VariantInit( &body );
3507 V_VT( &body ) = VT_ERROR;
3508 hr = IWinHttpRequest_get_ResponseStream( req, &body );
3509 ok( hr == S_OK, "got %08x\n", hr );
3510 ok( V_VT( &body ) == VT_UNKNOWN, "got %08x\n", V_VT( &body ) );
3511
3512 hr = IUnknown_QueryInterface( V_UNKNOWN( &body ), &IID_IStream, (void **)&stream );
3513 ok( hr == S_OK, "got %08x\n", hr );
3514 ok( V_UNKNOWN( &body ) == (IUnknown *)stream, "got different interface pointer\n" );
3515
3516 buf[0] = 0;
3517 count = 0xdeadbeef;
3518 hr = IStream_Read( stream, buf, 128, &count );
3519 ok( hr == S_OK, "got %08x\n", hr );
3520 ok( count != 0xdeadbeef, "count not set\n" );
3521 ok( buf[0], "no data\n" );
3522
3523 VariantInit( &body2 );
3524 V_VT( &body2 ) = VT_ERROR;
3525 hr = IWinHttpRequest_get_ResponseStream( req, &body2 );
3526 ok( hr == S_OK, "got %08x\n", hr );
3527 ok( V_VT( &body2 ) == VT_UNKNOWN, "got %08x\n", V_VT( &body2 ) );
3528 ok( V_UNKNOWN( &body ) != V_UNKNOWN( &body2 ), "got same interface pointer\n" );
3529
3530 hr = IUnknown_QueryInterface( V_UNKNOWN( &body2 ), &IID_IStream, (void **)&stream2 );
3531 ok( hr == S_OK, "got %08x\n", hr );
3532 ok( V_UNKNOWN( &body2 ) == (IUnknown *)stream2, "got different interface pointer\n" );
3533 IStream_Release( stream2 );
3534
3535 hr = VariantClear( &body );
3536 ok( hr == S_OK, "got %08x\n", hr );
3537
3538 hr = VariantClear( &body2 );
3539 ok( hr == S_OK, "got %08x\n", hr );
3540
3541 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3542 ok( hr == S_OK, "got %08x\n", hr );
3543
3544 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3545 ok( hr == S_OK, "got %08x\n", hr );
3546
3547 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3548 ok( hr == S_OK, "got %08x\n", hr );
3549 SysFreeString( headers );
3550
3551 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3552 ok( hr == S_OK, "got %08x\n", hr );
3553 SysFreeString( value );
3554
3555 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3556 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND ), "got %08x\n", hr );
3557
3558 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3559 ok( hr == S_OK, "got %08x\n", hr );
3560
3561 hr = IWinHttpRequest_Send( req, empty );
3562 ok( hr == S_OK, "got %08x\n", hr );
3563
3564 hr = IWinHttpRequest_Abort( req );
3565 ok( hr == S_OK, "got %08x\n", hr );
3566
3567 hr = IWinHttpRequest_Abort( req );
3568 ok( hr == S_OK, "got %08x\n", hr );
3569
3570 IWinHttpRequest_Release( req );
3571
3572 pos.QuadPart = 0;
3573 hr = IStream_Seek( stream, pos, STREAM_SEEK_SET, NULL );
3574 ok( hr == S_OK, "got %08x\n", hr );
3575
3576 buf[0] = 0;
3577 count = 0xdeadbeef;
3578 hr = IStream_Read( stream, buf, 128, &count );
3579 ok( hr == S_OK, "got %08x\n", hr );
3580 ok( count != 0xdeadbeef, "count not set\n" );
3581 ok( buf[0], "no data\n" );
3582 IStream_Release( stream );
3583
3584 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3585 ok( hr == S_OK, "got %08x\n", hr );
3586
3587 V_VT( &async ) = VT_I4;
3588 V_I4( &async ) = 1;
3589 hr = IWinHttpRequest_Open( req, method, url, async );
3590 ok( hr == S_OK, "got %08x\n", hr );
3591
3592 hr = IWinHttpRequest_Send( req, empty );
3593 ok( hr == S_OK, "got %08x\n", hr );
3594
3595 hr = IWinHttpRequest_WaitForResponse( req, timeout, &succeeded );
3596 ok( hr == S_OK, "got %08x\n", hr );
3597
3598 IWinHttpRequest_Release( req );
3599
3600 SysFreeString( method );
3601 SysFreeString( url );
3602 SysFreeString( username );
3603 SysFreeString( password );
3604 SysFreeString( connection );
3605 SysFreeString( date );
3606 SysFreeString( today );
3607 VariantClear( &proxy_server );
3608 VariantClear( &bypass_list );
3609
3610 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3611 ok( hr == S_OK, "got %08x\n", hr );
3612
3613 url = SysAllocString( test_winehq_https );
3614 method = SysAllocString( method3W );
3615 V_VT( &async ) = VT_BOOL;
3616 V_BOOL( &async ) = VARIANT_FALSE;
3617 hr = IWinHttpRequest_Open( req, method, url, async );
3618 ok( hr == S_OK, "got %08x\n", hr );
3619 SysFreeString( method );
3620 SysFreeString( url );
3621
3622 hr = IWinHttpRequest_Send( req, empty );
3623 ok( hr == S_OK || broken(hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_INVALID_SERVER_RESPONSE )), "got %08x\n", hr );
3624 if (hr == S_OK)
3625 {
3626 hr = IWinHttpRequest_get_ResponseText( req, &response );
3627 ok( hr == S_OK, "got %08x\n", hr );
3628 ok( !memcmp(response, data_start, sizeof(data_start)), "got %s\n", wine_dbgstr_wn(response, 32) );
3629 SysFreeString( response );
3630 }
3631
3632 IWinHttpRequest_Release( req );
3633
3634 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3635 ok( hr == S_OK, "got %08x\n", hr );
3636
3637 sprintf( buf, "http://localhost:%d/auth", port );
3638 MultiByteToWideChar( CP_ACP, 0, buf, -1, bufW, sizeof(bufW)/sizeof(bufW[0]) );
3639 url = SysAllocString( bufW );
3640 method = SysAllocString( method3W );
3641 V_VT( &async ) = VT_BOOL;
3642 V_BOOL( &async ) = VARIANT_FALSE;
3643 hr = IWinHttpRequest_Open( req, method, url, async );
3644 ok( hr == S_OK, "got %08x\n", hr );
3645 SysFreeString( method );
3646 SysFreeString( url );
3647
3648 hr = IWinHttpRequest_get_Status( req, &status );
3649 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3650
3651 V_VT( &data ) = VT_BSTR;
3652 V_BSTR( &data ) = SysAllocString( test_dataW );
3653 hr = IWinHttpRequest_Send( req, data );
3654 ok( hr == S_OK, "got %08x\n", hr );
3655 SysFreeString( V_BSTR( &data ) );
3656
3657 hr = IWinHttpRequest_get_ResponseText( req, &response );
3658 ok( hr == S_OK, "got %08x\n", hr );
3659 ok( !memcmp( response, unauthW, sizeof(unauthW) ), "got %s\n", wine_dbgstr_w(response) );
3660 SysFreeString( response );
3661
3662 status = 0xdeadbeef;
3663 hr = IWinHttpRequest_get_Status( req, &status );
3664 ok( hr == S_OK, "got %08x\n", hr );
3665 ok( status == HTTP_STATUS_DENIED, "got %d\n", status );
3666
3667 IWinHttpRequest_Release( req );
3668
3669 CoUninitialize();
3670 }
3671
3672 static void request_get_property(IWinHttpRequest *request, int property, VARIANT *ret)
3673 {
3674 DISPPARAMS params;
3675 VARIANT arg;
3676 HRESULT hr;
3677
3678 memset(&params, 0, sizeof(params));
3679 params.cNamedArgs = 0;
3680 params.rgdispidNamedArgs = NULL;
3681 params.cArgs = 1;
3682 params.rgvarg = &arg;
3683 VariantInit(&arg);
3684 V_VT(&arg) = VT_I4;
3685 V_I4(&arg) = property;
3686 VariantInit(ret);
3687 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
3688 DISPATCH_PROPERTYGET, &params, ret, NULL, NULL);
3689 ok(hr == S_OK, "error %#x\n", hr);
3690 }
3691
3692 static void test_IWinHttpRequest_Invoke(void)
3693 {
3694 static const WCHAR utf8W[] = {'U','T','F','-','8',0};
3695 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};
3696 WCHAR openW[] = {'O','p','e','n',0};
3697 WCHAR optionW[] = {'O','p','t','i','o','n',0};
3698 OLECHAR *open = openW, *option = optionW;
3699 BSTR utf8;
3700 CLSID clsid;
3701 IWinHttpRequest *request;
3702 IDispatch *dispatch;
3703 DISPID id;
3704 DISPPARAMS params;
3705 VARIANT arg[3], ret;
3706 UINT err;
3707 BOOL bret;
3708 HRESULT hr;
3709
3710 CoInitialize(NULL);
3711
3712 hr = CLSIDFromProgID(regid, &clsid);
3713 ok(hr == S_OK, "CLSIDFromProgID error %#x\n", hr);
3714 bret = IsEqualIID(&clsid, &CLSID_WinHttpRequest);
3715 ok(bret || broken(!bret) /* win2003 */, "not expected %s\n", wine_dbgstr_guid(&clsid));
3716
3717 hr = CoCreateInstance(&CLSID_WinHttpRequest, 0, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&request);
3718 ok(hr == S_OK, "error %#x\n", hr);
3719
3720 hr = IWinHttpRequest_QueryInterface(request, &IID_IDispatch, (void **)&dispatch);
3721 ok(hr == S_OK, "error %#x\n", hr);
3722 IDispatch_Release(dispatch);
3723
3724 hr = IWinHttpRequest_GetIDsOfNames(request, &IID_NULL, &open, 1, 0x0409, &id);
3725 ok(hr == S_OK, "error %#x\n", hr);
3726 ok(id == DISPID_HTTPREQUEST_OPEN, "expected DISPID_HTTPREQUEST_OPEN, got %u\n", id);
3727
3728 hr = IWinHttpRequest_GetIDsOfNames(request, &IID_NULL, &option, 1, 0x0409, &id);
3729 ok(hr == S_OK, "error %#x\n", hr);
3730 ok(id == DISPID_HTTPREQUEST_OPTION, "expected DISPID_HTTPREQUEST_OPTION, got %u\n", id);
3731
3732 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3733 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3734 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
3735
3736 memset(&params, 0, sizeof(params));
3737 params.cArgs = 2;
3738 params.cNamedArgs = 0;
3739 params.rgvarg = arg;
3740 V_VT(&arg[0]) = VT_I4;
3741 V_I4(&arg[0]) = 1252;
3742 V_VT(&arg[1]) = VT_R8;
3743 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
3744 VariantInit(&ret);
3745 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
3746 DISPATCH_METHOD, &params, NULL, NULL, &err);
3747 ok(hr == S_OK, "error %#x\n", hr);
3748
3749 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3750 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3751 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
3752
3753 memset(&params, 0, sizeof(params));
3754 params.cArgs = 2;
3755 params.cNamedArgs = 0;
3756 params.rgvarg = arg;
3757 V_VT(&arg[0]) = VT_I4;
3758 V_I4(&arg[0]) = 1252;
3759 V_VT(&arg[1]) = VT_R8;
3760 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
3761 VariantInit(&ret);
3762 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
3763 DISPATCH_METHOD | DISPATCH_PROPERTYPUT, &params, NULL, NULL, &err);
3764 ok(hr == S_OK, "error %#x\n", hr);
3765
3766 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3767 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3768 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
3769
3770 memset(&params, 0, sizeof(params));
3771 params.cArgs = 2;
3772 params.cNamedArgs = 0;
3773 params.rgvarg = arg;
3774 V_VT(&arg[0]) = VT_I4;
3775 V_I4(&arg[0]) = 1252;
3776 V_VT(&arg[1]) = VT_R8;
3777 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
3778 VariantInit(&ret);
3779 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
3780 DISPATCH_PROPERTYPUT, &params, NULL, NULL, &err);
3781 ok(hr == S_OK, "error %#x\n", hr);
3782
3783 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3784 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3785 ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
3786
3787 memset(&params, 0, sizeof(params));
3788 params.cArgs = 2;
3789 params.cNamedArgs = 0;
3790 params.rgvarg = arg;
3791 V_VT(&arg[0]) = VT_BSTR;
3792 utf8 = SysAllocString(utf8W);
3793 V_BSTR(&arg[0]) = utf8;
3794 V_VT(&arg[1]) = VT_R8;
3795 V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
3796 hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_METHOD, &params, NULL, NULL, &err);
3797 ok(hr == S_OK, "error %#x\n", hr);
3798
3799 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3800 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3801 ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
3802
3803 VariantInit(&ret);
3804 hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_METHOD, &params, &ret, NULL, &err);
3805 ok(hr == S_OK, "error %#x\n", hr);
3806
3807 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3808 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3809 ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
3810
3811 VariantInit(&ret);
3812 hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
3813 ok(hr == S_OK, "error %#x\n", hr);
3814
3815 request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
3816 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3817 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
3818
3819 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, NULL, NULL, NULL);
3820 ok(hr == S_OK, "error %#x\n", hr);
3821
3822 hr = IWinHttpRequest_Invoke(request, 255, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, NULL, NULL, NULL);
3823 ok(hr == DISP_E_MEMBERNOTFOUND, "error %#x\n", hr);
3824
3825 VariantInit(&ret);
3826 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
3827 ok(hr == DISP_E_UNKNOWNINTERFACE, "error %#x\n", hr);
3828
3829 VariantInit(&ret);
3830 if (0) /* crashes */
3831 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, &ret, NULL, &err);
3832
3833 params.cArgs = 1;
3834 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
3835 ok(hr == DISP_E_TYPEMISMATCH, "error %#x\n", hr);
3836
3837 VariantInit(&arg[2]);
3838 params.cArgs = 3;
3839 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
3840 todo_wine
3841 ok(hr == S_OK, "error %#x\n", hr);
3842
3843 VariantInit(&arg[0]);
3844 VariantInit(&arg[1]);
3845 VariantInit(&arg[2]);
3846
3847 params.cArgs = 1;
3848 V_VT(&arg[0]) = VT_I4;
3849 V_I4(&arg[0]) = WinHttpRequestOption_URLCodePage;
3850 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
3851 ok(hr == S_OK, "error %#x\n", hr);
3852
3853 V_VT(&ret) = 0xdead;
3854 V_I4(&ret) = 0xbeef;
3855 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &params, &ret, NULL, NULL);
3856 ok(hr == S_OK, "error %#x\n", hr);
3857 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3858 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
3859
3860 V_VT(&ret) = 0xdead;
3861 V_I4(&ret) = 0xbeef;
3862 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD, &params, &ret, NULL, NULL);
3863 ok(hr == S_OK, "error %#x\n", hr);
3864 ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
3865 ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
3866
3867 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
3868 ok(hr == S_OK, "error %#x\n", hr);
3869
3870 V_VT(&ret) = 0xdead;
3871 V_I4(&ret) = 0xbeef;
3872 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, 0, &params, &ret, NULL, NULL);
3873 ok(hr == S_OK, "error %#x\n", hr);
3874 ok(V_VT(&ret) == VT_EMPTY, "expected VT_EMPTY, got %d\n", V_VT(&ret));
3875 ok(V_I4(&ret) == 0xbeef || V_I4(&ret) == 0 /* Win8 */, "expected 0xdead, got %d\n", V_I4(&ret));
3876
3877 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, 0, &params, NULL, NULL, NULL);
3878 ok(hr == S_OK, "error %#x\n", hr);
3879
3880 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_IUnknown, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
3881 ok(hr == DISP_E_UNKNOWNINTERFACE, "error %#x\n", hr);
3882
3883 params.cArgs = 2;
3884 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
3885 todo_wine
3886 ok(hr == S_OK, "error %#x\n", hr);
3887
3888 params.cArgs = 0;
3889 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
3890 ok(hr == DISP_E_PARAMNOTFOUND, "error %#x\n", hr);
3891
3892 SysFreeString(utf8);
3893
3894 params.cArgs = 1;
3895 V_VT(&arg[0]) = VT_I4;
3896 V_I4(&arg[0]) = AutoLogonPolicy_Never;
3897 VariantInit(&ret);
3898 hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_SETAUTOLOGONPOLICY, &IID_NULL, 0,
3899 DISPATCH_METHOD, &params, &ret, NULL, NULL);
3900 ok(hr == S_OK, "error %#x\n", hr);
3901
3902 IWinHttpRequest_Release(request);
3903
3904 CoUninitialize();
3905 }
3906
3907 static void test_WinHttpDetectAutoProxyConfigUrl(void)
3908 {
3909 BOOL ret;
3910 WCHAR *url;
3911 DWORD error;
3912
3913 if (0) /* crashes on some win2k systems */
3914 {
3915 SetLastError(0xdeadbeef);
3916 ret = WinHttpDetectAutoProxyConfigUrl( 0, NULL );
3917 error = GetLastError();
3918 ok( !ret, "expected failure\n" );
3919 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3920 }
3921 url = NULL;
3922 SetLastError(0xdeadbeef);
3923 ret = WinHttpDetectAutoProxyConfigUrl( 0, &url );
3924 error = GetLastError();
3925 ok( !ret, "expected failure\n" );
3926 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3927
3928 if (0) /* crashes on some win2k systems */
3929 {
3930 SetLastError(0xdeadbeef);
3931 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, NULL );
3932 error = GetLastError();
3933 ok( !ret, "expected failure\n" );
3934 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3935 }
3936 url = (WCHAR *)0xdeadbeef;
3937 SetLastError(0xdeadbeef);
3938 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, &url );
3939 error = GetLastError();
3940 if (!ret)
3941 {
3942 ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED, "got %u\n", error );
3943 ok( !url || broken(url == (WCHAR *)0xdeadbeef), "got %p\n", url );
3944 }
3945 else
3946 {
3947 trace("%s\n", wine_dbgstr_w(url));
3948 GlobalFree( url );
3949 }
3950
3951 url = (WCHAR *)0xdeadbeef;
3952 SetLastError(0xdeadbeef);
3953 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DHCP, &url );
3954 error = GetLastError();
3955 if (!ret)
3956 {
3957 ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED, "got %u\n", error );
3958 ok( !url || broken(url == (WCHAR *)0xdeadbeef), "got %p\n", url );
3959 }
3960 else
3961 {
3962 ok( error == ERROR_SUCCESS, "got %u\n", error );
3963 trace("%s\n", wine_dbgstr_w(url));
3964 GlobalFree( url );
3965 }
3966 }
3967
3968 static void test_WinHttpGetIEProxyConfigForCurrentUser(void)
3969 {
3970 BOOL ret;
3971 DWORD error;
3972 WINHTTP_CURRENT_USER_IE_PROXY_CONFIG cfg;
3973
3974 memset( &cfg, 0, sizeof(cfg) );
3975
3976 SetLastError(0xdeadbeef);
3977 ret = WinHttpGetIEProxyConfigForCurrentUser( NULL );
3978 error = GetLastError();
3979 ok( !ret, "expected failure\n" );
3980 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
3981
3982 SetLastError(0xdeadbeef);
3983 ret = WinHttpGetIEProxyConfigForCurrentUser( &cfg );
3984 error = GetLastError();
3985 ok( ret, "expected success\n" );
3986 ok( error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* < win7 */, "got %u\n", error );
3987
3988 trace("IEProxy.AutoDetect=%d\n", cfg.fAutoDetect);
3989 trace("IEProxy.AutoConfigUrl=%s\n", wine_dbgstr_w(cfg.lpszAutoConfigUrl));
3990 trace("IEProxy.Proxy=%s\n", wine_dbgstr_w(cfg.lpszProxy));
3991 trace("IEProxy.ProxyBypass=%s\n", wine_dbgstr_w(cfg.lpszProxyBypass));
3992 GlobalFree( cfg.lpszAutoConfigUrl );
3993 GlobalFree( cfg.lpszProxy );
3994 GlobalFree( cfg.lpszProxyBypass );
3995 }
3996
3997 static void test_WinHttpGetProxyForUrl(void)
3998 {
3999 static const WCHAR urlW[] = {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0};
4000 static const WCHAR wpadW[] = {'h','t','t','p',':','/','/','w','p','a','d','/','w','p','a','d','.','d','a','t',0};
4001 static const WCHAR emptyW[] = {0};
4002 BOOL ret;
4003 DWORD error;
4004 HINTERNET session;
4005 WINHTTP_AUTOPROXY_OPTIONS options;
4006 WINHTTP_PROXY_INFO info;
4007
4008 memset( &options, 0, sizeof(options) );
4009
4010 SetLastError(0xdeadbeef);
4011 ret = WinHttpGetProxyForUrl( NULL, NULL, NULL, NULL );
4012 error = GetLastError();
4013 ok( !ret, "expected failure\n" );
4014 ok( error == ERROR_INVALID_HANDLE, "got %u\n", error );
4015
4016 session = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
4017 ok( session != NULL, "failed to open session %u\n", GetLastError() );
4018
4019 SetLastError(0xdeadbeef);
4020 ret = WinHttpGetProxyForUrl( session, NULL, NULL, NULL );
4021 error = GetLastError();
4022 ok( !ret, "expected failure\n" );
4023 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4024
4025 SetLastError(0xdeadbeef);
4026 ret = WinHttpGetProxyForUrl( session, emptyW, NULL, NULL );
4027 error = GetLastError();
4028 ok( !ret, "expected failure\n" );
4029 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4030
4031 SetLastError(0xdeadbeef);
4032 ret = WinHttpGetProxyForUrl( session, urlW, NULL, NULL );
4033 error = GetLastError();
4034 ok( !ret, "expected failure\n" );
4035 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4036
4037 SetLastError(0xdeadbeef);
4038 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
4039 error = GetLastError();
4040 ok( !ret, "expected failure\n" );
4041 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4042
4043 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
4044 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
4045
4046 SetLastError(0xdeadbeef);
4047 ret = WinHttpGetProxyForUrl( session, urlW, &options, NULL );
4048 error = GetLastError();
4049 ok( !ret, "expected failure\n" );
4050 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4051
4052 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
4053 options.dwAutoDetectFlags = 0;
4054
4055 SetLastError(0xdeadbeef);
4056 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
4057 error = GetLastError();
4058 ok( !ret, "expected failure\n" );
4059 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4060
4061 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT | WINHTTP_AUTOPROXY_CONFIG_URL;
4062 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
4063
4064 SetLastError(0xdeadbeef);
4065 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
4066 error = GetLastError();
4067 ok( !ret, "expected failure\n" );
4068 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4069
4070 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
4071 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
4072
4073 memset( &info, 0, sizeof(info) );
4074 SetLastError(0xdeadbeef);
4075 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
4076 error = GetLastError();
4077 if (ret)
4078 {
4079 ok( error == ERROR_SUCCESS, "got %u\n", error );
4080 trace("Proxy.AccessType=%u\n", info.dwAccessType);
4081 trace("Proxy.Proxy=%s\n", wine_dbgstr_w(info.lpszProxy));
4082 trace("Proxy.ProxyBypass=%s\n", wine_dbgstr_w(info.lpszProxyBypass));
4083 GlobalFree( info.lpszProxy );
4084 GlobalFree( info.lpszProxyBypass );
4085 }
4086
4087 options.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
4088 options.dwAutoDetectFlags = 0;
4089 options.lpszAutoConfigUrl = wpadW;
4090
4091 memset( &info, 0, sizeof(info) );
4092 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
4093 if (ret)
4094 {
4095 trace("Proxy.AccessType=%u\n", info.dwAccessType);
4096 trace("Proxy.Proxy=%s\n", wine_dbgstr_w(info.lpszProxy));
4097 trace("Proxy.ProxyBypass=%s\n", wine_dbgstr_w(info.lpszProxyBypass));
4098 GlobalFree( info.lpszProxy );
4099 GlobalFree( info.lpszProxyBypass );
4100 }
4101 WinHttpCloseHandle( session );
4102 }
4103
4104 static void test_chunked_read(void)
4105 {
4106 static const WCHAR verb[] = {'/','t','e','s','t','c','h','u','n','k','e','d',0};
4107 static const WCHAR chunked[] = {'c','h','u','n','k','e','d',0};
4108 WCHAR header[32];
4109 DWORD len, err;
4110 HINTERNET ses, con = NULL, req = NULL;
4111 BOOL ret;
4112
4113 trace( "starting chunked read test\n" );
4114
4115 ses = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
4116 ok( ses != NULL, "WinHttpOpen failed with error %u\n", GetLastError() );
4117 if (!ses) goto done;
4118
4119 con = WinHttpConnect( ses, test_winehq, 0, 0 );
4120 ok( con != NULL, "WinHttpConnect failed with error %u\n", GetLastError() );
4121 if (!con) goto done;
4122
4123 req = WinHttpOpenRequest( con, NULL, verb, NULL, NULL, NULL, 0 );
4124 ok( req != NULL, "WinHttpOpenRequest failed with error %u\n", GetLastError() );
4125 if (!req) goto done;
4126
4127 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
4128 err = GetLastError();
4129 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
4130 {
4131 skip("connection failed, skipping\n");
4132 goto done;
4133 }
4134 ok( ret, "WinHttpSendRequest failed with error %u\n", GetLastError() );
4135
4136 ret = WinHttpReceiveResponse( req, NULL );
4137 ok( ret, "WinHttpReceiveResponse failed with error %u\n", GetLastError() );
4138
4139 header[0] = 0;
4140 len = sizeof(header);
4141 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, header, &len, 0 );
4142 ok( ret, "failed to get TRANSFER_ENCODING header (error %u)\n", GetLastError() );
4143 ok( !lstrcmpW( header, chunked ), "wrong transfer encoding %s\n", wine_dbgstr_w(header) );
4144 trace( "transfer encoding: %s\n", wine_dbgstr_w(header) );
4145
4146 header[0] = 0;
4147 len = sizeof(header);
4148 SetLastError( 0xdeadbeef );
4149 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_CONTENT_LENGTH, NULL, &header, &len, 0 );
4150 ok( !ret, "unexpected CONTENT_LENGTH header %s\n", wine_dbgstr_w(header) );
4151 ok( GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND, "wrong error %u\n", GetLastError() );
4152
4153 trace( "entering query loop\n" );
4154 for (;;)
4155 {
4156 len = 0xdeadbeef;
4157 ret = WinHttpQueryDataAvailable( req, &len );
4158 ok( ret, "WinHttpQueryDataAvailable failed with error %u\n", GetLastError() );
4159 if (ret) ok( len != 0xdeadbeef, "WinHttpQueryDataAvailable return wrong length\n" );
4160 trace( "got %u available\n", len );
4161 if (len)
4162 {
4163 DWORD bytes_read;
4164 char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 );
4165
4166 ret = WinHttpReadData( req, buf, len, &bytes_read );
4167
4168 buf[bytes_read] = 0;
4169 trace( "WinHttpReadData -> %d %u\n", ret, bytes_read );
4170 ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len );
4171 ok( buf[bytes_read - 1] == '\n', "received partial line '%s'\n", buf );
4172
4173 HeapFree( GetProcessHeap(), 0, buf );
4174 if (!bytes_read) break;
4175 }
4176 if (!len) break;
4177 }
4178 trace( "done\n" );
4179
4180 done:
4181 if (req) WinHttpCloseHandle( req );
4182 if (con) WinHttpCloseHandle( con );
4183 if (ses) WinHttpCloseHandle( ses );
4184 }
4185
4186 START_TEST (winhttp)
4187 {
4188 static const WCHAR basicW[] = {'/','b','a','s','i','c',0};
4189 static const WCHAR quitW[] = {'/','q','u','i','t',0};
4190 struct server_info si;
4191 HANDLE thread;
4192 DWORD ret;
4193
4194 test_OpenRequest();
4195 test_SendRequest();
4196 test_WinHttpTimeFromSystemTime();
4197 test_WinHttpTimeToSystemTime();
4198 test_WinHttpAddHeaders();
4199 test_secure_connection();
4200 test_request_parameter_defaults();
4201 test_QueryOption();
4202 test_set_default_proxy_config();
4203 test_empty_headers_param();
4204 test_Timeouts();
4205 test_resolve_timeout();
4206 test_credentials();
4207 test_IWinHttpRequest_Invoke();
4208 test_WinHttpDetectAutoProxyConfigUrl();
4209 test_WinHttpGetIEProxyConfigForCurrentUser();
4210 test_WinHttpGetProxyForUrl();
4211 test_chunked_read();
4212
4213 si.event = CreateEventW(NULL, 0, 0, NULL);
4214 si.port = 7532;
4215
4216 thread = CreateThread(NULL, 0, server_thread, (LPVOID)&si, 0, NULL);
4217 ok(thread != NULL, "failed to create thread %u\n", GetLastError());
4218
4219 ret = WaitForSingleObject(si.event, 10000);
4220 ok(ret == WAIT_OBJECT_0, "failed to start winhttp test server %u\n", GetLastError());
4221 if (ret != WAIT_OBJECT_0)
4222 return;
4223
4224 test_IWinHttpRequest(si.port);
4225 test_connection_info(si.port);
4226 test_basic_request(si.port, NULL, basicW);
4227 test_no_headers(si.port);
4228 test_no_content(si.port);
4229 test_head_request(si.port);
4230 test_not_modified(si.port);
4231 test_basic_authentication(si.port);
4232 test_bad_header(si.port);
4233 test_multiple_reads(si.port);
4234 test_cookies(si.port);
4235
4236 /* send the basic request again to shutdown the server thread */
4237 test_basic_request(si.port, NULL, quitW);
4238
4239 WaitForSingleObject(thread, 3000);
4240 }