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