Author: akhaldi
Date: Sun Sep 24 11:17:43 2017
New Revision: 75944

URL: http://svn.reactos.org/svn/reactos?rev=75944&view=rev
Log:
[WINHTTP] Sync with Wine Staging 2.16. CORE-13762

d0813b7 winhttp: Avoid returning while holding a lock (Coverity).
5a61913 winhttp: Rename host_t to hostdata_t.
2a99f0e winhttp: Periodically free outdated connections.
5226865 winhttp: Cache and reuse persistent HTTP connections.
e0e8a3f winhttp: Introduce global connected hosts store and keep reference to 
host in netconn_t.
d1d65c9 winhttp: Merge netconn_create and netconn_connect implementations.
3e60241 winhttp: Store socked address in netconn_t.
e129023 winhttp: Pass socket address as sockaddr_storage to netconn_connect.
c2f464d winhttp: Get rid of no longer needed netconn_init.
8c9df5b winhttp: Use notification flags to explicitly mark notifications that 
should signal an event.
c502629 winhttp: Allocate netconn_t separately from request_t.
c06104c winhttp: Store security_flags in request_t instead of netconn_t.
f2bb206 winhttp: Reset content length when a redirect creates a new connection.
0923897 winhttp: Only read as much data as advertized when draining content.

Modified:
    trunk/reactos/dll/win32/winhttp/CMakeLists.txt
    trunk/reactos/dll/win32/winhttp/inet_ntop.c
    trunk/reactos/dll/win32/winhttp/main.c
    trunk/reactos/dll/win32/winhttp/net.c
    trunk/reactos/dll/win32/winhttp/request.c
    trunk/reactos/dll/win32/winhttp/session.c
    trunk/reactos/dll/win32/winhttp/winhttp_private.h
    trunk/reactos/media/doc/README.WINE

