winhttp: Implement WINHTTP_OPTION_CONNECTION_INFO.
This commit is contained in:
parent
6f2f577fa5
commit
02f2ab9437
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue