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