Modified: trunk/reactos/dll/win32/winhttp/CMakeLists.txt
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/CMakeLists.txt?rev=75944&r1=75943&r2=75944&view=diff
==============================================================================
--- trunk/reactos/dll/win32/winhttp/CMakeLists.txt      [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/winhttp/CMakeLists.txt      [iso-8859-1] Sun Sep 24 
11:17:43 2017
@@ -1,3 +1,6 @@
+
+remove_definitions(-D_WIN32_WINNT=0x502)
+add_definitions(-D_WIN32_WINNT=0x600)
 
 add_definitions(
     -D__WINESRC__
@@ -27,7 +30,7 @@
 set_module_type(winhttp win32dll)
 target_link_libraries(winhttp uuid wine)
 add_delay_importlibs(winhttp oleaut32 ole32 crypt32 secur32)
-add_importlibs(winhttp user32 advapi32 ws2_32 jsproxy msvcrt kernel32 ntdll)
+add_importlibs(winhttp user32 advapi32 ws2_32 jsproxy kernel32_vista msvcrt 
kernel32 ntdll)
 add_dependencies(winhttp stdole2)
 add_pch(winhttp winhttp_private.h SOURCE)
 add_cd_file(TARGET winhttp DESTINATION reactos/system32 FOR all)

Modified: trunk/reactos/dll/win32/winhttp/inet_ntop.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/inet_ntop.c?rev=75944&r1=75943&r2=75944&view=diff
==============================================================================
--- trunk/reactos/dll/win32/winhttp/inet_ntop.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/winhttp/inet_ntop.c [iso-8859-1] Sun Sep 24 
11:17:43 2017
@@ -51,16 +51,18 @@
  * author:
  *     Paul Vixie, 1996.
  */
-const char *
-inet_ntop(int af, const void *src, char *dst, size_t size)
+
+PCSTR
+WSAAPI
+inet_ntop(INT Family, PVOID pAddr, PSTR pStringBuf, size_t StringBufSize)
 {
 
-       switch (af) {
+       switch (Family) {
        case AF_INET:
-               return (inet_ntop4(src, dst, size));
+               return (inet_ntop4(pAddr, pStringBuf, StringBufSize));
 #ifdef INET6
        case AF_INET6:
-               return (inet_ntop6(src, dst, size));
+               return (inet_ntop6(pAddr, pStringBuf, StringBufSize));
 #endif
        default:
                WSASetLastError(WSAEAFNOSUPPORT);

Modified: trunk/reactos/dll/win32/winhttp/main.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/main.c?rev=75944&r1=75943&r2=75944&view=diff
==============================================================================
--- trunk/reactos/dll/win32/winhttp/main.c      [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/winhttp/main.c      [iso-8859-1] Sun Sep 24 
11:17:43 2017
@@ -21,7 +21,7 @@
 #include <rpcproxy.h>
 #include <httprequest.h>
 
-static HINSTANCE instance;
+HINSTANCE winhttp_instance;
 
 /******************************************************************
  *              DllMain (winhttp.@)
@@ -31,7 +31,7 @@
     switch(fdwReason)
     {
     case DLL_PROCESS_ATTACH:
-        instance = hInstDLL;
+        winhttp_instance = hInstDLL;
         DisableThreadLibraryCalls(hInstDLL);
         break;
     case DLL_PROCESS_DETACH:
@@ -158,7 +158,7 @@
  */
 HRESULT WINAPI DllRegisterServer(void)
 {
-    return __wine_register_resources( instance );
+    return __wine_register_resources( winhttp_instance );
 }
 
 /***********************************************************************
@@ -166,5 +166,5 @@
  */
 HRESULT WINAPI DllUnregisterServer(void)
 {
-    return __wine_unregister_resources( instance );
+    return __wine_unregister_resources( winhttp_instance );
 }

Modified: trunk/reactos/dll/win32/winhttp/net.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/net.c?rev=75944&r1=75943&r2=75944&view=diff
==============================================================================
--- trunk/reactos/dll/win32/winhttp/net.c       [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/winhttp/net.c       [iso-8859-1] Sun Sep 24 
11:17:43 2017
@@ -298,13 +298,6 @@
 
 #endif
 
-BOOL netconn_init( netconn_t *conn )
-{
-    memset(conn, 0, sizeof(*conn));
-    conn->socket = -1;
-    return TRUE;
-}
-
 void netconn_unload( void )
 {
     if(cred_handle_initialized)
@@ -319,56 +312,38 @@
 #endif
 }
 
-BOOL netconn_connected( netconn_t *conn )
-{
-    return (conn->socket != -1);
-}
-
-BOOL netconn_create( netconn_t *conn, int domain, int type, int protocol )
-{
-    if ((conn->socket = socket( domain, type, protocol )) == -1)
-    {
-        WARN("unable to create socket (%s)\n", strerror(errno));
-        set_last_error( sock_get_error( errno ) );
-        return FALSE;
-    }
-    return TRUE;
-}
-
-BOOL netconn_close( netconn_t *conn )
-{
-    int res;
-
-    if (conn->secure)
-    {
-        heap_free( conn->peek_msg_mem );
-        conn->peek_msg_mem = NULL;
-        conn->peek_msg = NULL;
-        conn->peek_len = 0;
-        heap_free(conn->ssl_buf);
-        conn->ssl_buf = NULL;
-        heap_free(conn->extra_buf);
-        conn->extra_buf = NULL;
-        conn->extra_len = 0;
-        DeleteSecurityContext(&conn->ssl_ctx);
-        conn->secure = FALSE;
-    }
-    res = closesocket( conn->socket );
-    conn->socket = -1;
-    if (res == -1)
-    {
-        set_last_error( sock_get_error( errno ) );
-        return FALSE;
-    }
-    return TRUE;
-}
-
-BOOL netconn_connect( netconn_t *conn, const struct sockaddr *sockaddr, 
unsigned int addr_len, int timeout )
-{
+netconn_t *netconn_create( hostdata_t *host, const struct sockaddr_storage 
*sockaddr, int timeout )
+{
+    netconn_t *conn;
+    unsigned int addr_len;
     BOOL ret = FALSE;
     int res;
     ULONG state;
 
+    conn = heap_alloc_zero(sizeof(*conn));
+    if (!conn) return NULL;
+    conn->host = host;
+    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 ) );
+        heap_free(conn);
+        return NULL;
+    }
+
+    switch (conn->sockaddr.ss_family)
+    {
+    case AF_INET:
+        addr_len = sizeof(struct sockaddr_in);
+        break;
+    case AF_INET6:
+        addr_len = sizeof(struct sockaddr_in6);
+        break;
+    default:
+        assert(0);
+    }
+
     if (timeout > 0)
     {
         state = 1;
@@ -378,7 +353,7 @@
     for (;;)
     {
         res = 0;
-        if (connect( conn->socket, sockaddr, addr_len ) < 0)
+        if (connect( conn->socket, (const struct sockaddr *)&conn->sockaddr, 
addr_len ) < 0)
         {
             res = sock_get_error( errno );
             if (res == WSAEWOULDBLOCK || res == WSAEINPROGRESS)
@@ -436,11 +411,35 @@
     {
         WARN("unable to connect to host (%d)\n", res);
         set_last_error( res );
-    }
-    return ret;
-}
-
-BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname )
+        netconn_close( conn );
+        return NULL;
+    }
+    return conn;
+}
+
+BOOL netconn_close( netconn_t *conn )
+{
+    int res;
+
+    if (conn->secure)
+    {
+        heap_free( conn->peek_msg_mem );
+        heap_free(conn->ssl_buf);
+        heap_free(conn->extra_buf);
+        DeleteSecurityContext(&conn->ssl_ctx);
+    }
+    res = 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 )
 {
     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};
@@ -540,7 +539,7 @@
 
             status = QueryContextAttributesW(&ctx, 
SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&cert);
             if(status == SEC_E_OK) {
-                res = netconn_verify_cert(cert, hostname, 
conn->security_flags);
+                res = netconn_verify_cert(cert, hostname, security_flags);
                 CertFreeCertificateContext(cert);
                 if(res != ERROR_SUCCESS) {
                     WARN("cert verify failed: %u\n", res);
@@ -605,7 +604,6 @@
 
 BOOL netconn_send( netconn_t *conn, const void *msg, size_t len, int *sent )
 {
-    if (!netconn_connected( conn )) return FALSE;
     if (conn->secure)
     {
         const BYTE *ptr = msg;
@@ -729,7 +727,6 @@
 BOOL netconn_recv( netconn_t *conn, void *buf, size_t len, int flags, int 
*recvd )
 {
     *recvd = 0;
-    if (!netconn_connected( conn )) return FALSE;
     if (!len) return TRUE;
 
     if (conn->secure)
@@ -786,13 +783,7 @@
 
 ULONG netconn_query_data_available( netconn_t *conn )
 {
-    if(!netconn_connected(conn))
-        return 0;
-
-    if(conn->secure)
-        return conn->peek_len;
-
-    return 0;
+    return conn->secure ? conn->peek_len : 0;
 }
 
 DWORD netconn_set_timeout( netconn_t *netconn, BOOL send, int value )
@@ -811,7 +802,37 @@
     return ERROR_SUCCESS;
 }
 
-static DWORD resolve_hostname( const WCHAR *hostnameW, INTERNET_PORT port, 
struct sockaddr *sa, socklen_t *sa_len )
+BOOL netconn_is_alive( netconn_t *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;
+
+    mode = 1;
+    if(!ioctlsocket(netconn->socket, FIONBIO, &mode))
+        return FALSE;
+
+    len = recv(netconn->socket, &b, 1, MSG_PEEK);
+
+    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
+}
+
+static DWORD resolve_hostname( const WCHAR *hostnameW, INTERNET_PORT port, 
struct sockaddr_storage *sa )
 {
     char *hostname;
 #ifdef HAVE_GETADDRINFO
@@ -845,13 +866,6 @@
         }
     }
     heap_free( hostname );
-    if (*sa_len < res->ai_addrlen)
-    {
-        WARN("address too small\n");
-        freeaddrinfo( res );
-        return ERROR_WINHTTP_NAME_NOT_RESOLVED;
-    }
-    *sa_len = res->ai_addrlen;
     memcpy( sa, res->ai_addr, res->ai_addrlen );
     /* Copy port */
     switch (res->ai_family)
@@ -877,13 +891,6 @@
         LeaveCriticalSection( &cs_gethostbyname );
         return ERROR_WINHTTP_NAME_NOT_RESOLVED;
     }
-    if (*sa_len < sizeof(struct sockaddr_in))
-    {
-        WARN("address too small\n");
-        LeaveCriticalSection( &cs_gethostbyname );
-        return ERROR_WINHTTP_NAME_NOT_RESOLVED;
-    }
-    *sa_len = sizeof(struct sockaddr_in);
     memset( sa, 0, sizeof(struct sockaddr_in) );
     memcpy( &sin->sin_addr, he->h_addr, he->h_length );
     sin->sin_family = he->h_addrtype;
@@ -896,19 +903,18 @@
 
 struct resolve_args
 {
-    const WCHAR     *hostname;
-    INTERNET_PORT    port;
-    struct sockaddr *sa;
-    socklen_t       *sa_len;
+    const WCHAR             *hostname;
+    INTERNET_PORT            port;
+    struct sockaddr_storage *sa;
 };
 
 static DWORD CALLBACK resolve_proc( LPVOID arg )
 {
     struct resolve_args *ra = arg;
-    return resolve_hostname( ra->hostname, ra->port, ra->sa, ra->sa_len );
-}
-
-BOOL netconn_resolve( WCHAR *hostname, INTERNET_PORT port, struct sockaddr 
*sa, socklen_t *sa_len, int timeout )
+    return resolve_hostname( ra->hostname, ra->port, ra->sa );
+}
+
+BOOL netconn_resolve( WCHAR *hostname, INTERNET_PORT port, struct 
sockaddr_storage *sa, int timeout )
 {
     DWORD ret;
 
@@ -921,7 +927,6 @@
         ra.hostname = hostname;
         ra.port     = port;
         ra.sa       = sa;
-        ra.sa_len   = sa_len;
 
         thread = CreateThread( NULL, 0, resolve_proc, &ra, 0, NULL );
         if (!thread) return FALSE;
@@ -931,7 +936,7 @@
         else ret = ERROR_WINHTTP_TIMEOUT;
         CloseHandle( thread );
     }
-    else ret = resolve_hostname( hostname, port, sa, sa_len );
+    else ret = resolve_hostname( hostname, port, sa );
 
     if (ret)
     {

Modified: trunk/reactos/dll/win32/winhttp/request.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/request.c?rev=75944&r1=75943&r2=75944&view=diff
==============================================================================
--- trunk/reactos/dll/win32/winhttp/request.c   [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/winhttp/request.c   [iso-8859-1] Sun Sep 24 
11:17:43 2017
@@ -31,6 +31,8 @@
 #include <httprequestid.h>
 
 #include "inet_ntop.c"
+
+#define DEFAULT_KEEP_ALIVE_TIMEOUT 30000
 
 static const WCHAR attr_accept[] = {'A','c','c','e','p','t',0};
 static const WCHAR attr_accept_charset[] = 
{'A','c','c','e','p','t','-','C','h','a','r','s','e','t', 0};
@@ -540,7 +542,7 @@
         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.secure ? https : http;
+        LPCWSTR scheme = (request->netconn ? request->netconn->secure : 
(request->hdr.flags & WINHTTP_FLAG_SECURE)) ? https : http;
         int len;
 
         len = strlenW( scheme ) + strlenW( request->connect->hostname );
@@ -945,7 +947,7 @@
             {
                 int len = strlen( req_ascii ), bytes_sent;
 
-                ret = netconn_send( &request->netconn, req_ascii, len, 
&bytes_sent );
+                ret = netconn_send( request->netconn, req_ascii, len, 
&bytes_sent );
                 heap_free( req_ascii );
                 if (ret)
                     ret = read_reply( request );
@@ -959,12 +961,12 @@
 #define INET6_ADDRSTRLEN 46
 #endif
 
-static WCHAR *addr_to_str( struct sockaddr *addr )
+static WCHAR *addr_to_str( struct sockaddr_storage *addr )
 {
     char buf[INET6_ADDRSTRLEN];
     void *src;
 
-    switch (addr->sa_family)
+    switch (addr->ss_family)
     {
     case AF_INET:
         src = &((struct sockaddr_in *)addr)->sin_addr;
@@ -973,79 +975,258 @@
         src = &((struct sockaddr_in6 *)addr)->sin6_addr;
         break;
     default:
-        WARN("unsupported address family %d\n", addr->sa_family);
+        WARN("unsupported address family %d\n", addr->ss_family);
         return NULL;
     }
-    if (!inet_ntop( addr->sa_family, src, buf, sizeof(buf) )) return NULL;
+    if (!inet_ntop( addr->ss_family, src, buf, sizeof(buf) )) return NULL;
     return strdupAW( buf );
 }
 
+static CRITICAL_SECTION connection_pool_cs;
+static CRITICAL_SECTION_DEBUG connection_pool_debug =
+{
+    0, 0, &connection_pool_cs,
+    { &connection_pool_debug.ProcessLocksList, 
&connection_pool_debug.ProcessLocksList },
+      0, 0, { (DWORD_PTR)(__FILE__ ": connection_pool_cs") }
+};
+static CRITICAL_SECTION connection_pool_cs = { &connection_pool_debug, -1, 0, 
0, 0, 0 };
+
+static struct list connection_pool = LIST_INIT( connection_pool );
+
+void release_host( hostdata_t *host )
+{
+    LONG ref;
+
+    EnterCriticalSection( &connection_pool_cs );
+    if (!(ref = --host->ref)) list_remove( &host->entry );
+    LeaveCriticalSection( &connection_pool_cs );
+    if (ref) return;
+
+    assert( list_empty( &host->connections ) );
+    heap_free( host->hostname );
+    heap_free( host );
+}
+
+static BOOL connection_collector_running;
+
+static DWORD WINAPI connection_collector(void *arg)
+{
+    unsigned int remaining_connections;
+    netconn_t *netconn, *next_netconn;
+    hostdata_t *host, *next_host;
+    ULONGLONG now;
+
+    do
+    {
+        /* FIXME: Use more sophisticated method */
+        Sleep(5000);
+        remaining_connections = 0;
+        now = GetTickCount64();
+
+        EnterCriticalSection(&connection_pool_cs);
+
+        LIST_FOR_EACH_ENTRY_SAFE(host, next_host, &connection_pool, 
hostdata_t, entry)
+        {
+            LIST_FOR_EACH_ENTRY_SAFE(netconn, next_netconn, 
&host->connections, netconn_t, entry)
+            {
+                if (netconn->keep_until < now)
+                {
+                    TRACE("freeing %p\n", netconn);
+                    list_remove(&netconn->entry);
+                    netconn_close(netconn);
+                }
+                else
+                {
+                    remaining_connections++;
+                }
+            }
+        }
+
+        if (!remaining_connections) connection_collector_running = FALSE;
+
+        LeaveCriticalSection(&connection_pool_cs);
+    } while(remaining_connections);
+
+    FreeLibraryAndExitThread( winhttp_instance, 0 );
+}
+
+static void cache_connection( netconn_t *netconn )
+{
+    TRACE( "caching connection %p\n", netconn );
+
+    EnterCriticalSection( &connection_pool_cs );
+
+    netconn->keep_until = GetTickCount64() + DEFAULT_KEEP_ALIVE_TIMEOUT;
+    list_add_head( &netconn->host->connections, &netconn->entry );
+
+    if (!connection_collector_running)
+    {
+        HMODULE module;
+        HANDLE thread;
+
+        GetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (const 
WCHAR*)winhttp_instance, &module );
+
+        thread = CreateThread(NULL, 0, connection_collector, NULL, 0, NULL);
+        if (thread)
+        {
+            CloseHandle( thread );
+            connection_collector_running = TRUE;
+        }
+        else
+        {
+            FreeLibrary( winhttp_instance );
+        }
+    }
+
+    LeaveCriticalSection( &connection_pool_cs );
+}
+
 static BOOL open_connection( request_t *request )
 {
+    BOOL is_secure = request->hdr.flags & WINHTTP_FLAG_SECURE;
+    hostdata_t *host = NULL, *iter;
+    netconn_t *netconn = NULL;
     connect_t *connect;
     WCHAR *addressW = NULL;
     INTERNET_PORT port;
-    socklen_t slen;
-    struct sockaddr *saddr;
     DWORD len;
 
-    if (netconn_connected( &request->netconn )) goto done;
+    if (request->netconn) goto done;
 
     connect = request->connect;
     port = connect->serverport ? connect->serverport : (request->hdr.flags & 
WINHTTP_FLAG_SECURE ? 443 : 80);
-    saddr = (struct sockaddr *)&connect->sockaddr;
-    slen = sizeof(struct sockaddr);
+
+    EnterCriticalSection( &connection_pool_cs );
+
+    LIST_FOR_EACH_ENTRY( iter, &connection_pool, hostdata_t, entry )
+    {
+        if (iter->port == port && !strcmpW( connect->servername, 
iter->hostname ) && !is_secure == !iter->secure)
+        {
+            host = iter;
+            host->ref++;
+            break;
+        }
+    }
+
+    if (!host)
+    {
+        if ((host = heap_alloc( sizeof(*host) )))
+        {
+            host->ref = 1;
+            host->secure = is_secure;
+            host->port = port;
+            list_init( &host->connections );
+            if ((host->hostname = strdupW( connect->servername )))
+            {
+                list_add_head( &connection_pool, &host->entry );
+            }
+            else
+            {
+                heap_free( host );
+                host = NULL;
+            }
+        }
+    }
+
+    LeaveCriticalSection( &connection_pool_cs );
+
+    if (!host) return FALSE;
+
+    for (;;)
+    {
+        EnterCriticalSection( &connection_pool_cs );
+        if (!list_empty( &host->connections ))
+        {
+            netconn = LIST_ENTRY( list_head( &host->connections ), netconn_t, 
entry );
+            list_remove( &netconn->entry );
+        }
+        LeaveCriticalSection( &connection_pool_cs );
+        if (!netconn) break;
+
+        if (netconn_is_alive( netconn )) break;
+        TRACE("connection %p no longer alive, closing\n", netconn);
+        netconn_close( netconn );
+        netconn = NULL;
+    }
+
+    if (!connect->resolved && netconn)
+    {
+        connect->sockaddr = netconn->sockaddr;
+        connect->resolved = TRUE;
+    }
 
     if (!connect->resolved)
     {
-        len = strlenW( connect->servername ) + 1;
-        send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, 
connect->servername, len );
-
-        if (!netconn_resolve( connect->servername, port, saddr, &slen, 
request->resolve_timeout )) return FALSE;
+        len = strlenW( host->hostname ) + 1;
+        send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, 
host->hostname, len );
+
+        if (!netconn_resolve( host->hostname, port, &connect->sockaddr, 
request->resolve_timeout ))
+        {
+            release_host( host );
+            return FALSE;
+        }
         connect->resolved = TRUE;
 
-        if (!(addressW = addr_to_str( saddr ))) return FALSE;
+        if (!(addressW = addr_to_str( &connect->sockaddr )))
+        {
+            release_host( host );
+            return FALSE;
+        }
         len = strlenW( addressW ) + 1;
         send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, 
addressW, len );
     }
-    if (!addressW && !(addressW = addr_to_str( saddr ))) return FALSE;
-    TRACE("connecting to %s:%u\n", debugstr_w(addressW), port);
-
-    send_callback( &request->hdr, 
WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, addressW, 0 );
-
-    if (!netconn_create( &request->netconn, saddr->sa_family, SOCK_STREAM, 0 ))
-    {
-        heap_free( addressW );
-        return FALSE;
-    }
-    netconn_set_timeout( &request->netconn, TRUE, request->send_timeout );
-    netconn_set_timeout( &request->netconn, FALSE, request->recv_timeout );
-    if (!netconn_connect( &request->netconn, saddr, slen, 
request->connect_timeout ))
-    {
-        netconn_close( &request->netconn );
-        heap_free( addressW );
-        return FALSE;
-    }
-    if (request->hdr.flags & WINHTTP_FLAG_SECURE)
-    {
-        if (connect->session->proxy_server &&
-            strcmpiW( connect->hostname, connect->servername ))
-        {
-            if (!secure_proxy_connect( request ))
+
+    if (!netconn)
+    {
+        if (!addressW && !(addressW = addr_to_str( &connect->sockaddr )))
+        {
+            release_host( host );
+            return FALSE;
+        }
+
+        TRACE("connecting to %s:%u\n", debugstr_w(addressW), port);
+
+        send_callback( &request->hdr, 
WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, addressW, 0 );
+
+        if (!(netconn = netconn_create( host, &connect->sockaddr, 
request->connect_timeout )))
+        {
+            heap_free( addressW );
+            release_host( host );
+            return FALSE;
+        }
+        netconn_set_timeout( netconn, TRUE, request->send_timeout );
+        netconn_set_timeout( netconn, FALSE, request->recv_timeout );
+        if (is_secure)
+        {
+            if (connect->session->proxy_server &&
+                strcmpiW( connect->hostname, connect->servername ))
+            {
+                if (!secure_proxy_connect( request ))
+                {
+                    heap_free( addressW );
+                    netconn_close( netconn );
+                    return FALSE;
+                }
+            }
+            if (!netconn_secure_connect( netconn, connect->hostname, 
request->security_flags ))
             {
                 heap_free( addressW );
+                netconn_close( netconn );
                 return FALSE;
             }
         }
-        if (!netconn_secure_connect( &request->netconn, connect->hostname ))
-        {
-            netconn_close( &request->netconn );
-            heap_free( addressW );
-            return FALSE;
-        }
-    }
-
-    send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, 
addressW, strlenW(addressW) + 1 );
+
+        request->netconn = netconn;
+        send_callback( &request->hdr, 
WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, addressW, strlenW(addressW) + 1 );
+    }
+    else
+    {
+        TRACE("using connection %p\n", netconn);
+
+        netconn_set_timeout( netconn, TRUE, request->send_timeout );
+        netconn_set_timeout( netconn, FALSE, request->recv_timeout );
+        request->netconn = netconn;
+    }
 
 done:
     request->read_pos = request->read_size = 0;
@@ -1058,10 +1239,11 @@
 
 void close_connection( request_t *request )
 {
-    if (!netconn_connected( &request->netconn )) return;
+    if (!request->netconn) return;
 
     send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, 
0, 0 );
-    netconn_close( &request->netconn );
+    netconn_close( request->netconn );
+    request->netconn = NULL;
     send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, 
0, 0 );
 }
 
@@ -1127,7 +1309,7 @@
 
     if (notify) send_callback( &request->hdr, 
WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE, NULL, 0 );
 
-    ret = netconn_recv( &request->netconn, request->read_buf + 
request->read_size,
+    ret = netconn_recv( request->netconn, request->read_buf + 
request->read_size,
                         maxlen - request->read_size, 0, &len );
 
     if (notify) send_callback( &request->hdr, 
WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED, &len, sizeof(len) );
@@ -1229,6 +1411,8 @@
     WCHAR connection[20];
     DWORD size = sizeof(connection);
 
+    if (!request->netconn) return;
+
     if (request->hdr.disable_flags & WINHTTP_DISABLE_KEEP_ALIVE) close = TRUE;
     else if (query_headers( request, WINHTTP_QUERY_CONNECTION, NULL, 
connection, &size, NULL ) ||
              query_headers( request, WINHTTP_QUERY_PROXY_CONNECTION, NULL, 
connection, &size, NULL ))
@@ -1236,7 +1420,14 @@
         if (!strcmpiW( connection, closeW )) close = TRUE;
     }
     else if (!strcmpW( request->version, http1_0 )) close = TRUE;
-    if (close) close_connection( request );
+    if (close)
+    {
+        close_connection( request );
+        return;
+    }
+
+    cache_connection( request->netconn );
+    request->netconn = NULL;
 }
 
 /* return the size of data available to be read immediately */
@@ -1291,13 +1482,20 @@
 /* read any content returned by the server so that the connection can be 
reused */
 static void drain_content( request_t *request )
 {
-    DWORD bytes_read;
+    DWORD size, bytes_read, bytes_total = 0, bytes_left = 
request->content_length - request->content_read;
     char buffer[2048];
 
     refill_buffer( request, FALSE );
     for (;;)
     {
-        if (!read_data( request, buffer, sizeof(buffer), &bytes_read, FALSE ) 
|| !bytes_read) return;
+        if (request->read_chunked) size = sizeof(buffer);
+        else
+        {
+            if (bytes_total >= bytes_left) return;
+            size = min( sizeof(buffer), bytes_left - bytes_total );
+        }
+        if (!read_data( request, buffer, size, &bytes_read, FALSE ) || 
!bytes_read) return;
+        bytes_total += bytes_read;
     }
 }
 
@@ -1362,13 +1560,13 @@
 
     send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST, 
NULL, 0 );
 
-    ret = netconn_send( &request->netconn, req_ascii, len, &bytes_sent );
+    ret = netconn_send( request->netconn, req_ascii, len, &bytes_sent );
     heap_free( req_ascii );
     if (!ret) goto end;
 
     if (optional_len)
     {
-        if (!netconn_send( &request->netconn, optional, optional_len, 
&bytes_sent )) goto end;
+        if (!netconn_send( request->netconn, optional, optional_len, 
&bytes_sent )) goto end;
         request->optional = optional;
         request->optional_len = optional_len;
         len += optional_len;
@@ -2145,7 +2343,7 @@
     WCHAR *versionW, *status_textW, *raw_headers;
     WCHAR status_codeW[4]; /* sizeof("nnn") */
 
-    if (!netconn_connected( &request->netconn )) return FALSE;
+    if (!request->netconn) return FALSE;
 
     do
     {
@@ -2331,11 +2529,11 @@
             connect->hostport = port;
             if (!(ret = set_server_for_hostname( connect, hostname, port ))) 
goto end;
 
-            netconn_close( &request->netconn );
-            if (!(ret = netconn_init( &request->netconn ))) goto end;
+            netconn_close( request->netconn );
+            request->netconn = NULL;
+            request->content_length = request->content_read = 0;
             request->read_pos = request->read_size = 0;
-            request->read_chunked = FALSE;
-            request->read_chunked_eof = FALSE;
+            request->read_chunked = request->read_chunked_eof = FALSE;
         }
         else heap_free( hostname );
 
@@ -2483,14 +2681,14 @@
     if (end_of_read_data( request )) goto done;
 
     count = get_available_data( request );
-    if (!request->read_chunked)
-        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 );
         count = get_available_data( request );
-        if (!request->read_chunked)
-            count += netconn_query_data_available( &request->netconn );
+        if (!request->read_chunked && request->netconn)
+            count += netconn_query_data_available( request->netconn );
     }
 
 done:
@@ -2603,7 +2801,7 @@
     BOOL ret;
     int num_bytes;
 
-    ret = netconn_send( &request->netconn, buffer, to_write, &num_bytes );
+    ret = netconn_send( request->netconn, buffer, to_write, &num_bytes );
 
     if (async)
     {

Modified: trunk/reactos/dll/win32/winhttp/session.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/session.c?rev=75944&r1=75943&r2=75944&view=diff
==============================================================================
--- trunk/reactos/dll/win32/winhttp/session.c   [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/winhttp/session.c   [iso-8859-1] Sun Sep 24 
11:17:43 2017
@@ -685,7 +685,7 @@
     {
     case WINHTTP_OPTION_SECURITY_FLAGS:
     {
-        DWORD flags;
+        DWORD flags = 0;
         int bits;
 
         if (!buffer || *buflen < sizeof(flags))
@@ -697,14 +697,17 @@
 
         flags = 0;
         if (hdr->flags & WINHTTP_FLAG_SECURE) flags |= SECURITY_FLAG_SECURE;
-        flags |= request->netconn.security_flags;
-        bits = netconn_get_cipher_strength( &request->netconn );
-        if (bits >= 128)
-            flags |= SECURITY_FLAG_STRENGTH_STRONG;
-        else if (bits >= 56)
-            flags |= SECURITY_FLAG_STRENGTH_MEDIUM;
-        else
-            flags |= SECURITY_FLAG_STRENGTH_WEAK;
+        flags |= request->security_flags;
+        if (request->netconn)
+        {
+            bits = netconn_get_cipher_strength( request->netconn );
+            if (bits >= 128)
+                flags |= SECURITY_FLAG_STRENGTH_STRONG;
+            else if (bits >= 56)
+                flags |= SECURITY_FLAG_STRENGTH_MEDIUM;
+            else
+                flags |= SECURITY_FLAG_STRENGTH_WEAK;
+        }
         *(DWORD *)buffer = flags;
         *buflen = sizeof(flags);
         return TRUE;
@@ -720,7 +723,7 @@
             return FALSE;
         }
 
-        if (!(cert = netconn_get_certificate( &request->netconn ))) return 
FALSE;
+        if (!request->netconn || !(cert = netconn_get_certificate( 
request->netconn ))) return FALSE;
         *(CERT_CONTEXT **)buffer = (CERT_CONTEXT *)cert;
         *buflen = sizeof(cert);
         return TRUE;
@@ -739,7 +742,7 @@
             set_last_error( ERROR_INSUFFICIENT_BUFFER );
             return FALSE;
         }
-        if (!(cert = netconn_get_certificate( &request->netconn ))) return 
FALSE;
+        if (!request->netconn || !(cert = netconn_get_certificate( 
request->netconn ))) return FALSE;
 
         ci->ftExpiry = cert->pCertInfo->NotAfter;
         ci->ftStart  = cert->pCertInfo->NotBefore;
@@ -754,7 +757,7 @@
         else
             ci->lpszSignatureAlgName  = NULL;
         ci->lpszEncryptionAlgName = NULL;
-        ci->dwKeySize = netconn_get_cipher_strength( &request->netconn );
+        ci->dwKeySize = request->netconn ? netconn_get_cipher_strength( 
request->netconn ) : 0;
 
         CertFreeCertificateContext( cert );
         *buflen = sizeof(*ci);
@@ -769,7 +772,7 @@
             return FALSE;
         }
 
-        *(DWORD *)buffer = netconn_get_cipher_strength( &request->netconn );
+        *(DWORD *)buffer = request->netconn ? netconn_get_cipher_strength( 
request->netconn ) : 0;
         *buflen = sizeof(DWORD);
         return TRUE;
     }
@@ -786,12 +789,12 @@
             set_last_error( ERROR_INSUFFICIENT_BUFFER );
             return FALSE;
         }
