Module: wine Branch: master Commit: 02f2ab943777840176bc7ee552826e7933be7aa8 URL: http://source.winehq.org/git/wine.git/?a=commit;h=02f2ab943777840176bc7ee552...
Author: Hans Leidekker hans@codeweavers.com Date: Fri Mar 15 10:39:00 2013 +0100
winhttp: Implement WINHTTP_OPTION_CONNECTION_INFO.
---
dlls/winhttp/session.c | 94 ++++++++++++++++++++++++++++++++++++++++++ dlls/winhttp/tests/winhttp.c | 62 +++++++++++++++++++++++++++ include/winhttp.h | 16 +++++++ 3 files changed, 172 insertions(+), 0 deletions(-)
diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c index d43b225..394fddd 100644 --- a/dlls/winhttp/session.c +++ b/dlls/winhttp/session.c @@ -25,6 +25,11 @@
#include "windef.h" #include "winbase.h" +#ifndef __MINGW32__ +#define USE_WS_PREFIX +#endif +#include "winsock2.h" +#include "ws2ipdef.h" #include "winhttp.h" #include "wincrypt.h" #include "winreg.h" @@ -587,6 +592,71 @@ static WCHAR *blob_to_str( DWORD encoding, CERT_NAME_BLOB *blob ) return ret; }
+static BOOL convert_sockaddr( const struct sockaddr *addr, SOCKADDR_STORAGE *addr_storage ) +{ +#ifndef __MINGW32__ + switch (addr->sa_family) + { + case AF_INET: + { + const struct sockaddr_in *addr_unix = (const struct sockaddr_in *)addr; + struct WS_sockaddr_in *addr_win = (struct WS_sockaddr_in *)addr_storage; + char *p; + + addr_win->sin_family = WS_AF_INET; + addr_win->sin_port = addr_unix->sin_port; + memcpy( &addr_win->sin_addr, &addr_unix->sin_addr, 4 ); + p = (char *)&addr_win->sin_addr + 4; + memset( p, 0, sizeof(*addr_storage) - (p - (char *)addr_win) ); + return TRUE; + } + case AF_INET6: + { + const struct sockaddr_in6 *addr_unix = (const struct sockaddr_in6 *)addr; + struct WS_sockaddr_in6 *addr_win = (struct WS_sockaddr_in6 *)addr_storage; + + addr_win->sin6_family = WS_AF_INET6; + addr_win->sin6_port = addr_unix->sin6_port; + addr_win->sin6_flowinfo = addr_unix->sin6_flowinfo; + memcpy( &addr_win->sin6_addr, &addr_unix->sin6_addr, 16 ); +#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID + addr_win->sin6_scope_id = addr_unix->sin6_scope_id; +#else + addr_win->sin6_scope_id = 0; +#endif + memset( addr_win + 1, 0, sizeof(*addr_storage) - sizeof(*addr_win) ); + return TRUE; + } + default: + ERR("unhandled family %u\n", addr->sa_family); + return FALSE; + } +#else + switch (addr->sa_family) + { + case AF_INET: + { + struct sockaddr_in *addr_in = (struct sockaddr_in *)addr_storage; + + memcpy( addr_in, addr, sizeof(*addr_in) ); + memset( addr_in + 1, 0, sizeof(*addr_storage) - sizeof(*addr_in) ); + return TRUE; + } + case AF_INET6: + { + struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr_storage; + + memcpy( addr_in6, addr, sizeof(*addr_in6) ); + memset( addr_in6 + 1, 0, sizeof(*addr_storage) - sizeof(*addr_in6) ); + return TRUE; + } + default: + ERR("unhandled family %u\n", addr->sa_family); + return FALSE; + } +#endif +} + static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD buflen ) { request_t *request = (request_t *)hdr; @@ -683,6 +753,30 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf *buflen = sizeof(DWORD); return TRUE; } + case WINHTTP_OPTION_CONNECTION_INFO: + { + WINHTTP_CONNECTION_INFO *info = buffer; + struct sockaddr local; + socklen_t len = sizeof(local); + const struct sockaddr *remote = (const struct sockaddr *)&request->connect->sockaddr; + + if (!buffer || *buflen < sizeof(*info)) + { + *buflen = sizeof(*info); + set_last_error( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + if (!netconn_connected( &request->netconn )) + { + set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_STATE ); + return FALSE; + } + if (getsockname( request->netconn.socket, &local, &len )) return FALSE; + if (!convert_sockaddr( &local, &info->LocalAddress )) return FALSE; + if (!convert_sockaddr( remote, &info->RemoteAddress )) return FALSE; + info->cbSize = sizeof(*info); + return TRUE; + } case WINHTTP_OPTION_RESOLVE_TIMEOUT: *(DWORD *)buffer = request->resolve_timeout; *buflen = sizeof(DWORD); diff --git a/dlls/winhttp/tests/winhttp.c b/dlls/winhttp/tests/winhttp.c index fd0db18..b03e108 100644 --- a/dlls/winhttp/tests/winhttp.c +++ b/dlls/winhttp/tests/winhttp.c @@ -23,6 +23,8 @@ #include <stdlib.h> #include <windef.h> #include <winbase.h> +#include <winsock2.h> +#include <ws2tcpip.h> #include <winhttp.h> #include <wincrypt.h> #include <winreg.h> @@ -2019,6 +2021,65 @@ static void test_bad_header( int port ) WinHttpCloseHandle( ses ); }
+static void test_connection_info( int port ) +{ + static const WCHAR basicW[] = {'/','b','a','s','i','c',0}; + HINTERNET ses, con, req; + WINHTTP_CONNECTION_INFO info; + DWORD size, error; + BOOL ret; + + ses = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 ); + ok( ses != NULL, "failed to open session %u\n", GetLastError() ); + + con = WinHttpConnect( ses, localhostW, port, 0 ); + ok( con != NULL, "failed to open a connection %u\n", GetLastError() ); + + req = WinHttpOpenRequest( con, NULL, basicW, NULL, NULL, NULL, 0 ); + ok( req != NULL, "failed to open a request %u\n", GetLastError() ); + + size = sizeof(info); + SetLastError( 0xdeadbeef ); + ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size ); + error = GetLastError(); + if (!ret && error == ERROR_INVALID_PARAMETER) + { + win_skip( "WINHTTP_OPTION_CONNECTION_INFO not supported\n" ); + return; + } + ok( !ret, "unexpected success\n" ); + ok( error == ERROR_WINHTTP_INCORRECT_HANDLE_STATE, "got %u\n", error ); + + ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 ); + ok( ret, "failed to send request %u\n", GetLastError() ); + + size = 0; + SetLastError( 0xdeadbeef ); + ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size ); + error = GetLastError(); + ok( !ret, "unexpected success\n" ); + ok( error == ERROR_INSUFFICIENT_BUFFER, "got %u\n", error ); + + size = sizeof(info); + memset( &info, 0, sizeof(info) ); + ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size ); + ok( ret, "failed to retrieve connection info %u\n", GetLastError() ); + ok( info.cbSize == sizeof(info), "wrong size %u\n", info.cbSize ); + + ret = WinHttpReceiveResponse( req, NULL ); + ok( ret, "failed to receive response %u\n", GetLastError() ); + + size = sizeof(info); + memset( &info, 0, sizeof(info) ); + ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size ); + ok( ret, "failed to retrieve connection info %u\n", GetLastError() ); + ok( info.cbSize == sizeof(info), "wrong size %u\n", info.cbSize ); + + WinHttpCloseHandle( req ); + WinHttpCloseHandle( con ); + WinHttpCloseHandle( ses ); +} + static void test_credentials(void) { static WCHAR userW[] = {'u','s','e','r',0}; @@ -2768,6 +2829,7 @@ START_TEST (winhttp) if (ret != WAIT_OBJECT_0) return;
+ test_connection_info(si.port); test_basic_request(si.port, NULL, basicW); test_no_headers(si.port); test_basic_authentication(si.port); diff --git a/include/winhttp.h b/include/winhttp.h index cf0da83..9247abf 100644 --- a/include/winhttp.h +++ b/include/winhttp.h @@ -19,6 +19,12 @@ #ifndef __WINE_WINHTTP_H #define __WINE_WINHTTP_H
+#ifdef _WIN64 +#include <pshpack8.h> +#else +#include <pshpack4.h> +#endif + #define WINHTTPAPI #define BOOLAPI WINHTTPAPI BOOL WINAPI
@@ -527,6 +533,14 @@ typedef struct DWORD dwMinorVersion; } HTTP_VERSION_INFO, *LPHTTP_VERSION_INFO;
+#ifdef _WS2DEF_ +typedef struct +{ + DWORD cbSize; + SOCKADDR_STORAGE LocalAddress; + SOCKADDR_STORAGE RemoteAddress; +} WINHTTP_CONNECTION_INFO; +#endif
#ifdef __cplusplus extern "C" { @@ -565,4 +579,6 @@ BOOL WINAPI WinHttpWriteData(HINTERNET,LPCVOID,DWORD,LPDWORD); } #endif
+#include <poppack.h> + #endif /* __WINE_WINHTTP_H */