diff --git a/reactos/dll/win32/winhttp/cookie.c b/reactos/dll/win32/winhttp/cookie.c index 7ada9546110..6b0088a3a46 100644 --- a/reactos/dll/win32/winhttp/cookie.c +++ b/reactos/dll/win32/winhttp/cookie.c @@ -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 ); } } diff --git a/reactos/dll/win32/winhttp/net.c b/reactos/dll/win32/winhttp/net.c index f825463e4dd..bdb778716c9 100644 --- a/reactos/dll/win32/winhttp/net.c +++ b/reactos/dll/win32/winhttp/net.c @@ -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 ); diff --git a/reactos/dll/win32/winhttp/request.c b/reactos/dll/win32/winhttp/request.c index 6cf9d78aff5..a2fa48afcaa 100644 --- a/reactos/dll/win32/winhttp/request.c +++ b/reactos/dll/win32/winhttp/request.c @@ -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) + else if (value) { - delete_header( request, index ); - if (value) + + if ((flags & (WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA | WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON)) && + index >= 0) { - header_t hdr; + WCHAR *tmp; + int len, len_orig, len_value; + header_t *header = &request->headers[index]; - hdr.field = (LPWSTR)field; - hdr.value = (LPWSTR)value; - hdr.is_request = request_only; + len_orig = strlenW( header->value ); + len_value = strlenW( value ); - return insert_header( request, &hdr ); - } - return TRUE; - } - else if (flags & (WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA | WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON)) - { - 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) sep = ','; - else sep = ';'; - - 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 ))) - { - err = get_last_error(); - goto error; - } - if (!(hconnect = WinHttpConnect( hsession, hostname, uc.nPort, 0 ))) + if (SUCCEEDED( VariantChangeType( &async, &async, 0, VT_BOOL )) && V_BOOL( &async )) request->async = TRUE; + else request->async = FALSE; + + if (!request->hsession) + { + 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; + } + } + 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; diff --git a/reactos/dll/win32/winhttp/session.c b/reactos/dll/win32/winhttp/session.c index 8c5689f0fc8..02c7ae7cb55 100644 --- a/reactos/dll/win32/winhttp/session.c +++ b/reactos/dll/win32/winhttp/session.c @@ -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 } diff --git a/reactos/dll/win32/winhttp/winhttp_private.h b/reactos/dll/win32/winhttp/winhttp_private.h index c342065be2a..052c0a5f8a8 100644 --- a/reactos/dll/win32/winhttp/winhttp_private.h +++ b/reactos/dll/win32/winhttp/winhttp_private.h @@ -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; diff --git a/reactos/dll/win32/winhttp/winhttp_ros.diff b/reactos/dll/win32/winhttp/winhttp_ros.diff index 3802ba79083..60f010e03b9 100644 --- a/reactos/dll/win32/winhttp/winhttp_ros.diff +++ b/reactos/dll/win32/winhttp/winhttp_ros.diff @@ -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 ) { diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 347577b0dc7..1af4a271b36 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -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