winhttp: Implement WinHttpTimeFromSystemTime and WinHttpTimeToSystemTime.
[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 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <winhttp.h>
25
26 #include "wine/test.h"
27
28 static const WCHAR test_useragent[] =
29     {'W','i','n','e',' ','R','e','g','r','e','s','s','i','o','n',' ','T','e','s','t',0};
30 static const WCHAR test_server[] = {'w','i','n','e','h','q','.','o','r','g',0};
31
32 static void test_OpenRequest (void)
33 {
34     BOOL ret;
35     HINTERNET session, request, connection;
36
37     session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
38         WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
39     ok(session != NULL, "WinHttpOpen failed to open session.\n");
40
41     /* Test with a bad server name */
42     SetLastError(0xdeadbeef);
43     connection = WinHttpConnect(session, NULL, INTERNET_DEFAULT_HTTP_PORT, 0);
44     ok (connection == NULL, "WinHttpConnect succeeded in opening connection to NULL server argument.\n");
45     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u.\n", GetLastError());
46
47     /* Test with a valid server name */
48     connection = WinHttpConnect (session, test_server, INTERNET_DEFAULT_HTTP_PORT, 0);
49     ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
50
51     request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
52         WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
53     if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
54     {
55         skip("Network unreachable, skipping.\n");
56         goto done;
57     }
58     ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError());
59
60     ret = WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, NULL, 0, 0, 0);
61     todo_wine ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError());
62     ret = WinHttpCloseHandle(request);
63     ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
64
65  done:
66     ret = WinHttpCloseHandle(connection);
67     ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
68     ret = WinHttpCloseHandle(session);
69     ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
70
71 }
72
73 static void test_SendRequest (void)
74 {
75     HINTERNET session, request, connection;
76     DWORD header_len, optional_len, total_len;
77     DWORD bytes_rw;
78     BOOL ret;
79     CHAR buffer[256];
80     int i;
81
82     static const WCHAR test_site[] = {'c','r','o','s','s','o','v','e','r','.',
83                                 'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
84     static const WCHAR content_type[] =
85         {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t','i','o','n',
86          '/','x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o','d','e','d',0};
87     static const WCHAR test_file[] = {'/','p','o','s','t','t','e','s','t','.','p','h','p',0};
88     static const WCHAR test_verb[] = {'P','O','S','T',0};
89     static CHAR post_data[] = "mode=Test";
90     static CHAR test_post[] = "mode => Test\\0\n";
91
92     header_len = -1L;
93     total_len = optional_len = sizeof(post_data);
94     memset(buffer, 0xff, sizeof(buffer));
95
96     session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
97         WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
98     ok(session != NULL, "WinHttpOpen failed to open session.\n");
99
100     connection = WinHttpConnect (session, test_site, INTERNET_DEFAULT_HTTP_PORT, 0);
101     ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
102
103     request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
104         WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
105     if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
106     {
107         skip("Network unreachable, skipping.\n");
108         goto done;
109     }
110     ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError());
111
112     ret = WinHttpSendRequest(request, content_type, header_len, post_data, optional_len, total_len, 0);
113     todo_wine ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError());
114
115     for (i = 3; post_data[i]; i++)
116     {
117         bytes_rw = -1;
118         ret = WinHttpWriteData(request, &post_data[i], 1, &bytes_rw);
119         todo_wine ok(ret == TRUE, "WinHttpWriteData failed: %u.\n", GetLastError());
120         todo_wine ok(bytes_rw == 1, "WinHttpWriteData failed, wrote %u bytes instead of 1 byte.\n", bytes_rw);
121     }
122
123     ret = WinHttpReceiveResponse(request, NULL);
124     todo_wine ok(ret == TRUE, "WinHttpReceiveResponse failed: %u.\n", GetLastError());
125
126     bytes_rw = -1;
127     ret = WinHttpReadData(request, buffer, sizeof(buffer) - 1, &bytes_rw);
128     todo_wine ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
129
130     todo_wine ok(bytes_rw == strlen(test_post), "Read %u bytes instead of %d.\n",
131         bytes_rw, strlen(test_post));
132     todo_wine ok(strncmp(buffer, test_post, bytes_rw) == 0,
133         "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 test_headers[][14] =
207         {
208             {'W','a','r','n','i','n','g',':','t','e','s','t','1',0},
209             {'W','a','r','n','i','n','g',':','t','e','s','t','2',0},
210             {'W','a','r','n','i','n','g',':','t','e','s','t','3',0},
211             {'W','a','r','n','i','n','g',':','t','e','s','t','4',0},
212             {'W','a','r','n','i','n','g',':','t','e','s','t','5',0},
213             {'W','a','r','n','i','n','g',':','t','e','s','t','6',0},
214             {'W','a','r','n','i','n','g',':','t','e','s','t','7',0}
215         };
216     static const WCHAR test_indices[][6] =
217         {
218             {'t','e','s','t','1',0},
219             {'t','e','s','t','2',0},
220             {'t','e','s','t','3',0},
221             {'t','e','s','t','4',0}
222         };
223
224     session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
225         WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
226     ok(session != NULL, "WinHttpOpen failed to open session.\n");
227
228     connection = WinHttpConnect (session, test_site, INTERNET_DEFAULT_HTTP_PORT, 0);
229     ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
230
231     request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
232         WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
233     if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
234     {
235         skip("Network unreachable, skipping.\n");
236         goto done;
237     }
238     ok(request != NULL, "WinHttpOpenRequest failed to open a request, error: %u.\n", GetLastError());
239
240     index = 0;
241     len = sizeof(buffer);
242     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
243         test_header_name, buffer, &len, &index);
244     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, found 'Warning' header.");
245     ret = WinHttpAddRequestHeaders(request, test_headers[0], -1L, WINHTTP_ADDREQ_FLAG_ADD);
246     todo_wine ok(ret == TRUE, "WinHttpAddRequestHeader failed to add new header, got %d with error %u.\n", ret, GetLastError());
247
248     index = 0;
249     len = sizeof(buffer);
250     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
251         test_header_name, buffer, &len, &index);
252     todo_wine
253     {
254         ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
255         ok(index == 1, "WinHttpQueryHeaders failed: header index not incremented\n");
256         ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0,
257             "WinHttpQueryHeaders failed: incorrect string returned\n");
258         ok(len == 5*sizeof(WCHAR),
259             "WinHttpQueryHeaders failed: invalid length returned, expected 5, got %d\n", len);
260     }
261     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
262         test_header_name, buffer, &len, &index);
263     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, second index should not exist.\n");
264
265     /* Try to fetch the header info with a buffer thats big enough to fit string but not NULL terminator. */
266     index = 0;
267     len = 5*sizeof(WCHAR);
268     memcpy(buffer, check_buffer, sizeof(buffer));
269     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
270         test_header_name, buffer, &len, &index);
271     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded with a buffer thats too small.\n");
272     ok(memcmp(buffer, check_buffer, sizeof(buffer)) == 0,
273             "WinHttpQueryHeaders failed, modified the buffer when it should not have.\n");
274     todo_wine ok(len == 6*sizeof(WCHAR), "WinHttpQueryHeaders returned invalid length, expected 12, got %d\n", len);
275
276     /* Try with a NULL buffer */
277     index = 0;
278     len = sizeof(buffer);
279     SetLastError(0xdeadbeef);
280     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
281         test_header_name, NULL, &len, &index);
282     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
283     todo_wine ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
284     ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
285     ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
286
287     /* Try with a NULL buffer and a length thats too small */
288     index = 0;
289     len = 10;
290     SetLastError(0xdeadbeef);
291     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
292         test_header_name, NULL, &len, &index);
293     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
294     todo_wine
295     {
296         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
297             "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICENT_BUFFER, go %u\n", GetLastError());
298         ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
299     }
300     ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
301
302     index = 0;
303     len = 0;
304     SetLastError(0xdeadbeef);
305     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
306         test_header_name, NULL, &len, &index);
307     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
308     todo_wine
309     {
310         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
311             "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n",
312             GetLastError());
313         ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
314     }
315     ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
316
317     /* valid query */
318     oldlen = len;
319     index = 0;
320     len = sizeof(buffer);
321     memset(buffer, 0xff, sizeof(buffer));
322     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
323         test_header_name, buffer, &len, &index);
324     todo_wine
325     {
326         ok(ret == TRUE, "WinHttpQueryHeaders failed: got %d\n", ret);
327         ok(len + sizeof(WCHAR) <= oldlen, "WinHttpQueryHeaders resulting length longer than advertized.\n");
328         ok((len < sizeof(buffer) - sizeof(WCHAR)) && buffer[len / sizeof(WCHAR)] == 0,
329             "WinHttpQueryHeaders did not append NULL terminator\n");
330         ok(len == lstrlenW(buffer) * sizeof(WCHAR), "WinHttpQueryHeaders returned incorrect length.\n");
331         ok(memcmp(buffer, test_header_begin, sizeof(test_header_begin)) == 0,
332             "WinHttpQueryHeaders returned invalid beginning of header string.\n");
333         ok(memcmp(buffer + lstrlenW(buffer) - 4, test_header_end, sizeof(test_header_end)) == 0,
334             "WinHttpQueryHeaders returned invalid end of header string.\n");
335     }
336     ok(index == 0, "WinHttpQueryHeaders incremented header index.\n");
337
338     /* tests for more indices */
339     ret = WinHttpAddRequestHeaders(request, test_headers[1], -1L, WINHTTP_ADDREQ_FLAG_ADD);
340     todo_wine ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header: %d\n", ret);
341
342     index = 0;
343     len = sizeof(buffer);
344     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
345         test_header_name, buffer, &len, &index);
346     todo_wine
347     {
348         ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
349         ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
350         ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0,
351             "WinHttpQueryHeaders returned incorrect string.\n");
352     }
353     len = sizeof(buffer);
354     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
355         test_header_name, buffer, &len, &index);
356     todo_wine
357     {
358         ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
359         ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
360         ok(memcmp(buffer, test_indices[1], sizeof(test_indices[1])) == 0,
361             "WinHttpQueryHeaders returned incorrect string.\n");
362     }
363
364     ret = WinHttpAddRequestHeaders(request, test_headers[2], -1L, WINHTTP_ADDREQ_FLAG_REPLACE);
365     todo_wine ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header.\n");
366
367     index = 0;
368     len = sizeof(buffer);
369     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
370         test_header_name, buffer, &len, &index);
371     todo_wine
372     {
373         ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
374         ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
375         ok(memcmp(buffer, test_indices[1], sizeof(test_indices[1])) == 0,
376             "WinHttpQueryHeaders returned incorrect string.\n");
377     }
378     len = sizeof(buffer);
379     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
380         test_header_name, buffer, &len, &index);
381     todo_wine
382     {
383         ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
384         ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
385         ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0,
386             "WinHttpQueryHeaders returned incorrect string.\n");
387     }
388
389     /* add if new flag */
390     ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW);
391     ok(ret == FALSE, "WinHttpAddRequestHeaders incorrectly replaced existing header.\n");
392
393     index = 0;
394     len = sizeof(buffer);
395     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
396         test_header_name, buffer, &len, &index);
397     todo_wine
398     {
399         ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
400         ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
401         ok(memcmp(buffer, test_indices[1], sizeof(test_indices[1])) == 0,
402             "WinHttpQueryHeaders returned incorrect string.\n");
403     }
404     len = sizeof(buffer);
405     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
406         test_header_name, buffer, &len, &index);
407     todo_wine
408     {
409         ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
410         ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
411         ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0,
412             "WinHttpQueryHeaders returned incorrect string.\n");
413     }
414     len = sizeof(buffer);
415     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
416         test_header_name, buffer, &len, &index);
417     ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
418
419     /* coalesce flag */
420     ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_COALESCE);
421     todo_wine ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE.\n");
422
423     index = 0;
424     len = sizeof(buffer);
425     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
426         test_header_name, buffer, &len, &index);
427     todo_wine
428     {
429         ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
430         ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
431         ok(memcmp(buffer, test_flag_coalesce, sizeof(test_flag_coalesce)) == 0,
432             "WinHttpQueryHeaders returned incorrect string.\n");
433     }
434     len = sizeof(buffer);
435     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
436         test_header_name, buffer, &len, &index);
437     todo_wine
438     {
439         ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
440         ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
441         ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0,
442             "WinHttpQueryHeaders returned incorrect string.\n");
443     }
444     len = sizeof(buffer);
445     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
446         test_header_name, buffer, &len, &index);
447     ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
448
449     /* coalesce with comma flag */
450     ret = WinHttpAddRequestHeaders(request, test_headers[4], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA);
451     todo_wine ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA.\n");
452
453     index = 0;
454     len = sizeof(buffer);
455     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
456         test_header_name, buffer, &len, &index);
457     todo_wine
458     {
459         ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
460         ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
461         ok(memcmp(buffer, test_flag_coalesce_comma, sizeof(test_flag_coalesce_comma)) == 0,
462             "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     todo_wine
468     {
469         ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
470         ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
471         ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0,
472             "WinHttpQueryHeaders returned incorrect string.\n");
473     }
474     len = sizeof(buffer);
475     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
476         test_header_name, buffer, &len, &index);
477     ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
478
479
480     /* coalesce with semicolon flag */
481     ret = WinHttpAddRequestHeaders(request, test_headers[5], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON);
482     todo_wine ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON.\n");
483
484     index = 0;
485     len = sizeof(buffer);
486     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
487         test_header_name, buffer, &len, &index);
488     todo_wine
489     {
490         ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
491         ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
492         ok(memcmp(buffer, test_flag_coalesce_semicolon, sizeof(test_flag_coalesce_semicolon)) == 0,
493             "WinHttpQueryHeaders returned incorrect string.\n");
494     }
495     len = sizeof(buffer);
496     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
497         test_header_name, buffer, &len, &index);
498     todo_wine
499     {
500         ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
501         ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
502         ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0,
503             "WinHttpQueryHeaders returned incorrect string.\n");
504     }
505     len = sizeof(buffer);
506     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
507         test_header_name, buffer, &len, &index);
508     ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
509
510     /* add and replace flags */
511     ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
512     todo_wine ok(ret == TRUE,
513         "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE.\n");
514
515     index = 0;
516     len = sizeof(buffer);
517     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
518         test_header_name, buffer, &len, &index);
519     todo_wine
520     {
521         ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
522         ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
523         ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0,
524             "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     todo_wine
530     {
531         ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
532         ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
533         ok(memcmp(buffer, test_indices[3], sizeof(test_indices[2])) == 0,
534             "WinHttpQueryHeaders returned incorrect string.\n");
535     }
536     len = sizeof(buffer);
537     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
538         test_header_name, buffer, &len, &index);
539     ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
540
541     ret = WinHttpCloseHandle(request);
542     ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
543  done:
544     ret = WinHttpCloseHandle(connection);
545     ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
546     ret = WinHttpCloseHandle(session);
547     ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
548
549 }
550
551 START_TEST (winhttp)
552 {
553     test_OpenRequest();
554     test_SendRequest();
555     test_WinHttpTimeFromSystemTime();
556     test_WinHttpTimeToSystemTime();
557     test_WinHttpAddHeaders();
558 }