[Wine-patches] [eter-2.1 8/9] winhttp: Implement WINHTTP_OPTION_CONNECTION_INFO. (eterbug #10937).
Dmitry Timoshkov
dmitry на baikal.ru
Пн Дек 14 10:33:49 MSK 2015
From: Hans Leidekker <hans на codeweavers.com>
---
dlls/winhttp/session.c | 94 ++++++++++++++++++++++++++++++++++++++++++++
dlls/winhttp/tests/winhttp.c | 62 +++++++++++++++++++++++++++++
include/winhttp.h | 16 ++++++++
3 files changed, 172 insertions(+)
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 */
--
2.6.4
Подробная информация о списке рассылки Wine-patches