[WINHTTP] Sync with Wine Staging 4.18. CORE-16441
authorAmine Khaldi <amine.khaldi@reactos.org>
Sat, 7 Dec 2019 12:05:48 +0000 (13:05 +0100)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sat, 7 Dec 2019 12:05:48 +0000 (13:05 +0100)
dll/win32/winhttp/cookie.c
dll/win32/winhttp/handle.c
dll/win32/winhttp/main.c
dll/win32/winhttp/net.c
dll/win32/winhttp/request.c
dll/win32/winhttp/session.c
dll/win32/winhttp/url.c
dll/win32/winhttp/winhttp_private.h
media/doc/README.WINE

index b4b2530..40c11c6 100644 (file)
  */
 
 #include "config.h"
+#include "ws2tcpip.h"
 #include <stdarg.h>
 
-#include "wine/debug.h"
-#include "wine/list.h"
-
 #include "windef.h"
 #include "winbase.h"
 #include "winhttp.h"
 
+#include "wine/debug.h"
+#include "wine/list.h"
 #include "winhttp_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
 
-static domain_t *add_domain( session_t *session, WCHAR *name )
+struct cookie
+{
+    struct list entry;
+    WCHAR *name;
+    WCHAR *value;
+    WCHAR *path;
+};
+
+struct domain
+{
+    struct list entry;
+    WCHAR *name;
+    struct list cookies;
+};
+
+static struct domain *add_domain( struct session *session, WCHAR *name )
 {
-    domain_t *domain;
+    struct domain *domain;
 
-    if (!(domain = heap_alloc_zero( sizeof(domain_t) ))) return NULL;
+    if (!(domain = heap_alloc_zero( sizeof(struct domain) ))) return NULL;
 
     list_init( &domain->entry );
     list_init( &domain->cookies );
@@ -46,14 +61,14 @@ static domain_t *add_domain( session_t *session, WCHAR *name )
     return domain;
 }
 
