ReactOS 0.4.16-dev-2491-g3dc6630
request.c
Go to the documentation of this file.
1/*
2 * Copyright 2004 Mike McCormack for CodeWeavers
3 * Copyright 2006 Rob Shearman for CodeWeavers
4 * Copyright 2008, 2011 Hans Leidekker for CodeWeavers
5 * Copyright 2009 Juan Lang
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22#include <assert.h>
23#include <stdarg.h>
24#include <wchar.h>
25
26#define COBJMACROS
27#include "windef.h"
28#include "winbase.h"
29#include "ws2tcpip.h"
30#include "ole2.h"
31#include "initguid.h"
32#include "httprequest.h"
33#include "httprequestid.h"
34#include "schannel.h"
35#include "winhttp.h"
36#include "winternl.h"
37#include "ntsecapi.h"
38
39#include "wine/debug.h"
40#include "winhttp_private.h"
41
43
44#ifdef __REACTOS__
45#include "inet_ntop.c"
46#endif
47
48#define DEFAULT_KEEP_ALIVE_TIMEOUT 30000
49
50#define ACTUAL_DEFAULT_RECEIVE_RESPONSE_TIMEOUT 21000
51
53{
55 return req->receive_response_timeout;
56}
57
58static const WCHAR *attribute_table[] =
59{
60 L"Mime-Version", /* WINHTTP_QUERY_MIME_VERSION = 0 */
61 L"Content-Type" , /* WINHTTP_QUERY_CONTENT_TYPE = 1 */
62 L"Content-Transfer-Encoding", /* WINHTTP_QUERY_CONTENT_TRANSFER_ENCODING = 2 */
63 L"Content-ID", /* WINHTTP_QUERY_CONTENT_ID = 3 */
64 NULL, /* WINHTTP_QUERY_CONTENT_DESCRIPTION = 4 */
65 L"Content-Length", /* WINHTTP_QUERY_CONTENT_LENGTH = 5 */
66 L"Content-Language", /* WINHTTP_QUERY_CONTENT_LANGUAGE = 6 */
67 L"Allow", /* WINHTTP_QUERY_ALLOW = 7 */
68 L"Public", /* WINHTTP_QUERY_PUBLIC = 8 */
69 L"Date", /* WINHTTP_QUERY_DATE = 9 */
70 L"Expires", /* WINHTTP_QUERY_EXPIRES = 10 */
71 L"Last-Modified", /* WINHTTP_QUERY_LAST_MODIFIEDcw = 11 */
72 NULL, /* WINHTTP_QUERY_MESSAGE_ID = 12 */
73 L"URI", /* WINHTTP_QUERY_URI = 13 */
74 L"From", /* WINHTTP_QUERY_DERIVED_FROM = 14 */
75 NULL, /* WINHTTP_QUERY_COST = 15 */
76 NULL, /* WINHTTP_QUERY_LINK = 16 */
77 L"Pragma", /* WINHTTP_QUERY_PRAGMA = 17 */
78 NULL, /* WINHTTP_QUERY_VERSION = 18 */
79 L"Status", /* WINHTTP_QUERY_STATUS_CODE = 19 */
80 NULL, /* WINHTTP_QUERY_STATUS_TEXT = 20 */
81 NULL, /* WINHTTP_QUERY_RAW_HEADERS = 21 */
82 NULL, /* WINHTTP_QUERY_RAW_HEADERS_CRLF = 22 */
83 L"Connection", /* WINHTTP_QUERY_CONNECTION = 23 */
84 L"Accept", /* WINHTTP_QUERY_ACCEPT = 24 */
85 L"Accept-Charset", /* WINHTTP_QUERY_ACCEPT_CHARSET = 25 */
86 L"Accept-Encoding", /* WINHTTP_QUERY_ACCEPT_ENCODING = 26 */
87 L"Accept-Language", /* WINHTTP_QUERY_ACCEPT_LANGUAGE = 27 */
88 L"Authorization", /* WINHTTP_QUERY_AUTHORIZATION = 28 */
89 L"Content-Encoding", /* WINHTTP_QUERY_CONTENT_ENCODING = 29 */
90 NULL, /* WINHTTP_QUERY_FORWARDED = 30 */
91 NULL, /* WINHTTP_QUERY_FROM = 31 */
92 L"If-Modified-Since", /* WINHTTP_QUERY_IF_MODIFIED_SINCE = 32 */
93 L"Location", /* WINHTTP_QUERY_LOCATION = 33 */
94 NULL, /* WINHTTP_QUERY_ORIG_URI = 34 */
95 L"Referer", /* WINHTTP_QUERY_REFERER = 35 */
96 L"Retry-After", /* WINHTTP_QUERY_RETRY_AFTER = 36 */
97 L"Server", /* WINHTTP_QUERY_SERVER = 37 */
98 NULL, /* WINHTTP_TITLE = 38 */
99 L"User-Agent", /* WINHTTP_QUERY_USER_AGENT = 39 */
100 L"WWW-Authenticate", /* WINHTTP_QUERY_WWW_AUTHENTICATE = 40 */
101 L"Proxy-Authenticate", /* WINHTTP_QUERY_PROXY_AUTHENTICATE = 41 */
102 L"Accept-Ranges", /* WINHTTP_QUERY_ACCEPT_RANGES = 42 */
103 L"Set-Cookie", /* WINHTTP_QUERY_SET_COOKIE = 43 */
104 L"Cookie", /* WINHTTP_QUERY_COOKIE = 44 */
105 NULL, /* WINHTTP_QUERY_REQUEST_METHOD = 45 */
106 NULL, /* WINHTTP_QUERY_REFRESH = 46 */
107 NULL, /* WINHTTP_QUERY_CONTENT_DISPOSITION = 47 */
108 L"Age", /* WINHTTP_QUERY_AGE = 48 */
109 L"Cache-Control", /* WINHTTP_QUERY_CACHE_CONTROL = 49 */
110 L"Content-Base", /* WINHTTP_QUERY_CONTENT_BASE = 50 */
111 L"Content-Location", /* WINHTTP_QUERY_CONTENT_LOCATION = 51 */
112 L"Content-MD5", /* WINHTTP_QUERY_CONTENT_MD5 = 52 */
113 L"Content-Range", /* WINHTTP_QUERY_CONTENT_RANGE = 53 */
114 L"ETag", /* WINHTTP_QUERY_ETAG = 54 */
115 L"Host", /* WINHTTP_QUERY_HOST = 55 */
116 L"If-Match", /* WINHTTP_QUERY_IF_MATCH = 56 */
117 L"If-None-Match", /* WINHTTP_QUERY_IF_NONE_MATCH = 57 */
118 L"If-Range", /* WINHTTP_QUERY_IF_RANGE = 58 */
119 L"If-Unmodified-Since", /* WINHTTP_QUERY_IF_UNMODIFIED_SINCE = 59 */
120 L"Max-Forwards", /* WINHTTP_QUERY_MAX_FORWARDS = 60 */
121 L"Proxy-Authorization", /* WINHTTP_QUERY_PROXY_AUTHORIZATION = 61 */
122 L"Range", /* WINHTTP_QUERY_RANGE = 62 */
123 L"Transfer-Encoding", /* WINHTTP_QUERY_TRANSFER_ENCODING = 63 */
124 L"Upgrade", /* WINHTTP_QUERY_UPGRADE = 64 */
125 L"Vary", /* WINHTTP_QUERY_VARY = 65 */
126 L"Via", /* WINHTTP_QUERY_VIA = 66 */
127 L"Warning", /* WINHTTP_QUERY_WARNING = 67 */
128 L"Expect", /* WINHTTP_QUERY_EXPECT = 68 */
129 L"Proxy-Connection", /* WINHTTP_QUERY_PROXY_CONNECTION = 69 */
130 L"Unless-Modified-Since", /* WINHTTP_QUERY_UNLESS_MODIFIED_SINCE = 70 */
131 NULL, /* WINHTTP_QUERY_PROXY_SUPPORT = 75 */
132 NULL, /* WINHTTP_QUERY_AUTHENTICATION_INFO = 76 */
133 NULL, /* WINHTTP_QUERY_PASSPORT_URLS = 77 */
134 NULL /* WINHTTP_QUERY_PASSPORT_CONFIG = 78 */
135};
136
137void init_queue( struct queue *queue )
138{
142}
143
144void stop_queue( struct queue *queue )
145{
147 TRACE("stopped %p\n", queue);
148}
149
150static void addref_task( struct task_header *task )
151{
152 InterlockedIncrement( &task->refs );
153}
154
155static void release_task( struct task_header *task )
156{
157 if (!InterlockedDecrement( &task->refs ))
158 free( task );
159}
160
161static struct task_header *get_next_task( struct queue *queue, struct task_header *prev_task )
162{
163 struct task_header *task;
164 struct list *entry;
165
168 if (prev_task)
169 {
170 list_remove( &prev_task->entry );
171 release_task( prev_task );
172 }
173 if ((entry = list_head( &queue->queued_tasks )))
174 {
175 task = LIST_ENTRY( entry, struct task_header, entry );
176 addref_task( task );
177 }
178 else
179 {
180 task = NULL;
182 }
184 return task;
185}
186
188{
189 struct task_header *task, *next_task;
190 struct queue *queue = ctx;
191
192 TRACE( "instance %p.\n", instance );
193
195 while (task)
196 {
197 task->callback( task, FALSE );
198 /* Queue object may be freed by release_object() unless there is another task referencing it. */
199 next_task = get_next_task( queue, task );
200 release_object( task->obj );
202 task = next_task;
203 }
204 TRACE( "instance %p exiting.\n", instance );
205}
206
207static DWORD queue_task( struct queue *queue, TASK_CALLBACK task, struct task_header *task_hdr,
208 struct object_header *obj )
209{
211
212 TRACE("queueing %p in %p\n", task_hdr, queue);
213 task_hdr->callback = task;
214 task_hdr->completion_sent = 0;
215 task_hdr->refs = 1;
216 task_hdr->obj = obj;
218
220 list_add_tail( &queue->queued_tasks, &task_hdr->entry );
222 {
225 else
226 list_remove( &task_hdr->entry );
227 }
229
230 if (!callback_running)
231 {
233 ERR( "Submiting threadpool callback failed, err %lu.\n", GetLastError() );
234 return ERROR_OUTOFMEMORY;
235 }
236
237 return ERROR_SUCCESS;
238}
239
240static BOOL task_needs_completion( struct task_header *task_hdr )
241{
242 return !InterlockedExchange( &task_hdr->completion_sent, 1 );
243}
244
245static BOOL cancel_queue( struct queue *queue )
246{
247 struct task_header *task_hdr, *found;
248 BOOL cancelled = FALSE;
249
250 while (1)
251 {
253 found = NULL;
255 {
256 if (task_needs_completion( task_hdr ))
257 {
258 found = task_hdr;
259 addref_task( found );
260 break;
261 }
262 }
264 if (!found) break;
265 cancelled = TRUE;
266 found->callback( found, TRUE );
267 release_task( found );
268 }
269 return cancelled;
270}
271
272static void task_send_callback( void *ctx, BOOL abort )
273{
274 struct send_callback *s = ctx;
275
276 if (abort) return;
277
278 TRACE( "running %p\n", ctx );
279 send_callback( s->task_hdr.obj, s->status, s->info, s->buflen );
280}
281
282static void free_header( struct header *header )
283{
284 free( header->field );
285 free( header->value );
286 free( header );
287}
288
290{
291 if (c < 32 || c == 127) return FALSE;
292 switch (c)
293 {
294 case '(': case ')':
295 case '<': case '>':
296 case '@': case ',':
297 case ';': case ':':
298 case '\\': case '\"':
299 case '/': case '[':
300 case ']': case '?':
301 case '=': case '{':
302 case '}': case ' ':
303 case '\t':
304 return FALSE;
305 default:
306 return TRUE;
307 }
308}
309
310static struct header *parse_header( const WCHAR *string, size_t string_len, BOOL reply )
311{
312 const WCHAR *p, *q, *name_end;
313 struct header *header;
314 int len;
315
316 p = string;
317 if (!(q = wcschr( p, ':' )))
318 {
319 WARN("no ':' in line %s\n", debugstr_w(string));
320 return NULL;
321 }
322 name_end = q;
323 if (reply)
324 {
325 while (name_end != string)
326 {
327 if (name_end[-1] != ' ') break;
328 --name_end;
329 }
330 }
331 if (name_end == string)
332 {
333 WARN("empty field name in line %s\n", debugstr_w(string));
334 return NULL;
335 }
336 while (p != name_end)
337 {
338 if (!valid_token_char( *p ))
339 {
340 WARN("invalid character in field name %s\n", debugstr_w(string));
341 return NULL;
342 }
343 p++;
344 }
345 len = name_end - string;
346 if (!(header = calloc( 1, sizeof(*header) ))) return NULL;
347 if (!(header->field = malloc( (len + 1) * sizeof(WCHAR) )))
348 {
349 free( header );
350 return NULL;
351 }
352 memcpy( header->field, string, len * sizeof(WCHAR) );
353 header->field[len] = 0;
354
355 q++; /* skip past colon */
356 while (*q == ' ') q++;
357 len = (string + string_len) - q;
358
359 if (!(header->value = malloc( (len + 1) * sizeof(WCHAR) )))
360 {
362 return NULL;
363 }
364 memcpy( header->value, q, len * sizeof(WCHAR) );
365 header->value[len] = 0;
366
367 return header;
368}
369
370static int get_header_index( struct request *request, const WCHAR *field, int requested_index, BOOL request_only )
371{
372 int index;
373
374 TRACE("%s\n", debugstr_w(field));
375
376 for (index = 0; index < request->num_headers; index++)
377 {
378 if (wcsicmp( request->headers[index].field, field )) continue;
379 if (request_only && !request->headers[index].is_request) continue;
380 if (!request_only && request->headers[index].is_request) continue;
381
382 if (!requested_index) break;
383 requested_index--;
384 }
385 if (index >= request->num_headers) index = -1;
386 TRACE("returning %d\n", index);
387 return index;
388}
389
390static DWORD insert_header( struct request *request, struct header *header )
391{
393 struct header *hdrs;
394
395 if (request->headers)
396 {
397 if ((hdrs = realloc( request->headers, sizeof(*header) * count )))
398 memset( &hdrs[count - 1], 0, sizeof(*header) );
399 }
400 else hdrs = calloc( 1, sizeof(*header) );
401 if (!hdrs) return ERROR_OUTOFMEMORY;
402
403 request->headers = hdrs;
404 request->headers[count - 1].field = wcsdup( header->field );
405 request->headers[count - 1].value = wcsdup( header->value );
406 request->headers[count - 1].is_request = header->is_request;
408 return ERROR_SUCCESS;
409}
410
411static void delete_header( struct request *request, DWORD index )
412{
413 if (!request->num_headers || index >= request->num_headers) return;
415
416 free( request->headers[index].field );
417 free( request->headers[index].value );
418
420 (request->num_headers - index) * sizeof(struct header) );
421 memset( &request->headers[request->num_headers], 0, sizeof(struct header) );
422}
423
424DWORD process_header( struct request *request, const WCHAR *field, const WCHAR *value, DWORD flags, BOOL request_only )
425{
426 int index;
427 struct header hdr;
428
429 TRACE( "%s: %s %#lx\n", debugstr_w(field), debugstr_w(value), flags );
430
431 if ((index = get_header_index( request, field, 0, request_only )) >= 0)
432 {
434 }
435
437 {
438 if (index >= 0)
439 {
441 if (!value || !value[0]) return ERROR_SUCCESS;
442 }
444
445 hdr.field = (LPWSTR)field;
446 hdr.value = (LPWSTR)value;
447 hdr.is_request = request_only;
448 return insert_header( request, &hdr );
449 }
450 else if (value)
451 {
452
454 index >= 0)
455 {
456 WCHAR *tmp;
457 int len, len_orig, len_value;
458 struct header *header = &request->headers[index];
459
460 len_orig = lstrlenW( header->value );
461 len_value = lstrlenW( value );
462
463 len = len_orig + len_value + 2;
464 if (!(tmp = realloc( header->value, (len + 1) * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY;
465 header->value = tmp;
466 header->value[len_orig++] = (flags & WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA) ? ',' : ';';
467 header->value[len_orig++] = ' ';
468
469 memcpy( &header->value[len_orig], value, len_value * sizeof(WCHAR) );
470 header->value[len] = 0;
471 return ERROR_SUCCESS;
472 }
473 else
474 {
475 hdr.field = (LPWSTR)field;
476 hdr.value = (LPWSTR)value;
477 hdr.is_request = request_only;
478 return insert_header( request, &hdr );
479 }
480 }
481
482 return ERROR_SUCCESS;
483}
484
486{
488 struct header *header;
489 const WCHAR *p, *q;
490
491 if (len == ~0u) len = lstrlenW( headers );
492 if (!len) return ERROR_SUCCESS;
493
494 p = headers;
495 do
496 {
497 const WCHAR *end;
498
499 if (p >= headers + len) break;
500
501 for (q = p; q < headers + len && *q != '\r' && *q != '\n'; ++q)
502 ;
503 end = q;
504 while (*q == '\r' || *q == '\n')
505 ++q;
506
507 if ((header = parse_header( p, end - p, FALSE )))
508 {
511 }
512 p = q;
513 } while (!ret);
514
515 return ret;
516}
517
518/***********************************************************************
519 * WinHttpAddRequestHeaders (winhttp.@)
520 */
522{
523 DWORD ret;
524 struct request *request;
525
526 TRACE( "%p, %s, %lu, %#lx\n", hrequest, debugstr_wn(headers, len), len, flags );
527
528 if (!headers || !len)
529 {
531 return FALSE;
532 }
533 if (!(request = (struct request *)grab_object( hrequest )))
534 {
536 return FALSE;
537 }
539 {
542 return FALSE;
543 }
544
546
548 SetLastError( ret );
549 return !ret;
550}
551
553{
554 const WCHAR *scheme;
555 WCHAR *ret;
556 int len, offset;
557
558 scheme = (request->netconn ? request->netconn->secure : (request->hdr.flags & WINHTTP_FLAG_SECURE)) ? L"https" : L"http";
559
560 len = lstrlenW( scheme ) + lstrlenW( request->connect->hostname ) + 4; /* '://' + nul */
561 if (request->connect->hostport) len += 6; /* ':' between host and port, up to 5 for port */
562
563 len += lstrlenW( request->path );
564 if ((ret = malloc( len * sizeof(WCHAR) )))
565 {
566 offset = swprintf( ret, len, L"%s://%s", scheme, request->connect->hostname );
567 if (request->connect->hostport)
568 {
569 offset += swprintf( ret + offset, len - offset, L":%u", request->connect->hostport );
570 }
572 if (path) *path = ret + offset;
573 }
574
575 return ret;
576}
577
579{
580 WCHAR *path, *ret;
581 unsigned int i, len;
582
583 if (!wcsicmp( request->connect->hostname, request->connect->servername )) path = request->path;
584 else if (!(path = build_absolute_request_path( request, NULL ))) return NULL;
585
586 len = lstrlenW( request->verb ) + 1 /* ' ' */;
587 len += lstrlenW( path ) + 1 /* ' ' */;
589
590 for (i = 0; i < request->num_headers; i++)
591 {
592 if (request->headers[i].is_request)
593 len += lstrlenW( request->headers[i].field ) + lstrlenW( request->headers[i].value ) + 4; /* '\r\n: ' */
594 }
595 len += 4; /* '\r\n\r\n' */
596
597 if ((ret = malloc( (len + 1) * sizeof(WCHAR) )))
598 {
600 lstrcatW( ret, L" " );
601 lstrcatW( ret, path );
602 lstrcatW( ret, L" " );
604
605 for (i = 0; i < request->num_headers; i++)
606 {
607 if (request->headers[i].is_request)
608 {
609 lstrcatW( ret, L"\r\n" );
610 lstrcatW( ret, request->headers[i].field );
611 lstrcatW( ret, L": " );
612 lstrcatW( ret, request->headers[i].value );
613 }
614 }
615 lstrcatW( ret, L"\r\n\r\n" );
616 }
617
618 if (path != request->path) free( path );
619 return ret;
620}
621
622#define QUERY_MODIFIER_MASK (WINHTTP_QUERY_FLAG_REQUEST_HEADERS | WINHTTP_QUERY_FLAG_SYSTEMTIME | WINHTTP_QUERY_FLAG_NUMBER)
623
624static DWORD query_headers( struct request *request, DWORD level, const WCHAR *name, void *buffer, DWORD *buflen,
625 DWORD *index )
626{
627 struct header *header = NULL;
628 BOOL request_only;
629 int requested_index, header_index = -1;
631
633 requested_index = index ? *index : 0;
634
635 attr = level & ~QUERY_MODIFIER_MASK;
636 switch (attr)
637 {
639 {
640 header_index = get_header_index( request, name, requested_index, request_only );
641 break;
642 }
644 {
645 WCHAR *headers, *p, *q;
646
647 if (request_only)
649 else
651
652 if (!(p = headers)) return ERROR_OUTOFMEMORY;
653 for (len = 0; *p; p++) if (*p != '\r') len++;
654
655 if (!buffer || len * sizeof(WCHAR) > *buflen) ret = ERROR_INSUFFICIENT_BUFFER;
656 else
657 {
658 for (p = headers, q = buffer; *p; p++, q++)
659 {
660 if (*p != '\r') *q = *p;
661 else
662 {
663 *q = 0;
664 p++; /* skip '\n' */
665 }
666 }
667 TRACE("returning data: %s\n", debugstr_wn(buffer, len));
668 if (len) len--;
670 }
671 *buflen = len * sizeof(WCHAR);
672 if (request_only) free( headers );
673 return ret;
674 }
676 {
677 WCHAR *headers;
678
679 if (request_only)
681 else
683
684 if (!headers) return ERROR_OUTOFMEMORY;
685 len = lstrlenW( headers ) * sizeof(WCHAR);
686 if (!buffer || len + sizeof(WCHAR) > *buflen)
687 {
688 len += sizeof(WCHAR);
690 }
691 else
692 {
693 memcpy( buffer, headers, len + sizeof(WCHAR) );
694 TRACE("returning data: %s\n", debugstr_wn(buffer, len / sizeof(WCHAR)));
696 }
697 *buflen = len;
698 if (request_only) free( headers );
699 return ret;
700 }
702 len = lstrlenW( request->version ) * sizeof(WCHAR);
703 if (!buffer || len + sizeof(WCHAR) > *buflen)
704 {
705 len += sizeof(WCHAR);
707 }
708 else
709 {
711 TRACE("returning string: %s\n", debugstr_w(buffer));
713 }
714 *buflen = len;
715 return ret;
716
718 len = lstrlenW( request->status_text ) * sizeof(WCHAR);
719 if (!buffer || len + sizeof(WCHAR) > *buflen)
720 {
721 len += sizeof(WCHAR);
723 }
724 else
725 {
727 TRACE("returning string: %s\n", debugstr_w(buffer));
729 }
730 *buflen = len;
731 return ret;
732
734 len = lstrlenW( request->verb ) * sizeof(WCHAR);
735 if (!buffer || len + sizeof(WCHAR) > *buflen)
736 {
737 len += sizeof(WCHAR);
739 }
740 else
741 {
743 TRACE("returning string: %s\n", debugstr_w(buffer));
745 }
746 *buflen = len;
747 return ret;
748
749 default:
751 if (!attribute_table[attr])
752 {
753 FIXME( "attribute %lu not implemented\n", attr );
755 }
756 TRACE("attribute %s\n", debugstr_w(attribute_table[attr]));
757 header_index = get_header_index( request, attribute_table[attr], requested_index, request_only );
758 break;
759 }
760
761 if (header_index >= 0)
762 {
763 header = &request->headers[header_index];
764 }
765 if (!header || (request_only && !header->is_request)) return ERROR_WINHTTP_HEADER_NOT_FOUND;
767 {
768 if (!buffer || sizeof(DWORD) > *buflen) ret = ERROR_INSUFFICIENT_BUFFER;
769 else
770 {
772 *number = wcstoul( header->value, NULL, 10 );
773 TRACE("returning number: %lu\n", *number);
775 }
776 *buflen = sizeof(DWORD);
777 }
779 {
780 SYSTEMTIME *st = buffer;
781 if (!buffer || sizeof(SYSTEMTIME) > *buflen) ret = ERROR_INSUFFICIENT_BUFFER;
782 else if (WinHttpTimeToSystemTime( header->value, st ))
783 {
784 TRACE("returning time: %04d/%02d/%02d - %d - %02d:%02d:%02d.%02d\n",
785 st->wYear, st->wMonth, st->wDay, st->wDayOfWeek,
786 st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
788 }
789 *buflen = sizeof(SYSTEMTIME);
790 }
791 else if (header->value)
792 {
793 len = lstrlenW( header->value ) * sizeof(WCHAR);
794 if (!buffer || len + sizeof(WCHAR) > *buflen)
795 {
796 len += sizeof(WCHAR);
798 }
799 else
800 {
802 TRACE("returning string: %s\n", debugstr_w(buffer));
804 }
805 *buflen = len;
806 }
807 if (!ret && index) *index += 1;
808 return ret;
809}
810
811/***********************************************************************
812 * WinHttpQueryHeaders (winhttp.@)
813 */
815 DWORD *index )
816{
817 DWORD ret;
818 struct request *request;
819
820 TRACE( "%p, %#lx, %s, %p, %p, %p\n", hrequest, level, debugstr_w(name), buffer, buflen, index );
821
822 if (!(request = (struct request *)grab_object( hrequest )))
823 {
825 return FALSE;
826 }
828 {
831 return FALSE;
832 }
835 {
838 return FALSE;
839 }
840
841 ret = query_headers( request, level, name, buffer, buflen, index );
842
844 SetLastError( ret );
845 return !ret;
846}
847
848static const struct
849{
850 const WCHAR *str;
851 unsigned int len;
853}
854auth_schemes[] =
855{
856 { L"Basic", ARRAY_SIZE(L"Basic") - 1, WINHTTP_AUTH_SCHEME_BASIC },
857 { L"NTLM", ARRAY_SIZE(L"NTLM") - 1, WINHTTP_AUTH_SCHEME_NTLM },
858 { L"Passport", ARRAY_SIZE(L"Passport") - 1, WINHTTP_AUTH_SCHEME_PASSPORT },
859 { L"Digest", ARRAY_SIZE(L"Digest") - 1, WINHTTP_AUTH_SCHEME_DIGEST },
860 { L"Negotiate", ARRAY_SIZE(L"Negotiate") - 1, WINHTTP_AUTH_SCHEME_NEGOTIATE }
862
864{
865 int i;
866
867 for (i = 0; i < ARRAY_SIZE( auth_schemes ); i++) if (flag == auth_schemes[i].scheme) return i;
868 return SCHEME_INVALID;
869}
870
872{
873 unsigned int i;
874
875 for (i = 0; i < ARRAY_SIZE( auth_schemes ); i++)
876 {
878 (header[auth_schemes[i].len] == ' ' || !header[auth_schemes[i].len])) return auth_schemes[i].scheme;
879 }
880 return 0;
881}
882
884{
885 DWORD ret, index = 0, supported_schemes = 0, first_scheme = 0;
886
887 for (;;)
888 {
889 WCHAR *buffer;
891
892 size = 0;
895 {
896 if (index) ret = ERROR_SUCCESS;
897 break;
898 }
899
900 if (!(buffer = malloc( size ))) return ERROR_OUTOFMEMORY;
902 {
903 free( buffer );
904 return ret;
905 }
907 free( buffer );
908 if (!scheme) continue;
909
910 if (!first_scheme) first_scheme = scheme;
911 supported_schemes |= scheme;
912 }
913
914 if (!ret)
915 {
916 *supported = supported_schemes;
917 *first = first_scheme;
918 }
919 return ret;
920}
921
922/***********************************************************************
923 * WinHttpQueryAuthSchemes (winhttp.@)
924 */
926{
927 DWORD ret;
928 struct request *request;
929
930 TRACE("%p, %p, %p, %p\n", hrequest, supported, first, target);
931
932 if (!(request = (struct request *)grab_object( hrequest )))
933 {
935 return FALSE;
936 }
938 {
941 return FALSE;
942 }
943 if (!supported || !first || !target)
944 {
947 return FALSE;
948
949 }
950
952 {
954 }
956 {
958 }
960
962 SetLastError( ret );
963 return !ret;
964}
965
966static UINT encode_base64( const char *bin, unsigned int len, WCHAR *base64 )
967{
968 UINT n = 0, x;
969 static const char base64enc[] =
970 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
971
972 while (len > 0)
973 {
974 /* first 6 bits, all from bin[0] */
975 base64[n++] = base64enc[(bin[0] & 0xfc) >> 2];
976 x = (bin[0] & 3) << 4;
977
978 /* next 6 bits, 2 from bin[0] and 4 from bin[1] */
979 if (len == 1)
980 {
981 base64[n++] = base64enc[x];
982 base64[n++] = '=';
983 base64[n++] = '=';
984 break;
985 }
986 base64[n++] = base64enc[x | ((bin[1] & 0xf0) >> 4)];
987 x = (bin[1] & 0x0f) << 2;
988
989 /* next 6 bits 4 from bin[1] and 2 from bin[2] */
990 if (len == 2)
991 {
992 base64[n++] = base64enc[x];
993 base64[n++] = '=';
994 break;
995 }
996 base64[n++] = base64enc[x | ((bin[2] & 0xc0) >> 6)];
997
998 /* last 6 bits, all from bin [2] */
999 base64[n++] = base64enc[bin[2] & 0x3f];
1000 bin += 3;
1001 len -= 3;
1002 }
1003 base64[n] = 0;
1004 return n;
1005}
1006
1007static inline char decode_char( WCHAR c )
1008{
1009 if (c >= 'A' && c <= 'Z') return c - 'A';
1010 if (c >= 'a' && c <= 'z') return c - 'a' + 26;
1011 if (c >= '0' && c <= '9') return c - '0' + 52;
1012 if (c == '+') return 62;
1013 if (c == '/') return 63;
1014 return 64;
1015}
1016
1017static unsigned int decode_base64( const WCHAR *base64, unsigned int len, char *buf )
1018{
1019 unsigned int i = 0;
1020 char c0, c1, c2, c3;
1021 const WCHAR *p = base64;
1022
1023 while (len > 4)
1024 {
1025 if ((c0 = decode_char( p[0] )) > 63) return 0;
1026 if ((c1 = decode_char( p[1] )) > 63) return 0;
1027 if ((c2 = decode_char( p[2] )) > 63) return 0;
1028 if ((c3 = decode_char( p[3] )) > 63) return 0;
1029
1030 if (buf)
1031 {
1032 buf[i + 0] = (c0 << 2) | (c1 >> 4);
1033 buf[i + 1] = (c1 << 4) | (c2 >> 2);
1034 buf[i + 2] = (c2 << 6) | c3;
1035 }
1036 len -= 4;
1037 i += 3;
1038 p += 4;
1039 }
1040 if (p[2] == '=')
1041 {
1042 if ((c0 = decode_char( p[0] )) > 63) return 0;
1043 if ((c1 = decode_char( p[1] )) > 63) return 0;
1044
1045 if (buf) buf[i] = (c0 << 2) | (c1 >> 4);
1046 i++;
1047 }
1048 else if (p[3] == '=')
1049 {
1050 if ((c0 = decode_char( p[0] )) > 63) return 0;
1051 if ((c1 = decode_char( p[1] )) > 63) return 0;
1052 if ((c2 = decode_char( p[2] )) > 63) return 0;
1053
1054 if (buf)
1055 {
1056 buf[i + 0] = (c0 << 2) | (c1 >> 4);
1057 buf[i + 1] = (c1 << 4) | (c2 >> 2);
1058 }
1059 i += 2;
1060 }
1061 else
1062 {
1063 if ((c0 = decode_char( p[0] )) > 63) return 0;
1064 if ((c1 = decode_char( p[1] )) > 63) return 0;
1065 if ((c2 = decode_char( p[2] )) > 63) return 0;
1066 if ((c3 = decode_char( p[3] )) > 63) return 0;
1067
1068 if (buf)
1069 {
1070 buf[i + 0] = (c0 << 2) | (c1 >> 4);
1071 buf[i + 1] = (c1 << 4) | (c2 >> 2);
1072 buf[i + 2] = (c2 << 6) | c3;
1073 }
1074 i += 3;
1075 }
1076 return i;
1077}
1078
1079static struct authinfo *alloc_authinfo(void)
1080{
1081 struct authinfo *ret;
1082
1083 if (!(ret = malloc( sizeof(*ret) ))) return NULL;
1084
1085 SecInvalidateHandle( &ret->cred );
1086 SecInvalidateHandle( &ret->ctx );
1087 memset( &ret->exp, 0, sizeof(ret->exp) );
1088 ret->scheme = 0;
1089 ret->attr = 0;
1090 ret->max_token = 0;
1091 ret->data = NULL;
1092 ret->data_len = 0;
1093 ret->finished = FALSE;
1094 return ret;
1095}
1096
1098{
1099 if (!authinfo) return;
1100
1101 if (SecIsValidHandle( &authinfo->ctx ))
1105
1106 free( authinfo->data );
1107 free( authinfo );
1108}
1109
1111{
1112 DWORD size, index = 0;
1113 for (;;)
1114 {
1115 size = len;
1116 if (query_headers( request, level, NULL, buffer, &size, &index )) return FALSE;
1117 if (auth_scheme_from_header( buffer ) == scheme) break;
1118 }
1119 return TRUE;
1120}
1121
1122static BOOL do_authorization( struct request *request, DWORD target, DWORD scheme_flag )
1123{
1124 struct authinfo *authinfo, **auth_ptr;
1125 enum auth_scheme scheme = scheme_from_flag( scheme_flag );
1127 WCHAR auth_value[2048], *auth_reply;
1128 DWORD len = sizeof(auth_value), len_scheme, flags;
1129 BOOL ret, has_auth_value;
1130
1131 if (scheme == SCHEME_INVALID) return FALSE;
1132
1133 switch (target)
1134 {
1136 has_auth_value = get_authvalue( request, WINHTTP_QUERY_WWW_AUTHENTICATE, scheme_flag, auth_value, len );
1137 auth_ptr = &request->authinfo;
1138 auth_target = L"Authorization";
1139 if (request->creds[TARGET_SERVER][scheme].username)
1140 {
1141 if (scheme != SCHEME_BASIC && !has_auth_value) return FALSE;
1144 }
1145 else
1146 {
1147 if (!has_auth_value) return FALSE;
1148 username = request->connect->username;
1149 password = request->connect->password;
1150 }
1151 break;
1152
1154 if (!get_authvalue( request, WINHTTP_QUERY_PROXY_AUTHENTICATE, scheme_flag, auth_value, len ))
1155 return FALSE;
1156 auth_ptr = &request->proxy_authinfo;
1157 auth_target = L"Proxy-Authorization";
1158 if (request->creds[TARGET_PROXY][scheme].username)
1159 {
1162 }
1163 else
1164 {
1165 username = request->connect->session->proxy_username;
1166 password = request->connect->session->proxy_password;
1167 }
1168 break;
1169
1170 default:
1171 WARN( "unknown target %#lx\n", target );
1172 return FALSE;
1173 }
1174 authinfo = *auth_ptr;
1175
1176 switch (scheme)
1177 {
1178 case SCHEME_BASIC:
1179 {
1180 int userlen, passlen;
1181
1182 if (!username || !password) return FALSE;
1183 if ((!authinfo && !(authinfo = alloc_authinfo())) || authinfo->finished) return FALSE;
1184
1187
1188 authinfo->data_len = userlen + 1 + passlen;
1189 if (!(authinfo->data = malloc( authinfo->data_len ))) return FALSE;
1190
1191 WideCharToMultiByte( CP_UTF8, 0, username, -1, authinfo->data, userlen, NULL, NULL );
1192 authinfo->data[userlen] = ':';
1193 WideCharToMultiByte( CP_UTF8, 0, password, -1, authinfo->data + userlen + 1, passlen, NULL, NULL );
1194
1197 break;
1198 }
1199 case SCHEME_NTLM:
1200 case SCHEME_NEGOTIATE:
1201 {
1203 SecBufferDesc out_desc, in_desc;
1204 SecBuffer out, in;
1206 const WCHAR *p;
1207 BOOL first = FALSE;
1208
1209 if (!authinfo)
1210 {
1211 TimeStamp exp;
1213 WCHAR *domain, *user;
1214
1215 if (!username || !password || !(authinfo = alloc_authinfo())) return FALSE;
1216
1217 first = TRUE;
1218 domain = (WCHAR *)username;
1219 user = wcschr( username, '\\' );
1220
1221 if (user) user++;
1222 else
1223 {
1224 user = (WCHAR *)username;
1225 domain = NULL;
1226 }
1228 id.User = user;
1229 id.UserLength = lstrlenW( user );
1230 id.Domain = domain;
1231 id.DomainLength = domain ? user - domain - 1 : 0;
1232 id.Password = (WCHAR *)password;
1233 id.PasswordLength = lstrlenW( password );
1234
1237 &authinfo->cred, &exp );
1238 if (status == SEC_E_OK)
1239 {
1242 if (status == SEC_E_OK)
1243 {
1244 authinfo->max_token = info->cbMaxToken;
1246 }
1247 }
1248 if (status != SEC_E_OK)
1249 {
1250 WARN( "AcquireCredentialsHandleW for scheme %s failed with error %#lx\n",
1252 free( authinfo );
1253 return FALSE;
1254 }
1256 }
1257 else if (authinfo->finished) return FALSE;
1258
1259 if ((lstrlenW( auth_value ) < auth_schemes[authinfo->scheme].len ||
1260 wcsnicmp( auth_value, auth_schemes[authinfo->scheme].str, auth_schemes[authinfo->scheme].len )))
1261 {
1262 ERR("authentication scheme changed from %s to %s\n",
1263 debugstr_w(auth_schemes[authinfo->scheme].str), debugstr_w(auth_value));
1265 *auth_ptr = NULL;
1266 return FALSE;
1267 }
1268 in.BufferType = SECBUFFER_TOKEN;
1269 in.cbBuffer = 0;
1270 in.pvBuffer = NULL;
1271
1272 in_desc.ulVersion = 0;
1273 in_desc.cBuffers = 1;
1274 in_desc.pBuffers = &in;
1275
1276 p = auth_value + auth_schemes[scheme].len;
1277 if (*p == ' ')
1278 {
1279 int len = lstrlenW( ++p );
1280 in.cbBuffer = decode_base64( p, len, NULL );
1281 if (!(in.pvBuffer = malloc( in.cbBuffer ))) {
1283 *auth_ptr = NULL;
1284 return FALSE;
1285 }
1286 decode_base64( p, len, in.pvBuffer );
1287 }
1288 out.BufferType = SECBUFFER_TOKEN;
1289 out.cbBuffer = authinfo->max_token;
1290 if (!(out.pvBuffer = malloc( authinfo->max_token )))
1291 {
1292 free( in.pvBuffer );
1294 *auth_ptr = NULL;
1295 return FALSE;
1296 }
1297 out_desc.ulVersion = 0;
1298 out_desc.cBuffers = 1;
1299 out_desc.pBuffers = &out;
1300
1302 first ? request->connect->servername : NULL, flags, 0,
1303 SECURITY_NETWORK_DREP, in.pvBuffer ? &in_desc : NULL, 0,
1304 &authinfo->ctx, &out_desc, &authinfo->attr, &authinfo->exp );
1305 free( in.pvBuffer );
1306 if (status == SEC_E_OK)
1307 {
1308 free( authinfo->data );
1309 authinfo->data = out.pvBuffer;
1310 authinfo->data_len = out.cbBuffer;
1312 TRACE("sending last auth packet\n");
1313 }
1314 else if (status == SEC_I_CONTINUE_NEEDED)
1315 {
1316 free( authinfo->data );
1317 authinfo->data = out.pvBuffer;
1318 authinfo->data_len = out.cbBuffer;
1319 TRACE("sending next auth packet\n");
1320 }
1321 else
1322 {
1323 ERR( "InitializeSecurityContextW failed with error %#lx\n", status );
1324 free( out.pvBuffer );
1326 *auth_ptr = NULL;
1327 return FALSE;
1328 }
1329 break;
1330 }
1331 default:
1332 ERR("invalid scheme %u\n", scheme);
1333 return FALSE;
1334 }
1335 *auth_ptr = authinfo;
1336
1337 len_scheme = auth_schemes[authinfo->scheme].len;
1338 len = len_scheme + 1 + ((authinfo->data_len + 2) * 4) / 3;
1339 if (!(auth_reply = malloc( (len + 1) * sizeof(WCHAR) ))) return FALSE;
1340
1341 memcpy( auth_reply, auth_schemes[authinfo->scheme].str, len_scheme * sizeof(WCHAR) );
1342 auth_reply[len_scheme] = ' ';
1343 encode_base64( authinfo->data, authinfo->data_len, auth_reply + len_scheme + 1 );
1344
1346 ret = !process_header( request, auth_target, auth_reply, flags, TRUE );
1347 free( auth_reply );
1348 return ret;
1349}
1350
1352{
1353 WCHAR *ret, *host;
1354 unsigned int i;
1355 int len = lstrlenW( request->connect->hostname ) + 7;
1356
1357 if (!(host = malloc( len * sizeof(WCHAR) ))) return NULL;
1358 len = swprintf( host, len, L"%s:%u", request->connect->hostname, request->connect->hostport );
1359
1360 len += ARRAY_SIZE(L"CONNECT");
1361 len += ARRAY_SIZE(L"HTTP/1.1");
1362
1363 for (i = 0; i < request->num_headers; i++)
1364 {
1365 if (request->headers[i].is_request)
1366 len += lstrlenW( request->headers[i].field ) + lstrlenW( request->headers[i].value ) + 4; /* '\r\n: ' */
1367 }
1368 len += 4; /* '\r\n\r\n' */
1369
1370 if ((ret = malloc( (len + 1) * sizeof(WCHAR) )))
1371 {
1372 lstrcpyW( ret, L"CONNECT" );
1373 lstrcatW( ret, L" " );
1374 lstrcatW( ret, host );
1375 lstrcatW( ret, L" " );
1376 lstrcatW( ret, L"HTTP/1.1" );
1377
1378 for (i = 0; i < request->num_headers; i++)
1379 {
1380 if (request->headers[i].is_request)
1381 {
1382 lstrcatW( ret, L"\r\n" );
1383 lstrcatW( ret, request->headers[i].field );
1384 lstrcatW( ret, L": " );
1385 lstrcatW( ret, request->headers[i].value );
1386 }
1387 }
1388 lstrcatW( ret, L"\r\n\r\n" );
1389 }
1390
1391 free( host );
1392 return ret;
1393}
1394
1395static DWORD read_reply( struct request *request );
1396
1398{
1399 WCHAR *str;
1400 char *strA;
1401 int len, bytes_sent;
1402 DWORD ret;
1403
1405 strA = strdupWA( str );
1406 free( str );
1407 if (!strA) return ERROR_OUTOFMEMORY;
1408
1409 len = strlen( strA );
1410 ret = netconn_send( request->netconn, strA, len, &bytes_sent, NULL );
1411 free( strA );
1412 if (!ret) ret = read_reply( request );
1413
1414 return ret;
1415}
1416
1418{
1419 char buf[INET6_ADDRSTRLEN];
1420 void *src;
1421
1422 switch (addr->ss_family)
1423 {
1424 case AF_INET:
1425 src = &((struct sockaddr_in *)addr)->sin_addr;
1426 break;
1427 case AF_INET6:
1428 src = &((struct sockaddr_in6 *)addr)->sin6_addr;
1429 break;
1430 default:
1431 WARN("unsupported address family %d\n", addr->ss_family);
1432 return NULL;
1433 }
1434 if (!inet_ntop( addr->ss_family, src, buf, sizeof(buf) )) return NULL;
1435 return strdupAW( buf );
1436}
1437
1440{
1441 0, 0, &connection_pool_cs,
1443 0, 0, { (DWORD_PTR)(__FILE__ ": connection_pool_cs") }
1444};
1445static CRITICAL_SECTION connection_pool_cs = { &connection_pool_debug, -1, 0, 0, 0, 0 };
1446
1448
1450{
1451 LONG ref;
1452
1454 if (!(ref = --host->ref)) list_remove( &host->entry );
1456 if (ref) return;
1457
1458 assert( list_empty( &host->connections ) );
1459 free( host->hostname );
1460 free( host );
1461}
1462
1464
1466{
1467 unsigned int remaining_connections;
1468 struct netconn *netconn, *next_netconn;
1469 struct hostdata *host, *next_host;
1470 ULONGLONG now;
1471
1472 do
1473 {
1474 /* FIXME: Use more sophisticated method */
1475 Sleep(5000);
1476 remaining_connections = 0;
1477 now = GetTickCount64();
1478
1480
1482 {
1483 LIST_FOR_EACH_ENTRY_SAFE(netconn, next_netconn, &host->connections, struct netconn, entry)
1484 {
1485 if (netconn->keep_until < now)
1486 {
1487 TRACE("freeing %p\n", netconn);
1490 }
1491 else remaining_connections++;
1492 }
1493 }
1494
1495 if (!remaining_connections) connection_collector_running = FALSE;
1496
1498 } while(remaining_connections);
1499
1501}
1502
1503static void cache_connection( struct netconn *netconn )
1504{
1505 TRACE( "caching connection %p\n", netconn );
1506
1508
1510 list_add_head( &netconn->host->connections, &netconn->entry );
1511
1513 {
1515
1516 GetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (const WCHAR *)winhttp_instance, &module );
1517
1520 }
1521
1523}
1524
1526{
1527 DWORD ret = 0;
1533 return ret;
1534}
1535
1537{
1539
1541
1543 {
1544 SCHANNEL_CRED cred;
1545 memset( &cred, 0, sizeof(cred) );
1547 cred.grbitEnabledProtocols = map_secure_protocols( request->connect->session->secure_protocols );
1548 if (request->client_cert)
1549 {
1550 cred.paCred = &request->client_cert;
1551 cred.cCreds = 1;
1552 }
1554 &cred, NULL, NULL, &request->cred_handle, NULL );
1555 if (status == SEC_E_OK)
1557 }
1558
1559 if (status != SEC_E_OK)
1560 {
1561 WARN( "AcquireCredentialsHandleW failed: %#lx\n", status );
1562 return status;
1563 }
1564 return ERROR_SUCCESS;
1565}
1566
1568{
1570 struct hostdata *host = NULL, *iter;
1571 struct netconn *netconn = NULL;
1572 struct connect *connect;
1573 WCHAR *addressW = NULL;
1575 DWORD ret, len;
1576
1577 if (request->netconn) goto done;
1578
1581
1583
1585 {
1586 if (iter->port == port && !wcscmp( connect->servername, iter->hostname ) && !is_secure == !iter->secure)
1587 {
1588 host = iter;
1589 host->ref++;
1590 break;
1591 }
1592 }
1593
1594 if (!host)
1595 {
1596 if ((host = malloc( sizeof(*host) )))
1597 {
1598 host->ref = 1;
1599 host->secure = is_secure;
1600 host->port = port;
1601 list_init( &host->connections );
1602 if ((host->hostname = wcsdup( connect->servername )))
1603 {
1604 list_add_head( &connection_pool, &host->entry );
1605 }
1606 else
1607 {
1608 free( host );
1609 host = NULL;
1610 }
1611 }
1612 }
1613
1615
1616 if (!host) return ERROR_OUTOFMEMORY;
1617
1618 for (;;)
1619 {
1621 if (!list_empty( &host->connections ))
1622 {
1623 netconn = LIST_ENTRY( list_head( &host->connections ), struct netconn, entry );
1625 }
1627 if (!netconn) break;
1628
1629 if (netconn_is_alive( netconn )) break;
1630 TRACE("connection %p no longer alive, closing\n", netconn);
1632 netconn = NULL;
1633 }
1634
1635 if (!connect->resolved && netconn)
1636 {
1639 }
1640
1641 if (!connect->resolved)
1642 {
1643 len = lstrlenW( host->hostname ) + 1;
1645
1647 {
1648 release_host( host );
1649 return ret;
1650 }
1652
1653 if (!(addressW = addr_to_str( &connect->sockaddr )))
1654 {
1655 release_host( host );
1656 return ERROR_OUTOFMEMORY;
1657 }
1658 len = lstrlenW( addressW ) + 1;
1660 }
1661
1662 if (!netconn)
1663 {
1664 if (!addressW && !(addressW = addr_to_str( &connect->sockaddr )))
1665 {
1666 release_host( host );
1667 return ERROR_OUTOFMEMORY;
1668 }
1669
1670 TRACE("connecting to %s:%u\n", debugstr_w(addressW), port);
1671
1672 len = lstrlenW( addressW ) + 1;
1674
1676 {
1677 free( addressW );
1678 release_host( host );
1679 return ret;
1680 }
1683
1685
1686 if (is_secure)
1687 {
1688 if (connect->session->proxy_server && wcsicmp( connect->hostname, connect->servername ))
1689 {
1690 if ((ret = secure_proxy_connect( request )))
1691 {
1692 request->netconn = NULL;
1693 free( addressW );
1695 return ret;
1696 }
1697 }
1698
1701
1702 if ((ret = ensure_cred_handle( request )) ||
1705 {
1706 request->netconn = NULL;
1707 free( addressW );
1709 return ret;
1710 }
1711 }
1712
1714 }
1715 else
1716 {
1717 TRACE("using connection %p\n", netconn);
1718
1722 }
1723
1725 {
1726 free( addressW );
1729 }
1730
1731done:
1736 free( addressW );
1737 return ERROR_SUCCESS;
1738}
1739
1741{
1742 if (!request->netconn) return;
1743
1745 request->netconn = NULL;
1746}
1747
1748static DWORD add_host_header( struct request *request, DWORD modifier )
1749{
1750 DWORD ret, len;
1751 WCHAR *host;
1752 struct connect *connect = request->connect;
1754
1755 port = connect->hostport ? connect->hostport : (request->hdr.flags & WINHTTP_FLAG_SECURE ? 443 : 80);
1756
1758 {
1759 return process_header( request, L"Host", connect->hostname, modifier, TRUE );
1760 }
1761 len = lstrlenW( connect->hostname ) + 7; /* sizeof(":65335") */
1762 if (!(host = malloc( len * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY;
1763 swprintf( host, len, L"%s:%u", connect->hostname, port );
1764 ret = process_header( request, L"Host", host, modifier, TRUE );
1765 free( host );
1766 return ret;
1767}
1768
1770{
1771 unsigned int i;
1772
1773 for (i = 0; i < request->num_headers; i++)
1774 {
1775 if (!request->headers[i].field) continue;
1776 if (!request->headers[i].value) continue;
1777 if (request->headers[i].is_request) continue;
1779 i--;
1780 }
1781}
1782
1783/* remove some amount of data from the read buffer */
1784static void remove_data( struct request *request, int count )
1785{
1786 if (!(request->read_size -= count)) request->read_pos = 0;
1787 else request->read_pos += count;
1788}
1789
1790/* read some more data into the read buffer */
1791static DWORD read_more_data( struct request *request, int maxlen, BOOL notify )
1792{
1793 int len;
1794 DWORD ret;
1795
1797
1799 {
1800 /* move existing data to the start of the buffer */
1802 request->read_pos = 0;
1803 }
1804 if (maxlen == -1) maxlen = sizeof(request->read_buf);
1805
1807
1809 maxlen - request->read_size, 0, &len );
1810
1813
1814 request->read_size += len;
1815 return ret;
1816}
1817
1818/* discard data contents until we reach end of line */
1820{
1821 DWORD ret;
1822 do
1823 {
1824 char *eol = memchr( request->read_buf + request->read_pos, '\n', request->read_size );
1825 if (eol)
1826 {
1827 remove_data( request, (eol + 1) - (request->read_buf + request->read_pos) );
1828 break;
1829 }
1830 request->read_pos = request->read_size = 0; /* discard everything */
1831 if ((ret = read_more_data( request, -1, notify ))) return ret;
1832 } while (request->read_size);
1833 return ERROR_SUCCESS;
1834}
1835
1837{
1838 if (ch >= '0' && ch <= '9') *value = *value * 16 + ch - '0';
1839 else if (ch >= 'a' && ch <= 'f') *value = *value * 16 + ch - 'a' + 10;
1840 else if (ch >= 'A' && ch <= 'F') *value = *value * 16 + ch - 'A' + 10;
1841}
1842
1843/* read chunk size if already in the read buffer */
1845{
1846 DWORD chunk_size;
1847 char *p, *eol;
1848
1849 if (request->read_chunked_size != ~0ul) return TRUE;
1850
1852 if (!eol) return FALSE;
1853
1854 chunk_size = 0;
1855 for (p = request->read_buf + request->read_pos; p != eol; ++p)
1856 {
1857 if (*p == ';' || *p == '\r') break;
1858 update_value_from_digit( &chunk_size, *p );
1859 }
1860
1861 request->read_chunked_size = chunk_size;
1862 if (!chunk_size) request->read_chunked_eof = TRUE;
1863
1864 remove_data( request, (eol + 1) - (request->read_buf + request->read_pos) );
1865 return TRUE;
1866}
1867
1868/* read the size of the next chunk */
1870{
1871 DWORD ret, chunk_size = 0;
1872
1874
1876
1877 /* read terminator for the previous chunk */
1878 if (!request->read_chunked_size && (ret = discard_eol( request, notify ))) return ret;
1879
1880 for (;;)
1881 {
1882 while (request->read_size)
1883 {
1885
1886 if (ch == ';' || ch == '\r' || ch == '\n')
1887 {
1888 TRACE( "reading %lu byte chunk\n", chunk_size );
1889
1890 if (request->content_length == ~0u) request->content_length = chunk_size;
1891 else request->content_length += chunk_size;
1892
1893 request->read_chunked_size = chunk_size;
1894 if (!chunk_size) request->read_chunked_eof = TRUE;
1895
1896 return discard_eol( request, notify );
1897 }
1898 update_value_from_digit( &chunk_size, ch );
1899 remove_data( request, 1 );
1900 }
1901 if ((ret = read_more_data( request, -1, notify ))) return ret;
1902 if (!request->read_size)
1903 {
1906 return ERROR_SUCCESS;
1907 }
1908 }
1909}
1910
1912{
1913 int len = sizeof(request->read_buf);
1914 DWORD ret;
1915
1916 if (request->read_chunked)
1917 {
1920 {
1921 if ((ret = start_next_chunk( request, notify ))) return ret;
1922 }
1924 }
1925 else if (request->content_length != ~0u)
1926 {
1928 }
1929
1930 if (len <= request->read_size) return ERROR_SUCCESS;
1931 if ((ret = read_more_data( request, len, notify ))) return ret;
1933 return ERROR_SUCCESS;
1934}
1935
1936static void finished_reading( struct request *request )
1937{
1938 BOOL close = FALSE, close_request_headers;
1939 WCHAR connection[20];
1940 DWORD size = sizeof(connection);
1941
1942 if (!request->netconn) return;
1943
1944 if (request->netconn->socket == -1) close = TRUE;
1945 else if (request->hdr.disable_flags & WINHTTP_DISABLE_KEEP_ALIVE) close = TRUE;
1946 else if (!query_headers( request, WINHTTP_QUERY_CONNECTION, NULL, connection, &size, NULL ) ||
1948 {
1949 if (!wcsicmp( connection, L"close" )) close = TRUE;
1950 }
1951 else if (!wcscmp( request->version, L"HTTP/1.0" )) close = TRUE;
1952
1953 size = sizeof(connection);
1954 close_request_headers =
1957 && !wcsicmp( connection, L"close" );
1958 if (close || close_request_headers)
1959 {
1960 if (close_request_headers) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, 0, 0 );
1962 if (close_request_headers) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, 0, 0 );
1963 }
1964 else
1966 request->netconn = NULL;
1967}
1968
1969/* return the size of data available to be read immediately */
1971{
1972 if (request->read_chunked)
1973 {
1974 if (!get_chunk_size( request )) return 0;
1976 }
1977 return request->read_size;
1978}
1979
1980/* check if we have reached the end of the data to read */
1982{
1983 if (!request->content_length) return TRUE;
1985 if (request->content_length == ~0u) return FALSE;
1987}
1988
1989static DWORD read_data( struct request *request, void *buffer, DWORD size, DWORD *read, BOOL async )
1990{
1991 int count, bytes_read = 0;
1993
1995 && (ret = start_next_chunk( request, async ))) goto done;
1996
1997 if (end_of_read_data( request )) goto done;
1998
1999 while (size)
2000 {
2001 if (!(count = get_available_data( request )))
2002 {
2003 if ((ret = refill_buffer( request, async ))) goto done;
2004 if (!(count = get_available_data( request ))) goto done;
2005 }
2006 count = min( count, size );
2007 memcpy( (char *)buffer + bytes_read, request->read_buf + request->read_pos, count );
2010 size -= count;
2011 bytes_read += count;
2013 if (end_of_read_data( request )) goto done;
2014 }
2016
2017done:
2018 TRACE( "retrieved %u bytes (%lu/%lu)\n", bytes_read, request->content_read, request->content_length );
2020 if (async)
2021 {
2023 else
2024 {
2026 result.dwResult = API_READ_DATA;
2027 result.dwError = ret;
2029 }
2030 }
2031
2032 if (!ret && read) *read = bytes_read;
2033 return ret;
2034}
2035
2036/* read any content returned by the server so that the connection can be reused */
2037static void drain_content( struct request *request )
2038{
2039 DWORD size, bytes_read, bytes_total = 0, bytes_left = request->content_length - request->content_read;
2040 char buffer[2048];
2041
2043 for (;;)
2044 {
2045 if (request->read_chunked) size = sizeof(buffer);
2046 else size = min( sizeof(buffer), bytes_left - bytes_total );
2047
2048 if (read_data( request, buffer, size, &bytes_read, FALSE ) || !bytes_read) return;
2049 bytes_total += bytes_read;
2050 }
2051}
2052
2054{
2062};
2063
2064#define ESCAPE_MASK_DEFAULT (ESCAPE_FLAG_NON_PRINTABLE | ESCAPE_FLAG_SPACE | ESCAPE_FLAG_UNSAFE |\
2065 ESCAPE_FLAG_DEL | ESCAPE_FLAG_8BIT)
2066#define ESCAPE_MASK_PERCENT (ESCAPE_FLAG_PERCENT | ESCAPE_MASK_DEFAULT)
2067#define ESCAPE_MASK_DISABLE (ESCAPE_FLAG_SPACE | ESCAPE_FLAG_8BIT | ESCAPE_FLAG_STRIP_CRLF)
2068
2069static inline BOOL need_escape( char ch, enum escape_flags flags )
2070{
2071 static const char unsafe[] = "\"#<>[\\]^`{|}";
2072 const char *ptr = unsafe;
2073
2074 if ((flags & ESCAPE_FLAG_SPACE) && ch == ' ') return TRUE;
2075 if ((flags & ESCAPE_FLAG_PERCENT) && ch == '%') return TRUE;
2076 if ((flags & ESCAPE_FLAG_NON_PRINTABLE) && ch < 0x20) return TRUE;
2077 if ((flags & ESCAPE_FLAG_DEL) && ch == 0x7f) return TRUE;
2078 if ((flags & ESCAPE_FLAG_8BIT) && (ch & 0x80)) return TRUE;
2079 if ((flags & ESCAPE_FLAG_UNSAFE)) while (*ptr) { if (ch == *ptr++) return TRUE; }
2080 return FALSE;
2081}
2082
2083static DWORD escape_string( const char *src, DWORD len, char *dst, enum escape_flags flags )
2084{
2085 static const char hex[] = "0123456789ABCDEF";
2086 DWORD i, ret = len;
2087 char *ptr = dst;
2088
2089 for (i = 0; i < len; i++)
2090 {
2091 if ((flags & ESCAPE_FLAG_STRIP_CRLF) && (src[i] == '\r' || src[i] == '\n'))
2092 {
2093 ret--;
2094 continue;
2095 }
2096 if (need_escape( src[i], flags ))
2097 {
2098 if (dst)
2099 {
2100 ptr[0] = '%';
2101 ptr[1] = hex[(src[i] >> 4) & 0xf];
2102 ptr[2] = hex[src[i] & 0xf];
2103 ptr += 3;
2104 }
2105 ret += 2;
2106 }
2107 else if (dst) *ptr++ = src[i];
2108 }
2109
2110 if (dst) dst[ret] = 0;
2111 return ret;
2112}
2113
2114static DWORD str_to_wire( const WCHAR *src, int src_len, char *dst, enum escape_flags flags )
2115{
2116 DWORD len;
2117 char *utf8;
2118
2119 if (src_len < 0) src_len = lstrlenW( src );
2120 len = WideCharToMultiByte( CP_UTF8, 0, src, src_len, NULL, 0, NULL, NULL );
2121 if (!(utf8 = malloc( len ))) return 0;
2122
2125 free( utf8 );
2126
2127 return len;
2128}
2129
2131{
2132 WCHAR *full_path;
2133 const WCHAR *start, *path, *query = NULL;
2134 DWORD len, len_path = 0, len_query = 0;
2135 enum escape_flags path_flags, query_flags;
2136 char *ret;
2137
2138 if (!wcsicmp( request->connect->hostname, request->connect->servername )) start = full_path = request->path;
2139 else if (!(full_path = build_absolute_request_path( request, &start ))) return NULL;
2140
2141 len = lstrlenW( full_path );
2142 if ((path = wcschr( start, '/' )))
2143 {
2144 len_path = lstrlenW( path );
2145 if ((query = wcschr( path, '?' )))
2146 {
2147 len_query = lstrlenW( query );
2148 len_path -= len_query;
2149 }
2150 }
2151
2153 else if (request->hdr.flags & WINHTTP_FLAG_ESCAPE_PERCENT) path_flags = ESCAPE_MASK_PERCENT;
2154 else path_flags = ESCAPE_MASK_DEFAULT;
2155
2157 else query_flags = path_flags;
2158
2159 *ret_len = str_to_wire( full_path, len - len_path - len_query, NULL, 0 );
2160 if (path) *ret_len += str_to_wire( path, len_path, NULL, path_flags );
2161 if (query) *ret_len += str_to_wire( query, len_query, NULL, query_flags );
2162
2163 if ((ret = malloc( *ret_len + 1 )))
2164 {
2165 len = str_to_wire( full_path, len - len_path - len_query, ret, 0 );
2166 if (path) len += str_to_wire( path, len_path, ret + len, path_flags );
2167 if (query) str_to_wire( query, len_query, ret + len, query_flags );
2168 }
2169
2170 if (full_path != request->path) free( full_path );
2171 return ret;
2172}
2173
2174static char *build_wire_request( struct request *request, DWORD *len )
2175{
2176 char *path, *ptr, *ret;
2177 DWORD i, len_path;
2178
2179 if (!(path = build_wire_path( request, &len_path ))) return NULL;
2180
2181 *len = str_to_wire( request->verb, -1, NULL, 0 ) + 1; /* ' ' */
2182 *len += len_path + 1; /* ' ' */
2183 *len += str_to_wire( request->version, -1, NULL, 0 );
2184
2185 for (i = 0; i < request->num_headers; i++)
2186 {
2187 if (request->headers[i].is_request)
2188 {
2189 *len += str_to_wire( request->headers[i].field, -1, NULL, 0 ) + 2; /* ': ' */
2190 *len += str_to_wire( request->headers[i].value, -1, NULL, 0 ) + 2; /* '\r\n' */
2191 }
2192 }
2193 *len += 4; /* '\r\n\r\n' */
2194
2195 if ((ret = ptr = malloc( *len + 1 )))
2196 {
2197 ptr += str_to_wire( request->verb, -1, ptr, 0 );
2198 *ptr++ = ' ';
2199 memcpy( ptr, path, len_path );
2200 ptr += len_path;
2201 *ptr++ = ' ';
2202 ptr += str_to_wire( request->version, -1, ptr, 0 );
2203
2204 for (i = 0; i < request->num_headers; i++)
2205 {
2206 if (request->headers[i].is_request)
2207 {
2208 *ptr++ = '\r';
2209 *ptr++ = '\n';
2210 ptr += str_to_wire( request->headers[i].field, -1, ptr, 0 );
2211 *ptr++ = ':';
2212 *ptr++ = ' ';
2213 ptr += str_to_wire( request->headers[i].value, -1, ptr, 0 );
2214 }
2215 }
2216 memcpy( ptr, "\r\n\r\n", sizeof("\r\n\r\n") );
2217 }
2218
2219 free( path );
2220 return ret;
2221}
2222
2224{
2225 WCHAR *ret;
2226 char buf[16];
2227 DWORD base64_len = ((sizeof(buf) + 2) * 4) / 3;
2228 if (!RtlGenRandom( buf, sizeof(buf) )) return NULL;
2229 if ((ret = malloc( (base64_len + 1) * sizeof(WCHAR) ))) encode_base64( buf, sizeof(buf), ret );
2230 return ret;
2231}
2232
2234{
2236 if (!key) return ERROR_OUTOFMEMORY;
2238 free( key );
2239 return ERROR_SUCCESS;
2240}
2241
2242static DWORD send_request( struct request *request, const WCHAR *headers, DWORD headers_len, void *optional,
2243 DWORD optional_len, DWORD total_len, DWORD_PTR context, BOOL async )
2244{
2245 struct connect *connect = request->connect;
2246 struct session *session = connect->session;
2247 DWORD ret, len, buflen, content_length;
2248 WCHAR encoding[20];
2249 char *wire_req;
2250 int bytes_sent;
2251 BOOL chunked;
2252
2253 TRACE( "request state %d.\n", request->state );
2254
2258
2261 {
2262 WARN( "Invalid send buffer size %u.\n", request->websocket_set_send_buffer_size );
2264 goto end;
2265 }
2266
2269
2270 if (session->agent)
2272
2273 if (connect->hostname)
2275
2276 if (request->creds[TARGET_SERVER][SCHEME_BASIC].username)
2278
2279 buflen = sizeof(encoding);
2281 NULL, encoding, &buflen, NULL ) && !wcsicmp( encoding, L"chunked" );
2282 if (!chunked && (total_len || (request->verb && (!wcscmp( request->verb, L"POST" )
2283 || !wcscmp( request->verb, L"PUT" )))))
2284 {
2285 WCHAR length[21]; /* decimal long int + null */
2286 swprintf( length, ARRAY_SIZE(length), L"%ld", total_len );
2288 }
2290 {
2292 process_header( request, L"Upgrade", L"websocket", WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE );
2293 process_header( request, L"Connection", L"Upgrade", WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE );
2294 process_header( request, L"Sec-WebSocket-Version", L"13", WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE );
2295 if ((ret = add_websocket_key_header( request ))) return ret;
2296 }
2297 else if (!(request->hdr.disable_flags & WINHTTP_DISABLE_KEEP_ALIVE))
2298 {
2299 process_header( request, L"Connection", L"Keep-Alive", WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE );
2300 }
2301 if (request->hdr.flags & WINHTTP_FLAG_REFRESH)
2302 {
2304 process_header( request, L"Cache-Control", L"no-cache", WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE );
2305 }
2306 if (headers && (ret = add_request_headers( request, headers, headers_len,
2308 {
2309 TRACE( "failed to add request headers: %lu\n", ret );
2310 return ret;
2311 }
2312 if (!(request->hdr.disable_flags & WINHTTP_DISABLE_COOKIES) && (ret = add_cookie_headers( request )))
2313 {
2314 WARN( "failed to add cookie headers: %lu\n", ret );
2315 return ret;
2316 }
2317
2318 if (context) request->hdr.context = context;
2319
2320 if ((ret = open_connection( request ))) goto end;
2321 if (!(wire_req = build_wire_request( request, &len )))
2322 {
2324 goto end;
2325 }
2326 TRACE("full request: %s\n", debugstr_a(wire_req));
2327
2330
2331 ret = netconn_send( request->netconn, wire_req, len, &bytes_sent, NULL );
2332 free( wire_req );
2333 if (ret) goto end;
2334
2335 if (optional_len)
2336 {
2337 if ((ret = netconn_send( request->netconn, optional, optional_len, &bytes_sent, NULL ))) goto end;
2339 request->optional_len = optional_len;
2340 len += optional_len;
2341 }
2343
2344 buflen = sizeof(content_length);
2347 content_length = total_len;
2348
2349 if (!chunked && content_length <= optional_len)
2350 {
2355 else
2357 }
2358 else
2359 {
2362 else
2364 }
2365
2366end:
2367 if (async)
2368 {
2370 else
2371 {
2373 result.dwResult = API_SEND_REQUEST;
2374 result.dwError = ret;
2376 }
2377 }
2378 return ret;
2379}
2380
2381static void task_send_request( void *ctx, BOOL abort )
2382{
2383 struct send_request *s = ctx;
2384 struct request *request = (struct request *)s->task_hdr.obj;
2385
2386 if (abort) return;
2387
2388 TRACE( "running %p\n", ctx );
2389 send_request( request, s->headers, s->headers_len, s->optional, s->optional_len, s->total_len, s->context, TRUE );
2390
2391 free( s->headers );
2392}
2393
2394/***********************************************************************
2395 * WinHttpSendRequest (winhttp.@)
2396 */
2398 void *optional, DWORD optional_len, DWORD total_len, DWORD_PTR context )
2399{
2400 DWORD ret;
2401 struct request *request;
2402
2403 TRACE( "%p, %s, %lu, %p, %lu, %lu, %Ix\n", hrequest, debugstr_wn(headers, headers_len), headers_len, optional,
2404 optional_len, total_len, context );
2405
2406 if (!(request = (struct request *)grab_object( hrequest )))
2407 {
2409 return FALSE;
2410 }
2412 {
2415 return FALSE;
2416 }
2417
2418 if (headers && !headers_len) headers_len = lstrlenW( headers );
2419
2420 if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC)
2421 {
2422 struct send_request *s;
2423
2424 if (!(s = malloc( sizeof(*s) )))
2425 {
2428 return FALSE;
2429 }
2430 s->headers = wcsdup( headers );
2431 s->headers_len = headers_len;
2432 s->optional = optional;
2433 s->optional_len = optional_len;
2434 s->total_len = total_len;
2435 s->context = context;
2436
2437 if ((ret = queue_task( &request->queue, task_send_request, &s->task_hdr, &request->hdr )))
2438 {
2439 free( s->headers );
2440 free( s );
2441 }
2442 }
2444
2446 SetLastError( ret );
2447 return !ret;
2448}
2449
2450static DWORD set_credentials( struct request *request, DWORD target, DWORD scheme_flag, const WCHAR *username,
2451 const WCHAR *password )
2452{
2453 enum auth_scheme scheme = scheme_from_flag( scheme_flag );
2454
2456 {
2458 }
2459 switch (target)
2460 {
2462 {
2463 free( request->creds[TARGET_SERVER][scheme].username );
2464 if (!username) request->creds[TARGET_SERVER][scheme].username = NULL;
2465 else if (!(request->creds[TARGET_SERVER][scheme].username = wcsdup( username ))) return ERROR_OUTOFMEMORY;
2466
2467 free( request->creds[TARGET_SERVER][scheme].password );
2468 if (!password) request->creds[TARGET_SERVER][scheme].password = NULL;
2469 else if (!(request->creds[TARGET_SERVER][scheme].password = wcsdup( password ))) return ERROR_OUTOFMEMORY;
2470 break;
2471 }
2473 {
2474 free( request->creds[TARGET_PROXY][scheme].username );
2475 if (!username) request->creds[TARGET_PROXY][scheme].username = NULL;
2476 else if (!(request->creds[TARGET_PROXY][scheme].username = wcsdup( username ))) return ERROR_OUTOFMEMORY;
2477
2478 free( request->creds[TARGET_PROXY][scheme].password );
2479 if (!password) request->creds[TARGET_PROXY][scheme].password = NULL;
2480 else if (!(request->creds[TARGET_PROXY][scheme].password = wcsdup( password ))) return ERROR_OUTOFMEMORY;
2481 break;
2482 }
2483 default:
2484 WARN( "unknown target %lu\n", target );
2486 }
2487 return ERROR_SUCCESS;
2488}
2489
2490/***********************************************************************
2491 * WinHttpSetCredentials (winhttp.@)
2492 */
2494 const WCHAR *password, void *params )
2495{
2496 DWORD ret;
2497 struct request *request;
2498
2499 TRACE( "%p, %lu, %#lx, %s, %p, %p\n", hrequest, target, scheme, debugstr_w(username), password, params );
2500
2501 if (!(request = (struct request *)grab_object( hrequest )))
2502 {
2504 return FALSE;
2505 }
2507 {
2510 return FALSE;
2511 }
2512
2514
2516 SetLastError( ret );
2517 return !ret;
2518}
2519
2521{
2522 DWORD ret, i, schemes, first, level, target;
2523
2524 switch (status)
2525 {
2526 case HTTP_STATUS_DENIED:
2529 break;
2530
2534 break;
2535
2536 default:
2537 ERR( "unhandled status %lu\n", status );
2539 }
2540
2541 if ((ret = query_auth_schemes( request, level, &schemes, &first ))) return ret;
2543
2544 schemes &= ~first;
2545 for (i = 0; i < ARRAY_SIZE( auth_schemes ); i++)
2546 {
2547 if (!(schemes & auth_schemes[i].scheme)) continue;
2549 }
2551}
2552
2553/* set the request content length based on the headers */
2555{
2556 WCHAR encoding[20];
2557 DWORD buflen = sizeof(request->content_length);
2558
2561 {
2563 }
2564 else
2565 {
2567 NULL, &request->content_length, &buflen, NULL ))
2569
2570 buflen = sizeof(encoding);
2571 if (!query_headers( request, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, encoding, &buflen, NULL ) &&
2572 !wcsicmp( encoding, L"chunked" ))
2573 {
2578 }
2579 }
2580 request->content_read = 0;
2581}
2582
2583static DWORD read_line( struct request *request, char *buffer, DWORD *len )
2584{
2585 int count, bytes_read, pos = 0;
2586 DWORD ret;
2587
2588 for (;;)
2589 {
2590 char *eol = memchr( request->read_buf + request->read_pos, '\n', request->read_size );
2591 if (eol)
2592 {
2593 count = eol - (request->read_buf + request->read_pos);
2594 bytes_read = count + 1;
2595 }
2596 else count = bytes_read = request->read_size;
2597
2598 count = min( count, *len - pos );
2600 pos += count;
2601 remove_data( request, bytes_read );
2602 if (eol) break;
2603
2604 if ((ret = read_more_data( request, -1, FALSE ))) return ret;
2605 if (!request->read_size)
2606 {
2607 *len = 0;
2608 TRACE("returning empty string\n");
2610 }
2611 }
2612 if (pos < *len)
2613 {
2614 if (pos && buffer[pos - 1] == '\r') pos--;
2615 *len = pos + 1;
2616 }
2617 buffer[*len - 1] = 0;
2618 TRACE("returning %s\n", debugstr_a(buffer));
2619 return ERROR_SUCCESS;
2620}
2621
2622#define MAX_REPLY_LEN 1460
2623#define INITIAL_HEADER_BUFFER_LEN 512
2624
2626{
2627 char buffer[MAX_REPLY_LEN];
2628 DWORD ret, buflen, len, offset, crlf_len = 2; /* lstrlenW(crlf) */
2629 char *status_code, *status_text;
2630 WCHAR *versionW, *status_textW, *raw_headers;
2631 WCHAR status_codeW[4]; /* sizeof("nnn") */
2632
2634
2635 do
2636 {
2637 buflen = MAX_REPLY_LEN;
2638 if ((ret = read_line( request, buffer, &buflen ))) return ret;
2639
2640 /* first line should look like 'HTTP/1.x nnn OK' where nnn is the status code */
2642 status_code++;
2644 if ((len = status_text - status_code) != sizeof("nnn") - 1) return ERROR_WINHTTP_INVALID_SERVER_RESPONSE;
2645 status_text++;
2646
2647 TRACE("version [%s] status code [%s] status text [%s]\n",
2651
2652 } while (!memcmp( status_code, "100", len )); /* ignore "100 Continue" responses */
2653
2654 /* we rely on the fact that the protocol is ascii */
2655 MultiByteToWideChar( CP_ACP, 0, status_code, len, status_codeW, len );
2656 status_codeW[len] = 0;
2657 if ((ret = process_header( request, L"Status", status_codeW,
2659
2661 if (!(versionW = malloc( len * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY;
2663 versionW[len - 1] = 0;
2664
2665 free( request->version );
2667
2668 len = buflen - (status_text - buffer);
2669 if (!(status_textW = malloc( len * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY;
2670 MultiByteToWideChar( CP_ACP, 0, status_text, len, status_textW, len );
2671
2673 request->status_text = status_textW;
2674
2675 len = max( buflen + crlf_len, INITIAL_HEADER_BUFFER_LEN );
2676 if (!(raw_headers = malloc( len * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY;
2677 MultiByteToWideChar( CP_ACP, 0, buffer, buflen, raw_headers, buflen );
2678 memcpy( raw_headers + buflen - 1, L"\r\n", sizeof(L"\r\n") );
2679
2682
2683 offset = buflen + crlf_len - 1;
2684 for (;;)
2685 {
2686 struct header *header;
2687 int lenW;
2688
2689 buflen = MAX_REPLY_LEN;
2690 if (read_line( request, buffer, &buflen )) return ERROR_SUCCESS;
2691 if (!*buffer) buflen = 1;
2692
2693 while (len - offset < buflen + crlf_len)
2694 {
2695 WCHAR *tmp;
2696 len *= 2;
2697 if (!(tmp = realloc( raw_headers, len * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY;
2698 request->raw_headers = raw_headers = tmp;
2699 }
2700 if (!*buffer)
2701 {
2702 memcpy( raw_headers + offset, L"\r\n", sizeof(L"\r\n") );
2703 break;
2704 }
2705 lenW = MultiByteToWideChar( CP_ACP, 0, buffer, buflen, raw_headers + offset, buflen );
2706
2707 if (!(header = parse_header( raw_headers + offset, lenW - 1, TRUE ))) break;
2709 {
2711 break;
2712 }
2713
2714 lenW = wcslen( header->field );
2715 assert( len - offset >= lenW + 1 );
2716 memcpy( raw_headers + offset, header->field, lenW * sizeof(WCHAR) );
2717 offset += lenW;
2718
2719 lenW = 2;
2720 assert( len - offset >= lenW + 1 );
2721 memcpy( raw_headers + offset, L": ", lenW * sizeof(WCHAR) );
2722 offset += lenW;
2723
2724 lenW = wcslen( header->value );
2725 assert( len - offset >= lenW + 1 );
2726 memcpy( raw_headers + offset, header->value, lenW * sizeof(WCHAR) );
2727 offset += lenW;
2728
2729 lenW = crlf_len;
2730 assert( len - offset >= lenW + 1 );
2731 memcpy( raw_headers + offset, L"\r\n", lenW * sizeof(WCHAR) );
2732 offset += lenW;
2733
2734 raw_headers[offset] = 0;
2736 }
2737
2738 TRACE("raw headers: %s\n", debugstr_w(raw_headers));
2739 return ret;
2740}
2741
2742static void record_cookies( struct request *request )
2743{
2744 unsigned int i;
2745
2746 for (i = 0; i < request->num_headers; i++)
2747 {
2748 struct header *set_cookie = &request->headers[i];
2749 if (!wcsicmp( set_cookie->field, L"Set-Cookie" ) && !set_cookie->is_request)
2750 {
2751 set_cookies( request, set_cookie->value );
2752 }
2753 }
2754}
2755
2757{
2758 DWORD size, ret;
2759 WCHAR *url;
2760
2762 if (ret != ERROR_INSUFFICIENT_BUFFER) return ret;
2763 if (!(url = malloc( size ))) return ERROR_OUTOFMEMORY;
2765 {
2766 free( url );
2767 return ret;
2768 }
2769 *ret_url = url;
2770 *ret_len = size / sizeof(WCHAR);
2771 return ERROR_SUCCESS;
2772}
2773
2775{
2776 DWORD ret, len, len_loc = 0;
2777 URL_COMPONENTS uc;
2778 struct connect *connect = request->connect;
2781
2782 if ((ret = get_redirect_url( request, &location, &len_loc ))) return ret;
2783
2784 memset( &uc, 0, sizeof(uc) );
2785 uc.dwStructSize = sizeof(uc);
2787
2788 if (!WinHttpCrackUrl( location, len_loc, 0, &uc )) /* assume relative redirect */
2789 {
2790 WCHAR *path, *p;
2791
2793 if (location[0] == '/')
2794 {
2795 if (!(path = malloc( (len_loc + 1) * sizeof(WCHAR) ))) goto end;
2796 memcpy( path, location, len_loc * sizeof(WCHAR) );
2797 path[len_loc] = 0;
2798 }
2799 else
2800 {
2801 if ((p = wcsrchr( request->path, '/' ))) *p = 0;
2802 len = lstrlenW( request->path ) + 1 + len_loc;
2803 if (!(path = malloc( (len + 1) * sizeof(WCHAR) ))) goto end;
2805 lstrcatW( path, L"/" );
2806 memcpy( path + lstrlenW(path), location, len_loc * sizeof(WCHAR) );
2807 path[len_loc] = 0;
2808 }
2809 free( request->path );
2810 request->path = path;
2812
2814 }
2815 else
2816 {
2818 {
2820 {
2822 goto end;
2823 }
2824 TRACE("redirect from secure page to non-secure page\n");
2825 request->hdr.flags &= ~WINHTTP_FLAG_SECURE;
2826 }
2827 else if (uc.nScheme == INTERNET_SCHEME_HTTPS && !(request->hdr.flags & WINHTTP_FLAG_SECURE))
2828 {
2829 TRACE("redirect from non-secure page to secure page\n");
2831 }
2832
2834
2835 len = uc.dwHostNameLength;
2836 if (!(hostname = malloc( (len + 1) * sizeof(WCHAR) )))
2837 {
2839 goto end;
2840 }
2841 memcpy( hostname, uc.lpszHostName, len * sizeof(WCHAR) );
2842 hostname[len] = 0;
2843
2844 port = uc.nPort ? uc.nPort : (uc.nScheme == INTERNET_SCHEME_HTTPS ? 443 : 80);
2846 {
2847 free( connect->hostname );
2851 {
2853 goto end;
2854 }
2855
2857 request->netconn = NULL;
2861 }
2862 else free( hostname );
2863
2865
2866 free( request->path );
2867 request->path = NULL;
2868 if (uc.dwUrlPathLength)
2869 {
2871 if (!(request->path = malloc( (len + 1) * sizeof(WCHAR) ))) goto end;
2872 memcpy( request->path, uc.lpszUrlPath, (len + 1) * sizeof(WCHAR) );
2873 request->path[len] = 0;
2874 }
2875 else request->path = wcsdup( L"/" );
2876 }
2877
2879 {
2880 free( request->verb );
2881 request->verb = wcsdup( L"GET" );
2883 request->optional_len = 0;
2884 }
2885
2886end:
2887 free( location );
2888 return ret;
2889}
2890
2892{
2893 static const WCHAR passportW[] = {'P','a','s','s','p','o','r','t','1','.','4'};
2894 WCHAR buf[1024];
2896
2897 if (!(request->connect->session->passport_flags & WINHTTP_ENABLE_PASSPORT_AUTH) ||
2899
2900 if (!wcsnicmp( buf, passportW, ARRAY_SIZE(passportW) ) &&
2901 (buf[ARRAY_SIZE(passportW)] == ' ' || !buf[ARRAY_SIZE(passportW)])) return TRUE;
2902
2903 return FALSE;
2904}
2905
2907{
2909 int i, len = lstrlenW( request->raw_headers );
2911
2912 if ((ret = process_header( request, L"Status", L"401", flags, FALSE ))) return ret;
2913
2914 for (i = 0; i < len; i++)
2915 {
2916 if (i <= len - 3 && p[i] == '3' && p[i + 1] == '0' && p[i + 2] == '2')
2917 {
2918 p[i] = '4';
2919 p[i + 2] = '1';
2920 break;
2921 }
2922 }
2923 return ERROR_SUCCESS;
2924}
2925
2926static void task_receive_response( void *ctx, BOOL abort );
2927
2929{
2930 struct receive_response *r;
2931 DWORD ret;
2932
2933 if (!(r = malloc( sizeof(*r) ))) return ERROR_OUTOFMEMORY;
2934 if ((ret = queue_task( &request->queue, task_receive_response, &r->task_hdr, &request->hdr )))
2935 free( r );
2936 return ret;
2937}
2938
2940{
2941 BOOL async_mode = request->connect->hdr.flags & WINHTTP_FLAG_ASYNC;
2943
2944 TRACE( "request state %d.\n", request->state );
2945
2946 switch (request->state)
2947 {
2949 TRACE( "Sending request.\n" );
2950 if ((ret = send_request( request, NULL, 0, request->optional, request->optional_len, 0, 0, FALSE ))) goto done;
2952 break;
2953
2955 if (!async_mode)
2956 {
2958 goto done;
2959 }
2963
2964
2967 if (async_mode)
2968 {
2971 }
2972 /* fallthrough */
2977 break;
2978
2981 break;
2982
2985 break;
2986
2987 default:
2989 goto done;
2990 }
2991
2994 if ((ret = request->read_reply_status)) goto done;
2995
2996 size = sizeof(DWORD);
2998 if ((ret = query_headers( request, query, NULL, &status, &size, NULL ))) goto done;
2999
3001
3002 if (!(request->hdr.disable_flags & WINHTTP_DISABLE_COOKIES)) record_cookies( request );
3003
3005 {
3007 goto done;
3008 }
3010 {
3011 if (request->hdr.disable_flags & WINHTTP_DISABLE_REDIRECTS ||
3012 request->hdr.redirect_policy == WINHTTP_OPTION_REDIRECT_POLICY_NEVER) goto done;
3013
3015 {
3017 goto done;
3018 }
3019
3020 if ((ret = handle_redirect( request, status ))) goto done;
3021 }
3023 {
3024 if (request->hdr.disable_flags & WINHTTP_DISABLE_AUTHENTICATION) goto done;
3025
3026 if (handle_authorization( request, status )) goto done;
3027 }
3028 else goto done;
3029
3031 return async_mode ? queue_receive_response( request ) : receive_response( request );
3032
3033done:
3034 if (!ret)
3035 {
3038 }
3039 if (async_mode)
3040 {
3042 else
3043 {
3045 result.dwResult = API_RECEIVE_RESPONSE;
3046 result.dwError = ret;
3048 }
3049 return ERROR_SUCCESS;
3050 }
3051 return ret;
3052}
3053
3055{
3056 struct receive_response *r = ctx;
3057 struct request *request = (struct request *)r->task_hdr.obj;
3058
3059 if (abort) return;
3060
3061 TRACE("running %p\n", ctx);
3063}
3064
3065/***********************************************************************
3066 * WinHttpReceiveResponse (winhttp.@)
3067 */
3069{
3070 DWORD ret;
3071 struct request *request;
3072
3073 TRACE("%p, %p\n", hrequest, reserved);
3074
3075 if (!(request = (struct request *)grab_object( hrequest )))
3076 {
3078 return FALSE;
3079 }
3081 {
3084 return FALSE;
3085 }
3086
3088
3090 SetLastError( ret );
3091 return !ret;
3092}
3093
3095{
3096 DWORD count;
3097
3100
3101 return count;
3102}
3103
3104static BOOL skip_async_queue( struct request *request, BOOL *wont_block, DWORD to_read )
3105{
3106 if (!request->read_chunked)
3108 *wont_block = end_of_read_data( request ) || query_data_ready( request ) >= to_read;
3109 return request->hdr.recursion_count < 3 && *wont_block;
3110}
3111
3113{
3115
3116 if (end_of_read_data( request )) goto done;
3117
3118 if (!(count = query_data_ready( request )))
3119 {
3120 if ((ret = refill_buffer( request, async ))) goto done;
3122 }
3123
3124done:
3125 TRACE( "%lu bytes available\n", count );
3126 if (async)
3127 {
3129 else
3130 {
3133 result.dwError = ret;
3135 }
3136 }
3137
3138 if (!ret && available) *available = count;
3139 return ret;
3140}
3141
3143{
3144 struct query_data *q = ctx;
3145 struct request *request = (struct request *)q->task_hdr.obj;
3146
3147 if (abort) return;
3148
3149 TRACE("running %p\n", ctx);
3150 query_data_available( request, q->available, TRUE );
3151}
3152
3153/***********************************************************************
3154 * WinHttpQueryDataAvailable (winhttp.@)
3155 */
3157{
3158 DWORD ret;
3159 struct request *request;
3160 BOOL async;
3161 BOOL wont_block = FALSE;
3162
3163 TRACE("%p, %p\n", hrequest, available);
3164
3165 if (!(request = (struct request *)grab_object( hrequest )))
3166 {
3168 return FALSE;
3169 }
3171 {
3174 return FALSE;
3175 }
3176
3177 if (!(async = request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) || skip_async_queue( request, &wont_block, 1 ))
3178 {
3180 }
3181 else if (wont_block)
3182 {
3183 /* Data available but recursion limit reached, only queue callback. */
3184 struct send_callback *s;
3185
3186 if (!(s = malloc( sizeof(*s) )))
3187 {
3190 return FALSE;
3191 }
3192
3193 if (!(ret = query_data_available( request, &s->count, FALSE )))
3194 {
3195 if (available) *available = s->count;
3197 s->info = &s->count;
3198 s->buflen = sizeof(s->count);
3199 }
3200 else
3201 {
3202 s->result.dwResult = API_QUERY_DATA_AVAILABLE;
3203 s->result.dwError = ret;
3205 s->info = &s->result;
3206 s->buflen = sizeof(s->result);
3207 }
3208
3209 if ((ret = queue_task( &request->queue, task_send_callback, &s->task_hdr, &request->hdr )))
3210 free( s );
3211 else
3213 }
3214 else
3215 {
3216 struct query_data *q;
3217
3218 if (!(q = malloc( sizeof(*q) )))
3219 {
3222 return FALSE;
3223 }
3224
3225 q->available = available;
3226
3227 if ((ret = queue_task( &request->queue, task_query_data_available, &q->task_hdr, &request->hdr )))
3228 free( q );
3229 else
3231 }
3232
3234 SetLastError( ret );
3235 return !ret || ret == ERROR_IO_PENDING;
3236}
3237
3238static void task_read_data( void *ctx, BOOL abort )
3239{
3240 struct read_data *r = ctx;
3241 struct request *request = (struct request *)r->task_hdr.obj;
3242
3243 if (abort) return;
3244
3245 TRACE("running %p\n", ctx);
3246 read_data( request, r->buffer, r->to_read, r->read, TRUE );
3247}
3248
3249/***********************************************************************
3250 * WinHttpReadData (winhttp.@)
3251 */
3253{
3254 DWORD ret;
3255 struct request *request;
3256 BOOL async;
3257 BOOL wont_block = FALSE;
3258
3259 TRACE( "%p, %p, %lu, %p\n", hrequest, buffer, to_read, read );
3260
3261 if (!(request = (struct request *)grab_object( hrequest )))
3262 {
3264 return FALSE;
3265 }
3267 {
3270 return FALSE;
3271 }
3272
3273 if (!(async = request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) || skip_async_queue( request, &wont_block, to_read ))
3274 {
3275 ret = read_data( request, buffer, to_read, read, async );
3276 }
3277 else if (wont_block)
3278 {
3279 /* Data available but recursion limit reached, only queue callback. */
3280 struct send_callback *s;
3281
3282 if (!(s = malloc( sizeof(*s) )))
3283 {
3286 return FALSE;
3287 }
3288
3289 if (!(ret = read_data( request, buffer, to_read, &s->count, FALSE )))
3290 {
3291 if (read) *read = s->count;
3293 s->info = buffer;
3294 s->buflen = s->count;
3295 }
3296 else
3297 {
3298 s->result.dwResult = API_READ_DATA;
3299 s->result.dwError = ret;
3301 s->info = &s->result;
3302 s->buflen = sizeof(s->result);
3303 }
3304
3305 if ((ret = queue_task( &request->queue, task_send_callback, &s->task_hdr, &request->hdr )))
3306 free( s );
3307 else
3309 }
3310 else
3311 {
3312 struct read_data *r;
3313
3314 if (!(r = malloc( sizeof(*r) )))
3315 {
3318 return FALSE;
3319 }
3320 r->buffer = buffer;
3321 r->to_read = to_read;
3322 r->read = read;
3323
3324 if ((ret = queue_task( &request->queue, task_read_data, &r->task_hdr, &request->hdr )))
3325 free( r );
3326 else
3328 }
3329
3331 SetLastError( ret );
3332 return !ret || ret == ERROR_IO_PENDING;
3333}
3334
3335static DWORD write_data( struct request *request, const void *buffer, DWORD to_write, DWORD *written, BOOL async )
3336{
3337 DWORD ret;
3338 int num_bytes;
3339
3340 ret = netconn_send( request->netconn, buffer, to_write, &num_bytes, NULL );
3341
3342 if (async)
3343 {
3344 if (!ret) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE, &num_bytes, sizeof(num_bytes) );
3345 else
3346 {
3348 result.dwResult = API_WRITE_DATA;
3349 result.dwError = ret;
3351 }
3352 }
3353 if (!ret && written) *written = num_bytes;
3354 return ret;
3355}
3356
3357static void task_write_data( void *ctx, BOOL abort )
3358{
3359 struct write_data *w = ctx;
3360 struct request *request = (struct request *)w->task_hdr.obj;
3361
3362 if (abort) return;
3363
3364 TRACE("running %p\n", ctx);
3365 write_data( request, w->buffer, w->to_write, w->written, TRUE );
3366}
3367
3368/***********************************************************************
3369 * WinHttpWriteData (winhttp.@)
3370 */
3371BOOL WINAPI WinHttpWriteData( HINTERNET hrequest, const void *buffer, DWORD to_write, DWORD *written )
3372{
3373 DWORD ret;
3374 struct request *request;
3375
3376 TRACE( "%p, %p, %lu, %p\n", hrequest, buffer, to_write, written );
3377
3378 if (!(request = (struct request *)grab_object( hrequest )))
3379 {
3381 return FALSE;
3382 }
3384 {
3387 return FALSE;
3388 }
3389
3390 if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC)
3391 {
3392 struct write_data *w;
3393
3394 if (!(w = malloc( sizeof(*w) )))
3395 {
3398 return FALSE;
3399 }
3400 w->buffer = buffer;
3401 w->to_write = to_write;
3402 w->written = written;
3403
3404 if ((ret = queue_task( &request->queue, task_write_data, &w->task_hdr, &request->hdr )))
3405 free( w );
3406 }
3408
3410 SetLastError( ret );
3411 return !ret;
3412}
3413
3415{
3416 struct socket *socket = (struct socket *)hdr;
3417 BOOL pending_tasks;
3418
3419 pending_tasks = cancel_queue( &socket->send_q );
3420 pending_tasks = cancel_queue( &socket->recv_q ) || pending_tasks;
3421
3422 if (pending_tasks)
3424}
3425
3427{
3428 switch (option)
3429 {
3432 return FALSE;
3433 }
3434
3435 FIXME( "unimplemented option %lu\n", option );
3437 return FALSE;
3438}
3439
3440static void socket_destroy( struct object_header *hdr )
3441{
3442 struct socket *socket = (struct socket *)hdr;
3443
3444 TRACE("%p\n", socket);
3445
3448
3452 free( socket );
3453}
3454
3456{
3457 struct socket *socket = (struct socket *)hdr;
3458
3459 switch (option)
3460 {
3462 {
3464
3465 if (buflen != sizeof(DWORD) || (interval = *(DWORD *)buffer) < 15000)
3466 {
3467 WARN( "Invalid parameters for WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL.\n" );
3469 return FALSE;
3470 }
3474 TRACE( "WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL %lu.\n", interval);
3475 return TRUE;
3476 }
3477 }
3478
3479 FIXME( "unimplemented option %lu\n", option );
3481 return FALSE;
3482}
3483
3484static const struct object_vtbl socket_vtbl =
3485{
3490};
3491
3493{
3494 struct socket *socket;
3495 struct request *request;
3496 HINTERNET hsocket = NULL;
3497
3498 TRACE( "%p, %Ix\n", hrequest, context );
3499
3500 if (!(request = (struct request *)grab_object( hrequest )))
3501 {
3503 return NULL;
3504 }
3506 {
3509 return NULL;
3510 }
3511 if (!(socket = calloc( 1, sizeof(*socket) )))
3512 {
3514 return NULL;
3515 }
3517 socket->hdr.vtbl = &socket_vtbl;
3518 socket->hdr.refs = 1;
3519 socket->hdr.callback = request->hdr.callback;
3520 socket->hdr.notify_mask = request->hdr.notify_mask;
3521 socket->hdr.context = context;
3522 socket->hdr.flags = request->connect->hdr.flags & WINHTTP_FLAG_ASYNC;
3523 socket->keepalive_interval = 30000;
3525 if (request->read_size)
3526 {
3528 {
3529 ERR( "No memory.\n" );
3530 free( socket );
3532 return NULL;
3533 }
3537 }
3543
3545
3546 if ((hsocket = alloc_handle( &socket->hdr )))
3547 {
3548 send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED, &hsocket, sizeof(hsocket) );
3549 }
3550
3553 TRACE("returning %p\n", hsocket);
3554 if (hsocket) SetLastError( ERROR_SUCCESS );
3555 return hsocket;
3556}
3557
3558static DWORD send_bytes( struct socket *socket, char *bytes, int len, int *sent, WSAOVERLAPPED *ovr )
3559{
3560 int count;
3561 DWORD err;
3562 err = netconn_send( socket->netconn, bytes, len, &count, ovr );
3563 if (sent) *sent = count;
3564 if (err) return err;
3565 return (count == len || (ovr && count)) ? ERROR_SUCCESS : ERROR_INTERNAL_ERROR;
3566}
3567
3568#define FIN_BIT (1 << 7)
3569#define MASK_BIT (1 << 7)
3570#define RESERVED_BIT (7 << 4)
3571#define CONTROL_BIT (1 << 3)
3572
3573static DWORD send_frame( struct socket *socket, enum socket_opcode opcode, USHORT status, const char *buf,
3574 DWORD buflen, BOOL final, WSAOVERLAPPED *ovr )
3575{
3576 DWORD i, offset = 2, len = buflen, buffer_size, ret = 0;
3577 int sent_size;
3578 char hdr[14];
3579 char *ptr;
3580
3581 TRACE( "sending %02x frame, len %lu\n", opcode, len );
3582
3583 if (opcode == SOCKET_OPCODE_CLOSE) len += sizeof(status);
3584
3585 hdr[0] = final ? (char)FIN_BIT : 0;
3586 hdr[0] |= opcode;
3587 hdr[1] = (char)MASK_BIT;
3588 if (len < 126) hdr[1] |= len;
3589 else if (len < 65536)
3590 {
3591 hdr[1] |= 126;
3592 hdr[2] = len >> 8;
3593 hdr[3] = len & 0xff;
3594 offset += 2;
3595 }
3596 else
3597 {
3598 hdr[1] |= 127;
3599 hdr[2] = hdr[3] = hdr[4] = hdr[5] = 0;
3600 hdr[6] = len >> 24;
3601 hdr[7] = (len >> 16) & 0xff;
3602 hdr[8] = (len >> 8) & 0xff;
3603 hdr[9] = len & 0xff;
3604 offset += 8;
3605 }
3606
3607 buffer_size = len + offset + 4;
3608 assert( buffer_size - len < socket->send_buffer_size );
3610 {
3612 void *new;
3613
3615 if (!(new = realloc( socket->send_frame_buffer, new_size )))
3616 {
3617 ERR( "out of memory, buffer_size %lu\n", buffer_size);
3618 return ERROR_OUTOFMEMORY;
3619 }
3622 }
3624
3625 memcpy(ptr, hdr, offset);
3626 ptr += offset;
3627
3628 RtlGenRandom( socket->mask, 4 );
3629 memcpy( ptr, socket->mask, 4 );
3630 ptr += 4;
3631 socket->mask_index = 0;
3632
3633 if (opcode == SOCKET_OPCODE_CLOSE) /* prepend status code */
3634 {
3635 *ptr++ = (status >> 8) ^ socket->mask[socket->mask_index++ % 4];
3636 *ptr++ = (status & 0xff) ^ socket->mask[socket->mask_index++ % 4];
3637 }
3638
3640 socket->send_remaining_size = offset + buflen;
3643 {
3644 len = min( buflen, socket->send_buffer_size - offset );
3645 for (i = 0; i < len; ++i)
3646 {
3648 ^ socket->mask[socket->mask_index++ % 4];
3649 }
3650
3651 sent_size = 0;
3652 ret = send_bytes( socket, socket->send_frame_buffer, offset, &sent_size, ovr );
3653 socket->send_remaining_size -= sent_size;
3654 if (ret)
3655 {
3656 if (ovr && ret == WSA_IO_PENDING)
3657 {
3658 memmove( socket->send_frame_buffer, socket->send_frame_buffer + sent_size, offset - sent_size );
3660 }
3661 return ret;
3662 }
3663 assert( sent_size == offset );
3664 offset = 0;
3665 buflen -= len;
3666 }
3667 return ERROR_SUCCESS;
3668}
3669
3670static DWORD complete_send_frame( struct socket *socket, WSAOVERLAPPED *ovr, const char *buf )
3671{
3672 DWORD ret, len, i;
3673
3675 return WSAGetLastError();
3676
3678 {
3680 if (ret) return ret;
3681 }
3682
3685
3687 {
3689 for (i = 0; i < len; ++i)
3690 {
3692 ^ socket->mask[socket->mask_index++ % 4];
3693 }
3695 if (ret) return ret;
3697 }
3698 return ERROR_SUCCESS;
3699}
3700
3701static void send_io_complete( struct object_header *hdr )
3702{
3703 LONG count = InterlockedDecrement( &hdr->pending_sends );
3704 assert( count >= 0 );
3705}
3706
3707/* returns FALSE if sending callback should be omitted. */
3708static void receive_io_complete( struct socket *socket )
3709{
3710 LONG count = InterlockedDecrement( &socket->hdr.pending_receives );
3711 assert( count >= 0 );
3712}
3713
3715{
3717}
3718
3720{
3722}
3723
3725{
3726 switch (current_fragment)
3727 {
3739 }
3740 assert( 0 );
3741 return FALSE;
3742}
3743
3745{
3746 switch (type)
3747 {
3750 {
3753 }
3754 return SOCKET_OPCODE_TEXT;
3755
3758 {
3761 }
3762 return SOCKET_OPCODE_BINARY;
3763
3766 {
3768 return SOCKET_OPCODE_TEXT;
3769 }
3771
3774 {
3776 return SOCKET_OPCODE_BINARY;
3777 }
3779
3781 return SOCKET_OPCODE_CLOSE;
3782
3783 default:
3784 FIXME("buffer type %u not supported\n", type);
3785 return SOCKET_OPCODE_INVALID;
3786 }
3787}
3788
3790{
3791 if (!ret)
3792 {
3794 status.dwBytesTransferred = len;
3795 status.eBufferType = type;
3797 }
3798 else
3799 {
3801 result.AsyncResult.dwResult = API_WRITE_DATA;
3802 result.AsyncResult.dwError = ret;
3805 }
3806}
3807
3809 WSAOVERLAPPED *ovr )
3810{
3811 enum socket_opcode opcode = map_buffer_type( socket, type );
3814
3815 return send_frame( socket, opcode, 0, buf, len, final, ovr );
3816}
3817
3818static void task_socket_send( void *ctx, BOOL abort )
3819{
3820 struct socket_send *s = ctx;
3821 struct socket *socket = (struct socket *)s->task_hdr.obj;
3822 DWORD ret;
3823
3824 if (abort) return;
3825
3826 TRACE("running %p\n", ctx);
3827
3828 if (s->complete_async) ret = complete_send_frame( socket, &s->ovr, s->buf );
3829 else ret = socket_send( socket, s->type, s->buf, s->len, NULL );
3830
3833 socket_send_complete( socket, ret, s->type, s->len );
3834}
3835
3837{
3838 struct socket *socket;
3839 DWORD ret = 0;
3840
3841 TRACE( "%p, %u, %p, %lu\n", hsocket, type, buf, len );
3842
3843 if (len && !buf) return ERROR_INVALID_PARAMETER;
3844
3845 if (!(socket = (struct socket *)grab_object( hsocket ))) return ERROR_INVALID_HANDLE;
3847 {
3850 }
3851 if (!socket_can_send( socket ))
3852 {
3855 }
3856
3857 if (socket->hdr.flags & WINHTTP_FLAG_ASYNC)
3858 {
3859 BOOL async_send, complete_async = FALSE;
3860 struct socket_send *s;
3861
3863 {
3864 WARN( "Previous send is still queued.\n" );
3867 }
3869 {
3870 WARN( "Invalid buffer type %u, sending_fragment_type %u.\n", type, socket->sending_fragment_type );
3874 }
3875
3876 if (!(s = malloc( sizeof(*s) )))
3877 {
3880 return ERROR_OUTOFMEMORY;
3881 }
3882
3884 async_send = InterlockedIncrement( &socket->hdr.pending_sends ) > 1 || socket->hdr.recursion_count >= 3;
3885 if (!async_send)
3886 {
3887 memset( &s->ovr, 0, sizeof(s->ovr) );
3888 if ((ret = socket_send( socket, type, buf, len, &s->ovr )) == WSA_IO_PENDING)
3889 {
3890 async_send = TRUE;
3892 }
3893 }
3894
3895 if (async_send)
3896 {
3897 s->complete_async = complete_async;
3898 TRACE("queueing, complete_async %#x.\n", complete_async);
3899 s->type = type;
3900 s->buf = buf;
3901 s->len = len;
3902
3903 if ((ret = queue_task( &socket->send_q, task_socket_send, &s->task_hdr, &socket->hdr )))
3904 free( s );
3905 }
3906 if (!async_send || ret)
3907 {
3908 InterlockedDecrement( &socket->hdr.pending_sends );
3910 }
3912 if (!async_send)
3913 {
3914 TRACE("sent sync.\n");
3915 free( s );
3918 }
3919 }
3920 else
3921 {
3923 {
3925 }
3926 else
3927 {
3928 WARN( "Invalid buffer type %u, sending_fragment_type %u.\n", type, socket->sending_fragment_type );
3930 }
3931 }
3932
3934 return ret;
3935}
3936
3937static DWORD receive_bytes( struct socket *socket, char *buf, DWORD len, DWORD *ret_len, BOOL read_full_buffer )
3938{
3939 DWORD err, size = 0, needed = len;
3940 char *ptr = buf;
3941 int received;
3942
3944 {
3945 size = min( needed, socket->bytes_in_read_buffer );
3949 needed -= size;
3950 ptr += size;
3951 }
3952 while (size != len)
3953 {
3954 if ((err = netconn_recv( socket->netconn, ptr, needed, 0, &received ))) return err;
3955 if (!received) break;
3956 size += received;
3957 if (!read_full_buffer) break;
3958 needed -= received;
3959 ptr += received;
3960 }
3961 *ret_len = size;
3962 if (size != len && (read_full_buffer || !size)) return ERROR_WINHTTP_INVALID_SERVER_RESPONSE;
3963 return ERROR_SUCCESS;
3964}
3965
3967{
3968 switch (opcode)
3969 {
3971 case SOCKET_OPCODE_TEXT:
3974 case SOCKET_OPCODE_PING:
3975 case SOCKET_OPCODE_PONG:
3976 return TRUE;
3977 default:
3978 FIXME( "opcode %02x not handled\n", opcode );
3979 return FALSE;
3980 }
3981}
3982
3983static DWORD receive_frame( struct socket *socket, DWORD *ret_len, enum socket_opcode *opcode, BOOL *final )
3984{
3985 DWORD ret, len, count;
3986 char hdr[2];
3987
3988 if ((ret = receive_bytes( socket, hdr, sizeof(hdr), &count, TRUE ))) return ret;
3989 if ((hdr[0] & RESERVED_BIT) || (hdr[1] & MASK_BIT) || !is_supported_opcode( hdr[0] & 0xf ))
3990 {
3992 }
3993 *opcode = hdr[0] & 0xf;
3994 *final = hdr[0] & FIN_BIT;
3995 TRACE("received %02x frame, final %#x\n", *opcode, *final);
3996
3997 len = hdr[1] & ~MASK_BIT;
3998 if (len == 126)
3999 {
4000 USHORT len16;
4001 if ((ret = receive_bytes( socket, (char *)&len16, sizeof(len16), &count, TRUE ))) return ret;
4002 len = RtlUshortByteSwap( len16 );
4003 }
4004 else if (len == 127)
4005 {
4006 ULONGLONG len64;
4007 if ((ret = receive_bytes( socket, (char *)&len64, sizeof(len64), &count, TRUE ))) return ret;
4008 if ((len64 = RtlUlonglongByteSwap( len64 )) > ~0u) return ERROR_NOT_SUPPORTED;
4009 len = len64;
4010 }
4011
4012 *ret_len = len;
4013 return ERROR_SUCCESS;
4014}
4015
4017{
4018 struct socket_send *s = ctx;
4019 struct socket *socket = (struct socket *)s->task_hdr.obj;
4020
4021 if (abort) return;
4022
4023 TRACE("running %p\n", ctx);
4024
4025 if (s->complete_async) complete_send_frame( socket, &s->ovr, NULL );
4027
4029}
4030
4032{
4033 if (socket->hdr.flags & WINHTTP_FLAG_ASYNC)
4034 {
4035 BOOL async_send, complete_async = FALSE;
4036 struct socket_send *s;
4037 DWORD ret = 0;
4038
4039 if (!(s = malloc( sizeof(*s) ))) return ERROR_OUTOFMEMORY;
4040
4042 async_send = InterlockedIncrement( &socket->hdr.pending_sends ) > 1;
4043 if (!async_send)
4044 {
4045 memset( &s->ovr, 0, sizeof(s->ovr) );
4046 if ((ret = send_frame( socket, SOCKET_OPCODE_PONG, 0, NULL, 0, TRUE, &s->ovr )) == WSA_IO_PENDING)
4047 {
4048 async_send = TRUE;
4050 }
4051 }
4052
4053 if (async_send)
4054 {
4055 s->complete_async = complete_async;
4056 if ((ret = queue_task( &socket->send_q, task_socket_send_pong, &s->task_hdr, &socket->hdr )))
4057 {
4058 InterlockedDecrement( &socket->hdr.pending_sends );
4059 free( s );
4060 }
4061 }
4062 else
4063 {
4064 InterlockedDecrement( &socket->hdr.pending_sends );
4065 free( s );
4066 }
4068 return ret;
4069 }
4070 return send_frame( socket, SOCKET_OPCODE_PONG, 0, NULL, 0, TRUE, NULL );
4071}
4072
4074{
4075 DWORD ret, count;
4076
4077 while (socket->read_size)
4078 {
4079 char buf[1024];
4080 if ((ret = receive_bytes( socket, buf, min(socket->read_size, sizeof(buf)), &count, TRUE ))) return ret;
4082 }
4083 return ERROR_SUCCESS;
4084}
4085
4087{
4088 DWORD reason_len, ret;
4089
4091 if ((len && (len < sizeof(socket->status) || len > sizeof(socket->status) + sizeof(socket->reason))))
4093
4095
4096 reason_len = len - sizeof(socket->status);
4097 if ((ret = receive_bytes( socket, (char *)&socket->status, sizeof(socket->status), &len, TRUE )))
4101 = receive_bytes( socket, socket->reason, reason_len, &socket->reason_len, TRUE ));
4102}
4103
4105{
4106 DWORD ret;
4107
4108 TRACE( "opcode %u.\n", socket->opcode );
4109
4110 switch (socket->opcode)
4111 {
4112 case SOCKET_OPCODE_PING:
4113 return socket_send_pong( socket );
4114
4115 case SOCKET_OPCODE_PONG:
4116 return socket_drain( socket );
4117
4120 WARN( "SOCKET_OPCODE_CLOSE received, socket->state %u.\n", socket->state );
4122 {
4123 FIXME( "Close frame already received.\n" );
4125 }
4126
4128 socket->read_size = 0;
4129 return ret;
4130
4131 default:
4132 ERR("unhandled control opcode %02x\n", socket->opcode);
4134 }
4135
4136 return ERROR_SUCCESS;
4137}
4138
4140{
4142
4143 switch (opcode)
4144 {
4145 case SOCKET_OPCODE_TEXT:
4146 if (frag_type && frag_type != SOCKET_FRAGMENT_UTF8)
4147 FIXME( "Received SOCKET_OPCODE_TEXT with prev fragment %u.\n", frag_type );
4148 if (fragment)
4149 {
4152 }
4155
4157 if (frag_type && frag_type != SOCKET_FRAGMENT_BINARY)
4158 FIXME( "Received SOCKET_OPCODE_BINARY with prev fragment %u.\n", frag_type );
4159 if (fragment)
4160 {
4163 }
4166
4168 if (!frag_type)
4169 {
4170 FIXME( "Received SOCKET_OPCODE_CONTINUE without starting fragment.\n" );
4171 return ~0u;
4172 }
4173 if (fragment)
4174 {
4177 }
4181
4184
4185 default:
4186 FIXME("opcode %02x not handled\n", opcode);
4187 return ~0u;
4188 }
4189}
4190
4193{
4196
4197 if (!socket->read_size)
4198 {
4199 for (;;)
4200 {
4201 if (!(ret = receive_frame( socket, &socket->read_size, &socket->opcode, &final )))
4202 {
4204 || socket->opcode == SOCKET_OPCODE_CLOSE) break;
4205 }
4206 else if (ret == WSAETIMEDOUT) ret = socket_send_pong( socket );
4207 if (ret) break;
4208 }
4209 }
4210 if (!ret)
4211 {
4212 socket->last_receive_final = final;
4214 }
4215 if (!ret)
4216 {
4217 if (count < socket->read_size)
4218 WARN("Short read.\n");
4219
4221 *ret_len = count;
4222 *ret_type = map_opcode( socket, socket->opcode, !final || socket->read_size != 0 );
4223 TRACE( "len %lu, *ret_len %lu, *ret_type %u.\n", len, *ret_len, *ret_type );
4224 if (*ret_type == ~0u)
4225 {
4226 FIXME( "Unexpected opcode %u.\n", socket->opcode );
4227 socket->read_size = 0;
4229 }
4230 }
4231 return ret;
4232}
4233
4235{
4236 if (!ret)
4237 {
4239 status.dwBytesTransferred = len;
4240 status.eBufferType = type;
4242 }
4243 else
4244 {
4246 result.AsyncResult.dwResult = 0;
4247 result.AsyncResult.dwError = ret;
4250 }
4251}
4252
4253static void task_socket_receive( void *ctx, BOOL abort )
4254{
4255 struct socket_receive *r = ctx;
4256 struct socket *socket = (struct socket *)r->task_hdr.obj;
4257 DWORD ret, count;
4259
4260 if (abort)
4261 {
4263 return;
4264 }
4265
4266 TRACE("running %p\n", ctx);
4267 ret = socket_receive( socket, r->buf, r->len, &count, &type );
4269 if (task_needs_completion( &r->task_hdr ))
4271}
4272
4275{
4276 struct socket *socket;
4277 DWORD ret;
4278
4279 TRACE( "%p, %p, %lu, %p, %p\n", hsocket, buf, len, ret_len, ret_type );
4280
4281 if (!buf || !len) return ERROR_INVALID_PARAMETER;
4282
4283 if (!(socket = (struct socket *)grab_object( hsocket ))) return ERROR_INVALID_HANDLE;
4285 {
4288 }
4289 if (!socket_can_receive( socket ))
4290 {
4293 }
4294
4295 if (socket->hdr.flags & WINHTTP_FLAG_ASYNC)
4296 {
4297 struct socket_receive *r;
4298
4299 if (InterlockedIncrement( &socket->hdr.pending_receives ) > 1)
4300 {
4301 InterlockedDecrement( &socket->hdr.pending_receives );
4302 WARN( "Attempt to queue receive while another is pending.\n" );
4305 }
4306
4307 if (!(r = malloc( sizeof(*r) )))
4308 {
4309 InterlockedDecrement( &socket->hdr.pending_receives );
4311 return ERROR_OUTOFMEMORY;
4312 }
4313 r->buf = buf;
4314 r->len = len;
4315
4316 if ((ret = queue_task( &socket->recv_q, task_socket_receive, &r->task_hdr, &socket->hdr )))
4317 {
4318 InterlockedDecrement( &socket->hdr.pending_receives );
4319 free( r );
4320 }
4321 }
4322 else ret = socket_receive( socket, buf, len, ret_len, ret_type );
4323
4325 return ret;
4326}
4327
4329{
4331 else
4332 {
4334 result.AsyncResult.dwResult = API_WRITE_DATA;
4335 result.AsyncResult.dwError = ret;
4338 }
4339}
4340
4341static void task_socket_shutdown( void *ctx, BOOL abort )
4342{
4343 struct socket_shutdown *s = ctx;
4344 struct socket *socket = (struct socket *)s->task_hdr.obj;
4345 DWORD ret;
4346
4347 if (abort) return;
4348
4349 TRACE("running %p\n", ctx);
4350
4351 if (s->complete_async) ret = complete_send_frame( socket, &s->ovr, s->reason );
4352 else ret = send_frame( socket, SOCKET_OPCODE_CLOSE, s->status, s->reason, s->len, TRUE, NULL );
4353
4355 if (s->send_callback) socket_shutdown_complete( socket, ret );
4356}
4357
4360{
4361 DWORD ret;
4362
4364
4365 if (socket->hdr.flags & WINHTTP_FLAG_ASYNC)
4366 {
4367 BOOL async_send, complete_async = FALSE;
4368 struct socket_shutdown *s;
4369
4370 if (!(s = malloc( sizeof(*s) ))) return FALSE;
4371
4373 async_send = InterlockedIncrement( &socket->hdr.pending_sends ) > 1 || socket->hdr.recursion_count >= 3;
4374 if (!async_send)
4375 {
4376 memset( &s->ovr, 0, sizeof(s->ovr) );
4378 {
4379 async_send = TRUE;
4381 }
4382 }
4383
4384 if (async_send)
4385 {
4386 s->complete_async = complete_async;
4387 s->status = status;
4388 memcpy( s->reason, reason, len );
4389 s->len = len;
4390 s->send_callback = send_callback;
4391
4392 if ((ret = queue_task( &socket->send_q, task_socket_shutdown, &s->task_hdr, &socket->hdr )))
4393 {
4394 InterlockedDecrement( &socket->hdr.pending_sends );
4395 free( s );
4396 }
4397 }
4398 else InterlockedDecrement( &socket->hdr.pending_sends );
4400 if (!async_send)
4401 {
4402 free( s );
4403 if (send_callback)
4404 {
4407 }
4408 }
4409 }
4411
4412 return ret;
4413}
4414
4416{
4417 struct socket *socket;
4418 DWORD ret;
4419
4420 TRACE( "%p, %u, %p, %lu\n", hsocket, status, reason, len );
4421
4422 if ((len && !reason) || len > sizeof(socket->reason)) return ERROR_INVALID_PARAMETER;
4423
4424 if (!(socket = (struct socket *)grab_object( hsocket ))) return ERROR_INVALID_HANDLE;
4426 {
4429 }
4431 {
4434 }
4435
4438 return ret;
4439}
4440
4442{
4443 BOOL final = FALSE;
4444 DWORD ret, count;
4445
4447
4448 if ((ret = socket_drain( socket ))) return ret;
4449
4450 while (1)
4451 {
4452 if ((ret = receive_frame( socket, &count, &socket->opcode, &final ))) return ret;
4453 if (socket->opcode == SOCKET_OPCODE_CLOSE) break;
4454
4456 if ((ret = socket_drain( socket ))) return ret;
4457 }
4458 if (!final)
4459 FIXME( "Received close opcode without FIN bit.\n" );
4460
4462}
4463
4465{
4467 else
4468 {
4470 result.AsyncResult.dwResult = API_READ_DATA; /* FIXME */
4471 result.AsyncResult.dwError = ret;
4474 }
4475}
4476
4477static void task_socket_close( void *ctx, BOOL abort )
4478{
4479 struct socket_shutdown *s = ctx;
4480 struct socket *socket = (struct socket *)s->task_hdr.obj;
4481 DWORD ret;
4482
4483 if (abort)
4484 {
4486 return;
4487 }
4488
4489 TRACE("running %p\n", ctx);
4490
4491 ret = socket_close( socket );
4493 if (task_needs_completion( &s->task_hdr ))
4495}
4496
4498{
4499 enum socket_state prev_state;
4500 LONG pending_receives = 0;
4501 struct socket *socket;
4502 DWORD ret;
4503
4504 TRACE( "%p, %u, %p, %lu\n", hsocket, status, reason, len );
4505
4506 if ((len && !reason) || len > sizeof(socket->reason)) return ERROR_INVALID_PARAMETER;
4507
4508 if (!(socket = (struct socket *)grab_object( hsocket ))) return ERROR_INVALID_HANDLE;
4510 {
4513 }
4515 {
4518 }
4519
4520 prev_state = socket->state;
4522
4523 if (socket->hdr.flags & WINHTTP_FLAG_ASYNC)
4524 {
4525 pending_receives = InterlockedIncrement( &socket->hdr.pending_receives );
4527 }
4528
4530 goto done;
4531
4532 if (pending_receives == 1 && socket->close_frame_received)
4533 {
4534 if (socket->hdr.flags & WINHTTP_FLAG_ASYNC)
4536 goto done;
4537 }
4538
4539 if (socket->hdr.flags & WINHTTP_FLAG_ASYNC)
4540 {
4541 struct socket_shutdown *s;
4542
4543 if (!(s = calloc( 1, sizeof(*s) )))
4544 {
4546 goto done;
4547 }
4548 if ((ret = queue_task( &socket->recv_q, task_socket_close, &s->task_hdr, &socket->hdr )))
4549 {
4550 InterlockedDecrement( &socket->hdr.pending_receives );
4551 free( s );
4552 }
4553 }
4554 else ret = socket_close( socket );
4555
4556done:
4558 return ret;
4559}
4560
4562 DWORD *ret_len )
4563{
4564 struct socket *socket;
4565 DWORD ret;
4566
4567 TRACE( "%p, %p, %p, %lu, %p\n", hsocket, status, reason, len, ret_len );
4568
4569 if (!status || (len && !reason) || !ret_len) return ERROR_INVALID_PARAMETER;
4570
4571 if (!(socket = (struct socket *)grab_object( hsocket ))) return ERROR_INVALID_HANDLE;
4573 {
4576 }
4577
4579 {
4582 return ret;
4583 }
4584 *status = socket->status;
4587 else
4588 {
4591 }
4592
4594 return ret;
4595}
4596
4598{
4605
4607{
4608 IWinHttpRequest IWinHttpRequest_iface;
4621 char *buffer;
4636};
4637
4638static inline struct winhttp_request *impl_from_IWinHttpRequest( IWinHttpRequest *iface )
4639{
4641}
4642
4644 IWinHttpRequest *iface )
4645{
4647 return InterlockedIncrement( &request->refs );
4648}
4649
4650/* critical section must be held */
4652{
4653 if (request->state <= REQUEST_STATE_CANCELLED) return;
4654
4655 if (request->proc_running)
4656 {
4657 SetEvent( request->cancel );
4659
4661
4663 }
4665}
4666
4667/* critical section must be held */
4669{
4671 WinHttpCloseHandle( request->hrequest );
4672 WinHttpCloseHandle( request->hconnect );
4673 WinHttpCloseHandle( request->hsession );
4674 CloseHandle( request->done );
4675 CloseHandle( request->wait );
4676 CloseHandle( request->cancel );
4677 free( request->proxy.lpszProxy );
4678 free( request->proxy.lpszProxyBypass );
4679 free( request->buffer );
4680 free( request->verb );
4681 VariantClear( &request->data );
4682}
4683
4685 IWinHttpRequest *iface )
4686{
4689 if (!refs)
4690 {
4691 TRACE("destroying %p\n", request);
4692
4697 request->cs.DebugInfo->Spare[0] = 0;
4699 free( request );
4700 }
4701 return refs;
4702}
4703
4705 IWinHttpRequest *iface,
4706 REFIID riid,
4707 void **obj )
4708{
4710
4711 TRACE("%p, %s, %p\n", request, debugstr_guid(riid), obj );
4712
4713 if (IsEqualGUID( riid, &IID_IWinHttpRequest ) ||
4716 {
4717 *obj = iface;
4718 }
4719 else
4720 {
4721 FIXME("interface %s not implemented\n", debugstr_guid(riid));
4722 return E_NOINTERFACE;
4723 }
4724 IWinHttpRequest_AddRef( iface );
4725 return S_OK;
4726}
4727
4729 IWinHttpRequest *iface,
4730 UINT *count )
4731{
4733
4734 TRACE("%p, %p\n", request, count);
4735 *count = 1;
4736 return S_OK;
4737}
4738
4740{
4742 last_tid
4744
4747
4749{
4750 &IID_IWinHttpRequest
4751};
4752
4754{
4755 HRESULT hr;
4756
4757 if (!winhttp_typelib)
4758 {
4760
4761 hr = LoadRegTypeLib( &LIBID_WinHttp, 5, 1, LOCALE_SYSTEM_DEFAULT, &typelib );
4762 if (FAILED(hr))
4763 {
4764 ERR( "LoadRegTypeLib failed: %#lx\n", hr );
4765 return hr;
4766 }
4768 ITypeLib_Release( typelib );
4769 }
4770 if (!winhttp_typeinfo[tid])
4771 {
4773
4774 hr = ITypeLib_GetTypeInfoOfGuid( winhttp_typelib, winhttp_tid_id[tid], &typeinfo );
4775 if (FAILED(hr))
4776 {
4777 ERR( "GetTypeInfoOfGuid(%s) failed: %#lx\n", debugstr_guid(winhttp_tid_id[tid]), hr );
4778 return hr;
4779 }
4781 ITypeInfo_Release( typeinfo );
4782 }
4784 ITypeInfo_AddRef(winhttp_typeinfo[tid]);
4785 return S_OK;
4786}
4787
4789{
4790 unsigned i;
4791
4792 for (i = 0; i < ARRAY_SIZE(winhttp_typeinfo); i++)
4793 if (winhttp_typeinfo[i])
4794 ITypeInfo_Release(winhttp_typeinfo[i]);
4795
4796 if (winhttp_typelib)
4797 ITypeLib_Release(winhttp_typelib);
4798}
4799
4801 IWinHttpRequest *iface,
4802 UINT index,
4803 LCID lcid,
4804 ITypeInfo **info )
4805{
4807 TRACE( "%p, %u, %lu, %p\n", request, index, lcid, info );
4808
4810}
4811
4813 IWinHttpRequest *iface,
4814 REFIID riid,
4815 LPOLESTR *names,
4816 UINT count,
4817 LCID lcid,
4818 DISPID *dispid )
4819{
4822 HRESULT hr;
4823
4824 TRACE( "%p, %s, %p, %u, %lu, %p\n", request, debugstr_guid(riid), names, count, lcid, dispid );
4825
4826 if (!names || !count || !dispid) return E_INVALIDARG;
4827
4829 if (SUCCEEDED(hr))
4830 {
4831 hr = ITypeInfo_GetIDsOfNames( typeinfo, names, count, dispid );
4832 ITypeInfo_Release( typeinfo );
4833 }
4834 return hr;
4835}
4836
4838 IWinHttpRequest *iface,
4839 DISPID member,
4840 REFIID riid,
4841 LCID lcid,
4842 WORD flags,
4843 DISPPARAMS *params,
4844 VARIANT *result,
4845 EXCEPINFO *excep_info,
4846 UINT *arg_err )
4847{
4850 HRESULT hr;
4851
4852 TRACE( "%p, %ld, %s, %lu, %d, %p, %p, %p, %p\n", request, member, debugstr_guid(riid),
4853 lcid, flags, params, result, excep_info, arg_err );
4854
4856
4858 {
4859 VARIANT ret_value, option;
4860 UINT err_pos;
4861
4862 if (!result) result = &ret_value;
4863 if (!arg_err) arg_err = &err_pos;
4864
4865 VariantInit( &option );
4867
4868 if (!flags) return S_OK;
4869
4871 {
4872 hr = DispGetParam( params, 0, VT_I4, &option, arg_err );
4873 if (FAILED(hr)) return hr;
4874
4875 hr = IWinHttpRequest_put_Option( &request->IWinHttpRequest_iface, V_I4( &option ), params->rgvarg[0] );
4876 if (FAILED(hr))
4877 WARN( "put_Option(%ld) failed: %#lx\n", V_I4( &option ), hr );
4878 return hr;
4879 }
4881 {
4882 hr = DispGetParam( params, 0, VT_I4, &option, arg_err );
4883 if (FAILED(hr)) return hr;
4884
4885 hr = IWinHttpRequest_get_Option( &request->IWinHttpRequest_iface, V_I4( &option ), result );
4886 if (FAILED(hr))
4887 WARN( "get_Option(%ld) failed: %#lx\n", V_I4( &option ), hr );
4888 return hr;
4889 }
4890
4891 FIXME("unsupported flags %x\n", flags);
4892 return E_NOTIMPL;
4893 }
4894
4895 /* fallback to standard implementation */
4896
4898 if (SUCCEEDED(hr))
4899 {
4900 hr = ITypeInfo_Invoke( typeinfo, &request->IWinHttpRequest_iface, member, flags,
4901 params, result, excep_info, arg_err );
4902 ITypeInfo_Release( typeinfo );
4903 }
4904 return hr;
4905}
4906
4908 IWinHttpRequest *iface,
4909 HTTPREQUEST_PROXY_SETTING proxy_setting,
4911 VARIANT bypass_list )
4912{
4915
4916 TRACE( "%p, %lu, %s, %s\n", request, proxy_setting, debugstr_variant(&proxy_server),
4917 debugstr_variant(&bypass_list) );
4918
4920 switch (proxy_setting)
4921 {
4922 case HTTPREQUEST_PROXYSETTING_DEFAULT:
4923 request->proxy.dwAccessType = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
4924 free( request->proxy.lpszProxy );
4925 free( request->proxy.lpszProxyBypass );
4926 request->proxy.lpszProxy = NULL;
4927 request->proxy.lpszProxyBypass = NULL;
4928 break;
4929
4930 case HTTPREQUEST_PROXYSETTING_DIRECT:
4931 request->proxy.dwAccessType = WINHTTP_ACCESS_TYPE_NO_PROXY;
4932 free( request->proxy.lpszProxy );
4933 free( request->proxy.lpszProxyBypass );
4934 request->proxy.lpszProxy = NULL;
4935 request->proxy.lpszProxyBypass = NULL;
4936 break;
4937
4938 case HTTPREQUEST_PROXYSETTING_PROXY:
4939 request->proxy.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
4940 if (V_VT( &proxy_server ) == VT_BSTR)
4941 {
4942 free( request->proxy.lpszProxy );
4943 request->proxy.lpszProxy = wcsdup( V_BSTR( &proxy_server ) );
4944 }
4945 if (V_VT( &bypass_list ) == VT_BSTR)
4946 {
4947 free( request->proxy.lpszProxyBypass );
4948 request->proxy.lpszProxyBypass = wcsdup( V_BSTR( &bypass_list ) );
4949 }
4950 break;
4951
4952 default:
4954 break;
4955 }
4957 return HRESULT_FROM_WIN32( err );
4958}
4959
4961 IWinHttpRequest *iface,
4962 BSTR username,
4963 BSTR password,
4964 HTTPREQUEST_SETCREDENTIALS_FLAGS flags )
4965{
4967 DWORD target, scheme = WINHTTP_AUTH_SCHEME_BASIC; /* FIXME: query supported schemes */
4969
4970 TRACE( "%p, %s, %p, %#lx\n", request, debugstr_w(username), password, flags );
4971
4974 {
4976 goto done;
4977 }
4978 switch (flags)
4979 {
4980 case HTTPREQUEST_SETCREDENTIALS_FOR_SERVER:
4982 break;
4983 case HTTPREQUEST_SETCREDENTIALS_FOR_PROXY:
4985 break;
4986 default:
4988 goto done;
4989 }
4991 {
4992 err = GetLastError();
4993 }
4994done:
4996 return HRESULT_FROM_WIN32( err );
4997}
4998
5000{
5001 request->wait = CreateEventW( NULL, FALSE, FALSE, NULL );
5002 request->cancel = CreateEventW( NULL, FALSE, FALSE, NULL );
5003 request->done = CreateEventW( NULL, FALSE, FALSE, NULL );
5004 request->connect_timeout = 60000;
5005 request->send_timeout = 30000;
5006 request->receive_timeout = 30000;
5007 request->url_codepage = CP_UTF8;
5008 VariantInit( &request->data );
5010}
5011
5013{
5015 WinHttpCloseHandle( request->hrequest );
5016 request->hrequest = NULL;
5017 WinHttpCloseHandle( request->hconnect );
5018 request->hconnect = NULL;
5019 free( request->buffer );
5020 request->buffer = NULL;
5021 free( request->verb );
5022 request->verb = NULL;
5023 request->offset = 0;
5024 request->bytes_available = 0;
5025 request->bytes_read = 0;
5026 request->error = ERROR_SUCCESS;
5027 request->logon_policy = 0;
5028 request->disable_feature = 0;
5029 request->async = FALSE;
5030 request->connect_timeout = 60000;
5031 request->send_timeout = 30000;
5032 request->receive_timeout = 30000;
5033 request->url_codepage = CP_UTF8;
5034 free( request->proxy.lpszProxy );
5035 request->proxy.lpszProxy = NULL;
5036 free( request->proxy.lpszProxyBypass );
5037 request->proxy.lpszProxyBypass = NULL;
5038 VariantClear( &request->data );
5040}
5041
5043 IWinHttpRequest *iface,
5044 BSTR method,
5045 BSTR url,
5046 VARIANT async )
5047{
5048 static const WCHAR httpsW[] = {'h','t','t','p','s'};
5049 static const WCHAR *acceptW[] = {L"*/*", NULL};
5050 static const WCHAR user_agentW[] = L"Mozilla/4.0 (compatible; Win32; WinHttp.WinHttpRequest.5)";
5052 URL_COMPONENTS uc;
5053 WCHAR *hostname, *path = NULL, *verb = NULL;
5055
5056 TRACE("%p, %s, %s, %s\n", request, debugstr_w(method), debugstr_w(url),
5058
5059 if (!method || !url) return E_INVALIDARG;
5060
5061 memset( &uc, 0, sizeof(uc) );
5062 uc.dwStructSize = sizeof(uc);
5063 uc.dwSchemeLength = ~0u;
5064 uc.dwHostNameLength = ~0u;
5065 uc.dwUrlPathLength = ~0u;
5066 uc.dwExtraInfoLength = ~0u;
5067 if (!WinHttpCrackUrl( url, 0, 0, &uc )) return HRESULT_FROM_WIN32( GetLastError() );
5068
5071
5072 if (!(hostname = malloc( (uc.dwHostNameLength + 1) * sizeof(WCHAR) ))) goto error;
5073 memcpy( hostname, uc.lpszHostName, uc.dwHostNameLength * sizeof(WCHAR) );
5074 hostname[uc.dwHostNameLength] = 0;
5075
5076 if (!(path = malloc( (uc.dwUrlPathLength + uc.dwExtraInfoLength + 1) * sizeof(WCHAR) ))) goto error;
5077 memcpy( path, uc.lpszUrlPath, (uc.dwUrlPathLength + uc.dwExtraInfoLength) * sizeof(WCHAR) );
5079
5080 if (!(verb = wcsdup( method ))) goto error;
5081 if (SUCCEEDED( VariantChangeType( &async, &async, 0, VT_BOOL )) && V_BOOL( &async )) request->async = TRUE;
5082 else request->async = FALSE;
5083
5084 if (!request->hsession)
5085 {
5088 {
5089 err = GetLastError();
5090 goto error;
5091 }
5092 if (!(request->hconnect = WinHttpConnect( request->hsession, hostname, uc.nPort, 0 )))
5093 {
5094 WinHttpCloseHandle( request->hsession );
5095 request->hsession = NULL;
5096 err = GetLastError();
5097 goto error;
5098 }
5099 }
5100 else if (!(request->hconnect = WinHttpConnect( request->hsession, hostname, uc.nPort, 0 )))
5101 {
5102 err = GetLastError();
5103 goto error;
5104 }
5105
5106 len = ARRAY_SIZE( httpsW );
5107 if (uc.dwSchemeLength == len && !memcmp( uc.lpszScheme, httpsW, len * sizeof(WCHAR) ))
5108 {
5110 }
5111 if (!(request->hrequest = WinHttpOpenRequest( request->hconnect, method, path, NULL, NULL, acceptW, flags )))
5112 {
5113 err = GetLastError();
5114 goto error;
5115 }
5117
5119 request->verb = verb;
5120 free( hostname );
5121 free( path );
5123 return S_OK;
5124
5125error:
5126 WinHttpCloseHandle( request->hconnect );
5127 request->hconnect = NULL;
5128 free( hostname );
5129 free( path );
5130 free( verb );
5132 return HRESULT_FROM_WIN32( err );
5133}
5134
5136 IWinHttpRequest *iface,
5137 BSTR header,
5138 BSTR value )
5139{
5142 WCHAR *str;
5143
5144 TRACE("%p, %s, %s\n", request, debugstr_w(header), debugstr_w(value));
5145
5146 if (!header) return E_INVALIDARG;
5147
5150 {
5152 goto done;
5153 }
5155 {
5157 goto done;
5158 }
5159 len = lstrlenW( header ) + 4;
5160 if (value) len += lstrlenW( value );
5161 if (!(str = malloc( (len + 1) * sizeof(WCHAR) )))
5162 {
5164 goto done;
5165 }
5166 swprintf( str, len + 1, L"%s: %s\r\n", header, value ? value : L"" );
5167 if (!WinHttpAddRequestHeaders( request->hrequest, str, len,
5169 {
5170 err = GetLastError();
5171 }
5172 free( str );
5173
5174done:
5176 return HRESULT_FROM_WIN32( err );
5177}
5178
5180 IWinHttpRequest *iface,
5181 BSTR header,
5182 BSTR *value )
5183{
5186
5187 TRACE("%p, %p\n", request, header);
5188
5191 {
5193 goto done;
5194 }
5195 if (!header || !value)
5196 {
5198 goto done;
5199 }
5200 size = 0;
5202 {
5203 err = GetLastError();
5204 if (err != ERROR_INSUFFICIENT_BUFFER) goto done;
5205 }
5206 if (!(*value = SysAllocStringLen( NULL, size / sizeof(WCHAR) )))
5207 {
5209 goto done;
5210 }
5213 {
5214 err = GetLastError();
5215 SysFreeString( *value );
5216 }
5217done:
5219 return HRESULT_FROM_WIN32( err );
5220}
5221
5223 IWinHttpRequest *iface,
5224 BSTR *headers )
5225{
5228
5229 TRACE("%p, %p\n", request, headers);
5230
5231 if (!headers) return E_INVALIDARG;
5232
5235 {
5237 goto done;
5238 }
5239 size = 0;
5241 {
5242 err = GetLastError();
5243 if (err != ERROR_INSUFFICIENT_BUFFER) goto done;
5244 }
5245 if (!(*headers = SysAllocStringLen( NULL, size / sizeof(WCHAR) )))
5246 {
5248 goto done;
5249 }
5252 {
5253 err = GetLastError();
5255 }
5256done:
5258 return HRESULT_FROM_WIN32( err );
5259}
5260
5262{
5263 struct winhttp_request *request = (struct winhttp_request *)context;
5264
5265 switch (status)
5266 {
5268 request->bytes_available = *(DWORD *)buffer;
5269 request->error = ERROR_SUCCESS;
5270 break;
5272 request->bytes_read = size;
5273 request->error = ERROR_SUCCESS;
5274 break;
5276 {
5278 request->error = result->dwError;
5279 break;
5280 }
5281 default:
5282 request->error = ERROR_SUCCESS;
5283 break;
5284 }
5285 SetEvent( request->wait );
5286}
5287
5289{
5292}
5293
5295{
5296 HANDLE handles[2] = { request->wait, request->cancel };
5297 DWORD ret;
5298
5300 {
5301 case WAIT_OBJECT_0:
5302 ret = request->error;
5303 break;
5304 case WAIT_OBJECT_0 + 1:
5305 ret = request->error = ERROR_CANCELLED;
5306 SetEvent( request->done );
5307 break;
5308 default:
5309 ret = request->error = GetLastError();
5310 break;
5311 }
5312 return ret;
5313}
5314
5316{
5317 DWORD err, size, buflen = 4096;
5318
5320 if (!WinHttpReceiveResponse( request->hrequest, NULL ))
5321 {
5322 return HRESULT_FROM_WIN32( GetLastError() );
5323 }
5325 if (!wcscmp( request->verb, L"HEAD" ))
5326 {
5328 return S_OK;
5329 }
5330 if (!(request->buffer = malloc( buflen ))) return E_OUTOFMEMORY;
5331 request->buffer[0] = 0;
5332 size = 0;
5333 do
5334 {
5336 if (!WinHttpQueryDataAvailable( request->hrequest, &request->bytes_available ))
5337 {
5338 err = GetLastError();
5339 goto error;
5340 }
5341 if ((err = wait_for_completion( request ))) goto error;
5342 if (!request->bytes_available) break;
5343 size += request->bytes_available;
5344 if (buflen < size)
5345 {
5346 char *tmp;
5347 while (buflen < size) buflen *= 2;
5348 if (!(tmp = realloc( request->buffer, buflen )))
5349 {
5351 goto error;
5352 }
5353 request->buffer = tmp;
5354 }
5356 if (!WinHttpReadData( request->hrequest, request->buffer + request->offset,
5357 request->bytes_available, &request->bytes_read ))
5358 {
5359 err = GetLastError();
5360 goto error;
5361 }
5362 if ((err = wait_for_completion( request ))) goto error;
5363 request->offset += request->bytes_read;
5364 } while (request->bytes_read);
5365
5367 return S_OK;
5368
5369error:
5370 free( request->buffer );
5371 request->buffer = NULL;
5372 return HRESULT_FROM_WIN32( err );
5373}
5374
5376{
5377 if (!WinHttpSetOption( request->hrequest, WINHTTP_OPTION_PROXY, &request->proxy,
5378 sizeof(request->proxy) )) return GetLastError();
5379
5380 if (!WinHttpSetOption( request->hrequest, WINHTTP_OPTION_AUTOLOGON_POLICY, &request->logon_policy,
5381 sizeof(request->logon_policy) )) return GetLastError();
5382
5383 if (!WinHttpSetOption( request->hrequest, WINHTTP_OPTION_DISABLE_FEATURE, &request->disable_feature,
5384 sizeof(request->disable_feature) )) return GetLastError();
5385
5387 sizeof(request->security_flags) )) return GetLastError();
5388
5389 if (!WinHttpSetTimeouts( request->hrequest,
5394 return ERROR_SUCCESS;
5395}
5396
5398{
5399 WCHAR headerW[64];
5400 int len;
5401
5402 len = swprintf( headerW, ARRAY_SIZE(headerW), L"%s: %s", L"Content-Type", L"text/plain" );
5404
5405 len = swprintf( headerW, ARRAY_SIZE(headerW), L"%s: %s", L"Content-Type", L"charset=utf-8" );
5407}
5408
5410{
5411 SAFEARRAY *sa = NULL;
5412 VARIANT data;
5413 char *ptr = NULL;
5414 LONG size = 0;
5415 HRESULT hr;
5416 DWORD err;
5417
5419 if (wcscmp( request->verb, L"GET" ))
5420 {
5421 VariantInit( &data );
5422 if (V_VT( &request->data ) == VT_BSTR)
5423 {
5424 UINT cp = CP_ACP;
5425 const WCHAR *str = V_BSTR( &request->data );
5426 int i, len = lstrlenW( str );
5427
5428 for (i = 0; i < len; i++)
5429 {
5430 if (str[i] > 127)
5431 {
5432 cp = CP_UTF8;
5433 break;
5434 }
5435 }
5436 size = WideCharToMultiByte( cp, 0, str, len, NULL, 0, NULL, NULL );
5437 if (!(ptr = malloc( size ))) return E_OUTOFMEMORY;
5440 }
5441 else if (VariantChangeType( &data, &request->data, 0, VT_ARRAY|VT_UI1 ) == S_OK)
5442 {
5443 sa = V_ARRAY( &data );
5444 if ((hr = SafeArrayAccessData( sa, (void **)&ptr )) != S_OK) return hr;
5445 if ((hr = SafeArrayGetUBound( sa, 1, &size )) != S_OK)
5446 {
5448 return hr;
5449 }
5450 size++;
5451 }
5452 }
5454 if (!WinHttpSendRequest( request->hrequest, NULL, 0, ptr, size, size, 0 ))
5455 {
5456 err = GetLastError();
5457 goto error;
5458 }
5459 if ((err = wait_for_completion( request ))) goto error;
5460 if (sa) SafeArrayUnaccessData( sa );
5461 else free( ptr );
5463 return S_OK;
5464
5465error:
5466 if (sa) SafeArrayUnaccessData( sa );
5467 else free( ptr );
5468 return HRESULT_FROM_WIN32( err );
5469}
5470
5472{
5473 struct winhttp_request *request = (struct winhttp_request *)ctx;
5475 SetEvent( request->done );
5476}
5477
5478/* critical section must be held */
5480{
5481 HANDLE done = request->done;
5482 DWORD err, ret;
5483
5486 {
5487 MSG msg;
5488 while (PeekMessageW( &msg, NULL, 0, 0, PM_REMOVE ))
5489 {
5492 }
5493 }
5494 switch (err)
5495 {
5496 case WAIT_OBJECT_0:
5497 ret = request->error;
5498 break;
5499 case WAIT_TIMEOUT:
5501 break;
5502 default:
5503 ret = GetLastError();
5504 break;
5505 }
5507 if (err == WAIT_OBJECT_0) request->proc_running = FALSE;
5508 return ret;
5509}
5510
5512 IWinHttpRequest *iface,
5513 VARIANT body )
5514{
5516 HRESULT hr;
5517
5518 TRACE("%p, %s\n", request, debugstr_variant(&body));
5519
5522 {
5525 }
5527 {
5529 return S_OK;
5530 }
5531 VariantClear( &request->data );
5532 if ((hr = VariantCopyInd( &request->data, &body )) != S_OK)
5533 {
5535 return hr;
5536 }
5538 {
5540 return HRESULT_FROM_WIN32( GetLastError() );
5541 }
5542 request->proc_running = TRUE;
5543 if (!request->async)
5544 {
5546 }
5548 return hr;
5549}
5550
5552 IWinHttpRequest *iface,
5553 LONG *status )
5554{
5557
5558 TRACE("%p, %p\n", request, status);
5559
5560 if (!status) return E_INVALIDARG;
5561
5564 {
5566 goto done;
5567 }
5569 if (!WinHttpQueryHeaders( request->hrequest, flags, NULL, &status_code, &len, &index ))
5570 {
5571 err = GetLastError();
5572 goto done;
5573 }
5575
5576done:
5578 return HRESULT_FROM_WIN32( err );
5579}
5580
5582 IWinHttpRequest *iface,
5583 BSTR *status )
5584{
5586 DWORD err = ERROR_SUCCESS, len = 0, index = 0;
5587
5588 TRACE("%p, %p\n", request, status);
5589
5590 if (!status) return E_INVALIDARG;
5591
5594 {
5596 goto done;
5597 }
5599 {
5600 err = GetLastError();
5601 if (err != ERROR_INSUFFICIENT_BUFFER) goto done;
5602 }
5603 if (!(*status = SysAllocStringLen( NULL, len / sizeof(WCHAR) )))
5604 {
5606 goto done;
5607 }
5608 index = 0;
5611 {
5612 err = GetLastError();
5614 }
5615done:
5617 return HRESULT_FROM_WIN32( err );
5618}
5619
5621{
5622 WCHAR *buffer, *p;
5623 DWORD size;
5624
5625 *codepage = CP_ACP;
5628 {
5629 if (!(buffer = malloc( size ))) return ERROR_OUTOFMEMORY;
5631 {
5632 free( buffer );
5633 return GetLastError();
5634 }
5635 if ((p = wcsstr( buffer, L"charset" )))
5636 {
5637 p += lstrlenW( L"charset" );
5638 while (*p == ' ') p++;
5639 if (*p++ == '=')
5640 {
5641 while (*p == ' ') p++;
5642 if (!wcsicmp( p, L"utf-8" )) *codepage = CP_UTF8;
5643 }
5644 }
5645 free( buffer );
5646 }
5647 return ERROR_SUCCESS;
5648}
5649
5651 IWinHttpRequest *iface,
5652 BSTR *body )
5653{
5655 UINT codepage;
5657 int len;
5658
5659 TRACE("%p, %p\n", request, body);
5660
5661 if (!body) return E_INVALIDARG;
5662
5665 {
5667 goto done;
5668 }
5669 if ((err = request_get_codepage( request, &codepage ))) goto done;
5670 len = MultiByteToWideChar( codepage, 0, request->buffer, request->offset, NULL, 0 );
5671 if (!(*body = SysAllocStringLen( NULL, len )))
5672 {
5674 goto done;
5675 }
5676 MultiByteToWideChar( codepage, 0, request->buffer, request->offset, *body, len );
5677 (*body)[len] = 0;
5678
5679done:
5681 return HRESULT_FROM_WIN32( err );
5682}
5683
5685 IWinHttpRequest *iface,
5686 VARIANT *body )
5687{
5689 SAFEARRAY *sa;
5690 HRESULT hr;
5692 char *ptr;
5693
5694 TRACE("%p, %p\n", request, body);
5695
5696 if (!body) return E_INVALIDARG;
5697
5700 {
5702 goto done;
5703 }
5704 if (!(sa = SafeArrayCreateVector( VT_UI1, 0, request->offset )))
5705 {
5707 goto done;
5708 }
5709 if ((hr = SafeArrayAccessData( sa, (void **)&ptr )) != S_OK)
5710 {
5713 return hr;
5714 }
5715 memcpy( ptr, request->buffer, request->offset );
5716 if ((hr = SafeArrayUnaccessData( sa )) != S_OK)
5717 {
5720 return hr;
5721 }
5722 V_VT( body ) = VT_ARRAY|VT_UI1;
5723 V_ARRAY( body ) = sa;
5724
5725done:
5727 return HRESULT_FROM_WIN32( err );
5728}
5729
5730struct stream
5731{
5734 char *data;
5736};
5737
5738static inline struct stream *impl_from_IStream( IStream *iface )
5739{
5740 return CONTAINING_RECORD( iface, struct stream, IStream_iface );
5741}
5742
5744{
5745 struct stream *stream = impl_from_IStream( iface );
5746
5747 TRACE("%p, %s, %p\n", stream, debugstr_guid(riid), obj);
5748
5749 if (IsEqualGUID( riid, &IID_IStream ) || IsEqualGUID( riid, &IID_IUnknown ))
5750 {
5751 *obj = iface;
5752 }
5753 else
5754 {
5755 FIXME("interface %s not implemented\n", debugstr_guid(riid));
5756 return E_NOINTERFACE;
5757 }
5758 IStream_AddRef( iface );
5759 return S_OK;
5760}
5761
5763{
5764 struct stream *stream = impl_from_IStream( iface );
5765 return InterlockedIncrement( &stream->refs );
5766}
5767
5769{
5770 struct stream *stream = impl_from_IStream( iface );
5772 if (!refs)
5773 {
5774 free( stream->data );
5775 free( stream );
5776 }
5777 return refs;
5778}
5779
5781{
5782 struct stream *stream = impl_from_IStream( iface );
5783 ULONG size;
5784
5785 if (stream->pos.QuadPart >= stream->size.QuadPart)
5786 {
5787 *read = 0;
5788 return S_FALSE;
5789 }
5790
5791 size = min( stream->size.QuadPart - stream->pos.QuadPart, len );
5793 stream->pos.QuadPart += size;
5794 *read = size;
5795
5796 return S_OK;
5797}
5798
5799static HRESULT WINAPI stream_Write( IStream *iface, const void *buf, ULONG len, ULONG *written )
5800{
5801 FIXME("\n");
5802 return E_NOTIMPL;
5803}
5804
5806{
5807 struct stream *stream = impl_from_IStream( iface );
5808
5809 if (origin == STREAM_SEEK_SET)
5810 stream->pos.QuadPart = move.QuadPart;
5811 else if (origin == STREAM_SEEK_CUR)
5812 stream->pos.QuadPart += move.QuadPart;
5813 else if (origin == STREAM_SEEK_END)
5814 stream->pos.QuadPart = stream->size.QuadPart - move.QuadPart;
5815
5816 if (newpos) newpos->QuadPart = stream->pos.QuadPart;
5817 return S_OK;
5818}
5819
5821{
5822 FIXME("\n");
5823 return E_NOTIMPL;
5824}
5825
5827 ULARGE_INTEGER *written )
5828{
5829 FIXME("\n");
5830 return E_NOTIMPL;
5831}
5832
5834{
5835 FIXME("\n");
5836 return E_NOTIMPL;
5837}
5838
5840{
5841 FIXME("\n");
5842 return E_NOTIMPL;
5843}
5844
5846{
5847 FIXME("\n");
5848 return E_NOTIMPL;
5849}
5850
5852{
5853 FIXME("\n");
5854 return E_NOTIMPL;
5855}
5856
5857static HRESULT WINAPI stream_Stat( IStream *iface, STATSTG *stg, DWORD flag )
5858{
5859 FIXME("\n");
5860 return E_NOTIMPL;
5861}
5862
5864{
5865 FIXME("\n");
5866 return E_NOTIMPL;
5867}
5868
5869static const IStreamVtbl stream_vtbl =
5870{
5885};
5886
5888 IWinHttpRequest *iface,
5889 VARIANT *body )
5890{
5893 struct stream *stream;
5894
5895 TRACE("%p, %p\n", request, body);
5896
5897 if (!body) return E_INVALIDARG;
5898
5901 {
5903 goto done;
5904 }
5905 if (!(stream = malloc( sizeof(*stream) )))
5906 {
5908 goto done;
5909 }
5910 stream->IStream_iface.lpVtbl = &stream_vtbl;
5911 stream->refs = 1;
5912 if (!(stream->data = malloc( request->offset )))
5913 {
5914 free( stream );
5916 goto done;
5917 }
5918 memcpy( stream->data, request->buffer, request->offset );
5919 stream->pos.QuadPart = 0;
5920 stream->size.QuadPart = request->offset;
5921 V_VT( body ) = VT_UNKNOWN;
5923
5924done:
5926 return HRESULT_FROM_WIN32( err );
5927}
5928
5930 IWinHttpRequest *iface,
5931 WinHttpRequestOption option,
5932 VARIANT *value )
5933{
5935 HRESULT hr = S_OK;
5936
5937 TRACE("%p, %u, %p\n", request, option, value);
5938
5940 switch (option)
5941 {
5942 case WinHttpRequestOption_URLCodePage:
5943 V_VT( value ) = VT_I4;
5944 V_I4( value ) = request->url_codepage;
5945 break;
5946 case WinHttpRequestOption_SslErrorIgnoreFlags:
5947 {
5948 V_VT( value ) = VT_I4;
5950 break;
5951 }
5952 default:
5953 FIXME("unimplemented option %u\n", option);
5954 hr = E_NOTIMPL;
5955 break;
5956 }
5958 return hr;
5959}
5960
5962 IWinHttpRequest *iface,
5963 WinHttpRequestOption option,
5964 VARIANT value )
5965{
5967 HRESULT hr = S_OK;
5968
5969 TRACE("%p, %u, %s\n", request, option, debugstr_variant(&value));
5970
5972 switch (option)
5973 {
5974 case WinHttpRequestOption_EnableRedirects:
5975 {
5976 if (V_BOOL( &value ))
5977 request->disable_feature &= ~WINHTTP_DISABLE_REDIRECTS;
5978 else
5979 request->disable_feature |= WINHTTP_DISABLE_REDIRECTS;
5980 break;
5981 }
5982 case WinHttpRequestOption_URLCodePage:
5983 {
5984 VARIANT cp;
5985 VariantInit( &cp );
5986 hr = VariantChangeType( &cp, &value, 0, VT_UI4 );
5987 if (SUCCEEDED( hr ))
5988 {
5989 request->url_codepage = V_UI4( &cp );
5990 TRACE("URL codepage: %u\n", request->url_codepage);
5991 }
5992 else if (V_VT( &value ) == VT_BSTR && !wcsicmp( V_BSTR( &value ), L"utf-8" ))
5993 {
5994 TRACE("URL codepage: UTF-8\n");
5995 request->url_codepage = CP_UTF8;
5996 hr = S_OK;
5997 }
5998 else
5999 FIXME("URL codepage %s is not recognized\n", debugstr_variant( &value ));
6000 break;
6001 }
6002 case WinHttpRequestOption_SslErrorIgnoreFlags:
6003 {
6008
6009 DWORD flags = V_I4( &value );
6010 if (flags && (flags & ~accepted))
6011 hr = E_INVALIDARG;
6012 else
6014 break;
6015 }
6016 default:
6017 FIXME("unimplemented option %u\n", option);
6018 hr = E_NOTIMPL;
6019 break;
6020 }
6022 return hr;
6023}
6024
6026 IWinHttpRequest *iface,
6028 VARIANT_BOOL *succeeded )
6029{
6031 DWORD err, msecs = (V_I4(&timeout) == -1) ? INFINITE : V_I4(&timeout) * 1000;
6032
6033 TRACE("%p, %s, %p\n", request, debugstr_variant(&timeout), succeeded);
6034
6037 {
6039 return S_OK;
6040 }
6041 switch ((err = request_wait( request, msecs )))
6042 {
6043 case ERROR_TIMEOUT:
6044 if (succeeded) *succeeded = VARIANT_FALSE;
6046 break;
6047
6048 default:
6049 if (succeeded) *succeeded = VARIANT_TRUE;
6050 break;
6051 }
6053 return HRESULT_FROM_WIN32( err );
6054}
6055
6057 IWinHttpRequest *iface )
6058{
6060
6061 TRACE("%p\n", request);
6062
6066 return S_OK;
6067}
6068
6070 IWinHttpRequest *iface,
6075{
6077
6078 TRACE( "%p, %ld, %ld, %ld, %ld\n", request, resolve_timeout, connect_timeout, send_timeout, receive_timeout );
6079
6086 return S_OK;
6087}
6088
6090 IWinHttpRequest *iface,
6091 BSTR certificate )
6092{
6093 FIXME("\n");
6094 return E_NOTIMPL;
6095}
6096
6098 IWinHttpRequest *iface,
6099 WinHttpRequestAutoLogonPolicy policy )
6100{
6102 HRESULT hr = S_OK;
6103
6104 TRACE("%p, %u\n", request, policy );
6105
6107 switch (policy)
6108 {
6109 case AutoLogonPolicy_Always:
6111 break;
6112 case AutoLogonPolicy_OnlyIfBypassProxy:
6114 break;
6115 case AutoLogonPolicy_Never:
6117 break;
6118 default: hr = E_INVALIDARG;
6119 break;
6120 }
6122 return hr;
6123}
6124
6125static const struct IWinHttpRequestVtbl winhttp_request_vtbl =
6126{
6153};
6154
6156{
6157 struct winhttp_request *request;
6158
6159 TRACE("%p\n", obj);
6160
6161 if (!(request = calloc( 1, sizeof(*request) ))) return E_OUTOFMEMORY;
6162 request->IWinHttpRequest_iface.lpVtbl = &winhttp_request_vtbl;
6163 request->refs = 1;
6165 request->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": winhttp_request.cs");
6167
6168 *obj = &request->IWinHttpRequest_iface;
6169 TRACE("returning iface %p\n", *obj);
6170 return S_OK;
6171}
@ sent
Definition: SystemMenu.c:27
@ optional
Definition: SystemMenu.c:34
#define read
Definition: acwin.h:96
#define close
Definition: acwin.h:98
static unsigned char bytes[4]
Definition: adnsresfilter.c:74
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
#define SOCKET_STATE_CLOSED
Definition: afd.h:83
WINBASEAPI _Check_return_ _Out_ AppPolicyProcessTerminationMethod * policy
Definition: appmodel.h:73
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedExchange
Definition: armddk.h:54
#define InterlockedDecrement
Definition: armddk.h:52
#define msg(x)
Definition: auth_time.c:54
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define index(s, c)
Definition: various.h:29
void user(int argc, const char *argv[])
Definition: cmds.c:1350
char * hostname
Definition: ftp.c:88
#define ARRAY_SIZE(A)
Definition: main.h:20
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static int list_empty(struct list_entry *head)
Definition: list.h:58
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
static void list_add_head(struct list_entry *head, struct list_entry *entry)
Definition: list.h:76
static void list_init(struct list_entry *head)
Definition: list.h:51
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
const GUID IID_IUnknown
Definition: list.h:37
static const WCHAR proxy_server[]
Definition: connections.c:40
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define WAIT_TIMEOUT
Definition: dderror.h:14
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define ERROR_IO_PENDING
Definition: dderror.h:15
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define realloc
Definition: debug_ros.c:6
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
DWORD task
Definition: delayimp.cpp:484
HRESULT hr
Definition: delayimp.cpp:573
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static HINSTANCE instance
Definition: main.c:40
static WCHAR * strdupAW(const char *src)
Definition: main.c:31
BOOL WINAPI CertFreeCertificateContext(PCCERT_CONTEXT pCertContext)
Definition: cert.c:371
static WCHAR available[MAX_STRING_RESOURCE_LEN]
Definition: object.c:2336
static WCHAR reason[MAX_STRING_RESOURCE_LEN]
Definition: object.c:1904
#define CloseHandle
Definition: compat.h:739
#define wcschr
Definition: compat.h:17
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define wcsnicmp
Definition: compat.h:14
#define wcsrchr
Definition: compat.h:16
#define CP_ACP
Definition: compat.h:109
#define SetLastError(x)
Definition: compat.h:752
static __inline const char * debugstr_an(const char *s, int n)
Definition: compat.h:55
#define FreeLibrary(x)
Definition: compat.h:748
OLECHAR * BSTR
Definition: compat.h:2293
#define ERROR_NOT_SUPPORTED
Definition: compat.h:100
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
#define CALLBACK
Definition: compat.h:35
#define lstrcpyW
Definition: compat.h:749
#define WideCharToMultiByte
Definition: compat.h:111
short VARIANT_BOOL
Definition: compat.h:2290
#define MultiByteToWideChar
Definition: compat.h:110
@ VT_BSTR
Definition: compat.h:2303
@ VT_UNKNOWN
Definition: compat.h:2308
@ VT_ARRAY
Definition: compat.h:2341
@ VT_I4
Definition: compat.h:2298
@ VT_BOOL
Definition: compat.h:2306
@ VT_UI4
Definition: compat.h:2313
@ VT_UI1
Definition: compat.h:2311
#define wcsicmp
Definition: compat.h:15
#define lstrlenW
Definition: compat.h:750
static char * strdupWA(const WCHAR *src)
Definition: main.c:91
BOOL WINAPI GetModuleHandleExW(IN DWORD dwFlags, IN LPCWSTR lpwModuleName OPTIONAL, OUT HMODULE *phModule)
Definition: loader.c:866
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:8
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:36
VOID WINAPI InitializeSRWLock(PSRWLOCK Lock)
Definition: sync.c:29
BOOL WINAPI InitializeCriticalSectionEx(OUT LPCRITICAL_SECTION lpCriticalSection, IN DWORD dwSpinCount, IN DWORD flags)
Definition: sync.c:107
BOOL WINAPI DECLSPEC_HOTPATCH TrySubmitThreadpoolCallback(PTP_SIMPLE_CALLBACK callback, PVOID userdata, TP_CALLBACK_ENVIRON *environment)
Definition: threadpool.c:9
LCID lcid
Definition: locale.c:5656
ULONGLONG WINAPI DECLSPEC_HOTPATCH GetTickCount64(void)
Definition: sync.c:192
unsigned char ch[4][2]
Definition: console.c:118
#define assert(_expr)
Definition: assert.h:32
_ACRTIMP __msvcrt_ulong __cdecl wcstoul(const wchar_t *, wchar_t **, int)
Definition: wcs.c:2912
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2983
_ACRTIMP int __cdecl wcscmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:1972
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2802
_ACRTIMP wchar_t *__cdecl wcsstr(const wchar_t *, const wchar_t *)
Definition: wcs.c:2993
_ACRTIMP char *__cdecl strchr(const char *, int)
Definition: string.c:3286
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
static wchar_t * wcsdup(const wchar_t *str)
Definition: string.h:94
HRESULT WINAPI DispGetParam(DISPPARAMS *pdispparams, UINT position, VARTYPE vtTarg, VARIANT *pvarResult, UINT *puArgErr)
Definition: dispatch.c:116
HRESULT WINAPI SafeArrayGetUBound(SAFEARRAY *psa, UINT nDim, LONG *plUbound)
Definition: safearray.c:1033
HRESULT WINAPI SafeArrayAccessData(SAFEARRAY *psa, void **ppvData)
Definition: safearray.c:1137
HRESULT WINAPI SafeArrayUnaccessData(SAFEARRAY *psa)
Definition: safearray.c:1168
SAFEARRAY *WINAPI SafeArrayCreateVector(VARTYPE vt, LONG lLbound, ULONG cElements)
Definition: safearray.c:677
HRESULT WINAPI SafeArrayDestroy(SAFEARRAY *psa)
Definition: safearray.c:1347
HRESULT WINAPI LoadRegTypeLib(REFGUID rguid, WORD wVerMajor, WORD wVerMinor, LCID lcid, ITypeLib **ppTLib)
Definition: typelib.c:531
static BOOL alloc_handle(struct handle_table *lpTable, OBJECTHDR *lpObject, HCRYPTKEY *lpHandle)
Definition: handle.c:183
static const WCHAR versionW[]
Definition: name.c:52
USHORT port
Definition: uri.c:228
unsigned char
Definition: typeof.h:29
struct object_header * grab_object(HINTERNET hinternet)
Definition: handle.c:55
void release_object(struct object_header *hdr)
Definition: handle.c:71
struct object_header * addref_object(struct object_header *hdr)
Definition: handle.c:48
HINSTANCE winhttp_instance
Definition: main.c:33
ULONG netconn_query_data_available(struct netconn *conn)
Definition: net.c:681
void netconn_release(struct netconn *conn)
Definition: net.c:295
DWORD netconn_resolve(WCHAR *hostname, INTERNET_PORT port, struct sockaddr_storage *addr, int timeout)
Definition: net.c:819
DWORD netconn_secure_connect(struct netconn *conn, WCHAR *hostname, DWORD security_flags, CredHandle *cred_handle, BOOL check_revocation)
Definition: net.c:315
void netconn_cancel_io(struct netconn *conn)
Definition: net.c:674
const void * netconn_get_certificate(struct netconn *conn)
Definition: net.c:850
DWORD netconn_recv(struct netconn *conn, void *buf, size_t len, int flags, int *recvd)
Definition: net.c:618
DWORD netconn_create(struct hostdata *host, const struct sockaddr_storage *sockaddr, int timeout, struct netconn **ret_conn)
Definition: net.c:212
void netconn_addref(struct netconn *conn)
Definition: net.c:290
BOOL netconn_is_alive(struct netconn *netconn)
Definition: net.c:698
DWORD netconn_set_timeout(struct netconn *netconn, BOOL send, int value)
Definition: net.c:686
BOOL netconn_wait_overlapped_result(struct netconn *conn, WSAOVERLAPPED *ovr, DWORD *len)
Definition: net.c:54
DWORD netconn_send(struct netconn *conn, const void *msg, size_t len, int *sent, WSAOVERLAPPED *ovr)
Definition: net.c:479
HINTERNET WINAPI WinHttpOpenRequest(HINTERNET hconnect, const WCHAR *verb, const WCHAR *object, const WCHAR *version, const WCHAR *referrer, const WCHAR **types, DWORD flags)
Definition: session.c:1277
HINTERNET WINAPI WinHttpOpen(LPCWSTR agent, DWORD access, LPCWSTR proxy, LPCWSTR bypass, DWORD flags)
Definition: session.c:304
HINTERNET WINAPI WinHttpConnect(HINTERNET hsession, const WCHAR *server, INTERNET_PORT port, DWORD reserved)
Definition: session.c:594
BOOL WINAPI WinHttpSetOption(HINTERNET handle, DWORD option, void *buffer, DWORD buflen)
Definition: session.c:1479
BOOL set_server_for_hostname(struct connect *connect, const WCHAR *server, INTERNET_PORT port)
Definition: session.c:532
BOOL WINAPI WinHttpCloseHandle(HINTERNET handle)
Definition: session.c:1358
BOOL WINAPI WinHttpSetTimeouts(HINTERNET handle, int resolve, int connect, int send, int receive)
Definition: session.c:2460
BOOL WINAPI WinHttpTimeToSystemTime(LPCWSTR string, SYSTEMTIME *time)
Definition: session.c:2561
WINHTTP_STATUS_CALLBACK WINAPI WinHttpSetStatusCallback(HINTERNET handle, WINHTTP_STATUS_CALLBACK callback, DWORD flags, DWORD_PTR reserved)
Definition: session.c:2435
BOOL WINAPI WinHttpCrackUrl(const WCHAR *url, DWORD len, DWORD flags, URL_COMPONENTSW *uc)
Definition: url.c:173
static ULONG connect_timeout
Definition: internet.c:98
#define swprintf
Definition: precomp.h:40
static const char * debugstr_variant(const VARIANT *var)
Definition: dom.c:505
method
Definition: dragdrop.c:54
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
r reserved
Definition: btrfs.c:3006
r received
Definition: btrfs.c:3005
ULONG to_read
Definition: btrfs.c:4260
#define AF_INET
Definition: tcpip.h:117
#define INFINITE
Definition: serial.h:102
size_t const new_size
Definition: expand.cpp:66
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
time_t now
Definition: finger.c:65
GLuint start
Definition: gl.h:1545
GLint level
Definition: gl.h:1546
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLdouble s
Definition: gl.h:2039
GLuint GLuint end
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLdouble n
Definition: glext.h:7729
GLenum src
Definition: glext.h:6340
GLuint GLuint * names
Definition: glext.h:11545
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
const GLubyte * c
Definition: glext.h:8905
GLuint index
Definition: glext.h:6031
GLenum GLint GLuint mask
Definition: glext.h:6028
GLenum const GLfloat * params
Definition: glext.h:5645
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint in
Definition: glext.h:9616
GLenum GLenum dst
Definition: glext.h:6340
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
const GLint * first
Definition: glext.h:5794
GLenum const GLvoid * addr
Definition: glext.h:9621
GLuint64EXT * result
Definition: glext.h:11304
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
GLuint id
Definition: glext.h:5910
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean flag
Definition: glfuncs.h:52
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
type_id
#define DISPID_HTTPREQUEST_OPTION
Definition: httprequestid.h:28
#define abort()
Definition: i386-dis.c:34
int hex(char ch)
REFIID riid
Definition: atlbase.h:39
static TfClientId tid
#define InterlockedCompareExchangePointer
Definition: interlocked.h:144
#define InterlockedCompareExchange
Definition: interlocked.h:119
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
voidpf uLong int origin
Definition: ioapi.h:144
char hdr[14]
Definition: iptest.cpp:33
uint32_t entry
Definition: isohybrid.c:63
#define debugstr_guid
Definition: kernel32.h:35
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_wn
Definition: kernel32.h:33
#define debugstr_w
Definition: kernel32.h:32
if(dx< 0)
Definition: linetemp.h:194
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
POINT cp
Definition: magnifier.c:59
struct _SYSTEMTIME SYSTEMTIME
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
#define memchr(s, c, n)
Definition: mkisofs.h:875
char string[160]
Definition: util.h:11
static PVOID ptr
Definition: dispmode.c:27
static const WCHAR url[]
Definition: encode.c:1384
static unsigned int number
Definition: dsound.c:1479
static struct _PeImage bin
static JOBOBJECTINFOCLASS LPVOID DWORD LPDWORD ret_len
Definition: process.c:81
static BSTR *static LPOLESTR
Definition: varformat.c:44
static VARIANTARG static DISPID
Definition: ordinal.c:49
static const WCHAR user_agentW[]
Definition: protocol.c:138
char strA[12]
Definition: clipboard.c:2215
DWORD exp
Definition: msg.c:18625
static WCHAR password[]
Definition: url.c:33
static WCHAR username[]
Definition: url.c:32
static void close_connection(void)
Definition: http.c:5576
static DWORD64 content_length
Definition: http.c:2127
#define min(a, b)
Definition: monoChain.cc:55
int notify
Definition: msacm.c:1366
unsigned int UINT
Definition: ndis.h:50
static BOOL ensure_cred_handle(void)
#define DWORD
Definition: nt_native.h:44
#define LOCALE_SYSTEM_DEFAULT
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:271
BSTR WINAPI SysAllocStringLen(const OLECHAR *str, unsigned int len)
Definition: oleaut.c:339
#define V_BOOL(A)
Definition: oleauto.h:224
#define V_ARRAY(A)
Definition: oleauto.h:222
#define V_UNKNOWN(A)
Definition: oleauto.h:281
#define DISPATCH_PROPERTYPUT
Definition: oleauto.h:1008
#define DISPATCH_METHOD
Definition: oleauto.h:1006
#define V_VT(A)
Definition: oleauto.h:211
#define V_BSTR(A)
Definition: oleauto.h:226
#define V_I4(A)
Definition: oleauto.h:247
#define V_UI4(A)
Definition: oleauto.h:270
#define DISPATCH_PROPERTYGET
Definition: oleauto.h:1007
const GUID IID_IDispatch
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
#define IID_NULL
Definition: guiddef.h:98
#define RtlGenRandom
Definition: ntsecapi.h:691
LONG SECURITY_STATUS
Definition: sspi.h:34
#define SecIsValidHandle(x)
Definition: sspi.h:63
#define SECPKG_CRED_OUTBOUND
Definition: sspi.h:291
#define SECBUFFER_TOKEN
Definition: sspi.h:161
#define SECURITY_NETWORK_DREP
Definition: sspi.h:474
#define ISC_REQ_DELEGATE
Definition: sspi.h:362
#define UNISP_NAME_W
Definition: sspi.h:38
#define ISC_REQ_MUTUAL_AUTH
Definition: sspi.h:363
#define SecInvalidateHandle(x)
Definition: sspi.h:58
WCHAR SEC_WCHAR
Definition: sspi.h:29
#define ISC_REQ_CONNECTION
Definition: sspi.h:373
#define ISC_REQ_USE_DCE_STYLE
Definition: sspi.h:371
#define err(...)
static HRESULT WINAPI stream_LockRegion(IStream *iface, ULARGE_INTEGER offset, ULARGE_INTEGER len, DWORD locktype)
Definition: request.c:5845
static DWORD query_headers(struct request *request, DWORD level, const WCHAR *name, void *buffer, DWORD *buflen, DWORD *index)
Definition: request.c:624
DWORD WINAPI WinHttpWebSocketClose(HINTERNET hsocket, USHORT status, void *reason, DWORD len)
Definition: request.c:4497
static HRESULT request_receive(struct winhttp_request *request)
Definition: request.c:5315
static char * build_wire_request(struct request *request, DWORD *len)
Definition: request.c:2174
DWORD WINAPI WinHttpWebSocketQueryCloseStatus(HINTERNET hsocket, USHORT *status, void *reason, DWORD len, DWORD *ret_len)
Definition: request.c:4561
static BOOL need_escape(char ch, enum escape_flags flags)
Definition: request.c:2069
static WCHAR * build_request_string(struct request *request)
Definition: request.c:578
static DWORD handle_redirect(struct request *request, DWORD status)
Definition: request.c:2774
static void release_task(struct task_header *task)
Definition: request.c:155
static DWORD refill_buffer(struct request *request, BOOL notify)
Definition: request.c:1911
DWORD WINAPI WinHttpWebSocketShutdown(HINTERNET hsocket, USHORT status, void *reason, DWORD len)
Definition: request.c:4415
void init_queue(struct queue *queue)
Definition: request.c:137
static HRESULT WINAPI winhttp_request_SetClientCertificate(IWinHttpRequest *iface, BSTR certificate)
Definition: request.c:6089
static DWORD complete_send_frame(struct socket *socket, WSAOVERLAPPED *ovr, const char *buf)
Definition: request.c:3670
static DWORD open_connection(struct request *request)
Definition: request.c:1567
static DWORD socket_close(struct socket *socket)
Definition: request.c:4441
static HRESULT WINAPI winhttp_request_SetRequestHeader(IWinHttpRequest *iface, BSTR header, BSTR value)
Definition: request.c:5135
static HRESULT WINAPI winhttp_request_GetIDsOfNames(IWinHttpRequest *iface, REFIID riid, LPOLESTR *names, UINT count, LCID lcid, DISPID *dispid)
Definition: request.c:4812
static BOOL socket_set_option(struct object_header *hdr, DWORD option, void *buffer, DWORD buflen)
Definition: request.c:3455
static HRESULT WINAPI stream_Stat(IStream *iface, STATSTG *stg, DWORD flag)
Definition: request.c:5857
static HRESULT WINAPI winhttp_request_GetTypeInfo(IWinHttpRequest *iface, UINT index, LCID lcid, ITypeInfo **info)
Definition: request.c:4800
static void task_socket_send_pong(void *ctx, BOOL abort)
Definition: request.c:4016
static DWORD queue_receive_response(struct request *request)
Definition: request.c:2928
static void request_set_utf8_content_type(struct winhttp_request *request)
Definition: request.c:5397
static BOOL validate_buffer_type(WINHTTP_WEB_SOCKET_BUFFER_TYPE type, enum fragment_type current_fragment)
Definition: request.c:3724
static HRESULT WINAPI winhttp_request_put_Option(IWinHttpRequest *iface, WinHttpRequestOption option, VARIANT value)
Definition: request.c:5961
static void socket_send_complete(struct socket *socket, DWORD ret, WINHTTP_WEB_SOCKET_BUFFER_TYPE type, DWORD len)
Definition: request.c:3789
static void task_receive_response(void *ctx, BOOL abort)
Definition: request.c:3054
static HRESULT WINAPI winhttp_request_get_StatusText(IWinHttpRequest *iface, BSTR *status)
Definition: request.c:5581
static BOOL valid_token_char(WCHAR c)
Definition: request.c:289
static BOOL socket_can_receive(struct socket *socket)
Definition: request.c:3719
static DWORD query_data_available(struct request *request, DWORD *available, BOOL async)
Definition: request.c:3112
static DWORD auth_scheme_from_header(const WCHAR *header)
Definition: request.c:871
static ULONG WINAPI stream_AddRef(IStream *iface)
Definition: request.c:5762
static void wait_set_status_callback(struct winhttp_request *request, DWORD status)
Definition: request.c:5288
static void socket_shutdown_complete(struct socket *socket, DWORD ret)
Definition: request.c:4328
static void update_value_from_digit(DWORD *value, char ch)
Definition: request.c:1836
static WINHTTP_WEB_SOCKET_BUFFER_TYPE map_opcode(struct socket *socket, enum socket_opcode opcode, BOOL fragment)
Definition: request.c:4139
static BOOL do_authorization(struct request *request, DWORD target, DWORD scheme_flag)
Definition: request.c:1122
static ULONG WINAPI winhttp_request_Release(IWinHttpRequest *iface)
Definition: request.c:4684
static DWORD request_get_codepage(struct winhttp_request *request, UINT *codepage)
Definition: request.c:5620
static BOOL get_chunk_size(struct request *request)
Definition: request.c:1844
static struct list connection_pool
Definition: request.c:1447
BOOL WINAPI WinHttpQueryHeaders(HINTERNET hrequest, DWORD level, const WCHAR *name, void *buffer, DWORD *buflen, DWORD *index)
Definition: request.c:814
static HRESULT WINAPI winhttp_request_SetProxy(IWinHttpRequest *iface, HTTPREQUEST_PROXY_SETTING proxy_setting, VARIANT proxy_server, VARIANT bypass_list)
Definition: request.c:4907
static void receive_io_complete(struct socket *socket)
Definition: request.c:3708
static struct header * parse_header(const WCHAR *string, size_t string_len, BOOL reply)
Definition: request.c:310
static HRESULT WINAPI winhttp_request_get_ResponseText(IWinHttpRequest *iface, BSTR *body)
Definition: request.c:5650
static DWORD receive_frame(struct socket *socket, DWORD *ret_len, enum socket_opcode *opcode, BOOL *final)
Definition: request.c:3983
static HRESULT WINAPI stream_Clone(IStream *iface, IStream **stream)
Definition: request.c:5863
static void delete_header(struct request *request, DWORD index)
Definition: request.c:411
static const struct IWinHttpRequestVtbl winhttp_request_vtbl
Definition: request.c:6125
static DWORD read_more_data(struct request *request, int maxlen, BOOL notify)
Definition: request.c:1791
static HRESULT WINAPI winhttp_request_Abort(IWinHttpRequest *iface)
Definition: request.c:6056
static DWORD receive_bytes(struct socket *socket, char *buf, DWORD len, DWORD *ret_len, BOOL read_full_buffer)
Definition: request.c:3937
#define DEFAULT_KEEP_ALIVE_TIMEOUT
Definition: request.c:48
static ITypeInfo * winhttp_typeinfo[last_tid]
Definition: request.c:4746
static HRESULT WINAPI stream_CopyTo(IStream *iface, IStream *stream, ULARGE_INTEGER len, ULARGE_INTEGER *read, ULARGE_INTEGER *written)
Definition: request.c:5826
static HRESULT WINAPI winhttp_request_QueryInterface(IWinHttpRequest *iface, REFIID riid, void **obj)
Definition: request.c:4704
static DWORD read_reply(struct request *request)
Definition: request.c:2625
static DWORD socket_drain(struct socket *socket)
Definition: request.c:4073
static BOOL connection_collector_running
Definition: request.c:1463
BOOL WINAPI WinHttpAddRequestHeaders(HINTERNET hrequest, const WCHAR *headers, DWORD len, DWORD flags)
Definition: request.c:521
static void set_content_length(struct request *request, DWORD status)
Definition: request.c:2554
static unsigned int decode_base64(const WCHAR *base64, unsigned int len, char *buf)
Definition: request.c:1017
static void task_query_data_available(void *ctx, BOOL abort)
Definition: request.c:3142
#define ESCAPE_MASK_DISABLE
Definition: request.c:2067
static BOOL end_of_read_data(struct request *request)
Definition: request.c:1981
#define ACTUAL_DEFAULT_RECEIVE_RESPONSE_TIMEOUT
Definition: request.c:50
static void clear_response_headers(struct request *request)
Definition: request.c:1769
static DWORD send_bytes(struct socket *socket, char *bytes, int len, int *sent, WSAOVERLAPPED *ovr)
Definition: request.c:3558
static enum socket_opcode map_buffer_type(struct socket *socket, WINHTTP_WEB_SOCKET_BUFFER_TYPE type)
Definition: request.c:3744
#define CONTROL_BIT
Definition: request.c:3571
static HRESULT WINAPI winhttp_request_Send(IWinHttpRequest *iface, VARIANT body)
Definition: request.c:5511
static HRESULT WINAPI winhttp_request_get_ResponseStream(IWinHttpRequest *iface, VARIANT *body)
Definition: request.c:5887
static BOOL get_authvalue(struct request *request, DWORD level, DWORD scheme, WCHAR *buffer, DWORD len)
Definition: request.c:1110
static void task_send_request(void *ctx, BOOL abort)
Definition: request.c:2381
static void socket_handle_closing(struct object_header *hdr)
Definition: request.c:3414
DWORD WINAPI WinHttpWebSocketReceive(HINTERNET hsocket, void *buf, DWORD len, DWORD *ret_len, WINHTTP_WEB_SOCKET_BUFFER_TYPE *ret_type)
Definition: request.c:4273
const WCHAR * str
Definition: request.c:850
void release_host(struct hostdata *host)
Definition: request.c:1449
static ITypeLib * winhttp_typelib
Definition: request.c:4745
static DWORD get_available_data(struct request *request)
Definition: request.c:1970
static char decode_char(WCHAR c)
Definition: request.c:1007
static void task_socket_shutdown(void *ctx, BOOL abort)
Definition: request.c:4341
static DWORD queue_task(struct queue *queue, TASK_CALLBACK task, struct task_header *task_hdr, struct object_header *obj)
Definition: request.c:207
static DWORD send_socket_shutdown(struct socket *socket, USHORT status, const void *reason, DWORD len, BOOL send_callback)
Definition: request.c:4358
static void send_io_complete(struct object_header *hdr)
Definition: request.c:3701
static DWORD insert_header(struct request *request, struct header *header)
Definition: request.c:390
static DWORD handle_control_frame(struct socket *socket)
Definition: request.c:4104
static void socket_close_complete(struct socket *socket, DWORD ret)
Definition: request.c:4464
static int request_receive_response_timeout(struct request *req)
Definition: request.c:52
static DWORD send_frame(struct socket *socket, enum socket_opcode opcode, USHORT status, const char *buf, DWORD buflen, BOOL final, WSAOVERLAPPED *ovr)
Definition: request.c:3573
static void free_header(struct header *header)
Definition: request.c:282
static HRESULT get_typeinfo(enum type_id tid, ITypeInfo **ret)
Definition: request.c:4753
static HRESULT WINAPI winhttp_request_WaitForResponse(IWinHttpRequest *iface, VARIANT timeout, VARIANT_BOOL *succeeded)
Definition: request.c:6025
static DWORD start_next_chunk(struct request *request, BOOL notify)
Definition: request.c:1869
unsigned int len
Definition: request.c:851
static HRESULT WINAPI stream_UnlockRegion(IStream *iface, ULARGE_INTEGER offset, ULARGE_INTEGER len, DWORD locktype)
Definition: request.c:5851
static ULONG WINAPI stream_Release(IStream *iface)
Definition: request.c:5768
static void drain_content(struct request *request)
Definition: request.c:2037
#define INITIAL_HEADER_BUFFER_LEN
Definition: request.c:2623
static BOOL skip_async_queue(struct request *request, BOOL *wont_block, DWORD to_read)
Definition: request.c:3104
static DWORD handle_authorization(struct request *request, DWORD status)
Definition: request.c:2520
#define MASK_BIT
Definition: request.c:3569
static DWORD request_wait(struct winhttp_request *request, DWORD timeout)
Definition: request.c:5479
DWORD WINAPI WinHttpWebSocketSend(HINTERNET hsocket, WINHTTP_WEB_SOCKET_BUFFER_TYPE type, void *buf, DWORD len)
Definition: request.c:3836
static HRESULT WINAPI winhttp_request_SetAutoLogonPolicy(IWinHttpRequest *iface, WinHttpRequestAutoLogonPolicy policy)
Definition: request.c:6097
BOOL WINAPI WinHttpQueryDataAvailable(HINTERNET hrequest, LPDWORD available)
Definition: request.c:3156
static DWORD wait_for_completion(struct winhttp_request *request)
Definition: request.c:5294
static DWORD add_host_header(struct request *request, DWORD modifier)
Definition: request.c:1748
#define FIN_BIT
Definition: request.c:3568
static void task_socket_send(void *ctx, BOOL abort)
Definition: request.c:3818
static DWORD discard_eol(struct request *request, BOOL notify)
Definition: request.c:1819
static enum auth_scheme scheme_from_flag(DWORD flag)
Definition: request.c:863
static struct authinfo * alloc_authinfo(void)
Definition: request.c:1079
@ last_tid
Definition: request.c:4742
@ IWinHttpRequest_tid
Definition: request.c:4741
static void task_write_data(void *ctx, BOOL abort)
Definition: request.c:3357
static void addref_task(struct task_header *task)
Definition: request.c:150
static void finished_reading(struct request *request)
Definition: request.c:1936
static HRESULT WINAPI winhttp_request_Open(IWinHttpRequest *iface, BSTR method, BSTR url, VARIANT async)
Definition: request.c:5042
static UINT encode_base64(const char *bin, unsigned int len, WCHAR *base64)
Definition: request.c:966
static DWORD set_credentials(struct request *request, DWORD target, DWORD scheme_flag, const WCHAR *username, const WCHAR *password)
Definition: request.c:2450
static HRESULT WINAPI winhttp_request_GetTypeInfoCount(IWinHttpRequest *iface, UINT *count)
Definition: request.c:4728
static HRESULT WINAPI winhttp_request_SetTimeouts(IWinHttpRequest *iface, LONG resolve_timeout, LONG connect_timeout, LONG send_timeout, LONG receive_timeout)
Definition: request.c:6069
void stop_queue(struct queue *queue)
Definition: request.c:144
static void reset_request(struct winhttp_request *request)
Definition: request.c:5012
static DWORD add_websocket_key_header(struct request *request)
Definition: request.c:2233
static void remove_data(struct request *request, int count)
Definition: request.c:1784
static BOOL cancel_queue(struct queue *queue)
Definition: request.c:245
DWORD add_request_headers(struct request *request, const WCHAR *headers, DWORD len, DWORD flags)
Definition: request.c:485
BOOL WINAPI WinHttpWriteData(HINTERNET hrequest, const void *buffer, DWORD to_write, DWORD *written)
Definition: request.c:3371
static DWORD map_secure_protocols(DWORD mask)
Definition: request.c:1525
static void task_send_callback(void *ctx, BOOL abort)
Definition: request.c:272
static const struct object_vtbl socket_vtbl
Definition: request.c:3484
static void initialize_request(struct winhttp_request *request)
Definition: request.c:4999
static void cancel_request(struct winhttp_request *request)
Definition: request.c:4651
void release_typelib(void)
Definition: request.c:4788
#define ESCAPE_MASK_PERCENT
Definition: request.c:2066
static HRESULT WINAPI stream_Revert(IStream *iface)
Definition: request.c:5839
static DWORD secure_proxy_connect(struct request *request)
Definition: request.c:1397
#define QUERY_MODIFIER_MASK
Definition: request.c:622
BOOL WINAPI WinHttpReadData(HINTERNET hrequest, void *buffer, DWORD to_read, DWORD *read)
Definition: request.c:3252
static DWORD escape_string(const char *src, DWORD len, char *dst, enum escape_flags flags)
Definition: request.c:2083
static void CALLBACK wait_status_callback(HINTERNET handle, DWORD_PTR context, DWORD status, LPVOID buffer, DWORD size)
Definition: request.c:5261
static BOOL is_passport_request(struct request *request)
Definition: request.c:2891
static DWORD get_redirect_url(struct request *request, WCHAR **ret_url, DWORD *ret_len)
Definition: request.c:2756
static HRESULT WINAPI winhttp_request_GetResponseHeader(IWinHttpRequest *iface, BSTR header, BSTR *value)
Definition: request.c:5179
static DWORD query_auth_schemes(struct request *request, DWORD level, DWORD *supported, DWORD *first)
Definition: request.c:883
#define RESERVED_BIT
Definition: request.c:3570
static HRESULT WINAPI stream_Seek(IStream *iface, LARGE_INTEGER move, DWORD origin, ULARGE_INTEGER *newpos)
Definition: request.c:5805
static struct winhttp_request * impl_from_IWinHttpRequest(IWinHttpRequest *iface)
Definition: request.c:4638
static WCHAR * create_websocket_key(void)
Definition: request.c:2223
static HRESULT WINAPI stream_SetSize(IStream *iface, ULARGE_INTEGER newsize)
Definition: request.c:5820
DWORD process_header(struct request *request, const WCHAR *field, const WCHAR *value, DWORD flags, BOOL request_only)
Definition: request.c:424
BOOL WINAPI WinHttpSetCredentials(HINTERNET hrequest, DWORD target, DWORD scheme, const WCHAR *username, const WCHAR *password, void *params)
Definition: request.c:2493
#define ESCAPE_MASK_DEFAULT
Definition: request.c:2064
static WCHAR * build_absolute_request_path(struct request *request, const WCHAR **path)
Definition: request.c:552
static void task_read_data(void *ctx, BOOL abort)
Definition: request.c:3238
static const WCHAR * attribute_table[]
Definition: request.c:58
static BOOL task_needs_completion(struct task_header *task_hdr)
Definition: request.c:240
static HRESULT WINAPI winhttp_request_GetAllResponseHeaders(IWinHttpRequest *iface, BSTR *headers)
Definition: request.c:5222
static HRESULT WINAPI stream_Write(IStream *iface, const void *buf, ULONG len, ULONG *written)
Definition: request.c:5799
static struct stream * impl_from_IStream(IStream *iface)
Definition: request.c:5738
static void record_cookies(struct request *request)
Definition: request.c:2742
static DWORD query_data_ready(struct request *request)
Definition: request.c:3094
HRESULT WinHttpRequest_create(void **obj)
Definition: request.c:6155
static char * build_wire_path(struct request *request, DWORD *ret_len)
Definition: request.c:2130
static CRITICAL_SECTION connection_pool_cs
Definition: request.c:1438
static DWORD receive_close_status(struct socket *socket, DWORD len)
Definition: request.c:4086
static const struct @632 auth_schemes[]
escape_flags
Definition: request.c:2054
@ ESCAPE_FLAG_NON_PRINTABLE
Definition: request.c:2055
@ ESCAPE_FLAG_8BIT
Definition: request.c:2060
@ ESCAPE_FLAG_STRIP_CRLF
Definition: request.c:2061
@ ESCAPE_FLAG_DEL
Definition: request.c:2059
@ ESCAPE_FLAG_SPACE
Definition: request.c:2056
@ ESCAPE_FLAG_PERCENT
Definition: request.c:2057
@ ESCAPE_FLAG_UNSAFE
Definition: request.c:2058
static void CALLBACK connection_collector(TP_CALLBACK_INSTANCE *instance, void *ctx)
Definition: request.c:1465
static HRESULT request_send(struct winhttp_request *request)
Definition: request.c:5409
HINTERNET WINAPI WinHttpWebSocketCompleteUpgrade(HINTERNET hrequest, DWORD_PTR context)
Definition: request.c:3492
request_state
Definition: request.c:4598
@ REQUEST_STATE_RESPONSE_RECEIVED
Definition: request.c:4603
@ REQUEST_STATE_OPEN
Definition: request.c:4601
@ REQUEST_STATE_INITIALIZED
Definition: request.c:4599
@ REQUEST_STATE_CANCELLED
Definition: request.c:4600
@ REQUEST_STATE_SENT
Definition: request.c:4602
static void CALLBACK task_callback(TP_CALLBACK_INSTANCE *instance, void *ctx)
Definition: request.c:187
static HRESULT WINAPI winhttp_request_get_Option(IWinHttpRequest *iface, WinHttpRequestOption option, VARIANT *value)
Definition: request.c:5929
static HRESULT WINAPI stream_QueryInterface(IStream *iface, REFIID riid, void **obj)
Definition: request.c:5743
static WCHAR * addr_to_str(struct sockaddr_storage *addr)
Definition: request.c:1417
static DWORD handle_passport_redirect(struct request *request)
Definition: request.c:2906
static CRITICAL_SECTION_DEBUG connection_pool_debug
Definition: request.c:1439
void destroy_authinfo(struct authinfo *authinfo)
Definition: request.c:1097
static HRESULT WINAPI winhttp_request_get_Status(IWinHttpRequest *iface, LONG *status)
Definition: request.c:5551
static BOOL socket_can_send(struct socket *socket)
Definition: request.c:3714
static HRESULT WINAPI stream_Commit(IStream *iface, DWORD flags)
Definition: request.c:5833
static struct task_header * get_next_task(struct queue *queue, struct task_header *prev_task)
Definition: request.c:161
static HRESULT WINAPI stream_Read(IStream *iface, void *buf, ULONG len, ULONG *read)
Definition: request.c:5780
static void CALLBACK send_and_receive_proc(TP_CALLBACK_INSTANCE *instance, void *ctx)
Definition: request.c:5471
static ULONG WINAPI winhttp_request_AddRef(IWinHttpRequest *iface)
Definition: request.c:4643
static REFIID winhttp_tid_id[]
Definition: request.c:4748
static void socket_destroy(struct object_header *hdr)
Definition: request.c:3440
static void free_request(struct winhttp_request *request)
Definition: request.c:4668
static void socket_receive_complete(struct socket *socket, DWORD ret, WINHTTP_WEB_SOCKET_BUFFER_TYPE type, DWORD len)
Definition: request.c:4234
static DWORD str_to_wire(const WCHAR *src, int src_len, char *dst, enum escape_flags flags)
Definition: request.c:2114
static const IStreamVtbl stream_vtbl
Definition: request.c:5869
static HRESULT WINAPI winhttp_request_Invoke(IWinHttpRequest *iface, DISPID member, REFIID riid, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep_info, UINT *arg_err)
Definition: request.c:4837
static DWORD socket_send_pong(struct socket *socket)
Definition: request.c:4031
DWORD scheme
Definition: request.c:852
static int get_header_index(struct request *request, const WCHAR *field, int requested_index, BOOL request_only)
Definition: request.c:370
BOOL WINAPI WinHttpSendRequest(HINTERNET hrequest, const WCHAR *headers, DWORD headers_len, void *optional, DWORD optional_len, DWORD total_len, DWORD_PTR context)
Definition: request.c:2397
static HRESULT WINAPI winhttp_request_get_ResponseBody(IWinHttpRequest *iface, VARIANT *body)
Definition: request.c:5684
static BOOL is_supported_opcode(enum socket_opcode opcode)
Definition: request.c:3966
BOOL WINAPI WinHttpReceiveResponse(HINTERNET hrequest, LPVOID reserved)
Definition: request.c:3068
static DWORD request_set_parameters(struct winhttp_request *request)
Definition: request.c:5375
static void cache_connection(struct netconn *netconn)
Definition: request.c:1503
static HRESULT WINAPI winhttp_request_SetCredentials(IWinHttpRequest *iface, BSTR username, BSTR password, HTTPREQUEST_SETCREDENTIALS_FLAGS flags)
Definition: request.c:4960
BOOL WINAPI WinHttpQueryAuthSchemes(HINTERNET hrequest, LPDWORD supported, LPDWORD first, LPDWORD target)
Definition: request.c:925
static void task_socket_close(void *ctx, BOOL abort)
Definition: request.c:4477
static WCHAR * build_proxy_connect_string(struct request *request)
Definition: request.c:1351
static void task_socket_receive(void *ctx, BOOL abort)
Definition: request.c:4253
static BOOL socket_query_option(struct object_header *hdr, DWORD option, void *buffer, DWORD *buflen)
Definition: request.c:3426
#define MAX_REPLY_LEN
Definition: request.c:2622
#define calloc
Definition: rosglue.h:14
static void accepted(enum accept_stat, struct rpc_err *)
Definition: rpc_prot.c:280
static BOOL is_secure(RpcConnection_http *httpc)
#define SEC_WINNT_AUTH_IDENTITY_UNICODE
Definition: rpcdce.h:310
#define SP_PROT_TLS1_1_CLIENT
Definition: schannel.h:33
#define SP_PROT_TLS1_CLIENT
Definition: schannel.h:31
#define SCHANNEL_CRED_VERSION
Definition: schannel.h:22
#define SP_PROT_TLS1_2_CLIENT
Definition: schannel.h:34
#define SP_PROT_SSL2_CLIENT
Definition: schannel.h:29
#define SP_PROT_SSL3_CLIENT
Definition: schannel.h:30
DWORD LCID
Definition: nls.h:13
#define CP_UTF8
Definition: nls.h:20
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field)
Definition: list.h:204
static const void * body(MD5_CTX *ctx, const void *data, unsigned long size)
Definition: md5.c:100
#define memset(x, y, z)
Definition: compat.h:39
vector< Header * > headers
Definition: sdkparse.cpp:39
#define TRACE(s)
Definition: solgame.cpp:4
SECURITY_STATUS WINAPI FreeContextBuffer(PVOID pv)
Definition: sspi.c:699
wchar_t const *const size_t const buffer_size
Definition: stat.cpp:95
INTERNET_PORT nPort
Definition: winhttp.h:543
LPWSTR lpszScheme
Definition: winhttp.h:538
LPWSTR lpszUrlPath
Definition: winhttp.h:548
DWORD dwHostNameLength
Definition: winhttp.h:542
DWORD dwExtraInfoLength
Definition: winhttp.h:551
DWORD dwUrlPathLength
Definition: winhttp.h:549
LPWSTR lpszHostName
Definition: winhttp.h:541
INTERNET_SCHEME nScheme
Definition: winhttp.h:540
DWORD dwStructSize
Definition: winhttp.h:537
DWORD dwSchemeLength
Definition: winhttp.h:539
PCCERT_CONTEXT * paCred
Definition: schannel.h:90
DWORD dwVersion
Definition: schannel.h:88
DWORD cCreds
Definition: schannel.h:89
DWORD grbitEnabledProtocols
Definition: schannel.h:96
WORD wMilliseconds
Definition: minwinbase.h:263
WORD wSecond
Definition: minwinbase.h:262
WORD wMinute
Definition: minwinbase.h:261
WORD wDayOfWeek
Definition: minwinbase.h:258
ULONG cBuffers
Definition: sspi.h:182
ULONG ulVersion
Definition: sspi.h:181
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
Definition: cookie.c:202
char * data
DWORD scheme
CredHandle cred
CtxtHandle ctx
TimeStamp exp
unsigned int data_len
ULONG max_token
WCHAR * hostname
struct sockaddr_storage sockaddr
struct session * session
WCHAR * servername
INTERNET_PORT hostport
INTERNET_PORT serverport
Definition: http.c:7252
Definition: cookie.c:42
Definition: parser.c:44
WCHAR * field
BOOL is_request
WCHAR * value
Definition: txthost.c:37
LONG ref
Definition: txthost.c:39
Definition: copy.c:22
Definition: list.h:15
Definition: name.c:39
struct hostdata * host
struct list entry
struct sockaddr_storage sockaddr
ULONGLONG keep_until
Definition: getopt.h:109
BOOL callback_running
SRWLOCK lock
struct list queued_tasks
Definition: send.c:48
Definition: tftpd.h:86
unsigned int websocket_set_send_buffer_size
DWORD content_read
DWORD read_reply_status
DWORD read_size
struct queue queue
struct request::@633 creds[TARGET_MAX][SCHEME_MAX]
DWORD optional_len
const CERT_CONTEXT * server_cert
DWORD max_redirects
WCHAR * version
char path[256]
Definition: tftpd.h:94
const CERT_CONTEXT * client_cert
int send_timeout
struct header * headers
struct object_header hdr
WCHAR * verb
DWORD security_flags
DWORD redirect_count
enum request_flags flags
struct authinfo * authinfo
DWORD num_headers
CredHandle cred_handle
WCHAR * status_text
int read_reply_len
void * optional
int receive_timeout
BOOL check_revocation
int connect_timeout
int resolve_timeout
WCHAR * raw_headers
struct connect * connect
DWORD read_pos
char read_buf[8192]
unsigned int websocket_send_buffer_size
BOOL read_chunked
int receive_response_timeout
BOOL read_chunked_size
BOOL cred_handle_initialized
struct netconn * netconn
DWORD content_length
struct authinfo * proxy_authinfo
enum request_response_state state
BOOL read_chunked_eof
DWORD_PTR context
WCHAR * agent
SRWLOCK send_lock
enum fragment_type sending_fragment_type
unsigned int send_frame_buffer_size
DWORD read_size
struct object_header hdr
enum socket_opcode opcode
enum socket_state state
USHORT status
DWORD close_frame_receive_err
struct queue send_q
enum fragment_type receiving_fragment_type
unsigned int send_remaining_size
struct queue recv_q
volatile LONG pending_noncontrol_send
char mask[4]
char * send_frame_buffer
struct netconn * netconn
unsigned int mask_index
unsigned int bytes_in_read_buffer
char reason[123]
unsigned int client_buffer_offset
BOOL last_receive_final
unsigned int bytes_in_send_frame_buffer
unsigned int send_buffer_size
BOOL close_frame_received
char * read_buffer
DWORD reason_len
int keepalive_interval
Definition: ps.c:97
Definition: parse.h:23
char * data
Definition: request.c:5734
LONG refs
Definition: request.c:5733
ULARGE_INTEGER pos
Definition: request.c:5735
unsigned int size
Definition: parse.h:27
unsigned char * data
Definition: parse.h:26
IStream IStream_iface
Definition: request.c:5732
Definition: tools.h:99
struct object_header * obj
volatile LONG refs
TASK_CALLBACK callback
volatile LONG completion_sent
struct list entry
Definition: dhcpd.h:248
VARIANT data
Definition: request.c:4615
DWORD bytes_read
Definition: request.c:4624
LONG send_timeout
Definition: request.c:4630
HANDLE cancel
Definition: request.c:4619
LONG receive_timeout
Definition: request.c:4631
HINTERNET hrequest
Definition: request.c:4614
IWinHttpRequest IWinHttpRequest_iface
Definition: request.c:4608
LONG resolve_timeout
Definition: request.c:4628
BOOL proc_running
Definition: request.c:4620
WCHAR * verb
Definition: request.c:4616
DWORD logon_policy
Definition: request.c:4626
HINTERNET hconnect
Definition: request.c:4613
DWORD bytes_available
Definition: request.c:4623
char * buffer
Definition: request.c:4621
HINTERNET hsession
Definition: request.c:4612
LONG connect_timeout
Definition: request.c:4629
CRITICAL_SECTION cs
Definition: request.c:4610
DWORD security_flags
Definition: request.c:4635
enum request_state state
Definition: request.c:4611
WINHTTP_PROXY_INFO proxy
Definition: request.c:4632
UINT url_codepage
Definition: request.c:4634
DWORD disable_feature
Definition: request.c:4627
DWORD * written
#define max(a, b)
Definition: svc.c:63
DWORD WINAPI WaitForMultipleObjects(IN DWORD nCount, IN CONST HANDLE *lpHandles, IN BOOL bWaitAll, IN DWORD dwMilliseconds)
Definition: synch.c:151
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:726
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:587
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:669
#define LIST_INIT(head)
Definition: queue.h:197
#define LIST_ENTRY(type)
Definition: queue.h:175
int read_line()
WINBASEAPI VOID WINAPI FreeLibraryWhenCallbackReturns(_Inout_ PTP_CALLBACK_INSTANCE pci, _In_ HMODULE mod)
#define DWORD_PTR
Definition: treelist.c:76
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
uint32_t DWORD_PTR
Definition: typedefs.h:65
uint32_t * LPDWORD
Definition: typedefs.h:59
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
static EFI_HANDLE * handles
Definition: uefidisk.c:118
LONGLONG QuadPart
Definition: typedefs.h:114
Definition: pdh_main.c:96
const char *WSAAPI inet_ntop(int af, const void *src, char *dst, size_t cnt)
Definition: unix_func.c:8
HRESULT WINAPI DECLSPEC_HOTPATCH VariantChangeType(VARIANTARG *pvargDest, VARIANTARG *pvargSrc, USHORT wFlags, VARTYPE vt)
Definition: variant.c:962
HRESULT WINAPI DECLSPEC_HOTPATCH VariantClear(VARIANTARG *pVarg)
Definition: variant.c:648
void WINAPI VariantInit(VARIANTARG *pVarg)
Definition: variant.c:568
HRESULT WINAPI VariantCopyInd(VARIANT *pvargDest, VARIANTARG *pvargSrc)
Definition: variant.c:847
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
int codepage
Definition: win_iconv.c:156
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
#define WAIT_OBJECT_0
Definition: winbase.h:383
#define WINAPI
Definition: msvc.h:6
#define SEC_E_OK
Definition: winerror.h:3450
#define S_FALSE
Definition: winerror.h:3451
static HRESULT HRESULT_FROM_WIN32(unsigned int x)
Definition: winerror.h:210
#define ERROR_INVALID_OPERATION
Definition: winerror.h:1689
#define E_NOINTERFACE
Definition: winerror.h:3479
#define DISP_E_UNKNOWNINTERFACE
Definition: winerror.h:3614
#define WSAETIMEDOUT
Definition: winerror.h:2876
#define ERROR_CANCELLED
Definition: winerror.h:1055
#define SEC_I_CONTINUE_NEEDED
Definition: winerror.h:4324
#define ERROR_TIMEOUT
Definition: winerror.h:1286
#define ERROR_INTERNAL_ERROR
Definition: winerror.h:1185
BOOL set_cookies(struct request *request, const WCHAR *cookies)
Definition: cookie.c:263
DWORD add_cookie_headers(struct request *request)
Definition: cookie.c:322
#define WINHTTP_OPTION_PROXY
Definition: winhttp.h:118
#define WINHTTP_HANDLE_TYPE_REQUEST
Definition: winhttp.h:503
#define WINHTTP_DISABLE_AUTHENTICATION
Definition: winhttp.h:216
#define WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
Definition: winhttp.h:450
#define WINHTTP_CALLBACK_STATUS_CLOSE_COMPLETE
Definition: winhttp.h:466
#define WINHTTP_QUERY_CONTENT_LENGTH
Definition: winhttp.h:365
#define ERROR_WINHTTP_INTERNAL_ERROR
Definition: winhttp.h:236
WORD INTERNET_PORT
Definition: winhttp.h:43
#define WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE
Definition: winhttp.h:460
#define WINHTTP_AUTOLOGON_SECURITY_LEVEL_HIGH
Definition: winhttp.h:200
#define ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN
Definition: winhttp.h:255
#define WINHTTP_OPTION_CONTEXT_VALUE
Definition: winhttp.h:121
#define WINHTTP_CALLBACK_STATUS_REDIRECT
Definition: winhttp.h:456
#define WINHTTP_FLAG_ESCAPE_DISABLE_QUERY
Definition: winhttp.h:64
#define SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE
Definition: winhttp.h:346
#define WINHTTP_QUERY_WWW_AUTHENTICATE
Definition: winhttp.h:400
#define WINHTTP_QUERY_CONNECTION
Definition: winhttp.h:383
#define WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
Definition: winhttp.h:447
#define WINHTTP_QUERY_VERSION
Definition: winhttp.h:378
#define HTTP_STATUS_NO_CONTENT
Definition: winhttp.h:305
#define ERROR_WINHTTP_OPERATION_CANCELLED
Definition: winhttp.h:244
#define WINHTTP_OPTION_SECURITY_FLAGS
Definition: winhttp.h:114
#define WINHTTP_CALLBACK_STATUS_SHUTDOWN_COMPLETE
Definition: winhttp.h:467
#define WINHTTP_CALLBACK_STATUS_REQUEST_SENT
Definition: winhttp.h:448
#define WINHTTP_OPTION_REDIRECT_POLICY_NEVER
Definition: winhttp.h:203
#define WINHTTP_QUERY_FLAG_SYSTEMTIME
Definition: winhttp.h:438
#define WINHTTP_AUTH_SCHEME_BASIC
Definition: winhttp.h:524
#define WINHTTP_QUERY_PROXY_AUTHENTICATE
Definition: winhttp.h:401
#define ERROR_WINHTTP_INVALID_SERVER_RESPONSE
Definition: winhttp.h:260
#define WINHTTP_AUTH_SCHEME_PASSPORT
Definition: winhttp.h:526
#define ERROR_WINHTTP_HEADER_ALREADY_EXISTS
Definition: winhttp.h:263
#define WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE
Definition: winhttp.h:459
#define API_QUERY_DATA_AVAILABLE
Definition: winhttp.h:495
#define WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
Definition: winhttp.h:449
#define WINHTTP_QUERY_PROXY_CONNECTION
Definition: winhttp.h:429
#define WINHTTP_OPTION_DISABLE_FEATURE
Definition: winhttp.h:125
#define HTTP_STATUS_PROXY_AUTH_REQ
Definition: winhttp.h:324
#define WINHTTP_ADDREQ_FLAG_ADD_IF_NEW
Definition: winhttp.h:91
#define WINHTTP_DISABLE_KEEP_ALIVE
Definition: winhttp.h:217
#define WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON
Definition: winhttp.h:94
#define WINHTTP_QUERY_STATUS_CODE
Definition: winhttp.h:379
#define WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
Definition: winhttp.h:451
#define WINHTTP_QUERY_FLAG_REQUEST_HEADERS
Definition: winhttp.h:437
#define WINHTTP_ACCESS_TYPE_DEFAULT_PROXY
Definition: winhttp.h:69
#define WINHTTP_ENABLE_PASSPORT_AUTH
Definition: winhttp.h:210
#define WINHTTP_ACCESS_TYPE_NAMED_PROXY
Definition: winhttp.h:71
#define API_WRITE_DATA
Definition: winhttp.h:497
#define HTTP_STATUS_SWITCH_PROTOCOLS
Definition: winhttp.h:300
#define WINHTTP_QUERY_CONTENT_TYPE
Definition: winhttp.h:361
#define ERROR_WINHTTP_SECURE_FAILURE
Definition: winhttp.h:271
#define WINHTTP_CALLBACK_STATUS_READ_COMPLETE
Definition: winhttp.h:461
#define WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP
Definition: winhttp.h:204
#define WINHTTP_AUTH_SCHEME_NEGOTIATE
Definition: winhttp.h:528
#define WINHTTP_AUTH_TARGET_SERVER
Definition: winhttp.h:530
#define WINHTTP_QUERY_LOCATION
Definition: winhttp.h:393
#define ERROR_WINHTTP_INCORRECT_HANDLE_STATE
Definition: winhttp.h:246
#define ERROR_WINHTTP_INVALID_OPTION
Definition: winhttp.h:240
#define WINHTTP_ADDREQ_FLAG_ADD
Definition: winhttp.h:92
#define WINHTTP_AUTH_SCHEME_DIGEST
Definition: winhttp.h:527
#define WINHTTP_QUERY_FLAG_NUMBER
Definition: winhttp.h:439
#define WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
Definition: winhttp.h:452
#define SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
Definition: winhttp.h:344
#define HTTP_STATUS_REDIRECT_KEEP_VERB
Definition: winhttp.h:315
#define ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND
Definition: winhttp.h:256
#define WINHTTP_FLAG_SECURE_PROTOCOL_SSL2
Definition: winhttp.h:514
@ WINHTTP_WEB_SOCKET_CLOSE_OPERATION
Definition: winhttp.h:782
@ WINHTTP_WEB_SOCKET_SHUTDOWN_OPERATION
Definition: winhttp.h:783
@ WINHTTP_WEB_SOCKET_RECEIVE_OPERATION
Definition: winhttp.h:781
@ WINHTTP_WEB_SOCKET_SEND_OPERATION
Definition: winhttp.h:780
#define WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM
Definition: winhttp.h:198
#define WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
Definition: winhttp.h:445
@ WINHTTP_WEB_SOCKET_CLOSE_BUFFER_TYPE
Definition: winhttp.h:792
@ WINHTTP_WEB_SOCKET_UTF8_FRAGMENT_BUFFER_TYPE
Definition: winhttp.h:791
@ WINHTTP_WEB_SOCKET_UTF8_MESSAGE_BUFFER_TYPE
Definition: winhttp.h:790
@ WINHTTP_WEB_SOCKET_BINARY_FRAGMENT_BUFFER_TYPE
Definition: winhttp.h:789
@ WINHTTP_WEB_SOCKET_BINARY_MESSAGE_BUFFER_TYPE
Definition: winhttp.h:788
#define WINHTTP_OPTION_AUTOLOGON_POLICY
Definition: winhttp.h:129
#define WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
Definition: winhttp.h:446
#define WINHTTP_QUERY_CUSTOM
Definition: winhttp.h:436
#define INTERNET_SCHEME_HTTP
Definition: winhttp.h:47
#define ERROR_WINHTTP_INCORRECT_HANDLE_TYPE
Definition: winhttp.h:245
#define WINHTTP_ACCESS_TYPE_NO_PROXY
Definition: winhttp.h:70
#define WINHTTP_QUERY_STATUS_TEXT
Definition: winhttp.h:380
#define API_RECEIVE_RESPONSE
Definition: winhttp.h:494
#define WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE
Definition: winhttp.h:464
#define WINHTTP_FLAG_ESCAPE_PERCENT
Definition: winhttp.h:61
enum _WINHTTP_WEB_SOCKET_BUFFER_TYPE WINHTTP_WEB_SOCKET_BUFFER_TYPE
#define WINHTTP_CALLBACK_STATUS_REQUEST_ERROR
Definition: winhttp.h:463
#define WINHTTP_FLAG_ASYNC
Definition: winhttp.h:58
#define WINHTTP_AUTH_TARGET_PROXY
Definition: winhttp.h:531
#define WINHTTP_FLAG_ESCAPE_DISABLE
Definition: winhttp.h:63
#define HTTP_STATUS_DENIED
Definition: winhttp.h:318
#define WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW
Definition: winhttp.h:199
#define WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
Definition: winhttp.h:443
#define API_SEND_REQUEST
Definition: winhttp.h:498
#define ERROR_WINHTTP_LOGIN_FAILURE
Definition: winhttp.h:243
#define WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE
Definition: winhttp.h:462
#define WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL
Definition: winhttp.h:162
#define WINHTTP_ADDREQ_FLAG_REPLACE
Definition: winhttp.h:96
#define ERROR_WINHTTP_HEADER_NOT_FOUND
Definition: winhttp.h:259
#define WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
Definition: winhttp.h:444
#define WINHTTP_QUERY_TRANSFER_ENCODING
Definition: winhttp.h:423
#define WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
Definition: winhttp.h:453
#define HTTP_STATUS_NOT_MODIFIED
Definition: winhttp.h:313
#define WINHTTP_QUERY_RAW_HEADERS_CRLF
Definition: winhttp.h:382
#define WINHTTP_FLAG_SECURE
Definition: winhttp.h:67
#define INTERNET_DEFAULT_HTTP_PORT
Definition: winhttp.h:41
#define WINHTTP_QUERY_REQUEST_METHOD
Definition: winhttp.h:405
#define WINHTTP_DISABLE_REDIRECTS
Definition: winhttp.h:215
#define ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND
Definition: winhttp.h:257
#define INTERNET_SCHEME_HTTPS
Definition: winhttp.h:48
#define WINHTTP_FLAG_REFRESH
Definition: winhttp.h:66
#define WINHTTP_FLAG_SECURE_PROTOCOL_SSL3
Definition: winhttp.h:515
#define HTTP_STATUS_REDIRECT
Definition: winhttp.h:311
#define HTTP_STATUS_MOVED
Definition: winhttp.h:310
#define WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2
Definition: winhttp.h:518
#define WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1
Definition: winhttp.h:517
#define WINHTTP_AUTH_SCHEME_NTLM
Definition: winhttp.h:525
#define SECURITY_FLAG_IGNORE_UNKNOWN_CA
Definition: winhttp.h:343
#define ERROR_WINHTTP_INVALID_HEADER
Definition: winhttp.h:261
#define WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA
Definition: winhttp.h:93
#define WINHTTP_DISABLE_COOKIES
Definition: winhttp.h:214
#define API_READ_DATA
Definition: winhttp.h:496
#define WINHTTP_QUERY_RAW_HEADERS
Definition: winhttp.h:381
#define SECURITY_FLAG_IGNORE_CERT_CN_INVALID
Definition: winhttp.h:345
#define ERROR_WINHTTP_REDIRECT_FAILED
Definition: winhttp.h:264
#define INTERNET_DEFAULT_HTTPS_PORT
Definition: winhttp.h:42
#define WINHTTP_FLAG_SECURE_PROTOCOL_TLS1
Definition: winhttp.h:516
@ REQUEST_RESPONSE_STATE_READ_RESPONSE_QUEUED_REQUEST_SENT
@ REQUEST_RESPONSE_STATE_SENDING_REQUEST
@ REQUEST_RESPONSE_STATE_READ_RESPONSE_QUEUED
@ REQUEST_RESPONSE_STATE_RESPONSE_RECEIVED
@ REQUEST_RESPONSE_RECURSIVE_REQUEST
@ REQUEST_RESPONSE_STATE_NONE
@ REQUEST_RESPONSE_STATE_REQUEST_SENT
@ REQUEST_RESPONSE_STATE_REPLY_RECEIVED
@ REQUEST_RESPONSE_STATE_READ_RESPONSE_QUEUED_REPLY_RECEIVED
fragment_type
@ SOCKET_FRAGMENT_UTF8
@ SOCKET_FRAGMENT_NONE
@ SOCKET_FRAGMENT_BINARY
socket_opcode
@ SOCKET_OPCODE_TEXT
@ SOCKET_OPCODE_PING
@ SOCKET_OPCODE_PONG
@ SOCKET_OPCODE_CONTINUE
@ SOCKET_OPCODE_BINARY
@ SOCKET_OPCODE_INVALID
@ SOCKET_OPCODE_CLOSE
socket_state
@ SOCKET_STATE_SHUTDOWN
@ SOCKET_STATE_OPEN
auth_target
@ TARGET_SERVER
@ TARGET_PROXY
@ REQUEST_FLAG_WEBSOCKET_UPGRADE
#define MIN_WEBSOCKET_SEND_BUFFER_SIZE
auth_scheme
@ SCHEME_BASIC
@ SCHEME_DIGEST
@ SCHEME_INVALID
@ SCHEME_NTLM
@ SCHEME_NEGOTIATE
void(* TASK_CALLBACK)(void *ctx, BOOL abort)
#define WINHTTP_HANDLE_TYPE_SOCKET
DWORD set_cookie(substr_t domain, substr_t path, substr_t name, substr_t data, DWORD flags)
Definition: cookie.c:912
#define RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO
Definition: winnt_old.h:1156
struct _TP_CALLBACK_INSTANCE TP_CALLBACK_INSTANCE
Definition: winnt_old.h:4676
#define WSA_IO_PENDING
Definition: winsock2.h:610
int PASCAL FAR WSAGetLastError(void)
Definition: dllmain.c:131
#define AF_INET6
Definition: winsock.h:363
BOOL WINAPI TranslateMessage(_In_ const MSG *)
#define QS_ALLINPUT
Definition: winuser.h:914
DWORD WINAPI MsgWaitForMultipleObjects(_In_ DWORD nCount, _In_reads_opt_(nCount) CONST HANDLE *pHandles, _In_ BOOL fWaitAll, _In_ DWORD dwMilliseconds, _In_ DWORD dwWakeMask)
BOOL WINAPI PeekMessageW(_Out_ LPMSG, _In_opt_ HWND, _In_ UINT, _In_ UINT, _In_ UINT)
#define PM_REMOVE
Definition: winuser.h:1207
LRESULT WINAPI DispatchMessageW(_In_ const MSG *)
SECURITY_STATUS WINAPI AcquireCredentialsHandleW(SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, ULONG fCredentialsUse, PLUID pvLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn, PVOID pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
Definition: wrapper.c:105
SECURITY_STATUS WINAPI InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR *pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry)
Definition: wrapper.c:301
SECURITY_STATUS WINAPI DeleteSecurityContext(PCtxtHandle phContext)
Definition: wrapper.c:450
SECURITY_STATUS WINAPI QuerySecurityPackageInfoW(SEC_WCHAR *pszPackageName, PSecPkgInfoW *ppPackageInfo)
Definition: wrapper.c:750
SECURITY_STATUS WINAPI FreeCredentialsHandle(PCredHandle phCredential)
Definition: wrapper.c:151
#define INET6_ADDRSTRLEN
Definition: ws2ipdef.h:132
#define RtlUlonglongByteSwap(_x)
Definition: rtlfuncs.h:3216
#define RtlUshortByteSwap(_x)
Definition: rtlfuncs.h:3214
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184