winhttp: Add version resource.
[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
28 #include "wine/test.h"
29
30 static const WCHAR test_useragent[] =
31     {'W','i','n','e',' ','R','e','g','r','e','s','s','i','o','n',' ','T','e','s','t',0};
32 static const WCHAR test_server[] = {'w','i','n','e','h','q','.','o','r','g',0};
33
34 static void test_OpenRequest (void)
35 {
36     BOOL ret;
37     HINTERNET session, request, connection;
38
39     session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
40         WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
41     ok(session != NULL, "WinHttpOpen failed to open session.\n");
42
43     /* Test with a bad server name */
44     SetLastError(0xdeadbeef);
45     connection = WinHttpConnect(session, NULL, INTERNET_DEFAULT_HTTP_PORT, 0);
46     ok (connection == NULL, "WinHttpConnect succeeded in opening connection to NULL server argument.\n");
47     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u.\n", GetLastError());
48
49     /* Test with a valid server name */
50     connection = WinHttpConnect (session, test_server, INTERNET_DEFAULT_HTTP_PORT, 0);
51     ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
52
53     request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
54         WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
55     if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
56     {
57         skip("Network unreachable, skipping.\n");
58         goto done;
59     }
60     ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError());
61
62     ret = WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, NULL, 0, 0, 0);
63     ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError());
64     ret = WinHttpCloseHandle(request);
65     ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
66
67  done:
68     ret = WinHttpCloseHandle(connection);
69     ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
70     ret = WinHttpCloseHandle(session);
71     ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
72
73 }
74
75 static void test_SendRequest (void)
76 {
77     HINTERNET session, request, connection;
78     DWORD header_len, optional_len, total_len;
79     DWORD bytes_rw;
80     BOOL ret;
81     CHAR buffer[256];
82     int i;
83
84     static const WCHAR test_site[] = {'c','r','o','s','s','o','v','e','r','.',
85                                 'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
86     static const WCHAR content_type[] =
87         {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t','i','o','n',
88          '/','x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o','d','e','d',0};
89     static const WCHAR test_file[] = {'/','p','o','s','t','t','e','s','t','.','p','h','p',0};
90     static const WCHAR test_verb[] = {'P','O','S','T',0};
91     static CHAR post_data[] = "mode=Test";
92     static CHAR test_post[] = "mode => Test\\0\n";
93
94     header_len = -1L;
95     total_len = optional_len = sizeof(post_data);
96     memset(buffer, 0xff, sizeof(buffer));
97
98     session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
99         WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
100     ok(session != NULL, "WinHttpOpen failed to open session.\n");
101
102     connection = WinHttpConnect (session, test_site, INTERNET_DEFAULT_HTTP_PORT, 0);
103     ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
104
105     request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
106         WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
107     if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
108     {
109         skip("Network unreachable, skipping.\n");
110         goto done;
111     }
112     ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError());
113
114     ret = WinHttpSendRequest(request, content_type, header_len, post_data, optional_len, total_len, 0);
115     ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError());
116
117     for (i = 3; post_data[i]; i++)
118     {
119         bytes_rw = -1;
120         ret = WinHttpWriteData(request, &post_data[i], 1, &bytes_rw);
121         ok(ret == TRUE, "WinHttpWriteData failed: %u.\n", GetLastError());
122         ok(bytes_rw == 1, "WinHttpWriteData failed, wrote %u bytes instead of 1 byte.\n", bytes_rw);
123     }
124
125     ret = WinHttpReceiveResponse(request, NULL);
126     ok(ret == TRUE, "WinHttpReceiveResponse failed: %u.\n", GetLastError());
127
128     bytes_rw = -1;
129     ret = WinHttpReadData(request, buffer, sizeof(buffer) - 1, &bytes_rw);
130     ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
131
132     ok(bytes_rw == strlen(test_post), "Read %u bytes instead of %d.\n", bytes_rw, lstrlen(test_post));
133     ok(strncmp(buffer, test_post, bytes_rw) == 0, "Data read did not match, got '%s'.\n", buffer);
134
135     ret = WinHttpCloseHandle(request);
136     ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
137  done:
138     ret = WinHttpCloseHandle(connection);
139     ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
140     ret = WinHttpCloseHandle(session);
141     ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
142 }
143
144 static void test_WinHttpTimeFromSystemTime(void)
145 {
146     BOOL ret;
147     static const SYSTEMTIME time = {2008, 7, 1, 28, 10, 5, 52, 0};
148     static const WCHAR expected_string[] =
149         {'M','o','n',',',' ','2','8',' ','J','u','l',' ','2','0','0','8',' ',
150          '1','0',':','0','5',':','5','2',' ','G','M','T',0};
151     WCHAR time_string[WINHTTP_TIME_FORMAT_BUFSIZE+1];
152
153     ret = WinHttpTimeFromSystemTime(&time, time_string);
154     ok(ret == TRUE, "WinHttpTimeFromSystemTime failed: %u\n", GetLastError());
155     ok(memcmp(time_string, expected_string, sizeof(expected_string)) == 0,
156         "Time string returned did not match expected time string.\n");
157 }
158
159 static void test_WinHttpTimeToSystemTime(void)
160 {
161     BOOL ret;
162     SYSTEMTIME time;
163     static const SYSTEMTIME expected_time = {2008, 7, 1, 28, 10, 5, 52, 0};
164     static const WCHAR time_string1[] =
165         {'M','o','n',',',' ','2','8',' ','J','u','l',' ','2','0','0','8',' ',
166          +          '1','0',':','0','5',':','5','2',' ','G','M','T','\n',0};
167     static const WCHAR time_string2[] =
168         {' ','m','o','n',' ','2','8',' ','j','u','l',' ','2','0','0','8',' ',
169          '1','0',' ','0','5',' ','5','2','\n',0};
170
171     ret = WinHttpTimeToSystemTime(time_string1, &time);
172     ok(ret == TRUE, "WinHttpTimeToSystemTime failed: %u\n", GetLastError());
173     ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
174         "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
175
176     ret = WinHttpTimeToSystemTime(time_string2, &time);
177     ok(ret == TRUE, "WinHttpTimeToSystemTime failed: %u\n", GetLastError());
178     ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
179         "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
180 }
181
182 static void test_WinHttpAddHeaders(void)
183 {
184     HINTERNET session, request, connection;
185     BOOL ret;
186     WCHAR buffer[MAX_PATH];
187     WCHAR check_buffer[MAX_PATH];
188     DWORD index, len, oldlen;
189
190     static const WCHAR test_site[] = {'c','r','o','s','s','o','v','e','r','.',
191                                 'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
192     static const WCHAR test_file[] = {'/','p','o','s','t','t','e','s','t','.','p','h','p',0};
193     static const WCHAR test_verb[] = {'P','O','S','T',0};
194
195     static const WCHAR test_header_begin[] =
196         {'P','O','S','T',' ','/','p','o','s','t','t','e','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
197     static const WCHAR test_header_end[] = {'\r','\n','\r','\n',0};
198     static const WCHAR test_header_name[] = {'W','a','r','n','i','n','g',0};
199
200     static const WCHAR test_flag_coalesce[] = {'t','e','s','t','2',',',' ','t','e','s','t','4',0};
201     static const WCHAR test_flag_coalesce_comma[] =
202         {'t','e','s','t','2',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',0};
203     static const WCHAR test_flag_coalesce_semicolon[] =
204         {'t','e','s','t','2',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',';',' ','t','e','s','t','6',0};
205
206     static const WCHAR field[] = {'f','i','e','l','d',0};
207     static const WCHAR value[] = {'v','a','l','u','e',' ',0};
208
209     static const WCHAR test_headers[][14] =
210         {
211             {'W','a','r','n','i','n','g',':','t','e','s','t','1',0},
212             {'W','a','r','n','i','n','g',':','t','e','s','t','2',0},
213             {'W','a','r','n','i','n','g',':','t','e','s','t','3',0},
214             {'W','a','r','n','i','n','g',':','t','e','s','t','4',0},
215             {'W','a','r','n','i','n','g',':','t','e','s','t','5',0},
216             {'W','a','r','n','i','n','g',':','t','e','s','t','6',0},
217             {'W','a','r','n','i','n','g',':','t','e','s','t','7',0},
218             {0},
219             {':',0},
220             {'a',':',0},
221             {':','b',0},
222             {'c','d',0},
223             {' ','e',' ',':','f',0},
224             {'f','i','e','l','d',':',' ','v','a','l','u','e',' ',0}
225         };
226     static const WCHAR test_indices[][6] =
227         {
228             {'t','e','s','t','1',0},
229             {'t','e','s','t','2',0},
230             {'t','e','s','t','3',0},
231             {'t','e','s','t','4',0}
232         };
233
234     session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
235         WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
236     ok(session != NULL, "WinHttpOpen failed to open session.\n");
237
238     connection = WinHttpConnect (session, test_site, INTERNET_DEFAULT_HTTP_PORT, 0);
239     ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
240
241     request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
242         WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
243     if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
244     {
245         skip("Network unreachable, skipping.\n");
246         goto done;
247     }
248     ok(request != NULL, "WinHttpOpenRequest failed to open a request, error: %u.\n", GetLastError());
249
250     index = 0;
251     len = sizeof(buffer);
252     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
253         test_header_name, buffer, &len, &index);
254     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, found 'Warning' header.\n");
255     ret = WinHttpAddRequestHeaders(request, test_headers[0], -1L, WINHTTP_ADDREQ_FLAG_ADD);
256     ok(ret == TRUE, "WinHttpAddRequestHeader failed to add new header, got %d with error %u.\n", ret, GetLastError());
257
258     index = 0;
259     len = sizeof(buffer);
260     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
261         test_header_name, buffer, &len, &index);
262     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
263     ok(index == 1, "WinHttpQueryHeaders failed: header index not incremented\n");
264     ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders failed: incorrect string returned\n");
265     ok(len == 5*sizeof(WCHAR), "WinHttpQueryHeaders failed: invalid length returned, expected 5, got %d\n", len);
266
267     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
268         test_header_name, buffer, &len, &index);
269     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, second index should not exist.\n");
270
271     /* Try to fetch the header info with a buffer that's big enough to fit the
272      * string but not the NULL terminator.
273      */
274     index = 0;
275     len = 5*sizeof(WCHAR);
276     memcpy(buffer, check_buffer, sizeof(buffer));
277     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
278         test_header_name, buffer, &len, &index);
279     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded with a buffer that's too small.\n");
280     ok(memcmp(buffer, check_buffer, sizeof(buffer)) == 0,
281             "WinHttpQueryHeaders failed, modified the buffer when it should not have.\n");
282     ok(len == 6*sizeof(WCHAR), "WinHttpQueryHeaders returned invalid length, expected 12, got %d\n", len);
283
284     /* Try with a NULL buffer */
285     index = 0;
286     len = sizeof(buffer);
287     SetLastError(0xdeadbeef);
288     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
289         test_header_name, NULL, &len, &index);
290     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
291     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
292     ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
293     ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
294
295     /* Try with a NULL buffer and a length that's too small */
296     index = 0;
297     len = 10;
298     SetLastError(0xdeadbeef);
299     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
300         test_header_name, NULL, &len, &index);
301     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
302     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
303         "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICENT_BUFFER, go %u\n", GetLastError());
304     ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
305     ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
306
307     index = 0;
308     len = 0;
309     SetLastError(0xdeadbeef);
310     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
311         test_header_name, NULL, &len, &index);
312     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
313     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
314         "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
315     ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
316     ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
317
318     /* valid query */
319     oldlen = len;
320     index = 0;
321     len = sizeof(buffer);
322     memset(buffer, 0xff, sizeof(buffer));
323     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
324         test_header_name, buffer, &len, &index);
325     ok(ret == TRUE, "WinHttpQueryHeaders failed: got %d\n", ret);
326     ok(len + sizeof(WCHAR) <= oldlen, "WinHttpQueryHeaders resulting length longer than advertized.\n");
327     ok((len < sizeof(buffer) - sizeof(WCHAR)) && buffer[len / sizeof(WCHAR)] == 0, "WinHttpQueryHeaders did not append NULL terminator\n");
328     ok(len == lstrlenW(buffer) * sizeof(WCHAR), "WinHttpQueryHeaders returned incorrect length.\n");
329     ok(memcmp(buffer, test_header_begin, sizeof(test_header_begin)) == 0,
330         "WinHttpQueryHeaders returned invalid beginning of header string.\n");
331     ok(memcmp(buffer + lstrlenW(buffer) - 4, test_header_end, sizeof(test_header_end)) == 0,
332         "WinHttpQueryHeaders returned invalid end of header string.\n");
333     ok(index == 0, "WinHttpQueryHeaders incremented header index.\n");
334
335     index = 0;
336     len = 0;
337     SetLastError(0xdeadbeef);
338     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
339         test_header_name, NULL, &len, &index);
340     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
341     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
342         "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
343     ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
344     ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
345
346     oldlen = len;
347     index = 0;
348     len = sizeof(buffer);
349     memset(buffer, 0xff, sizeof(buffer));
350     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
351         test_header_name, buffer, &len, &index);
352     ok(ret == TRUE, "WinHttpQueryHeaders failed %u\n", GetLastError());
353     ok(len + sizeof(WCHAR) <= oldlen, "resulting length longer than advertized\n");
354     ok((len < sizeof(buffer) - sizeof(WCHAR)) && !buffer[len / sizeof(WCHAR)] && !buffer[len / sizeof(WCHAR) - 1],
355         "no double NULL terminator\n");
356     ok(!memcmp(buffer, test_header_begin, sizeof(test_header_begin)), "invalid beginning of header string\n");
357     ok(index == 0, "header index was incremented\n");
358
359     /* tests for more indices */
360     ret = WinHttpAddRequestHeaders(request, test_headers[1], -1L, WINHTTP_ADDREQ_FLAG_ADD);
361     ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header: %d\n", ret);
362
363     index = 0;
364     len = sizeof(buffer);
365     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
366         test_header_name, buffer, &len, &index);
367     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
368     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
369     ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
370
371     len = sizeof(buffer);
372     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
373         test_header_name, buffer, &len, &index);
374     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
375     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
376     ok(memcmp(buffer, test_indices[1], sizeof(test_indices[1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
377
378     ret = WinHttpAddRequestHeaders(request, test_headers[2], -1L, WINHTTP_ADDREQ_FLAG_REPLACE);
379     ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header.\n");
380
381     index = 0;
382     len = sizeof(buffer);
383     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
384         test_header_name, buffer, &len, &index);
385     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
386     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
387     ok(memcmp(buffer, test_indices[1], sizeof(test_indices[1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
388
389     len = sizeof(buffer);
390     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
391         test_header_name, buffer, &len, &index);
392     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
393     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
394     ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
395
396     /* add if new flag */
397     ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW);
398     ok(ret == FALSE, "WinHttpAddRequestHeaders incorrectly replaced existing header.\n");
399
400     index = 0;
401     len = sizeof(buffer);
402     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
403         test_header_name, buffer, &len, &index);
404     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
405     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
406     ok(memcmp(buffer, test_indices[1], sizeof(test_indices[1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
407
408     len = sizeof(buffer);
409     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
410         test_header_name, buffer, &len, &index);
411     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
412     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
413     ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
414
415     len = sizeof(buffer);
416     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
417         test_header_name, buffer, &len, &index);
418     ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
419
420     /* coalesce flag */
421     ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_COALESCE);
422     ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE.\n");
423
424     index = 0;
425     len = sizeof(buffer);
426     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
427         test_header_name, buffer, &len, &index);
428     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
429     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
430     ok(memcmp(buffer, test_flag_coalesce, sizeof(test_flag_coalesce)) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
431
432     len = sizeof(buffer);
433     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
434         test_header_name, buffer, &len, &index);
435     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
436     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
437     ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
438
439     len = sizeof(buffer);
440     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
441         test_header_name, buffer, &len, &index);
442     ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
443
444     /* coalesce with comma flag */
445     ret = WinHttpAddRequestHeaders(request, test_headers[4], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA);
446     ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA.\n");
447
448     index = 0;
449     len = sizeof(buffer);
450     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
451         test_header_name, buffer, &len, &index);
452     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
453     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
454     ok(memcmp(buffer, test_flag_coalesce_comma, sizeof(test_flag_coalesce_comma)) == 0,
455         "WinHttpQueryHeaders returned incorrect string.\n");
456
457     len = sizeof(buffer);
458     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
459         test_header_name, buffer, &len, &index);
460     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
461     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
462     ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
463
464     len = sizeof(buffer);
465     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
466         test_header_name, buffer, &len, &index);
467     ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
468
469
470     /* coalesce with semicolon flag */
471     ret = WinHttpAddRequestHeaders(request, test_headers[5], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON);
472     ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON.\n");
473
474     index = 0;
475     len = sizeof(buffer);
476     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
477         test_header_name, buffer, &len, &index);
478     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
479     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
480     ok(memcmp(buffer, test_flag_coalesce_semicolon, sizeof(test_flag_coalesce_semicolon)) == 0,
481             "WinHttpQueryHeaders returned incorrect string.\n");
482
483     len = sizeof(buffer);
484     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
485         test_header_name, buffer, &len, &index);
486     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
487     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
488     ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
489
490     len = sizeof(buffer);
491     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
492         test_header_name, buffer, &len, &index);
493     ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
494
495     /* add and replace flags */
496     ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
497     ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE.\n");
498
499     index = 0;
500     len = sizeof(buffer);
501     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
502         test_header_name, buffer, &len, &index);
503     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
504     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
505     ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
506
507     len = sizeof(buffer);
508     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
509         test_header_name, buffer, &len, &index);
510     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
511     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
512     ok(memcmp(buffer, test_indices[3], sizeof(test_indices[2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
513
514     len = sizeof(buffer);
515     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
516         test_header_name, buffer, &len, &index);
517     ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
518
519     ret = WinHttpAddRequestHeaders(request, test_headers[8], ~0UL, WINHTTP_ADDREQ_FLAG_ADD);
520     ok(!ret, "WinHttpAddRequestHeaders failed\n");
521
522     ret = WinHttpAddRequestHeaders(request, test_headers[9], ~0UL, WINHTTP_ADDREQ_FLAG_ADD);
523     ok(ret, "WinHttpAddRequestHeaders failed\n");
524
525     ret = WinHttpAddRequestHeaders(request, test_headers[10], ~0UL, WINHTTP_ADDREQ_FLAG_ADD);
526     ok(!ret, "WinHttpAddRequestHeaders failed\n");
527
528     ret = WinHttpAddRequestHeaders(request, test_headers[11], ~0UL, WINHTTP_ADDREQ_FLAG_ADD);
529     ok(!ret, "WinHttpAddRequestHeaders failed\n");
530
531     ret = WinHttpAddRequestHeaders(request, test_headers[12], ~0UL, WINHTTP_ADDREQ_FLAG_ADD);
532     ok(!ret, "WinHttpAddRequestHeaders failed\n");
533
534     ret = WinHttpAddRequestHeaders(request, test_headers[13], ~0UL, WINHTTP_ADDREQ_FLAG_ADD);
535     ok(ret, "WinHttpAddRequestHeaders failed\n");
536
537     index = 0;
538     buffer[0] = 0;
539     len = sizeof(buffer);
540     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
541         field, buffer, &len, &index);
542     ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
543     ok(!memcmp(buffer, value, sizeof(value)), "unexpected result\n");
544
545     ret = WinHttpCloseHandle(request);
546     ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
547  done:
548     ret = WinHttpCloseHandle(connection);
549     ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
550     ret = WinHttpCloseHandle(session);
551     ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
552
553 }
554
555 static void test_secure_connection(void)
556 {
557     static const WCHAR google[] = {'w','w','w','.','g','o','o','g','l','e','.','c','o','m',0};
558
559     HANDLE ses, con, req;
560     DWORD size, status, policy, bitness;
561     BOOL ret;
562     CERT_CONTEXT *cert;
563
564     ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
565     ok(ses != NULL, "failed to open session %u\n", GetLastError());
566
567     policy = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
568     ret = WinHttpSetOption(ses, WINHTTP_OPTION_REDIRECT_POLICY, &policy, sizeof(policy));
569     ok(ret, "failed to set redirect policy %u\n", GetLastError());
570
571     con = WinHttpConnect(ses, google, 443, 0);
572     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
573
574     /* try without setting WINHTTP_FLAG_SECURE */
575     req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
576     ok(req != NULL, "failed to open a request %u\n", GetLastError());
577
578     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
579     ok(ret, "failed to send request %u\n", GetLastError());
580
581     ret = WinHttpReceiveResponse(req, NULL);
582     ok(!ret, "succeeded unexpectedly\n");
583
584     size = 0;
585     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL);
586     ok(!ret, "succeeded unexpectedly\n");
587
588     WinHttpCloseHandle(req);
589
590     req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, WINHTTP_FLAG_SECURE);
591     ok(req != NULL, "failed to open a request %u\n", GetLastError());
592
593     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
594     ok(ret, "failed to send request %u\n", GetLastError());
595
596     size = sizeof(cert);
597     ret = WinHttpQueryOption(req, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert, &size );
598     ok(ret, "failed to retrieve certificate context %u\n", GetLastError());
599
600     size = sizeof(bitness);
601     ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_KEY_BITNESS, &bitness, &size );
602     ok(ret, "failed to retrieve key bitness %u\n", GetLastError());
603
604     ret = WinHttpReceiveResponse(req, NULL);
605     ok(ret, "failed to receive response %u\n", GetLastError());
606
607     size = sizeof(status);
608     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
609     ok(ret, "failed unexpectedly %u\n", GetLastError());
610     ok(status == 200, "request failed unexpectedly %u\n", status);
611
612     size = 0;
613     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL);
614     ok(!ret, "succeeded unexpectedly\n");
615
616     WinHttpCloseHandle(req);
617     WinHttpCloseHandle(con);
618     WinHttpCloseHandle(ses);
619 }
620
621 static void test_request_parameter_defaults(void)
622 {
623     static const WCHAR empty[] = {0};
624     static const WCHAR codeweavers[] = {'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
625
626     HANDLE ses, con, req;
627     DWORD size, status;
628     BOOL ret;
629
630     ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
631     ok(ses != NULL, "failed to open session %u\n", GetLastError());
632
633     con = WinHttpConnect(ses, codeweavers, 0, 0);
634     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
635
636     req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
637     ok(req != NULL, "failed to open a request %u\n", GetLastError());
638
639     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
640     ok(ret, "failed to send request %u\n", GetLastError());
641
642     ret = WinHttpReceiveResponse(req, NULL);
643     ok(ret, "failed to receive response %u\n", GetLastError());
644
645     size = sizeof(status);
646     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
647     ok(ret, "failed unexpectedly %u\n", GetLastError());
648     ok(status == 200, "request failed unexpectedly %u\n", status);
649
650     WinHttpCloseHandle(req);
651
652     req = WinHttpOpenRequest(con, empty, empty, empty, NULL, NULL, 0);
653     ok(req != NULL, "failed to open a request %u\n", GetLastError());
654
655     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
656     ok(ret, "failed to send request %u\n", GetLastError());
657
658     ret = WinHttpReceiveResponse(req, NULL);
659     ok(ret, "failed to receive response %u\n", GetLastError());
660
661     size = sizeof(status);
662     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
663     ok(ret, "failed unexpectedly %u\n", GetLastError());
664     ok(status == 200, "request failed unexpectedly %u\n", status);
665
666     WinHttpCloseHandle(req);
667     WinHttpCloseHandle(con);
668     WinHttpCloseHandle(ses);
669 }
670
671 START_TEST (winhttp)
672 {
673     test_OpenRequest();
674     test_SendRequest();
675     test_WinHttpTimeFromSystemTime();
676     test_WinHttpTimeToSystemTime();
677     test_WinHttpAddHeaders();
678     test_secure_connection();
679     test_request_parameter_defaults();
680 }