-static cookie_t *find_cookie( domain_t *domain, const WCHAR *path, const WCHAR *name )
+static struct cookie *find_cookie( struct domain *domain, const WCHAR *path, const WCHAR *name )
 {
     struct list *item;
-    cookie_t *cookie;
+    struct cookie *cookie;
 
     LIST_FOR_EACH( item, &domain->cookies )
     {
-        cookie = LIST_ENTRY( item, cookie_t, entry );
+        cookie = LIST_ENTRY( item, struct cookie, entry );
         if (!strcmpW( cookie->path, path ) && !strcmpW( cookie->name, name ))
         {
             TRACE("found %s=%s\n", debugstr_w(cookie->name), debugstr_w(cookie->value));
@@ -63,7 +78,7 @@ static cookie_t *find_cookie( domain_t *domain, const WCHAR *path, const WCHAR *
     return NULL;
 }
 
-static BOOL domain_match( const WCHAR *name, domain_t *domain, BOOL partial )
+static BOOL domain_match( const WCHAR *name, struct domain *domain, BOOL partial )
 {
     TRACE("comparing %s with %s\n", debugstr_w(name), debugstr_w(domain->name));
 
@@ -72,7 +87,7 @@ static BOOL domain_match( const WCHAR *name, domain_t *domain, BOOL partial )
     return TRUE;
 }
 
-static void free_cookie( cookie_t *cookie )
+static void free_cookie( struct cookie *cookie )
 {
     heap_free( cookie->name );
     heap_free( cookie->value );
@@ -80,20 +95,20 @@ static void free_cookie( cookie_t *cookie )
     heap_free( cookie );
 }
 
-static void delete_cookie( cookie_t *cookie )
+static void delete_cookie( struct cookie *cookie )
 {
     list_remove( &cookie->entry );
     free_cookie( cookie );
 }
 
-void delete_domain( domain_t *domain )
+static void delete_domain( struct domain *domain )
 {
-    cookie_t *cookie;
+    struct cookie *cookie;
     struct list *item, *next;
 
     LIST_FOR_EACH_SAFE( item, next, &domain->cookies )
     {
-        cookie = LIST_ENTRY( item, cookie_t, entry );
+        cookie = LIST_ENTRY( item, struct cookie, entry );
         delete_cookie( cookie );
     }
 
@@ -102,35 +117,51 @@ void delete_domain( domain_t *domain )
     heap_free( domain );
 }
 
-static BOOL add_cookie( session_t *session, cookie_t *cookie, WCHAR *domain_name, WCHAR *path )
+void destroy_cookies( struct session *session )
+{
+    struct list *item, *next;
+    struct domain *domain;
+
+    LIST_FOR_EACH_SAFE( item, next, &session->cookie_cache )
+    {
+        domain = LIST_ENTRY( item, struct domain, entry );
+        delete_domain( domain );
+    }
+}
+
+static BOOL add_cookie( struct session *session, struct cookie *cookie, WCHAR *domain_name, WCHAR *path )
 {
-    domain_t *domain = NULL;
-    cookie_t *old_cookie;
+    struct domain *domain = NULL;
+    struct cookie *old_cookie;
     struct list *item;
 
+    if (!(cookie->path = strdupW( path ))) return FALSE;
+
+    EnterCriticalSection( &session->cs );
+
     LIST_FOR_EACH( item, &session->cookie_cache )
     {
-        domain = LIST_ENTRY( item, domain_t, entry );
+        domain = LIST_ENTRY( item, struct domain, entry );
         if (domain_match( domain_name, domain, FALSE )) break;
         domain = NULL;
     }
-    if (!domain)
-    {
-        if (!(domain = add_domain( session, domain_name ))) return FALSE;
-    }
+    if (!domain) domain = add_domain( session, domain_name );
     else if ((old_cookie = find_cookie( domain, path, cookie->name ))) delete_cookie( old_cookie );
 
-    cookie->path = strdupW( path );
-    list_add_head( &domain->cookies, &cookie->entry );
+    if (domain)
+    {
+        list_add_head( &domain->cookies, &cookie->entry );
+        TRACE("domain %s path %s <- %s=%s\n", debugstr_w(domain_name), debugstr_w(cookie->path),
+              debugstr_w(cookie->name), debugstr_w(cookie->value));
+    }
 
-    TRACE("domain %s path %s <- %s=%s\n", debugstr_w(domain_name), debugstr_w(cookie->path),
-          debugstr_w(cookie->name), debugstr_w(cookie->value));
-    return TRUE;
+    LeaveCriticalSection( &session->cs );
+    return domain != NULL;
 }
 
-static cookie_t *parse_cookie( const WCHAR *string )
+static struct cookie *parse_cookie( const WCHAR *string )
 {
-    cookie_t *cookie;
+    struct cookie *cookie;
     const WCHAR *p;
     int len;
 
@@ -139,7 +170,7 @@ static cookie_t *parse_cookie( const WCHAR *string )
     while (len && string[len - 1] == ' ') len--;
     if (!len) return NULL;
 
-    if (!(cookie = heap_alloc_zero( sizeof(cookie_t) ))) return NULL;
+    if (!(cookie = heap_alloc_zero( sizeof(struct cookie) ))) return NULL;
     list_init( &cookie->entry );
 
     if (!(cookie->name = heap_alloc( (len + 1) * sizeof(WCHAR) )))
@@ -229,7 +260,7 @@ static struct attr *parse_attr( const WCHAR *str, int *used )
     return attr;
 }
 
-BOOL set_cookies( request_t *request, const WCHAR *cookies )
+BOOL set_cookies( struct request *request, const WCHAR *cookies )
 {
     static const WCHAR pathW[] = {'p','a','t','h',0};
     static const WCHAR domainW[] = {'d','o','m','a','i','n',0};
@@ -237,8 +268,8 @@ BOOL set_cookies( request_t *request, const WCHAR *cookies )
     WCHAR *buffer, *p;
     WCHAR *cookie_domain = NULL, *cookie_path = NULL;
     struct attr *attr, *domain = NULL, *path = NULL;
-    session_t *session = request->connect->session;
-    cookie_t *cookie;
+    struct session *session = request->connect->session;
+    struct cookie *cookie;
     int len, used;
 
     len = strlenW( cookies );
@@ -290,14 +321,16 @@ end:
     return ret;
 }
 
-BOOL add_cookie_headers( request_t *request )
+BOOL add_cookie_headers( struct request *request )
 {
     struct list *domain_cursor;
-    session_t *session = request->connect->session;
+    struct session *session = request->connect->session;
+
+    EnterCriticalSection( &session->cs );
 
     LIST_FOR_EACH( domain_cursor, &session->cookie_cache )
     {
-        domain_t *domain = LIST_ENTRY( domain_cursor, domain_t, entry );
+        struct domain *domain = LIST_ENTRY( domain_cursor, struct domain, entry );
         if (domain_match( request->connect->servername, domain, TRUE ))
         {
             struct list *cookie_cursor;
@@ -305,19 +338,23 @@ BOOL add_cookie_headers( request_t *request )
 
             LIST_FOR_EACH( cookie_cursor, &domain->cookies )
             {
-                cookie_t *cookie = LIST_ENTRY( cookie_cursor, cookie_t, entry );
+                struct cookie *cookie = LIST_ENTRY( cookie_cursor, struct cookie, entry );
 
                 TRACE("comparing path %s with %s\n", debugstr_w(request->path), debugstr_w(cookie->path));
 
                 if (strstrW( request->path, cookie->path ) == request->path)
                 {
-                    const WCHAR cookieW[] = {'C','o','o','k','i','e',':',' '};
-                    int len, len_cookie = sizeof(cookieW) / sizeof(cookieW[0]), len_name = strlenW( cookie->name );
+                    static const WCHAR cookieW[] = {'C','o','o','k','i','e',':',' '};
+                    int len, len_cookie = ARRAY_SIZE( cookieW ), len_name = strlenW( cookie->name );
                     WCHAR *header;
 
                     len = len_cookie + len_name;
                     if (cookie->value) len += strlenW( cookie->value ) + 1;
-                    if (!(header = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return FALSE;
+                    if (!(header = heap_alloc( (len + 1) * sizeof(WCHAR) )))
+                    {
+                        LeaveCriticalSection( &session->cs );
+                        return FALSE;
+                    }
 
                     memcpy( header, cookieW, len_cookie * sizeof(WCHAR) );
                     strcpyW( header + len_cookie, cookie->name );
@@ -335,5 +372,7 @@ BOOL add_cookie_headers( request_t *request )
             }
         }
     }
+
+    LeaveCriticalSection( &session->cs );
     return TRUE;
 }
index 6026a49..6711cd9 100644 (file)
  */
 
 #include "config.h"
-#include "wine/port.h"
-#include "wine/debug.h"
-
+#include "ws2tcpip.h"
 #include <stdarg.h>
 
 #include "windef.h"
 #include "winbase.h"
 #include "winhttp.h"
 
+#include "wine/debug.h"
 #include "winhttp_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
@@ -43,20 +42,20 @@ static CRITICAL_SECTION_DEBUG handle_cs_debug =
 };
 static CRITICAL_SECTION handle_cs = { &handle_cs_debug, -1, 0, 0, 0, 0 };
 
-static object_header_t **handles;
+static struct object_header **handles;
 static ULONG_PTR next_handle;
 static ULONG_PTR max_handles;
 
-object_header_t *addref_object( object_header_t *hdr )
+struct object_header *addref_object( struct object_header *hdr )
 {
     ULONG refs = InterlockedIncrement( &hdr->refs );
     TRACE("%p -> refcount = %d\n", hdr, refs);
     return hdr;
 }
 
-object_header_t *grab_object( HINTERNET hinternet )
+struct object_header *grab_object( HINTERNET hinternet )
 {
-    object_header_t *hdr = NULL;
+    struct object_header *hdr = NULL;
     ULONG_PTR handle = (ULONG_PTR)hinternet;
 
     EnterCriticalSection( &handle_cs );
@@ -70,13 +69,13 @@ object_header_t *grab_object( HINTERNET hinternet )
     return hdr;
 }
 
-void release_object( object_header_t *hdr )
+void release_object( struct object_header *hdr )
 {
     ULONG refs = InterlockedDecrement( &hdr->refs );
     TRACE("object %p refcount = %d\n", hdr, refs);
     if (!refs)
     {
-        if (hdr->type == WINHTTP_HANDLE_TYPE_REQUEST) close_connection( (request_t *)hdr );
+        if (hdr->type == WINHTTP_HANDLE_TYPE_REQUEST) close_connection( (struct request *)hdr );
 
         send_callback( hdr, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, &hdr->handle, sizeof(HINTERNET) );
 
@@ -86,9 +85,9 @@ void release_object( object_header_t *hdr )
     }
 }
 
-HINTERNET alloc_handle( object_header_t *hdr )
+HINTERNET alloc_handle( struct object_header *hdr )
 {
-    object_header_t **p;
+    struct object_header **p;
     ULONG_PTR handle, num;
 
     list_init( &hdr->children );
@@ -125,7 +124,7 @@ BOOL free_handle( HINTERNET hinternet )
 {
     BOOL ret = FALSE;
     ULONG_PTR handle = (ULONG_PTR)hinternet;
-    object_header_t *hdr = NULL, *child, *next;
+    struct object_header *hdr = NULL, *child, *next;
 
     EnterCriticalSection( &handle_cs );
 
@@ -145,7 +144,7 @@ BOOL free_handle( HINTERNET hinternet )
 
     if (hdr)
     {
-        LIST_FOR_EACH_ENTRY_SAFE( child, next, &hdr->children, object_header_t, entry )
+        LIST_FOR_EACH_ENTRY_SAFE( child, next, &hdr->children, struct object_header, entry )
         {
             TRACE("freeing child handle %p for parent handle 0x%lx\n", child->handle, handle + 1);
             free_handle( child->handle );
index a63f28c..e6c084b 100644 (file)
@@ -18,6 +18,7 @@
 
 #define COBJMACROS
 #include "config.h"
+#include "ws2tcpip.h"
 #include <stdarg.h>
 
 #include "windef.h"
index e9ff86a..277a22e 100644 (file)
  */
 
 #include "config.h"
-#include "wine/port.h"
-
+#define NONAMELESSUNION
+#include "ws2tcpip.h"
 #include <stdarg.h>
 #include <stdio.h>
-#include <errno.h>
 #include <assert.h>
 
-#include <sys/types.h>
-#ifdef HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif
-#ifdef HAVE_SYS_FILIO_H
-# include <sys/filio.h>
-#endif
-#ifdef HAVE_POLL_H
-# include <poll.h>
-#endif
-
-#define NONAMELESSUNION
-
-#include "wine/debug.h"
-#include "wine/library.h"
-
 #include "windef.h"
 #include "winbase.h"
 #include "winhttp.h"
-#include "wincrypt.h"
 #include "schannel.h"
 
+#include "wine/debug.h"
+#include "wine/library.h"
 #include "winhttp_private.h"
 
-/* to avoid conflicts with the Unix socket headers */
-#define USE_WS_PREFIX
-#include "winsock2.h"
-
 WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
 
-#ifndef HAVE_GETADDRINFO
-
-/* critical section to protect non-reentrant gethostbyname() */
-static CRITICAL_SECTION cs_gethostbyname;
-static CRITICAL_SECTION_DEBUG critsect_debug =
-{
-    0, 0, &cs_gethostbyname,
-    { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
-      0, 0, { (DWORD_PTR)(__FILE__ ": cs_gethostbyname") }
-};
-static CRITICAL_SECTION cs_gethostbyname = { &critsect_debug, -1, 0, 0, 0, 0 };
-
-#endif
-
-/* translate a unix error code into a winsock error code */
-#ifndef __REACTOS__
-static int sock_get_error( int err )
-{
-#if !defined(__MINGW32__) && !defined (_MSC_VER)
-    switch (err)
-    {
-        case EINTR:             return WSAEINTR;
-        case EBADF:             return WSAEBADF;
-        case EPERM:
-        case EACCES:            return WSAEACCES;
-        case EFAULT:            return WSAEFAULT;
-        case EINVAL:            return WSAEINVAL;
-        case EMFILE:            return WSAEMFILE;
-        case EWOULDBLOCK:       return WSAEWOULDBLOCK;
-        case EINPROGRESS:       return WSAEINPROGRESS;
-        case EALREADY:          return WSAEALREADY;
-        case ENOTSOCK:          return WSAENOTSOCK;
-        case EDESTADDRREQ:      return WSAEDESTADDRREQ;
-        case EMSGSIZE:          return WSAEMSGSIZE;
-        case EPROTOTYPE:        return WSAEPROTOTYPE;
-        case ENOPROTOOPT:       return WSAENOPROTOOPT;
-        case EPROTONOSUPPORT:   return WSAEPROTONOSUPPORT;
-        case ESOCKTNOSUPPORT:   return WSAESOCKTNOSUPPORT;
-        case EOPNOTSUPP:        return WSAEOPNOTSUPP;
-        case EPFNOSUPPORT:      return WSAEPFNOSUPPORT;
-        case EAFNOSUPPORT:      return WSAEAFNOSUPPORT;
-        case EADDRINUSE:        return WSAEADDRINUSE;
-        case EADDRNOTAVAIL:     return WSAEADDRNOTAVAIL;
-        case ENETDOWN:          return WSAENETDOWN;
-        case ENETUNREACH:       return WSAENETUNREACH;
-        case ENETRESET:         return WSAENETRESET;
-        case ECONNABORTED:      return WSAECONNABORTED;
-        case EPIPE:
-        case ECONNRESET:        return WSAECONNRESET;
-        case ENOBUFS:           return WSAENOBUFS;
-        case EISCONN:           return WSAEISCONN;
-        case ENOTCONN:          return WSAENOTCONN;
-        case ESHUTDOWN:         return WSAESHUTDOWN;
-        case ETOOMANYREFS:      return WSAETOOMANYREFS;
-        case ETIMEDOUT:         return WSAETIMEDOUT;
-        case ECONNREFUSED:      return WSAECONNREFUSED;
-        case ELOOP:             return WSAELOOP;
-        case ENAMETOOLONG:      return WSAENAMETOOLONG;
-        case EHOSTDOWN:         return WSAEHOSTDOWN;
-        case EHOSTUNREACH:      return WSAEHOSTUNREACH;
-        case ENOTEMPTY:         return WSAENOTEMPTY;
-#ifdef EPROCLIM
-        case EPROCLIM:          return WSAEPROCLIM;
-#endif
-#ifdef EUSERS
-        case EUSERS:            return WSAEUSERS;
-#endif
-#ifdef EDQUOT
-        case EDQUOT:            return WSAEDQUOT;
-#endif
-#ifdef ESTALE
-        case ESTALE:            return WSAESTALE;
-#endif
-#ifdef EREMOTE
-        case EREMOTE:           return WSAEREMOTE;
-#endif
-    default: errno = err; perror( "sock_set_error" ); return WSAEFAULT;
-    }
-#endif
-    return err;
-}
-#else
-#define sock_get_error(x) WSAGetLastError()
-
-static inline int unix_ioctl(int filedes, long request, void *arg)
-{
-    return ioctlsocket(filedes, request, arg);
-}
-#define ioctlsocket unix_ioctl
-#endif
-
 static int sock_send(int fd, const void *msg, size_t len, int flags)
 {
     int ret;
     do
     {
-        if ((ret = send(fd, msg, len, flags)) == -1) WARN("send error %s\n", strerror(errno));
+        if ((ret = send(fd, msg, len, flags)) == -1) WARN("send error %u\n", WSAGetLastError());
     }
-    while(ret == -1 && errno == EINTR);
+    while(ret == -1 && WSAGetLastError() == WSAEINTR);
     return ret;
 }
 
@@ -165,13 +51,13 @@ static int sock_recv(int fd, void *msg, size_t len, int flags)
     int ret;
     do
     {
-        if ((ret = recv(fd, msg, len, flags)) == -1) WARN("recv error %s\n", strerror(errno));
+        if ((ret = recv(fd, msg, len, flags)) == -1) WARN("recv error %u\n", WSAGetLastError());
     }
-    while(ret == -1 && errno == EINTR);
+    while(ret == -1 && WSAGetLastError() == WSAEINTR);
     return ret;
 }
 
-static DWORD netconn_verify_cert( PCCERT_CONTEXT cert, WCHAR *server, DWORD security_flags )
+static DWORD netconn_verify_cert( PCCERT_CONTEXT cert, WCHAR *server, DWORD security_flags, BOOL check_revocation )
 {
     HCERTSTORE store = cert->hCertStore;
     BOOL ret;
@@ -184,9 +70,10 @@ static DWORD netconn_verify_cert( PCCERT_CONTEXT cert, WCHAR *server, DWORD secu
     TRACE("verifying %s\n", debugstr_w( server ));
     chainPara.RequestedUsage.Usage.cUsageIdentifier = 1;
     chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = server_auth;
-    if ((ret = CertGetCertificateChain( NULL, cert, NULL, store, &chainPara,
-                                        CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,
-                                        NULL, &chain )))
+    ret = CertGetCertificateChain( NULL, cert, NULL, store, &chainPara,
+                                   check_revocation ? CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT : 0,
+                                   NULL, &chain );
+    if (ret)
     {
         if (chain->TrustStatus.dwErrorStatus)
         {
@@ -264,46 +151,41 @@ static DWORD netconn_verify_cert( PCCERT_CONTEXT cert, WCHAR *server, DWORD secu
     return err;
 }
 
-#ifdef __REACTOS__
-static BOOL winsock_initialized = FALSE;
-BOOL netconn_init_winsock()
+static BOOL winsock_loaded;
+
+void netconn_unload( void )
 {
-    WSADATA wsaData;
-    int error;
-    if (!winsock_initialized)
-    {
-        error = WSAStartup(MAKEWORD(1, 1), &wsaData);
-        if (error)
-        {
-            ERR("WSAStartup failed: %d\n", error);
-            return FALSE;
-        }
-        else
-            winsock_initialized = TRUE;
-    }
-    return winsock_initialized;
+    if (winsock_loaded) WSACleanup();
+}
+
+static BOOL WINAPI winsock_startup( INIT_ONCE *once, void *param, void **ctx )
+{
+    int ret;
+    WSADATA data;
+    if (!(ret = WSAStartup( MAKEWORD(1,1), &data ))) winsock_loaded = TRUE;
+    else ERR( "WSAStartup failed: %d\n", ret );
+    return TRUE;
 }
 
-#endif
+static void winsock_init(void)
+{
+    static INIT_ONCE once = INIT_ONCE_STATIC_INIT;
+    InitOnceExecuteOnce( &once, winsock_startup, NULL, NULL );
+}
 
-void netconn_unload( void )
+static void set_blocking( struct netconn *conn, BOOL blocking )
 {
-#ifndef HAVE_GETADDRINFO
-    DeleteCriticalSection(&cs_gethostbyname);
-#endif
-#ifdef __REACTOS__
-    if(winsock_initialized)
-        WSACleanup();
-#endif
+    ULONG state = !blocking;
+    ioctlsocket( conn->socket, FIONBIO, &state );
 }
 
-netconn_t *netconn_create( hostdata_t *host, const struct sockaddr_storage *sockaddr, int timeout )
+struct netconn *netconn_create( struct hostdata *host, const struct sockaddr_storage *sockaddr, int timeout )
 {
-    netconn_t *conn;
+    struct netconn *conn;
     unsigned int addr_len;
     BOOL ret = FALSE;
-    int res;
-    ULONG state;
+
+    winsock_init();
 
     conn = heap_alloc_zero(sizeof(*conn));
     if (!conn) return NULL;
@@ -311,8 +193,7 @@ netconn_t *netconn_create( hostdata_t *host, const struct sockaddr_storage *sock
     conn->sockaddr = *sockaddr;
     if ((conn->socket = socket( sockaddr->ss_family, SOCK_STREAM, 0 )) == -1)
     {
-        WARN("unable to create socket (%s)\n", strerror(errno));
-        set_last_error( sock_get_error( errno ) );
+        WARN("unable to create socket (%u)\n", WSAGetLastError());
         heap_free(conn);
         return NULL;
     }
@@ -329,83 +210,39 @@ netconn_t *netconn_create( hostdata_t *host, const struct sockaddr_storage *sock
         assert(0);
     }
 
-    if (timeout > 0)
-    {
-        state = 1;
-        ioctlsocket( conn->socket, FIONBIO, &state );
-    }
+    if (timeout > 0) set_blocking( conn, FALSE );
 
-    for (;;)
+    if (!connect( conn->socket, (const struct sockaddr *)&conn->sockaddr, addr_len )) ret = TRUE;
+    else
     {
-        res = 0;
-        if (connect( conn->socket, (const struct sockaddr *)&conn->sockaddr, addr_len ) < 0)
-        {
-            res = sock_get_error( errno );
-            if (res == WSAEWOULDBLOCK || res == WSAEINPROGRESS)
-            {
-#ifdef __REACTOS__
-                /* ReactOS: use select instead of poll */
-                fd_set outfd;
-                struct timeval tv;
-
-                FD_ZERO(&outfd);
-                FD_SET(conn->socket, &outfd);
-
-                tv.tv_sec = 0;
-                tv.tv_usec = timeout * 1000;
-                for (;;)
-                {
-                    res = 0;
-
-                    if (select( 0, NULL, &outfd, NULL, &tv ) > 0)
-#else
-                struct pollfd pfd;
-
-                pfd.fd = conn->socket;
-                pfd.events = POLLOUT;
-                for (;;)
-                {
-                    res = 0;
-                    if (poll( &pfd, 1, timeout ) > 0)
-#endif
-                    {
-                        ret = TRUE;
-                        break;
-                    }
-                    else
-                    {
-                        res = sock_get_error( errno );
-                        if (res != WSAEINTR) break;
-                    }
-                }
-            }
-            if (res != WSAEINTR) break;
-        }
-        else
+        DWORD err = WSAGetLastError();
+        if (err == WSAEWOULDBLOCK || err == WSAEINPROGRESS)
         {
-            ret = TRUE;
-            break;
+            FD_SET set;
+            TIMEVAL timeval = { 0, timeout * 1000 };
+            int res;
+
+            FD_ZERO( &set );
+            FD_SET( conn->socket, &set );
+            if ((res = select( conn->socket + 1, NULL, &set, NULL, &timeval )) > 0) ret = TRUE;
+            else if (!res) SetLastError( ERROR_WINHTTP_TIMEOUT );
         }
     }
-    if (timeout > 0)
-    {
-        state = 0;
-        ioctlsocket( conn->socket, FIONBIO, &state );
-    }
+
+    if (timeout > 0) set_blocking( conn, TRUE );
+
     if (!ret)
     {
-        WARN("unable to connect to host (%d)\n", res);
-        set_last_error( res );
-        netconn_close( conn );
+        WARN("unable to connect to host (%u)\n", GetLastError());
+        closesocket( conn->socket );
+        heap_free( conn );
         return NULL;
     }
     return conn;
 }
 
-BOOL netconn_close( netconn_t *conn )
+void netconn_close( struct netconn *conn )
 {
-    int res;
-
     if (conn->secure)
     {
         heap_free( conn->peek_msg_mem );
@@ -413,18 +250,13 @@ BOOL netconn_close( netconn_t *conn )
         heap_free(conn->extra_buf);
         DeleteSecurityContext(&conn->ssl_ctx);
     }
-    res = closesocket( conn->socket );
+    closesocket( conn->socket );
     release_host( conn->host );
     heap_free(conn);
-    if (res == -1)
-    {
-        set_last_error( sock_get_error( errno ) );
-        return FALSE;
-    }
-    return TRUE;
 }
 
-BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD security_flags, CredHandle *cred_handle )
+BOOL netconn_secure_connect( struct netconn *conn, WCHAR *hostname, DWORD security_flags, CredHandle *cred_handle,
+                             BOOL check_revocation)
 {
     SecBuffer out_buf = {0, SECBUFFER_TOKEN, NULL}, in_bufs[2] = {{0, SECBUFFER_TOKEN}, {0, SECBUFFER_EMPTY}};
     SecBufferDesc out_desc = {SECBUFFER_VERSION, 1, &out_buf}, in_desc = {SECBUFFER_VERSION, 2, in_bufs};
@@ -520,7 +352,7 @@ BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD security_fl
 
             status = QueryContextAttributesW(&ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&cert);
             if(status == SEC_E_OK) {
-                res = netconn_verify_cert(cert, hostname, security_flags);
+                res = netconn_verify_cert(cert, hostname, security_flags, check_revocation);
                 CertFreeCertificateContext(cert);
                 if(res != ERROR_SUCCESS) {
                     WARN("cert verify failed: %u\n", res);
@@ -546,7 +378,7 @@ BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD security_fl
         heap_free(conn->ssl_buf);
         conn->ssl_buf = NULL;
         DeleteSecurityContext(&ctx);
-        set_last_error(res ? res : ERROR_WINHTTP_SECURE_CHANNEL_ERROR);
+        SetLastError(res ? res : ERROR_WINHTTP_SECURE_CHANNEL_ERROR);
         return FALSE;
     }
 
@@ -557,7 +389,7 @@ BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD security_fl
     return TRUE;
 }
 
-static BOOL send_ssl_chunk(netconn_t *conn, const void *msg, size_t size)
+static BOOL send_ssl_chunk(struct netconn *conn, const void *msg, size_t size)
 {
     SecBuffer bufs[4] = {
         {conn->ssl_sizes.cbHeader, SECBUFFER_STREAM_HEADER, conn->ssl_buf},
@@ -565,7 +397,7 @@ static BOOL send_ssl_chunk(netconn_t *conn, const void *msg, size_t size)
         {conn->ssl_sizes.cbTrailer, SECBUFFER_STREAM_TRAILER, conn->ssl_buf+conn->ssl_sizes.cbHeader+size},
         {0, SECBUFFER_EMPTY, NULL}
     };
-    SecBufferDesc buf_desc = {SECBUFFER_VERSION, sizeof(bufs)/sizeof(*bufs), bufs};
+    SecBufferDesc buf_desc = {SECBUFFER_VERSION, ARRAY_SIZE(bufs), bufs};
     SECURITY_STATUS res;
 
     memcpy(bufs[1].pvBuffer, msg, size);
@@ -583,7 +415,7 @@ static BOOL send_ssl_chunk(netconn_t *conn, const void *msg, size_t size)
     return TRUE;
 }
 
-BOOL netconn_send( netconn_t *conn, const void *msg, size_t len, int *sent )
+BOOL netconn_send( struct netconn *conn, const void *msg, size_t len, int *sent )
 {
     if (conn->secure)
     {
@@ -604,19 +436,14 @@ BOOL netconn_send( netconn_t *conn, const void *msg, size_t len, int *sent )
 
         return TRUE;
     }
-    if ((*sent = sock_send( conn->socket, msg, len, 0 )) == -1)
-    {
-        set_last_error( sock_get_error( errno ) );
-        return FALSE;
-    }
-    return TRUE;
+    return ((*sent = sock_send( conn->socket, msg, len, 0 )) != -1);
 }
 
-static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T buf_size, SIZE_T *ret_size, BOOL *eof)
+static BOOL read_ssl_chunk(struct netconn *conn, void *buf, SIZE_T buf_size, SIZE_T *ret_size, BOOL *eof)
 {
     const SIZE_T ssl_buf_size = conn->ssl_sizes.cbHeader+conn->ssl_sizes.cbMaximumMessage+conn->ssl_sizes.cbTrailer;
     SecBuffer bufs[4];
-    SecBufferDesc buf_desc = {SECBUFFER_VERSION, sizeof(bufs)/sizeof(*bufs), bufs};
+    SecBufferDesc buf_desc = {SECBUFFER_VERSION, ARRAY_SIZE(bufs), bufs};
     SSIZE_T size, buf_len;
     unsigned int i;
     SECURITY_STATUS res;
@@ -672,7 +499,7 @@ static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T buf_size, SIZE_T *
         }
     } while(res != SEC_E_OK);
 
-    for(i=0; i < sizeof(bufs)/sizeof(*bufs); i++) {
+    for(i = 0; i < ARRAY_SIZE(bufs); i++) {
         if(bufs[i].BufferType == SECBUFFER_DATA) {
             size = min(buf_size, bufs[i].cbBuffer);
             memcpy(buf, bufs[i].pvBuffer, size);
@@ -689,7 +516,7 @@ static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T buf_size, SIZE_T *
         }
     }
 
-    for(i=0; i < sizeof(bufs)/sizeof(*bufs); i++) {
+    for(i = 0; i < ARRAY_SIZE(bufs); i++) {
         if(bufs[i].BufferType == SECBUFFER_EXTRA) {
             conn->extra_buf = heap_alloc(bufs[i].cbBuffer);
             if(!conn->extra_buf)
@@ -703,7 +530,7 @@ static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T buf_size, SIZE_T *
     return TRUE;
 }
 
-BOOL netconn_recv( netconn_t *conn, void *buf, size_t len, int flags, int *recvd )
+BOOL netconn_recv( struct netconn *conn, void *buf, size_t len, int flags, int *recvd )
 {
     *recvd = 0;
     if (!len) return TRUE;
@@ -752,101 +579,64 @@ BOOL netconn_recv( netconn_t *conn, void *buf, size_t len, int flags, int *recvd
         *recvd = size;
         return TRUE;
     }
-    if ((*recvd = sock_recv( conn->socket, buf, len, flags )) == -1)
-    {
-        set_last_error( sock_get_error( errno ) );
-        return FALSE;
-    }
-    return TRUE;
+    return ((*recvd = sock_recv( conn->socket, buf, len, flags )) != -1);
 }
 
-ULONG netconn_query_data_available( netconn_t *conn )
+ULONG netconn_query_data_available( struct netconn *conn )
 {
     return conn->secure ? conn->peek_len : 0;
 }
 
-DWORD netconn_set_timeout( netconn_t *netconn, BOOL send, int value )
+DWORD netconn_set_timeout( struct netconn *netconn, BOOL send, int value )
 {
-    struct timeval tv;
-
-    /* value is in milliseconds, convert to struct timeval */
-    tv.tv_sec = value / 1000;
-    tv.tv_usec = (value % 1000) * 1000;
-
-    if (setsockopt( netconn->socket, SOL_SOCKET, send ? SO_SNDTIMEO : SO_RCVTIMEO, (void*)&tv, sizeof(tv) ) == -1)
+    int opt = send ? SO_SNDTIMEO : SO_RCVTIMEO;
+    if (setsockopt( netconn->socket, SOL_SOCKET, opt, (void *)&value, sizeof(value) ) == -1)
     {
-        WARN("setsockopt failed (%s)\n", strerror( errno ));
-        return sock_get_error( errno );
+        DWORD err = WSAGetLastError();
+        WARN("setsockopt failed (%u)\n", err );
+        return err;
     }
     return ERROR_SUCCESS;
 }
 
-BOOL netconn_is_alive( netconn_t *netconn )
+BOOL netconn_is_alive( struct netconn *netconn )
 {
-#ifdef MSG_DONTWAIT
-    ssize_t len;
-    BYTE b;
-
-    len = recv( netconn->socket, &b, 1, MSG_PEEK | MSG_DONTWAIT );
-    return len == 1 || (len == -1 && errno == EWOULDBLOCK);
-#elif defined(__MINGW32__) || defined(_MSC_VER)
-    ULONG mode;
     int len;
     char b;
+    DWORD err;
 
-    mode = 1;
-    if(!ioctlsocket(netconn->socket, FIONBIO, &mode))
-        return FALSE;
-
-    len = recv(netconn->socket, &b, 1, MSG_PEEK);
+    set_blocking( netconn, FALSE );
+    len = sock_recv( netconn->socket, &b, 1, MSG_PEEK );
+    err = WSAGetLastError();
+    set_blocking( netconn, TRUE );
 
-    mode = 0;
-    if(!ioctlsocket(netconn->socket, FIONBIO, &mode))
-        return FALSE;
-
-    return len == 1 || (len == -1 && WSAGetLastError() == WSAEWOULDBLOCK);
-#else
-    FIXME("not supported on this platform\n");
-    return TRUE;
-#endif
+    return len == 1 || (len == -1 && err == WSAEWOULDBLOCK);
 }
 
-static DWORD resolve_hostname( const WCHAR *hostnameW, INTERNET_PORT port, struct sockaddr_storage *sa )
+static DWORD resolve_hostname( const WCHAR *name, INTERNET_PORT port, struct sockaddr_storage *sa )
 {
-    char *hostname;
-#ifdef HAVE_GETADDRINFO
-    struct addrinfo *res, hints;
+    ADDRINFOW *res, hints;
     int ret;
-#else
-    struct hostent *he;
-    struct sockaddr_in *sin = (struct sockaddr_in *)sa;
-#endif
-
-    if (!(hostname = strdupWA( hostnameW ))) return ERROR_OUTOFMEMORY;
 
-#ifdef HAVE_GETADDRINFO
-    memset( &hints, 0, sizeof(struct addrinfo) );
+    memset( &hints, 0, sizeof(hints) );
     /* Prefer IPv4 to IPv6 addresses, since some web servers do not listen on
      * their IPv6 addresses even though they have IPv6 addresses in the DNS.
      */
     hints.ai_family = AF_INET;
 
-    ret = getaddrinfo( hostname, NULL, &hints, &res );
+    ret = GetAddrInfoW( name, NULL, &hints, &res );
     if (ret != 0)
     {
-        TRACE("failed to get IPv4 address of %s (%s), retrying with IPv6\n", debugstr_w(hostnameW), gai_strerror(ret));
+        TRACE("failed to get IPv4 address of %s, retrying with IPv6\n", debugstr_w(name));
         hints.ai_family = AF_INET6;
-        ret = getaddrinfo( hostname, NULL, &hints, &res );
+        ret = GetAddrInfoW( name, NULL, &hints, &res );
         if (ret != 0)
         {
-            TRACE("failed to get address of %s (%s)\n", debugstr_w(hostnameW), gai_strerror(ret));
-            heap_free( hostname );
+            TRACE("failed to get address of %s\n", debugstr_w(name));
             return ERROR_WINHTTP_NAME_NOT_RESOLVED;
         }
     }
-    heap_free( hostname );
     memcpy( sa, res->ai_addr, res->ai_addrlen );
-    /* Copy port */
     switch (res->ai_family)
     {
     case AF_INET:
@@ -857,29 +647,12 @@ static DWORD resolve_hostname( const WCHAR *hostnameW, INTERNET_PORT port, struc
         break;
     }
 
-    freeaddrinfo( res );
+    FreeAddrInfoW( res );
     return ERROR_SUCCESS;
-#else
-    EnterCriticalSection( &cs_gethostbyname );
-
-    he = gethostbyname( hostname );
-    heap_free( hostname );
-    if (!he)
-    {
-        TRACE("failed to get address of %s (%d)\n", debugstr_w(hostnameW), h_errno);
-        LeaveCriticalSection( &cs_gethostbyname );
-        return ERROR_WINHTTP_NAME_NOT_RESOLVED;
-    }
-    memset( sa, 0, sizeof(struct sockaddr_in) );
-    memcpy( &sin->sin_addr, he->h_addr, he->h_length );
-    sin->sin_family = he->h_addrtype;
-    sin->sin_port = htons( port );
-
-    LeaveCriticalSection( &cs_gethostbyname );
-    return ERROR_SUCCESS;
-#endif
 }
 
+#ifdef __REACTOS__
+
 struct resolve_args
 {
     const WCHAR             *hostname;
@@ -919,13 +692,64 @@ BOOL netconn_resolve( WCHAR *hostname, INTERNET_PORT port, struct sockaddr_stora
 
     if (ret)
     {
-        set_last_error( ret );
+        SetLastError( ret );
         return FALSE;
     }
     return TRUE;
 }
 
-const void *netconn_get_certificate( netconn_t *conn )
+#else /* __REACTOS__ */
+
+struct async_resolve
+{
+    const WCHAR             *hostname;
+    INTERNET_PORT            port;
+    struct sockaddr_storage *addr;
+    DWORD                    result;
+    HANDLE                   done;
+};
+
+static void CALLBACK resolve_proc( TP_CALLBACK_INSTANCE *instance, void *ctx )
+{
+    struct async_resolve *async = ctx;
+    async->result = resolve_hostname( async->hostname, async->port, async->addr );
+    SetEvent( async->done );
+}
+
+BOOL netconn_resolve( WCHAR *hostname, INTERNET_PORT port, struct sockaddr_storage *addr, int timeout )
+{
+    DWORD ret;
+
+    if (!timeout) ret = resolve_hostname( hostname, port, addr );
+    else
+    {
+        struct async_resolve async;
+
+        async.hostname = hostname;
+        async.port     = port;
+        async.addr     = addr;
+        if (!(async.done = CreateEventW( NULL, FALSE, FALSE, NULL ))) return FALSE;
+        if (!TrySubmitThreadpoolCallback( resolve_proc, &async, NULL ))
+        {
+            CloseHandle( async.done );
+            return FALSE;
+        }
+        if (WaitForSingleObject( async.done, timeout ) != WAIT_OBJECT_0) ret = ERROR_WINHTTP_TIMEOUT;
+        else ret = async.result;
+        CloseHandle( async.done );
+    }
+
+    if (ret)
+    {
+        SetLastError( ret );
+        return FALSE;
+    }
+    return TRUE;
+}
+
+#endif /* __REACTOS__ */
+
+const void *netconn_get_certificate( struct netconn *conn )
 {
     const CERT_CONTEXT *ret;
     SECURITY_STATUS res;
@@ -935,7 +759,7 @@ const void *netconn_get_certificate( netconn_t *conn )
     return res == SEC_E_OK ? ret : NULL;
 }
 
-int netconn_get_cipher_strength( netconn_t *conn )
+int netconn_get_cipher_strength( struct netconn *conn )
 {
     SecPkgContext_ConnectionInfo conn_info;
     SECURITY_STATUS res;
index 5bb5b09..da28f7b 100644 (file)
 
 #define COBJMACROS
 #include "config.h"
-#include "wine/port.h"
-
+#include "ws2tcpip.h"
 #include <stdarg.h>
 #include <assert.h>
-#ifdef HAVE_ARPA_INET_H
-# include <arpa/inet.h>
-#endif
 
 #include "windef.h"
 #include "winbase.h"
@@ -38,9 +34,8 @@
 #include "schannel.h"
 #include "winhttp.h"
 
-#include "winhttp_private.h"
-
 #include "wine/debug.h"
+#include "winhttp_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
 
@@ -186,13 +181,13 @@ static const WCHAR *attribute_table[] =
     NULL                            /* WINHTTP_QUERY_PASSPORT_CONFIG            = 78 */
 };
 
-static task_header_t *dequeue_task( request_t *request )
+static struct task_header *dequeue_task( struct request *request )
 {
-    task_header_t *task;
+    struct task_header *task;
 
     EnterCriticalSection( &request->task_cs );
     TRACE("%u tasks queued\n", list_count( &request->task_queue ));
-    task = LIST_ENTRY( list_head( &request->task_queue ), task_header_t, entry );
+    task = LIST_ENTRY( list_head( &request->task_queue ), struct task_header, entry );
     if (task) list_remove( &task->entry );
     LeaveCriticalSection( &request->task_cs );
 
@@ -200,9 +195,17 @@ static task_header_t *dequeue_task( request_t *request )
     return task;
 }
 
+#ifdef __REACTOS__
 static DWORD CALLBACK task_proc( LPVOID param )
+#else
+static void CALLBACK task_proc( TP_CALLBACK_INSTANCE *instance, void *ctx )
+#endif
 {
-    request_t *request = param;
+#ifdef __REACTOS__
+    struct request *request = param;
+#else
+    struct request *request = ctx;
+#endif
     HANDLE handles[2];
 
     handles[0] = request->task_wait;
@@ -214,7 +217,7 @@ static DWORD CALLBACK task_proc( LPVOID param )
         {
         case WAIT_OBJECT_0:
         {
-            task_header_t *task;
+            struct task_header *task;
             while ((task = dequeue_task( request )))
             {
                 task->proc( task );
@@ -230,21 +233,31 @@ static DWORD CALLBACK task_proc( LPVOID param )
             request->task_cs.DebugInfo->Spare[0] = 0;
             DeleteCriticalSection( &request->task_cs );
             request->hdr.vtbl->destroy( &request->hdr );
+#ifdef __REACTOS__
             return 0;
+#else
+            return;
+#endif
 
         default:
             ERR("wait failed %u (%u)\n", err, GetLastError());
             break;
         }
     }
+#ifdef __REACTOS__
     return 0;
+#endif
 }
 
-static BOOL queue_task( task_header_t *task )
+static BOOL queue_task( struct task_header *task )
 {
-    request_t *request = task->request;
+    struct request *request = task->request;
 
+#ifdef __REACTOS__
     if (!request->task_thread)
+#else
+    if (!request->task_wait)
+#endif
     {
         if (!(request->task_wait = CreateEventW( NULL, FALSE, FALSE, NULL ))) return FALSE;
         if (!(request->task_cancel = CreateEventW( NULL, FALSE, FALSE, NULL )))
@@ -253,7 +266,11 @@ static BOOL queue_task( task_header_t *task )
             request->task_wait = NULL;
             return FALSE;
         }
+#ifdef __REACTOS__
         if (!(request->task_thread = CreateThread( NULL, 0, task_proc, request, 0, NULL )))
+#else
+        if (!TrySubmitThreadpoolCallback( task_proc, request, NULL ))
+#endif
         {
             CloseHandle( request->task_wait );
             request->task_wait = NULL;
@@ -261,6 +278,9 @@ static BOOL queue_task( task_header_t *task )
             request->task_cancel = NULL;
             return FALSE;
         }
+#ifndef __REACTOS__
+        request->task_proc_running = TRUE;
+#endif
         InitializeCriticalSection( &request->task_cs );
         request->task_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": request.task_cs");
     }
@@ -274,7 +294,7 @@ static BOOL queue_task( task_header_t *task )
     return TRUE;
 }
 
-static void free_header( header_t *header )
+static void free_header( struct header *header )
 {
     heap_free( header->field );
     heap_free( header->value );
@@ -302,10 +322,10 @@ static BOOL valid_token_char( WCHAR c )
     }
 }
 
-static header_t *parse_header( LPCWSTR string )
+static struct header *parse_header( const WCHAR *string )
 {
     const WCHAR *p, *q;
-    header_t *header;
+    struct header *header;
     int len;
 
     p = string;
@@ -329,7 +349,7 @@ static header_t *parse_header( LPCWSTR string )
         p++;
     }
     len = q - string;
-    if (!(header = heap_alloc_zero( sizeof(header_t) ))) return NULL;
+    if (!(header = heap_alloc_zero( sizeof(struct header) ))) return NULL;
     if (!(header->field = heap_alloc( (len + 1) * sizeof(WCHAR) )))
     {
         heap_free( header );
@@ -353,7 +373,7 @@ static header_t *parse_header( LPCWSTR string )
     return header;
 }
 
-static int get_header_index( request_t *request, LPCWSTR field, int requested_index, BOOL request_only )
+static int get_header_index( struct request *request, const WCHAR *field, int requested_index, BOOL request_only )
 {
     int index;
 
@@ -373,15 +393,15 @@ static int get_header_index( request_t *request, LPCWSTR field, int requested_in
     return index;
 }
 
-static BOOL insert_header( request_t *request, header_t *header )
+static BOOL insert_header( struct request *request, struct header *header )
 {
     DWORD count = request->num_headers + 1;
-    header_t *hdrs;
+    struct header *hdrs;
 
     if (request->headers)
-        hdrs = heap_realloc_zero( request->headers, sizeof(header_t) * count );
+        hdrs = heap_realloc_zero( request->headers, sizeof(struct header) * count );
     else
-        hdrs = heap_alloc_zero( sizeof(header_t) );
+        hdrs = heap_alloc_zero( sizeof(struct header) );
     if (!hdrs) return FALSE;
 
     request->headers = hdrs;
@@ -392,7 +412,7 @@ static BOOL insert_header( request_t *request, header_t *header )
     return TRUE;
 }
 
-static BOOL delete_header( request_t *request, DWORD index )
+static BOOL delete_header( struct request *request, DWORD index )
 {
     if (!request->num_headers) return FALSE;
     if (index >= request->num_headers) return FALSE;
@@ -401,15 +421,16 @@ static BOOL delete_header( request_t *request, DWORD index )
     heap_free( request->headers[index].field );
     heap_free( request->headers[index].value );
 
-    memmove( &request->headers[index], &request->headers[index + 1], (request->num_headers - index) * sizeof(header_t) );
-    memset( &request->headers[request->num_headers], 0, sizeof(header_t) );
+    memmove( &request->headers[index], &request->headers[index + 1],
+             (request->num_headers - index) * sizeof(struct header) );
+    memset( &request->headers[request->num_headers], 0, sizeof(struct header) );
     return TRUE;
 }
 
-BOOL process_header( request_t *request, LPCWSTR field, LPCWSTR value, DWORD flags, BOOL request_only )
+BOOL process_header( struct request *request, const WCHAR *field, const WCHAR *value, DWORD flags, BOOL request_only )
 {
     int index;
-    header_t hdr;
+    struct header hdr;
 
     TRACE("%s: %s 0x%08x\n", debugstr_w(field), debugstr_w(value), flags);
 
@@ -427,7 +448,7 @@ BOOL process_header( request_t *request, LPCWSTR field, LPCWSTR value, DWORD fla
         }
         else if (!(flags & WINHTTP_ADDREQ_FLAG_ADD))
         {
-            set_last_error( ERROR_WINHTTP_HEADER_NOT_FOUND );
+            SetLastError( ERROR_WINHTTP_HEADER_NOT_FOUND );
             return FALSE;
         }
 
@@ -444,7 +465,7 @@ BOOL process_header( request_t *request, LPCWSTR field, LPCWSTR value, DWORD fla
         {
             WCHAR *tmp;
             int len, len_orig, len_value;
-            header_t *header = &request->headers[index];
+            struct header *header = &request->headers[index];
 
             len_orig = strlenW( header->value );
             len_value = strlenW( value );
@@ -471,11 +492,11 @@ BOOL process_header( request_t *request, LPCWSTR field, LPCWSTR value, DWORD fla
     return TRUE;
 }
 
-BOOL add_request_headers( request_t *request, LPCWSTR headers, DWORD len, DWORD flags )
+BOOL add_request_headers( struct request *request, const WCHAR *headers, DWORD len, DWORD flags )
 {
     BOOL ret = FALSE;
     WCHAR *buffer, *p, *q;
-    header_t *header;
+    struct header *header;
 
     if (len == ~0u) len = strlenW( headers );
     if (!len) return TRUE;
@@ -521,134 +542,116 @@ BOOL add_request_headers( request_t *request, LPCWSTR headers, DWORD len, DWORD
 BOOL WINAPI WinHttpAddRequestHeaders( HINTERNET hrequest, LPCWSTR headers, DWORD len, DWORD flags )
 {
     BOOL ret;
-    request_t *request;
+    struct request *request;
 
     TRACE("%p, %s, %u, 0x%08x\n", hrequest, debugstr_wn(headers, len), len, flags);
 
     if (!headers || !len)
     {
-        set_last_error( ERROR_INVALID_PARAMETER );
+        SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
-    if (!(request = (request_t *)grab_object( hrequest )))
+    if (!(request = (struct request *)grab_object( hrequest )))
     {
-        set_last_error( ERROR_INVALID_HANDLE );
+        SetLastError( ERROR_INVALID_HANDLE );
         return FALSE;
     }
     if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST)
     {
         release_object( &request->hdr );
-        set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+        SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
         return FALSE;
     }
 
     ret = add_request_headers( request, headers, len, flags );
 
     release_object( &request->hdr );
-    if (ret) set_last_error( ERROR_SUCCESS );
+    if (ret) SetLastError( ERROR_SUCCESS );
     return ret;
 }
 
-static WCHAR *build_request_path( request_t *request )
+static WCHAR *build_absolute_request_path( struct request *request, const WCHAR **path )
 {
+    static const WCHAR http[] = {'h','t','t','p',0};
+    static const WCHAR https[] = {'h','t','t','p','s',0};
+    static const WCHAR fmt[] = {'%','s',':','/','/','%','s',0};
+    const WCHAR *scheme;
     WCHAR *ret;
+    int len;
 
-    if (strcmpiW( request->connect->hostname, request->connect->servername ))
-    {
-        static const WCHAR http[] = { 'h','t','t','p',0 };
-        static const WCHAR https[] = { 'h','t','t','p','s',0 };
-        static const WCHAR fmt[] = { '%','s',':','/','/','%','s',0 };
-        LPCWSTR scheme = (request->netconn ? request->netconn->secure : (request->hdr.flags & WINHTTP_FLAG_SECURE)) ? https : http;
-        int len;
+    scheme = (request->netconn ? request->netconn->secure : (request->hdr.flags & WINHTTP_FLAG_SECURE)) ? https : http;
+
+    len = strlenW( scheme ) + strlenW( request->connect->hostname ) + 4; /* '://' + nul */
+    if (request->connect->hostport) len += 6; /* ':' between host and port, up to 5 for port */
 
-        len = strlenW( scheme ) + strlenW( request->connect->hostname );
-        /* 3 characters for '://', 1 for NUL. */
-        len += 4;
+    len += strlenW( request->path );
+    if ((ret = heap_alloc( len * sizeof(WCHAR) )))
+    {
+        len = sprintfW( ret, fmt, scheme, request->connect->hostname );
         if (request->connect->hostport)
         {
-            /* 1 for ':' between host and port, up to 5 for port */
-            len += 6;
-        }
-        if (request->path)
-            len += strlenW( request->path );
-        if ((ret = heap_alloc( len * sizeof(WCHAR) )))
-        {
-            sprintfW( ret, fmt, scheme, request->connect->hostname );
-            if (request->connect->hostport)
-            {
-                static const WCHAR colonFmt[] = { ':','%','u',0 };
-
-                sprintfW( ret + strlenW( ret ), colonFmt,
-                    request->connect->hostport );
-            }
-            if (request->path)
-                strcatW( ret, request->path );
+            static const WCHAR port_fmt[] = {':','%','u',0};
+            len += sprintfW( ret + len, port_fmt, request->connect->hostport );
         }
+        strcpyW( ret + len, request->path );
+        if (path) *path = ret + len;
     }
-    else
-        ret = request->path;
+
     return ret;
 }
 
-static WCHAR *build_request_string( request_t *request )
+static WCHAR *build_request_string( struct request *request )
 {
-    static const WCHAR space[]   = {' ',0};
-    static const WCHAR crlf[]    = {'\r','\n',0};
-    static const WCHAR colon[]   = {':',' ',0};
-    static const WCHAR twocrlf[] = {'\r','\n','\r','\n',0};
-
+    static const WCHAR spaceW[] = {' ',0}, crlfW[] = {'\r','\n',0}, colonW[] = {':',' ',0};
+    static const WCHAR twocrlfW[] = {'\r','\n','\r','\n',0};
     WCHAR *path, *ret;
-    const WCHAR **headers, **p;
-    unsigned int len, i = 0, j;
+    unsigned int i, len;
 
-    /* allocate space for an array of all the string pointers to be added */
-    len = request->num_headers * 4 + 7;
-    if (!(headers = heap_alloc( len * sizeof(LPCWSTR) ))) return NULL;
+    if (!strcmpiW( request->connect->hostname, request->connect->servername )) path = request->path;
+    else if (!(path = build_absolute_request_path( request, NULL ))) return NULL;
 
-    path = build_request_path( request );
-    headers[i++] = request->verb;
-    headers[i++] = space;
-    headers[i++] = path;
-    headers[i++] = space;
-    headers[i++] = request->version;
+    len = strlenW( request->verb ) + 1 /* ' ' */;
+    len += strlenW( path ) + 1 /* ' ' */;
+    len += strlenW( request->version );
 
-    for (j = 0; j < request->num_headers; j++)
+    for (i = 0; i < request->num_headers; i++)
     {
-        if (request->headers[j].is_request)
-        {
-            headers[i++] = crlf;
-            headers[i++] = request->headers[j].field;
-            headers[i++] = colon;
-            headers[i++] = request->headers[j].value;
-
-            TRACE("adding header %s (%s)\n", debugstr_w(request->headers[j].field),
-                  debugstr_w(request->headers[j].value));
-        }
+        if (request->headers[i].is_request)
+            len += strlenW( request->headers[i].field ) + strlenW( request->headers[i].value ) + 4; /* '\r\n: ' */
     }
-    headers[i++] = twocrlf;
-    headers[i] = NULL;
+    len += 4; /* '\r\n\r\n' */
 
-    len = 0;
-    for (p = headers; *p; p++) len += strlenW( *p );
-    len++;
+    if ((ret = heap_alloc( (len + 1) * sizeof(WCHAR) )))
+    {
+        strcpyW( ret, request->verb );
+        strcatW( ret, spaceW );
+        strcatW( ret, path );
+        strcatW( ret, spaceW );
+        strcatW( ret, request->version );
 
-    if (!(ret = heap_alloc( len * sizeof(WCHAR) )))
-        goto out;
-    *ret = 0;
-    for (p = headers; *p; p++) strcatW( ret, *p );
+        for (i = 0; i < request->num_headers; i++)
+        {
+            if (request->headers[i].is_request)
+            {
+                strcatW( ret, crlfW );
+                strcatW( ret, request->headers[i].field );
+                strcatW( ret, colonW );
+                strcatW( ret, request->headers[i].value );
+            }
+        }
+        strcatW( ret, twocrlfW );
+    }
 
-out:
-    if (path != request->path)
-        heap_free( path );
-    heap_free( headers );
+    if (path != request->path) heap_free( path );
     return ret;
 }
 
 #define QUERY_MODIFIER_MASK (WINHTTP_QUERY_FLAG_REQUEST_HEADERS | WINHTTP_QUERY_FLAG_SYSTEMTIME | WINHTTP_QUERY_FLAG_NUMBER)
 
-static BOOL query_headers( request_t *request, DWORD level, LPCWSTR name, LPVOID buffer, LPDWORD buflen, LPDWORD index )
+static BOOL query_headers( struct request *request, DWORD level, const WCHAR *name, void *buffer, DWORD *buflen,
+                           DWORD *index )
 {
-    header_t *header = NULL;
+    struct header *header = NULL;
     BOOL request_only, ret = FALSE;
     int requested_index, header_index = -1;
     DWORD attr, len;
@@ -677,7 +680,7 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR name, LPVOID
         for (len = 0; *p; p++) if (*p != '\r') len++;
 
         if (!buffer || len * sizeof(WCHAR) > *buflen)
-            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
         else
         {
             for (p = headers, q = buffer; *p; p++, q++)
@@ -711,7 +714,7 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR name, LPVOID
         if (!buffer || len + sizeof(WCHAR) > *buflen)
         {
             len += sizeof(WCHAR);
-            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
         }
         else
         {
@@ -728,7 +731,7 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR name, LPVOID
         if (!buffer || len + sizeof(WCHAR) > *buflen)
         {
             len += sizeof(WCHAR);
-            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
         }
         else
         {
@@ -744,7 +747,7 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR name, LPVOID
         if (!buffer || len + sizeof(WCHAR) > *buflen)
         {
             len += sizeof(WCHAR);
-            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
         }
         else
         {
@@ -755,10 +758,32 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR name, LPVOID
         *buflen = len;
         return ret;
 
+    case WINHTTP_QUERY_REQUEST_METHOD:
+        len = strlenW( request->verb ) * sizeof(WCHAR);
+        if (!buffer || len + sizeof(WCHAR) > *buflen)
+        {
+            len += sizeof(WCHAR);
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
+        }
+        else
+        {
+            strcpyW( buffer, request->verb );
+            TRACE("returning string: %s\n", debugstr_w(buffer));
+            ret = TRUE;
+        }
+        *buflen = len;
+        return ret;
+
     default:
-        if (attr >= sizeof(attribute_table)/sizeof(attribute_table[0]) || !attribute_table[attr])
+        if (attr >= ARRAY_SIZE(attribute_table))
+        {
+            SetLastError( ERROR_INVALID_PARAMETER );
+            return FALSE;
+        }
+        if (!attribute_table[attr])
         {
             FIXME("attribute %u not implemented\n", attr);
+            SetLastError( ERROR_WINHTTP_HEADER_NOT_FOUND );
             return FALSE;
         }
         TRACE("attribute %s\n", debugstr_w(attribute_table[attr]));
@@ -772,15 +797,14 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR name, LPVOID
     }
     if (!header || (request_only && !header->is_request))
     {
-        set_last_error( ERROR_WINHTTP_HEADER_NOT_FOUND );
+        SetLastError( ERROR_WINHTTP_HEADER_NOT_FOUND );
         return FALSE;
     }
-    if (index) *index += 1;
     if (level & WINHTTP_QUERY_FLAG_NUMBER)
     {
         if (!buffer || sizeof(int) > *buflen)
         {
-            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
         }
         else
         {
@@ -796,7 +820,7 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR name, LPVOID
         SYSTEMTIME *st = buffer;
         if (!buffer || sizeof(SYSTEMTIME) > *buflen)
         {
-            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
         }
         else if ((ret = WinHttpTimeToSystemTime( header->value, st )))
         {
@@ -812,7 +836,7 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR name, LPVOID
         if (!buffer || len + sizeof(WCHAR) > *buflen)
         {
             len += sizeof(WCHAR);
-            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
         }
         else
         {
@@ -822,6 +846,7 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR name, LPVOID
         }
         *buflen = len;
     }
+    if (ret && index) *index += 1;
     return ret;
 }
 
@@ -831,32 +856,29 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR name, LPVOID
 BOOL WINAPI WinHttpQueryHeaders( HINTERNET hrequest, DWORD level, LPCWSTR name, LPVOID buffer, LPDWORD buflen, LPDWORD index )
 {
     BOOL ret;
-    request_t *request;
+    struct request *request;
 
     TRACE("%p, 0x%08x, %s, %p, %p, %p\n", hrequest, level, debugstr_w(name), buffer, buflen, index);
 
-    if (!(request = (request_t *)grab_object( hrequest )))
+    if (!(request = (struct request *)grab_object( hrequest )))
     {
-        set_last_error( ERROR_INVALID_HANDLE );
+        SetLastError( ERROR_INVALID_HANDLE );
         return FALSE;
     }
     if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST)
     {
         release_object( &request->hdr );
-        set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+        SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
         return FALSE;
     }
 
     ret = query_headers( request, level, name, buffer, buflen, index );
 
     release_object( &request->hdr );
-    if (ret) set_last_error( ERROR_SUCCESS );
+    if (ret) SetLastError( ERROR_SUCCESS );
     return ret;
 }
 
-#undef ARRAYSIZE
-#define ARRAYSIZE(array) (sizeof(array) / sizeof((array)[0]))
-
 static const WCHAR basicW[]     = {'B','a','s','i','c',0};
 static const WCHAR ntlmW[]      = {'N','T','L','M',0};
 static const WCHAR passportW[]  = {'P','a','s','s','p','o','r','t',0};
@@ -871,27 +893,26 @@ static const struct
 }
 auth_schemes[] =
 {
-    { basicW,     ARRAYSIZE(basicW) - 1,     WINHTTP_AUTH_SCHEME_BASIC },
-    { ntlmW,      ARRAYSIZE(ntlmW) - 1,      WINHTTP_AUTH_SCHEME_NTLM },
-    { passportW,  ARRAYSIZE(passportW) - 1,  WINHTTP_AUTH_SCHEME_PASSPORT },
-    { digestW,    ARRAYSIZE(digestW) - 1,    WINHTTP_AUTH_SCHEME_DIGEST },
-    { negotiateW, ARRAYSIZE(negotiateW) - 1, WINHTTP_AUTH_SCHEME_NEGOTIATE }
+    { basicW,     ARRAY_SIZE(basicW) - 1,     WINHTTP_AUTH_SCHEME_BASIC },
+    { ntlmW,      ARRAY_SIZE(ntlmW) - 1,      WINHTTP_AUTH_SCHEME_NTLM },
+    { passportW,  ARRAY_SIZE(passportW) - 1,  WINHTTP_AUTH_SCHEME_PASSPORT },
+    { digestW,    ARRAY_SIZE(digestW) - 1,    WINHTTP_AUTH_SCHEME_DIGEST },
+    { negotiateW, ARRAY_SIZE(negotiateW) - 1, WINHTTP_AUTH_SCHEME_NEGOTIATE }
 };
-static const unsigned int num_auth_schemes = sizeof(auth_schemes)/sizeof(auth_schemes[0]);
 
 static enum auth_scheme scheme_from_flag( DWORD flag )
 {
     int i;
 
-    for (i = 0; i < num_auth_schemes; i++) if (flag == auth_schemes[i].scheme) return i;
+    for (i = 0; i < ARRAY_SIZE( auth_schemes ); i++) if (flag == auth_schemes[i].scheme) return i;
     return SCHEME_INVALID;
 }
 
-static DWORD auth_scheme_from_header( WCHAR *header )
+static DWORD auth_scheme_from_header( const WCHAR *header )
 {
     unsigned int i;
 
-    for (i = 0; i < num_auth_schemes; i++)
+    for (i = 0; i < ARRAY_SIZE( auth_schemes ); i++)
     {
         if (!strncmpiW( header, auth_schemes[i].str, auth_schemes[i].len ) &&
             (header[auth_schemes[i].len] == ' ' || !header[auth_schemes[i].len])) return auth_schemes[i].scheme;
@@ -899,7 +920,7 @@ static DWORD auth_scheme_from_header( WCHAR *header )
     return 0;
 }
 
-static BOOL query_auth_schemes( request_t *request, DWORD level, LPDWORD supported, LPDWORD first )
+static BOOL query_auth_schemes( struct request *request, DWORD level, DWORD *supported, DWORD *first )
 {
     DWORD index = 0, supported_schemes = 0, first_scheme = 0;
     BOOL ret = FALSE;
@@ -911,9 +932,8 @@ static BOOL query_auth_schemes( request_t *request, DWORD level, LPDWORD support
 
         size = 0;
         query_headers( request, level, NULL, NULL, &size, &index );
-        if (get_last_error() != ERROR_INSUFFICIENT_BUFFER) break;
+        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) break;
 
-        index--;
         if (!(buffer = heap_alloc( size ))) return FALSE;
         if (!query_headers( request, level, NULL, buffer, &size, &index ))
         {
@@ -944,25 +964,25 @@ static BOOL query_auth_schemes( request_t *request, DWORD level, LPDWORD support
 BOOL WINAPI WinHttpQueryAuthSchemes( HINTERNET hrequest, LPDWORD supported, LPDWORD first, LPDWORD target )
 {
     BOOL ret = FALSE;
-    request_t *request;
+    struct request *request;
 
     TRACE("%p, %p, %p, %p\n", hrequest, supported, first, target);
 
-    if (!(request = (request_t *)grab_object( hrequest )))
+    if (!(request = (struct request *)grab_object( hrequest )))
     {
-        set_last_error( ERROR_INVALID_HANDLE );
+        SetLastError( ERROR_INVALID_HANDLE );
         return FALSE;
     }
     if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST)
     {
         release_object( &request->hdr );
-        set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+        SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
         return FALSE;
     }
     if (!supported || !first || !target)
     {
         release_object( &request->hdr );
-        set_last_error( ERROR_INVALID_PARAMETER );
+        SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
 
     }
@@ -977,9 +997,10 @@ BOOL WINAPI WinHttpQueryAuthSchemes( HINTERNET hrequest, LPDWORD supported, LPDW
         *target = WINHTTP_AUTH_TARGET_PROXY;
         ret = TRUE;
     }
+    else SetLastError( ERROR_INVALID_OPERATION );
 
     release_object( &request->hdr );
-    if (ret) set_last_error( ERROR_SUCCESS );
+    if (ret) SetLastError( ERROR_SUCCESS );
     return ret;
 }
 
@@ -1127,7 +1148,7 @@ void destroy_authinfo( struct authinfo *authinfo )
     heap_free( authinfo );
 }
 
-static BOOL get_authvalue( request_t *request, DWORD level, DWORD scheme, WCHAR *buffer, DWORD len )
+static BOOL get_authvalue( struct request *request, DWORD level, DWORD scheme, WCHAR *buffer, DWORD len )
 {
     DWORD size, index = 0;
     for (;;)
@@ -1139,7 +1160,7 @@ static BOOL get_authvalue( request_t *request, DWORD level, DWORD scheme, WCHAR
     return TRUE;
 }
 
-static BOOL do_authorization( request_t *request, DWORD target, DWORD scheme_flag )
+static BOOL do_authorization( struct request *request, DWORD target, DWORD scheme_flag )
 {
     struct authinfo *authinfo, **auth_ptr;
     enum auth_scheme scheme = scheme_from_flag( scheme_flag );
@@ -1368,129 +1389,76 @@ static BOOL do_authorization( request_t *request, DWORD target, DWORD scheme_fla
     return ret;
 }
 
-static LPWSTR concatenate_string_list( LPCWSTR *list, int len )
+static WCHAR *build_proxy_connect_string( struct request *request )
 {
-    LPCWSTR *t;
-    LPWSTR str;
-
-    for( t = list; *t ; t++  )
-        len += strlenW( *t );
-    len++;
-
-    str = heap_alloc( len * sizeof(WCHAR) );
-    if (!str) return NULL;
-    *str = 0;
+    static const WCHAR fmtW[] = {'%','s',':','%','u',0};
+    static const WCHAR connectW[] = {'C','O','N','N','E','C','T', 0};
+    static const WCHAR spaceW[] = {' ',0}, crlfW[] = {'\r','\n',0}, colonW[] = {':',' ',0};
+    static const WCHAR twocrlfW[] = {'\r','\n','\r','\n',0};
+    WCHAR *ret, *host;
+    unsigned int i;
+    int len;
 
-    for( t = list; *t ; t++ )
-        strcatW( str, *t );
+    if (!(host = heap_alloc( (strlenW( request->connect->hostname ) + 7) * sizeof(WCHAR) ))) return NULL;
+    len = sprintfW( host, fmtW, request->connect->hostname, request->connect->hostport );
 
-    return str;
-}
+    len += ARRAY_SIZE(connectW);
+    len += ARRAY_SIZE(http1_1);
 
-static LPWSTR build_header_request_string( request_t *request, LPCWSTR verb,
-    LPCWSTR path, LPCWSTR version )
-{
-    static const WCHAR crlf[] = {'\r','\n',0};
-    static const WCHAR space[] = { ' ',0 };
-    static const WCHAR colon[] = { ':',' ',0 };
-    static const WCHAR twocrlf[] = {'\r','\n','\r','\n', 0};
-    LPWSTR requestString;
-    DWORD len, n;
-    LPCWSTR *req;
-    UINT i;
-    LPWSTR p;
-
-    /* allocate space for an array of all the string pointers to be added */
-    len = (request->num_headers) * 4 + 10;
-    req = heap_alloc( len * sizeof(LPCWSTR) );
-    if (!req) return NULL;
-
-    /* add the verb, path and HTTP version string */
-    n = 0;
-    req[n++] = verb;
-    req[n++] = space;
-    req[n++] = path;
-    req[n++] = space;
-    req[n++] = version;
-
-    /* Append custom request headers */
     for (i = 0; i < request->num_headers; i++)
     {
         if (request->headers[i].is_request)
-        {
-            req[n++] = crlf;
-            req[n++] = request->headers[i].field;
-            req[n++] = colon;
-            req[n++] = request->headers[i].value;
-
-            TRACE("Adding custom header %s (%s)\n",
-                   debugstr_w(request->headers[i].field),
-                   debugstr_w(request->headers[i].value));
-        }
+            len += strlenW( request->headers[i].field ) + strlenW( request->headers[i].value ) + 4; /* '\r\n: ' */
     }
+    len += 4; /* '\r\n\r\n' */
 
-    if( n >= len )
-        ERR("oops. buffer overrun\n");
-
-    req[n] = NULL;
-    requestString = concatenate_string_list( req, 4 );
-    heap_free( req );
-    if (!requestString) return NULL;
+    if ((ret = heap_alloc( (len + 1) * sizeof(WCHAR) )))
+    {
+        strcpyW( ret, connectW );
+        strcatW( ret, spaceW );
+        strcatW( ret, host );
+        strcatW( ret, spaceW );
+        strcatW( ret, http1_1 );
 
-    /*
-     * Set (header) termination string for request
-     * Make sure there are exactly two new lines at the end of the request
-     */
-    p = &requestString[strlenW(requestString)-1];
-    while ( (*p == '\n') || (*p == '\r') )
-       p--;
-    strcpyW( p+1, twocrlf );
+        for (i = 0; i < request->num_headers; i++)
+        {
+            if (request->headers[i].is_request)
+            {
+                strcatW( ret, crlfW );
+                strcatW( ret, request->headers[i].field );
+                strcatW( ret, colonW );
+                strcatW( ret, request->headers[i].value );
+            }
+        }
+        strcatW( ret, twocrlfW );
+    }
 
-    return requestString;
+    heap_free( host );
+    return ret;
 }
 
-static BOOL read_reply( request_t *request );
+static BOOL read_reply( struct request *request );
 
-static BOOL secure_proxy_connect( request_t *request )
+static BOOL secure_proxy_connect( struct request *request )
 {
-    static const WCHAR verbConnect[] = {'C','O','N','N','E','C','T',0};
-    static const WCHAR fmt[] = {'%','s',':','%','u',0};
-    BOOL ret = FALSE;
-    LPWSTR path;
-    connect_t *connect = request->connect;
-
-    path = heap_alloc( (strlenW( connect->hostname ) + 13) * sizeof(WCHAR) );
-    if (path)
-    {
-        LPWSTR requestString;
+    WCHAR *str;
+    char *strA;
+    int len, bytes_sent;
+    BOOL ret;
 
-        sprintfW( path, fmt, connect->hostname, connect->hostport );
-        requestString = build_header_request_string( request, verbConnect,
-            path, http1_1 );
-        heap_free( path );
-        if (requestString)
-        {
-            LPSTR req_ascii = strdupWA( requestString );
+    if (!(str = build_proxy_connect_string( request ))) return FALSE;
+    strA = strdupWA( str );
+    heap_free( str );
+    if (!strA) return FALSE;
 
-            heap_free( requestString );
-            if (req_ascii)
-            {
-                int len = strlen( req_ascii ), bytes_sent;
+    len = strlen( strA );
+    ret = netconn_send( request->netconn, strA, len, &bytes_sent );
+    heap_free( strA );
+    if (ret) ret = read_reply( request );
 
-                ret = netconn_send( request->netconn, req_ascii, len, &bytes_sent );
-                heap_free( req_ascii );
-                if (ret)
-                    ret = read_reply( request );
-            }
-        }
-    }
     return ret;
 }
 
-#ifndef INET6_ADDRSTRLEN
-#define INET6_ADDRSTRLEN 46
-#endif
-
 static WCHAR *addr_to_str( struct sockaddr_storage *addr )
 {
     char buf[INET6_ADDRSTRLEN];
@@ -1523,7 +1491,7 @@ static CRITICAL_SECTION connection_pool_cs = { &connection_pool_debug, -1, 0, 0,
 
 static struct list connection_pool = LIST_INIT( connection_pool );
 
-void release_host( hostdata_t *host )
+void release_host( struct hostdata *host )
 {
     LONG ref;
 
@@ -1539,11 +1507,15 @@ void release_host( hostdata_t *host )
 
 static BOOL connection_collector_running;
 
+#ifdef __REACTOS__
 static DWORD WINAPI connection_collector(void *arg)
+#else
+static void CALLBACK connection_collector( TP_CALLBACK_INSTANCE *instance, void *ctx )
+#endif
 {
     unsigned int remaining_connections;
-    netconn_t *netconn, *next_netconn;
-    hostdata_t *host, *next_host;
+    struct netconn *netconn, *next_netconn;
+    struct hostdata *host, *next_host;
     ULONGLONG now;
 
     do
@@ -1555,9 +1527,9 @@ static DWORD WINAPI connection_collector(void *arg)
 
         EnterCriticalSection(&connection_pool_cs);
 
-        LIST_FOR_EACH_ENTRY_SAFE(host, next_host, &connection_pool, hostdata_t, entry)
+        LIST_FOR_EACH_ENTRY_SAFE(host, next_host, &connection_pool, struct hostdata, entry)
         {
-            LIST_FOR_EACH_ENTRY_SAFE(netconn, next_netconn, &host->connections, netconn_t, entry)
+            LIST_FOR_EACH_ENTRY_SAFE(netconn, next_netconn, &host->connections, struct netconn, entry)
             {
                 if (netconn->keep_until < now)
                 {
@@ -1565,10 +1537,7 @@ static DWORD WINAPI connection_collector(void *arg)
                     list_remove(&netconn->entry);
                     netconn_close(netconn);
                 }
-                else
-                {
-                    remaining_connections++;
-                }
+                else remaining_connections++;
             }
         }
 
@@ -1577,10 +1546,14 @@ static DWORD WINAPI connection_collector(void *arg)
         LeaveCriticalSection(&connection_pool_cs);
     } while(remaining_connections);
 
+#ifdef __REACTOS__
     FreeLibraryAndExitThread( winhttp_instance, 0 );
+#else
+    FreeLibraryWhenCallbackReturns( instance, winhttp_instance );
+#endif
 }
 
-static void cache_connection( netconn_t *netconn )
+static void cache_connection( struct netconn *netconn )
 {
     TRACE( "caching connection %p\n", netconn );
 
@@ -1592,10 +1565,13 @@ static void cache_connection( netconn_t *netconn )
     if (!connection_collector_running)
     {
         HMODULE module;
+#ifdef __REACTOS__
         HANDLE thread;
+#endif
 
-        GetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (const WCHAR*)winhttp_instance, &module );
+        GetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (const WCHAR *)winhttp_instance, &module );
 
+#ifdef __REACTOS__
         thread = CreateThread(NULL, 0, connection_collector, NULL, 0, NULL);
         if (thread)
         {
@@ -1606,6 +1582,10 @@ static void cache_connection( netconn_t *netconn )
         {
             FreeLibrary( winhttp_instance );
         }
+#else
+        if (TrySubmitThreadpoolCallback( connection_collector, NULL, NULL )) connection_collector_running = TRUE;
+        else FreeLibrary( winhttp_instance );
+#endif
     }
 
     LeaveCriticalSection( &connection_pool_cs );
@@ -1622,32 +1602,43 @@ static DWORD map_secure_protocols( DWORD mask )
     return ret;
 }
 
-static BOOL ensure_cred_handle( session_t *session )
+static BOOL ensure_cred_handle( struct request *request )
 {
-    SCHANNEL_CRED cred;
-    SECURITY_STATUS status;
+    SECURITY_STATUS status = SEC_E_OK;
+
+    if (request->cred_handle_initialized) return TRUE;
 
-    if (session->cred_handle_initialized) return TRUE;
+    if (!request->cred_handle_initialized)
+    {
+        SCHANNEL_CRED cred;
+        memset( &cred, 0, sizeof(cred) );
+        cred.dwVersion             = SCHANNEL_CRED_VERSION;
+        cred.grbitEnabledProtocols = map_secure_protocols( request->connect->session->secure_protocols );
+        if (request->client_cert)
+        {
+            cred.paCred = &request->client_cert;
+            cred.cCreds = 1;
+        }
+        status = AcquireCredentialsHandleW( NULL, (WCHAR *)UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL,
+                                            &cred, NULL, NULL, &request->cred_handle, NULL );
+        if (status == SEC_E_OK)
+            request->cred_handle_initialized = TRUE;
+    }
 
-    memset( &cred, 0, sizeof(cred) );
-    cred.dwVersion             = SCHANNEL_CRED_VERSION;
-    cred.grbitEnabledProtocols = map_secure_protocols( session->secure_protocols );
-    if ((status = AcquireCredentialsHandleW( NULL, (WCHAR *)UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL, &cred,
-                                             NULL, NULL, &session->cred_handle, NULL )) != SEC_E_OK)
+    if (status != SEC_E_OK)
     {
         WARN( "AcquireCredentialsHandleW failed: 0x%08x\n", status );
         return FALSE;
     }
-    session->cred_handle_initialized = TRUE;
     return TRUE;
 }
 
-static BOOL open_connection( request_t *request )
+static BOOL open_connection( struct request *request )
 {
     BOOL is_secure = request->hdr.flags & WINHTTP_FLAG_SECURE;
-    hostdata_t *host = NULL, *iter;
-    netconn_t *netconn = NULL;
-    connect_t *connect;
+    struct hostdata *host = NULL, *iter;
+    struct netconn *netconn = NULL;
+    struct connect *connect;
     WCHAR *addressW = NULL;
     INTERNET_PORT port;
     DWORD len;
@@ -1659,7 +1650,7 @@ static BOOL open_connection( request_t *request )
 
     EnterCriticalSection( &connection_pool_cs );
 
-    LIST_FOR_EACH_ENTRY( iter, &connection_pool, hostdata_t, entry )
+    LIST_FOR_EACH_ENTRY( iter, &connection_pool, struct hostdata, entry )
     {
         if (iter->port == port && !strcmpW( connect->servername, iter->hostname ) && !is_secure == !iter->secure)
         {
@@ -1698,7 +1689,7 @@ static BOOL open_connection( request_t *request )
         EnterCriticalSection( &connection_pool_cs );
         if (!list_empty( &host->connections ))
         {
-            netconn = LIST_ENTRY( list_head( &host->connections ), netconn_t, entry );
+            netconn = LIST_ENTRY( list_head( &host->connections ), struct netconn, entry );
             list_remove( &netconn->entry );
         }
         LeaveCriticalSection( &connection_pool_cs );
@@ -1756,7 +1747,10 @@ static BOOL open_connection( request_t *request )
             return FALSE;
         }
         netconn_set_timeout( netconn, TRUE, request->send_timeout );
-        netconn_set_timeout( netconn, FALSE, request->recv_timeout );
+        netconn_set_timeout( netconn, FALSE, request->receive_response_timeout );
+
+        request->netconn = netconn;
+
         if (is_secure)
         {
             if (connect->session->proxy_server &&
@@ -1764,22 +1758,27 @@ static BOOL open_connection( request_t *request )
             {
                 if (!secure_proxy_connect( request ))
                 {
+                    request->netconn = NULL;
                     heap_free( addressW );
                     netconn_close( netconn );
                     return FALSE;
                 }
             }
-            if (!ensure_cred_handle( connect->session ) ||
+
+            CertFreeCertificateContext( request->server_cert );
+            request->server_cert = NULL;
+
+            if (!ensure_cred_handle( request ) ||
                 !netconn_secure_connect( netconn, connect->hostname, request->security_flags,
-                                         &connect->session->cred_handle ))
+                                         &request->cred_handle, request->check_revocation ))
             {
+                request->netconn = NULL;
                 heap_free( addressW );
                 netconn_close( netconn );
                 return FALSE;
             }
         }
 
-        request->netconn = netconn;
         send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, addressW, strlenW(addressW) + 1 );
     }
     else
@@ -1787,10 +1786,17 @@ static BOOL open_connection( request_t *request )
         TRACE("using connection %p\n", netconn);
 
         netconn_set_timeout( netconn, TRUE, request->send_timeout );
-        netconn_set_timeout( netconn, FALSE, request->recv_timeout );
+        netconn_set_timeout( netconn, FALSE, request->receive_response_timeout );
         request->netconn = netconn;
     }
 
+    if (netconn->secure && !(request->server_cert = netconn_get_certificate( netconn )))
+    {
+        heap_free( addressW );
+        netconn_close( netconn );
+        return FALSE;
+    }
+
 done:
     request->read_pos = request->read_size = 0;
     request->read_chunked = FALSE;
@@ -1800,7 +1806,7 @@ done:
     return TRUE;
 }
 
-void close_connection( request_t *request )
+void close_connection( struct request *request )
 {
     if (!request->netconn) return;
 
@@ -1810,13 +1816,13 @@ void close_connection( request_t *request )
     send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, 0, 0 );
 }
 
-static BOOL add_host_header( request_t *request, DWORD modifier )
+static BOOL add_host_header( struct request *request, DWORD modifier )
 {
     BOOL ret;
     DWORD len;
     WCHAR *host;
     static const WCHAR fmt[] = {'%','s',':','%','u',0};
-    connect_t *connect = request->connect;
+    struct connect *connect = request->connect;
     INTERNET_PORT port;
 
     port = connect->hostport ? connect->hostport : (request->hdr.flags & WINHTTP_FLAG_SECURE ? 443 : 80);
@@ -1833,7 +1839,7 @@ static BOOL add_host_header( request_t *request, DWORD modifier )
     return ret;
 }
 
-static void clear_response_headers( request_t *request )
+static void clear_response_headers( struct request *request )
 {
     unsigned int i;
 
@@ -1848,14 +1854,14 @@ static void clear_response_headers( request_t *request )
 }
 
 /* remove some amount of data from the read buffer */
-static void remove_data( request_t *request, int count )
+static void remove_data( struct request *request, int count )
 {
     if (!(request->read_size -= count)) request->read_pos = 0;
     else request->read_pos += count;
 }
 
 /* read some more data into the read buffer */
-static BOOL read_more_data( request_t *request, int maxlen, BOOL notify )
+static BOOL read_more_data( struct request *request, int maxlen, BOOL notify )
 {
     int len;
     BOOL ret;
@@ -1882,7 +1888,7 @@ static BOOL read_more_data( request_t *request, int maxlen, BOOL notify )
 }
 
 /* discard data contents until we reach end of line */
-static BOOL discard_eol( request_t *request, BOOL notify )
+static BOOL discard_eol( struct request *request, BOOL notify )
 {
     do
     {
@@ -1899,7 +1905,7 @@ static BOOL discard_eol( request_t *request, BOOL notify )
 }
 
 /* read the size of the next chunk */
-static BOOL start_next_chunk( request_t *request, BOOL notify )
+static BOOL start_next_chunk( struct request *request, BOOL notify )
 {
     DWORD chunk_size = 0;
 
@@ -1942,7 +1948,7 @@ static BOOL start_next_chunk( request_t *request, BOOL notify )
     }
 }
 
-static BOOL refill_buffer( request_t *request, BOOL notify )
+static BOOL refill_buffer( struct request *request, BOOL notify )
 {
     int len = sizeof(request->read_buf);
 
@@ -1966,7 +1972,7 @@ static BOOL refill_buffer( request_t *request, BOOL notify )
     return TRUE;
 }
 
-static void finished_reading( request_t *request )
+static void finished_reading( struct request *request )
 {
     static const WCHAR closeW[] = {'c','l','o','s','e',0};
 
@@ -1994,14 +2000,14 @@ static void finished_reading( request_t *request )
 }
 
 /* return the size of data available to be read immediately */
-static DWORD get_available_data( request_t *request )
+static DWORD get_available_data( struct request *request )
 {
     if (request->read_chunked) return min( request->read_chunked_size, request->read_size );
     return request->read_size;
 }
 
 /* check if we have reached the end of the data to read */
-static BOOL end_of_read_data( request_t *request )
+static BOOL end_of_read_data( struct request *request )
 {
     if (!request->content_length) return TRUE;
     if (request->read_chunked) return request->read_chunked_eof;
@@ -2009,9 +2015,10 @@ static BOOL end_of_read_data( request_t *request )
     return (request->content_length == request->content_read);
 }
 
-static BOOL read_data( request_t *request, void *buffer, DWORD size, DWORD *read, BOOL async )
+static BOOL read_data( struct request *request, void *buffer, DWORD size, DWORD *read, BOOL async )
 {
     int count, bytes_read = 0;
+    BOOL ret = TRUE;
 
     if (end_of_read_data( request )) goto done;
 
@@ -2019,7 +2026,7 @@ static BOOL read_data( request_t *request, void *buffer, DWORD size, DWORD *read
     {
         if (!(count = get_available_data( request )))
         {
-            if (!refill_buffer( request, async )) goto done;
+            if (!(ret = refill_buffer( request, async ))) goto done;
             if (!(count = get_available_data( request ))) goto done;
         }
         count = min( count, size );
@@ -2031,19 +2038,29 @@ static BOOL read_data( request_t *request, void *buffer, DWORD size, DWORD *read
         request->content_read += count;
         if (end_of_read_data( request )) goto done;
     }
-    if (request->read_chunked && !request->read_chunked_size) refill_buffer( request, async );
+    if (request->read_chunked && !request->read_chunked_size) ret = refill_buffer( request, async );
 
 done:
     TRACE( "retrieved %u bytes (%u/%u)\n", bytes_read, request->content_read, request->content_length );
+    if (async)
+    {
+        if (ret) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, buffer, bytes_read );
+        else
+        {
+            WINHTTP_ASYNC_RESULT result;
+            result.dwResult = API_READ_DATA;
+            result.dwError  = GetLastError();
+            send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) );
+        }
+    }
 
-    if (async) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, buffer, bytes_read );
-    if (read) *read = bytes_read;
+    if (ret && read) *read = bytes_read;
     if (end_of_read_data( request )) finished_reading( request );
-    return TRUE;
+    return ret;
 }
 
 /* read any content returned by the server so that the connection can be reused */
-static void drain_content( request_t *request )
+static void drain_content( struct request *request )
 {
     DWORD size, bytes_read, bytes_total = 0, bytes_left = request->content_length - request->content_read;
     char buffer[2048];
@@ -2062,7 +2079,177 @@ static void drain_content( request_t *request )
     }
 }
 
-static BOOL send_request( request_t *request, LPCWSTR headers, DWORD headers_len, LPVOID optional,
+enum escape_flags
+{
+    ESCAPE_FLAG_NON_PRINTABLE = 0x01,
+    ESCAPE_FLAG_SPACE         = 0x02,
+    ESCAPE_FLAG_PERCENT       = 0x04,
+    ESCAPE_FLAG_UNSAFE        = 0x08,
+    ESCAPE_FLAG_DEL           = 0x10,
+    ESCAPE_FLAG_8BIT          = 0x20,
+    ESCAPE_FLAG_STRIP_CRLF    = 0x40,
+};
+
+#define ESCAPE_MASK_DEFAULT (ESCAPE_FLAG_NON_PRINTABLE | ESCAPE_FLAG_SPACE | ESCAPE_FLAG_UNSAFE |\
+                             ESCAPE_FLAG_DEL | ESCAPE_FLAG_8BIT)
+#define ESCAPE_MASK_PERCENT (ESCAPE_FLAG_PERCENT | ESCAPE_MASK_DEFAULT)
+#define ESCAPE_MASK_DISABLE (ESCAPE_FLAG_SPACE | ESCAPE_FLAG_8BIT | ESCAPE_FLAG_STRIP_CRLF)
+
+static inline BOOL need_escape( char ch, enum escape_flags flags )
+{
+    static const char unsafe[] = "\"#<>[\\]^`{|}";
+    const char *ptr = unsafe;
+
+    if ((flags & ESCAPE_FLAG_SPACE) && ch == ' ') return TRUE;
+    if ((flags & ESCAPE_FLAG_PERCENT) && ch == '%') return TRUE;
+    if ((flags & ESCAPE_FLAG_NON_PRINTABLE) && ch < 0x20) return TRUE;
+    if ((flags & ESCAPE_FLAG_DEL) && ch == 0x7f) return TRUE;
+    if ((flags & ESCAPE_FLAG_8BIT) && (ch & 0x80)) return TRUE;
+    if ((flags & ESCAPE_FLAG_UNSAFE)) while (*ptr) { if (ch == *ptr++) return TRUE; }
+    return FALSE;
+}
+
+static DWORD escape_string( const char *src, DWORD len, char *dst, enum escape_flags flags )
+{
+    static const char hex[] = "0123456789ABCDEF";
+    DWORD i, ret = len;
+    char *ptr = dst;
+
+    for (i = 0; i < len; i++)
+    {
+        if ((flags & ESCAPE_FLAG_STRIP_CRLF) && (src[i] == '\r' || src[i] == '\n'))
+        {
+            ret--;
+            continue;
+        }
+        if (need_escape( src[i], flags ))
+        {
+            if (dst)
+            {
+                ptr[0] = '%';
+                ptr[1] = hex[(src[i] >> 4) & 0xf];
+                ptr[2] = hex[src[i] & 0xf];
+                ptr += 3;
+            }
+            ret += 2;
+        }
+        else if (dst) *ptr++ = src[i];
+    }
+
+    if (dst) dst[ret] = 0;
+    return ret;
+}
+
+static DWORD str_to_wire( const WCHAR *src, int src_len, char *dst, enum escape_flags flags )
+{
+    DWORD len;
+    char *utf8;
+
+    if (src_len < 0) src_len = strlenW( src );
+    len = WideCharToMultiByte( CP_UTF8, 0, src, src_len, NULL, 0, NULL, NULL );
+    if (!(utf8 = heap_alloc( len ))) return 0;
+
+    WideCharToMultiByte( CP_UTF8, 0, src, -1, utf8, len, NULL, NULL );
+    len = escape_string( utf8, len, dst, flags );
+    heap_free( utf8 );
+
+    return len;
+}
+
+static char *build_wire_path( struct request *request, DWORD *ret_len )
+{
+    WCHAR *full_path;
+    const WCHAR *start, *path, *query = NULL;
+    DWORD len, len_path = 0, len_query = 0;
+    enum escape_flags path_flags, query_flags;
+    char *ret;
+
+    if (!strcmpiW( request->connect->hostname, request->connect->servername )) start = full_path = request->path;
+    else if (!(full_path = build_absolute_request_path( request, &start ))) return NULL;
+
+    len = strlenW( full_path );
+    if ((path = strchrW( start, '/' )))
+    {
+        len_path = strlenW( path );
+        if ((query = strchrW( path, '?' )))
+        {
+            len_query = strlenW( query );
+            len_path -= len_query;
+        }
+    }
+
+    if (request->hdr.flags & WINHTTP_FLAG_ESCAPE_DISABLE) path_flags = ESCAPE_MASK_DISABLE;
+    else if (request->hdr.flags & WINHTTP_FLAG_ESCAPE_PERCENT) path_flags = ESCAPE_MASK_PERCENT;
+    else path_flags = ESCAPE_MASK_DEFAULT;
+
+    if (request->hdr.flags & WINHTTP_FLAG_ESCAPE_DISABLE_QUERY) query_flags = ESCAPE_MASK_DISABLE;
+    else query_flags = path_flags;
+
+    *ret_len = str_to_wire( full_path, len - len_path - len_query, NULL, 0 );
+    if (path) *ret_len += str_to_wire( path, len_path, NULL, path_flags );
+    if (query) *ret_len += str_to_wire( query, len_query, NULL, query_flags );
+
+    if ((ret = heap_alloc( *ret_len + 1 )))
+    {
+        len = str_to_wire( full_path, len - len_path - len_query, ret, 0 );
+        if (path) len += str_to_wire( path, len_path, ret + len, path_flags );
+        if (query) str_to_wire( query, len_query, ret + len, query_flags );
+    }
+
+    if (full_path != request->path) heap_free( full_path );
+    return ret;
+}
+
+static char *build_wire_request( struct request *request, DWORD *len )
+{
+    char *path, *ptr, *ret;
+    DWORD i, len_path;
+
+    if (!(path = build_wire_path( request, &len_path ))) return NULL;
+
+    *len = str_to_wire( request->verb, -1, NULL, 0 ) + 1; /* ' ' */
+    *len += len_path + 1; /* ' ' */
+    *len += str_to_wire( request->version, -1, NULL, 0 );
+
+    for (i = 0; i < request->num_headers; i++)
+    {
+        if (request->headers[i].is_request)
+        {
+            *len += str_to_wire( request->headers[i].field, -1, NULL, 0 ) + 2; /* ': ' */
+            *len += str_to_wire( request->headers[i].value, -1, NULL, 0 ) + 2; /* '\r\n' */
+        }
+    }
+    *len += 4; /* '\r\n\r\n' */
+
+    if ((ret = ptr = heap_alloc( *len + 1 )))
+    {
+        ptr += str_to_wire( request->verb, -1, ptr, 0 );
+        *ptr++ = ' ';
+        memcpy( ptr, path, len_path );
+        ptr += len_path;
+        *ptr++ = ' ';
+        ptr += str_to_wire( request->version, -1, ptr, 0 );
+
+        for (i = 0; i < request->num_headers; i++)
+        {
+            if (request->headers[i].is_request)
+            {
+                *ptr++ = '\r';
+                *ptr++ = '\n';
+                ptr += str_to_wire( request->headers[i].field, -1, ptr, 0 );
+                *ptr++ = ':';
+                *ptr++ = ' ';
+                ptr += str_to_wire( request->headers[i].value, -1, ptr, 0 );
+            }
+        }
+        memcpy( ptr, "\r\n\r\n", sizeof("\r\n\r\n") );
+    }
+
+    heap_free( path );
+    return ret;
+}
+
+static BOOL send_request( struct request *request, const WCHAR *headers, DWORD headers_len, void *optional,
                           DWORD optional_len, DWORD total_len, DWORD_PTR context, BOOL async )
 {
     static const WCHAR keep_alive[] = {'K','e','e','p','-','A','l','i','v','e',0};
@@ -2070,10 +2257,9 @@ static BOOL send_request( request_t *request, LPCWSTR headers, DWORD headers_len
     static const WCHAR length_fmt[] = {'%','l','d',0};
 
     BOOL ret = FALSE;
-    connect_t *connect = request->connect;
-    session_t *session = connect->session;
-    WCHAR *req = NULL;
-    char *req_ascii;
+    struct connect *connect = request->connect;
+    struct session *session = connect->session;
+    char *wire_req;
     int bytes_sent;
     DWORD len;
 
@@ -2118,16 +2304,13 @@ static BOOL send_request( request_t *request, LPCWSTR headers, DWORD headers_len
     if (context) request->hdr.context = context;
 
     if (!(ret = open_connection( request ))) goto end;
-    if (!(req = build_request_string( request ))) goto end;
-
-    if (!(req_ascii = strdupWA( req ))) goto end;
-    TRACE("full request: %s\n", debugstr_a(req_ascii));
-    len = strlen(req_ascii);
+    if (!(wire_req = build_wire_request( request, &len ))) goto end;
+    TRACE("full request: %s\n", debugstr_a(wire_req));
 
     send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST, NULL, 0 );
 
-    ret = netconn_send( request->netconn, req_ascii, len, &bytes_sent );
-    heap_free( req_ascii );
+    ret = netconn_send( request->netconn, wire_req, len, &bytes_sent );
+    heap_free( wire_req );
     if (!ret) goto end;
 
     if (optional_len)
@@ -2147,17 +2330,16 @@ end:
         {
             WINHTTP_ASYNC_RESULT result;
             result.dwResult = API_SEND_REQUEST;
-            result.dwError  = get_last_error();
+            result.dwError  = GetLastError();
             send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) );
         }
     }
-    heap_free( req );
     return ret;
 }
 
-static void task_send_request( task_header_t *task )
+static void task_send_request( struct task_header *task )
 {
-    send_request_t *s = (send_request_t *)task;
+    struct send_request *s = (struct send_request *)task;
     send_request( s->hdr.request, s->headers, s->headers_len, s->optional, s->optional_len, s->total_len, s->context, TRUE );
     heap_free( s->headers );
 }
@@ -2169,20 +2351,20 @@ BOOL WINAPI WinHttpSendRequest( HINTERNET hrequest, LPCWSTR headers, DWORD heade
                                 LPVOID optional, DWORD optional_len, DWORD total_len, DWORD_PTR context )
 {
     BOOL ret;
-    request_t *request;
+    struct request *request;
 
-    TRACE("%p, %s, %u, %u, %u, %lx\n", hrequest, debugstr_wn(headers, headers_len), headers_len, optional_len,
-          total_len, context);
+    TRACE("%p, %s, %u, %p, %u, %u, %lx\n", hrequest, debugstr_wn(headers, headers_len), headers_len, optional,
+          optional_len, total_len, context);
 
-    if (!(request = (request_t *)grab_object( hrequest )))
+    if (!(request = (struct request *)grab_object( hrequest )))
     {
-        set_last_error( ERROR_INVALID_HANDLE );
+        SetLastError( ERROR_INVALID_HANDLE );
         return FALSE;
     }
     if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST)
     {
         release_object( &request->hdr );
-        set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+        SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
         return FALSE;
     }
 
@@ -2190,9 +2372,9 @@ BOOL WINAPI WinHttpSendRequest( HINTERNET hrequest, LPCWSTR headers, DWORD heade
 
     if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC)
     {
-        send_request_t *s;
+        struct send_request *s;
 
-        if (!(s = heap_alloc( sizeof(send_request_t) ))) return FALSE;
+        if (!(s = heap_alloc( sizeof(struct send_request) ))) return FALSE;
         s->hdr.request  = request;
         s->hdr.proc     = task_send_request;
         s->headers      = strdupW( headers );
@@ -2203,24 +2385,24 @@ BOOL WINAPI WinHttpSendRequest( HINTERNET hrequest, LPCWSTR headers, DWORD heade
         s->context      = context;
 
         addref_object( &request->hdr );
-        ret = queue_task( (task_header_t *)s );
+        ret = queue_task( (struct task_header *)s );
     }
     else
         ret = send_request( request, headers, headers_len, optional, optional_len, total_len, context, FALSE );
 
     release_object( &request->hdr );
-    if (ret) set_last_error( ERROR_SUCCESS );
+    if (ret) SetLastError( ERROR_SUCCESS );
     return ret;
 }
 
-static BOOL set_credentials( request_t *request, DWORD target, DWORD scheme_flag, const WCHAR *username,
+static BOOL set_credentials( struct request *request, DWORD target, DWORD scheme_flag, const WCHAR *username,
                              const WCHAR *password )
 {
     enum auth_scheme scheme = scheme_from_flag( scheme_flag );
 
     if (scheme == SCHEME_INVALID || ((scheme == SCHEME_BASIC || scheme == SCHEME_DIGEST) && (!username || !password)))
     {
-        set_last_error( ERROR_INVALID_PARAMETER );
+        SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
     switch (target)
@@ -2261,30 +2443,30 @@ BOOL WINAPI WinHttpSetCredentials( HINTERNET hrequest, DWORD target, DWORD schem
                                    LPCWSTR password, LPVOID params )
 {
     BOOL ret;
-    request_t *request;
+    struct request *request;
 
     TRACE("%p, %x, 0x%08x, %s, %p, %p\n", hrequest, target, scheme, debugstr_w(username), password, params);
 
-    if (!(request = (request_t *)grab_object( hrequest )))
+    if (!(request = (struct request *)grab_object( hrequest )))
     {
-        set_last_error( ERROR_INVALID_HANDLE );
+        SetLastError( ERROR_INVALID_HANDLE );
         return FALSE;
     }
     if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST)
     {
         release_object( &request->hdr );
-        set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+        SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
         return FALSE;
     }
 
     ret = set_credentials( request, target, scheme, username, password );
 
     release_object( &request->hdr );
-    if (ret) set_last_error( ERROR_SUCCESS );
+    if (ret) SetLastError( ERROR_SUCCESS );
     return ret;
 }
 
-static BOOL handle_authorization( request_t *request, DWORD status )
+static BOOL handle_authorization( struct request *request, DWORD status )
 {
     DWORD i, schemes, first, level, target;
 
@@ -2309,7 +2491,7 @@ static BOOL handle_authorization( request_t *request, DWORD status )
     if (do_authorization( request, target, first )) return TRUE;
 
     schemes &= ~first;
-    for (i = 0; i < num_auth_schemes; i++)
+    for (i = 0; i < ARRAY_SIZE( auth_schemes ); i++)
     {
         if (!(schemes & auth_schemes[i].scheme)) continue;
         if (do_authorization( request, target, auth_schemes[i].scheme )) return TRUE;
@@ -2318,7 +2500,7 @@ static BOOL handle_authorization( request_t *request, DWORD status )
 }
 
 /* set the request content length based on the headers */
-static DWORD set_content_length( request_t *request, DWORD status )
+static DWORD set_content_length( struct request *request, DWORD status )
 {
     WCHAR encoding[20];
     DWORD buflen = sizeof(request->content_length);
@@ -2345,7 +2527,7 @@ static DWORD set_content_length( request_t *request, DWORD status )
     return request->content_length;
 }
 
-static BOOL read_line( request_t *request, char *buffer, DWORD *len )
+static BOOL read_line( struct request *request, char *buffer, DWORD *len )
 {
     int count, bytes_read, pos = 0;
 
@@ -2386,7 +2568,7 @@ static BOOL read_line( request_t *request, char *buffer, DWORD *len )
 #define MAX_REPLY_LEN   1460
 #define INITIAL_HEADER_BUFFER_LEN  512
 
-static BOOL read_reply( request_t *request )
+static BOOL read_reply( struct request *request )
 {
     static const WCHAR crlf[] = {'\r','\n',0};
 
@@ -2450,7 +2632,7 @@ static BOOL read_reply( request_t *request )
     offset = buflen + crlf_len - 1;
     for (;;)
     {
-        header_t *header;
+        struct header *header;
 
         buflen = MAX_REPLY_LEN;
         if (!read_line( request, buffer, &buflen )) return TRUE;
@@ -2485,13 +2667,13 @@ static BOOL read_reply( request_t *request )
     return TRUE;
 }
 
-static void record_cookies( request_t *request )
+static void record_cookies( struct request *request )
 {
     unsigned int i;
 
     for (i = 0; i < request->num_headers; i++)
     {
-        header_t *set_cookie = &request->headers[i];
+        struct header *set_cookie = &request->headers[i];
         if (!strcmpiW( set_cookie->field, attr_set_cookie ) && !set_cookie->is_request)
         {
             set_cookies( request, set_cookie->value );
@@ -2499,59 +2681,60 @@ static void record_cookies( request_t *request )
     }
 }
 
-static WCHAR *get_redirect_url( request_t *request, DWORD *len )
+static WCHAR *get_redirect_url( struct request *request, DWORD *len )
 {
     DWORD size;
     WCHAR *ret;
 
     query_headers( request, WINHTTP_QUERY_LOCATION, NULL, NULL, &size, NULL );
-    if (get_last_error() != ERROR_INSUFFICIENT_BUFFER) return FALSE;
+    if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return NULL;
     if (!(ret = heap_alloc( size ))) return NULL;
-    *len = size / sizeof(WCHAR);
+    *len = size / sizeof(WCHAR) - 1;
     if (query_headers( request, WINHTTP_QUERY_LOCATION, NULL, ret, &size, NULL )) return ret;
     heap_free( ret );
     return NULL;
 }
 
-static BOOL handle_redirect( request_t *request, DWORD status )
+static BOOL handle_redirect( struct request *request, DWORD status )
 {
     BOOL ret = FALSE;
-    DWORD len, len_url;
+    DWORD len, len_loc;
     URL_COMPONENTS uc;
-    connect_t *connect = request->connect;
+    struct connect *connect = request->connect;
     INTERNET_PORT port;
     WCHAR *hostname = NULL, *location;
     int index;
 
-    if (!(location = get_redirect_url( request, &len_url ))) return FALSE;
+    if (!(location = get_redirect_url( request, &len_loc ))) return FALSE;
 
     memset( &uc, 0, sizeof(uc) );
     uc.dwStructSize = sizeof(uc);
     uc.dwSchemeLength = uc.dwHostNameLength = uc.dwUrlPathLength = uc.dwExtraInfoLength = ~0u;
 
-    if (!WinHttpCrackUrl( location, len_url, 0, &uc )) /* assume relative redirect */
+    if (!WinHttpCrackUrl( location, len_loc, 0, &uc )) /* assume relative redirect */
     {
         WCHAR *path, *p;
 
         if (location[0] == '/')
         {
-            len = strlenW( location );
-            if (!(path = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end;
-            strcpyW( path, location );
+            if (!(path = heap_alloc( (len_loc + 1) * sizeof(WCHAR) ))) goto end;
+            memcpy( path, location, len_loc * sizeof(WCHAR) );
+            path[len_loc] = 0;
         }
         else
         {
             if ((p = strrchrW( request->path, '/' ))) *p = 0;
-            len = strlenW( request->path ) + 1 + strlenW( location );
+            len = strlenW( request->path ) + 1 + len_loc;
             if (!(path = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end;
             strcpyW( path, request->path );
             strcatW( path, slashW );
-            strcatW( path, location );
+            memcpy( path + strlenW(path), location, len_loc * sizeof(WCHAR) );
+            path[len_loc] = 0;
         }
         heap_free( request->path );
         request->path = path;
 
-        send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REDIRECT, location, len_url + 1 );
+        send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REDIRECT, location, len_loc + 1 );
     }
     else
     {
@@ -2567,7 +2750,7 @@ static BOOL handle_redirect( request_t *request, DWORD status )
             request->hdr.flags |= WINHTTP_FLAG_SECURE;
         }
 
-        send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REDIRECT, location, len_url + 1 );
+        send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REDIRECT, location, len_loc + 1 );
 
         len = uc.dwHostNameLength;
         if (!(hostname = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end;
@@ -2599,7 +2782,8 @@ static BOOL handle_redirect( request_t *request, DWORD status )
         {
             len = uc.dwUrlPathLength + uc.dwExtraInfoLength;
             if (!(request->path = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end;
-            strcpyW( request->path, uc.lpszUrlPath );
+            memcpy( request->path, uc.lpszUrlPath, (len + 1) * sizeof(WCHAR) );
+            request->path[len] = 0;
         }
         else request->path = strdupW( slashW );
     }
@@ -2622,16 +2806,59 @@ end:
     return ret;
 }
 
-static BOOL receive_response( request_t *request, BOOL async )
+static BOOL is_passport_request( struct request *request )
+{
+    static const WCHAR passportW[] = {'P','a','s','s','p','o','r','t','1','.','4'};
+    WCHAR buf[1024];
+    DWORD len = ARRAY_SIZE(buf);
+
+    if (!(request->connect->session->passport_flags & WINHTTP_ENABLE_PASSPORT_AUTH) ||
+        !query_headers( request, WINHTTP_QUERY_WWW_AUTHENTICATE, NULL, buf, &len, NULL )) return FALSE;
+
+    if (!strncmpiW( buf, passportW, ARRAY_SIZE(passportW) ) &&
+        (buf[ARRAY_SIZE(passportW)] == ' ' || !buf[ARRAY_SIZE(passportW)])) return TRUE;
+
+    return FALSE;
+}
+
+static BOOL handle_passport_redirect( struct request *request )
+{
+    static const WCHAR status401W[] = {'4','0','1',0};
+    DWORD flags = WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE;
+    int i, len = strlenW( request->raw_headers );
+    WCHAR *p = request->raw_headers;
+
+    if (!process_header( request, attr_status, status401W, flags, FALSE )) return FALSE;
+
+    for (i = 0; i < len; i++)
+    {
+        if (i <= len - 3 && p[i] == '3' && p[i + 1] == '0' && p[i + 2] == '2')
+        {
+            p[i] = '4';
+            p[i + 2] = '1';
+            break;
+        }
+    }
+    return TRUE;
+}
+
+static BOOL receive_response( struct request *request, BOOL async )
 {
     BOOL ret;
     DWORD size, query, status;
 
+    if (!request->netconn)
+    {
+        SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_STATE );
+        return FALSE;
+    }
+
+    netconn_set_timeout( request->netconn, FALSE, request->receive_response_timeout );
     for (;;)
     {
         if (!(ret = read_reply( request )))
         {
-            set_last_error( ERROR_WINHTTP_INVALID_SERVER_RESPONSE );
+            SetLastError( ERROR_WINHTTP_INVALID_SERVER_RESPONSE );
             break;
         }
         size = sizeof(DWORD);
@@ -2642,7 +2869,11 @@ static BOOL receive_response( request_t *request, BOOL async )
 
         if (!(request->hdr.disable_flags & WINHTTP_DISABLE_COOKIES)) record_cookies( request );
 
-        if (status == HTTP_STATUS_MOVED || status == HTTP_STATUS_REDIRECT || status == HTTP_STATUS_REDIRECT_KEEP_VERB)
+        if (status == HTTP_STATUS_REDIRECT && is_passport_request( request ))
+        {
+            ret = handle_passport_redirect( request );
+        }
+        else if (status == HTTP_STATUS_MOVED || status == HTTP_STATUS_REDIRECT || status == HTTP_STATUS_REDIRECT_KEEP_VERB)
         {
             if (request->hdr.disable_flags & WINHTTP_DISABLE_REDIRECTS ||
                 request->hdr.redirect_policy == WINHTTP_OPTION_REDIRECT_POLICY_NEVER) break;
@@ -2664,7 +2895,8 @@ static BOOL receive_response( request_t *request, BOOL async )
         break;
     }
 
-    if (request->content_length) refill_buffer( request, FALSE );
+    netconn_set_timeout( request->netconn, FALSE, request->receive_timeout );
+    if (request->content_length) ret = refill_buffer( request, FALSE );
 
     if (async)
     {
@@ -2673,16 +2905,16 @@ static BOOL receive_response( request_t *request, BOOL async )
         {
             WINHTTP_ASYNC_RESULT result;
             result.dwResult = API_RECEIVE_RESPONSE;
-            result.dwError  = get_last_error();
+            result.dwError  = GetLastError();
             send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) );
         }
     }
     return ret;
 }
 
-static void task_receive_response( task_header_t *task )
+static void task_receive_response( struct task_header *task )
 {
-    receive_response_t *r = (receive_response_t *)task;
+    struct receive_response *r = (struct receive_response *)task;
     receive_response( r->hdr.request, TRUE );
 }
 
@@ -2692,68 +2924,78 @@ static void task_receive_response( task_header_t *task )
 BOOL WINAPI WinHttpReceiveResponse( HINTERNET hrequest, LPVOID reserved )
 {
     BOOL ret;
-    request_t *request;
+    struct request *request;
 
     TRACE("%p, %p\n", hrequest, reserved);
 
-    if (!(request = (request_t *)grab_object( hrequest )))
+    if (!(request = (struct request *)grab_object( hrequest )))
     {
-        set_last_error( ERROR_INVALID_HANDLE );
+        SetLastError( ERROR_INVALID_HANDLE );
         return FALSE;
     }
     if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST)
     {
         release_object( &request->hdr );
-        set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+        SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
         return FALSE;
     }
 
     if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC)
     {
-        receive_response_t *r;
+        struct receive_response *r;
 
-        if (!(r = heap_alloc( sizeof(receive_response_t) ))) return FALSE;
+        if (!(r = heap_alloc( sizeof(struct receive_response) ))) return FALSE;
         r->hdr.request = request;
         r->hdr.proc    = task_receive_response;
 
         addref_object( &request->hdr );
-        ret = queue_task( (task_header_t *)r );
+        ret = queue_task( (struct task_header *)r );
     }
     else
         ret = receive_response( request, FALSE );
 
     release_object( &request->hdr );
-    if (ret) set_last_error( ERROR_SUCCESS );
+    if (ret) SetLastError( ERROR_SUCCESS );
     return ret;
 }
 
-static BOOL query_data_available( request_t *request, DWORD *available, BOOL async )
+static BOOL query_data_available( struct request *request, DWORD *available, BOOL async )
 {
     DWORD count = 0;
+    BOOL ret = TRUE;
 
     if (end_of_read_data( request )) goto done;
 
     count = get_available_data( request );
-    if (!request->read_chunked && request->netconn)
-        count += netconn_query_data_available( request->netconn );
+    if (!request->read_chunked && request->netconn) count += netconn_query_data_available( request->netconn );
     if (!count)
     {
-        refill_buffer( request, async );
+        if (!(ret = refill_buffer( request, async ))) goto done;
         count = get_available_data( request );
-        if (!request->read_chunked && request->netconn)
-            count += netconn_query_data_available( request->netconn );
+        if (!request->read_chunked && request->netconn) count += netconn_query_data_available( request->netconn );
     }
 
 done:
-    if (async) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE, &count, sizeof(count) );
     TRACE("%u bytes available\n", count);
-    if (available) *available = count;
-    return TRUE;
+    if (async)
+    {
+        if (ret) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE, &count, sizeof(count) );
+        else
+        {
+            WINHTTP_ASYNC_RESULT result;
+            result.dwResult = API_QUERY_DATA_AVAILABLE;
+            result.dwError  = GetLastError();
+            send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) );
+        }
+    }
+
+    if (ret && available) *available = count;
+    return ret;
 }
 
-static void task_query_data_available( task_header_t *task )
+static void task_query_data_available( struct task_header *task )
 {
-    query_data_t *q = (query_data_t *)task;
+    struct query_data *q = (struct query_data *)task;
     query_data_available( q->hdr.request, q->available, TRUE );
 }
 
@@ -2763,45 +3005,45 @@ static void task_query_data_available( task_header_t *task )
 BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available )
 {
     BOOL ret;
-    request_t *request;
+    struct request *request;
 
     TRACE("%p, %p\n", hrequest, available);
 
-    if (!(request = (request_t *)grab_object( hrequest )))
+    if (!(request = (struct request *)grab_object( hrequest )))
     {
-        set_last_error( ERROR_INVALID_HANDLE );
+        SetLastError( ERROR_INVALID_HANDLE );
         return FALSE;
     }
     if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST)
     {
         release_object( &request->hdr );
-        set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+        SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
         return FALSE;
     }
 
     if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC)
     {
-        query_data_t *q;
+        struct query_data *q;
 
-        if (!(q = heap_alloc( sizeof(query_data_t) ))) return FALSE;
+        if (!(q = heap_alloc( sizeof(struct query_data) ))) return FALSE;
         q->hdr.request = request;
         q->hdr.proc    = task_query_data_available;
         q->available   = available;
 
         addref_object( &request->hdr );
-        ret = queue_task( (task_header_t *)q );
+        ret = queue_task( (struct task_header *)q );
     }
     else
         ret = query_data_available( request, available, FALSE );
 
     release_object( &request->hdr );
-    if (ret) set_last_error( ERROR_SUCCESS );
+    if (ret) SetLastError( ERROR_SUCCESS );
     return ret;
 }
 
-static void task_read_data( task_header_t *task )
+static void task_read_data( struct task_header *task )
 {
-    read_data_t *r = (read_data_t *)task;
+    struct read_data *r = (struct read_data *)task;
     read_data( r->hdr.request, r->buffer, r->to_read, r->read, TRUE );
 }
 
@@ -2811,27 +3053,27 @@ static void task_read_data( task_header_t *task )
 BOOL WINAPI WinHttpReadData( HINTERNET hrequest, LPVOID buffer, DWORD to_read, LPDWORD read )
 {
     BOOL ret;
-    request_t *request;
+    struct request *request;
 
     TRACE("%p, %p, %d, %p\n", hrequest, buffer, to_read, read);
 
-    if (!(request = (request_t *)grab_object( hrequest )))
+    if (!(request = (struct request *)grab_object( hrequest )))
     {
-        set_last_error( ERROR_INVALID_HANDLE );
+        SetLastError( ERROR_INVALID_HANDLE );
         return FALSE;
     }
     if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST)
     {
         release_object( &request->hdr );
-        set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+        SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
         return FALSE;
     }
 
     if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC)
     {
-        read_data_t *r;
+        struct read_data *r;
 
-        if (!(r = heap_alloc( sizeof(read_data_t) ))) return FALSE;
+        if (!(r = heap_alloc( sizeof(struct read_data) ))) return FALSE;
         r->hdr.request = request;
         r->hdr.proc    = task_read_data;
         r->buffer      = buffer;
@@ -2839,17 +3081,17 @@ BOOL WINAPI WinHttpReadData( HINTERNET hrequest, LPVOID buffer, DWORD to_read, L
         r->read        = read;
 
         addref_object( &request->hdr );
-        ret = queue_task( (task_header_t *)r );
+        ret = queue_task( (struct task_header *)r );
     }
     else
         ret = read_data( request, buffer, to_read, read, FALSE );
 
     release_object( &request->hdr );
-    if (ret) set_last_error( ERROR_SUCCESS );
+    if (ret) SetLastError( ERROR_SUCCESS );
     return ret;
 }
 
-static BOOL write_data( request_t *request, LPCVOID buffer, DWORD to_write, LPDWORD written, BOOL async )
+static BOOL write_data( struct request *request, const void *buffer, DWORD to_write, DWORD *written, BOOL async )
 {
     BOOL ret;
     int num_bytes;
@@ -2863,7 +3105,7 @@ static BOOL write_data( request_t *request, LPCVOID buffer, DWORD to_write, LPDW
         {
             WINHTTP_ASYNC_RESULT result;
             result.dwResult = API_WRITE_DATA;
-            result.dwError  = get_last_error();
+            result.dwError  = GetLastError();
             send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) );
         }
     }
@@ -2871,9 +3113,9 @@ static BOOL write_data( request_t *request, LPCVOID buffer, DWORD to_write, LPDW
     return ret;
 }
 
-static void task_write_data( task_header_t *task )
+static void task_write_data( struct task_header *task )
 {
-    write_data_t *w = (write_data_t *)task;
+    struct write_data *w = (struct write_data *)task;
     write_data( w->hdr.request, w->buffer, w->to_write, w->written, TRUE );
 }
 
@@ -2883,27 +3125,27 @@ static void task_write_data( task_header_t *task )
 BOOL WINAPI WinHttpWriteData( HINTERNET hrequest, LPCVOID buffer, DWORD to_write, LPDWORD written )
 {
     BOOL ret;
-    request_t *request;
+    struct request *request;
 
     TRACE("%p, %p, %d, %p\n", hrequest, buffer, to_write, written);
 
-    if (!(request = (request_t *)grab_object( hrequest )))
+    if (!(request = (struct request *)grab_object( hrequest )))
     {
-        set_last_error( ERROR_INVALID_HANDLE );
+        SetLastError( ERROR_INVALID_HANDLE );
         return FALSE;
     }
     if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST)
     {
         release_object( &request->hdr );
-        set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+        SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
         return FALSE;
     }
 
     if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC)
     {
-        write_data_t *w;
+        struct write_data *w;
 
-        if (!(w = heap_alloc( sizeof(write_data_t) ))) return FALSE;
+        if (!(w = heap_alloc( sizeof(struct write_data) ))) return FALSE;
         w->hdr.request = request;
         w->hdr.proc    = task_write_data;
         w->buffer      = buffer;
@@ -2911,19 +3153,18 @@ BOOL WINAPI WinHttpWriteData( HINTERNET hrequest, LPCVOID buffer, DWORD to_write
         w->written     = written;
 
         addref_object( &request->hdr );
-        ret = queue_task( (task_header_t *)w );
+        ret = queue_task( (struct task_header *)w );
     }
     else
         ret = write_data( request, buffer, to_write, written, FALSE );
 
     release_object( &request->hdr );
-    if (ret) set_last_error( ERROR_SUCCESS );
+    if (ret) SetLastError( ERROR_SUCCESS );
     return ret;
 }
 
 enum request_state
 {
-    REQUEST_STATE_UNINITIALIZED,
     REQUEST_STATE_INITIALIZED,
     REQUEST_STATE_CANCELLED,
     REQUEST_STATE_OPEN,
@@ -2942,9 +3183,16 @@ struct winhttp_request
     HINTERNET hrequest;
     VARIANT data;
     WCHAR *verb;
+#ifdef __REACTOS__
     HANDLE thread;
+#else
+    HANDLE done;
+#endif
     HANDLE wait;
     HANDLE cancel;
+#ifndef __REACTOS__
+    BOOL proc_running;
+#endif
     char *buffer;
     DWORD offset;
     DWORD bytes_available;
@@ -2978,6 +3226,7 @@ static void cancel_request( struct winhttp_request *request )
 {
     if (request->state <= REQUEST_STATE_CANCELLED) return;
 
+#ifdef __REACTOS__
     SetEvent( request->cancel );
     LeaveCriticalSection( &request->cs );
     WaitForSingleObject( request->thread, INFINITE );
@@ -2987,10 +3236,18 @@ static void cancel_request( struct winhttp_request *request )
 
     CloseHandle( request->thread );
     request->thread = NULL;
-    CloseHandle( request->wait );
-    request->wait = NULL;
-    CloseHandle( request->cancel );
-    request->cancel = NULL;
+#else
+    if (request->proc_running)
+    {
+        SetEvent( request->cancel );
+        LeaveCriticalSection( &request->cs );
+
+        WaitForSingleObject( request->done, INFINITE );
+
+        EnterCriticalSection( &request->cs );
+    }
+    request->state = REQUEST_STATE_CANCELLED;
+#endif
 }
 
 /* critical section must be held */
@@ -3000,7 +3257,11 @@ static void free_request( struct winhttp_request *request )
     WinHttpCloseHandle( request->hrequest );
     WinHttpCloseHandle( request->hconnect );
     WinHttpCloseHandle( request->hsession );
+#ifdef __REACTOS__
     CloseHandle( request->thread );
+#else
+    CloseHandle( request->done );
+#endif
     CloseHandle( request->wait );
     CloseHandle( request->cancel );
     heap_free( (WCHAR *)request->proxy.lpszProxy );
@@ -3118,7 +3379,7 @@ void release_typelib(void)
 {
     unsigned i;
 
-    for (i = 0; i < sizeof(winhttp_typeinfo)/sizeof(*winhttp_typeinfo); i++)
+    for (i = 0; i < ARRAY_SIZE(winhttp_typeinfo); i++)
         if (winhttp_typeinfo[i])
             ITypeInfo_Release(winhttp_typeinfo[i]);
 
@@ -3318,7 +3579,7 @@ static HRESULT WINAPI winhttp_request_SetCredentials(
     }
     if (!WinHttpSetCredentials( request->hrequest, target, scheme, username, password, NULL ))
     {
-        err = get_last_error();
+        err = GetLastError();
     }
 done:
     LeaveCriticalSection( &request->cs );
@@ -3327,25 +3588,11 @@ done:
 
 static void initialize_request( struct winhttp_request *request )
 {
-    request->hrequest = NULL;
-    request->hconnect = NULL;
-    request->hsession = NULL;
-    request->thread   = NULL;
-    request->wait     = NULL;
-    request->cancel   = NULL;
-    request->buffer   = NULL;
-    request->verb     = NULL;
-    request->offset = 0;
-    request->bytes_available = 0;
-    request->bytes_read = 0;
-    request->error = ERROR_SUCCESS;
-    request->async = FALSE;
-    request->logon_policy = WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM;
-    request->disable_feature = 0;
-    request->proxy.dwAccessType = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
-    request->proxy.lpszProxy = NULL;
-    request->proxy.lpszProxyBypass = NULL;
-    request->resolve_timeout = 0;
+    request->wait   = CreateEventW( NULL, FALSE, FALSE, NULL );
+    request->cancel = CreateEventW( NULL, FALSE, FALSE, NULL );
+#ifndef __REACTOS__
+    request->done   = CreateEventW( NULL, FALSE, FALSE, NULL );
+#endif
     request->connect_timeout = 60000;
     request->send_timeout    = 30000;
     request->receive_timeout = 30000;
@@ -3369,8 +3616,17 @@ static void reset_request( struct winhttp_request *request )
     request->bytes_available = 0;
     request->bytes_read = 0;
     request->error    = ERROR_SUCCESS;
+    request->logon_policy = 0;
+    request->disable_feature = 0;
     request->async    = FALSE;
+    request->connect_timeout = 60000;
+    request->send_timeout    = 30000;
+    request->receive_timeout = 30000;
     request->url_codepage = CP_UTF8;
+    heap_free( request->proxy.lpszProxy );
+    request->proxy.lpszProxy = NULL;
+    heap_free( request->proxy.lpszProxyBypass );
+    request->proxy.lpszProxyBypass = NULL;
     VariantClear( &request->data );
     request->state = REQUEST_STATE_INITIALIZED;
 }
@@ -3404,11 +3660,10 @@ static HRESULT WINAPI winhttp_request_Open(
     uc.dwHostNameLength = ~0u;
     uc.dwUrlPathLength  = ~0u;
     uc.dwExtraInfoLength = ~0u;
-    if (!WinHttpCrackUrl( url, 0, 0, &uc )) return HRESULT_FROM_WIN32( get_last_error() );
+    if (!WinHttpCrackUrl( url, 0, 0, &uc )) return HRESULT_FROM_WIN32( GetLastError() );
 
     EnterCriticalSection( &request->cs );
-    if (request->state < REQUEST_STATE_INITIALIZED) initialize_request( request );
-    else reset_request( request );
+    reset_request( request );
 
     if (!(hostname = heap_alloc( (uc.dwHostNameLength + 1) * sizeof(WCHAR) ))) goto error;
     memcpy( hostname, uc.lpszHostName, uc.dwHostNameLength * sizeof(WCHAR) );
@@ -3427,31 +3682,31 @@ static HRESULT WINAPI winhttp_request_Open(
         if (!(request->hsession = WinHttpOpen( user_agentW, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, NULL, NULL,
                                                WINHTTP_FLAG_ASYNC )))
         {
-            err = get_last_error();
+            err = GetLastError();
             goto error;
         }
         if (!(request->hconnect = WinHttpConnect( request->hsession, hostname, uc.nPort, 0 )))
         {
             WinHttpCloseHandle( request->hsession );
             request->hsession = NULL;
-            err = get_last_error();
+            err = GetLastError();
             goto error;
         }
     }
     else if (!(request->hconnect = WinHttpConnect( request->hsession, hostname, uc.nPort, 0 )))
     {
-        err = get_last_error();
+        err = GetLastError();
         goto error;
     }
 
-    len = sizeof(httpsW) / sizeof(WCHAR);
+    len = ARRAY_SIZE( httpsW );
     if (uc.dwSchemeLength == len && !memcmp( uc.lpszScheme, httpsW, len * sizeof(WCHAR) ))
     {
         flags |= WINHTTP_FLAG_SECURE;
     }
     if (!(request->hrequest = WinHttpOpenRequest( request->hconnect, method, path, NULL, NULL, acceptW, flags )))
     {
-        err = get_last_error();
+        err = GetLastError();
         goto error;
     }
     WinHttpSetOption( request->hrequest, WINHTTP_OPTION_CONTEXT_VALUE, &request, sizeof(request) );
@@ -3510,7 +3765,7 @@ static HRESULT WINAPI winhttp_request_SetRequestHeader(
     if (!WinHttpAddRequestHeaders( request->hrequest, str, len,
                                    WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE ))
     {
-        err = get_last_error();
+        err = GetLastError();
     }
     heap_free( str );
 
@@ -3543,7 +3798,7 @@ static HRESULT WINAPI winhttp_request_GetResponseHeader(
     size = 0;
     if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_CUSTOM, header, NULL, &size, NULL ))
     {
-        err = get_last_error();
+        err = GetLastError();
         if (err != ERROR_INSUFFICIENT_BUFFER) goto done;
     }
     if (!(*value = SysAllocStringLen( NULL, size / sizeof(WCHAR) )))
@@ -3554,7 +3809,7 @@ static HRESULT WINAPI winhttp_request_GetResponseHeader(
     err = ERROR_SUCCESS;
     if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_CUSTOM, header, *value, &size, NULL ))
     {
-        err = get_last_error();
+        err = GetLastError();
         SysFreeString( *value );
     }
 done:
@@ -3582,7 +3837,7 @@ static HRESULT WINAPI winhttp_request_GetAllResponseHeaders(
     size = 0;
     if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL ))
     {
-        err = get_last_error();
+        err = GetLastError();
         if (err != ERROR_INSUFFICIENT_BUFFER) goto done;
     }
     if (!(*headers = SysAllocStringLen( NULL, size / sizeof(WCHAR) )))
@@ -3593,7 +3848,7 @@ static HRESULT WINAPI winhttp_request_GetAllResponseHeaders(
     err = ERROR_SUCCESS;
     if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, *headers, &size, NULL ))
     {
-        err = get_last_error();
+        err = GetLastError();
         SysFreeString( *headers );
     }
 done:
@@ -3621,7 +3876,9 @@ static void CALLBACK wait_status_callback( HINTERNET handle, DWORD_PTR context,
         request->error = result->dwError;
         break;
     }
-    default: break;
+    default:
+        request->error = ERROR_SUCCESS;
+        break;
     }
     SetEvent( request->wait );
 }
@@ -3635,19 +3892,38 @@ static void wait_set_status_callback( struct winhttp_request *request, DWORD sta
 static DWORD wait_for_completion( struct winhttp_request *request )
 {
     HANDLE handles[2] = { request->wait, request->cancel };
+#ifndef __REACTOS__
+    DWORD ret;
+#endif
 
     switch (WaitForMultipleObjects( 2, handles, FALSE, INFINITE ))
     {
     case WAIT_OBJECT_0:
+#ifndef __REACTOS__
+        ret = request->error;
+#endif
         break;
     case WAIT_OBJECT_0 + 1:
+#ifdef __REACTOS__
         request->error = ERROR_CANCELLED;
+#else
+        ret = request->error = ERROR_CANCELLED;
+        SetEvent( request->done );
+#endif
         break;
     default:
-        request->error = get_last_error();
+#ifdef __REACTOS__
+        request->error = GetLastError();
+#else
+        ret = request->error = GetLastError();
+#endif
         break;
     }
+#ifdef __REACTOS__
     return request->error;
+#else
+    return ret;
+#endif
 }
 
 static HRESULT request_receive( struct winhttp_request *request )
@@ -3657,7 +3933,7 @@ static HRESULT request_receive( struct winhttp_request *request )
     wait_set_status_callback( request, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE );
     if (!WinHttpReceiveResponse( request->hrequest, NULL ))
     {
-        return HRESULT_FROM_WIN32( get_last_error() );
+        return HRESULT_FROM_WIN32( GetLastError() );
     }
     if ((err = wait_for_completion( request ))) return HRESULT_FROM_WIN32( err );
     if (!strcmpW( request->verb, headW ))
@@ -3673,7 +3949,7 @@ static HRESULT request_receive( struct winhttp_request *request )
         wait_set_status_callback( request, WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE );
         if (!WinHttpQueryDataAvailable( request->hrequest, &request->bytes_available ))
         {
-            err = get_last_error();
+            err = GetLastError();
             goto error;
         }
         if ((err = wait_for_completion( request ))) goto error;
@@ -3694,7 +3970,7 @@ static HRESULT request_receive( struct winhttp_request *request )
         if (!WinHttpReadData( request->hrequest, request->buffer + request->offset,
                               request->bytes_available, &request->bytes_read ))
         {
-            err = get_last_error();
+            err = GetLastError();
             goto error;
         }
         if ((err = wait_for_completion( request ))) goto error;
@@ -3713,19 +3989,19 @@ error:
 static DWORD request_set_parameters( struct winhttp_request *request )
 {
     if (!WinHttpSetOption( request->hrequest, WINHTTP_OPTION_PROXY, &request->proxy,
-                           sizeof(request->proxy) )) return get_last_error();
+                           sizeof(request->proxy) )) return GetLastError();
 
     if (!WinHttpSetOption( request->hrequest, WINHTTP_OPTION_AUTOLOGON_POLICY, &request->logon_policy,
-                           sizeof(request->logon_policy) )) return get_last_error();
+                           sizeof(request->logon_policy) )) return GetLastError();
 
     if (!WinHttpSetOption( request->hrequest, WINHTTP_OPTION_DISABLE_FEATURE, &request->disable_feature,
-                           sizeof(request->disable_feature) )) return get_last_error();
+                           sizeof(request->disable_feature) )) return GetLastError();
 
     if (!WinHttpSetTimeouts( request->hrequest,
                              request->resolve_timeout,
                              request->connect_timeout,
                              request->send_timeout,
-                             request->receive_timeout )) return get_last_error();
+                             request->receive_timeout )) return GetLastError();
     return ERROR_SUCCESS;
 }
 
@@ -3790,7 +4066,7 @@ static HRESULT request_send( struct winhttp_request *request )
     wait_set_status_callback( request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT );
     if (!WinHttpSendRequest( request->hrequest, NULL, 0, ptr, size, size, 0 ))
     {
-        err = get_last_error();
+        err = GetLastError();
         goto error;
     }
     if ((err = wait_for_completion( request ))) goto error;
@@ -3805,6 +4081,7 @@ error:
     return HRESULT_FROM_WIN32( err );
 }
 
+#ifdef __REACTOS__
 static HRESULT request_send_and_receive( struct winhttp_request *request )
 {
     HRESULT hr = request_send( request );
@@ -3817,15 +4094,31 @@ static DWORD CALLBACK send_and_receive_proc( void *arg )
     struct winhttp_request *request = (struct winhttp_request *)arg;
     return request_send_and_receive( request );
 }
+#else
+static void CALLBACK send_and_receive_proc( TP_CALLBACK_INSTANCE *instance, void *ctx )
+{
+    struct winhttp_request *request = (struct winhttp_request *)ctx;
+    if (request_send( request ) == S_OK) request_receive( request );
+    SetEvent( request->done );
+}
+#endif
 
 /* critical section must be held */
 static DWORD request_wait( struct winhttp_request *request, DWORD timeout )
 {
+#ifdef __REACTOS__
     HANDLE thread = request->thread;
+#else
+    HANDLE done = request->done;
+#endif
     DWORD err, ret;
 
     LeaveCriticalSection( &request->cs );
+#ifdef __REACTOS__
     while ((err = MsgWaitForMultipleObjects( 1, &thread, FALSE, timeout, QS_ALLINPUT )) == WAIT_OBJECT_0 + 1)
+#else
+    while ((err = MsgWaitForMultipleObjects( 1, &done, FALSE, timeout, QS_ALLINPUT )) == WAIT_OBJECT_0 + 1)
+#endif
     {
         MSG msg;
         while (PeekMessageW( &msg, NULL, 0, 0, PM_REMOVE ))
@@ -3837,17 +4130,19 @@ static DWORD request_wait( struct winhttp_request *request, DWORD timeout )
     switch (err)
     {
     case WAIT_OBJECT_0:
-        ret = ERROR_SUCCESS;
+        ret = request->error;
         break;
     case WAIT_TIMEOUT:
         ret = ERROR_TIMEOUT;
         break;
-    case WAIT_FAILED:
     default:
-        ret = get_last_error();
+        ret = GetLastError();
         break;
     }
     EnterCriticalSection( &request->cs );
+#ifndef __REACTOS__
+    if (err == WAIT_OBJECT_0) request->proc_running = FALSE;
+#endif
     return ret;
 }
 
@@ -3877,13 +4172,18 @@ static HRESULT WINAPI winhttp_request_Send(
         LeaveCriticalSection( &request->cs );
         return hr;
     }
+#ifdef __REACTOS__
     if (!(request->thread = CreateThread( NULL, 0, send_and_receive_proc, request, 0, NULL )))
+#else
+    if (!TrySubmitThreadpoolCallback( send_and_receive_proc, request, NULL ))
+#endif
     {
         LeaveCriticalSection( &request->cs );
-        return HRESULT_FROM_WIN32( get_last_error() );
+        return HRESULT_FROM_WIN32( GetLastError() );
     }
-    request->wait = CreateEventW( NULL, FALSE, FALSE, NULL );
-    request->cancel = CreateEventW( NULL, FALSE, FALSE, NULL );
+#ifndef __REACTOS__
+    request->proc_running = TRUE;
+#endif
     if (!request->async)
     {
         hr = HRESULT_FROM_WIN32( request_wait( request, INFINITE ) );
@@ -3912,7 +4212,7 @@ static HRESULT WINAPI winhttp_request_get_Status(
     flags = WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER;
     if (!WinHttpQueryHeaders( request->hrequest, flags, NULL, &status_code, &len, &index ))
     {
-        err = get_last_error();
+        err = GetLastError();
         goto done;
     }
     *status = status_code;
@@ -3941,7 +4241,7 @@ static HRESULT WINAPI winhttp_request_get_StatusText(
     }
     if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_STATUS_TEXT, NULL, NULL, &len, &index ))
     {
-        err = get_last_error();
+        err = GetLastError();
         if (err != ERROR_INSUFFICIENT_BUFFER) goto done;
     }
     if (!(*status = SysAllocStringLen( NULL, len / sizeof(WCHAR) )))
@@ -3953,7 +4253,7 @@ static HRESULT WINAPI winhttp_request_get_StatusText(
     err = ERROR_SUCCESS;
     if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_STATUS_TEXT, NULL, *status, &len, &index ))
     {
-        err = get_last_error();
+        err = GetLastError();
         SysFreeString( *status );
     }
 done:
@@ -3970,12 +4270,12 @@ static DWORD request_get_codepage( struct winhttp_request *request, UINT *codepa
 
     *codepage = CP_ACP;
     if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_CONTENT_TYPE, NULL, NULL, &size, NULL ) &&
-        get_last_error() == ERROR_INSUFFICIENT_BUFFER)
+        GetLastError() == ERROR_INSUFFICIENT_BUFFER)
     {
         if (!(buffer = heap_alloc( size ))) return ERROR_OUTOFMEMORY;
         if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_CONTENT_TYPE, NULL, buffer, &size, NULL ))
         {
-            return get_last_error();
+            return GetLastError();
         }
         if ((p = strstrW( buffer, charsetW )))
         {
@@ -4372,11 +4672,9 @@ static HRESULT WINAPI winhttp_request_WaitForResponse(
         err = ERROR_SUCCESS;
         break;
 
-    case ERROR_SUCCESS:
+    default:
         if (succeeded) *succeeded = VARIANT_TRUE;
         break;
-
-    default: break;
     }
     LeaveCriticalSection( &request->cs );
     return HRESULT_FROM_WIN32( err );
@@ -4487,15 +4785,12 @@ HRESULT WinHttpRequest_create( void **obj )
 
     TRACE("%p\n", obj);
 
-    if (!(request = heap_alloc( sizeof(*request) ))) return E_OUTOFMEMORY;
+    if (!(request = heap_alloc_zero( sizeof(*request) ))) return E_OUTOFMEMORY;
     request->IWinHttpRequest_iface.lpVtbl = &winhttp_request_vtbl;
     request->refs = 1;
-    request->state = REQUEST_STATE_UNINITIALIZED;
-    request->proxy.lpszProxy = NULL;
-    request->proxy.lpszProxyBypass = NULL;
-    request->url_codepage = CP_UTF8;
     InitializeCriticalSection( &request->cs );
     request->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": winhttp_request.cs");
+    initialize_request( request );
 
     *obj = &request->IWinHttpRequest_iface;
     TRACE("returning iface %p\n", *obj);
index 7cfc240..8e24de7 100644 (file)
@@ -17,9 +17,6 @@
  */
 
 #include "config.h"
-#include "wine/port.h"
-#include "wine/debug.h"
-
 #include <stdarg.h>
 #include <stdlib.h>
 
 #include <CoreServices/CoreServices.h>
 #undef GetCurrentThread
 #undef LoadResource
-#undef DPRINTF
 #endif
 
 #include "windef.h"
 #include "winbase.h"
-#ifndef __MINGW32__
-#define USE_WS_PREFIX
-#endif
 #include "winsock2.h"
 #include "ws2ipdef.h"
+#include "ws2tcpip.h"
 #include "winhttp.h"
-#include "wincrypt.h"
 #include "winreg.h"
+#include "wine/winternl.h"
 #define COBJMACROS
 #include "ole2.h"
 #include "dispex.h"
 #include "activscp.h"
 
+#include "wine/debug.h"
 #include "winhttp_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
 
-#define DEFAULT_RESOLVE_TIMEOUT     0
-#define DEFAULT_CONNECT_TIMEOUT     20000
-#define DEFAULT_SEND_TIMEOUT        30000
-#define DEFAULT_RECEIVE_TIMEOUT     30000
-
-void set_last_error( DWORD error )
-{
-    /* FIXME */
-    SetLastError( error );
-}
-
-DWORD get_last_error( void )
-{
-    /* FIXME */
-    return GetLastError();
-}
+#define DEFAULT_RESOLVE_TIMEOUT             0
+#define DEFAULT_CONNECT_TIMEOUT             20000
+#define DEFAULT_SEND_TIMEOUT                30000
+#define DEFAULT_RECEIVE_TIMEOUT             30000
+#define DEFAULT_RECEIVE_RESPONSE_TIMEOUT    ~0u
 
-void send_callback( object_header_t *hdr, DWORD status, LPVOID info, DWORD buflen )
+void send_callback( struct object_header *hdr, DWORD status, void *info, DWORD buflen )
 {
     if (hdr->callback && (hdr->notify_mask & status))
     {
@@ -90,22 +74,17 @@ BOOL WINAPI WinHttpCheckPlatform( void )
 /***********************************************************************
  *          session_destroy (internal)
  */
-static void session_destroy( object_header_t *hdr )
+static void session_destroy( struct object_header *hdr )
 {
-    session_t *session = (session_t *)hdr;
-    struct list *item, *next;
-    domain_t *domain;
+    struct session *session = (struct session *)hdr;
 
     TRACE("%p\n", session);
 
     if (session->unload_event) SetEvent( session->unload_event );
-    if (session->cred_handle_initialized) FreeCredentialsHandle( &session->cred_handle );
+    destroy_cookies( session );
 
-    LIST_FOR_EACH_SAFE( item, next, &session->cookie_cache )
-    {
-        domain = LIST_ENTRY( item, domain_t, entry );
-        delete_domain( domain );
-    }
+    session->cs.DebugInfo->Spare[0] = 0;
+    DeleteCriticalSection( &session->cs );
     heap_free( session->agent );
     heap_free( session->proxy_server );
     heap_free( session->proxy_bypass );
@@ -114,9 +93,9 @@ static void session_destroy( object_header_t *hdr )
     heap_free( session );
 }
 
-static BOOL session_query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD buflen )
+static BOOL session_query_option( struct object_header *hdr, DWORD option, void *buffer, DWORD *buflen )
 {
-    session_t *session = (session_t *)hdr;
+    struct session *session = (struct session *)hdr;
 
     switch (option)
     {
@@ -125,7 +104,7 @@ static BOOL session_query_option( object_header_t *hdr, DWORD option, LPVOID buf
         if (!buffer || *buflen < sizeof(DWORD))
         {
             *buflen = sizeof(DWORD);
-            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
             return FALSE;
         }
 
@@ -137,28 +116,37 @@ static BOOL session_query_option( object_header_t *hdr, DWORD option, LPVOID buf
         *(DWORD *)buffer = session->resolve_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
+
     case WINHTTP_OPTION_CONNECT_TIMEOUT:
         *(DWORD *)buffer = session->connect_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
+
     case WINHTTP_OPTION_SEND_TIMEOUT:
         *(DWORD *)buffer = session->send_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
+
     case WINHTTP_OPTION_RECEIVE_TIMEOUT:
-        *(DWORD *)buffer = session->recv_timeout;
+        *(DWORD *)buffer = session->receive_timeout;
+        *buflen = sizeof(DWORD);
+        return TRUE;
+
+    case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
+        *(DWORD *)buffer = session->receive_response_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
+
     default:
         FIXME("unimplemented option %u\n", option);
-        set_last_error( ERROR_INVALID_PARAMETER );
+        SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
 }
 
-static BOOL session_set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD buflen )
+static BOOL session_set_option( struct object_header *hdr, DWORD option, void *buffer, DWORD buflen )
 {
-    session_t *session = (session_t *)hdr;
+    struct session *session = (struct session *)hdr;
 
     switch (option)
     {
@@ -175,7 +163,7 @@ static BOOL session_set_option( object_header_t *hdr, DWORD option, LPVOID buffe
 
         if (buflen != sizeof(policy))
         {
-            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
             return FALSE;
         }
 
@@ -188,72 +176,81 @@ static BOOL session_set_option( object_header_t *hdr, DWORD option, LPVOID buffe
     {
         if (buflen != sizeof(session->secure_protocols))
         {
-            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
             return FALSE;
         }
+        EnterCriticalSection( &session->cs );
         session->secure_protocols = *(DWORD *)buffer;
+        LeaveCriticalSection( &session->cs );
         TRACE("0x%x\n", session->secure_protocols);
         return TRUE;
     }
     case WINHTTP_OPTION_DISABLE_FEATURE:
-        set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+        SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
         return FALSE;
+
     case WINHTTP_OPTION_RESOLVE_TIMEOUT:
         session->resolve_timeout = *(DWORD *)buffer;
         return TRUE;
+
     case WINHTTP_OPTION_CONNECT_TIMEOUT:
         session->connect_timeout = *(DWORD *)buffer;
         return TRUE;
+
     case WINHTTP_OPTION_SEND_TIMEOUT:
         session->send_timeout = *(DWORD *)buffer;
         return TRUE;
+
     case WINHTTP_OPTION_RECEIVE_TIMEOUT:
-        session->recv_timeout = *(DWORD *)buffer;
+        session->receive_timeout = *(DWORD *)buffer;
         return TRUE;
+
+    case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
+        session->receive_response_timeout = *(DWORD *)buffer;
+        return TRUE;
+
     case WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH:
-        FIXME("WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH: 0x%x\n", *(DWORD *)buffer);
+        session->passport_flags = *(DWORD *)buffer;
         return TRUE;
+
     case WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT:
         TRACE("WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT: %p\n", *(HANDLE *)buffer);
         session->unload_event = *(HANDLE *)buffer;
         return TRUE;
+
     case WINHTTP_OPTION_MAX_CONNS_PER_SERVER:
         FIXME("WINHTTP_OPTION_MAX_CONNS_PER_SERVER: %d\n", *(DWORD *)buffer);
         return TRUE;
+
     case WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER:
         FIXME("WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER: %d\n", *(DWORD *)buffer);
         return TRUE;
+
     default:
         FIXME("unimplemented option %u\n", option);
-        set_last_error( ERROR_WINHTTP_INVALID_OPTION );
+        SetLastError( ERROR_WINHTTP_INVALID_OPTION );
         return FALSE;
     }
 }
 
-static const object_vtbl_t session_vtbl =
+static const struct object_vtbl session_vtbl =
 {
     session_destroy,
     session_query_option,
     session_set_option
 };
 
-#ifdef __REACTOS__
-BOOL netconn_init_winsock();
-#endif /* __REACTOS__ */
 /***********************************************************************
  *          WinHttpOpen (winhttp.@)
  */
 HINTERNET WINAPI WinHttpOpen( LPCWSTR agent, DWORD access, LPCWSTR proxy, LPCWSTR bypass, DWORD flags )
 {
-    session_t *session;
+    struct session *session;
     HINTERNET handle = NULL;
-#ifdef __REACTOS__
-    if (!netconn_init_winsock()) return NULL;
-#endif
 
     TRACE("%s, %u, %s, %s, 0x%08x\n", debugstr_w(agent), access, debugstr_w(proxy), debugstr_w(bypass), flags);
 
-    if (!(session = heap_alloc_zero( sizeof(session_t) ))) return NULL;
+    if (!(session = heap_alloc_zero( sizeof(struct session) ))) return NULL;
 
     session->hdr.type = WINHTTP_HANDLE_TYPE_SESSION;
     session->hdr.vtbl = &session_vtbl;
@@ -264,8 +261,11 @@ HINTERNET WINAPI WinHttpOpen( LPCWSTR agent, DWORD access, LPCWSTR proxy, LPCWST
     session->resolve_timeout = DEFAULT_RESOLVE_TIMEOUT;
     session->connect_timeout = DEFAULT_CONNECT_TIMEOUT;
     session->send_timeout = DEFAULT_SEND_TIMEOUT;
-    session->recv_timeout = DEFAULT_RECEIVE_TIMEOUT;
+    session->receive_timeout = DEFAULT_RECEIVE_TIMEOUT;
+    session->receive_response_timeout = DEFAULT_RECEIVE_RESPONSE_TIMEOUT;
     list_init( &session->cookie_cache );
+    InitializeCriticalSection( &session->cs );
+    session->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": session.cs");
 
     if (agent && !(session->agent = strdupW( agent ))) goto end;
     if (access == WINHTTP_ACCESS_TYPE_DEFAULT_PROXY)
@@ -300,16 +300,16 @@ HINTERNET WINAPI WinHttpOpen( LPCWSTR agent, DWORD access, LPCWSTR proxy, LPCWST
 end:
     release_object( &session->hdr );
     TRACE("returning %p\n", handle);
-    if (handle) set_last_error( ERROR_SUCCESS );
+    if (handle) SetLastError( ERROR_SUCCESS );
     return handle;
 }
 
 /***********************************************************************
  *          connect_destroy (internal)
  */
-static void connect_destroy( object_header_t *hdr )
+static void connect_destroy( struct object_header *hdr )
 {
-    connect_t *connect = (connect_t *)hdr;
+    struct connect *connect = (struct connect *)hdr;
 
     TRACE("%p\n", connect);
 
@@ -322,9 +322,9 @@ static void connect_destroy( object_header_t *hdr )
     heap_free( connect );
 }
 
-static BOOL connect_query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD buflen )
+static BOOL connect_query_option( struct object_header *hdr, DWORD option, void *buffer, DWORD *buflen )
 {
-    connect_t *connect = (connect_t *)hdr;
+    struct connect *connect = (struct connect *)hdr;
 
     switch (option)
     {
@@ -333,11 +333,11 @@ static BOOL connect_query_option( object_header_t *hdr, DWORD option, LPVOID buf
         if (!buffer || *buflen < sizeof(HINTERNET))
         {
             *buflen = sizeof(HINTERNET);
-            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
             return FALSE;
         }
 
-        *(HINTERNET *)buffer = ((object_header_t *)connect->session)->handle;
+        *(HINTERNET *)buffer = ((struct object_header *)connect->session)->handle;
         *buflen = sizeof(HINTERNET);
         return TRUE;
     }
@@ -345,26 +345,35 @@ static BOOL connect_query_option( object_header_t *hdr, DWORD option, LPVOID buf
         *(DWORD *)buffer = connect->session->resolve_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
+
     case WINHTTP_OPTION_CONNECT_TIMEOUT:
         *(DWORD *)buffer = connect->session->connect_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
+
     case WINHTTP_OPTION_SEND_TIMEOUT:
         *(DWORD *)buffer = connect->session->send_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
+
     case WINHTTP_OPTION_RECEIVE_TIMEOUT:
-        *(DWORD *)buffer = connect->session->recv_timeout;
+        *(DWORD *)buffer = connect->session->receive_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
+
+    case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
+        *(DWORD *)buffer = connect->session->receive_response_timeout;
+        *buflen = sizeof(DWORD);
+        return TRUE;
+
     default:
         FIXME("unimplemented option %u\n", option);
-        set_last_error( ERROR_INVALID_PARAMETER );
+        SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
 }
 
-static const object_vtbl_t connect_vtbl =
+static const struct object_vtbl connect_vtbl =
 {
     connect_destroy,
     connect_query_option,
@@ -425,7 +434,7 @@ static BOOL domain_matches(LPCWSTR server, LPCWSTR domain)
 /* Matches INTERNET_MAX_HOST_NAME_LENGTH in wininet.h, also RFC 1035 */
 #define MAX_HOST_NAME_LENGTH 256
 
-static BOOL should_bypass_proxy(session_t *session, LPCWSTR server)
+static BOOL should_bypass_proxy(struct session *session, LPCWSTR server)
 {
     LPCWSTR ptr;
     BOOL ret = FALSE;
@@ -456,9 +465,9 @@ static BOOL should_bypass_proxy(session_t *session, LPCWSTR server)
     return ret;
 }
 
-BOOL set_server_for_hostname( connect_t *connect, LPCWSTR server, INTERNET_PORT port )
+BOOL set_server_for_hostname( struct connect *connect, const WCHAR *server, INTERNET_PORT port )
 {
-    session_t *session = connect->session;
+    struct session *session = connect->session;
     BOOL ret = TRUE;
 
     if (session->proxy_server && !should_bypass_proxy(session, server))
@@ -523,29 +532,29 @@ end:
  */
 HINTERNET WINAPI WinHttpConnect( HINTERNET hsession, LPCWSTR server, INTERNET_PORT port, DWORD reserved )
 {
-    connect_t *connect;
-    session_t *session;
+    struct connect *connect;
+    struct session *session;
     HINTERNET hconnect = NULL;
 
     TRACE("%p, %s, %u, %x\n", hsession, debugstr_w(server), port, reserved);
 
     if (!server)
     {
-        set_last_error( ERROR_INVALID_PARAMETER );
+        SetLastError( ERROR_INVALID_PARAMETER );
         return NULL;
     }
-    if (!(session = (session_t *)grab_object( hsession )))
+    if (!(session = (struct session *)grab_object( hsession )))
     {
-        set_last_error( ERROR_INVALID_HANDLE );
+        SetLastError( ERROR_INVALID_HANDLE );
         return NULL;
     }
     if (session->hdr.type != WINHTTP_HANDLE_TYPE_SESSION)
     {
         release_object( &session->hdr );
-        set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+        SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
         return NULL;
     }
-    if (!(connect = heap_alloc_zero( sizeof(connect_t) )))
+    if (!(connect = heap_alloc_zero( sizeof(struct connect) )))
     {
         release_object( &session->hdr );
         return NULL;
@@ -577,32 +586,44 @@ end:
     release_object( &connect->hdr );
     release_object( &session->hdr );
     TRACE("returning %p\n", hconnect);
-    if (hconnect) set_last_error( ERROR_SUCCESS );
+    if (hconnect) SetLastError( ERROR_SUCCESS );
     return hconnect;
 }
 
 /***********************************************************************
  *          request_destroy (internal)
  */
-static void request_destroy( object_header_t *hdr )
+static void request_destroy( struct object_header *hdr )
 {
-    request_t *request = (request_t *)hdr;
+    struct request *request = (struct request *)hdr;
     unsigned int i, j;
 
     TRACE("%p\n", request);
 
+#ifdef __REACTOS__
     if (request->task_thread)
+#else
+    if (request->task_proc_running)
+#endif
     {
-        /* Signal to the task proc to quit.  It will call
-           this again when it does. */
+        /* Signal to the task proc to quit. It will call this again when it does. */
+#ifdef __REACTOS__
         HANDLE thread = request->task_thread;
         request->task_thread = 0;
         SetEvent( request->task_cancel );
         CloseHandle( thread );
+#else
+        request->task_proc_running = FALSE;
+        SetEvent( request->task_cancel );
+#endif
         return;
     }
     release_object( &request->connect->hdr );
 
+    if (request->cred_handle_initialized) FreeCredentialsHandle( &request->cred_handle );
+    CertFreeCertificateContext( request->server_cert );
+    CertFreeCertificateContext( request->client_cert );
+
     destroy_authinfo( request->authinfo );
     destroy_authinfo( request->proxy_authinfo );
 
@@ -652,46 +673,8 @@ static WCHAR *blob_to_str( DWORD encoding, CERT_NAME_BLOB *blob )
     return ret;
 }
 
-static BOOL convert_sockaddr( const struct sockaddr *addr, SOCKADDR_STORAGE *addr_storage )
+static BOOL copy_sockaddr( const struct sockaddr *addr, SOCKADDR_STORAGE *addr_storage )
 {
-#if !defined(__MINGW32__) && !defined(_MSC_VER)
-    switch (addr->sa_family)
-    {
-    case AF_INET:
-    {
-        const struct sockaddr_in *addr_unix = (const struct sockaddr_in *)addr;
-        struct WS_sockaddr_in *addr_win = (struct WS_sockaddr_in *)addr_storage;
-        char *p;
-
-        addr_win->sin_family = WS_AF_INET;
-        addr_win->sin_port   = addr_unix->sin_port;
-        memcpy( &addr_win->sin_addr, &addr_unix->sin_addr, 4 );
-        p = (char *)&addr_win->sin_addr + 4;
-        memset( p, 0, sizeof(*addr_storage) - (p - (char *)addr_win) );
-        return TRUE;
-    }
-    case AF_INET6:
-    {
-        const struct sockaddr_in6 *addr_unix = (const struct sockaddr_in6 *)addr;
-        struct WS_sockaddr_in6 *addr_win = (struct WS_sockaddr_in6 *)addr_storage;
-
-        addr_win->sin6_family   = WS_AF_INET6;
-        addr_win->sin6_port     = addr_unix->sin6_port;
-        addr_win->sin6_flowinfo = addr_unix->sin6_flowinfo;
-        memcpy( &addr_win->sin6_addr, &addr_unix->sin6_addr, 16 );
-#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
-        addr_win->sin6_scope_id = addr_unix->sin6_scope_id;
-#else
-        addr_win->sin6_scope_id = 0;
-#endif
-        memset( addr_win + 1, 0, sizeof(*addr_storage) - sizeof(*addr_win) );
-        return TRUE;
-    }
-    default:
-        ERR("unhandled family %u\n", addr->sa_family);
-        return FALSE;
-    }
-#else
     switch (addr->sa_family)
     {
     case AF_INET:
@@ -714,30 +697,27 @@ static BOOL convert_sockaddr( const struct sockaddr *addr, SOCKADDR_STORAGE *add
         ERR("unhandled family %u\n", addr->sa_family);
         return FALSE;
     }
-#endif
 }
 
-static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD buflen )
+static BOOL request_query_option( struct object_header *hdr, DWORD option, void *buffer, DWORD *buflen )
 {
-    request_t *request = (request_t *)hdr;
+    struct request *request = (struct request *)hdr;
 
     switch (option)
     {
     case WINHTTP_OPTION_SECURITY_FLAGS:
     {
-        DWORD flags = 0;
+        DWORD flags;
         int bits;
 
         if (!buffer || *buflen < sizeof(flags))
         {
             *buflen = sizeof(flags);
-            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
             return FALSE;
         }
 
-        flags = 0;
-        if (hdr->flags & WINHTTP_FLAG_SECURE) flags |= SECURITY_FLAG_SECURE;
-        flags |= request->security_flags;
+        flags = request->security_flags;
         if (request->netconn)
         {
             bits = netconn_get_cipher_strength( request->netconn );
@@ -759,18 +739,18 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
         if (!buffer || *buflen < sizeof(cert))
         {
             *buflen = sizeof(cert);
-            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
             return FALSE;
         }
 
-        if (!request->netconn || !(cert = netconn_get_certificate( request->netconn ))) return FALSE;
+        if (!(cert = CertDuplicateCertificateContext( request->server_cert ))) return FALSE;
         *(CERT_CONTEXT **)buffer = (CERT_CONTEXT *)cert;
         *buflen = sizeof(cert);
         return TRUE;
     }
     case WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT:
     {
-        const CERT_CONTEXT *cert;
+        const CERT_CONTEXT *cert = request->server_cert;
         const CRYPT_OID_INFO *oidInfo;
         WINHTTP_CERTIFICATE_INFO *ci = buffer;
 
@@ -779,19 +759,17 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
         if (!buffer || *buflen < sizeof(*ci))
         {
             *buflen = sizeof(*ci);
-            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
             return FALSE;
         }
-        if (!request->netconn || !(cert = netconn_get_certificate( request->netconn ))) return FALSE;
+        if (!cert) return FALSE;
 
         ci->ftExpiry = cert->pCertInfo->NotAfter;
         ci->ftStart  = cert->pCertInfo->NotBefore;
         ci->lpszSubjectInfo = blob_to_str( cert->dwCertEncodingType, &cert->pCertInfo->Subject );
         ci->lpszIssuerInfo  = blob_to_str( cert->dwCertEncodingType, &cert->pCertInfo->Issuer );
         ci->lpszProtocolName      = NULL;
-        oidInfo = CryptFindOIDInfo( CRYPT_OID_INFO_OID_KEY,
-                                    cert->pCertInfo->SignatureAlgorithm.pszObjId,
-                                    0 );
+        oidInfo = CryptFindOIDInfo( CRYPT_OID_INFO_OID_KEY, cert->pCertInfo->SignatureAlgorithm.pszObjId, 0 );
         if (oidInfo)
             ci->lpszSignatureAlgName = (LPWSTR)oidInfo->pwszName;
         else
@@ -799,7 +777,6 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
         ci->lpszEncryptionAlgName = NULL;
         ci->dwKeySize = request->netconn ? netconn_get_cipher_strength( request->netconn ) : 0;
 
-        CertFreeCertificateContext( cert );
         *buflen = sizeof(*ci);
         return TRUE;
     }
@@ -808,7 +785,7 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
         if (!buffer || *buflen < sizeof(DWORD))
         {
             *buflen = sizeof(DWORD);
-            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
             return FALSE;
         }
 
@@ -826,17 +803,17 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
         if (!buffer || *buflen < sizeof(*info))
         {
             *buflen = sizeof(*info);
-            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
             return FALSE;
         }
         if (!request->netconn)
         {
-            set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_STATE );
+            SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_STATE );
             return FALSE;
         }
         if (getsockname( request->netconn->socket, &local, &len )) return FALSE;
-        if (!convert_sockaddr( &local, &info->LocalAddress )) return FALSE;
-        if (!convert_sockaddr( remote, &info->RemoteAddress )) return FALSE;
+        if (!copy_sockaddr( &local, &info->LocalAddress )) return FALSE;
+        if (!copy_sockaddr( remote, &info->RemoteAddress )) return FALSE;
         info->cbSize = sizeof(*info);
         return TRUE;
     }
@@ -844,16 +821,24 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
         *(DWORD *)buffer = request->resolve_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
+
     case WINHTTP_OPTION_CONNECT_TIMEOUT:
         *(DWORD *)buffer = request->connect_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
+
     case WINHTTP_OPTION_SEND_TIMEOUT:
         *(DWORD *)buffer = request->send_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
+
     case WINHTTP_OPTION_RECEIVE_TIMEOUT:
-        *(DWORD *)buffer = request->recv_timeout;
+        *(DWORD *)buffer = request->receive_timeout;
+        *buflen = sizeof(DWORD);
+        return TRUE;
+
+    case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
+        *(DWORD *)buffer = request->receive_response_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
 
@@ -875,7 +860,7 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
 
     default:
         FIXME("unimplemented option %u\n", option);
-        set_last_error( ERROR_INVALID_PARAMETER );
+        SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
 }
@@ -889,13 +874,13 @@ static WCHAR *buffer_to_str( WCHAR *buffer, DWORD buflen )
         ret[buflen] = 0;
         return ret;
     }
-    set_last_error( ERROR_OUTOFMEMORY );
+    SetLastError( ERROR_OUTOFMEMORY );
     return NULL;
 }
 
-static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD buflen )
+static BOOL request_set_option( struct object_header *hdr, DWORD option, void *buffer, DWORD buflen )
 {
-    request_t *request = (request_t *)hdr;
+    struct request *request = (struct request *)hdr;
 
     switch (option)
     {
@@ -912,7 +897,7 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffe
 
         if (buflen != sizeof(DWORD))
         {
-            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
             return FALSE;
         }
 
@@ -927,7 +912,7 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffe
 
         if (buflen != sizeof(DWORD))
         {
-            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
             return FALSE;
         }
 
@@ -942,7 +927,7 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffe
 
         if (buflen != sizeof(DWORD))
         {
-            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
             return FALSE;
         }
 
@@ -954,20 +939,21 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffe
     case WINHTTP_OPTION_SECURITY_FLAGS:
     {
         DWORD flags;
+        static const DWORD accepted = SECURITY_FLAG_IGNORE_CERT_CN_INVALID   |
+                                      SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
+                                      SECURITY_FLAG_IGNORE_UNKNOWN_CA        |
+                                      SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE;
 
         if (buflen < sizeof(DWORD))
         {
-            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
             return FALSE;
         }
         flags = *(DWORD *)buffer;
         TRACE("0x%x\n", flags);
-        if (!(flags & (SECURITY_FLAG_IGNORE_CERT_CN_INVALID   |
-                       SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
-                       SECURITY_FLAG_IGNORE_UNKNOWN_CA        |
-                       SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE)))
+        if (flags && (flags & ~accepted))
         {
-            set_last_error( ERROR_INVALID_PARAMETER );
+            SetLastError( ERROR_INVALID_PARAMETER );
             return FALSE;
         }
         request->security_flags = flags;
@@ -976,19 +962,26 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffe
     case WINHTTP_OPTION_RESOLVE_TIMEOUT:
         request->resolve_timeout = *(DWORD *)buffer;
         return TRUE;
+
     case WINHTTP_OPTION_CONNECT_TIMEOUT:
         request->connect_timeout = *(DWORD *)buffer;
         return TRUE;
+
     case WINHTTP_OPTION_SEND_TIMEOUT:
         request->send_timeout = *(DWORD *)buffer;
         return TRUE;
+
     case WINHTTP_OPTION_RECEIVE_TIMEOUT:
-        request->recv_timeout = *(DWORD *)buffer;
+        request->receive_timeout = *(DWORD *)buffer;
+        return TRUE;
+
+    case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
+        request->receive_response_timeout = *(DWORD *)buffer;
         return TRUE;
 
     case WINHTTP_OPTION_USERNAME:
     {
-        connect_t *connect = request->connect;
+        struct connect *connect = request->connect;
 
         heap_free( connect->username );
         if (!(connect->username = buffer_to_str( buffer, buflen ))) return FALSE;
@@ -996,7 +989,7 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffe
     }
     case WINHTTP_OPTION_PASSWORD:
     {
-        connect_t *connect = request->connect;
+        struct connect *connect = request->connect;
 
         heap_free( connect->password );
         if (!(connect->password = buffer_to_str( buffer, buflen ))) return FALSE;
@@ -1004,7 +997,7 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffe
     }
     case WINHTTP_OPTION_PROXY_USERNAME:
     {
-        session_t *session = request->connect->session;
+        struct session *session = request->connect->session;
 
         heap_free( session->proxy_username );
         if (!(session->proxy_username = buffer_to_str( buffer, buflen ))) return FALSE;
@@ -1012,82 +1005,136 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffe
     }
     case WINHTTP_OPTION_PROXY_PASSWORD:
     {
-        session_t *session = request->connect->session;
+        struct session *session = request->connect->session;
 
         heap_free( session->proxy_password );
         if (!(session->proxy_password = buffer_to_str( buffer, buflen ))) return FALSE;
         return TRUE;
     }
     case WINHTTP_OPTION_CLIENT_CERT_CONTEXT:
+    {
+        const CERT_CONTEXT *cert;
+
         if (!(hdr->flags & WINHTTP_FLAG_SECURE))
         {
             SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_STATE );
             return FALSE;
         }
-        FIXME("WINHTTP_OPTION_CLIENT_CERT_CONTEXT\n");
+        if (!buffer)
+        {
+            CertFreeCertificateContext( request->client_cert );
+            request->client_cert = NULL;
+        }
+        else if (buflen >= sizeof(cert))
+        {
+            if (!(cert = CertDuplicateCertificateContext( buffer ))) return FALSE;
+            CertFreeCertificateContext( request->client_cert );
+            request->client_cert = cert;
+        }
+        else
+        {
+            SetLastError( ERROR_INVALID_PARAMETER );
+            return FALSE;
+        }
+
+        if (request->cred_handle_initialized)
+        {
+            FreeCredentialsHandle( &request->cred_handle );
+            request->cred_handle_initialized = FALSE;
+        }
+
         return TRUE;
+    }
+    case WINHTTP_OPTION_ENABLE_FEATURE:
+        if(buflen == sizeof( DWORD ) && *(DWORD *)buffer == WINHTTP_ENABLE_SSL_REVOCATION)
+        {
+            request->check_revocation = TRUE;
+            SetLastError( NO_ERROR );
+            return TRUE;
+        }
+        else
+        {
+            SetLastError( ERROR_INVALID_PARAMETER );
+            return FALSE;
+        }
+
+    case WINHTTP_OPTION_CONNECT_RETRIES:
+        FIXME("WINHTTP_OPTION_CONNECT_RETRIES\n");
+        return TRUE;
+
     default:
         FIXME("unimplemented option %u\n", option);
-        set_last_error( ERROR_WINHTTP_INVALID_OPTION );
+        SetLastError( ERROR_WINHTTP_INVALID_OPTION );
         return FALSE;
     }
 }
 
-static const object_vtbl_t request_vtbl =
+static const struct object_vtbl request_vtbl =
 {
     request_destroy,
     request_query_option,
     request_set_option
 };
 
-static BOOL store_accept_types( request_t *request, const WCHAR **accept_types )
+static BOOL add_accept_types_header( struct request *request, const WCHAR **types )
 {
-    static const WCHAR attr_accept[] = {'A','c','c','e','p','t',0};
+    static const WCHAR acceptW[] = {'A','c','c','e','p','t',0};
     static const DWORD flags = WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA;
-    const WCHAR **types = accept_types;
 
     if (!types) return TRUE;
     while (*types)
     {
-        process_header( request, attr_accept, *types, flags, TRUE );
+        if (!process_header( request, acceptW, *types, flags, TRUE )) return FALSE;
         types++;
     }
     return TRUE;
 }
 
+static WCHAR *get_request_path( const WCHAR *object )
+{
+    int len = object ? strlenW(object) : 0;
+    WCHAR *p, *ret;
+
+    if (!object || object[0] != '/') len++;
+    if (!(p = ret = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return NULL;
+    if (!object || object[0] != '/') *p++ = '/';
+    if (object) strcpyW( p, object );
+    ret[len] = 0;
+    return ret;
+}
+
 /***********************************************************************
  *          WinHttpOpenRequest (winhttp.@)
  */
 HINTERNET WINAPI WinHttpOpenRequest( HINTERNET hconnect, LPCWSTR verb, LPCWSTR object, LPCWSTR version,
                                      LPCWSTR referrer, LPCWSTR *types, DWORD flags )
 {
-    request_t *request;
-    connect_t *connect;
+    struct request *request;
+    struct connect *connect;
     HINTERNET hrequest = NULL;
 
     TRACE("%p, %s, %s, %s, %s, %p, 0x%08x\n", hconnect, debugstr_w(verb), debugstr_w(object),
           debugstr_w(version), debugstr_w(referrer), types, flags);
 
-    if(types && TRACE_ON(winhttp)) {
+    if (types && TRACE_ON(winhttp))
+    {
         const WCHAR **iter;
-
         TRACE("accept types:\n");
-        for(iter = types; *iter; iter++)
-            TRACE("    %s\n", debugstr_w(*iter));
+        for (iter = types; *iter; iter++) TRACE("    %s\n", debugstr_w(*iter));
     }
 
-    if (!(connect = (connect_t *)grab_object( hconnect )))
+    if (!(connect = (struct connect *)grab_object( hconnect )))
     {
-        set_last_error( ERROR_INVALID_HANDLE );
+        SetLastError( ERROR_INVALID_HANDLE );
         return NULL;
     }
     if (connect->hdr.type != WINHTTP_HANDLE_TYPE_CONNECT)
     {
         release_object( &connect->hdr );
-        set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+        SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
         return NULL;
     }
-    if (!(request = heap_alloc_zero( sizeof(request_t) )))
+    if (!(request = heap_alloc_zero( sizeof(struct request) )))
     {
         release_object( &connect->hdr );
         return NULL;
@@ -1110,29 +1157,16 @@ HINTERNET WINAPI WinHttpOpenRequest( HINTERNET hconnect, LPCWSTR verb, LPCWSTR o
     request->resolve_timeout = connect->session->resolve_timeout;
     request->connect_timeout = connect->session->connect_timeout;
     request->send_timeout = connect->session->send_timeout;
-    request->recv_timeout = connect->session->recv_timeout;
+    request->receive_timeout = connect->session->receive_timeout;
+    request->receive_response_timeout = connect->session->receive_response_timeout;
 
     if (!verb || !verb[0]) verb = getW;
     if (!(request->verb = strdupW( verb ))) goto end;
-
-    if (object)
-    {
-        WCHAR *path, *p;
-        unsigned int len;
-
-        len = strlenW( object ) + 1;
-        if (object[0] != '/') len++;
-        if (!(p = path = heap_alloc( len * sizeof(WCHAR) ))) goto end;
-
-        if (object[0] != '/') *p++ = '/';
-        strcpyW( p, object );
-        request->path = path;
-    }
-    else if (!(request->path = strdupW( slashW ))) goto end;
+    if (!(request->path = get_request_path( object ))) goto end;
 
     if (!version || !version[0]) version = http1_1;
     if (!(request->version = strdupW( version ))) goto end;
-    if (!(store_accept_types( request, types ))) goto end;
+    if (!(add_accept_types_header( request, types ))) goto end;
 
     if (!(hrequest = alloc_handle( &request->hdr ))) goto end;
     request->hdr.handle = hrequest;
@@ -1143,7 +1177,7 @@ end:
     release_object( &request->hdr );
     release_object( &connect->hdr );
     TRACE("returning %p\n", hrequest);
-    if (hrequest) set_last_error( ERROR_SUCCESS );
+    if (hrequest) SetLastError( ERROR_SUCCESS );
     return hrequest;
 }
 
@@ -1152,28 +1186,28 @@ end:
  */
 BOOL WINAPI WinHttpCloseHandle( HINTERNET handle )
 {
-    object_header_t *hdr;
+    struct object_header *hdr;
 
     TRACE("%p\n", handle);
 
     if (!(hdr = grab_object( handle )))
     {
-        set_last_error( ERROR_INVALID_HANDLE );
+        SetLastError( ERROR_INVALID_HANDLE );
         return FALSE;
     }
     release_object( hdr );
     free_handle( handle );
-    set_last_error( ERROR_SUCCESS );
+    SetLastError( ERROR_SUCCESS );
     return TRUE;
 }
 
-static BOOL query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD buflen )
+static BOOL query_option( struct object_header *hdr, DWORD option, void *buffer, DWORD *buflen )
 {
     BOOL ret = FALSE;
 
     if (!buflen)
     {
-        set_last_error( ERROR_INVALID_PARAMETER );
+        SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
 
@@ -1184,7 +1218,7 @@ static BOOL query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPD
         if (!buffer || *buflen < sizeof(DWORD_PTR))
         {
             *buflen = sizeof(DWORD_PTR);
-            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
             return FALSE;
         }
 
@@ -1197,7 +1231,7 @@ static BOOL query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPD
         else
         {
             FIXME("unimplemented option %u\n", option);
-            set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+            SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
             return FALSE;
         }
         break;
@@ -1211,30 +1245,30 @@ static BOOL query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPD
 BOOL WINAPI WinHttpQueryOption( HINTERNET handle, DWORD option, LPVOID buffer, LPDWORD buflen )
 {
     BOOL ret = FALSE;
-    object_header_t *hdr;
+    struct object_header *hdr;
 
     TRACE("%p, %u, %p, %p\n", handle, option, buffer, buflen);
 
     if (!(hdr = grab_object( handle )))
     {
-        set_last_error( ERROR_INVALID_HANDLE );
+        SetLastError( ERROR_INVALID_HANDLE );
         return FALSE;
     }
 
     ret = query_option( hdr, option, buffer, buflen );
 
     release_object( hdr );
-    if (ret) set_last_error( ERROR_SUCCESS );
+    if (ret) SetLastError( ERROR_SUCCESS );
     return ret;
 }
 
-static BOOL set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD buflen )
+static BOOL set_option( struct object_header *hdr, DWORD option, void *buffer, DWORD buflen )
 {
     BOOL ret = TRUE;
 
     if (!buffer && buflen)
     {
-        set_last_error( ERROR_INVALID_PARAMETER );
+        SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
 
@@ -1244,7 +1278,7 @@ static BOOL set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD
     {
         if (buflen != sizeof(DWORD_PTR))
         {
-            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
             return FALSE;
         }
 
@@ -1256,7 +1290,7 @@ static BOOL set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD
         else
         {
             FIXME("unimplemented option %u\n", option);
-            set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+            SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
             return FALSE;
         }
         break;
@@ -1270,20 +1304,20 @@ static BOOL set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD
 BOOL WINAPI WinHttpSetOption( HINTERNET handle, DWORD option, LPVOID buffer, DWORD buflen )
 {
     BOOL ret = FALSE;
-    object_header_t *hdr;
+    struct object_header *hdr;
 
     TRACE("%p, %u, %p, %u\n", handle, option, buffer, buflen);
 
     if (!(hdr = grab_object( handle )))
     {
-        set_last_error( ERROR_INVALID_HANDLE );
+        SetLastError( ERROR_INVALID_HANDLE );
         return FALSE;
     }
 
     ret = set_option( hdr, option, buffer, buflen );
 
     release_object( hdr );
-    if (ret) set_last_error( ERROR_SUCCESS );
+    if (ret) SetLastError( ERROR_SUCCESS );
     return ret;
 }
 
@@ -1308,17 +1342,13 @@ static BOOL is_domain_suffix( const char *domain, const char *suffix )
     int len_domain = strlen( domain ), len_suffix = strlen( suffix );
 
     if (len_suffix > len_domain) return FALSE;
-    if (!strcasecmp( domain + len_domain - len_suffix, suffix )) return TRUE;
+    if (!_strnicmp( domain + len_domain - len_suffix, suffix, -1 )) return TRUE;
     return FALSE;
 }
 
 static int reverse_lookup( const struct addrinfo *ai, char *hostname, size_t len )
 {
-    int ret = -1;
-#ifdef HAVE_GETNAMEINFO
-    ret = getnameinfo( ai->ai_addr, ai->ai_addrlen, hostname, len, NULL, 0, 0 );
-#endif
-    return ret;
+    return getnameinfo( ai->ai_addr, ai->ai_addrlen, hostname, len, NULL, 0, 0 );
 }
 
 static WCHAR *build_wpad_url( const char *hostname, const struct addrinfo *ai )
@@ -1391,7 +1421,7 @@ BOOL WINAPI WinHttpDetectAutoProxyConfigUrl( DWORD flags, LPWSTR *url )
 
     if (!flags || !url)
     {
-        set_last_error( ERROR_INVALID_PARAMETER );
+        SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
     if (get_system_proxy_autoconfig_url( system_url, sizeof(system_url) ))
@@ -1400,7 +1430,7 @@ BOOL WINAPI WinHttpDetectAutoProxyConfigUrl( DWORD flags, LPWSTR *url )
 
         if (!(urlW = strdupAW( system_url ))) return FALSE;
         *url = urlW;
-        set_last_error( ERROR_SUCCESS );
+        SetLastError( ERROR_SUCCESS );
         return TRUE;
     }
     if (flags & WINHTTP_AUTO_DETECT_TYPE_DHCP)
@@ -1410,7 +1440,6 @@ BOOL WINAPI WinHttpDetectAutoProxyConfigUrl( DWORD flags, LPWSTR *url )
     }
     if (flags & WINHTTP_AUTO_DETECT_TYPE_DNS_A)
     {
-#ifdef HAVE_GETADDRINFO
         char *fqdn, *domain, *p;
 
         if (!(fqdn = get_computer_name( ComputerNamePhysicalDnsFullyQualified ))) return FALSE;
@@ -1452,16 +1481,13 @@ BOOL WINAPI WinHttpDetectAutoProxyConfigUrl( DWORD flags, LPWSTR *url )
         }
         heap_free( domain );
         heap_free( fqdn );
-#else
-    FIXME("getaddrinfo not found at build time\n");
-#endif
     }
     if (!ret)
     {
-        set_last_error( ERROR_WINHTTP_AUTODETECTION_FAILED );
+        SetLastError( ERROR_WINHTTP_AUTODETECTION_FAILED );
         *url = NULL;
     }
-    else set_last_error( ERROR_SUCCESS );
+    else SetLastError( ERROR_SUCCESS );
     return ret;
 }
 
@@ -1620,7 +1646,7 @@ BOOL WINAPI WinHttpGetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info )
         info->lpszProxy       = NULL;
         info->lpszProxyBypass = NULL;
     }
-    set_last_error( ERROR_SUCCESS );
+    SetLastError( ERROR_SUCCESS );
     return TRUE;
 }
 
@@ -1640,7 +1666,7 @@ BOOL WINAPI WinHttpGetIEProxyConfigForCurrentUser( WINHTTP_CURRENT_USER_IE_PROXY
 
     if (!config)
     {
-        set_last_error( ERROR_INVALID_PARAMETER );
+        SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
     memset( config, 0, sizeof(*config) );
@@ -1703,7 +1729,7 @@ done:
         GlobalFree( config->lpszProxyBypass );
         config->lpszProxyBypass = NULL;
     }
-    else set_last_error( ERROR_SUCCESS );
+    else SetLastError( ERROR_SUCCESS );
     return ret;
 }
 
@@ -1722,7 +1748,7 @@ static BOOL parse_script_result( const char *result, WINHTTP_PROXY_INFO *info )
     p = result;
     while (*p == ' ') p++;
     len = strlen( p );
-    if (len >= 5 && !strncasecmp( p, "PROXY", sizeof("PROXY") - 1 ))
+    if (len >= 5 && !_strnicmp( p, "PROXY", sizeof("PROXY") - 1 ))
     {
         p += 5;
         while (*p == ' ') p++;
@@ -1797,7 +1823,7 @@ done:
     WinHttpCloseHandle( con );
     WinHttpCloseHandle( ses );
     heap_free( hostname );
-    if (!buffer) set_last_error( ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT );
+    if (!buffer) SetLastError( ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT );
     return buffer;
 }
 
@@ -1860,22 +1886,22 @@ BOOL WINAPI WinHttpGetProxyForUrl( HINTERNET hsession, LPCWSTR url, WINHTTP_AUTO
 {
     WCHAR *detected_pac_url = NULL;
     const WCHAR *pac_url;
-    session_t *session;
+    struct session *session;
     char *script;
     DWORD size;
     BOOL ret = FALSE;
 
     TRACE("%p, %s, %p, %p\n", hsession, debugstr_w(url), options, info);
 
-    if (!(session = (session_t *)grab_object( hsession )))
+    if (!(session = (struct session *)grab_object( hsession )))
     {
-        set_last_error( ERROR_INVALID_HANDLE );
+        SetLastError( ERROR_INVALID_HANDLE );
         return FALSE;
     }
     if (session->hdr.type != WINHTTP_HANDLE_TYPE_SESSION)
     {
         release_object( &session->hdr );
-        set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+        SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
         return FALSE;
     }
     if (!url || !options || !info ||
@@ -1885,7 +1911,7 @@ BOOL WINAPI WinHttpGetProxyForUrl( HINTERNET hsession, LPCWSTR url, WINHTTP_AUTO
          (options->dwFlags & WINHTTP_AUTOPROXY_CONFIG_URL)))
     {
         release_object( &session->hdr );
-        set_last_error( ERROR_INVALID_PARAMETER );
+        SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
     if (options->dwFlags & WINHTTP_AUTOPROXY_AUTO_DETECT &&
@@ -1904,7 +1930,7 @@ BOOL WINAPI WinHttpGetProxyForUrl( HINTERNET hsession, LPCWSTR url, WINHTTP_AUTO
 done:
     GlobalFree( detected_pac_url );
     release_object( &session->hdr );
-    if (ret) set_last_error( ERROR_SUCCESS );
+    if (ret) SetLastError( ERROR_SUCCESS );
     return ret;
 }
 
@@ -1922,7 +1948,7 @@ BOOL WINAPI WinHttpSetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info )
 
     if (!info)
     {
-        set_last_error( ERROR_INVALID_PARAMETER );
+        SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
     switch (info->dwAccessType)
@@ -1932,14 +1958,14 @@ BOOL WINAPI WinHttpSetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info )
     case WINHTTP_ACCESS_TYPE_NAMED_PROXY:
         if (!info->lpszProxy)
         {
-            set_last_error( ERROR_INVALID_PARAMETER );
+            SetLastError( ERROR_INVALID_PARAMETER );
             return FALSE;
         }
         /* Only ASCII characters are allowed */
         for (src = info->lpszProxy; *src; src++)
             if (*src > 0x7f)
             {
-                set_last_error( ERROR_INVALID_PARAMETER );
+                SetLastError( ERROR_INVALID_PARAMETER );
                 return FALSE;
             }
         if (info->lpszProxyBypass)
@@ -1947,13 +1973,13 @@ BOOL WINAPI WinHttpSetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info )
             for (src = info->lpszProxyBypass; *src; src++)
                 if (*src > 0x7f)
                 {
-                    set_last_error( ERROR_INVALID_PARAMETER );
+                    SetLastError( ERROR_INVALID_PARAMETER );
                     return FALSE;
                 }
         }
         break;
     default:
-        set_last_error( ERROR_INVALID_PARAMETER );
+        SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
 
@@ -2012,7 +2038,7 @@ BOOL WINAPI WinHttpSetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info )
         }
         RegCloseKey( key );
     }
-    if (ret) set_last_error( ERROR_SUCCESS );
+    if (ret) SetLastError( ERROR_SUCCESS );
     return ret;
 }
 
@@ -2022,14 +2048,14 @@ BOOL WINAPI WinHttpSetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info )
 WINHTTP_STATUS_CALLBACK WINAPI WinHttpSetStatusCallback( HINTERNET handle, WINHTTP_STATUS_CALLBACK callback,
                                                          DWORD flags, DWORD_PTR reserved )
 {
-    object_header_t *hdr;
+    struct object_header *hdr;
     WINHTTP_STATUS_CALLBACK ret;
 
     TRACE("%p, %p, 0x%08x, 0x%lx\n", handle, callback, flags, reserved);
 
     if (!(hdr = grab_object( handle )))
     {
-        set_last_error( ERROR_INVALID_HANDLE );
+        SetLastError( ERROR_INVALID_HANDLE );
         return WINHTTP_INVALID_STATUS_CALLBACK;
     }
     ret = hdr->callback;
@@ -2037,7 +2063,7 @@ WINHTTP_STATUS_CALLBACK WINAPI WinHttpSetStatusCallback( HINTERNET handle, WINHT
     hdr->notify_mask = flags;
 
     release_object( hdr );
-    set_last_error( ERROR_SUCCESS );
+    SetLastError( ERROR_SUCCESS );
     return ret;
 }
 
@@ -2047,66 +2073,66 @@ WINHTTP_STATUS_CALLBACK WINAPI WinHttpSetStatusCallback( HINTERNET handle, WINHT
 BOOL WINAPI WinHttpSetTimeouts( HINTERNET handle, int resolve, int connect, int send, int receive )
 {
     BOOL ret = TRUE;
-    object_header_t *hdr;
-    request_t *request;
-    session_t *session;
+    struct object_header *hdr;
 
     TRACE("%p, %d, %d, %d, %d\n", handle, resolve, connect, send, receive);
 
     if (resolve < -1 || connect < -1 || send < -1 || receive < -1)
     {
-        set_last_error( ERROR_INVALID_PARAMETER );
+        SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
 
     if (!(hdr = grab_object( handle )))
     {
-        set_last_error( ERROR_INVALID_HANDLE );
+        SetLastError( ERROR_INVALID_HANDLE );
         return FALSE;
     }
 
     switch(hdr->type)
     {
-        case WINHTTP_HANDLE_TYPE_REQUEST:
-            request = (request_t *)hdr;
-            request->connect_timeout = connect;
-
-            if (resolve < 0) resolve = 0;
-            request->resolve_timeout = resolve;
+    case WINHTTP_HANDLE_TYPE_REQUEST:
+    {
+        struct request *request = (struct request *)hdr;
+        request->connect_timeout = connect;
 
-            if (send < 0) send = 0;
-            request->send_timeout = send;
+        if (resolve < 0) resolve = 0;
+        request->resolve_timeout = resolve;
 
-            if (receive < 0) receive = 0;
-            request->recv_timeout = receive;
+        if (send < 0) send = 0;
+        request->send_timeout = send;
 
-            if (request->netconn)
-            {
-                if (netconn_set_timeout( request->netconn, TRUE, send )) ret = FALSE;
-                if (netconn_set_timeout( request->netconn, FALSE, receive )) ret = FALSE;
-            }
-            break;
+        if (receive < 0) receive = 0;
+        request->receive_timeout = receive;
 
-        case WINHTTP_HANDLE_TYPE_SESSION:
-            session = (session_t *)hdr;
-            session->connect_timeout = connect;
-
-            if (resolve < 0) resolve = 0;
-            session->resolve_timeout = resolve;
+        if (request->netconn)
+        {
+            if (netconn_set_timeout( request->netconn, TRUE, send )) ret = FALSE;
+            if (netconn_set_timeout( request->netconn, FALSE, receive )) ret = FALSE;
+        }
+        break;
+    }
+    case WINHTTP_HANDLE_TYPE_SESSION:
+    {
+        struct session *session = (struct session *)hdr;
+        session->connect_timeout = connect;
 
-            if (send < 0) send = 0;
-            session->send_timeout = send;
+        if (resolve < 0) resolve = 0;
+        session->resolve_timeout = resolve;
 
-            if (receive < 0) receive = 0;
-            session->recv_timeout = receive;
-            break;
+        if (send < 0) send = 0;
+        session->send_timeout = send;
 
-        default:
-            set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
-            ret = FALSE;
+        if (receive < 0) receive = 0;
+        session->receive_timeout = receive;
+        break;
+    }
+    default:
+        SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+        ret = FALSE;
     }
     release_object( hdr );
-    if (ret) set_last_error( ERROR_SUCCESS );
+    if (ret) SetLastError( ERROR_SUCCESS );
     return ret;
 }
 
@@ -2131,7 +2157,7 @@ BOOL WINAPI WinHttpTimeFromSystemTime( const SYSTEMTIME *time, LPWSTR string )
 
     if (!time || !string)
     {
-        set_last_error( ERROR_INVALID_PARAMETER );
+        SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
 
@@ -2144,7 +2170,7 @@ BOOL WINAPI WinHttpTimeFromSystemTime( const SYSTEMTIME *time, LPWSTR string )
               time->wMinute,
               time->wSecond );
 
-    set_last_error( ERROR_SUCCESS );
+    SetLastError( ERROR_SUCCESS );
     return TRUE;
 }
 
@@ -2161,7 +2187,7 @@ BOOL WINAPI WinHttpTimeToSystemTime( LPCWSTR string, SYSTEMTIME *time )
 
     if (!string || !time)
     {
-        set_last_error( ERROR_INVALID_PARAMETER );
+        SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
 
@@ -2172,7 +2198,7 @@ BOOL WINAPI WinHttpTimeToSystemTime( LPCWSTR string, SYSTEMTIME *time )
      *  a SYSTEMTIME structure.
      */
 
-    set_last_error( ERROR_SUCCESS );
+    SetLastError( ERROR_SUCCESS );
 
     while (*s && !isalphaW( *s )) s++;
     if (s[0] == '\0' || s[1] == '\0' || s[2] == '\0') return TRUE;
index 32b30da..e1255bd 100644 (file)
  */
 
 #include "config.h"
+#include "ws2tcpip.h"
 #include <stdarg.h>
 
-#include "wine/debug.h"
-
 #include "windef.h"
 #include "winbase.h"
 #include "winreg.h"
 #include "winhttp.h"
 #include "shlwapi.h"
 
+#include "wine/debug.h"
 #include "winhttp_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
@@ -34,27 +34,33 @@ WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
 static const WCHAR scheme_http[] = {'h','t','t','p',0};
 static const WCHAR scheme_https[] = {'h','t','t','p','s',0};
 
-static DWORD set_component( WCHAR **str, DWORD *str_len, WCHAR *value, DWORD len, DWORD flags, BOOL *overflow )
+struct url_component
+{
+    WCHAR **str;
+    DWORD  *len;
+};
+
+static DWORD set_component( struct url_component *comp, WCHAR *value, DWORD len, DWORD flags, BOOL *overflow )
 {
-    if (*str && !*str_len) return ERROR_INVALID_PARAMETER;
-    if (!*str_len) return ERROR_SUCCESS;
-    if (!*str)
+    if (*comp->str && !*comp->len) return ERROR_INVALID_PARAMETER;
+    if (!*comp->len) return ERROR_SUCCESS;
+    if (!*comp->str)
     {
-        if (len && *str_len && (flags & (ICU_DECODE|ICU_ESCAPE))) return ERROR_INVALID_PARAMETER;
-        *str = value;
-        *str_len = len;
+        if (len && *comp->len && (flags & (ICU_DECODE|ICU_ESCAPE))) return ERROR_INVALID_PARAMETER;
+        *comp->str = value;
+        *comp->len = len;
     }
     else
     {
-        if (len >= *str_len)
+        if (len >= *comp->len)
         {
-            *str_len = len+1;
+            *comp->len = len + 1;
             *overflow = TRUE;
             return ERROR_SUCCESS;
         }
-        memcpy( *str, value, len * sizeof(WCHAR) );
-        (*str)[len] = 0;
-        *str_len = len;
+        memcpy( *comp->str, value, len * sizeof(WCHAR) );
+        (*comp->str)[len] = 0;
+        *comp->len = len;
     }
     return ERROR_SUCCESS;
 }
@@ -87,81 +93,71 @@ static WCHAR *decode_url( LPCWSTR url, DWORD *len )
     return ret;
 }
 
-static BOOL need_escape( WCHAR c )
+static inline BOOL need_escape( WCHAR ch )
 {
-    if (isalnumW( c )) return FALSE;
+    static const WCHAR escapes[] = {' ','"','#','%','<','>','[','\\',']','^','`','{','|','}','~',0};
+    const WCHAR *p = escapes;
 
-    if (c <= 31 || c >= 127) return TRUE;
-    else
+    if (ch <= 31 || ch >= 127) return TRUE;
+    while (*p)
     {
-        switch (c)
-        {
-        case ' ':
-        case '"':
-        case '#':
-        case '%':
-        case '<':
-        case '>':
-        case ']':
-        case '\\':
-        case '[':
-        case '^':
-        case '`':
-        case '{':
-        case '|':
-        case '}':
-        case '~':
-            return TRUE;
-        default:
-            return FALSE;
-        }
+        if (ch == *p++) return TRUE;
     }
+    return FALSE;
 }
 
-static DWORD copy_escape( WCHAR *dst, const WCHAR *src, DWORD len )
+static BOOL escape_string( const WCHAR *src, DWORD src_len, WCHAR *dst, DWORD *dst_len )
 {
     static const WCHAR hex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
-    DWORD ret = len;
-    unsigned int i;
     WCHAR *p = dst;
+    DWORD i;
 
-    for (i = 0; i < len; i++, p++)
+    *dst_len = src_len;
+    for (i = 0; i < src_len; i++)
     {
+        if (src[i] > 0xff) return FALSE;
         if (need_escape( src[i] ))
         {
-            p[0] = '%';
-            p[1] = hex[(src[i] >> 4) & 0xf];
-            p[2] = hex[src[i] & 0xf];
-            ret += 2;
-            p += 2;
+            if (dst)
+            {
+                p[0] = '%';
+                p[1] = hex[(src[i] >> 4) & 0xf];
+                p[2] = hex[src[i] & 0xf];
+                p += 3;
+            }
+            *dst_len += 2;
         }
-        else *p = src[i];
+        else if (dst) *p++ = src[i];
     }
-    dst[ret] = 0;
-    return ret;
+
+    if (dst) dst[*dst_len] = 0;
+    return TRUE;
 }
 
-static WCHAR *escape_url( LPCWSTR url, DWORD *len )
+static DWORD escape_url( const WCHAR *url, DWORD *len, WCHAR **ret )
 {
-    WCHAR *ret;
-    const WCHAR *p, *q;
+    const WCHAR *p;
+    DWORD len_base, len_path;
 
-    if ((p = q = strrchrW( url, '/' )))
+    if ((p = strrchrW( url, '/' )))
     {
-        while (*q)
-        {
-            if (need_escape( *q )) *len += 2;
-            q++;
-        }
+        len_base = p - url;
+        if (!escape_string( p, *len - len_base, NULL, &len_path )) return ERROR_INVALID_PARAMETER;
     }
-    if (!(ret = heap_alloc( (*len + 1) * sizeof(WCHAR) ))) return NULL;
-    if (!p) strcpyW( ret, url );
     else
     {
-        memcpy( ret, url, (p - url) * sizeof(WCHAR) );
-        copy_escape( ret + (p - url), p, q - p );
+        len_base = *len;
+        len_path = 0;
     }
-    return ret;
+
+    if (!(*ret = heap_alloc( (len_base + len_path + 1) * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY;
+    memcpy( *ret, url, len_base * sizeof(WCHAR) );
+
+    if (p) escape_string( p, *len - (p - url), *ret + len_base, &len_path );
+    (*ret)[len_base + len_path] = 0;
+
+    *len = len_base + len_path;
+    return ERROR_SUCCESS;
 }
 
 static DWORD parse_port( const WCHAR *str, DWORD len, INTERNET_PORT *ret )
@@ -183,24 +179,25 @@ static DWORD parse_port( const WCHAR *str, DWORD len, INTERNET_PORT *ret )
 BOOL WINAPI WinHttpCrackUrl( LPCWSTR url, DWORD len, DWORD flags, LPURL_COMPONENTSW uc )
 {
     WCHAR *p, *q, *r, *url_decoded = NULL, *url_escaped = NULL;
-    INTERNET_SCHEME scheme = 0;
+    INTERNET_SCHEME scheme_number = 0;
+    struct url_component scheme, username, password, hostname, path, extra;
     BOOL overflow = FALSE;
     DWORD err;
 
     TRACE("%s, %d, %x, %p\n", debugstr_wn(url, len), len, flags, uc);
 
-    if (!url || !uc || uc->dwStructSize != sizeof(URL_COMPONENTS))
+    if (!url || !uc || uc->dwStructSize != sizeof(*uc))
     {
-        set_last_error( ERROR_INVALID_PARAMETER );
+        SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
     if (!len) len = strlenW( url );
 
     if (flags & ICU_ESCAPE)
     {
-        if (!(url_escaped = escape_url( url, &len )))
+        if ((err = escape_url( url, &len, &url_escaped )))
         {
-            set_last_error( ERROR_OUTOFMEMORY );
+            SetLastError( err );
             return FALSE;
         }
         url = url_escaped;
@@ -209,25 +206,28 @@ BOOL WINAPI WinHttpCrackUrl( LPCWSTR url, DWORD len, DWORD flags, LPURL_COMPONEN
     {
         if (!(url_decoded = decode_url( url, &len )))
         {
-            set_last_error( ERROR_OUTOFMEMORY );
+            SetLastError( ERROR_OUTOFMEMORY );
             return FALSE;
         }
         url = url_decoded;
     }
     if (!(p = strchrW( url, ':' )))
     {
-        set_last_error( ERROR_WINHTTP_UNRECOGNIZED_SCHEME );
+        SetLastError( ERROR_WINHTTP_UNRECOGNIZED_SCHEME );
         return FALSE;
     }
-    if (p - url == 4 && !strncmpiW( url, scheme_http, 4 )) scheme = INTERNET_SCHEME_HTTP;
-    else if (p - url == 5 && !strncmpiW( url, scheme_https, 5 )) scheme = INTERNET_SCHEME_HTTPS;
+    if (p - url == 4 && !strncmpiW( url, scheme_http, 4 )) scheme_number = INTERNET_SCHEME_HTTP;
+    else if (p - url == 5 && !strncmpiW( url, scheme_https, 5 )) scheme_number = INTERNET_SCHEME_HTTPS;
     else
     {
         err = ERROR_WINHTTP_UNRECOGNIZED_SCHEME;
         goto exit;
     }
 
-    if ((err = set_component( &uc->lpszScheme, &uc->dwSchemeLength, (WCHAR *)url, p - url, flags, &overflow ))) goto exit;
+    scheme.str = &uc->lpszScheme;
+    scheme.len = &uc->dwSchemeLength;
+
+    if ((err = set_component( &scheme, (WCHAR *)url, p - url, flags, &overflow ))) goto exit;
 
     p++; /* skip ':' */
     if (!p[0] || p[0] != '/' || p[1] != '/')
@@ -241,83 +241,105 @@ BOOL WINAPI WinHttpCrackUrl( LPCWSTR url, DWORD len, DWORD flags, LPURL_COMPONEN
         err = ERROR_WINHTTP_INVALID_URL;
         goto exit;
     }
+
+    username.str = &uc->lpszUserName;
+    username.len = &uc->dwUserNameLength;
+
+    password.str = &uc->lpszPassword;
+    password.len = &uc->dwPasswordLength;
+
     if ((q = memchrW( p, '@', len - (p - url) )) && !(memchrW( p, '/', q - p )))
     {
+
         if ((r = memchrW( p, ':', q - p )))
         {
-            if ((err = set_component( &uc->lpszUserName, &uc->dwUserNameLength, p, r - p, flags, &overflow ))) goto exit;
+            if ((err = set_component( &username, p, r - p, flags, &overflow ))) goto exit;
             r++;
-            if ((err = set_component( &uc->lpszPassword, &uc->dwPasswordLength, r, q - r, flags, &overflow ))) goto exit;
+            if ((err = set_component( &password, r, q - r, flags, &overflow ))) goto exit;
         }
         else
         {
-            if ((err = set_component( &uc->lpszUserName, &uc->dwUserNameLength, p, q - p, flags, &overflow ))) goto exit;
-            if ((err = set_component( &uc->lpszPassword, &uc->dwPasswordLength, NULL, 0, flags, &overflow ))) goto exit;
+            if ((err = set_component( &username, p, q - p, flags, &overflow ))) goto exit;
+            if ((err = set_component( &password, NULL, 0, flags, &overflow ))) goto exit;
         }
         p = q + 1;
     }
     else
     {
-        if ((err = set_component( &uc->lpszUserName, &uc->dwUserNameLength, NULL, 0, flags, &overflow ))) goto exit;
-        if ((err = set_component( &uc->lpszPassword, &uc->dwPasswordLength, NULL, 0, flags, &overflow ))) goto exit;
+        if ((err = set_component( &username, NULL, 0, flags, &overflow ))) goto exit;
+        if ((err = set_component( &password, NULL, 0, flags, &overflow ))) goto exit;
     }
+
+    hostname.str = &uc->lpszHostName;
+    hostname.len = &uc->dwHostNameLength;
+
+    path.str = &uc->lpszUrlPath;
+    path.len = &uc->dwUrlPathLength;
+
+    extra.str = &uc->lpszExtraInfo;
+    extra.len = &uc->dwExtraInfoLength;
+
     if ((q = memchrW( p, '/', len - (p - url) )))
     {
         if ((r = memchrW( p, ':', q - p )))
         {
-            if ((err = set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, r - p, flags, &overflow ))) goto exit;
+            if ((err = set_component( &hostname, p, r - p, flags, &overflow ))) goto exit;
             r++;
             if ((err = parse_port( r, q - r, &uc->nPort ))) goto exit;
         }
         else
         {
-            if ((err = set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, q - p, flags, &overflow ))) goto exit;
-            if (scheme == INTERNET_SCHEME_HTTP) uc->nPort = INTERNET_DEFAULT_HTTP_PORT;
-            if (scheme == INTERNET_SCHEME_HTTPS) uc->nPort = INTERNET_DEFAULT_HTTPS_PORT;
+            if ((err = set_component( &hostname, p, q - p, flags, &overflow ))) goto exit;
+            if (scheme_number == INTERNET_SCHEME_HTTP) uc->nPort = INTERNET_DEFAULT_HTTP_PORT;
+            if (scheme_number == INTERNET_SCHEME_HTTPS) uc->nPort = INTERNET_DEFAULT_HTTPS_PORT;
         }
 
         if ((r = memchrW( q, '?', len - (q - url) )))
         {
-            if ((err = set_component( &uc->lpszUrlPath, &uc->dwUrlPathLength, q, r - q, flags, &overflow ))) goto exit;
-            if ((err = set_component( &uc->lpszExtraInfo, &uc->dwExtraInfoLength, r, len - (r - url), flags, &overflow ))) goto exit;
+            if (*extra.len)
+            {
+                if ((err = set_component( &path, q, r - q, flags, &overflow ))) goto exit;
+                if ((err = set_component( &extra, r, len - (r - url), flags, &overflow ))) goto exit;
+            }
+            else if ((err = set_component( &path, q, len - (q - url), flags, &overflow ))) goto exit;
         }
         else
         {
-            if ((err = set_component( &uc->lpszUrlPath, &uc->dwUrlPathLength, q, len - (q - url), flags, &overflow ))) goto exit;
-            if ((err = set_component( &uc->lpszExtraInfo, &uc->dwExtraInfoLength, (WCHAR *)url + len, 0, flags, &overflow ))) goto exit;
+            if ((err = set_component( &path, q, len - (q - url), flags, &overflow ))) goto exit;
+            if ((err = set_component( &extra, (WCHAR *)url + len, 0, flags, &overflow ))) goto exit;
         }
     }
     else
     {
         if ((r = memchrW( p, ':', len - (p - url) )))
         {
-            if ((err = set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, r - p, flags, &overflow ))) goto exit;
+            if ((err = set_component( &hostname, p, r - p, flags, &overflow ))) goto exit;
             r++;
             if ((err = parse_port( r, len - (r - url), &uc->nPort ))) goto exit;
         }
         else
         {
-            if ((err = set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, len - (p - url), flags, &overflow ))) goto exit;
-            if (scheme == INTERNET_SCHEME_HTTP) uc->nPort = INTERNET_DEFAULT_HTTP_PORT;
-            if (scheme == INTERNET_SCHEME_HTTPS) uc->nPort = INTERNET_DEFAULT_HTTPS_PORT;
+            if ((err = set_component( &hostname, p, len - (p - url), flags, &overflow ))) goto exit;
+            if (scheme_number == INTERNET_SCHEME_HTTP) uc->nPort = INTERNET_DEFAULT_HTTP_PORT;
+            if (scheme_number == INTERNET_SCHEME_HTTPS) uc->nPort = INTERNET_DEFAULT_HTTPS_PORT;
         }
-        if ((err = set_component( &uc->lpszUrlPath, &uc->dwUrlPathLength, (WCHAR *)url + len, 0, flags, &overflow ))) goto exit;
-        if ((err = set_component( &uc->lpszExtraInfo, &uc->dwExtraInfoLength, (WCHAR *)url + len, 0, flags, &overflow ))) goto exit;
+        if ((err = set_component( &path, (WCHAR *)url + len, 0, flags, &overflow ))) goto exit;
+        if ((err = set_component( &extra, (WCHAR *)url + len, 0, flags, &overflow ))) goto exit;
     }
 
-    TRACE("scheme(%s) host(%s) port(%d) path(%s) extra(%s)\n", debugstr_wn( uc->lpszScheme, uc->dwSchemeLength ),
-          debugstr_wn( uc->lpszHostName, uc->dwHostNameLength ), uc->nPort, debugstr_wn( uc->lpszUrlPath, uc->dwUrlPathLength ),
-          debugstr_wn( uc->lpszExtraInfo, uc->dwExtraInfoLength ));
+    TRACE("scheme(%s) host(%s) port(%d) path(%s) extra(%s)\n", debugstr_wn(*scheme.str, *scheme.len),
+          debugstr_wn(*hostname.str, *hostname.len ), uc->nPort, debugstr_wn(*path.str, *path.len),
+          debugstr_wn(*extra.str, *extra.len));
 
 exit:
     if (!err)
     {
         if (overflow) err = ERROR_INSUFFICIENT_BUFFER;
-        uc->nScheme = scheme;
+        uc->nScheme = scheme_number;
     }
     heap_free( url_decoded );
     heap_free( url_escaped );
-    set_last_error( err );
+    SetLastError( err );
     return !err;
 }
 
@@ -342,7 +364,7 @@ static BOOL uses_default_port( INTERNET_SCHEME scheme, INTERNET_PORT port )
     return FALSE;
 }
 
-static DWORD comp_length( DWORD len, DWORD flags, WCHAR *comp )
+static DWORD get_comp_length( DWORD len, DWORD flags, WCHAR *comp )
 {
     DWORD ret;
     unsigned int i;
@@ -353,7 +375,7 @@ static DWORD comp_length( DWORD len, DWORD flags, WCHAR *comp )
     return ret;
 }
 
-static BOOL calc_length( URL_COMPONENTS *uc, DWORD flags, LPDWORD len )
+static BOOL get_url_length( URL_COMPONENTS *uc, DWORD flags, DWORD *len )
 {
     static const WCHAR formatW[] = {'%','u',0};
     INTERNET_SCHEME scheme;
@@ -361,7 +383,7 @@ static BOOL calc_length( URL_COMPONENTS *uc, DWORD flags, LPDWORD len )
     *len = 0;
     if (uc->lpszScheme)
     {
-        DWORD scheme_len = comp_length( uc->dwSchemeLength, 0, uc->lpszScheme );
+        DWORD scheme_len = get_comp_length( uc->dwSchemeLength, 0, uc->lpszScheme );
         *len += scheme_len;
         scheme = get_scheme( uc->lpszScheme, scheme_len );
     }
@@ -371,30 +393,29 @@ static BOOL calc_length( URL_COMPONENTS *uc, DWORD flags, LPDWORD len )
         if (!scheme) scheme = INTERNET_SCHEME_HTTP;
         *len += strlenW( get_scheme_string( scheme ) );
     }
-    *len += 1; /* ':' */
-    if (uc->lpszHostName) *len += 2; /* "//" */
+    *len += 3; /* "://" */
 
     if (uc->lpszUserName)
     {
-        *len += comp_length( uc->dwUserNameLength, 0, uc->lpszUserName );
+        *len += get_comp_length( uc->dwUserNameLength, 0, uc->lpszUserName );
         *len += 1; /* "@" */
     }
     else
     {
         if (uc->lpszPassword)
         {
-            set_last_error( ERROR_INVALID_PARAMETER );
+            SetLastError( ERROR_INVALID_PARAMETER );
             return FALSE;
         }
     }
     if (uc->lpszPassword)
     {
         *len += 1; /* ":" */
-        *len += comp_length( uc->dwPasswordLength, 0, uc->lpszPassword );
+        *len += get_comp_length( uc->dwPasswordLength, 0, uc->lpszPassword );
     }
     if (uc->lpszHostName)
     {
-        *len += comp_length( uc->dwHostNameLength, 0, uc->lpszHostName );
+        *len += get_comp_length( uc->dwHostNameLength, 0, uc->lpszHostName );
 
         if (!uses_default_port( scheme, uc->nPort ))
         {
@@ -405,8 +426,8 @@ static BOOL calc_length( URL_COMPONENTS *uc, DWORD flags, LPDWORD len )
         }
         if (uc->lpszUrlPath && *uc->lpszUrlPath != '/') *len += 1; /* '/' */
     }
-    if (uc->lpszUrlPath) *len += comp_length( uc->dwUrlPathLength, flags, uc->lpszUrlPath );
-    if (uc->lpszExtraInfo) *len += comp_length( uc->dwExtraInfoLength, flags, uc->lpszExtraInfo );
+    if (uc->lpszUrlPath) *len += get_comp_length( uc->dwUrlPathLength, flags, uc->lpszUrlPath );
+    if (uc->lpszExtraInfo) *len += get_comp_length( uc->dwExtraInfoLength, flags, uc->lpszExtraInfo );
     return TRUE;
 }
 
@@ -416,29 +437,28 @@ static BOOL calc_length( URL_COMPONENTS *uc, DWORD flags, LPDWORD len )
 BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDWORD required )
 {
     static const WCHAR formatW[] = {'%','u',0};
-    static const WCHAR twoslashW[] = {'/','/'};
-    DWORD len;
+    DWORD len, len_escaped;
     INTERNET_SCHEME scheme;
 
     TRACE("%p, 0x%08x, %p, %p\n", uc, flags, url, required);
 
     if (!uc || uc->dwStructSize != sizeof(URL_COMPONENTS) || !required)
     {
-        set_last_error( ERROR_INVALID_PARAMETER );
+        SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
 
-    if (!calc_length( uc, flags, &len )) return FALSE;
+    if (!get_url_length( uc, flags, &len )) return FALSE;
 
     if (*required < len)
     {
         *required = len + 1;
-        set_last_error( ERROR_INSUFFICIENT_BUFFER );
+        SetLastError( ERROR_INSUFFICIENT_BUFFER );
         return FALSE;
     }
     if (!url)
     {
-        set_last_error( ERROR_INVALID_PARAMETER );
+        SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
 
@@ -446,7 +466,7 @@ BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDW
     *required = len;
     if (uc->lpszScheme)
     {
-        len = comp_length( uc->dwSchemeLength, 0, uc->lpszScheme );
+        len = get_comp_length( uc->dwSchemeLength, 0, uc->lpszScheme );
         memcpy( url, uc->lpszScheme, len * sizeof(WCHAR) );
         url += len;
 
@@ -465,58 +485,55 @@ BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDW
         url += len;
     }
 
-    /* all schemes are followed by at least a colon */
-    *url = ':';
-    url++;
+    *url++ = ':';
+    *url++ = '/';
+    *url++ = '/';
 
-    if (uc->lpszHostName)
-    {
-        memcpy( url, twoslashW, sizeof(twoslashW) );
-        url += sizeof(twoslashW) / sizeof(twoslashW[0]);
-    }
     if (uc->lpszUserName)
     {
-        len = comp_length( uc->dwUserNameLength, 0, uc->lpszUserName );
+        len = get_comp_length( uc->dwUserNameLength, 0, uc->lpszUserName );
         memcpy( url, uc->lpszUserName, len * sizeof(WCHAR) );
         url += len;
 
         if (uc->lpszPassword)
         {
-            *url = ':';
-            url++;
-
-            len = comp_length( uc->dwPasswordLength, 0, uc->lpszPassword );
+            *url++ = ':';
+            len = get_comp_length( uc->dwPasswordLength, 0, uc->lpszPassword );
             memcpy( url, uc->lpszPassword, len * sizeof(WCHAR) );
             url += len;
         }
-        *url = '@';
-        url++;
+        *url++ = '@';
     }
     if (uc->lpszHostName)
     {
-        len = comp_length( uc->dwHostNameLength, 0, uc->lpszHostName );
+        len = get_comp_length( uc->dwHostNameLength, 0, uc->lpszHostName );
         memcpy( url, uc->lpszHostName, len * sizeof(WCHAR) );
         url += len;
 
         if (!uses_default_port( scheme, uc->nPort ))
         {
-            *url = ':';
-            url++;
-
+            *url++ = ':';
             url += sprintfW( url, formatW, uc->nPort );
         }
 
         /* add slash between hostname and path if necessary */
         if (uc->lpszUrlPath && *uc->lpszUrlPath != '/')
         {
-            *url = '/';
-            url++;
+            *url++ = '/';
         }
     }
     if (uc->lpszUrlPath)
     {
-        len = comp_length( uc->dwUrlPathLength, 0, uc->lpszUrlPath );
-        if (flags & ICU_ESCAPE) url += copy_escape( url, uc->lpszUrlPath, len );
+        len = get_comp_length( uc->dwUrlPathLength, 0, uc->lpszUrlPath );
+        if (flags & ICU_ESCAPE)
+        {
+            if (!escape_string( uc->lpszUrlPath, len, url, &len_escaped ))
+            {
+                SetLastError( ERROR_INVALID_PARAMETER );
+                return FALSE;
+            }
+            url += len_escaped;
+        }
         else
         {
             memcpy( url, uc->lpszUrlPath, len * sizeof(WCHAR) );
@@ -525,8 +542,16 @@ BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDW
     }
     if (uc->lpszExtraInfo)
     {
-        len = comp_length( uc->dwExtraInfoLength, 0, uc->lpszExtraInfo );
-        if (flags & ICU_ESCAPE) url += copy_escape( url, uc->lpszExtraInfo, len );
+        len = get_comp_length( uc->dwExtraInfoLength, 0, uc->lpszExtraInfo );
+        if (flags & ICU_ESCAPE)
+        {
+            if (!escape_string( uc->lpszExtraInfo, len, url, &len_escaped ))
+            {
+                SetLastError( ERROR_INVALID_PARAMETER );
+                return FALSE;
+            }
+            url += len_escaped;
+        }
         else
         {
             memcpy( url, uc->lpszExtraInfo, len * sizeof(WCHAR) );
@@ -534,6 +559,6 @@ BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDW
         }
     }
     *url = 0;
-    set_last_error( ERROR_SUCCESS );
+    SetLastError( ERROR_SUCCESS );
     return TRUE;
 }
index d5ec9ca..3732dfa 100644 (file)
 #include "wine/list.h"
 #include "wine/unicode.h"
 
-#include <sys/types.h>
-#ifdef HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-#ifdef HAVE_NETDB_H
-# include <netdb.h>
-#endif
-#if defined(__MINGW32__) || defined (_MSC_VER)
-# include <ws2tcpip.h>
-#else
-# define closesocket close
-# define ioctlsocket ioctl
-#endif
-
 #include "ole2.h"
 #include "sspi.h"
+#include "wincrypt.h"
 
 static const WCHAR getW[]    = {'G','E','T',0};
 static const WCHAR postW[]   = {'P','O','S','T',0};
@@ -55,20 +39,19 @@ static const WCHAR http1_0[] = {'H','T','T','P','/','1','.','0',0};
 static const WCHAR http1_1[] = {'H','T','T','P','/','1','.','1',0};
 static const WCHAR chunkedW[] = {'c','h','u','n','k','e','d',0};
 
-typedef struct _object_header_t object_header_t;
-
-typedef struct
+struct object_header;
+struct object_vtbl
 {
-    void (*destroy)( object_header_t * );
-    BOOL (*query_option)( object_header_t *, DWORD, void *, DWORD * );
-    BOOL (*set_option)( object_header_t *, DWORD, void *, DWORD );
-} object_vtbl_t;
+    void (*destroy)( struct object_header * );
+    BOOL (*query_option)( struct object_header *, DWORD, void *, DWORD * );
+    BOOL (*set_option)( struct object_header *, DWORD, void *, DWORD );
+};
 
-struct _object_header_t
+struct object_header
 {
     DWORD type;
     HINTERNET handle;
-    const object_vtbl_t *vtbl;
+    const struct object_vtbl *vtbl;
     DWORD flags;
     DWORD disable_flags;
     DWORD logon_policy;
@@ -82,71 +65,58 @@ struct _object_header_t
     struct list children;
 };
 
-typedef struct
+struct hostdata
 {
-    struct list entry;
-    WCHAR *name;
-    struct list cookies;
-} domain_t;
-
-typedef struct
-{
-    struct list entry;
-    WCHAR *name;
-    WCHAR *value;
-    WCHAR *path;
-} cookie_t;
-
-typedef struct {
     struct list entry;
     LONG ref;
     WCHAR *hostname;
     INTERNET_PORT port;
     BOOL secure;
     struct list connections;
-} hostdata_t;
+};
 
-typedef struct
+struct session
 {
-    object_header_t hdr;
-    LPWSTR agent;
+    struct object_header hdr;
+    CRITICAL_SECTION cs;
+    WCHAR *agent;
     DWORD access;
     int resolve_timeout;
     int connect_timeout;
     int send_timeout;
-    int recv_timeout;
-    LPWSTR proxy_server;
-    LPWSTR proxy_bypass;
-    LPWSTR proxy_username;
-    LPWSTR proxy_password;
+    int receive_timeout;
+    int receive_response_timeout;
+    WCHAR *proxy_server;
+    WCHAR *proxy_bypass;
+    WCHAR *proxy_username;
+    WCHAR *proxy_password;
     struct list cookie_cache;
     HANDLE unload_event;
-    CredHandle cred_handle;
-    BOOL cred_handle_initialized;
     DWORD secure_protocols;
-} session_t;
+    DWORD passport_flags;
+};
 
-typedef struct
+struct connect
 {
-    object_header_t hdr;
-    session_t *session;
-    LPWSTR hostname;    /* final destination of the request */
-    LPWSTR servername;  /* name of the server we directly connect to */
-    LPWSTR username;
-    LPWSTR password;
+    struct object_header hdr;
+    struct session *session;
+    WCHAR *hostname;    /* final destination of the request */
+    WCHAR *servername;  /* name of the server we directly connect to */
+    WCHAR *username;
+    WCHAR *password;
     INTERNET_PORT hostport;
     INTERNET_PORT serverport;
     struct sockaddr_storage sockaddr;
     BOOL resolved;
-} connect_t;
+};
 
-typedef struct
+struct netconn
 {
     struct list entry;
     int socket;
     struct sockaddr_storage sockaddr;
     BOOL secure; /* SSL active on connection? */
-    hostdata_t *host;
+    struct hostdata *host;
     ULONGLONG keep_until;
     CtxtHandle ssl_ctx;
     SecPkgContext_StreamSizes ssl_sizes;
@@ -156,14 +126,14 @@ typedef struct
     char *peek_msg;
     char *peek_msg_mem;
     size_t peek_len;
-} netconn_t;
+};
 
-typedef struct
+struct header
 {
-    LPWSTR field;
-    LPWSTR value;
+    WCHAR *field;
+    WCHAR *value;
     BOOL is_request; /* part of request headers? */
-} header_t;
+};
 
 enum auth_target
 {
@@ -197,23 +167,29 @@ struct authinfo
     BOOL finished; /* finished authenticating */
 };
 
-typedef struct
+struct request
 {
-    object_header_t hdr;
-    connect_t *connect;
-    LPWSTR verb;
-    LPWSTR path;
-    LPWSTR version;
-    LPWSTR raw_headers;
+    struct object_header hdr;
+    struct connect *connect;
+    WCHAR *verb;
+    WCHAR *path;
+    WCHAR *version;
+    WCHAR *raw_headers;
     void *optional;
     DWORD optional_len;
-    netconn_t *netconn;
+    struct netconn *netconn;
     DWORD security_flags;
+    BOOL check_revocation;
+    const CERT_CONTEXT *server_cert;
+    const CERT_CONTEXT *client_cert;
+    CredHandle cred_handle;
+    BOOL cred_handle_initialized;
     int resolve_timeout;
     int connect_timeout;
     int send_timeout;
-    int recv_timeout;
-    LPWSTR status_text;
+    int receive_timeout;
+    int receive_response_timeout;
+    WCHAR *status_text;
     DWORD content_length; /* total number of bytes to be read */
     DWORD content_read;   /* bytes read so far */
     BOOL  read_chunked;   /* are we reading in chunked mode? */
@@ -222,13 +198,17 @@ typedef struct
     DWORD read_pos;       /* current read position in read_buf */
     DWORD read_size;      /* valid data size in read_buf */
     char  read_buf[8192]; /* buffer for already read but not returned data */
-    header_t *headers;
+    struct header *headers;
     DWORD num_headers;
     struct authinfo *authinfo;
     struct authinfo *proxy_authinfo;
     HANDLE task_wait;
     HANDLE task_cancel;
+#ifdef __REACTOS__
     HANDLE task_thread;
+#else
+    BOOL   task_proc_running;
+#endif
     struct list task_queue;
     CRITICAL_SECTION task_cs;
     struct
@@ -236,89 +216,84 @@ typedef struct
         WCHAR *username;
         WCHAR *password;
     } creds[TARGET_MAX][SCHEME_MAX];
-} request_t;
-
-typedef struct _task_header_t task_header_t;
+};
 
-struct _task_header_t
+struct task_header
 {
     struct list entry;
-    request_t *request;
-    void (*proc)( task_header_t * );
+    struct request *request;
+    void (*proc)( struct task_header * );
 };
 
-typedef struct
+struct send_request
 {
-    task_header_t hdr;
-    LPWSTR headers;
+    struct task_header hdr;
+    WCHAR *headers;
     DWORD headers_len;
-    LPVOID optional;
+    void *optional;
     DWORD optional_len;
     DWORD total_len;
     DWORD_PTR context;
-} send_request_t;
+};
 
-typedef struct
+struct receive_response
 {
-    task_header_t hdr;
-} receive_response_t;
+    struct task_header hdr;
+};
 
-typedef struct
+struct query_data
 {
-    task_header_t hdr;
-    LPDWORD available;
-} query_data_t;
+    struct task_header hdr;
+    DWORD *available;
+};
 
-typedef struct
+struct read_data
 {
-    task_header_t hdr;
-    LPVOID buffer;
+    struct task_header hdr;
+    void *buffer;
     DWORD to_read;
-    LPDWORD read;
-} read_data_t;
+    DWORD *read;
+};
 
-typedef struct
+struct write_data
 {
-    task_header_t hdr;
-    LPCVOID buffer;
+    struct task_header hdr;
+    const void *buffer;
     DWORD to_write;
-    LPDWORD written;
-} write_data_t;
+    DWORD *written;
+};
 
-object_header_t *addref_object( object_header_t * ) DECLSPEC_HIDDEN;
-object_header_t *grab_object( HINTERNET ) DECLSPEC_HIDDEN;
-void release_object( object_header_t * ) DECLSPEC_HIDDEN;
-HINTERNET alloc_handle( object_header_t * ) DECLSPEC_HIDDEN;
+struct object_header *addref_object( struct object_header * ) DECLSPEC_HIDDEN;
+struct object_header *grab_object( HINTERNET ) DECLSPEC_HIDDEN;
+void release_object( struct object_header * ) DECLSPEC_HIDDEN;
+HINTERNET alloc_handle( struct object_header * ) DECLSPEC_HIDDEN;
 BOOL free_handle( HINTERNET ) DECLSPEC_HIDDEN;
 
-void set_last_error( DWORD ) DECLSPEC_HIDDEN;
-DWORD get_last_error( void ) DECLSPEC_HIDDEN;
-void send_callback( object_header_t *, DWORD, LPVOID, DWORD ) DECLSPEC_HIDDEN;
-void close_connection( request_t * ) DECLSPEC_HIDDEN;
+void send_callback( struct object_header *, DWORD, LPVOID, DWORD ) DECLSPEC_HIDDEN;
+void close_connection( struct request * ) DECLSPEC_HIDDEN;
 
