winhttp: Add support for secure connections.
This commit is contained in:
parent
02ca43cbbc
commit
0b19e8559f
@ -19,6 +19,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "wine/port.h"
|
#include "wine/port.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
#include "wine/library.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -37,6 +38,11 @@
|
|||||||
#ifdef HAVE_POLL_H
|
#ifdef HAVE_POLL_H
|
||||||
# include <poll.h>
|
# include <poll.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_OPENSSL_SSL_H
|
||||||
|
# include <openssl/ssl.h>
|
||||||
|
#undef FAR
|
||||||
|
#undef DSA
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
@ -67,6 +73,42 @@ static CRITICAL_SECTION cs_gethostbyname = { &critsect_debug, -1, 0, 0, 0, 0 };
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef SONAME_LIBSSL
|
||||||
|
|
||||||
|
#include <openssl/err.h>
|
||||||
|
|
||||||
|
static void *libssl_handle;
|
||||||
|
static void *libcrypto_handle;
|
||||||
|
|
||||||
|
static SSL_METHOD *method;
|
||||||
|
|
||||||
|
#define MAKE_FUNCPTR(f) static typeof(f) * p##f
|
||||||
|
|
||||||
|
MAKE_FUNCPTR( SSL_library_init );
|
||||||
|
MAKE_FUNCPTR( SSL_load_error_strings );
|
||||||
|
MAKE_FUNCPTR( SSLv23_method );
|
||||||
|
MAKE_FUNCPTR( SSL_CTX_new );
|
||||||
|
MAKE_FUNCPTR( SSL_CTX_free );
|
||||||
|
MAKE_FUNCPTR( SSL_new );
|
||||||
|
MAKE_FUNCPTR( SSL_free );
|
||||||
|
MAKE_FUNCPTR( SSL_set_fd );
|
||||||
|
MAKE_FUNCPTR( SSL_connect );
|
||||||
|
MAKE_FUNCPTR( SSL_shutdown );
|
||||||
|
MAKE_FUNCPTR( SSL_write );
|
||||||
|
MAKE_FUNCPTR( SSL_read );
|
||||||
|
MAKE_FUNCPTR( SSL_get_verify_result );
|
||||||
|
MAKE_FUNCPTR( SSL_get_peer_certificate );
|
||||||
|
MAKE_FUNCPTR( SSL_CTX_get_timeout );
|
||||||
|
MAKE_FUNCPTR( SSL_CTX_set_timeout );
|
||||||
|
MAKE_FUNCPTR( SSL_CTX_set_default_verify_paths );
|
||||||
|
|
||||||
|
MAKE_FUNCPTR( BIO_new_fp );
|
||||||
|
MAKE_FUNCPTR( ERR_get_error );
|
||||||
|
MAKE_FUNCPTR( ERR_error_string );
|
||||||
|
#undef MAKE_FUNCPTR
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* translate a unix error code into a winsock error code */
|
/* translate a unix error code into a winsock error code */
|
||||||
static int sock_get_error( int err )
|
static int sock_get_error( int err )
|
||||||
{
|
{
|
||||||
@ -132,9 +174,75 @@ static int sock_get_error( int err )
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL netconn_init( netconn_t *conn )
|
BOOL netconn_init( netconn_t *conn, BOOL secure )
|
||||||
{
|
{
|
||||||
conn->socket = -1;
|
conn->socket = -1;
|
||||||
|
if (!secure) return TRUE;
|
||||||
|
|
||||||
|
#if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
|
||||||
|
if (libssl_handle) return TRUE;
|
||||||
|
if (!(libssl_handle = wine_dlopen( SONAME_LIBSSL, RTLD_NOW, NULL, 0 )))
|
||||||
|
{
|
||||||
|
ERR("Trying to use SSL but couldn't load %s. Expect trouble.\n", SONAME_LIBSSL);
|
||||||
|
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (!(libcrypto_handle = wine_dlopen( SONAME_LIBCRYPTO, RTLD_NOW, NULL, 0 )))
|
||||||
|
{
|
||||||
|
ERR("Trying to use SSL but couldn't load %s. Expect trouble.\n", SONAME_LIBCRYPTO);
|
||||||
|
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
#define LOAD_FUNCPTR(x) \
|
||||||
|
if (!(p##x = wine_dlsym( libssl_handle, #x, NULL, 0 ))) \
|
||||||
|
{ \
|
||||||
|
ERR("Failed to load symbol %s\n", #x); \
|
||||||
|
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); \
|
||||||
|
return FALSE; \
|
||||||
|
}
|
||||||
|
LOAD_FUNCPTR( SSL_library_init );
|
||||||
|
LOAD_FUNCPTR( SSL_load_error_strings );
|
||||||
|
LOAD_FUNCPTR( SSLv23_method );
|
||||||
|
LOAD_FUNCPTR( SSL_CTX_new );
|
||||||
|
LOAD_FUNCPTR( SSL_CTX_free );
|
||||||
|
LOAD_FUNCPTR( SSL_new );
|
||||||
|
LOAD_FUNCPTR( SSL_free );
|
||||||
|
LOAD_FUNCPTR( SSL_set_fd );
|
||||||
|
LOAD_FUNCPTR( SSL_connect );
|
||||||
|
LOAD_FUNCPTR( SSL_shutdown );
|
||||||
|
LOAD_FUNCPTR( SSL_write );
|
||||||
|
LOAD_FUNCPTR( SSL_read );
|
||||||
|
LOAD_FUNCPTR( SSL_get_verify_result );
|
||||||
|
LOAD_FUNCPTR( SSL_get_peer_certificate );
|
||||||
|
LOAD_FUNCPTR( SSL_CTX_get_timeout );
|
||||||
|
LOAD_FUNCPTR( SSL_CTX_set_timeout );
|
||||||
|
LOAD_FUNCPTR( SSL_CTX_set_default_verify_paths );
|
||||||
|
#undef LOAD_FUNCPTR
|
||||||
|
|
||||||
|
#define LOAD_FUNCPTR(x) \
|
||||||
|
if (!(p##x = wine_dlsym( libcrypto_handle, #x, NULL, 0 ))) \
|
||||||
|
{ \
|
||||||
|
ERR("Failed to load symbol %s\n", #x); \
|
||||||
|
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); \
|
||||||
|
return FALSE; \
|
||||||
|
}
|
||||||
|
LOAD_FUNCPTR( BIO_new_fp );
|
||||||
|
LOAD_FUNCPTR( ERR_get_error );
|
||||||
|
LOAD_FUNCPTR( ERR_error_string );
|
||||||
|
#undef LOAD_FUNCPTR
|
||||||
|
|
||||||
|
pSSL_library_init();
|
||||||
|
pSSL_load_error_strings();
|
||||||
|
pBIO_new_fp( stderr, BIO_NOCLOSE );
|
||||||
|
|
||||||
|
method = pSSLv23_method();
|
||||||
|
conn->ssl_ctx = pSSL_CTX_new( method );
|
||||||
|
|
||||||
|
#else
|
||||||
|
WARN("SSL support not compiled in.\n");
|
||||||
|
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
|
||||||
|
return FALSE;
|
||||||
|
#endif
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,6 +266,23 @@ BOOL netconn_close( netconn_t *conn )
|
|||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
#ifdef SONAME_LIBSSL
|
||||||
|
if (conn->secure)
|
||||||
|
{
|
||||||
|
heap_free( conn->peek_msg_mem );
|
||||||
|
conn->peek_msg_mem = NULL;
|
||||||
|
conn->peek_msg = NULL;
|
||||||
|
conn->peek_len = 0;
|
||||||
|
|
||||||
|
pSSL_shutdown( conn->ssl_conn );
|
||||||
|
pSSL_free( conn->ssl_conn );
|
||||||
|
pSSL_CTX_free( conn->ssl_ctx );
|
||||||
|
|
||||||
|
conn->ssl_conn = NULL;
|
||||||
|
conn->ssl_ctx = NULL;
|
||||||
|
conn->secure = FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
res = close( conn->socket );
|
res = close( conn->socket );
|
||||||
conn->socket = -1;
|
conn->socket = -1;
|
||||||
if (res == -1)
|
if (res == -1)
|
||||||
@ -179,9 +304,76 @@ BOOL netconn_connect( netconn_t *conn, const struct sockaddr *sockaddr, unsigned
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL netconn_secure_connect( netconn_t *conn )
|
||||||
|
{
|
||||||
|
#ifdef SONAME_LIBSSL
|
||||||
|
X509 *cert;
|
||||||
|
long res;
|
||||||
|
|
||||||
|
if (!pSSL_CTX_set_default_verify_paths( conn->ssl_ctx ))
|
||||||
|
{
|
||||||
|
ERR("SSL_CTX_set_default_verify_paths failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
|
||||||
|
set_last_error( ERROR_OUTOFMEMORY );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (!(conn->ssl_conn = pSSL_new( conn->ssl_ctx )))
|
||||||
|
{
|
||||||
|
ERR("SSL_new failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
|
||||||
|
set_last_error( ERROR_OUTOFMEMORY );
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (!pSSL_set_fd( conn->ssl_conn, conn->socket ))
|
||||||
|
{
|
||||||
|
ERR("SSL_set_fd failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
|
||||||
|
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (pSSL_connect( conn->ssl_conn ) <= 0)
|
||||||
|
{
|
||||||
|
ERR("SSL_connect failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
|
||||||
|
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (!(cert = pSSL_get_peer_certificate( conn->ssl_conn )))
|
||||||
|
{
|
||||||
|
ERR("No certificate for server: %s\n", pERR_error_string( pERR_get_error(), 0 ));
|
||||||
|
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if ((res = pSSL_get_verify_result( conn->ssl_conn )) != X509_V_OK)
|
||||||
|
{
|
||||||
|
/* FIXME: we should set an error and return, but we only print an error at the moment */
|
||||||
|
ERR("couldn't verify server certificate (%ld)\n", res);
|
||||||
|
}
|
||||||
|
TRACE("established SSL connection\n");
|
||||||
|
conn->secure = TRUE;
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (conn->ssl_conn)
|
||||||
|
{
|
||||||
|
pSSL_shutdown( conn->ssl_conn );
|
||||||
|
pSSL_free( conn->ssl_conn );
|
||||||
|
conn->ssl_conn = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL netconn_send( netconn_t *conn, const void *msg, size_t len, int flags, int *sent )
|
BOOL netconn_send( netconn_t *conn, const void *msg, size_t len, int flags, int *sent )
|
||||||
{
|
{
|
||||||
if (!netconn_connected( conn )) return FALSE;
|
if (!netconn_connected( conn )) return FALSE;
|
||||||
|
if (conn->secure)
|
||||||
|
{
|
||||||
|
#ifdef SONAME_LIBSSL
|
||||||
|
if (flags) FIXME("SSL_write doesn't support any flags (%08x)\n", flags);
|
||||||
|
*sent = pSSL_write( conn->ssl_conn, msg, len );
|
||||||
|
if (*sent < 1 && len) return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
#else
|
||||||
|
return FALSE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
if ((*sent = send( conn->socket, msg, len, flags )) == -1)
|
if ((*sent = send( conn->socket, msg, len, flags )) == -1)
|
||||||
{
|
{
|
||||||
set_last_error( sock_get_error( errno ) );
|
set_last_error( sock_get_error( errno ) );
|
||||||
@ -195,6 +387,59 @@ BOOL netconn_recv( netconn_t *conn, void *buf, size_t len, int flags, int *recvd
|
|||||||
*recvd = 0;
|
*recvd = 0;
|
||||||
if (!netconn_connected( conn )) return FALSE;
|
if (!netconn_connected( conn )) return FALSE;
|
||||||
if (!len) return TRUE;
|
if (!len) return TRUE;
|
||||||
|
|
||||||
|
if (conn->secure)
|
||||||
|
{
|
||||||
|
#ifdef SONAME_LIBSSL
|
||||||
|
if (flags & ~(MSG_PEEK | MSG_WAITALL))
|
||||||
|
FIXME("SSL_read does not support the following flags: %08x\n", flags);
|
||||||
|
|
||||||
|
/* this ugly hack is all for MSG_PEEK */
|
||||||
|
if (flags & MSG_PEEK && !conn->peek_msg)
|
||||||
|
{
|
||||||
|
if (!(conn->peek_msg = conn->peek_msg_mem = heap_alloc( len + 1 ))) return FALSE;
|
||||||
|
}
|
||||||
|
else if (flags & MSG_PEEK && conn->peek_msg)
|
||||||
|
{
|
||||||
|
if (len < conn->peek_len) FIXME("buffer isn't big enough, should we wrap?\n");
|
||||||
|
*recvd = min( len, conn->peek_len );
|
||||||
|
memcpy( buf, conn->peek_msg, *recvd );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else if (conn->peek_msg)
|
||||||
|
{
|
||||||
|
*recvd = min( len, conn->peek_len );
|
||||||
|
memcpy( buf, conn->peek_msg, *recvd );
|
||||||
|
conn->peek_len -= *recvd;
|
||||||
|
conn->peek_msg += *recvd;
|
||||||
|
|
||||||
|
if (conn->peek_len == 0)
|
||||||
|
{
|
||||||
|
heap_free( conn->peek_msg_mem );
|
||||||
|
conn->peek_msg_mem = NULL;
|
||||||
|
conn->peek_msg = NULL;
|
||||||
|
}
|
||||||
|
/* check if we have enough data from the peek buffer */
|
||||||
|
if (!(flags & MSG_WAITALL) || (*recvd == len)) return TRUE;
|
||||||
|
}
|
||||||
|
*recvd += pSSL_read( conn->ssl_conn, (char *)buf + *recvd, len - *recvd );
|
||||||
|
if (flags & MSG_PEEK) /* must copy into buffer */
|
||||||
|
{
|
||||||
|
conn->peek_len = *recvd;
|
||||||
|
if (!*recvd)
|
||||||
|
{
|
||||||
|
heap_free( conn->peek_msg_mem );
|
||||||
|
conn->peek_msg_mem = NULL;
|
||||||
|
conn->peek_msg = NULL;
|
||||||
|
}
|
||||||
|
else memcpy( conn->peek_msg, buf, *recvd );
|
||||||
|
}
|
||||||
|
if (*recvd < 1 && len) return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
#else
|
||||||
|
return FALSE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
if ((*recvd = recv( conn->socket, buf, len, flags )) == -1)
|
if ((*recvd = recv( conn->socket, buf, len, flags )) == -1)
|
||||||
{
|
{
|
||||||
set_last_error( sock_get_error( errno ) );
|
set_last_error( sock_get_error( errno ) );
|
||||||
@ -210,6 +455,14 @@ BOOL netconn_query_data_available( netconn_t *conn, DWORD *available )
|
|||||||
#endif
|
#endif
|
||||||
*available = 0;
|
*available = 0;
|
||||||
if (!netconn_connected( conn )) return FALSE;
|
if (!netconn_connected( conn )) return FALSE;
|
||||||
|
|
||||||
|
if (conn->secure)
|
||||||
|
{
|
||||||
|
#ifdef SONAME_LIBSSL
|
||||||
|
if (conn->peek_msg) *available = conn->peek_len;
|
||||||
|
#endif
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
#ifdef FIONREAD
|
#ifdef FIONREAD
|
||||||
if (!(ret = ioctl( conn->socket, FIONREAD, &unread )))
|
if (!(ret = ioctl( conn->socket, FIONREAD, &unread )))
|
||||||
{
|
{
|
||||||
@ -228,6 +481,42 @@ BOOL netconn_get_next_line( netconn_t *conn, char *buffer, DWORD *buflen )
|
|||||||
|
|
||||||
if (!netconn_connected( conn )) return FALSE;
|
if (!netconn_connected( conn )) return FALSE;
|
||||||
|
|
||||||
|
if (conn->secure)
|
||||||
|
{
|
||||||
|
#ifdef SONAME_LIBSSL
|
||||||
|
long timeout;
|
||||||
|
|
||||||
|
timeout = pSSL_CTX_get_timeout( conn->ssl_ctx );
|
||||||
|
pSSL_CTX_set_timeout( conn->ssl_ctx, DEFAULT_RECEIVE_TIMEOUT );
|
||||||
|
|
||||||
|
while (recvd < *buflen)
|
||||||
|
{
|
||||||
|
int dummy;
|
||||||
|
if (!netconn_recv( conn, &buffer[recvd], 1, 0, &dummy ))
|
||||||
|
{
|
||||||
|
set_last_error( ERROR_CONNECTION_ABORTED );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (buffer[recvd] == '\n')
|
||||||
|
{
|
||||||
|
ret = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (buffer[recvd] != '\r') recvd++;
|
||||||
|
}
|
||||||
|
pSSL_CTX_set_timeout( conn->ssl_ctx, timeout );
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
buffer[recvd++] = 0;
|
||||||
|
*buflen = recvd;
|
||||||
|
TRACE("received line %s\n", debugstr_a(buffer));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
|
return FALSE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
pfd.fd = conn->socket;
|
pfd.fd = conn->socket;
|
||||||
pfd.events = POLLIN;
|
pfd.events = POLLIN;
|
||||||
while (recvd < *buflen)
|
while (recvd < *buflen)
|
||||||
@ -257,9 +546,8 @@ BOOL netconn_get_next_line( netconn_t *conn, char *buffer, DWORD *buflen )
|
|||||||
buffer[recvd++] = 0;
|
buffer[recvd++] = 0;
|
||||||
*buflen = recvd;
|
*buflen = recvd;
|
||||||
TRACE("received line %s\n", debugstr_a(buffer));
|
TRACE("received line %s\n", debugstr_a(buffer));
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
return FALSE;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD netconn_set_timeout( netconn_t *netconn, BOOL send, int value )
|
DWORD netconn_set_timeout( netconn_t *netconn, BOOL send, int value )
|
||||||
|
@ -683,6 +683,12 @@ static BOOL open_connection( request_t *request )
|
|||||||
heap_free( addressW );
|
heap_free( addressW );
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
if (request->hdr.flags & WINHTTP_FLAG_SECURE && !netconn_secure_connect( &request->netconn ))
|
||||||
|
{
|
||||||
|
netconn_close( &request->netconn );
|
||||||
|
heap_free( addressW );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, addressW, 0 );
|
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, addressW, 0 );
|
||||||
|
|
||||||
|
@ -270,7 +270,7 @@ HINTERNET WINAPI WinHttpOpenRequest( HINTERNET hconnect, LPCWSTR verb, LPCWSTR o
|
|||||||
request->connect = connect;
|
request->connect = connect;
|
||||||
list_add_head( &connect->hdr.children, &request->hdr.entry );
|
list_add_head( &connect->hdr.children, &request->hdr.entry );
|
||||||
|
|
||||||
if (!netconn_init( &request->netconn )) goto end;
|
if (!netconn_init( &request->netconn, request->hdr.flags & WINHTTP_FLAG_SECURE )) goto end;
|
||||||
|
|
||||||
if (!verb) verb = get;
|
if (!verb) verb = get;
|
||||||
if (!object) object = slash;
|
if (!object) object = slash;
|
||||||
|
@ -87,6 +87,9 @@ typedef struct
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int socket;
|
int socket;
|
||||||
|
BOOL secure; /* SSL active on connection? */
|
||||||
|
void *ssl_ctx;
|
||||||
|
void *ssl_conn;
|
||||||
char *peek_msg;
|
char *peek_msg;
|
||||||
char *peek_msg_mem;
|
char *peek_msg_mem;
|
||||||
size_t peek_len;
|
size_t peek_len;
|
||||||
@ -130,10 +133,11 @@ BOOL netconn_connect( netconn_t *, const struct sockaddr *, unsigned int );
|
|||||||
BOOL netconn_connected( netconn_t * );
|
BOOL netconn_connected( netconn_t * );
|
||||||
BOOL netconn_create( netconn_t *, int, int, int );
|
BOOL netconn_create( netconn_t *, int, int, int );
|
||||||
BOOL netconn_get_next_line( netconn_t *, char *, DWORD * );
|
BOOL netconn_get_next_line( netconn_t *, char *, DWORD * );
|
||||||
BOOL netconn_init( netconn_t * );
|
BOOL netconn_init( netconn_t *, BOOL );
|
||||||
BOOL netconn_query_data_available( netconn_t *, DWORD * );
|
BOOL netconn_query_data_available( netconn_t *, DWORD * );
|
||||||
BOOL netconn_recv( netconn_t *, void *, size_t, int, int * );
|
BOOL netconn_recv( netconn_t *, void *, size_t, int, int * );
|
||||||
BOOL netconn_resolve( WCHAR *, INTERNET_PORT, struct sockaddr_in * );
|
BOOL netconn_resolve( WCHAR *, INTERNET_PORT, struct sockaddr_in * );
|
||||||
|
BOOL netconn_secure_connect( netconn_t * );
|
||||||
BOOL netconn_send( netconn_t *, const void *, size_t, int, int * );
|
BOOL netconn_send( netconn_t *, const void *, size_t, int, int * );
|
||||||
|
|
||||||
static inline void *heap_alloc( SIZE_T size )
|
static inline void *heap_alloc( SIZE_T size )
|
||||||
|
Loading…
x
Reference in New Issue
Block a user