-        if (!netconn_connected( &request->netconn ))
+        if (!request->netconn)
         {
             set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_STATE );
             return FALSE;
         }
-        if (getsockname( request->netconn.socket, &local, &len )) 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;
         info->cbSize = sizeof(*info);
@@ -927,7 +930,7 @@
             set_last_error( ERROR_INVALID_PARAMETER );
             return FALSE;
         }
-        request->netconn.security_flags = flags;
+        request->security_flags = flags;
         return TRUE;
     }
     case WINHTTP_OPTION_RESOLVE_TIMEOUT:
@@ -1064,7 +1067,6 @@
     request->connect = connect;
     list_add_head( &connect->hdr.children, &request->hdr.entry );
 
-    if (!netconn_init( &request->netconn )) goto end;
     request->resolve_timeout = connect->session->resolve_timeout;
     request->connect_timeout = connect->session->connect_timeout;
     request->send_timeout = connect->session->send_timeout;
@@ -2047,10 +2049,10 @@
             if (receive < 0) receive = 0;
             request->recv_timeout = receive;
 
-            if (netconn_connected( &request->netconn ))
+            if (request->netconn)
             {
-                if (netconn_set_timeout( &request->netconn, TRUE, send )) ret 
= FALSE;
-                if (netconn_set_timeout( &request->netconn, FALSE, receive )) 
ret = FALSE;
+                if (netconn_set_timeout( request->netconn, TRUE, send )) ret = 
FALSE;
+                if (netconn_set_timeout( request->netconn, FALSE, receive )) 
ret = FALSE;
             }
             break;
 