-BOOL netconn_close( netconn_t * ) DECLSPEC_HIDDEN;
-netconn_t *netconn_create( hostdata_t *, const struct sockaddr_storage *, int ) DECLSPEC_HIDDEN;
+void netconn_close( struct netconn * ) DECLSPEC_HIDDEN;
+struct netconn *netconn_create( struct hostdata *, const struct sockaddr_storage *, int ) DECLSPEC_HIDDEN;
 void netconn_unload( void ) DECLSPEC_HIDDEN;
-ULONG netconn_query_data_available( netconn_t * ) DECLSPEC_HIDDEN;
-BOOL netconn_recv( netconn_t *, void *, size_t, int, int * ) DECLSPEC_HIDDEN;
+ULONG netconn_query_data_available( struct netconn * ) DECLSPEC_HIDDEN;
+BOOL netconn_recv( struct netconn *, void *, size_t, int, int * ) DECLSPEC_HIDDEN;
 BOOL netconn_resolve( WCHAR *, INTERNET_PORT, struct sockaddr_storage *, int ) DECLSPEC_HIDDEN;
-BOOL netconn_secure_connect( netconn_t *, WCHAR *, DWORD, CredHandle * ) DECLSPEC_HIDDEN;
-BOOL netconn_send( netconn_t *, const void *, size_t, int * ) DECLSPEC_HIDDEN;
-DWORD netconn_set_timeout( netconn_t *, BOOL, int ) DECLSPEC_HIDDEN;
-BOOL netconn_is_alive( netconn_t * ) DECLSPEC_HIDDEN;
-const void *netconn_get_certificate( netconn_t * ) DECLSPEC_HIDDEN;
-int netconn_get_cipher_strength( netconn_t * ) DECLSPEC_HIDDEN;
-
-BOOL set_cookies( request_t *, const WCHAR * ) DECLSPEC_HIDDEN;
-BOOL add_cookie_headers( request_t * ) DECLSPEC_HIDDEN;
-BOOL add_request_headers( request_t *, LPCWSTR, DWORD, DWORD ) DECLSPEC_HIDDEN;
-void delete_domain( domain_t * ) DECLSPEC_HIDDEN;
-BOOL set_server_for_hostname( connect_t *, LPCWSTR, INTERNET_PORT ) DECLSPEC_HIDDEN;
+BOOL netconn_secure_connect( struct netconn *, WCHAR *, DWORD, CredHandle *, BOOL ) DECLSPEC_HIDDEN;
+BOOL netconn_send( struct netconn *, const void *, size_t, int * ) DECLSPEC_HIDDEN;
+DWORD netconn_set_timeout( struct netconn *, BOOL, int ) DECLSPEC_HIDDEN;
+BOOL netconn_is_alive( struct netconn * ) DECLSPEC_HIDDEN;
+const void *netconn_get_certificate( struct netconn * ) DECLSPEC_HIDDEN;
+int netconn_get_cipher_strength( struct netconn * ) DECLSPEC_HIDDEN;
+
+BOOL set_cookies( struct request *, const WCHAR * ) DECLSPEC_HIDDEN;
+BOOL add_cookie_headers( struct request * ) DECLSPEC_HIDDEN;
+BOOL add_request_headers( struct request *, const WCHAR *, DWORD, DWORD ) DECLSPEC_HIDDEN;
+void destroy_cookies( struct session * ) DECLSPEC_HIDDEN;
+BOOL set_server_for_hostname( struct connect *, const WCHAR *, INTERNET_PORT ) DECLSPEC_HIDDEN;
 void destroy_authinfo( struct authinfo * ) DECLSPEC_HIDDEN;
 
