winhttp: Implement WINHTTP_OPTION_CONNECTION_INFO.

This commit is contained in:
Hans Leidekker 2013-03-15 10:39:00 +01:00 committed by Alexandre Julliard
parent 6f2f577fa5
commit 02f2ab9437
3 changed files with 172 additions and 0 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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 */