Commit 02f2ab94 authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

winhttp: Implement WINHTTP_OPTION_CONNECTION_INFO.

parent 6f2f577f
...@@ -25,6 +25,11 @@ ...@@ -25,6 +25,11 @@
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
#ifndef __MINGW32__
#define USE_WS_PREFIX
#endif
#include "winsock2.h"
#include "ws2ipdef.h"
#include "winhttp.h" #include "winhttp.h"
#include "wincrypt.h" #include "wincrypt.h"
#include "winreg.h" #include "winreg.h"
...@@ -587,6 +592,71 @@ static WCHAR *blob_to_str( DWORD encoding, CERT_NAME_BLOB *blob ) ...@@ -587,6 +592,71 @@ static WCHAR *blob_to_str( DWORD encoding, CERT_NAME_BLOB *blob )
return ret; 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 ) static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD buflen )
{ {
request_t *request = (request_t *)hdr; request_t *request = (request_t *)hdr;
...@@ -683,6 +753,30 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf ...@@ -683,6 +753,30 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
*buflen = sizeof(DWORD); *buflen = sizeof(DWORD);
return TRUE; 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: case WINHTTP_OPTION_RESOLVE_TIMEOUT:
*(DWORD *)buffer = request->resolve_timeout; *(DWORD *)buffer = request->resolve_timeout;
*buflen = sizeof(DWORD); *buflen = sizeof(DWORD);
......
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <windef.h> #include <windef.h>
#include <winbase.h> #include <winbase.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <winhttp.h> #include <winhttp.h>
#include <wincrypt.h> #include <wincrypt.h>
#include <winreg.h> #include <winreg.h>
...@@ -2019,6 +2021,65 @@ static void test_bad_header( int port ) ...@@ -2019,6 +2021,65 @@ static void test_bad_header( int port )
WinHttpCloseHandle( ses ); 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 void test_credentials(void)
{ {
static WCHAR userW[] = {'u','s','e','r',0}; static WCHAR userW[] = {'u','s','e','r',0};
...@@ -2768,6 +2829,7 @@ START_TEST (winhttp) ...@@ -2768,6 +2829,7 @@ START_TEST (winhttp)
if (ret != WAIT_OBJECT_0) if (ret != WAIT_OBJECT_0)
return; return;
test_connection_info(si.port);
test_basic_request(si.port, NULL, basicW); test_basic_request(si.port, NULL, basicW);
test_no_headers(si.port); test_no_headers(si.port);
test_basic_authentication(si.port); test_basic_authentication(si.port);
......
...@@ -19,6 +19,12 @@ ...@@ -19,6 +19,12 @@
#ifndef __WINE_WINHTTP_H #ifndef __WINE_WINHTTP_H
#define __WINE_WINHTTP_H #define __WINE_WINHTTP_H
#ifdef _WIN64
#include <pshpack8.h>
#else
#include <pshpack4.h>
#endif
#define WINHTTPAPI #define WINHTTPAPI
#define BOOLAPI WINHTTPAPI BOOL WINAPI #define BOOLAPI WINHTTPAPI BOOL WINAPI
...@@ -527,6 +533,14 @@ typedef struct ...@@ -527,6 +533,14 @@ typedef struct
DWORD dwMinorVersion; DWORD dwMinorVersion;
} HTTP_VERSION_INFO, *LPHTTP_VERSION_INFO; } HTTP_VERSION_INFO, *LPHTTP_VERSION_INFO;
#ifdef _WS2DEF_
typedef struct
{
DWORD cbSize;
SOCKADDR_STORAGE LocalAddress;
SOCKADDR_STORAGE RemoteAddress;
} WINHTTP_CONNECTION_INFO;
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
...@@ -565,4 +579,6 @@ BOOL WINAPI WinHttpWriteData(HINTERNET,LPCVOID,DWORD,LPDWORD); ...@@ -565,4 +579,6 @@ BOOL WINAPI WinHttpWriteData(HINTERNET,LPCVOID,DWORD,LPDWORD);
} }
#endif #endif
#include <poppack.h>
#endif /* __WINE_WINHTTP_H */ #endif /* __WINE_WINHTTP_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment