diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index a56572d38c..f610ddef94 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -909,53 +909,68 @@ static BOOL secure_proxy_connect( request_t *request ) #define INET6_ADDRSTRLEN 46 #endif +static WCHAR *addr_to_str( const struct sockaddr *addr ) +{ + char buf[INET6_ADDRSTRLEN]; + const void *src; + + switch (addr->sa_family) + { + case AF_INET: + src = &((struct sockaddr_in *)addr)->sin_addr; + break; + case AF_INET6: + src = &((struct sockaddr_in6 *)addr)->sin6_addr; + break; + default: + WARN("unsupported address family %d\n", addr->sa_family); + return NULL; + } + if (!inet_ntop( addr->sa_family, src, buf, sizeof(buf) )) return NULL; + return strdupAW( buf ); +} + static BOOL open_connection( request_t *request ) { connect_t *connect; - const void *addr; - char address[INET6_ADDRSTRLEN]; - WCHAR *addressW; + WCHAR *addressW = NULL; INTERNET_PORT port; socklen_t slen; + struct sockaddr *saddr; + DWORD len; if (netconn_connected( &request->netconn )) return TRUE; 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); - send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, connect->servername, strlenW(connect->servername) + 1 ); - - slen = sizeof(connect->sockaddr); - if (!netconn_resolve( connect->servername, port, (struct sockaddr *)&connect->sockaddr, &slen, request->resolve_timeout )) return FALSE; - switch (connect->sockaddr.ss_family) + if (!connect->resolved) { - case AF_INET: - addr = &((struct sockaddr_in *)&connect->sockaddr)->sin_addr; - break; - case AF_INET6: - addr = &((struct sockaddr_in6 *)&connect->sockaddr)->sin6_addr; - break; - default: - WARN("unsupported address family %d\n", connect->sockaddr.ss_family); - return FALSE; + 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; + connect->resolved = TRUE; + + if (!(addressW = addr_to_str( saddr ))) return FALSE; + len = strlenW( addressW ) + 1; + send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, addressW, len ); } - inet_ntop( connect->sockaddr.ss_family, addr, address, sizeof(address) ); - addressW = strdupAW( address ); - - send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, addressW, strlenW(addressW) + 1 ); - - TRACE("connecting to %s:%u\n", address, port); + 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, connect->sockaddr.ss_family, SOCK_STREAM, 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, (struct sockaddr *)&connect->sockaddr, slen, request->connect_timeout )) + if (!netconn_connect( &request->netconn, saddr, slen, request->connect_timeout )) { netconn_close( &request->netconn ); heap_free( addressW ); diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c index 110de8089f..0f9e78279a 100644 --- a/dlls/winhttp/session.c +++ b/dlls/winhttp/session.c @@ -423,7 +423,7 @@ BOOL set_server_for_hostname( connect_t *connect, LPCWSTR server, INTERNET_PORT session->proxy_server, colon - session->proxy_server - 1 )) { heap_free( connect->servername ); - connect->sockaddr.ss_family = 0xffff; + connect->resolved = FALSE; if (!(connect->servername = heap_alloc( (colon - session->proxy_server + 1) * sizeof(WCHAR) ))) { @@ -445,7 +445,7 @@ BOOL set_server_for_hostname( connect_t *connect, LPCWSTR server, INTERNET_PORT session->proxy_server )) { heap_free( connect->servername ); - connect->sockaddr.ss_family = 0xffff; + connect->resolved = FALSE; if (!(connect->servername = strdupW( session->proxy_server ))) { ret = FALSE; @@ -458,7 +458,7 @@ BOOL set_server_for_hostname( connect_t *connect, LPCWSTR server, INTERNET_PORT else if (server) { heap_free( connect->servername ); - connect->sockaddr.ss_family = 0xffff; + connect->resolved = FALSE; if (!(connect->servername = strdupW( server ))) { ret = FALSE; diff --git a/dlls/winhttp/tests/notification.c b/dlls/winhttp/tests/notification.c index 7ceede75a3..84a35692b8 100644 --- a/dlls/winhttp/tests/notification.c +++ b/dlls/winhttp/tests/notification.c @@ -135,6 +135,16 @@ static const struct notification cache_test[] = { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, 0, 1 }, { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, 0, 1 }, { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, 0, 1 }, + { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED, 0 }, + { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, 0 }, + { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, 0 }, + { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST, 0 }, + { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT, 0 }, + { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE, 0 }, + { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED, 0 }, + { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, 0, 1 }, + { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, 0, 1 }, + { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, 0, 1 }, { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, 1, 1 }, { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, 1, 1 } }; @@ -188,6 +198,32 @@ static void test_connection_cache( void ) ok(ret, "failed unexpectedly %u\n", GetLastError()); ok(status == 200, "request failed unexpectedly %u\n", status); + setup_test( &info, winhttp_close_handle, __LINE__ ); + WinHttpCloseHandle( req ); + + setup_test( &info, winhttp_open_request, __LINE__ ); + req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 ); + ok(req != NULL, "failed to open a request %u\n", GetLastError()); + + ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) ); + ok(ret, "failed to set context value %u\n", GetLastError()); + + setup_test( &info, winhttp_send_request, __LINE__ ); + ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 ); + ok(ret, "failed to send request %u\n", GetLastError()); + + setup_test( &info, winhttp_receive_response, __LINE__ ); + ret = WinHttpReceiveResponse( req, NULL ); + ok(ret, "failed to receive response %u\n", GetLastError()); + + size = sizeof(status); + ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL ); + ok(ret, "failed unexpectedly %u\n", GetLastError()); + ok(status == 200, "request failed unexpectedly %u\n", status); + + setup_test( &info, winhttp_close_handle, __LINE__ ); + WinHttpCloseHandle( req ); + setup_test( &info, winhttp_close_handle, __LINE__ ); WinHttpCloseHandle( req ); WinHttpCloseHandle( con ); @@ -229,6 +265,29 @@ static void test_connection_cache( void ) ok(ret, "failed unexpectedly %u\n", GetLastError()); ok(status == 200, "request failed unexpectedly %u\n", status); + setup_test( &info, winhttp_close_handle, __LINE__ ); + WinHttpCloseHandle( req ); + + setup_test( &info, winhttp_open_request, __LINE__ ); + req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 ); + ok(req != NULL, "failed to open a request %u\n", GetLastError()); + + ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) ); + ok(ret, "failed to set context value %u\n", GetLastError()); + + setup_test( &info, winhttp_send_request, __LINE__ ); + ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 ); + ok(ret, "failed to send request %u\n", GetLastError()); + + setup_test( &info, winhttp_receive_response, __LINE__ ); + ret = WinHttpReceiveResponse( req, NULL ); + ok(ret, "failed to receive response %u\n", GetLastError()); + + size = sizeof(status); + ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL ); + ok(ret, "failed unexpectedly %u\n", GetLastError()); + ok(status == 200, "request failed unexpectedly %u\n", status); + setup_test( &info, winhttp_close_handle, __LINE__ ); WinHttpCloseHandle( req ); WinHttpCloseHandle( con ); diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h index fbd5032e17..7105553a21 100644 --- a/dlls/winhttp/winhttp_private.h +++ b/dlls/winhttp/winhttp_private.h @@ -119,6 +119,7 @@ typedef struct INTERNET_PORT hostport; INTERNET_PORT serverport; struct sockaddr_storage sockaddr; + BOOL resolved; } connect_t; typedef struct