winhttp: Implement WinHttpQueryHeaders.
[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     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     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
253     ok(index == 1, "WinHttpQueryHeaders failed: header index not incremented\n");
254     ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders failed: incorrect string returned\n");
255     ok(len == 5*sizeof(WCHAR), "WinHttpQueryHeaders failed: invalid length returned, expected 5, got %d\n", len);
256
257     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
258         test_header_name, buffer, &len, &index);
259     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, second index should not exist.\n");
260
261     /* Try to fetch the header info with a buffer thats big enough to fit string but not NULL terminator. */
262     index = 0;
263     len = 5*sizeof(WCHAR);
264     memcpy(buffer, check_buffer, sizeof(buffer));
265     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
266         test_header_name, buffer, &len, &index);
267     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded with a buffer thats too small.\n");
268     ok(memcmp(buffer, check_buffer, sizeof(buffer)) == 0,
269             "WinHttpQueryHeaders failed, modified the buffer when it should not have.\n");
270     ok(len == 6*sizeof(WCHAR), "WinHttpQueryHeaders returned invalid length, expected 12, got %d\n", len);
271
272     /* Try with a NULL buffer */
273     index = 0;
274     len = sizeof(buffer);
275     SetLastError(0xdeadbeef);
276     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
277         test_header_name, NULL, &len, &index);
278     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
279     todo_wine ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
280     todo_wine ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
281     ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
282
283     /* Try with a NULL buffer and a length thats too small */
284     index = 0;
285     len = 10;
286     SetLastError(0xdeadbeef);
287     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
288         test_header_name, NULL, &len, &index);
289     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
290     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
291         "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICENT_BUFFER, go %u\n", GetLastError());
292     todo_wine 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     index = 0;
296     len = 0;
297     SetLastError(0xdeadbeef);
298     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
299         test_header_name, NULL, &len, &index);
300     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
301     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
302         "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
303     todo_wine ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
304     ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
305
306     /* valid query */
307     oldlen = len;
308     index = 0;
309     len = sizeof(buffer);
310     memset(buffer, 0xff, sizeof(buffer));
311     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
312         test_header_name, buffer, &len, &index);
313     ok(ret == TRUE, "WinHttpQueryHeaders failed: got %d\n", ret);
314     ok(len + sizeof(WCHAR) <= oldlen, "WinHttpQueryHeaders resulting length longer than advertized.\n");
315     ok((len < sizeof(buffer) - sizeof(WCHAR)) && buffer[len / sizeof(WCHAR)] == 0, "WinHttpQueryHeaders did not append NULL terminator\n");
316     ok(len == lstrlenW(buffer) * sizeof(WCHAR), "WinHttpQueryHeaders returned incorrect length.\n");
317     todo_wine
318     {
319         ok(memcmp(buffer, test_header_begin, sizeof(test_header_begin)) == 0,
320             "WinHttpQueryHeaders returned invalid beginning of header string.\n");
321         ok(memcmp(buffer + lstrlenW(buffer) - 4, test_header_end, sizeof(test_header_end)) == 0,
322             "WinHttpQueryHeaders returned invalid end of header string.\n");
323     }
324     ok(index == 0, "WinHttpQueryHeaders incremented header index.\n");
325
326     /* tests for more indices */
327     ret = WinHttpAddRequestHeaders(request, test_headers[1], -1L, WINHTTP_ADDREQ_FLAG_ADD);
328     ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header: %d\n", ret);
329
330     index = 0;
331     len = sizeof(buffer);
332     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
333         test_header_name, buffer, &len, &index);
334     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
335     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
336     ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
337
338     len = sizeof(buffer);
339     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
340         test_header_name, buffer, &len, &index);
341     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
342     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
343     ok(memcmp(buffer, test_indices[1], sizeof(test_indices[1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
344
345     ret = WinHttpAddRequestHeaders(request, test_headers[2], -1L, WINHTTP_ADDREQ_FLAG_REPLACE);
346     ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header.\n");
347
348     index = 0;
349     len = sizeof(buffer);
350     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
351         test_header_name, buffer, &len, &index);
352     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
353     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
354     ok(memcmp(buffer, test_indices[1], sizeof(test_indices[1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
355
356     len = sizeof(buffer);
357     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
358         test_header_name, buffer, &len, &index);
359     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
360     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
361     ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
362
363     /* add if new flag */
364     ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW);
365     ok(ret == FALSE, "WinHttpAddRequestHeaders incorrectly replaced existing 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     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
372     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
373     ok(memcmp(buffer, test_indices[1], sizeof(test_indices[1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
374
375     len = sizeof(buffer);
376     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
377         test_header_name, buffer, &len, &index);
378     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
379     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
380     ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
381
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 == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
386
387     /* coalesce flag */
388     ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_COALESCE);
389     ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE.\n");
390
391     index = 0;
392     len = sizeof(buffer);
393     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
394         test_header_name, buffer, &len, &index);
395     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
396     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
397     ok(memcmp(buffer, test_flag_coalesce, sizeof(test_flag_coalesce)) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
398
399     len = sizeof(buffer);
400     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
401         test_header_name, buffer, &len, &index);
402     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
403     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
404     ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
405
406     len = sizeof(buffer);
407     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
408         test_header_name, buffer, &len, &index);
409     ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
410
411     /* coalesce with comma flag */
412     ret = WinHttpAddRequestHeaders(request, test_headers[4], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA);
413     ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA.\n");
414
415     index = 0;
416     len = sizeof(buffer);
417     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
418         test_header_name, buffer, &len, &index);
419     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
420     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
421     ok(memcmp(buffer, test_flag_coalesce_comma, sizeof(test_flag_coalesce_comma)) == 0,
422         "WinHttpQueryHeaders returned incorrect string.\n");
423
424     len = sizeof(buffer);
425     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
426         test_header_name, buffer, &len, &index);
427     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
428     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
429     ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
430
431     len = sizeof(buffer);
432     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
433         test_header_name, buffer, &len, &index);
434     ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
435
436
437     /* coalesce with semicolon flag */
438     ret = WinHttpAddRequestHeaders(request, test_headers[5], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON);
439     ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON.\n");
440
441     index = 0;
442     len = sizeof(buffer);
443     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
444         test_header_name, buffer, &len, &index);
445     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
446     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
447     ok(memcmp(buffer, test_flag_coalesce_semicolon, sizeof(test_flag_coalesce_semicolon)) == 0,
448             "WinHttpQueryHeaders returned incorrect string.\n");
449
450     len = sizeof(buffer);
451     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
452         test_header_name, buffer, &len, &index);
453     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
454     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
455     ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0, "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 == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
461
462     /* add and replace flags */
463     ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
464     ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE.\n");
465
466     index = 0;
467     len = sizeof(buffer);
468     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
469         test_header_name, buffer, &len, &index);
470     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
471     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
472     ok(memcmp(buffer, test_indices[2], sizeof(test_indices[2])) == 0, "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 == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
478     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
479     ok(memcmp(buffer, test_indices[3], sizeof(test_indices[2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
480
481     len = sizeof(buffer);
482     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
483         test_header_name, buffer, &len, &index);
484     ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
485
486     ret = WinHttpCloseHandle(request);
487     ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
488  done:
489     ret = WinHttpCloseHandle(connection);
490     ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
491     ret = WinHttpCloseHandle(session);
492     ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
493
494 }
495
496 START_TEST (winhttp)
497 {
498     test_OpenRequest();
499     test_SendRequest();
500     test_WinHttpTimeFromSystemTime();
501     test_WinHttpTimeToSystemTime();
502     test_WinHttpAddHeaders();
503 }