winhttp: Fix a crash on Vista and higher.
[wine] / dlls / winhttp / tests / winhttp.c
1 /*
2  * WinHTTP - tests
3  *
4  * Copyright 2008 Google (Zac Brown)
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <windef.h>
24 #include <winbase.h>
25 #include <winhttp.h>
26 #include <wincrypt.h>
27 #include <winreg.h>
28
29 #include "wine/test.h"
30
31 static const WCHAR test_useragent[] =
32     {'W','i','n','e',' ','R','e','g','r','e','s','s','i','o','n',' ','T','e','s','t',0};
33 static const WCHAR test_server[] = {'w','i','n','e','h','q','.','o','r','g',0};
34
35 static void test_QueryOption(void)
36 {
37     BOOL ret;
38     HINTERNET session, request, connection;
39     DWORD feature, size;
40
41     SetLastError(0xdeadbeef);
42     session = WinHttpOpen(test_useragent, 0, 0, 0, 0);
43     ok(session != NULL, "WinHttpOpen failed to open session, error %u\n", GetLastError());
44
45     SetLastError(0xdeadbeef);
46     ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, NULL);
47     ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
48     ok(GetLastError() == ERROR_INVALID_PARAMETER,
49        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
50
51     size = 0xdeadbeef;
52     SetLastError(0xdeadbeef);
53     ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, &size);
54     ok(!ret, "should fail to query option\n");
55     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
56        "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
57     ok(size == 4, "expected 4, got %u\n", size);
58
59     feature = 0xdeadbeef;
60     size = sizeof(feature) - 1;
61     SetLastError(0xdeadbeef);
62     ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
63     ok(!ret, "should fail to query option\n");
64     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
65        "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
66     ok(size == 4, "expected 4, got %u\n", size);
67
68     feature = 0xdeadbeef;
69     size = sizeof(feature) + 1;
70     SetLastError(0xdeadbeef);
71     ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
72     ok(ret, "failed to query option %u\n", GetLastError());
73     ok(size == sizeof(feature), "WinHttpQueryOption should set the size: %u\n", size);
74     ok(feature == WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP,
75        "expected WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP, got %#x\n", feature);
76
77     SetLastError(0xdeadbeef);
78     ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, sizeof(feature));
79     ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
80     ok(GetLastError() == ERROR_INVALID_PARAMETER,
81        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
82
83     feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
84     SetLastError(0xdeadbeef);
85     ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature) - 1);
86     ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
87     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
88        "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
89
90     feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
91     SetLastError(0xdeadbeef);
92     ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature) + 1);
93     ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
94     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
95        "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
96
97     feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
98     SetLastError(0xdeadbeef);
99     ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature));
100     ok(ret, "failed to set redirect policy %u\n", GetLastError());
101
102     feature = 0xdeadbeef;
103     size = sizeof(feature);
104     SetLastError(0xdeadbeef);
105     ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
106     ok(ret, "failed to query option %u\n", GetLastError());
107     ok(feature == WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS,
108        "expected WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS, got %#x\n", feature);
109
110     feature = WINHTTP_DISABLE_COOKIES;
111     SetLastError(0xdeadbeef);
112     ret = WinHttpSetOption(session, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
113     ok(!ret, "should fail to set disable feature for a session\n");
114     ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
115        "expected ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, got %u\n", GetLastError());
116
117     SetLastError(0xdeadbeef);
118     connection = WinHttpConnect(session, test_server, INTERNET_DEFAULT_HTTP_PORT, 0);
119     ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u\n", GetLastError());
120
121     feature = WINHTTP_DISABLE_COOKIES;
122     SetLastError(0xdeadbeef);
123     ret = WinHttpSetOption(connection, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
124     ok(!ret, "should fail to set disable feature for a connection\n");
125     ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
126        "expected ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, got %u\n", GetLastError());
127
128     SetLastError(0xdeadbeef);
129     request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
130                                  WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
131     if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
132     {
133         skip("Network unreachable, skipping the test\n");
134         goto done;
135     }
136
137     feature = 0xdeadbeef;
138     size = sizeof(feature);
139     SetLastError(0xdeadbeef);
140     ret = WinHttpQueryOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, &size);
141     ok(!ret, "should fail to query disable feature for a request\n");
142     ok(GetLastError() == ERROR_INVALID_PARAMETER,
143        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
144
145     feature = 0;
146     size = sizeof(feature);
147     SetLastError(0xdeadbeef);
148     ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
149     ok(ret, "failed to set feature %u\n", GetLastError());
150
151     feature = 0xffffffff;
152     size = sizeof(feature);
153     SetLastError(0xdeadbeef);
154     ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
155     ok(ret, "failed to set feature %u\n", GetLastError());
156
157     feature = WINHTTP_DISABLE_COOKIES;
158     size = sizeof(feature);
159     SetLastError(0xdeadbeef);
160     ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
161     ok(ret, "failed to set feature %u\n", GetLastError());
162
163     size = 0;
164     SetLastError(0xdeadbeef);
165     ret = WinHttpQueryOption(request, WINHTTP_OPTION_DISABLE_FEATURE, NULL, &size);
166     ok(!ret, "should fail to query disable feature for a request\n");
167     ok(GetLastError() == ERROR_INVALID_PARAMETER,
168        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
169
170     SetLastError(0xdeadbeef);
171     ret = WinHttpCloseHandle(request);
172     ok(ret, "WinHttpCloseHandle failed on closing request: %u\n", GetLastError());
173
174 done:
175     SetLastError(0xdeadbeef);
176     ret = WinHttpCloseHandle(connection);
177     ok(ret, "WinHttpCloseHandle failed on closing connection: %u\n", GetLastError());
178     SetLastError(0xdeadbeef);
179     ret = WinHttpCloseHandle(session);
180     ok(ret, "WinHttpCloseHandle failed on closing session: %u\n", GetLastError());
181 }
182
183 static void test_OpenRequest (void)
184 {
185     BOOL ret;
186     HINTERNET session, request, connection;
187
188     session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
189         WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
190     ok(session != NULL, "WinHttpOpen failed to open session.\n");
191
192     /* Test with a bad server name */
193     SetLastError(0xdeadbeef);
194     connection = WinHttpConnect(session, NULL, INTERNET_DEFAULT_HTTP_PORT, 0);
195     ok (connection == NULL, "WinHttpConnect succeeded in opening connection to NULL server argument.\n");
196     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u.\n", GetLastError());
197
198     /* Test with a valid server name */
199     connection = WinHttpConnect (session, test_server, INTERNET_DEFAULT_HTTP_PORT, 0);
200     ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
201
202     request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
203         WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
204     if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
205     {
206         skip("Network unreachable, skipping.\n");
207         goto done;
208     }
209     ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError());
210
211     ret = WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, NULL, 0, 0, 0);
212     ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError());
213     ret = WinHttpCloseHandle(request);
214     ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
215
216  done:
217     ret = WinHttpCloseHandle(connection);
218     ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
219     ret = WinHttpCloseHandle(session);
220     ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
221
222 }
223
224 static void test_SendRequest (void)
225 {
226     HINTERNET session, request, connection;
227     DWORD header_len, optional_len, total_len;
228     DWORD bytes_rw;
229     BOOL ret;
230     CHAR buffer[256];
231     int i;
232
233     static const WCHAR test_site[] = {'c','r','o','s','s','o','v','e','r','.',
234                                 'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
235     static const WCHAR content_type[] =
236         {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t','i','o','n',
237          '/','x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o','d','e','d',0};
238     static const WCHAR test_file[] = {'/','p','o','s','t','t','e','s','t','.','p','h','p',0};
239     static const WCHAR test_verb[] = {'P','O','S','T',0};
240     static CHAR post_data[] = "mode=Test";
241     static CHAR test_post[] = "mode => Test\\0\n";
242
243     header_len = -1L;
244     total_len = optional_len = sizeof(post_data);
245     memset(buffer, 0xff, sizeof(buffer));
246
247     session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
248         WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
249     ok(session != NULL, "WinHttpOpen failed to open session.\n");
250
251     connection = WinHttpConnect (session, test_site, INTERNET_DEFAULT_HTTP_PORT, 0);
252     ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
253
254     request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
255         WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
256     if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
257     {
258         skip("Network unreachable, skipping.\n");
259         goto done;
260     }
261     ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError());
262
263     ret = WinHttpSendRequest(request, content_type, header_len, post_data, optional_len, total_len, 0);
264     ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError());
265
266     for (i = 3; post_data[i]; i++)
267     {
268         bytes_rw = -1;
269         ret = WinHttpWriteData(request, &post_data[i], 1, &bytes_rw);
270         ok(ret == TRUE, "WinHttpWriteData failed: %u.\n", GetLastError());
271         ok(bytes_rw == 1, "WinHttpWriteData failed, wrote %u bytes instead of 1 byte.\n", bytes_rw);
272     }
273
274     ret = WinHttpReceiveResponse(request, NULL);
275     ok(ret == TRUE, "WinHttpReceiveResponse failed: %u.\n", GetLastError());
276
277     bytes_rw = -1;
278     ret = WinHttpReadData(request, buffer, sizeof(buffer) - 1, &bytes_rw);
279     ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
280
281     ok(bytes_rw == strlen(test_post), "Read %u bytes instead of %d.\n", bytes_rw, lstrlen(test_post));
282     ok(strncmp(buffer, test_post, bytes_rw) == 0, "Data read did not match, got '%s'.\n", buffer);
283
284     ret = WinHttpCloseHandle(request);
285     ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
286  done:
287     ret = WinHttpCloseHandle(connection);
288     ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
289     ret = WinHttpCloseHandle(session);
290     ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
291 }
292
293 static void test_WinHttpTimeFromSystemTime(void)
294 {
295     BOOL ret;
296     static const SYSTEMTIME time = {2008, 7, 1, 28, 10, 5, 52, 0};
297     static const WCHAR expected_string[] =
298         {'M','o','n',',',' ','2','8',' ','J','u','l',' ','2','0','0','8',' ',
299          '1','0',':','0','5',':','5','2',' ','G','M','T',0};
300     WCHAR time_string[WINHTTP_TIME_FORMAT_BUFSIZE+1];
301
302     ret = WinHttpTimeFromSystemTime(&time, time_string);
303     ok(ret == TRUE, "WinHttpTimeFromSystemTime failed: %u\n", GetLastError());
304     ok(memcmp(time_string, expected_string, sizeof(expected_string)) == 0,
305         "Time string returned did not match expected time string.\n");
306 }
307
308 static void test_WinHttpTimeToSystemTime(void)
309 {
310     BOOL ret;
311     SYSTEMTIME time;
312     static const SYSTEMTIME expected_time = {2008, 7, 1, 28, 10, 5, 52, 0};
313     static const WCHAR time_string1[] =
314         {'M','o','n',',',' ','2','8',' ','J','u','l',' ','2','0','0','8',' ',
315          +          '1','0',':','0','5',':','5','2',' ','G','M','T','\n',0};
316     static const WCHAR time_string2[] =
317         {' ','m','o','n',' ','2','8',' ','j','u','l',' ','2','0','0','8',' ',
318          '1','0',' ','0','5',' ','5','2','\n',0};
319
320     ret = WinHttpTimeToSystemTime(time_string1, &time);
321     ok(ret == TRUE, "WinHttpTimeToSystemTime failed: %u\n", GetLastError());
322     ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
323         "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
324
325     ret = WinHttpTimeToSystemTime(time_string2, &time);
326     ok(ret == TRUE, "WinHttpTimeToSystemTime failed: %u\n", GetLastError());
327     ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
328         "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
329 }
330
331 static void test_WinHttpAddHeaders(void)
332 {
333     HINTERNET session, request, connection;
334     BOOL ret;
335     WCHAR buffer[MAX_PATH];
336     WCHAR check_buffer[MAX_PATH];
337     DWORD index, len, oldlen;
338
339     static const WCHAR test_site[] = {'c','r','o','s','s','o','v','e','r','.',
340                                 'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
341     static const WCHAR test_file[] = {'/','p','o','s','t','t','e','s','t','.','p','h','p',0};
342     static const WCHAR test_verb[] = {'P','O','S','T',0};
343
344     static const WCHAR test_header_begin[] =
345         {'P','O','S','T',' ','/','p','o','s','t','t','e','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
346     static const WCHAR full_path_test_header_begin[] =
347         {'P','O','S','T',' ','h','t','t','p',':','/','/','c','r','o','s','s','o','v','e','r','.','c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',':','8','0','/','p','o','s','t','t','e','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
348     static const WCHAR test_header_end[] = {'\r','\n','\r','\n',0};
349     static const WCHAR test_header_name[] = {'W','a','r','n','i','n','g',0};
350
351     static const WCHAR test_flag_coalesce[] = {'t','e','s','t','2',',',' ','t','e','s','t','4',0};
352     static const WCHAR test_flag_coalesce_comma[] =
353         {'t','e','s','t','2',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',0};
354     static const WCHAR test_flag_coalesce_semicolon[] =
355         {'t','e','s','t','2',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',';',' ','t','e','s','t','6',0};
356
357     static const WCHAR field[] = {'f','i','e','l','d',0};
358     static const WCHAR value[] = {'v','a','l','u','e',' ',0};
359
360     static const WCHAR test_headers[][14] =
361         {
362             {'W','a','r','n','i','n','g',':','t','e','s','t','1',0},
363             {'W','a','r','n','i','n','g',':','t','e','s','t','2',0},
364             {'W','a','r','n','i','n','g',':','t','e','s','t','3',0},
365             {'W','a','r','n','i','n','g',':','t','e','s','t','4',0},
366             {'W','a','r','n','i','n','g',':','t','e','s','t','5',0},
367             {'W','a','r','n','i','n','g',':','t','e','s','t','6',0},
368             {'W','a','r','n','i','n','g',':','t','e','s','t','7',0},
369             {0},
370             {':',0},
371             {'a',':',0},
372             {':','b',0},
373             {'c','d',0},
374             {' ','e',' ',':','f',0},
375             {'f','i','e','l','d',':',' ','v','a','l','u','e',' ',0}
376         };
377     static const WCHAR test_indices[][6] =
378         {
379             {'t','e','s','t','1',0},
380             {'t','e','s','t','2',0},
381             {'t','e','s','t','3',0},
382             {'t','e','s','t','4',0}
383         };
384
385     session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
386         WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
387     ok(session != NULL, "WinHttpOpen failed to open session.\n");
388
389     connection = WinHttpConnect (session, test_site, INTERNET_DEFAULT_HTTP_PORT, 0);
390     ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
391
392     request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
393         WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
394     if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
395     {
396         skip("Network unreachable, skipping.\n");
397         goto done;
398     }
399     ok(request != NULL, "WinHttpOpenRequest failed to open a request, error: %u.\n", GetLastError());
400
401     index = 0;
402     len = sizeof(buffer);
403     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
404         test_header_name, buffer, &len, &index);
405     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, found 'Warning' header.\n");
406     ret = WinHttpAddRequestHeaders(request, test_headers[0], -1L, WINHTTP_ADDREQ_FLAG_ADD);
407     ok(ret == TRUE, "WinHttpAddRequestHeader failed to add new header, got %d with error %u.\n", ret, GetLastError());
408
409     index = 0;
410     len = sizeof(buffer);
411     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
412         test_header_name, buffer, &len, &index);
413     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
414     ok(index == 1, "WinHttpQueryHeaders failed: header index not incremented\n");
415     ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders failed: incorrect string returned\n");
416     ok(len == 5*sizeof(WCHAR), "WinHttpQueryHeaders failed: invalid length returned, expected 5, got %d\n", len);
417
418     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
419         test_header_name, buffer, &len, &index);
420     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, second index should not exist.\n");
421
422     /* Try to fetch the header info with a buffer that's big enough to fit the
423      * string but not the NULL terminator.
424      */
425     index = 0;
426     len = 5*sizeof(WCHAR);
427     memset(check_buffer, 0xab, sizeof(check_buffer));
428     memcpy(buffer, check_buffer, sizeof(buffer));
429     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
430         test_header_name, buffer, &len, &index);
431     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded with a buffer that's too small.\n");
432     ok(memcmp(buffer, check_buffer, sizeof(buffer)) == 0,
433             "WinHttpQueryHeaders failed, modified the buffer when it should not have.\n");
434     ok(len == 6*sizeof(WCHAR), "WinHttpQueryHeaders returned invalid length, expected 12, got %d\n", len);
435
436     /* Try with a NULL buffer */
437     index = 0;
438     len = sizeof(buffer);
439     SetLastError(0xdeadbeef);
440     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
441         test_header_name, NULL, &len, &index);
442     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
443     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
444     ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
445     ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
446
447     /* Try with a NULL buffer and a length that's too small */
448     index = 0;
449     len = 10;
450     SetLastError(0xdeadbeef);
451     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
452         test_header_name, NULL, &len, &index);
453     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
454     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
455         "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICENT_BUFFER, go %u\n", GetLastError());
456     ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
457     ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
458
459     index = 0;
460     len = 0;
461     SetLastError(0xdeadbeef);
462     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
463         test_header_name, NULL, &len, &index);
464     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
465     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
466         "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
467     ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
468     ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
469
470     /* valid query */
471     oldlen = len;
472     index = 0;
473     len = sizeof(buffer);
474     memset(buffer, 0xff, sizeof(buffer));
475     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
476         test_header_name, buffer, &len, &index);
477     ok(ret == TRUE, "WinHttpQueryHeaders failed: got %d\n", ret);
478     ok(len + sizeof(WCHAR) <= oldlen, "WinHttpQueryHeaders resulting length longer than advertized.\n");
479     ok((len < sizeof(buffer) - sizeof(WCHAR)) && buffer[len / sizeof(WCHAR)] == 0, "WinHttpQueryHeaders did not append NULL terminator\n");
480     ok(len == lstrlenW(buffer) * sizeof(WCHAR), "WinHttpQueryHeaders returned incorrect length.\n");
481     ok(memcmp(buffer, test_header_begin, sizeof(test_header_begin)) == 0 ||
482         memcmp(buffer, full_path_test_header_begin, sizeof(full_path_test_header_begin)) == 0,
483         "WinHttpQueryHeaders returned invalid beginning of header string.\n");
484     ok(memcmp(buffer + lstrlenW(buffer) - 4, test_header_end, sizeof(test_header_end)) == 0,
485         "WinHttpQueryHeaders returned invalid end of header string.\n");
486     ok(index == 0, "WinHttpQueryHeaders incremented header index.\n");
487
488     index = 0;
489     len = 0;
490     SetLastError(0xdeadbeef);
491     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
492         test_header_name, NULL, &len, &index);
493     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
494     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
495         "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
496     ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
497     ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
498
499     oldlen = len;
500     index = 0;
501     len = sizeof(buffer);
502     memset(buffer, 0xff, sizeof(buffer));
503     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
504         test_header_name, buffer, &len, &index);
505     ok(ret == TRUE, "WinHttpQueryHeaders failed %u\n", GetLastError());
506     ok(len + sizeof(WCHAR) <= oldlen, "resulting length longer than advertized\n");
507     ok((len < sizeof(buffer) - sizeof(WCHAR)) && !buffer[len / sizeof(WCHAR)] && !buffer[len / sizeof(WCHAR) - 1],
508         "no double NULL terminator\n");
509     ok(memcmp(buffer, test_header_begin, sizeof(test_header_begin)) == 0 ||
510         memcmp(buffer, full_path_test_header_begin, sizeof(full_path_test_header_begin)) == 0,
511         "invalid beginning of header string.\n");
512     ok(index == 0, "header index was incremented\n");
513
514     /* tests for more indices */
515     ret = WinHttpAddRequestHeaders(request, test_headers[1], -1L, WINHTTP_ADDREQ_FLAG_ADD);
516     ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header: %d\n", ret);
517
518     index = 0;
519     len = sizeof(buffer);
520     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
521         test_header_name, buffer, &len, &index);
522     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
523     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
524     ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
525
526     len = sizeof(buffer);
527     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
528         test_header_name, buffer, &len, &index);
529     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
530     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
531     ok(memcmp(buffer, test_indices[1], sizeof(test_indices[1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
532
533     ret = WinHttpAddRequestHeaders(request, test_headers[2], -1L, WINHTTP_ADDREQ_FLAG_REPLACE);
534     ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header.\n");
535
536     index = 0;
537     len = sizeof(buffer);
538     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
539         test_header_name, buffer, &len, &index);
540     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
541     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
542     ok(memcmp(buffer, test_indices[1], sizeof(test_indices[1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
543
544     len = sizeof(buffer);
545     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
546         test_header_name, buffer, &len, &index);
547     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
548     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
549     ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
550
551     /* add if new flag */
552     ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW);
553     ok(ret == FALSE, "WinHttpAddRequestHeaders incorrectly replaced existing header.\n");
554
555     index = 0;
556     len = sizeof(buffer);
557     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
558         test_header_name, buffer, &len, &index);
559     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
560     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
561     ok(memcmp(buffer, test_indices[1], sizeof(test_indices[1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
562
563     len = sizeof(buffer);
564     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
565         test_header_name, buffer, &len, &index);
566     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
567     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
568     ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
569
570     len = sizeof(buffer);
571     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
572         test_header_name, buffer, &len, &index);
573     ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
574
575     /* coalesce flag */
576     ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_COALESCE);
577     ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE.\n");
578
579     index = 0;
580     len = sizeof(buffer);
581     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
582         test_header_name, buffer, &len, &index);
583     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
584     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
585     ok(memcmp(buffer, test_flag_coalesce, sizeof(test_flag_coalesce)) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
586
587     len = sizeof(buffer);
588     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
589         test_header_name, buffer, &len, &index);
590     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
591     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
592     ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
593
594     len = sizeof(buffer);
595     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
596         test_header_name, buffer, &len, &index);
597     ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
598
599     /* coalesce with comma flag */
600     ret = WinHttpAddRequestHeaders(request, test_headers[4], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA);
601     ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA.\n");
602
603     index = 0;
604     len = sizeof(buffer);
605     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
606         test_header_name, buffer, &len, &index);
607     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
608     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
609     ok(memcmp(buffer, test_flag_coalesce_comma, sizeof(test_flag_coalesce_comma)) == 0,
610         "WinHttpQueryHeaders returned incorrect string.\n");
611
612     len = sizeof(buffer);
613     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
614         test_header_name, buffer, &len, &index);
615     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
616     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
617     ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
618
619     len = sizeof(buffer);
620     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
621         test_header_name, buffer, &len, &index);
622     ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
623
624
625     /* coalesce with semicolon flag */
626     ret = WinHttpAddRequestHeaders(request, test_headers[5], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON);
627     ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON.\n");
628
629     index = 0;
630     len = sizeof(buffer);
631     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
632         test_header_name, buffer, &len, &index);
633     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
634     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
635     ok(memcmp(buffer, test_flag_coalesce_semicolon, sizeof(test_flag_coalesce_semicolon)) == 0,
636             "WinHttpQueryHeaders returned incorrect string.\n");
637
638     len = sizeof(buffer);
639     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
640         test_header_name, buffer, &len, &index);
641     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
642     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
643     ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
644
645     len = sizeof(buffer);
646     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
647         test_header_name, buffer, &len, &index);
648     ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
649
650     /* add and replace flags */
651     ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
652     ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE.\n");
653
654     index = 0;
655     len = sizeof(buffer);
656     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
657         test_header_name, buffer, &len, &index);
658     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
659     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
660     ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
661
662     len = sizeof(buffer);
663     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
664         test_header_name, buffer, &len, &index);
665     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
666     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
667     ok(memcmp(buffer, test_indices[3], sizeof(test_indices[2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
668
669     len = sizeof(buffer);
670     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
671         test_header_name, buffer, &len, &index);
672     ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
673
674     ret = WinHttpAddRequestHeaders(request, test_headers[8], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
675     ok(!ret, "WinHttpAddRequestHeaders failed\n");
676
677     ret = WinHttpAddRequestHeaders(request, test_headers[9], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
678     ok(ret, "WinHttpAddRequestHeaders failed\n");
679
680     ret = WinHttpAddRequestHeaders(request, test_headers[10], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
681     ok(!ret, "WinHttpAddRequestHeaders failed\n");
682
683     ret = WinHttpAddRequestHeaders(request, test_headers[11], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
684     ok(!ret, "WinHttpAddRequestHeaders failed\n");
685
686     ret = WinHttpAddRequestHeaders(request, test_headers[12], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
687     ok(!ret, "WinHttpAddRequestHeaders failed\n");
688
689     ret = WinHttpAddRequestHeaders(request, test_headers[13], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
690     ok(ret, "WinHttpAddRequestHeaders failed\n");
691
692     index = 0;
693     buffer[0] = 0;
694     len = sizeof(buffer);
695     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
696         field, buffer, &len, &index);
697     ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
698     ok(!memcmp(buffer, value, sizeof(value)), "unexpected result\n");
699
700     ret = WinHttpCloseHandle(request);
701     ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
702  done:
703     ret = WinHttpCloseHandle(connection);
704     ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
705     ret = WinHttpCloseHandle(session);
706     ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
707
708 }
709
710 static void test_secure_connection(void)
711 {
712     static const WCHAR google[] = {'w','w','w','.','g','o','o','g','l','e','.','c','o','m',0};
713
714     HANDLE ses, con, req;
715     DWORD size, status, policy, bitness;
716     BOOL ret;
717     CERT_CONTEXT *cert;
718
719     ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
720     ok(ses != NULL, "failed to open session %u\n", GetLastError());
721
722     policy = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
723     ret = WinHttpSetOption(ses, WINHTTP_OPTION_REDIRECT_POLICY, &policy, sizeof(policy));
724     ok(ret, "failed to set redirect policy %u\n", GetLastError());
725
726     con = WinHttpConnect(ses, google, 443, 0);
727     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
728
729     /* try without setting WINHTTP_FLAG_SECURE */
730     req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
731     ok(req != NULL, "failed to open a request %u\n", GetLastError());
732
733     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
734     ok(ret, "failed to send request %u\n", GetLastError());
735
736     ret = WinHttpReceiveResponse(req, NULL);
737     ok(!ret, "succeeded unexpectedly\n");
738
739     size = 0;
740     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL);
741     ok(!ret, "succeeded unexpectedly\n");
742
743     WinHttpCloseHandle(req);
744
745     req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, WINHTTP_FLAG_SECURE);
746     ok(req != NULL, "failed to open a request %u\n", GetLastError());
747
748     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
749     ok(ret, "failed to send request %u\n", GetLastError());
750
751     size = sizeof(cert);
752     ret = WinHttpQueryOption(req, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert, &size );
753     ok(ret, "failed to retrieve certificate context %u\n", GetLastError());
754
755     size = sizeof(bitness);
756     ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_KEY_BITNESS, &bitness, &size );
757     ok(ret, "failed to retrieve key bitness %u\n", GetLastError());
758
759     ret = WinHttpReceiveResponse(req, NULL);
760     ok(ret, "failed to receive response %u\n", GetLastError());
761
762     size = sizeof(status);
763     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
764     ok(ret, "failed unexpectedly %u\n", GetLastError());
765     ok(status == 200, "request failed unexpectedly %u\n", status);
766
767     size = 0;
768     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL);
769     ok(!ret, "succeeded unexpectedly\n");
770
771     WinHttpCloseHandle(req);
772     WinHttpCloseHandle(con);
773     WinHttpCloseHandle(ses);
774 }
775
776 static void test_request_parameter_defaults(void)
777 {
778     static const WCHAR empty[] = {0};
779     static const WCHAR codeweavers[] = {'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
780
781     HANDLE ses, con, req;
782     DWORD size, status;
783     BOOL ret;
784
785     ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
786     ok(ses != NULL, "failed to open session %u\n", GetLastError());
787
788     con = WinHttpConnect(ses, codeweavers, 0, 0);
789     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
790
791     req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
792     ok(req != NULL, "failed to open a request %u\n", GetLastError());
793
794     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
795     ok(ret, "failed to send request %u\n", GetLastError());
796
797     ret = WinHttpReceiveResponse(req, NULL);
798     ok(ret, "failed to receive response %u\n", GetLastError());
799
800     size = sizeof(status);
801     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
802     ok(ret, "failed unexpectedly %u\n", GetLastError());
803     ok(status == 200, "request failed unexpectedly %u\n", status);
804
805     WinHttpCloseHandle(req);
806
807     req = WinHttpOpenRequest(con, empty, empty, empty, NULL, NULL, 0);
808     ok(req != NULL, "failed to open a request %u\n", GetLastError());
809
810     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
811     ok(ret, "failed to send request %u\n", GetLastError());
812
813     ret = WinHttpReceiveResponse(req, NULL);
814     ok(ret, "failed to receive response %u\n", GetLastError());
815
816     size = sizeof(status);
817     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
818     ok(ret, "failed unexpectedly %u\n", GetLastError());
819     ok(status == 200, "request failed unexpectedly %u\n", status);
820
821     WinHttpCloseHandle(req);
822     WinHttpCloseHandle(con);
823     WinHttpCloseHandle(ses);
824 }
825
826 static const WCHAR Connections[] = {
827     'S','o','f','t','w','a','r','e','\\',
828     'M','i','c','r','o','s','o','f','t','\\',
829     'W','i','n','d','o','w','s','\\',
830     'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
831     'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
832     'C','o','n','n','e','c','t','i','o','n','s',0 };
833 static const WCHAR WinHttpSettings[] = {
834     'W','i','n','H','t','t','p','S','e','t','t','i','n','g','s',0 };
835
836 static DWORD get_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD *type )
837 {
838     LONG l;
839     HKEY key;
840     DWORD ret = 0;
841
842     l = RegOpenKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, KEY_READ, &key );
843     if (!l)
844     {
845         DWORD size = 0;
846
847         l = RegQueryValueExW( key, WinHttpSettings, NULL, type, NULL, &size );
848         if (!l)
849         {
850             if (size <= len)
851                 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, buf,
852                     &size );
853             if (!l)
854                 ret = size;
855         }
856         RegCloseKey( key );
857     }
858     return ret;
859 }
860
861 static void set_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD type )
862 {
863     LONG l;
864     HKEY key;
865
866     l = RegCreateKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, NULL, 0,
867         KEY_WRITE, NULL, &key, NULL );
868     if (!l)
869     {
870         RegSetValueExW( key, WinHttpSettings, 0, type, buf, len );
871         RegCloseKey( key );
872     }
873 }
874
875 static void test_set_default_proxy_config(void)
876 {
877     static const WCHAR wideString[] = { 0x226f, 0x575b, 0 };
878     static const WCHAR normalString[] = { 'f','o','o',0 };
879     DWORD type, len;
880     BYTE *saved_proxy_settings = NULL;
881     WINHTTP_PROXY_INFO info;
882     BOOL ret;
883
884     /* FIXME: it would be simpler to read the current settings using
885      * WinHttpGetDefaultProxyConfiguration and save them using
886      * WinHttpSetDefaultProxyConfiguration, but they appear to have a bug.
887      *
888      * If a proxy is configured in the registry, e.g. via 'proxcfg -p "foo"',
889      * the access type reported by WinHttpGetDefaultProxyConfiguration is 1,
890      * WINHTTP_ACCESS_TYPE_NO_PROXY, whereas it should be
891      * WINHTTP_ACCESS_TYPE_NAMED_PROXY.
892      * If WinHttpSetDefaultProxyConfiguration is called with dwAccessType = 1,
893      * the lpszProxy and lpszProxyBypass values are ignored.
894      * Thus, if a proxy is set with proxycfg, then calling
895      * WinHttpGetDefaultProxyConfiguration followed by
896      * WinHttpSetDefaultProxyConfiguration results in the proxy settings
897      * getting deleted from the registry.
898      *
899      * Instead I read the current registry value and restore it directly.
900      */
901     len = get_default_proxy_reg_value( NULL, 0, &type );
902     if (len)
903     {
904         saved_proxy_settings = HeapAlloc( GetProcessHeap(), 0, len );
905         len = get_default_proxy_reg_value( saved_proxy_settings, len, &type );
906     }
907
908     if (0)
909     {
910         /* Crashes on Vista and higher */
911         SetLastError(0xdeadbeef);
912         ret = WinHttpSetDefaultProxyConfiguration(NULL);
913         ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
914             "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
915     }
916
917     /* test with invalid access type */
918     info.dwAccessType = 0xdeadbeef;
919     info.lpszProxy = info.lpszProxyBypass = NULL;
920     SetLastError(0xdeadbeef);
921     ret = WinHttpSetDefaultProxyConfiguration(&info);
922     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
923         "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
924
925     /* at a minimum, the proxy server must be set */
926     info.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
927     info.lpszProxy = info.lpszProxyBypass = NULL;
928     SetLastError(0xdeadbeef);
929     ret = WinHttpSetDefaultProxyConfiguration(&info);
930     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
931         "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
932     info.lpszProxyBypass = normalString;
933     SetLastError(0xdeadbeef);
934     ret = WinHttpSetDefaultProxyConfiguration(&info);
935     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
936         "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
937
938     /* the proxy server can't have wide characters */
939     info.lpszProxy = wideString;
940     SetLastError(0xdeadbeef);
941     ret = WinHttpSetDefaultProxyConfiguration(&info);
942     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
943         "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
944
945     info.lpszProxy = normalString;
946     SetLastError(0xdeadbeef);
947     ret = WinHttpSetDefaultProxyConfiguration(&info);
948     ok(ret, "WinHttpSetDefaultProxyConfiguration failed: %d\n", GetLastError());
949
950     set_default_proxy_reg_value( saved_proxy_settings, len, type );
951 }
952
953 START_TEST (winhttp)
954 {
955     test_OpenRequest();
956     test_SendRequest();
957     test_WinHttpTimeFromSystemTime();
958     test_WinHttpTimeToSystemTime();
959     test_WinHttpAddHeaders();
960     test_secure_connection();
961     test_request_parameter_defaults();
962     test_QueryOption();
963     test_set_default_proxy_config();
964 }