[WINHTTP] Sync with Wine Staging 1.7.47. CORE-9924
authorAmine Khaldi <amine.khaldi@reactos.org>
Wed, 22 Jul 2015 19:39:23 +0000 (19:39 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Wed, 22 Jul 2015 19:39:23 +0000 (19:39 +0000)
svn path=/trunk/; revision=68557

reactos/dll/win32/winhttp/cookie.c
reactos/dll/win32/winhttp/net.c
reactos/dll/win32/winhttp/request.c
reactos/dll/win32/winhttp/session.c
reactos/dll/win32/winhttp/winhttp_private.h
reactos/dll/win32/winhttp/winhttp_ros.diff
reactos/media/doc/README.WINE

index 7ada954..6b0088a 100644 (file)
@@ -42,7 +42,7 @@ static cookie_t *find_cookie( domain_t *domain, const WCHAR *path, const WCHAR *
     LIST_FOR_EACH( item, &domain->cookies )
     {
         cookie = LIST_ENTRY( item, cookie_t, entry );
-        if (!strcmpW( cookie->path, path ) && !strcmpiW( cookie->name, name ))
+        if (!strcmpW( cookie->path, path ) && !strcmpW( cookie->name, name ))
         {
             TRACE("found %s=%s\n", debugstr_w(cookie->name), debugstr_w(cookie->value));
             return cookie;
@@ -109,7 +109,7 @@ static BOOL add_cookie( session_t *session, cookie_t *cookie, WCHAR *domain_name
     else if ((old_cookie = find_cookie( domain, path, cookie->name ))) delete_cookie( old_cookie );
 
     cookie->path = strdupW( path );
-    list_add_tail( &domain->cookies, &cookie->entry );
+    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));
@@ -122,22 +122,14 @@ static cookie_t *parse_cookie( const WCHAR *string )
     const WCHAR *p;
     int len;
 
-    if (!(p = strchrW( string, '=' )))
-    {
-        WARN("no '=' in %s\n", debugstr_w(string));
-        return NULL;
-    }
-    if (p == string)
-    {
-        WARN("empty cookie name in %s\n", debugstr_w(string));
-        return NULL;
-    }
+    if (!(p = strchrW( string, '=' ))) p = string + strlenW( string );
+    len = p - string;
+    while (len && string[len - 1] == ' ') len--;
+    if (!len) return NULL;
 
     if (!(cookie = heap_alloc_zero( sizeof(cookie_t) ))) return NULL;
-
     list_init( &cookie->entry );
 
-    len = p - string;
     if (!(cookie->name = heap_alloc( (len + 1) * sizeof(WCHAR) )))
     {
         heap_free( cookie );
@@ -146,18 +138,20 @@ static cookie_t *parse_cookie( const WCHAR *string )
     memcpy( cookie->name, string, len * sizeof(WCHAR) );
     cookie->name[len] = 0;
 
-    p++; /* skip '=' */
-    while (*p == ' ') p++;
-
-    len = strlenW( p );
-    if (!(cookie->value = heap_alloc( (len + 1) * sizeof(WCHAR) )))
+    if (*p++ == '=')
     {
-        free_cookie( cookie );
-        return NULL;
-    }
-    memcpy( cookie->value, p, len * sizeof(WCHAR) );
-    cookie->value[len] = 0;
+        while (*p && *p == ' ') p++;
+        len = strlenW( p );
+        while (len && p[len - 1] == ' ') len--;
 
+        if (!(cookie->value = heap_alloc( (len + 1) * sizeof(WCHAR) )))
+        {
+            free_cookie( cookie );
+            return NULL;
+        }
+        memcpy( cookie->value, p, len * sizeof(WCHAR) );
+        cookie->value[len] = 0;
+    }
     return cookie;
 }
 
@@ -247,17 +241,25 @@ BOOL add_cookie_headers( request_t *request )
 
                 if (strstrW( request->path, cookie->path ) == request->path)
                 {
-                    const WCHAR format[] = {'C','o','o','k','i','e',':',' ','%','s','=','%','s',0};
-                    int len;
+                    const WCHAR cookieW[] = {'C','o','o','k','i','e',':',' '};
+                    int len, len_cookie = sizeof(cookieW) / sizeof(cookieW[0]), len_name = strlenW( cookie->name );
                     WCHAR *header;
 
-                    len = strlenW( cookie->name ) + strlenW( format ) + strlenW( cookie->value );
+                    len = len_cookie + len_name;
+                    if (cookie->value) len += strlenW( cookie->value ) + 1;
                     if (!(header = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return FALSE;
 
-                    sprintfW( header, format, cookie->name, cookie->value );
+                    memcpy( header, cookieW, len_cookie * sizeof(WCHAR) );
+                    strcpyW( header + len_cookie, cookie->name );
+                    if (cookie->value)
+                    {
+                        header[len_cookie + len_name] = '=';
+                        strcpyW( header + len_cookie + len_name + 1, cookie->value );
+                    }
 
                     TRACE("%s\n", debugstr_w(header));
-                    add_request_headers( request, header, len, WINHTTP_ADDREQ_FLAG_ADD );
+                    add_request_headers( request, header, len,
+                                         WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON );
                     heap_free( header );
                 }
             }
index f825463..bdb7787 100644 (file)
@@ -353,6 +353,7 @@ BOOL netconn_connect( netconn_t *conn, const struct sockaddr *sockaddr, unsigned
         res = sock_get_error( errno );
         if (res == WSAEWOULDBLOCK || res == WSAEINPROGRESS)
         {
+#ifdef __REACTOS__
             /* ReactOS: use select instead of poll */
             fd_set outfd;
             struct timeval tv;
@@ -364,6 +365,13 @@ BOOL netconn_connect( netconn_t *conn, const struct sockaddr *sockaddr, unsigned
             tv.tv_usec = timeout * 1000;
 
             if (select( 0, NULL, &outfd, NULL, &tv ) > 0)
+#else
+            struct pollfd pfd;
+
+            pfd.fd = conn->socket;
+            pfd.events = POLLOUT;
+            if (poll( &pfd, 1, timeout ) > 0)
+#endif
                 ret = TRUE;
             else
                 res = sock_get_error( errno );
index 6cf9d78..a2fa48a 100644 (file)
@@ -316,12 +316,8 @@ static header_t *parse_header( LPCWSTR string )
 
     q++; /* skip past colon */
     while (*q == ' ') q++;
-    if (!*q)
-    {
-        WARN("no value in line %s\n", debugstr_w(string));
-        return header;
-    }
     len = strlenW( q );
+
     if (!(header->value = heap_alloc( (len + 1) * sizeof(WCHAR) )))
     {
         free_header( header );
@@ -393,76 +389,65 @@ static BOOL delete_header( request_t *request, DWORD index )
 static BOOL process_header( request_t *request, LPCWSTR field, LPCWSTR value, DWORD flags, BOOL request_only )
 {
     int index;
-    header_t *header;
+    header_t hdr;
 
     TRACE("%s: %s 0x%08x\n", debugstr_w(field), debugstr_w(value), flags);
 
-    /* replace wins out over add */
-    if (flags & WINHTTP_ADDREQ_FLAG_REPLACE) flags &= ~WINHTTP_ADDREQ_FLAG_ADD;
-
-    if (flags & WINHTTP_ADDREQ_FLAG_ADD) index = -1;
-    else
-        index = get_header_index( request, field, 0, request_only );
-
-    if (index >= 0)
+    if ((index = get_header_index( request, field, 0, request_only )) >= 0)
     {
         if (flags & WINHTTP_ADDREQ_FLAG_ADD_IF_NEW) return FALSE;
-        header = &request->headers[index];
     }
-    else if (value)
+
+    if (flags & WINHTTP_ADDREQ_FLAG_REPLACE)
     {
-        header_t hdr;
+        if (index >= 0)
+        {
+            delete_header( request, index );
+            if (!value || !value[0]) return TRUE;
+        }
+        else if (!(flags & WINHTTP_ADDREQ_FLAG_ADD))
+        {
+            set_last_error( ERROR_WINHTTP_HEADER_NOT_FOUND );
+            return FALSE;
+        }
 
         hdr.field = (LPWSTR)field;
         hdr.value = (LPWSTR)value;
         hdr.is_request = request_only;
-
         return insert_header( request, &hdr );
     }
-    /* no value to delete */
-    else return TRUE;
-
-    if (flags & WINHTTP_ADDREQ_FLAG_REPLACE)
-    {
-        delete_header( request, index );
-        if (value)
-        {
-            header_t hdr;
-
-            hdr.field = (LPWSTR)field;
-            hdr.value = (LPWSTR)value;
-            hdr.is_request = request_only;
-
-            return insert_header( request, &hdr );
-        }
-        return TRUE;
-    }
-    else if (flags & (WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA | WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON))
+    else if (value)
     {
-        WCHAR sep, *tmp;
-        int len, orig_len, value_len;
 
-        orig_len = strlenW( header->value );
-        value_len = strlenW( value );
+        if ((flags & (WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA | WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON)) &&
+            index >= 0)
+        {
+            WCHAR *tmp;
+            int len, len_orig, len_value;
+            header_t *header = &request->headers[index];
 
-        if (flags & WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA) sep = ',';
-        else sep = ';';
+            len_orig = strlenW( header->value );
+            len_value = strlenW( value );
 
-        len = orig_len + value_len + 2;
-        if ((tmp = heap_realloc( header->value, (len + 1) * sizeof(WCHAR) )))
-        {
+            len = len_orig + len_value + 2;
+            if (!(tmp = heap_realloc( header->value, (len + 1) * sizeof(WCHAR) ))) return FALSE;
             header->value = tmp;
+            header->value[len_orig++] = (flags & WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA) ? ',' : ';';
+            header->value[len_orig++] = ' ';
 
-            header->value[orig_len] = sep;
-            orig_len++;
-            header->value[orig_len] = ' ';
-            orig_len++;
-
-            memcpy( &header->value[orig_len], value, value_len * sizeof(WCHAR) );
+            memcpy( &header->value[len_orig], value, len_value * sizeof(WCHAR) );
             header->value[len] = 0;
             return TRUE;
         }
+        else
+        {
+            hdr.field = (LPWSTR)field;
+            hdr.value = (LPWSTR)value;
+            hdr.is_request = request_only;
+            return insert_header( request, &hdr );
+        }
     }
+
     return TRUE;
 }
 
@@ -475,7 +460,8 @@ BOOL add_request_headers( request_t *request, LPCWSTR headers, DWORD len, DWORD
     if (len == ~0u) len = strlenW( headers );
     if (!len) return TRUE;
     if (!(buffer = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return FALSE;
-    strcpyW( buffer, headers );
+    memcpy( buffer, headers, len * sizeof(WCHAR) );
+    buffer[len] = 0;
 
     p = buffer;
     do
@@ -519,7 +505,7 @@ BOOL WINAPI WinHttpAddRequestHeaders( HINTERNET hrequest, LPCWSTR headers, DWORD
 
     TRACE("%p, %s, 0x%x, 0x%08x\n", hrequest, debugstr_w(headers), len, flags);
 
-    if (!headers)
+    if (!headers || !len)
     {
         set_last_error( ERROR_INVALID_PARAMETER );
         return FALSE;
@@ -972,10 +958,10 @@ static BOOL secure_proxy_connect( request_t *request )
 #define INET6_ADDRSTRLEN 46
 #endif
 
-static WCHAR *addr_to_str( const struct sockaddr *addr )
+static WCHAR *addr_to_str( struct sockaddr *addr )
 {
     char buf[INET6_ADDRSTRLEN];
-    const void *src;
+    void *src;
 
     switch (addr->sa_family)
     {
@@ -1240,6 +1226,8 @@ BOOL WINAPI WinHttpSendRequest( HINTERNET hrequest, LPCWSTR headers, DWORD heade
         return FALSE;
     }
 
+    if (headers && !headers_len) headers_len = strlenW( headers );
+
     if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC)
     {
         send_request_t *s;
@@ -1562,8 +1550,16 @@ static BOOL do_authorization( request_t *request, DWORD target, DWORD scheme_fla
             return FALSE;
         auth_ptr = &request->authinfo;
         auth_target = attr_authorization;
-        username = request->connect->username;
-        password = request->connect->password;
+        if (request->creds[TARGET_SERVER][scheme].username)
+        {
+            username = request->creds[TARGET_SERVER][scheme].username;
+            password = request->creds[TARGET_SERVER][scheme].password;
+        }
+        else
+        {
+            username = request->connect->username;
+            password = request->connect->password;
+        }
         break;
 
     case WINHTTP_AUTH_TARGET_PROXY:
@@ -1571,8 +1567,16 @@ static BOOL do_authorization( request_t *request, DWORD target, DWORD scheme_fla
             return FALSE;
         auth_ptr = &request->proxy_authinfo;
         auth_target = attr_proxy_authorization;
-        username = request->connect->session->proxy_username;
-        password = request->connect->session->proxy_password;
+        if (request->creds[TARGET_PROXY][scheme].username)
+        {
+            username = request->creds[TARGET_PROXY][scheme].username;
+            password = request->creds[TARGET_PROXY][scheme].password;
+        }
+        else
+        {
+            username = request->connect->session->proxy_username;
+            password = request->connect->session->proxy_password;
+        }
         break;
 
     default:
@@ -1756,11 +1760,12 @@ static BOOL do_authorization( request_t *request, DWORD target, DWORD scheme_fla
     return ret;
 }
 
-static BOOL set_credentials( request_t *request, DWORD target, DWORD scheme, const WCHAR *username,
+static BOOL set_credentials( request_t *request, DWORD target, DWORD scheme_flag, const WCHAR *username,
                              const WCHAR *password )
 {
-    if ((scheme == WINHTTP_AUTH_SCHEME_BASIC || scheme == WINHTTP_AUTH_SCHEME_DIGEST) &&
-        (!username || !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 );
         return FALSE;
@@ -1769,24 +1774,24 @@ static BOOL set_credentials( request_t *request, DWORD target, DWORD scheme, con
     {
     case WINHTTP_AUTH_TARGET_SERVER:
     {
-        heap_free( request->connect->username );
-        if (!username) request->connect->username = NULL;
-        else if (!(request->connect->username = strdupW( username ))) return FALSE;
+        heap_free( request->creds[TARGET_SERVER][scheme].username );
+        if (!username) request->creds[TARGET_SERVER][scheme].username = NULL;
+        else if (!(request->creds[TARGET_SERVER][scheme].username = strdupW( username ))) return FALSE;
 
-        heap_free( request->connect->password );
-        if (!password) request->connect->password = NULL;
-        else if (!(request->connect->password = strdupW( password ))) return FALSE;
+        heap_free( request->creds[TARGET_SERVER][scheme].password );
+        if (!password) request->creds[TARGET_SERVER][scheme].password = NULL;
+        else if (!(request->creds[TARGET_SERVER][scheme].password = strdupW( password ))) return FALSE;
         break;
     }
     case WINHTTP_AUTH_TARGET_PROXY:
     {
-        heap_free( request->connect->session->proxy_username );
-        if (!username) request->connect->session->proxy_username = NULL;
-        else if (!(request->connect->session->proxy_username = strdupW( username ))) return FALSE;
+        heap_free( request->creds[TARGET_PROXY][scheme].username );
+        if (!username) request->creds[TARGET_PROXY][scheme].username = NULL;
+        else if (!(request->creds[TARGET_PROXY][scheme].username = strdupW( username ))) return FALSE;
 
-        heap_free( request->connect->session->proxy_password );
-        if (!password) request->connect->session->proxy_password = NULL;
-        else if (!(request->connect->session->proxy_password = strdupW( password ))) return FALSE;
+        heap_free( request->creds[TARGET_PROXY][scheme].password );
+        if (!password) request->creds[TARGET_PROXY][scheme].password = NULL;
+        else if (!(request->creds[TARGET_PROXY][scheme].password = strdupW( password ))) return FALSE;
         break;
     }
     default:
@@ -2046,9 +2051,13 @@ static BOOL refill_buffer( request_t *request, BOOL notify )
         {
             if (!start_next_chunk( request, notify )) return FALSE;
         }
+        len = min( len, request->read_chunked_size );
     }
-    if (!request->read_chunked && request->content_length != ~0u)
+    else if (request->content_length != ~0u)
+    {
         len = min( len, request->content_length - request->content_read );
+    }
+
     if (len <= request->read_size) return TRUE;
     if (!read_more_data( request, len, notify )) return FALSE;
     if (!request->read_size) request->content_length = request->content_read = 0;
@@ -2094,7 +2103,9 @@ static BOOL read_reply( request_t *request )
     /*  we rely on the fact that the protocol is ascii */
     MultiByteToWideChar( CP_ACP, 0, status_code, len, status_codeW, len );
     status_codeW[len] = 0;
-    if (!(process_header( request, attr_status, status_codeW, WINHTTP_ADDREQ_FLAG_REPLACE, FALSE ))) return FALSE;
+    if (!(process_header( request, attr_status, status_codeW,
+                          WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE, FALSE )))
+        return FALSE;
 
     len = status_code - buffer;
     if (!(versionW = heap_alloc( len * sizeof(WCHAR) ))) return FALSE;
@@ -2265,13 +2276,21 @@ static BOOL handle_redirect( request_t *request, DWORD status )
     {
         WCHAR *path, *p;
 
-        len = strlenW( location ) + 1;
-        if (location[0] != '/') len++;
-        if (!(p = path = heap_alloc( len * sizeof(WCHAR) ))) goto end;
-
-        if (location[0] != '/') *p++ = '/';
-        strcpyW( p, location );
-
+        if (location[0] == '/')
+        {
+            len = strlenW( location );
+            if (!(path = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end;
+            strcpyW( path, location );
+        }
+        else
+        {
+            if ((p = strrchrW( request->path, '/' ))) *p = 0;
+            len = strlenW( request->path ) + 1 + strlenW( location );
+            if (!(path = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end;
+            strcpyW( path, request->path );
+            strcatW( path, slashW );
+            strcatW( path, location );
+        }
         heap_free( request->path );
         request->path = path;
 
@@ -2316,7 +2335,7 @@ static BOOL handle_redirect( request_t *request, DWORD status )
         }
         else heap_free( hostname );
 
-        if (!(ret = add_host_header( request, WINHTTP_ADDREQ_FLAG_REPLACE ))) goto end;
+        if (!(ret = add_host_header( request, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE ))) goto end;
         if (!(ret = open_connection( request ))) goto end;
 
         heap_free( request->path );
@@ -2680,6 +2699,7 @@ struct winhttp_request
     LONG send_timeout;
     LONG receive_timeout;
     WINHTTP_PROXY_INFO proxy;
+    BOOL async;
 };
 
 static inline struct winhttp_request *impl_from_IWinHttpRequest( IWinHttpRequest *iface )
@@ -2698,8 +2718,20 @@ static ULONG WINAPI winhttp_request_AddRef(
 static void cancel_request( struct winhttp_request *request )
 {
     if (request->state <= REQUEST_STATE_CANCELLED) return;
-    if (request->thread) SetEvent( request->cancel );
+
+    SetEvent( request->cancel );
+    LeaveCriticalSection( &request->cs );
+    WaitForSingleObject( request->thread, INFINITE );
+    EnterCriticalSection( &request->cs );
+
     request->state = REQUEST_STATE_CANCELLED;
+
+    CloseHandle( request->thread );
+    request->thread = NULL;
+    CloseHandle( request->wait );
+    request->wait = NULL;
+    CloseHandle( request->cancel );
+    request->cancel = NULL;
 }
 
 /* critical section must be held */
@@ -3006,6 +3038,7 @@ static void initialize_request( struct winhttp_request *request )
     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;
@@ -3019,6 +3052,26 @@ static void initialize_request( struct winhttp_request *request )
     request->state = REQUEST_STATE_INITIALIZED;
 }
 
+static void reset_request( struct winhttp_request *request )
+{
+    cancel_request( request );
+    WinHttpCloseHandle( request->hrequest );
+    request->hrequest = NULL;
+    WinHttpCloseHandle( request->hconnect );
+    request->hconnect = NULL;
+    heap_free( request->buffer );
+    request->buffer   = NULL;
+    heap_free( request->verb );
+    request->verb     = NULL;
+    request->offset   = 0;
+    request->bytes_available = 0;
+    request->bytes_read = 0;
+    request->error    = ERROR_SUCCESS;
+    request->async    = FALSE;
+    VariantClear( &request->data );
+    request->state = REQUEST_STATE_INITIALIZED;
+}
+
 static HRESULT WINAPI winhttp_request_Open(
     IWinHttpRequest *iface,
     BSTR method,
@@ -3033,10 +3086,9 @@ static HRESULT WINAPI winhttp_request_Open(
         'W','i','n','3','2',';',' ','W','i','n','H','t','t','p','.','W','i','n','H','t','t','p',
         'R','e','q','u','e','s','t','.','5',')',0};
     struct winhttp_request *request = impl_from_IWinHttpRequest( iface );
-    HINTERNET hsession = NULL, hconnect = NULL, hrequest;
     URL_COMPONENTS uc;
     WCHAR *hostname, *path = NULL, *verb = NULL;
-    DWORD err = ERROR_OUTOFMEMORY, len, flags = 0, request_flags = 0;
+    DWORD err = ERROR_OUTOFMEMORY, len, flags = 0;
 
     TRACE("%p, %s, %s, %s\n", request, debugstr_w(method), debugstr_w(url),
           debugstr_variant(&async));
@@ -3052,12 +3104,9 @@ static HRESULT WINAPI winhttp_request_Open(
     if (!WinHttpCrackUrl( url, 0, 0, &uc )) return HRESULT_FROM_WIN32( get_last_error() );
 
     EnterCriticalSection( &request->cs );
-    if (request->state != REQUEST_STATE_INITIALIZED)
-    {
-        cancel_request( request );
-        free_request( request );
-        initialize_request( request );
-    }
+    if (request->state < REQUEST_STATE_INITIALIZED) initialize_request( request );
+    else reset_request( request );
+
     if (!(hostname = heap_alloc( (uc.dwHostNameLength + 1) * sizeof(WCHAR) ))) goto error;
     memcpy( hostname, uc.lpszHostName, uc.dwHostNameLength * sizeof(WCHAR) );
     hostname[uc.dwHostNameLength] = 0;
@@ -3067,37 +3116,44 @@ static HRESULT WINAPI winhttp_request_Open(
     path[uc.dwUrlPathLength + uc.dwExtraInfoLength] = 0;
 
     if (!(verb = strdupW( method ))) goto error;
-    if (SUCCEEDED( VariantChangeType( &async, &async, 0, VT_BOOL )) && V_BOOL( &async )) flags |= WINHTTP_FLAG_ASYNC;
-    if (!(hsession = WinHttpOpen( user_agentW, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, NULL, NULL, flags )))
+    if (SUCCEEDED( VariantChangeType( &async, &async, 0, VT_BOOL )) && V_BOOL( &async )) request->async = TRUE;
+    else request->async = FALSE;
+
+    if (!request->hsession)
     {
-        err = get_last_error();
-        goto error;
+        if (!(request->hsession = WinHttpOpen( user_agentW, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, NULL, NULL,
+                                               WINHTTP_FLAG_ASYNC )))
+        {
+            err = get_last_error();
+            goto error;
+        }
+        if (!(request->hconnect = WinHttpConnect( request->hsession, hostname, uc.nPort, 0 )))
+        {
+            WinHttpCloseHandle( request->hsession );
+            request->hsession = NULL;
+            err = get_last_error();
+            goto error;
+        }
     }
-    if (!(hconnect = WinHttpConnect( hsession, hostname, uc.nPort, 0 )))
+    else if (!(request->hconnect = WinHttpConnect( request->hsession, hostname, uc.nPort, 0 )))
     {
         err = get_last_error();
         goto error;
     }
+
     len = sizeof(httpsW) / sizeof(WCHAR);
     if (uc.dwSchemeLength == len && !memcmp( uc.lpszScheme, httpsW, len * sizeof(WCHAR) ))
     {
-        request_flags |= WINHTTP_FLAG_SECURE;
+        flags |= WINHTTP_FLAG_SECURE;
     }
-    if (!(hrequest = WinHttpOpenRequest( hconnect, method, path, NULL, NULL, acceptW, request_flags )))
+    if (!(request->hrequest = WinHttpOpenRequest( request->hconnect, method, path, NULL, NULL, acceptW, flags )))
     {
         err = get_last_error();
         goto error;
     }
-    if (flags & WINHTTP_FLAG_ASYNC)
-    {
-        request->wait   = CreateEventW( NULL, FALSE, FALSE, NULL );
-        request->cancel = CreateEventW( NULL, FALSE, FALSE, NULL );
-        WinHttpSetOption( hrequest, WINHTTP_OPTION_CONTEXT_VALUE, &request, sizeof(request) );
-    }
+    WinHttpSetOption( request->hrequest, WINHTTP_OPTION_CONTEXT_VALUE, &request, sizeof(request) );
+
     request->state = REQUEST_STATE_OPEN;
-    request->hsession = hsession;
-    request->hconnect = hconnect;
-    request->hrequest = hrequest;
     request->verb = verb;
     heap_free( hostname );
     heap_free( path );
@@ -3105,8 +3161,8 @@ static HRESULT WINAPI winhttp_request_Open(
     return S_OK;
 
 error:
-    WinHttpCloseHandle( hconnect );
-    WinHttpCloseHandle( hsession );
+    WinHttpCloseHandle( request->hconnect );
+    request->hconnect = NULL;
     heap_free( hostname );
     heap_free( path );
     heap_free( verb );
@@ -3148,7 +3204,8 @@ static HRESULT WINAPI winhttp_request_SetRequestHeader(
         goto done;
     }
     sprintfW( str, fmtW, header, value ? value : emptyW );
-    if (!WinHttpAddRequestHeaders( request->hrequest, str, len, WINHTTP_ADDREQ_FLAG_REPLACE ))
+    if (!WinHttpAddRequestHeaders( request->hrequest, str, len,
+                                   WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE ))
     {
         err = get_last_error();
     }
@@ -3268,22 +3325,14 @@ static void CALLBACK wait_status_callback( HINTERNET handle, DWORD_PTR context,
 
 static void wait_set_status_callback( struct winhttp_request *request, DWORD status )
 {
-    if (!request->wait) return;
     status |= WINHTTP_CALLBACK_STATUS_REQUEST_ERROR;
     WinHttpSetStatusCallback( request->hrequest, wait_status_callback, status, 0 );
 }
 
 static DWORD wait_for_completion( struct winhttp_request *request )
 {
-    HANDLE handles[2];
+    HANDLE handles[2] = { request->wait, request->cancel };
 
-    if (!request->wait)
-    {
-        request->error = ERROR_SUCCESS;
-        return ERROR_SUCCESS;
-    }
-    handles[0] = request->wait;
-    handles[1] = request->cancel;
     switch (WaitForMultipleObjects( 2, handles, FALSE, INFINITE ))
     {
     case WAIT_OBJECT_0:
@@ -3466,6 +3515,39 @@ static DWORD CALLBACK send_and_receive_proc( void *arg )
     return request_send_and_receive( request );
 }
 
+/* critical section must be held */
+static DWORD request_wait( struct winhttp_request *request, DWORD timeout )
+{
+    HANDLE thread = request->thread;
+    DWORD err, ret;
+
+    LeaveCriticalSection( &request->cs );
+    while ((err = MsgWaitForMultipleObjects( 1, &thread, FALSE, timeout, QS_ALLINPUT )) == WAIT_OBJECT_0 + 1)
+    {
+        MSG msg;
+        while (PeekMessageW( &msg, NULL, 0, 0, PM_REMOVE ))
+        {
+            TranslateMessage( &msg );
+            DispatchMessageW( &msg );
+        }
+    }
+    switch (err)
+    {
+    case WAIT_OBJECT_0:
+        ret = ERROR_SUCCESS;
+        break;
+    case WAIT_TIMEOUT:
+        ret = ERROR_TIMEOUT;
+        break;
+    case WAIT_FAILED:
+    default:
+        ret = get_last_error();
+        break;
+    }
+    EnterCriticalSection( &request->cs );
+    return ret;
+}
+
 static HRESULT WINAPI winhttp_request_Send(
     IWinHttpRequest *iface,
     VARIANT body )
@@ -3487,20 +3569,22 @@ static HRESULT WINAPI winhttp_request_Send(
         return S_OK;
     }
     VariantClear( &request->data );
-    if ((hr = VariantCopyInd( &request->data, &body )) != S_OK) {
+    if ((hr = VariantCopyInd( &request->data, &body )) != S_OK)
+    {
         LeaveCriticalSection( &request->cs );
         return hr;
     }
-
-    if (request->wait) /* async request */
+    if (!(request->thread = CreateThread( NULL, 0, send_and_receive_proc, request, 0, NULL )))
     {
-        if (!(request->thread = CreateThread( NULL, 0, send_and_receive_proc, request, 0, NULL )))
-        {
-            LeaveCriticalSection( &request->cs );
-            return HRESULT_FROM_WIN32( get_last_error() );
-        }
+        LeaveCriticalSection( &request->cs );
+        return HRESULT_FROM_WIN32( get_last_error() );
+    }
+    request->wait = CreateEventW( NULL, FALSE, FALSE, NULL );
+    request->cancel = CreateEventW( NULL, FALSE, FALSE, NULL );
+    if (!request->async)
+    {
+        hr = HRESULT_FROM_WIN32( request_wait( request, INFINITE ) );
     }
-    else hr = request_send_and_receive( request );
     LeaveCriticalSection( &request->cs );
     return hr;
 }
@@ -3923,39 +4007,6 @@ static HRESULT WINAPI winhttp_request_put_Option(
     return hr;
 }
 
-/* critical section must be held */
-static DWORD wait_for_response( struct winhttp_request *request, DWORD timeout )
-{
-    HANDLE thread = request->thread;
-    DWORD err, ret;
-
-    LeaveCriticalSection( &request->cs );
-    while ((err = MsgWaitForMultipleObjects( 1, &thread, FALSE, timeout, QS_ALLINPUT )) == WAIT_OBJECT_0 + 1)
-    {
-        MSG msg;
-        while (PeekMessageW( &msg, NULL, 0, 0, PM_REMOVE ))
-        {
-            TranslateMessage( &msg );
-            DispatchMessageW( &msg );
-        }
-    }
-    switch (err)
-    {
-    case WAIT_OBJECT_0:
-        ret = ERROR_SUCCESS;
-        break;
-    case WAIT_TIMEOUT:
-        ret = ERROR_TIMEOUT;
-        break;
-    case WAIT_FAILED:
-    default:
-        ret = get_last_error();
-        break;
-    }
-    EnterCriticalSection( &request->cs );
-    return ret;
-}
-
 static HRESULT WINAPI winhttp_request_WaitForResponse(
     IWinHttpRequest *iface,
     VARIANT timeout,
@@ -3967,17 +4018,12 @@ static HRESULT WINAPI winhttp_request_WaitForResponse(
     TRACE("%p, %s, %p\n", request, debugstr_variant(&timeout), succeeded);
 
     EnterCriticalSection( &request->cs );
-    if (!request->thread)
-    {
-        LeaveCriticalSection( &request->cs );
-        return S_OK;
-    }
     if (request->state >= REQUEST_STATE_RESPONSE_RECEIVED)
     {
         LeaveCriticalSection( &request->cs );
         return S_OK;
     }
-    switch ((err = wait_for_response( request, msecs )))
+    switch ((err = request_wait( request, msecs )))
     {
     case ERROR_TIMEOUT:
         if (succeeded) *succeeded = VARIANT_FALSE;
index 8c5689f..02c7ae7 100644 (file)
@@ -535,7 +535,7 @@ end:
 static void request_destroy( object_header_t *hdr )
 {
     request_t *request = (request_t *)hdr;
-    unsigned int i;
+    unsigned int i, j;
 
     TRACE("%p\n", request);
 
@@ -546,6 +546,7 @@ static void request_destroy( object_header_t *hdr )
         CloseHandle( request->task_thread );
         CloseHandle( request->task_cancel );
         CloseHandle( request->task_wait );
+        request->task_cs.DebugInfo->Spare[0] = 0;
         DeleteCriticalSection( &request->task_cs );
     }
     release_object( &request->connect->hdr );
@@ -566,6 +567,14 @@ static void request_destroy( object_header_t *hdr )
     heap_free( request->headers );
     for (i = 0; i < request->num_accept_types; i++) heap_free( request->accept_types[i] );
     heap_free( request->accept_types );
+    for (i = 0; i < TARGET_MAX; i++)
+    {
+        for (j = 0; j < SCHEME_MAX; j++)
+        {
+            heap_free( request->creds[i][j].username );
+            heap_free( request->creds[i][j].password );
+        }
+    }
     heap_free( request );
 }
 
@@ -1310,7 +1319,8 @@ static BOOL get_system_proxy_autoconfig_url( char *buf, DWORD buflen )
     CFRelease( settings );
     return ret;
 #else
-    FIXME( "no support on this platform\n" );
+    static int once;
+    if (!once++) FIXME( "no support on this platform\n" );
     return FALSE;
 #endif
 }
index c342065..052c0a5 100644 (file)
@@ -163,6 +163,14 @@ typedef struct
     BOOL is_request; /* part of request headers? */
 } header_t;
 
+enum auth_target
+{
+    TARGET_INVALID = -1,
+    TARGET_SERVER,
+    TARGET_PROXY,
+    TARGET_MAX
+};
+
 enum auth_scheme
 {
     SCHEME_INVALID = -1,
@@ -170,7 +178,8 @@ enum auth_scheme
     SCHEME_NTLM,
     SCHEME_PASSPORT,
     SCHEME_DIGEST,
-    SCHEME_NEGOTIATE
+    SCHEME_NEGOTIATE,
+    SCHEME_MAX
 };
 
 struct authinfo
@@ -221,6 +230,11 @@ typedef struct
     HANDLE task_thread;
     struct list task_queue;
     CRITICAL_SECTION task_cs;
+    struct
+    {
+        WCHAR *username;
+        WCHAR *password;
+    } creds[TARGET_MAX][SCHEME_MAX];
 } request_t;
 
 typedef struct _task_header_t task_header_t;
index 3802ba7..60f010e 100644 (file)
@@ -1,6 +1,6 @@
-diff -pudN e:\wine\dlls\winhttp/net.c dll\win32\winhttp/net.c
+diff -pudN e:\wine\dlls\winhttp/net.c e:\reactos\dll\win32\winhttp/net.c
 --- e:\wine\dlls\winhttp/net.c 2015-02-21 17:13:15.365542100 +0100
-+++ dll\win32\winhttp/net.c    2015-04-09 13:48:12.485050200 +0100
++++ e:\reactos\dll\win32\winhttp/net.c 2015-07-20 14:25:14.321893000 +0100
 @@ -73,6 +50,7 @@ static CRITICAL_SECTION cs_gethostbyname
  #endif
  
@@ -25,18 +25,15 @@ diff -pudN e:\wine\dlls\winhttp/net.c dll\win32\winhttp/net.c
  
  static int sock_send(int fd, const void *msg, size_t len, int flags)
  {
-@@ -366,11 +353,17 @@ BOOL netconn_connect( netconn_t *conn, c
+@@ -366,11 +353,25 @@ BOOL netconn_connect( netconn_t *conn, c
          res = sock_get_error( errno );
          if (res == WSAEWOULDBLOCK || res == WSAEINPROGRESS)
          {
--            struct pollfd pfd;
++#ifdef __REACTOS__
 +            /* ReactOS: use select instead of poll */
 +            fd_set outfd;
 +            struct timeval tv;
--            pfd.fd = conn->socket;
--            pfd.events = POLLOUT;
--            if (poll( &pfd, 1, timeout ) > 0)
++
 +            FD_ZERO(&outfd);
 +            FD_SET(conn->socket, &outfd);
 +
@@ -44,13 +41,20 @@ diff -pudN e:\wine\dlls\winhttp/net.c dll\win32\winhttp/net.c
 +            tv.tv_usec = timeout * 1000;
 +
 +            if (select( 0, NULL, &outfd, NULL, &tv ) > 0)
++#else
+             struct pollfd pfd;
+             pfd.fd = conn->socket;
+             pfd.events = POLLOUT;
+             if (poll( &pfd, 1, timeout ) > 0)
++#endif
                  ret = TRUE;
              else
                  res = sock_get_error( errno );
-diff -pudN e:\wine\dlls\winhttp/request.c dll\win32\winhttp/request.c
---- e:\wine\dlls\winhttp/request.c     2015-02-22 13:25:32.479716600 +0100
-+++ dll\win32\winhttp/request.c        2015-04-09 13:49:32.753638400 +0100
-@@ -1275,6 +1264,7 @@ BOOL WINAPI WinHttpSendRequest( HINTERNE
+diff -pudN e:\wine\dlls\winhttp/request.c e:\reactos\dll\win32\winhttp/request.c
+--- e:\wine\dlls\winhttp/request.c     2015-07-14 15:44:36.027191600 +0100
++++ e:\reactos\dll\win32\winhttp/request.c     2015-07-20 14:28:31.803188200 +0100
+@@ -1263,6 +1252,7 @@ BOOL WINAPI WinHttpSendRequest( HINTERNE
      return ret;
  }
  
@@ -58,7 +62,7 @@ diff -pudN e:\wine\dlls\winhttp/request.c dll\win32\winhttp/request.c
  #define ARRAYSIZE(array) (sizeof(array) / sizeof((array)[0]))
  
  static const WCHAR basicW[]     = {'B','a','s','i','c',0};
-@@ -2722,8 +2712,8 @@ static void free_request( struct winhttp
+@@ -2754,8 +2744,8 @@ static void free_request( struct winhttp
      CloseHandle( request->thread );
      CloseHandle( request->wait );
      CloseHandle( request->cancel );
@@ -69,7 +73,7 @@ diff -pudN e:\wine\dlls\winhttp/request.c dll\win32\winhttp/request.c
      heap_free( request->buffer );
      heap_free( request->verb );
      VariantClear( &request->data );
-@@ -2927,16 +2917,16 @@ static HRESULT WINAPI winhttp_request_Se
+@@ -2959,16 +2949,16 @@ static HRESULT WINAPI winhttp_request_Se
      {
      case HTTPREQUEST_PROXYSETTING_DEFAULT:
          request->proxy.dwAccessType = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
@@ -90,7 +94,7 @@ diff -pudN e:\wine\dlls\winhttp/request.c dll\win32\winhttp/request.c
          request->proxy.lpszProxy = NULL;
          request->proxy.lpszProxyBypass = NULL;
          break;
-@@ -2945,12 +2935,12 @@ static HRESULT WINAPI winhttp_request_Se
+@@ -2977,12 +2967,12 @@ static HRESULT WINAPI winhttp_request_Se
          request->proxy.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
          if (V_VT( &proxy_server ) == VT_BSTR)
          {
@@ -105,9 +109,9 @@ diff -pudN e:\wine\dlls\winhttp/request.c dll\win32\winhttp/request.c
              request->proxy.lpszProxyBypass = strdupW( V_BSTR( &bypass_list ) );
          }
          break;
-diff -pudN e:\wine\dlls\winhttp/session.c dll\win32\winhttp/session.c
---- e:\wine\dlls\winhttp/session.c     2015-02-22 13:25:32.480717300 +0100
-+++ dll\win32\winhttp/session.c        2015-04-09 13:50:02.955100200 +0100
+diff -pudN e:\wine\dlls\winhttp/session.c e:\reactos\dll\win32\winhttp/session.c
+--- e:\wine\dlls\winhttp/session.c     2015-07-14 15:44:36.029191700 +0100
++++ e:\reactos\dll\win32\winhttp/session.c     2015-07-20 14:29:15.686698200 +0100
 @@ -109,6 +81,9 @@ static void session_destroy( object_head
      heap_free( session->proxy_username );
      heap_free( session->proxy_password );
@@ -149,7 +153,7 @@ diff -pudN e:\wine\dlls\winhttp/session.c dll\win32\winhttp/session.c
              goto end;
          }
      }
-@@ -615,7 +595,7 @@ static WCHAR *blob_to_str( DWORD encodin
+@@ -624,7 +604,7 @@ static WCHAR *blob_to_str( DWORD encodin
  
  static BOOL convert_sockaddr( const struct sockaddr *addr, SOCKADDR_STORAGE *addr_storage )
  {
index 347577b..1af4a27 100644 (file)
@@ -206,7 +206,7 @@ reactos/dll/win32/windowscodecs       # Synced to WineStaging-1.7.47
 reactos/dll/win32/windowscodecsext    # Synced to WineStaging-1.7.37
 reactos/dll/win32/winemp3.acm         # Synced to WineStaging-1.7.47
 reactos/dll/win32/wing32              # Out of sync
-reactos/dll/win32/winhttp             # Synced to WineStaging-1.7.37
+reactos/dll/win32/winhttp             # Synced to WineStaging-1.7.47
 reactos/dll/win32/wininet             # Synced to WineStaging-1.7.37
 reactos/dll/win32/winmm               # Forked at Wine-20050628
 reactos/dll/win32/winmm/midimap       # Forked at Wine-20050628