Modified: trunk/reactos/dll/win32/winhttp/winhttp_private.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/winhttp_private.h?rev=75944&r1=75943&r2=75944&view=diff
==============================================================================
--- trunk/reactos/dll/win32/winhttp/winhttp_private.h   [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/winhttp/winhttp_private.h   [iso-8859-1] Sun Sep 24 
11:17:43 2017
@@ -111,6 +111,15 @@
     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
 {
     object_header_t hdr;
@@ -144,8 +153,12 @@
 
 typedef struct
 {
+    struct list entry;
     int socket;
+    struct sockaddr_storage sockaddr;
     BOOL secure; /* SSL active on connection? */
+    hostdata_t *host;
+    ULONGLONG keep_until;
     CtxtHandle ssl_ctx;
     SecPkgContext_StreamSizes ssl_sizes;
     char *ssl_buf;
@@ -154,7 +167,6 @@
     char *peek_msg;
     char *peek_msg_mem;
     size_t peek_len;
-    DWORD security_flags;
 } netconn_t;
 
 typedef struct
@@ -206,7 +218,8 @@
     LPWSTR raw_headers;
     void *optional;
     DWORD optional_len;
-    netconn_t netconn;
+    netconn_t *netconn;
+    DWORD security_flags;
     int resolve_timeout;
     int connect_timeout;
     int send_timeout;
@@ -295,17 +308,15 @@
 void close_connection( request_t * ) DECLSPEC_HIDDEN;
 
 BOOL netconn_close( netconn_t * ) DECLSPEC_HIDDEN;
-BOOL netconn_connect( netconn_t *, const struct sockaddr *, unsigned int, int 
) DECLSPEC_HIDDEN;
-BOOL netconn_connected( netconn_t * ) DECLSPEC_HIDDEN;
-BOOL netconn_create( netconn_t *, int, int, int ) DECLSPEC_HIDDEN;
-BOOL netconn_init( netconn_t * ) DECLSPEC_HIDDEN;
+netconn_t *netconn_create( hostdata_t *, 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;
-BOOL netconn_resolve( WCHAR *, INTERNET_PORT, struct sockaddr *, socklen_t *, 
int ) DECLSPEC_HIDDEN;
-BOOL netconn_secure_connect( netconn_t *, WCHAR * ) DECLSPEC_HIDDEN;
+BOOL netconn_resolve( WCHAR *, INTERNET_PORT, struct sockaddr_storage *, int ) 
DECLSPEC_HIDDEN;
+BOOL netconn_secure_connect( netconn_t *, WCHAR *, DWORD ) 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;
 
@@ -315,6 +326,8 @@
 void delete_domain( domain_t * ) DECLSPEC_HIDDEN;
 BOOL set_server_for_hostname( connect_t *, LPCWSTR, 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;
 
@@ -395,4 +408,6 @@
     return dst;
 }
 
+extern HINSTANCE winhttp_instance DECLSPEC_HIDDEN;
+
 #endif /* _WINE_WINHTTP_PRIVATE_H_ */

Modified: trunk/reactos/media/doc/README.WINE
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/media/doc/README.WINE?rev=75944&r1=75943&r2=75944&view=diff
==============================================================================
--- trunk/reactos/media/doc/README.WINE [iso-8859-1] (original)
+++ trunk/reactos/media/doc/README.WINE [iso-8859-1] Sun Sep 24 11:17:43 2017
@@ -200,7 +200,7 @@
 reactos/dll/win32/windowscodecsext    # Synced to WineStaging-2.9
 reactos/dll/win32/winemp3.acm         # Synced to WineStaging-2.16
 reactos/dll/win32/wing32              # Synced to WineStaging-2.9
-reactos/dll/win32/winhttp             # Synced to WineStaging-2.9
+reactos/dll/win32/winhttp             # Synced to WineStaging-2.16
 reactos/dll/win32/wininet             # Synced to WineStaging-2.9
 reactos/dll/win32/winmm               # Forked at Wine-20050628
 reactos/dll/win32/winmm/midimap       # Forked at Wine-20050628


Reply via email to