-void release_host( hostdata_t *host ) DECLSPEC_HIDDEN;
-
-BOOL process_header( request_t *request, LPCWSTR field, LPCWSTR value, DWORD flags, BOOL request_only ) DECLSPEC_HIDDEN;
+void release_host( struct hostdata * ) DECLSPEC_HIDDEN;
+BOOL process_header( struct request *, const WCHAR *, const WCHAR *, DWORD, BOOL ) DECLSPEC_HIDDEN;
 
 extern HRESULT WinHttpRequest_create( void ** ) DECLSPEC_HIDDEN;
 void release_typelib( void ) DECLSPEC_HIDDEN;
index 7d41d92..c6c6232 100644 (file)
@@ -201,7 +201,7 @@ dll/win32/windowscodecs       # Synced to WineStaging-4.18
 dll/win32/windowscodecsext    # Synced to WineStaging-2.9
 dll/win32/winemp3.acm         # Synced to WineStaging-4.18
 dll/win32/wing32              # Synced to WineStaging-3.3
-dll/win32/winhttp             # Synced to WineStaging-3.9
+dll/win32/winhttp             # Synced to WineStaging-4.18
 dll/win32/wininet             # Synced to WineStaging-3.9
 dll/win32/winmm               # Forked at Wine-20050628
 dll/win32/winmm/midimap       # Forked at Wine-20050628