https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5bd6580fc63bb886686b6…
commit 5bd6580fc63bb886686b62caf26f3ea99a173922
Author: Amine Khaldi <amine.khaldi(a)reactos.org>
AuthorDate: Sat Dec 7 13:05:48 2019 +0100
Commit: Amine Khaldi <amine.khaldi(a)reactos.org>
CommitDate: Sat Dec 7 13:05:48 2019 +0100
[WINHTTP] Sync with Wine Staging 4.18. CORE-16441
---
dll/win32/winhttp/cookie.c | 121 ++--
dll/win32/winhttp/handle.c | 25 +-
dll/win32/winhttp/main.c | 1 +
dll/win32/winhttp/net.c | 480 +++++--------
dll/win32/winhttp/request.c | 1261 +++++++++++++++++++++--------------
dll/win32/winhttp/session.c | 604 +++++++++--------
dll/win32/winhttp/url.c | 313 +++++----
dll/win32/winhttp/winhttp_private.h | 243 +++----
media/doc/README.WINE | 2 +-
9 files changed, 1617 insertions(+), 1433 deletions(-)
diff --git a/dll/win32/winhttp/cookie.c b/dll/win32/winhttp/cookie.c
index b4b25304f7f..40c11c6f71c 100644
--- a/dll/win32/winhttp/cookie.c
+++ b/dll/win32/winhttp/cookie.c
@@ -17,24 +17,39 @@
*/
#include "config.h"
+#include "ws2tcpip.h"
#include <stdarg.h>
-#include "wine/debug.h"
-#include "wine/list.h"
-
#include "windef.h"
#include "winbase.h"
#include "winhttp.h"
+#include "wine/debug.h"
+#include "wine/list.h"
#include "winhttp_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
-static domain_t *add_domain( session_t *session, WCHAR *name )
+struct cookie
+{
+ struct list entry;
+ WCHAR *name;
+ WCHAR *value;
+ WCHAR *path;
+};
+
+struct domain
+{
+ struct list entry;
+ WCHAR *name;
+ struct list cookies;
+};
+
+static struct domain *add_domain( struct session *session, WCHAR *name )
{
- domain_t *domain;
+ struct domain *domain;
- if (!(domain = heap_alloc_zero( sizeof(domain_t) ))) return NULL;
+ if (!(domain = heap_alloc_zero( sizeof(struct domain) ))) return NULL;
list_init( &domain->entry );
list_init( &domain->cookies );
@@ -46,14 +61,14 @@ static domain_t *add_domain( session_t *session, WCHAR *name )
return domain;
}
-static cookie_t *find_cookie( domain_t *domain, const WCHAR *path, const WCHAR *name )
+static struct cookie *find_cookie( struct domain *domain, const WCHAR *path, const WCHAR
*name )
{
struct list *item;
- cookie_t *cookie;
+ struct cookie *cookie;
LIST_FOR_EACH( item, &domain->cookies )
{
- cookie = LIST_ENTRY( item, cookie_t, entry );
+ cookie = LIST_ENTRY( item, struct cookie, entry );
if (!strcmpW( cookie->path, path ) && !strcmpW( cookie->name, name
))
{
TRACE("found %s=%s\n", debugstr_w(cookie->name),
debugstr_w(cookie->value));
@@ -63,7 +78,7 @@ static cookie_t *find_cookie( domain_t *domain, const WCHAR *path, const
WCHAR *
return NULL;
}
-static BOOL domain_match( const WCHAR *name, domain_t *domain, BOOL partial )
+static BOOL domain_match( const WCHAR *name, struct domain *domain, BOOL partial )
{
TRACE("comparing %s with %s\n", debugstr_w(name),
debugstr_w(domain->name));
@@ -72,7 +87,7 @@ static BOOL domain_match( const WCHAR *name, domain_t *domain, BOOL
partial )
return TRUE;
}
-static void free_cookie( cookie_t *cookie )
+static void free_cookie( struct cookie *cookie )
{
heap_free( cookie->name );
heap_free( cookie->value );
@@ -80,20 +95,20 @@ static void free_cookie( cookie_t *cookie )
heap_free( cookie );
}
-static void delete_cookie( cookie_t *cookie )
+static void delete_cookie( struct cookie *cookie )
{
list_remove( &cookie->entry );
free_cookie( cookie );
}
-void delete_domain( domain_t *domain )
+static void delete_domain( struct domain *domain )
{
- cookie_t *cookie;
+ struct cookie *cookie;
struct list *item, *next;
LIST_FOR_EACH_SAFE( item, next, &domain->cookies )
{
- cookie = LIST_ENTRY( item, cookie_t, entry );
+ cookie = LIST_ENTRY( item, struct cookie, entry );
delete_cookie( cookie );
}
@@ -102,35 +117,51 @@ void delete_domain( domain_t *domain )
heap_free( domain );
}
-static BOOL add_cookie( session_t *session, cookie_t *cookie, WCHAR *domain_name, WCHAR
*path )
+void destroy_cookies( struct session *session )
+{
+ struct list *item, *next;
+ struct domain *domain;
+
+ LIST_FOR_EACH_SAFE( item, next, &session->cookie_cache )
+ {
+ domain = LIST_ENTRY( item, struct domain, entry );
+ delete_domain( domain );
+ }
+}
+
+static BOOL add_cookie( struct session *session, struct cookie *cookie, WCHAR
*domain_name, WCHAR *path )
{
- domain_t *domain = NULL;
- cookie_t *old_cookie;
+ struct domain *domain = NULL;
+ struct cookie *old_cookie;
struct list *item;
+ if (!(cookie->path = strdupW( path ))) return FALSE;
+
+ EnterCriticalSection( &session->cs );
+
LIST_FOR_EACH( item, &session->cookie_cache )
{
- domain = LIST_ENTRY( item, domain_t, entry );
+ domain = LIST_ENTRY( item, struct domain, entry );
if (domain_match( domain_name, domain, FALSE )) break;
domain = NULL;
}
- if (!domain)
- {
- if (!(domain = add_domain( session, domain_name ))) return FALSE;
- }
+ if (!domain) domain = add_domain( session, domain_name );
else if ((old_cookie = find_cookie( domain, path, cookie->name ))) delete_cookie(
old_cookie );
- cookie->path = strdupW( path );
- list_add_head( &domain->cookies, &cookie->entry );
+ if (domain)
+ {
+ list_add_head( &domain->cookies, &cookie->entry );
+ TRACE("domain %s path %s <- %s=%s\n", debugstr_w(domain_name),
debugstr_w(cookie->path),
+ debugstr_w(cookie->name), debugstr_w(cookie->value));
+ }
- TRACE("domain %s path %s <- %s=%s\n", debugstr_w(domain_name),
debugstr_w(cookie->path),
- debugstr_w(cookie->name), debugstr_w(cookie->value));
- return TRUE;
+ LeaveCriticalSection( &session->cs );
+ return domain != NULL;
}
-static cookie_t *parse_cookie( const WCHAR *string )
+static struct cookie *parse_cookie( const WCHAR *string )
{
- cookie_t *cookie;
+ struct cookie *cookie;
const WCHAR *p;
int len;
@@ -139,7 +170,7 @@ static cookie_t *parse_cookie( const WCHAR *string )
while (len && string[len - 1] == ' ') len--;
if (!len) return NULL;
- if (!(cookie = heap_alloc_zero( sizeof(cookie_t) ))) return NULL;
+ if (!(cookie = heap_alloc_zero( sizeof(struct cookie) ))) return NULL;
list_init( &cookie->entry );
if (!(cookie->name = heap_alloc( (len + 1) * sizeof(WCHAR) )))
@@ -229,7 +260,7 @@ static struct attr *parse_attr( const WCHAR *str, int *used )
return attr;
}
-BOOL set_cookies( request_t *request, const WCHAR *cookies )
+BOOL set_cookies( struct request *request, const WCHAR *cookies )
{
static const WCHAR pathW[] = {'p','a','t','h',0};
static const WCHAR domainW[] =
{'d','o','m','a','i','n',0};
@@ -237,8 +268,8 @@ BOOL set_cookies( request_t *request, const WCHAR *cookies )
WCHAR *buffer, *p;
WCHAR *cookie_domain = NULL, *cookie_path = NULL;
struct attr *attr, *domain = NULL, *path = NULL;
- session_t *session = request->connect->session;
- cookie_t *cookie;
+ struct session *session = request->connect->session;
+ struct cookie *cookie;
int len, used;
len = strlenW( cookies );
@@ -290,14 +321,16 @@ end:
return ret;
}
-BOOL add_cookie_headers( request_t *request )
+BOOL add_cookie_headers( struct request *request )
{
struct list *domain_cursor;
- session_t *session = request->connect->session;
+ struct session *session = request->connect->session;
+
+ EnterCriticalSection( &session->cs );
LIST_FOR_EACH( domain_cursor, &session->cookie_cache )
{
- domain_t *domain = LIST_ENTRY( domain_cursor, domain_t, entry );
+ struct domain *domain = LIST_ENTRY( domain_cursor, struct domain, entry );
if (domain_match( request->connect->servername, domain, TRUE ))
{
struct list *cookie_cursor;
@@ -305,19 +338,23 @@ BOOL add_cookie_headers( request_t *request )
LIST_FOR_EACH( cookie_cursor, &domain->cookies )
{
- cookie_t *cookie = LIST_ENTRY( cookie_cursor, cookie_t, entry );
+ struct cookie *cookie = LIST_ENTRY( cookie_cursor, struct cookie, entry
);
TRACE("comparing path %s with %s\n",
debugstr_w(request->path), debugstr_w(cookie->path));
if (strstrW( request->path, cookie->path ) == request->path)
{
- const WCHAR cookieW[] =
{'C','o','o','k','i','e',':','
'};
- int len, len_cookie = sizeof(cookieW) / sizeof(cookieW[0]), len_name
= strlenW( cookie->name );
+ static const WCHAR cookieW[] =
{'C','o','o','k','i','e',':','
'};
+ int len, len_cookie = ARRAY_SIZE( cookieW ), len_name = strlenW(
cookie->name );
WCHAR *header;
len = len_cookie + len_name;
if (cookie->value) len += strlenW( cookie->value ) + 1;
- if (!(header = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return
FALSE;
+ if (!(header = heap_alloc( (len + 1) * sizeof(WCHAR) )))
+ {
+ LeaveCriticalSection( &session->cs );
+ return FALSE;
+ }
memcpy( header, cookieW, len_cookie * sizeof(WCHAR) );
strcpyW( header + len_cookie, cookie->name );
@@ -335,5 +372,7 @@ BOOL add_cookie_headers( request_t *request )
}
}
}
+
+ LeaveCriticalSection( &session->cs );
return TRUE;
}
diff --git a/dll/win32/winhttp/handle.c b/dll/win32/winhttp/handle.c
index 6026a496103..6711cd91727 100644
--- a/dll/win32/winhttp/handle.c
+++ b/dll/win32/winhttp/handle.c
@@ -19,15 +19,14 @@
*/
#include "config.h"
-#include "wine/port.h"
-#include "wine/debug.h"
-
+#include "ws2tcpip.h"
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winhttp.h"
+#include "wine/debug.h"
#include "winhttp_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
@@ -43,20 +42,20 @@ static CRITICAL_SECTION_DEBUG handle_cs_debug =
};
static CRITICAL_SECTION handle_cs = { &handle_cs_debug, -1, 0, 0, 0, 0 };
-static object_header_t **handles;
+static struct object_header **handles;
static ULONG_PTR next_handle;
static ULONG_PTR max_handles;
-object_header_t *addref_object( object_header_t *hdr )
+struct object_header *addref_object( struct object_header *hdr )
{
ULONG refs = InterlockedIncrement( &hdr->refs );
TRACE("%p -> refcount = %d\n", hdr, refs);
return hdr;
}
-object_header_t *grab_object( HINTERNET hinternet )
+struct object_header *grab_object( HINTERNET hinternet )
{
- object_header_t *hdr = NULL;
+ struct object_header *hdr = NULL;
ULONG_PTR handle = (ULONG_PTR)hinternet;
EnterCriticalSection( &handle_cs );
@@ -70,13 +69,13 @@ object_header_t *grab_object( HINTERNET hinternet )
return hdr;
}
-void release_object( object_header_t *hdr )
+void release_object( struct object_header *hdr )
{
ULONG refs = InterlockedDecrement( &hdr->refs );
TRACE("object %p refcount = %d\n", hdr, refs);
if (!refs)
{
- if (hdr->type == WINHTTP_HANDLE_TYPE_REQUEST) close_connection( (request_t
*)hdr );
+ if (hdr->type == WINHTTP_HANDLE_TYPE_REQUEST) close_connection( (struct
request *)hdr );
send_callback( hdr, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, &hdr->handle,
sizeof(HINTERNET) );
@@ -86,9 +85,9 @@ void release_object( object_header_t *hdr )
}
}
-HINTERNET alloc_handle( object_header_t *hdr )
+HINTERNET alloc_handle( struct object_header *hdr )
{
- object_header_t **p;
+ struct object_header **p;
ULONG_PTR handle, num;
list_init( &hdr->children );
@@ -125,7 +124,7 @@ BOOL free_handle( HINTERNET hinternet )
{
BOOL ret = FALSE;
ULONG_PTR handle = (ULONG_PTR)hinternet;
- object_header_t *hdr = NULL, *child, *next;
+ struct object_header *hdr = NULL, *child, *next;
EnterCriticalSection( &handle_cs );
@@ -145,7 +144,7 @@ BOOL free_handle( HINTERNET hinternet )
if (hdr)
{
- LIST_FOR_EACH_ENTRY_SAFE( child, next, &hdr->children, object_header_t,
entry )
+ LIST_FOR_EACH_ENTRY_SAFE( child, next, &hdr->children, struct
object_header, entry )
{
TRACE("freeing child handle %p for parent handle 0x%lx\n",
child->handle, handle + 1);
free_handle( child->handle );
diff --git a/dll/win32/winhttp/main.c b/dll/win32/winhttp/main.c
index a63f28cf108..e6c084b979b 100644
--- a/dll/win32/winhttp/main.c
+++ b/dll/win32/winhttp/main.c
@@ -18,6 +18,7 @@
#define COBJMACROS
#include "config.h"
+#include "ws2tcpip.h"
#include <stdarg.h>
#include "windef.h"
diff --git a/dll/win32/winhttp/net.c b/dll/win32/winhttp/net.c
index e9ff86a165a..277a22eacb0 100644
--- a/dll/win32/winhttp/net.c
+++ b/dll/win32/winhttp/net.c
@@ -18,145 +18,31 @@
*/
#include "config.h"
-#include "wine/port.h"
-
+#define NONAMELESSUNION
+#include "ws2tcpip.h"
#include <stdarg.h>
#include <stdio.h>
-#include <errno.h>
#include <assert.h>
-#include <sys/types.h>
-#ifdef HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif
-#ifdef HAVE_SYS_FILIO_H
-# include <sys/filio.h>
-#endif
-#ifdef HAVE_POLL_H
-# include <poll.h>
-#endif
-
-#define NONAMELESSUNION
-
-#include "wine/debug.h"
-#include "wine/library.h"
-
#include "windef.h"
#include "winbase.h"
#include "winhttp.h"
-#include "wincrypt.h"
#include "schannel.h"
+#include "wine/debug.h"
+#include "wine/library.h"
#include "winhttp_private.h"
-/* to avoid conflicts with the Unix socket headers */
-#define USE_WS_PREFIX
-#include "winsock2.h"
-
WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
-#ifndef HAVE_GETADDRINFO
-
-/* critical section to protect non-reentrant gethostbyname() */
-static CRITICAL_SECTION cs_gethostbyname;
-static CRITICAL_SECTION_DEBUG critsect_debug =
-{
- 0, 0, &cs_gethostbyname,
- { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
- 0, 0, { (DWORD_PTR)(__FILE__ ": cs_gethostbyname") }
-};
-static CRITICAL_SECTION cs_gethostbyname = { &critsect_debug, -1, 0, 0, 0, 0 };
-
-#endif
-
-/* translate a unix error code into a winsock error code */
-#ifndef __REACTOS__
-static int sock_get_error( int err )
-{
-#if !defined(__MINGW32__) && !defined (_MSC_VER)
- switch (err)
- {
- case EINTR: return WSAEINTR;
- case EBADF: return WSAEBADF;
- case EPERM:
- case EACCES: return WSAEACCES;
- case EFAULT: return WSAEFAULT;
- case EINVAL: return WSAEINVAL;
- case EMFILE: return WSAEMFILE;
- case EWOULDBLOCK: return WSAEWOULDBLOCK;
- case EINPROGRESS: return WSAEINPROGRESS;
- case EALREADY: return WSAEALREADY;
- case ENOTSOCK: return WSAENOTSOCK;
- case EDESTADDRREQ: return WSAEDESTADDRREQ;
- case EMSGSIZE: return WSAEMSGSIZE;
- case EPROTOTYPE: return WSAEPROTOTYPE;
- case ENOPROTOOPT: return WSAENOPROTOOPT;
- case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
- case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
- case EOPNOTSUPP: return WSAEOPNOTSUPP;
- case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
- case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
- case EADDRINUSE: return WSAEADDRINUSE;
- case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
- case ENETDOWN: return WSAENETDOWN;
- case ENETUNREACH: return WSAENETUNREACH;
- case ENETRESET: return WSAENETRESET;
- case ECONNABORTED: return WSAECONNABORTED;
- case EPIPE:
- case ECONNRESET: return WSAECONNRESET;
- case ENOBUFS: return WSAENOBUFS;
- case EISCONN: return WSAEISCONN;
- case ENOTCONN: return WSAENOTCONN;
- case ESHUTDOWN: return WSAESHUTDOWN;
- case ETOOMANYREFS: return WSAETOOMANYREFS;
- case ETIMEDOUT: return WSAETIMEDOUT;
- case ECONNREFUSED: return WSAECONNREFUSED;
- case ELOOP: return WSAELOOP;
- case ENAMETOOLONG: return WSAENAMETOOLONG;
- case EHOSTDOWN: return WSAEHOSTDOWN;
- case EHOSTUNREACH: return WSAEHOSTUNREACH;
- case ENOTEMPTY: return WSAENOTEMPTY;
-#ifdef EPROCLIM
- case EPROCLIM: return WSAEPROCLIM;
-#endif
-#ifdef EUSERS
- case EUSERS: return WSAEUSERS;
-#endif
-#ifdef EDQUOT
- case EDQUOT: return WSAEDQUOT;
-#endif
-#ifdef ESTALE
- case ESTALE: return WSAESTALE;
-#endif
-#ifdef EREMOTE
- case EREMOTE: return WSAEREMOTE;
-#endif
- default: errno = err; perror( "sock_set_error" ); return WSAEFAULT;
- }
-#endif
- return err;
-}
-#else
-#define sock_get_error(x) WSAGetLastError()
-
-static inline int unix_ioctl(int filedes, long request, void *arg)
-{
- return ioctlsocket(filedes, request, arg);
-}
-#define ioctlsocket unix_ioctl
-#endif
-
static int sock_send(int fd, const void *msg, size_t len, int flags)
{
int ret;
do
{
- if ((ret = send(fd, msg, len, flags)) == -1) WARN("send error %s\n",
strerror(errno));
+ if ((ret = send(fd, msg, len, flags)) == -1) WARN("send error %u\n",
WSAGetLastError());
}
- while(ret == -1 && errno == EINTR);
+ while(ret == -1 && WSAGetLastError() == WSAEINTR);
return ret;
}
@@ -165,13 +51,13 @@ static int sock_recv(int fd, void *msg, size_t len, int flags)
int ret;
do
{
- if ((ret = recv(fd, msg, len, flags)) == -1) WARN("recv error %s\n",
strerror(errno));
+ if ((ret = recv(fd, msg, len, flags)) == -1) WARN("recv error %u\n",
WSAGetLastError());
}
- while(ret == -1 && errno == EINTR);
+ while(ret == -1 && WSAGetLastError() == WSAEINTR);
return ret;
}
-static DWORD netconn_verify_cert( PCCERT_CONTEXT cert, WCHAR *server, DWORD
security_flags )
+static DWORD netconn_verify_cert( PCCERT_CONTEXT cert, WCHAR *server, DWORD
security_flags, BOOL check_revocation )
{
HCERTSTORE store = cert->hCertStore;
BOOL ret;
@@ -184,9 +70,10 @@ static DWORD netconn_verify_cert( PCCERT_CONTEXT cert, WCHAR *server,
DWORD secu
TRACE("verifying %s\n", debugstr_w( server ));
chainPara.RequestedUsage.Usage.cUsageIdentifier = 1;
chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = server_auth;
- if ((ret = CertGetCertificateChain( NULL, cert, NULL, store, &chainPara,
- CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,
- NULL, &chain )))
+ ret = CertGetCertificateChain( NULL, cert, NULL, store, &chainPara,
+ check_revocation ?
CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT : 0,
+ NULL, &chain );
+ if (ret)
{
if (chain->TrustStatus.dwErrorStatus)
{
@@ -264,46 +151,41 @@ static DWORD netconn_verify_cert( PCCERT_CONTEXT cert, WCHAR
*server, DWORD secu
return err;
}
-#ifdef __REACTOS__
-static BOOL winsock_initialized = FALSE;
-BOOL netconn_init_winsock()
+static BOOL winsock_loaded;
+
+void netconn_unload( void )
{
- WSADATA wsaData;
- int error;
- if (!winsock_initialized)
- {
- error = WSAStartup(MAKEWORD(1, 1), &wsaData);
- if (error)
- {
- ERR("WSAStartup failed: %d\n", error);
- return FALSE;
- }
- else
- winsock_initialized = TRUE;
- }
- return winsock_initialized;
+ if (winsock_loaded) WSACleanup();
+}
+
+static BOOL WINAPI winsock_startup( INIT_ONCE *once, void *param, void **ctx )
+{
+ int ret;
+ WSADATA data;
+ if (!(ret = WSAStartup( MAKEWORD(1,1), &data ))) winsock_loaded = TRUE;
+ else ERR( "WSAStartup failed: %d\n", ret );
+ return TRUE;
}
-#endif
+static void winsock_init(void)
+{
+ static INIT_ONCE once = INIT_ONCE_STATIC_INIT;
+ InitOnceExecuteOnce( &once, winsock_startup, NULL, NULL );
+}
-void netconn_unload( void )
+static void set_blocking( struct netconn *conn, BOOL blocking )
{
-#ifndef HAVE_GETADDRINFO
- DeleteCriticalSection(&cs_gethostbyname);
-#endif
-#ifdef __REACTOS__
- if(winsock_initialized)
- WSACleanup();
-#endif
+ ULONG state = !blocking;
+ ioctlsocket( conn->socket, FIONBIO, &state );
}
-netconn_t *netconn_create( hostdata_t *host, const struct sockaddr_storage *sockaddr, int
timeout )
+struct netconn *netconn_create( struct hostdata *host, const struct sockaddr_storage
*sockaddr, int timeout )
{
- netconn_t *conn;
+ struct netconn *conn;
unsigned int addr_len;
BOOL ret = FALSE;
- int res;
- ULONG state;
+
+ winsock_init();
conn = heap_alloc_zero(sizeof(*conn));
if (!conn) return NULL;
@@ -311,8 +193,7 @@ netconn_t *netconn_create( hostdata_t *host, const struct
sockaddr_storage *sock
conn->sockaddr = *sockaddr;
if ((conn->socket = socket( sockaddr->ss_family, SOCK_STREAM, 0 )) == -1)
{
- WARN("unable to create socket (%s)\n", strerror(errno));
- set_last_error( sock_get_error( errno ) );
+ WARN("unable to create socket (%u)\n", WSAGetLastError());
heap_free(conn);
return NULL;
}
@@ -329,83 +210,39 @@ netconn_t *netconn_create( hostdata_t *host, const struct
sockaddr_storage *sock
assert(0);
}
- if (timeout > 0)
- {
- state = 1;
- ioctlsocket( conn->socket, FIONBIO, &state );
- }
+ if (timeout > 0) set_blocking( conn, FALSE );
- for (;;)
+ if (!connect( conn->socket, (const struct sockaddr *)&conn->sockaddr,
addr_len )) ret = TRUE;
+ else
{
- res = 0;
- if (connect( conn->socket, (const struct sockaddr *)&conn->sockaddr,
addr_len ) < 0)
- {
- res = sock_get_error( errno );
- if (res == WSAEWOULDBLOCK || res == WSAEINPROGRESS)
- {
-#ifdef __REACTOS__
- /* ReactOS: use select instead of poll */
- fd_set outfd;
- struct timeval tv;
-
- FD_ZERO(&outfd);
- FD_SET(conn->socket, &outfd);
-
- tv.tv_sec = 0;
- tv.tv_usec = timeout * 1000;
- for (;;)
- {
- res = 0;
-
- if (select( 0, NULL, &outfd, NULL, &tv ) > 0)
-#else
- struct pollfd pfd;
-
- pfd.fd = conn->socket;
- pfd.events = POLLOUT;
- for (;;)
- {
- res = 0;
- if (poll( &pfd, 1, timeout ) > 0)
-#endif
- {
- ret = TRUE;
- break;
- }
- else
- {
- res = sock_get_error( errno );
- if (res != WSAEINTR) break;
- }
- }
- }
- if (res != WSAEINTR) break;
- }
- else
+ DWORD err = WSAGetLastError();
+ if (err == WSAEWOULDBLOCK || err == WSAEINPROGRESS)
{
- ret = TRUE;
- break;
+ FD_SET set;
+ TIMEVAL timeval = { 0, timeout * 1000 };
+ int res;
+
+ FD_ZERO( &set );
+ FD_SET( conn->socket, &set );
+ if ((res = select( conn->socket + 1, NULL, &set, NULL, &timeval ))
> 0) ret = TRUE;
+ else if (!res) SetLastError( ERROR_WINHTTP_TIMEOUT );
}
}
- if (timeout > 0)
- {
- state = 0;
- ioctlsocket( conn->socket, FIONBIO, &state );
- }
+
+ if (timeout > 0) set_blocking( conn, TRUE );
+
if (!ret)
{
- WARN("unable to connect to host (%d)\n", res);
- set_last_error( res );
- netconn_close( conn );
+ WARN("unable to connect to host (%u)\n", GetLastError());
+ closesocket( conn->socket );
+ heap_free( conn );
return NULL;
}
return conn;
}
-BOOL netconn_close( netconn_t *conn )
+void netconn_close( struct netconn *conn )
{
- int res;
-
if (conn->secure)
{
heap_free( conn->peek_msg_mem );
@@ -413,18 +250,13 @@ BOOL netconn_close( netconn_t *conn )
heap_free(conn->extra_buf);
DeleteSecurityContext(&conn->ssl_ctx);
}
- res = closesocket( conn->socket );
+ closesocket( conn->socket );
release_host( conn->host );
heap_free(conn);
- if (res == -1)
- {
- set_last_error( sock_get_error( errno ) );
- return FALSE;
- }
- return TRUE;
}
-BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD security_flags,
CredHandle *cred_handle )
+BOOL netconn_secure_connect( struct netconn *conn, WCHAR *hostname, DWORD security_flags,
CredHandle *cred_handle,
+ BOOL check_revocation)
{
SecBuffer out_buf = {0, SECBUFFER_TOKEN, NULL}, in_bufs[2] = {{0, SECBUFFER_TOKEN},
{0, SECBUFFER_EMPTY}};
SecBufferDesc out_desc = {SECBUFFER_VERSION, 1, &out_buf}, in_desc =
{SECBUFFER_VERSION, 2, in_bufs};
@@ -520,7 +352,7 @@ BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD
security_fl
status = QueryContextAttributesW(&ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT,
(void*)&cert);
if(status == SEC_E_OK) {
- res = netconn_verify_cert(cert, hostname, security_flags);
+ res = netconn_verify_cert(cert, hostname, security_flags,
check_revocation);
CertFreeCertificateContext(cert);
if(res != ERROR_SUCCESS) {
WARN("cert verify failed: %u\n", res);
@@ -546,7 +378,7 @@ BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD
security_fl
heap_free(conn->ssl_buf);
conn->ssl_buf = NULL;
DeleteSecurityContext(&ctx);
- set_last_error(res ? res : ERROR_WINHTTP_SECURE_CHANNEL_ERROR);
+ SetLastError(res ? res : ERROR_WINHTTP_SECURE_CHANNEL_ERROR);
return FALSE;
}
@@ -557,7 +389,7 @@ BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD
security_fl
return TRUE;
}
-static BOOL send_ssl_chunk(netconn_t *conn, const void *msg, size_t size)
+static BOOL send_ssl_chunk(struct netconn *conn, const void *msg, size_t size)
{
SecBuffer bufs[4] = {
{conn->ssl_sizes.cbHeader, SECBUFFER_STREAM_HEADER, conn->ssl_buf},
@@ -565,7 +397,7 @@ static BOOL send_ssl_chunk(netconn_t *conn, const void *msg, size_t
size)
{conn->ssl_sizes.cbTrailer, SECBUFFER_STREAM_TRAILER,
conn->ssl_buf+conn->ssl_sizes.cbHeader+size},
{0, SECBUFFER_EMPTY, NULL}
};
- SecBufferDesc buf_desc = {SECBUFFER_VERSION, sizeof(bufs)/sizeof(*bufs), bufs};
+ SecBufferDesc buf_desc = {SECBUFFER_VERSION, ARRAY_SIZE(bufs), bufs};
SECURITY_STATUS res;
memcpy(bufs[1].pvBuffer, msg, size);
@@ -583,7 +415,7 @@ static BOOL send_ssl_chunk(netconn_t *conn, const void *msg, size_t
size)
return TRUE;
}
-BOOL netconn_send( netconn_t *conn, const void *msg, size_t len, int *sent )
+BOOL netconn_send( struct netconn *conn, const void *msg, size_t len, int *sent )
{
if (conn->secure)
{
@@ -604,19 +436,14 @@ BOOL netconn_send( netconn_t *conn, const void *msg, size_t len, int
*sent )
return TRUE;
}
- if ((*sent = sock_send( conn->socket, msg, len, 0 )) == -1)
- {
- set_last_error( sock_get_error( errno ) );
- return FALSE;
- }
- return TRUE;
+ return ((*sent = sock_send( conn->socket, msg, len, 0 )) != -1);
}
-static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T buf_size, SIZE_T *ret_size,
BOOL *eof)
+static BOOL read_ssl_chunk(struct netconn *conn, void *buf, SIZE_T buf_size, SIZE_T
*ret_size, BOOL *eof)
{
const SIZE_T ssl_buf_size =
conn->ssl_sizes.cbHeader+conn->ssl_sizes.cbMaximumMessage+conn->ssl_sizes.cbTrailer;
SecBuffer bufs[4];
- SecBufferDesc buf_desc = {SECBUFFER_VERSION, sizeof(bufs)/sizeof(*bufs), bufs};
+ SecBufferDesc buf_desc = {SECBUFFER_VERSION, ARRAY_SIZE(bufs), bufs};
SSIZE_T size, buf_len;
unsigned int i;
SECURITY_STATUS res;
@@ -672,7 +499,7 @@ static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T
buf_size, SIZE_T *
}
} while(res != SEC_E_OK);
- for(i=0; i < sizeof(bufs)/sizeof(*bufs); i++) {
+ for(i = 0; i < ARRAY_SIZE(bufs); i++) {
if(bufs[i].BufferType == SECBUFFER_DATA) {
size = min(buf_size, bufs[i].cbBuffer);
memcpy(buf, bufs[i].pvBuffer, size);
@@ -689,7 +516,7 @@ static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T
buf_size, SIZE_T *
}
}
- for(i=0; i < sizeof(bufs)/sizeof(*bufs); i++) {
+ for(i = 0; i < ARRAY_SIZE(bufs); i++) {
if(bufs[i].BufferType == SECBUFFER_EXTRA) {
conn->extra_buf = heap_alloc(bufs[i].cbBuffer);
if(!conn->extra_buf)
@@ -703,7 +530,7 @@ static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T
buf_size, SIZE_T *
return TRUE;
}
-BOOL netconn_recv( netconn_t *conn, void *buf, size_t len, int flags, int *recvd )
+BOOL netconn_recv( struct netconn *conn, void *buf, size_t len, int flags, int *recvd )
{
*recvd = 0;
if (!len) return TRUE;
@@ -752,101 +579,64 @@ BOOL netconn_recv( netconn_t *conn, void *buf, size_t len, int
flags, int *recvd
*recvd = size;
return TRUE;
}
- if ((*recvd = sock_recv( conn->socket, buf, len, flags )) == -1)
- {
- set_last_error( sock_get_error( errno ) );
- return FALSE;
- }
- return TRUE;
+ return ((*recvd = sock_recv( conn->socket, buf, len, flags )) != -1);
}
-ULONG netconn_query_data_available( netconn_t *conn )
+ULONG netconn_query_data_available( struct netconn *conn )
{
return conn->secure ? conn->peek_len : 0;
}
-DWORD netconn_set_timeout( netconn_t *netconn, BOOL send, int value )
+DWORD netconn_set_timeout( struct netconn *netconn, BOOL send, int value )
{
- struct timeval tv;
-
- /* value is in milliseconds, convert to struct timeval */
- tv.tv_sec = value / 1000;
- tv.tv_usec = (value % 1000) * 1000;
-
- if (setsockopt( netconn->socket, SOL_SOCKET, send ? SO_SNDTIMEO : SO_RCVTIMEO,
(void*)&tv, sizeof(tv) ) == -1)
+ int opt = send ? SO_SNDTIMEO : SO_RCVTIMEO;
+ if (setsockopt( netconn->socket, SOL_SOCKET, opt, (void *)&value,
sizeof(value) ) == -1)
{
- WARN("setsockopt failed (%s)\n", strerror( errno ));
- return sock_get_error( errno );
+ DWORD err = WSAGetLastError();
+ WARN("setsockopt failed (%u)\n", err );
+ return err;
}
return ERROR_SUCCESS;
}
-BOOL netconn_is_alive( netconn_t *netconn )
+BOOL netconn_is_alive( struct netconn *netconn )
{
-#ifdef MSG_DONTWAIT
- ssize_t len;
- BYTE b;
-
- len = recv( netconn->socket, &b, 1, MSG_PEEK | MSG_DONTWAIT );
- return len == 1 || (len == -1 && errno == EWOULDBLOCK);
-#elif defined(__MINGW32__) || defined(_MSC_VER)
- ULONG mode;
int len;
char b;
+ DWORD err;
- mode = 1;
- if(!ioctlsocket(netconn->socket, FIONBIO, &mode))
- return FALSE;
-
- len = recv(netconn->socket, &b, 1, MSG_PEEK);
+ set_blocking( netconn, FALSE );
+ len = sock_recv( netconn->socket, &b, 1, MSG_PEEK );
+ err = WSAGetLastError();
+ set_blocking( netconn, TRUE );
- mode = 0;
- if(!ioctlsocket(netconn->socket, FIONBIO, &mode))
- return FALSE;
-
- return len == 1 || (len == -1 && WSAGetLastError() == WSAEWOULDBLOCK);
-#else
- FIXME("not supported on this platform\n");
- return TRUE;
-#endif
+ return len == 1 || (len == -1 && err == WSAEWOULDBLOCK);
}
-static DWORD resolve_hostname( const WCHAR *hostnameW, INTERNET_PORT port, struct
sockaddr_storage *sa )
+static DWORD resolve_hostname( const WCHAR *name, INTERNET_PORT port, struct
sockaddr_storage *sa )
{
- char *hostname;
-#ifdef HAVE_GETADDRINFO
- struct addrinfo *res, hints;
+ ADDRINFOW *res, hints;
int ret;
-#else
- struct hostent *he;
- struct sockaddr_in *sin = (struct sockaddr_in *)sa;
-#endif
-
- if (!(hostname = strdupWA( hostnameW ))) return ERROR_OUTOFMEMORY;
-#ifdef HAVE_GETADDRINFO
- memset( &hints, 0, sizeof(struct addrinfo) );
+ memset( &hints, 0, sizeof(hints) );
/* Prefer IPv4 to IPv6 addresses, since some web servers do not listen on
* their IPv6 addresses even though they have IPv6 addresses in the DNS.
*/
hints.ai_family = AF_INET;
- ret = getaddrinfo( hostname, NULL, &hints, &res );
+ ret = GetAddrInfoW( name, NULL, &hints, &res );
if (ret != 0)
{
- TRACE("failed to get IPv4 address of %s (%s), retrying with IPv6\n",
debugstr_w(hostnameW), gai_strerror(ret));
+ TRACE("failed to get IPv4 address of %s, retrying with IPv6\n",
debugstr_w(name));
hints.ai_family = AF_INET6;
- ret = getaddrinfo( hostname, NULL, &hints, &res );
+ ret = GetAddrInfoW( name, NULL, &hints, &res );
if (ret != 0)
{
- TRACE("failed to get address of %s (%s)\n", debugstr_w(hostnameW),
gai_strerror(ret));
- heap_free( hostname );
+ TRACE("failed to get address of %s\n", debugstr_w(name));
return ERROR_WINHTTP_NAME_NOT_RESOLVED;
}
}
- heap_free( hostname );
memcpy( sa, res->ai_addr, res->ai_addrlen );
- /* Copy port */
switch (res->ai_family)
{
case AF_INET:
@@ -857,29 +647,12 @@ static DWORD resolve_hostname( const WCHAR *hostnameW, INTERNET_PORT
port, struc
break;
}
- freeaddrinfo( res );
+ FreeAddrInfoW( res );
return ERROR_SUCCESS;
-#else
- EnterCriticalSection( &cs_gethostbyname );
-
- he = gethostbyname( hostname );
- heap_free( hostname );
- if (!he)
- {
- TRACE("failed to get address of %s (%d)\n", debugstr_w(hostnameW),
h_errno);
- LeaveCriticalSection( &cs_gethostbyname );
- return ERROR_WINHTTP_NAME_NOT_RESOLVED;
- }
- memset( sa, 0, sizeof(struct sockaddr_in) );
- memcpy( &sin->sin_addr, he->h_addr, he->h_length );
- sin->sin_family = he->h_addrtype;
- sin->sin_port = htons( port );
-
- LeaveCriticalSection( &cs_gethostbyname );
- return ERROR_SUCCESS;
-#endif
}
+#ifdef __REACTOS__
+
struct resolve_args
{
const WCHAR *hostname;
@@ -919,13 +692,64 @@ BOOL netconn_resolve( WCHAR *hostname, INTERNET_PORT port, struct
sockaddr_stora
if (ret)
{
- set_last_error( ret );
+ SetLastError( ret );
return FALSE;
}
return TRUE;
}
-const void *netconn_get_certificate( netconn_t *conn )
+#else /* __REACTOS__ */
+
+struct async_resolve
+{
+ const WCHAR *hostname;
+ INTERNET_PORT port;
+ struct sockaddr_storage *addr;
+ DWORD result;
+ HANDLE done;
+};
+
+static void CALLBACK resolve_proc( TP_CALLBACK_INSTANCE *instance, void *ctx )
+{
+ struct async_resolve *async = ctx;
+ async->result = resolve_hostname( async->hostname, async->port,
async->addr );
+ SetEvent( async->done );
+}
+
+BOOL netconn_resolve( WCHAR *hostname, INTERNET_PORT port, struct sockaddr_storage *addr,
int timeout )
+{
+ DWORD ret;
+
+ if (!timeout) ret = resolve_hostname( hostname, port, addr );
+ else
+ {
+ struct async_resolve async;
+
+ async.hostname = hostname;
+ async.port = port;
+ async.addr = addr;
+ if (!(async.done = CreateEventW( NULL, FALSE, FALSE, NULL ))) return FALSE;
+ if (!TrySubmitThreadpoolCallback( resolve_proc, &async, NULL ))
+ {
+ CloseHandle( async.done );
+ return FALSE;
+ }
+ if (WaitForSingleObject( async.done, timeout ) != WAIT_OBJECT_0) ret =
ERROR_WINHTTP_TIMEOUT;
+ else ret = async.result;
+ CloseHandle( async.done );
+ }
+
+ if (ret)
+ {
+ SetLastError( ret );
+ return FALSE;
+ }
+ return TRUE;
+}
+
+#endif /* __REACTOS__ */
+
+const void *netconn_get_certificate( struct netconn *conn )
{
const CERT_CONTEXT *ret;
SECURITY_STATUS res;
@@ -935,7 +759,7 @@ const void *netconn_get_certificate( netconn_t *conn )
return res == SEC_E_OK ? ret : NULL;
}
-int netconn_get_cipher_strength( netconn_t *conn )
+int netconn_get_cipher_strength( struct netconn *conn )
{
SecPkgContext_ConnectionInfo conn_info;
SECURITY_STATUS res;
diff --git a/dll/win32/winhttp/request.c b/dll/win32/winhttp/request.c
index 5bb5b093373..da28f7b1826 100644
--- a/dll/win32/winhttp/request.c
+++ b/dll/win32/winhttp/request.c
@@ -21,13 +21,9 @@
#define COBJMACROS
#include "config.h"
-#include "wine/port.h"
-
+#include "ws2tcpip.h"
#include <stdarg.h>
#include <assert.h>
-#ifdef HAVE_ARPA_INET_H
-# include <arpa/inet.h>
-#endif
#include "windef.h"
#include "winbase.h"
@@ -38,9 +34,8 @@
#include "schannel.h"
#include "winhttp.h"
-#include "winhttp_private.h"
-
#include "wine/debug.h"
+#include "winhttp_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
@@ -186,13 +181,13 @@ static const WCHAR *attribute_table[] =
NULL /* WINHTTP_QUERY_PASSPORT_CONFIG = 78 */
};
-static task_header_t *dequeue_task( request_t *request )
+static struct task_header *dequeue_task( struct request *request )
{
- task_header_t *task;
+ struct task_header *task;
EnterCriticalSection( &request->task_cs );
TRACE("%u tasks queued\n", list_count( &request->task_queue ));
- task = LIST_ENTRY( list_head( &request->task_queue ), task_header_t, entry );
+ task = LIST_ENTRY( list_head( &request->task_queue ), struct task_header,
entry );
if (task) list_remove( &task->entry );
LeaveCriticalSection( &request->task_cs );
@@ -200,9 +195,17 @@ static task_header_t *dequeue_task( request_t *request )
return task;
}
+#ifdef __REACTOS__
static DWORD CALLBACK task_proc( LPVOID param )
+#else
+static void CALLBACK task_proc( TP_CALLBACK_INSTANCE *instance, void *ctx )
+#endif
{
- request_t *request = param;
+#ifdef __REACTOS__
+ struct request *request = param;
+#else
+ struct request *request = ctx;
+#endif
HANDLE handles[2];
handles[0] = request->task_wait;
@@ -214,7 +217,7 @@ static DWORD CALLBACK task_proc( LPVOID param )
{
case WAIT_OBJECT_0:
{
- task_header_t *task;
+ struct task_header *task;
while ((task = dequeue_task( request )))
{
task->proc( task );
@@ -230,21 +233,31 @@ static DWORD CALLBACK task_proc( LPVOID param )
request->task_cs.DebugInfo->Spare[0] = 0;
DeleteCriticalSection( &request->task_cs );
request->hdr.vtbl->destroy( &request->hdr );
+#ifdef __REACTOS__
return 0;
+#else
+ return;
+#endif
default:
ERR("wait failed %u (%u)\n", err, GetLastError());
break;
}
}
+#ifdef __REACTOS__
return 0;
+#endif
}
-static BOOL queue_task( task_header_t *task )
+static BOOL queue_task( struct task_header *task )
{
- request_t *request = task->request;
+ struct request *request = task->request;
+#ifdef __REACTOS__
if (!request->task_thread)
+#else
+ if (!request->task_wait)
+#endif
{
if (!(request->task_wait = CreateEventW( NULL, FALSE, FALSE, NULL ))) return
FALSE;
if (!(request->task_cancel = CreateEventW( NULL, FALSE, FALSE, NULL )))
@@ -253,7 +266,11 @@ static BOOL queue_task( task_header_t *task )
request->task_wait = NULL;
return FALSE;
}
+#ifdef __REACTOS__
if (!(request->task_thread = CreateThread( NULL, 0, task_proc, request, 0,
NULL )))
+#else
+ if (!TrySubmitThreadpoolCallback( task_proc, request, NULL ))
+#endif
{
CloseHandle( request->task_wait );
request->task_wait = NULL;
@@ -261,6 +278,9 @@ static BOOL queue_task( task_header_t *task )
request->task_cancel = NULL;
return FALSE;
}
+#ifndef __REACTOS__
+ request->task_proc_running = TRUE;
+#endif
InitializeCriticalSection( &request->task_cs );
request->task_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ":
request.task_cs");
}
@@ -274,7 +294,7 @@ static BOOL queue_task( task_header_t *task )
return TRUE;
}
-static void free_header( header_t *header )
+static void free_header( struct header *header )
{
heap_free( header->field );
heap_free( header->value );
@@ -302,10 +322,10 @@ static BOOL valid_token_char( WCHAR c )
}
}
-static header_t *parse_header( LPCWSTR string )
+static struct header *parse_header( const WCHAR *string )
{
const WCHAR *p, *q;
- header_t *header;
+ struct header *header;
int len;
p = string;
@@ -329,7 +349,7 @@ static header_t *parse_header( LPCWSTR string )
p++;
}
len = q - string;
- if (!(header = heap_alloc_zero( sizeof(header_t) ))) return NULL;
+ if (!(header = heap_alloc_zero( sizeof(struct header) ))) return NULL;
if (!(header->field = heap_alloc( (len + 1) * sizeof(WCHAR) )))
{
heap_free( header );
@@ -353,7 +373,7 @@ static header_t *parse_header( LPCWSTR string )
return header;
}
-static int get_header_index( request_t *request, LPCWSTR field, int requested_index, BOOL
request_only )
+static int get_header_index( struct request *request, const WCHAR *field, int
requested_index, BOOL request_only )
{
int index;
@@ -373,15 +393,15 @@ static int get_header_index( request_t *request, LPCWSTR field, int
requested_in
return index;
}
-static BOOL insert_header( request_t *request, header_t *header )
+static BOOL insert_header( struct request *request, struct header *header )
{
DWORD count = request->num_headers + 1;
- header_t *hdrs;
+ struct header *hdrs;
if (request->headers)
- hdrs = heap_realloc_zero( request->headers, sizeof(header_t) * count );
+ hdrs = heap_realloc_zero( request->headers, sizeof(struct header) * count );
else
- hdrs = heap_alloc_zero( sizeof(header_t) );
+ hdrs = heap_alloc_zero( sizeof(struct header) );
if (!hdrs) return FALSE;
request->headers = hdrs;
@@ -392,7 +412,7 @@ static BOOL insert_header( request_t *request, header_t *header )
return TRUE;
}
-static BOOL delete_header( request_t *request, DWORD index )
+static BOOL delete_header( struct request *request, DWORD index )
{
if (!request->num_headers) return FALSE;
if (index >= request->num_headers) return FALSE;
@@ -401,15 +421,16 @@ static BOOL delete_header( request_t *request, DWORD index )
heap_free( request->headers[index].field );
heap_free( request->headers[index].value );
- memmove( &request->headers[index], &request->headers[index + 1],
(request->num_headers - index) * sizeof(header_t) );
- memset( &request->headers[request->num_headers], 0, sizeof(header_t) );
+ memmove( &request->headers[index], &request->headers[index + 1],
+ (request->num_headers - index) * sizeof(struct header) );
+ memset( &request->headers[request->num_headers], 0, sizeof(struct header)
);
return TRUE;
}
-BOOL process_header( request_t *request, LPCWSTR field, LPCWSTR value, DWORD flags, BOOL
request_only )
+BOOL process_header( struct request *request, const WCHAR *field, const WCHAR *value,
DWORD flags, BOOL request_only )
{
int index;
- header_t hdr;
+ struct header hdr;
TRACE("%s: %s 0x%08x\n", debugstr_w(field), debugstr_w(value), flags);
@@ -427,7 +448,7 @@ BOOL process_header( request_t *request, LPCWSTR field, LPCWSTR value,
DWORD fla
}
else if (!(flags & WINHTTP_ADDREQ_FLAG_ADD))
{
- set_last_error( ERROR_WINHTTP_HEADER_NOT_FOUND );
+ SetLastError( ERROR_WINHTTP_HEADER_NOT_FOUND );
return FALSE;
}
@@ -444,7 +465,7 @@ BOOL process_header( request_t *request, LPCWSTR field, LPCWSTR value,
DWORD fla
{
WCHAR *tmp;
int len, len_orig, len_value;
- header_t *header = &request->headers[index];
+ struct header *header = &request->headers[index];
len_orig = strlenW( header->value );
len_value = strlenW( value );
@@ -471,11 +492,11 @@ BOOL process_header( request_t *request, LPCWSTR field, LPCWSTR
value, DWORD fla
return TRUE;
}
-BOOL add_request_headers( request_t *request, LPCWSTR headers, DWORD len, DWORD flags )
+BOOL add_request_headers( struct request *request, const WCHAR *headers, DWORD len, DWORD
flags )
{
BOOL ret = FALSE;
WCHAR *buffer, *p, *q;
- header_t *header;
+ struct header *header;
if (len == ~0u) len = strlenW( headers );
if (!len) return TRUE;
@@ -521,134 +542,116 @@ BOOL add_request_headers( request_t *request, LPCWSTR headers,
DWORD len, DWORD
BOOL WINAPI WinHttpAddRequestHeaders( HINTERNET hrequest, LPCWSTR headers, DWORD len,
DWORD flags )
{
BOOL ret;
- request_t *request;
+ struct request *request;
TRACE("%p, %s, %u, 0x%08x\n", hrequest, debugstr_wn(headers, len), len,
flags);
if (!headers || !len)
{
- set_last_error( ERROR_INVALID_PARAMETER );
+ SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
- if (!(request = (request_t *)grab_object( hrequest )))
+ if (!(request = (struct request *)grab_object( hrequest )))
{
- set_last_error( ERROR_INVALID_HANDLE );
+ SetLastError( ERROR_INVALID_HANDLE );
return FALSE;
}
if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST)
{
release_object( &request->hdr );
- set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+ SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
return FALSE;
}
ret = add_request_headers( request, headers, len, flags );
release_object( &request->hdr );
- if (ret) set_last_error( ERROR_SUCCESS );
+ if (ret) SetLastError( ERROR_SUCCESS );
return ret;
}
-static WCHAR *build_request_path( request_t *request )
+static WCHAR *build_absolute_request_path( struct request *request, const WCHAR **path )
{
+ static const WCHAR http[] = {'h','t','t','p',0};
+ static const WCHAR https[] =
{'h','t','t','p','s',0};
+ static const WCHAR fmt[] =
{'%','s',':','/','/','%','s',0};
+ const WCHAR *scheme;
WCHAR *ret;
+ int len;
- if (strcmpiW( request->connect->hostname, request->connect->servername
))
- {
- static const WCHAR http[] = { 'h','t','t','p',0
};
- static const WCHAR https[] = {
'h','t','t','p','s',0 };
- static const WCHAR fmt[] = {
'%','s',':','/','/','%','s',0 };
- LPCWSTR scheme = (request->netconn ? request->netconn->secure :
(request->hdr.flags & WINHTTP_FLAG_SECURE)) ? https : http;
- int len;
+ scheme = (request->netconn ? request->netconn->secure :
(request->hdr.flags & WINHTTP_FLAG_SECURE)) ? https : http;
+
+ len = strlenW( scheme ) + strlenW( request->connect->hostname ) + 4; /*
'://' + nul */
+ if (request->connect->hostport) len += 6; /* ':' between host and port,
up to 5 for port */
- len = strlenW( scheme ) + strlenW( request->connect->hostname );
- /* 3 characters for '://', 1 for NUL. */
- len += 4;
+ len += strlenW( request->path );
+ if ((ret = heap_alloc( len * sizeof(WCHAR) )))
+ {
+ len = sprintfW( ret, fmt, scheme, request->connect->hostname );
if (request->connect->hostport)
{
- /* 1 for ':' between host and port, up to 5 for port */
- len += 6;
- }
- if (request->path)
- len += strlenW( request->path );
- if ((ret = heap_alloc( len * sizeof(WCHAR) )))
- {
- sprintfW( ret, fmt, scheme, request->connect->hostname );
- if (request->connect->hostport)
- {
- static const WCHAR colonFmt[] = { ':','%','u',0
};
-
- sprintfW( ret + strlenW( ret ), colonFmt,
- request->connect->hostport );
- }
- if (request->path)
- strcatW( ret, request->path );
+ static const WCHAR port_fmt[] = {':','%','u',0};
+ len += sprintfW( ret + len, port_fmt, request->connect->hostport );
}
+ strcpyW( ret + len, request->path );
+ if (path) *path = ret + len;
}
- else
- ret = request->path;
+
return ret;
}
-static WCHAR *build_request_string( request_t *request )
+static WCHAR *build_request_string( struct request *request )
{
- static const WCHAR space[] = {' ',0};
- static const WCHAR crlf[] = {'\r','\n',0};
- static const WCHAR colon[] = {':',' ',0};
- static const WCHAR twocrlf[] =
{'\r','\n','\r','\n',0};
-
+ static const WCHAR spaceW[] = {' ',0}, crlfW[] =
{'\r','\n',0}, colonW[] = {':',' ',0};
+ static const WCHAR twocrlfW[] =
{'\r','\n','\r','\n',0};
WCHAR *path, *ret;
- const WCHAR **headers, **p;
- unsigned int len, i = 0, j;
+ unsigned int i, len;
- /* allocate space for an array of all the string pointers to be added */
- len = request->num_headers * 4 + 7;
- if (!(headers = heap_alloc( len * sizeof(LPCWSTR) ))) return NULL;
+ if (!strcmpiW( request->connect->hostname, request->connect->servername
)) path = request->path;
+ else if (!(path = build_absolute_request_path( request, NULL ))) return NULL;
- path = build_request_path( request );
- headers[i++] = request->verb;
- headers[i++] = space;
- headers[i++] = path;
- headers[i++] = space;
- headers[i++] = request->version;
+ len = strlenW( request->verb ) + 1 /* ' ' */;
+ len += strlenW( path ) + 1 /* ' ' */;
+ len += strlenW( request->version );
- for (j = 0; j < request->num_headers; j++)
+ for (i = 0; i < request->num_headers; i++)
{
- if (request->headers[j].is_request)
- {
- headers[i++] = crlf;
- headers[i++] = request->headers[j].field;
- headers[i++] = colon;
- headers[i++] = request->headers[j].value;
-
- TRACE("adding header %s (%s)\n",
debugstr_w(request->headers[j].field),
- debugstr_w(request->headers[j].value));
- }
+ if (request->headers[i].is_request)
+ len += strlenW( request->headers[i].field ) + strlenW(
request->headers[i].value ) + 4; /* '\r\n: ' */
}
- headers[i++] = twocrlf;
- headers[i] = NULL;
+ len += 4; /* '\r\n\r\n' */
- len = 0;
- for (p = headers; *p; p++) len += strlenW( *p );
- len++;
+ if ((ret = heap_alloc( (len + 1) * sizeof(WCHAR) )))
+ {
+ strcpyW( ret, request->verb );
+ strcatW( ret, spaceW );
+ strcatW( ret, path );
+ strcatW( ret, spaceW );
+ strcatW( ret, request->version );
- if (!(ret = heap_alloc( len * sizeof(WCHAR) )))
- goto out;
- *ret = 0;
- for (p = headers; *p; p++) strcatW( ret, *p );
+ for (i = 0; i < request->num_headers; i++)
+ {
+ if (request->headers[i].is_request)
+ {
+ strcatW( ret, crlfW );
+ strcatW( ret, request->headers[i].field );
+ strcatW( ret, colonW );
+ strcatW( ret, request->headers[i].value );
+ }
+ }
+ strcatW( ret, twocrlfW );
+ }
-out:
- if (path != request->path)
- heap_free( path );
- heap_free( headers );
+ if (path != request->path) heap_free( path );
return ret;
}
#define QUERY_MODIFIER_MASK (WINHTTP_QUERY_FLAG_REQUEST_HEADERS |
WINHTTP_QUERY_FLAG_SYSTEMTIME | WINHTTP_QUERY_FLAG_NUMBER)
-static BOOL query_headers( request_t *request, DWORD level, LPCWSTR name, LPVOID buffer,
LPDWORD buflen, LPDWORD index )
+static BOOL query_headers( struct request *request, DWORD level, const WCHAR *name, void
*buffer, DWORD *buflen,
+ DWORD *index )
{
- header_t *header = NULL;
+ struct header *header = NULL;
BOOL request_only, ret = FALSE;
int requested_index, header_index = -1;
DWORD attr, len;
@@ -677,7 +680,7 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR
name, LPVOID
for (len = 0; *p; p++) if (*p != '\r') len++;
if (!buffer || len * sizeof(WCHAR) > *buflen)
- set_last_error( ERROR_INSUFFICIENT_BUFFER );
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
else
{
for (p = headers, q = buffer; *p; p++, q++)
@@ -711,7 +714,7 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR
name, LPVOID
if (!buffer || len + sizeof(WCHAR) > *buflen)
{
len += sizeof(WCHAR);
- set_last_error( ERROR_INSUFFICIENT_BUFFER );
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
}
else
{
@@ -728,7 +731,7 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR
name, LPVOID
if (!buffer || len + sizeof(WCHAR) > *buflen)
{
len += sizeof(WCHAR);
- set_last_error( ERROR_INSUFFICIENT_BUFFER );
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
}
else
{
@@ -744,7 +747,7 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR
name, LPVOID
if (!buffer || len + sizeof(WCHAR) > *buflen)
{
len += sizeof(WCHAR);
- set_last_error( ERROR_INSUFFICIENT_BUFFER );
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
}
else
{
@@ -755,10 +758,32 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR
name, LPVOID
*buflen = len;
return ret;
+ case WINHTTP_QUERY_REQUEST_METHOD:
+ len = strlenW( request->verb ) * sizeof(WCHAR);
+ if (!buffer || len + sizeof(WCHAR) > *buflen)
+ {
+ len += sizeof(WCHAR);
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
+ }
+ else
+ {
+ strcpyW( buffer, request->verb );
+ TRACE("returning string: %s\n", debugstr_w(buffer));
+ ret = TRUE;
+ }
+ *buflen = len;
+ return ret;
+
default:
- if (attr >= sizeof(attribute_table)/sizeof(attribute_table[0]) ||
!attribute_table[attr])
+ if (attr >= ARRAY_SIZE(attribute_table))
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+ if (!attribute_table[attr])
{
FIXME("attribute %u not implemented\n", attr);
+ SetLastError( ERROR_WINHTTP_HEADER_NOT_FOUND );
return FALSE;
}
TRACE("attribute %s\n", debugstr_w(attribute_table[attr]));
@@ -772,15 +797,14 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR
name, LPVOID
}
if (!header || (request_only && !header->is_request))
{
- set_last_error( ERROR_WINHTTP_HEADER_NOT_FOUND );
+ SetLastError( ERROR_WINHTTP_HEADER_NOT_FOUND );
return FALSE;
}
- if (index) *index += 1;
if (level & WINHTTP_QUERY_FLAG_NUMBER)
{
if (!buffer || sizeof(int) > *buflen)
{
- set_last_error( ERROR_INSUFFICIENT_BUFFER );
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
}
else
{
@@ -796,7 +820,7 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR
name, LPVOID
SYSTEMTIME *st = buffer;
if (!buffer || sizeof(SYSTEMTIME) > *buflen)
{
- set_last_error( ERROR_INSUFFICIENT_BUFFER );
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
}
else if ((ret = WinHttpTimeToSystemTime( header->value, st )))
{
@@ -812,7 +836,7 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR
name, LPVOID
if (!buffer || len + sizeof(WCHAR) > *buflen)
{
len += sizeof(WCHAR);
- set_last_error( ERROR_INSUFFICIENT_BUFFER );
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
}
else
{
@@ -822,6 +846,7 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR
name, LPVOID
}
*buflen = len;
}
+ if (ret && index) *index += 1;
return ret;
}
@@ -831,32 +856,29 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR
name, LPVOID
BOOL WINAPI WinHttpQueryHeaders( HINTERNET hrequest, DWORD level, LPCWSTR name, LPVOID
buffer, LPDWORD buflen, LPDWORD index )
{
BOOL ret;
- request_t *request;
+ struct request *request;
TRACE("%p, 0x%08x, %s, %p, %p, %p\n", hrequest, level, debugstr_w(name),
buffer, buflen, index);
- if (!(request = (request_t *)grab_object( hrequest )))
+ if (!(request = (struct request *)grab_object( hrequest )))
{
- set_last_error( ERROR_INVALID_HANDLE );
+ SetLastError( ERROR_INVALID_HANDLE );
return FALSE;
}
if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST)
{
release_object( &request->hdr );
- set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+ SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
return FALSE;
}
ret = query_headers( request, level, name, buffer, buflen, index );
release_object( &request->hdr );
- if (ret) set_last_error( ERROR_SUCCESS );
+ if (ret) SetLastError( ERROR_SUCCESS );
return ret;
}
-#undef ARRAYSIZE
-#define ARRAYSIZE(array) (sizeof(array) / sizeof((array)[0]))
-
static const WCHAR basicW[] =
{'B','a','s','i','c',0};
static const WCHAR ntlmW[] = {'N','T','L','M',0};
static const WCHAR passportW[] =
{'P','a','s','s','p','o','r','t',0};
@@ -871,27 +893,26 @@ static const struct
}
auth_schemes[] =
{
- { basicW, ARRAYSIZE(basicW) - 1, WINHTTP_AUTH_SCHEME_BASIC },
- { ntlmW, ARRAYSIZE(ntlmW) - 1, WINHTTP_AUTH_SCHEME_NTLM },
- { passportW, ARRAYSIZE(passportW) - 1, WINHTTP_AUTH_SCHEME_PASSPORT },
- { digestW, ARRAYSIZE(digestW) - 1, WINHTTP_AUTH_SCHEME_DIGEST },
- { negotiateW, ARRAYSIZE(negotiateW) - 1, WINHTTP_AUTH_SCHEME_NEGOTIATE }
+ { basicW, ARRAY_SIZE(basicW) - 1, WINHTTP_AUTH_SCHEME_BASIC },
+ { ntlmW, ARRAY_SIZE(ntlmW) - 1, WINHTTP_AUTH_SCHEME_NTLM },
+ { passportW, ARRAY_SIZE(passportW) - 1, WINHTTP_AUTH_SCHEME_PASSPORT },
+ { digestW, ARRAY_SIZE(digestW) - 1, WINHTTP_AUTH_SCHEME_DIGEST },
+ { negotiateW, ARRAY_SIZE(negotiateW) - 1, WINHTTP_AUTH_SCHEME_NEGOTIATE }
};
-static const unsigned int num_auth_schemes =
sizeof(auth_schemes)/sizeof(auth_schemes[0]);
static enum auth_scheme scheme_from_flag( DWORD flag )
{
int i;
- for (i = 0; i < num_auth_schemes; i++) if (flag == auth_schemes[i].scheme) return
i;
+ for (i = 0; i < ARRAY_SIZE( auth_schemes ); i++) if (flag ==
auth_schemes[i].scheme) return i;
return SCHEME_INVALID;
}
-static DWORD auth_scheme_from_header( WCHAR *header )
+static DWORD auth_scheme_from_header( const WCHAR *header )
{
unsigned int i;
- for (i = 0; i < num_auth_schemes; i++)
+ for (i = 0; i < ARRAY_SIZE( auth_schemes ); i++)
{
if (!strncmpiW( header, auth_schemes[i].str, auth_schemes[i].len ) &&
(header[auth_schemes[i].len] == ' ' || !header[auth_schemes[i].len]))
return auth_schemes[i].scheme;
@@ -899,7 +920,7 @@ static DWORD auth_scheme_from_header( WCHAR *header )
return 0;
}
-static BOOL query_auth_schemes( request_t *request, DWORD level, LPDWORD supported,
LPDWORD first )
+static BOOL query_auth_schemes( struct request *request, DWORD level, DWORD *supported,
DWORD *first )
{
DWORD index = 0, supported_schemes = 0, first_scheme = 0;
BOOL ret = FALSE;
@@ -911,9 +932,8 @@ static BOOL query_auth_schemes( request_t *request, DWORD level,
LPDWORD support
size = 0;
query_headers( request, level, NULL, NULL, &size, &index );
- if (get_last_error() != ERROR_INSUFFICIENT_BUFFER) break;
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) break;
- index--;
if (!(buffer = heap_alloc( size ))) return FALSE;
if (!query_headers( request, level, NULL, buffer, &size, &index ))
{
@@ -944,25 +964,25 @@ static BOOL query_auth_schemes( request_t *request, DWORD level,
LPDWORD support
BOOL WINAPI WinHttpQueryAuthSchemes( HINTERNET hrequest, LPDWORD supported, LPDWORD
first, LPDWORD target )
{
BOOL ret = FALSE;
- request_t *request;
+ struct request *request;
TRACE("%p, %p, %p, %p\n", hrequest, supported, first, target);
- if (!(request = (request_t *)grab_object( hrequest )))
+ if (!(request = (struct request *)grab_object( hrequest )))
{
- set_last_error( ERROR_INVALID_HANDLE );
+ SetLastError( ERROR_INVALID_HANDLE );
return FALSE;
}
if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST)
{
release_object( &request->hdr );
- set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+ SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
return FALSE;
}
if (!supported || !first || !target)
{
release_object( &request->hdr );
- set_last_error( ERROR_INVALID_PARAMETER );
+ SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
@@ -977,9 +997,10 @@ BOOL WINAPI WinHttpQueryAuthSchemes( HINTERNET hrequest, LPDWORD
supported, LPDW
*target = WINHTTP_AUTH_TARGET_PROXY;
ret = TRUE;
}
+ else SetLastError( ERROR_INVALID_OPERATION );
release_object( &request->hdr );
- if (ret) set_last_error( ERROR_SUCCESS );
+ if (ret) SetLastError( ERROR_SUCCESS );
return ret;
}
@@ -1127,7 +1148,7 @@ void destroy_authinfo( struct authinfo *authinfo )
heap_free( authinfo );
}
-static BOOL get_authvalue( request_t *request, DWORD level, DWORD scheme, WCHAR *buffer,
DWORD len )
+static BOOL get_authvalue( struct request *request, DWORD level, DWORD scheme, WCHAR
*buffer, DWORD len )
{
DWORD size, index = 0;
for (;;)
@@ -1139,7 +1160,7 @@ static BOOL get_authvalue( request_t *request, DWORD level, DWORD
scheme, WCHAR
return TRUE;
}
-static BOOL do_authorization( request_t *request, DWORD target, DWORD scheme_flag )
+static BOOL do_authorization( struct request *request, DWORD target, DWORD scheme_flag )
{
struct authinfo *authinfo, **auth_ptr;
enum auth_scheme scheme = scheme_from_flag( scheme_flag );
@@ -1368,129 +1389,76 @@ static BOOL do_authorization( request_t *request, DWORD target,
DWORD scheme_fla
return ret;
}
-static LPWSTR concatenate_string_list( LPCWSTR *list, int len )
+static WCHAR *build_proxy_connect_string( struct request *request )
{
- LPCWSTR *t;
- LPWSTR str;
-
- for( t = list; *t ; t++ )
- len += strlenW( *t );
- len++;
-
- str = heap_alloc( len * sizeof(WCHAR) );
- if (!str) return NULL;
- *str = 0;
+ static const WCHAR fmtW[] =
{'%','s',':','%','u',0};
+ static const WCHAR connectW[] =
{'C','O','N','N','E','C','T', 0};
+ static const WCHAR spaceW[] = {' ',0}, crlfW[] =
{'\r','\n',0}, colonW[] = {':',' ',0};
+ static const WCHAR twocrlfW[] =
{'\r','\n','\r','\n',0};
+ WCHAR *ret, *host;
+ unsigned int i;
+ int len;
- for( t = list; *t ; t++ )
- strcatW( str, *t );
+ if (!(host = heap_alloc( (strlenW( request->connect->hostname ) + 7) *
sizeof(WCHAR) ))) return NULL;
+ len = sprintfW( host, fmtW, request->connect->hostname,
request->connect->hostport );
- return str;
-}
+ len += ARRAY_SIZE(connectW);
+ len += ARRAY_SIZE(http1_1);
-static LPWSTR build_header_request_string( request_t *request, LPCWSTR verb,
- LPCWSTR path, LPCWSTR version )
-{
- static const WCHAR crlf[] = {'\r','\n',0};
- static const WCHAR space[] = { ' ',0 };
- static const WCHAR colon[] = { ':',' ',0 };
- static const WCHAR twocrlf[] = {'\r','\n','\r','\n',
0};
- LPWSTR requestString;
- DWORD len, n;
- LPCWSTR *req;
- UINT i;
- LPWSTR p;
-
- /* allocate space for an array of all the string pointers to be added */
- len = (request->num_headers) * 4 + 10;
- req = heap_alloc( len * sizeof(LPCWSTR) );
- if (!req) return NULL;
-
- /* add the verb, path and HTTP version string */
- n = 0;
- req[n++] = verb;
- req[n++] = space;
- req[n++] = path;
- req[n++] = space;
- req[n++] = version;
-
- /* Append custom request headers */
for (i = 0; i < request->num_headers; i++)
{
if (request->headers[i].is_request)
- {
- req[n++] = crlf;
- req[n++] = request->headers[i].field;
- req[n++] = colon;
- req[n++] = request->headers[i].value;
-
- TRACE("Adding custom header %s (%s)\n",
- debugstr_w(request->headers[i].field),
- debugstr_w(request->headers[i].value));
- }
+ len += strlenW( request->headers[i].field ) + strlenW(
request->headers[i].value ) + 4; /* '\r\n: ' */
}
+ len += 4; /* '\r\n\r\n' */
- if( n >= len )
- ERR("oops. buffer overrun\n");
-
- req[n] = NULL;
- requestString = concatenate_string_list( req, 4 );
- heap_free( req );
- if (!requestString) return NULL;
+ if ((ret = heap_alloc( (len + 1) * sizeof(WCHAR) )))
+ {
+ strcpyW( ret, connectW );
+ strcatW( ret, spaceW );
+ strcatW( ret, host );
+ strcatW( ret, spaceW );
+ strcatW( ret, http1_1 );
- /*
- * Set (header) termination string for request
- * Make sure there are exactly two new lines at the end of the request
- */
- p = &requestString[strlenW(requestString)-1];
- while ( (*p == '\n') || (*p == '\r') )
- p--;
- strcpyW( p+1, twocrlf );
+ for (i = 0; i < request->num_headers; i++)
+ {
+ if (request->headers[i].is_request)
+ {
+ strcatW( ret, crlfW );
+ strcatW( ret, request->headers[i].field );
+ strcatW( ret, colonW );
+ strcatW( ret, request->headers[i].value );
+ }
+ }
+ strcatW( ret, twocrlfW );
+ }
- return requestString;
+ heap_free( host );
+ return ret;
}
-static BOOL read_reply( request_t *request );
+static BOOL read_reply( struct request *request );
-static BOOL secure_proxy_connect( request_t *request )
+static BOOL secure_proxy_connect( struct request *request )
{
- static const WCHAR verbConnect[] =
{'C','O','N','N','E','C','T',0};
- static const WCHAR fmt[] =
{'%','s',':','%','u',0};
- BOOL ret = FALSE;
- LPWSTR path;
- connect_t *connect = request->connect;
-
- path = heap_alloc( (strlenW( connect->hostname ) + 13) * sizeof(WCHAR) );
- if (path)
- {
- LPWSTR requestString;
+ WCHAR *str;
+ char *strA;
+ int len, bytes_sent;
+ BOOL ret;
- sprintfW( path, fmt, connect->hostname, connect->hostport );
- requestString = build_header_request_string( request, verbConnect,
- path, http1_1 );
- heap_free( path );
- if (requestString)
- {
- LPSTR req_ascii = strdupWA( requestString );
+ if (!(str = build_proxy_connect_string( request ))) return FALSE;
+ strA = strdupWA( str );
+ heap_free( str );
+ if (!strA) return FALSE;
- heap_free( requestString );
- if (req_ascii)
- {
- int len = strlen( req_ascii ), bytes_sent;
+ len = strlen( strA );
+ ret = netconn_send( request->netconn, strA, len, &bytes_sent );
+ heap_free( strA );
+ if (ret) ret = read_reply( request );
- ret = netconn_send( request->netconn, req_ascii, len, &bytes_sent
);
- heap_free( req_ascii );
- if (ret)
- ret = read_reply( request );
- }
- }
- }
return ret;
}
-#ifndef INET6_ADDRSTRLEN
-#define INET6_ADDRSTRLEN 46
-#endif
-
static WCHAR *addr_to_str( struct sockaddr_storage *addr )
{
char buf[INET6_ADDRSTRLEN];
@@ -1523,7 +1491,7 @@ static CRITICAL_SECTION connection_pool_cs = {
&connection_pool_debug, -1, 0, 0,
static struct list connection_pool = LIST_INIT( connection_pool );
-void release_host( hostdata_t *host )
+void release_host( struct hostdata *host )
{
LONG ref;
@@ -1539,11 +1507,15 @@ void release_host( hostdata_t *host )
static BOOL connection_collector_running;
+#ifdef __REACTOS__
static DWORD WINAPI connection_collector(void *arg)
+#else
+static void CALLBACK connection_collector( TP_CALLBACK_INSTANCE *instance, void *ctx )
+#endif
{
unsigned int remaining_connections;
- netconn_t *netconn, *next_netconn;
- hostdata_t *host, *next_host;
+ struct netconn *netconn, *next_netconn;
+ struct hostdata *host, *next_host;
ULONGLONG now;
do
@@ -1555,9 +1527,9 @@ static DWORD WINAPI connection_collector(void *arg)
EnterCriticalSection(&connection_pool_cs);
- LIST_FOR_EACH_ENTRY_SAFE(host, next_host, &connection_pool, hostdata_t,
entry)
+ LIST_FOR_EACH_ENTRY_SAFE(host, next_host, &connection_pool, struct hostdata,
entry)
{
- LIST_FOR_EACH_ENTRY_SAFE(netconn, next_netconn, &host->connections,
netconn_t, entry)
+ LIST_FOR_EACH_ENTRY_SAFE(netconn, next_netconn, &host->connections,
struct netconn, entry)
{
if (netconn->keep_until < now)
{
@@ -1565,10 +1537,7 @@ static DWORD WINAPI connection_collector(void *arg)
list_remove(&netconn->entry);
netconn_close(netconn);
}
- else
- {
- remaining_connections++;
- }
+ else remaining_connections++;
}
}
@@ -1577,10 +1546,14 @@ static DWORD WINAPI connection_collector(void *arg)
LeaveCriticalSection(&connection_pool_cs);
} while(remaining_connections);
+#ifdef __REACTOS__
FreeLibraryAndExitThread( winhttp_instance, 0 );
+#else
+ FreeLibraryWhenCallbackReturns( instance, winhttp_instance );
+#endif
}
-static void cache_connection( netconn_t *netconn )
+static void cache_connection( struct netconn *netconn )
{
TRACE( "caching connection %p\n", netconn );
@@ -1592,10 +1565,13 @@ static void cache_connection( netconn_t *netconn )
if (!connection_collector_running)
{
HMODULE module;
+#ifdef __REACTOS__
HANDLE thread;
+#endif
- GetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (const
WCHAR*)winhttp_instance, &module );
+ GetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (const WCHAR
*)winhttp_instance, &module );
+#ifdef __REACTOS__
thread = CreateThread(NULL, 0, connection_collector, NULL, 0, NULL);
if (thread)
{
@@ -1606,6 +1582,10 @@ static void cache_connection( netconn_t *netconn )
{
FreeLibrary( winhttp_instance );
}
+#else
+ if (TrySubmitThreadpoolCallback( connection_collector, NULL, NULL ))
connection_collector_running = TRUE;
+ else FreeLibrary( winhttp_instance );
+#endif
}
LeaveCriticalSection( &connection_pool_cs );
@@ -1622,32 +1602,43 @@ static DWORD map_secure_protocols( DWORD mask )
return ret;
}
-static BOOL ensure_cred_handle( session_t *session )
+static BOOL ensure_cred_handle( struct request *request )
{
- SCHANNEL_CRED cred;
- SECURITY_STATUS status;
+ SECURITY_STATUS status = SEC_E_OK;
+
+ if (request->cred_handle_initialized) return TRUE;
- if (session->cred_handle_initialized) return TRUE;
+ if (!request->cred_handle_initialized)
+ {
+ SCHANNEL_CRED cred;
+ memset( &cred, 0, sizeof(cred) );
+ cred.dwVersion = SCHANNEL_CRED_VERSION;
+ cred.grbitEnabledProtocols = map_secure_protocols(
request->connect->session->secure_protocols );
+ if (request->client_cert)
+ {
+ cred.paCred = &request->client_cert;
+ cred.cCreds = 1;
+ }
+ status = AcquireCredentialsHandleW( NULL, (WCHAR *)UNISP_NAME_W,
SECPKG_CRED_OUTBOUND, NULL,
+ &cred, NULL, NULL,
&request->cred_handle, NULL );
+ if (status == SEC_E_OK)
+ request->cred_handle_initialized = TRUE;
+ }
- memset( &cred, 0, sizeof(cred) );
- cred.dwVersion = SCHANNEL_CRED_VERSION;
- cred.grbitEnabledProtocols = map_secure_protocols( session->secure_protocols );
- if ((status = AcquireCredentialsHandleW( NULL, (WCHAR *)UNISP_NAME_W,
SECPKG_CRED_OUTBOUND, NULL, &cred,
- NULL, NULL, &session->cred_handle,
NULL )) != SEC_E_OK)
+ if (status != SEC_E_OK)
{
WARN( "AcquireCredentialsHandleW failed: 0x%08x\n", status );
return FALSE;
}
- session->cred_handle_initialized = TRUE;
return TRUE;
}
-static BOOL open_connection( request_t *request )
+static BOOL open_connection( struct request *request )
{
BOOL is_secure = request->hdr.flags & WINHTTP_FLAG_SECURE;
- hostdata_t *host = NULL, *iter;
- netconn_t *netconn = NULL;
- connect_t *connect;
+ struct hostdata *host = NULL, *iter;
+ struct netconn *netconn = NULL;
+ struct connect *connect;
WCHAR *addressW = NULL;
INTERNET_PORT port;
DWORD len;
@@ -1659,7 +1650,7 @@ static BOOL open_connection( request_t *request )
EnterCriticalSection( &connection_pool_cs );
- LIST_FOR_EACH_ENTRY( iter, &connection_pool, hostdata_t, entry )
+ LIST_FOR_EACH_ENTRY( iter, &connection_pool, struct hostdata, entry )
{
if (iter->port == port && !strcmpW( connect->servername,
iter->hostname ) && !is_secure == !iter->secure)
{
@@ -1698,7 +1689,7 @@ static BOOL open_connection( request_t *request )
EnterCriticalSection( &connection_pool_cs );
if (!list_empty( &host->connections ))
{
- netconn = LIST_ENTRY( list_head( &host->connections ), netconn_t,
entry );
+ netconn = LIST_ENTRY( list_head( &host->connections ), struct netconn,
entry );
list_remove( &netconn->entry );
}
LeaveCriticalSection( &connection_pool_cs );
@@ -1756,7 +1747,10 @@ static BOOL open_connection( request_t *request )
return FALSE;
}
netconn_set_timeout( netconn, TRUE, request->send_timeout );
- netconn_set_timeout( netconn, FALSE, request->recv_timeout );
+ netconn_set_timeout( netconn, FALSE, request->receive_response_timeout );
+
+ request->netconn = netconn;
+
if (is_secure)
{
if (connect->session->proxy_server &&
@@ -1764,22 +1758,27 @@ static BOOL open_connection( request_t *request )
{
if (!secure_proxy_connect( request ))
{
+ request->netconn = NULL;
heap_free( addressW );
netconn_close( netconn );
return FALSE;
}
}
- if (!ensure_cred_handle( connect->session ) ||
+
+ CertFreeCertificateContext( request->server_cert );
+ request->server_cert = NULL;
+
+ if (!ensure_cred_handle( request ) ||
!netconn_secure_connect( netconn, connect->hostname,
request->security_flags,
- &connect->session->cred_handle ))
+ &request->cred_handle,
request->check_revocation ))
{
+ request->netconn = NULL;
heap_free( addressW );
netconn_close( netconn );
return FALSE;
}
}
- request->netconn = netconn;
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER,
addressW, strlenW(addressW) + 1 );
}
else
@@ -1787,10 +1786,17 @@ static BOOL open_connection( request_t *request )
TRACE("using connection %p\n", netconn);
netconn_set_timeout( netconn, TRUE, request->send_timeout );
- netconn_set_timeout( netconn, FALSE, request->recv_timeout );
+ netconn_set_timeout( netconn, FALSE, request->receive_response_timeout );
request->netconn = netconn;
}
+ if (netconn->secure && !(request->server_cert =
netconn_get_certificate( netconn )))
+ {
+ heap_free( addressW );
+ netconn_close( netconn );
+ return FALSE;
+ }
+
done:
request->read_pos = request->read_size = 0;
request->read_chunked = FALSE;
@@ -1800,7 +1806,7 @@ done:
return TRUE;
}
-void close_connection( request_t *request )
+void close_connection( struct request *request )
{
if (!request->netconn) return;
@@ -1810,13 +1816,13 @@ void close_connection( request_t *request )
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, 0, 0
);
}
-static BOOL add_host_header( request_t *request, DWORD modifier )
+static BOOL add_host_header( struct request *request, DWORD modifier )
{
BOOL ret;
DWORD len;
WCHAR *host;
static const WCHAR fmt[] =
{'%','s',':','%','u',0};
- connect_t *connect = request->connect;
+ struct connect *connect = request->connect;
INTERNET_PORT port;
port = connect->hostport ? connect->hostport : (request->hdr.flags &
WINHTTP_FLAG_SECURE ? 443 : 80);
@@ -1833,7 +1839,7 @@ static BOOL add_host_header( request_t *request, DWORD modifier )
return ret;
}
-static void clear_response_headers( request_t *request )
+static void clear_response_headers( struct request *request )
{
unsigned int i;
@@ -1848,14 +1854,14 @@ static void clear_response_headers( request_t *request )
}
/* remove some amount of data from the read buffer */
-static void remove_data( request_t *request, int count )
+static void remove_data( struct request *request, int count )
{
if (!(request->read_size -= count)) request->read_pos = 0;
else request->read_pos += count;
}
/* read some more data into the read buffer */
-static BOOL read_more_data( request_t *request, int maxlen, BOOL notify )
+static BOOL read_more_data( struct request *request, int maxlen, BOOL notify )
{
int len;
BOOL ret;
@@ -1882,7 +1888,7 @@ static BOOL read_more_data( request_t *request, int maxlen, BOOL
notify )
}
/* discard data contents until we reach end of line */
-static BOOL discard_eol( request_t *request, BOOL notify )
+static BOOL discard_eol( struct request *request, BOOL notify )
{
do
{
@@ -1899,7 +1905,7 @@ static BOOL discard_eol( request_t *request, BOOL notify )
}
/* read the size of the next chunk */
-static BOOL start_next_chunk( request_t *request, BOOL notify )
+static BOOL start_next_chunk( struct request *request, BOOL notify )
{
DWORD chunk_size = 0;
@@ -1942,7 +1948,7 @@ static BOOL start_next_chunk( request_t *request, BOOL notify )
}
}
-static BOOL refill_buffer( request_t *request, BOOL notify )
+static BOOL refill_buffer( struct request *request, BOOL notify )
{
int len = sizeof(request->read_buf);
@@ -1966,7 +1972,7 @@ static BOOL refill_buffer( request_t *request, BOOL notify )
return TRUE;
}
-static void finished_reading( request_t *request )
+static void finished_reading( struct request *request )
{
static const WCHAR closeW[] =
{'c','l','o','s','e',0};
@@ -1994,14 +2000,14 @@ static void finished_reading( request_t *request )
}
/* return the size of data available to be read immediately */
-static DWORD get_available_data( request_t *request )
+static DWORD get_available_data( struct request *request )
{
if (request->read_chunked) return min( request->read_chunked_size,
request->read_size );
return request->read_size;
}
/* check if we have reached the end of the data to read */
-static BOOL end_of_read_data( request_t *request )
+static BOOL end_of_read_data( struct request *request )
{
if (!request->content_length) return TRUE;
if (request->read_chunked) return request->read_chunked_eof;
@@ -2009,9 +2015,10 @@ static BOOL end_of_read_data( request_t *request )
return (request->content_length == request->content_read);
}
-static BOOL read_data( request_t *request, void *buffer, DWORD size, DWORD *read, BOOL
async )
+static BOOL read_data( struct request *request, void *buffer, DWORD size, DWORD *read,
BOOL async )
{
int count, bytes_read = 0;
+ BOOL ret = TRUE;
if (end_of_read_data( request )) goto done;
@@ -2019,7 +2026,7 @@ static BOOL read_data( request_t *request, void *buffer, DWORD size,
DWORD *read
{
if (!(count = get_available_data( request )))
{
- if (!refill_buffer( request, async )) goto done;
+ if (!(ret = refill_buffer( request, async ))) goto done;
if (!(count = get_available_data( request ))) goto done;
}
count = min( count, size );
@@ -2031,19 +2038,29 @@ static BOOL read_data( request_t *request, void *buffer, DWORD
size, DWORD *read
request->content_read += count;
if (end_of_read_data( request )) goto done;
}
- if (request->read_chunked && !request->read_chunked_size)
refill_buffer( request, async );
+ if (request->read_chunked && !request->read_chunked_size) ret =
refill_buffer( request, async );
done:
TRACE( "retrieved %u bytes (%u/%u)\n", bytes_read,
request->content_read, request->content_length );
+ if (async)
+ {
+ if (ret) send_callback( &request->hdr,
WINHTTP_CALLBACK_STATUS_READ_COMPLETE, buffer, bytes_read );
+ else
+ {
+ WINHTTP_ASYNC_RESULT result;
+ result.dwResult = API_READ_DATA;
+ result.dwError = GetLastError();
+ send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR,
&result, sizeof(result) );
+ }
+ }
- if (async) send_callback( &request->hdr,
WINHTTP_CALLBACK_STATUS_READ_COMPLETE, buffer, bytes_read );
- if (read) *read = bytes_read;
+ if (ret && read) *read = bytes_read;
if (end_of_read_data( request )) finished_reading( request );
- return TRUE;
+ return ret;
}
/* read any content returned by the server so that the connection can be reused */
-static void drain_content( request_t *request )
+static void drain_content( struct request *request )
{
DWORD size, bytes_read, bytes_total = 0, bytes_left = request->content_length -
request->content_read;
char buffer[2048];
@@ -2062,7 +2079,177 @@ static void drain_content( request_t *request )
}
}
-static BOOL send_request( request_t *request, LPCWSTR headers, DWORD headers_len, LPVOID
optional,
+enum escape_flags
+{
+ ESCAPE_FLAG_NON_PRINTABLE = 0x01,
+ ESCAPE_FLAG_SPACE = 0x02,
+ ESCAPE_FLAG_PERCENT = 0x04,
+ ESCAPE_FLAG_UNSAFE = 0x08,
+ ESCAPE_FLAG_DEL = 0x10,
+ ESCAPE_FLAG_8BIT = 0x20,
+ ESCAPE_FLAG_STRIP_CRLF = 0x40,
+};
+
+#define ESCAPE_MASK_DEFAULT (ESCAPE_FLAG_NON_PRINTABLE | ESCAPE_FLAG_SPACE |
ESCAPE_FLAG_UNSAFE |\
+ ESCAPE_FLAG_DEL | ESCAPE_FLAG_8BIT)
+#define ESCAPE_MASK_PERCENT (ESCAPE_FLAG_PERCENT | ESCAPE_MASK_DEFAULT)
+#define ESCAPE_MASK_DISABLE (ESCAPE_FLAG_SPACE | ESCAPE_FLAG_8BIT |
ESCAPE_FLAG_STRIP_CRLF)
+
+static inline BOOL need_escape( char ch, enum escape_flags flags )
+{
+ static const char unsafe[] = "\"#<>[\\]^`{|}";
+ const char *ptr = unsafe;
+
+ if ((flags & ESCAPE_FLAG_SPACE) && ch == ' ') return TRUE;
+ if ((flags & ESCAPE_FLAG_PERCENT) && ch == '%') return TRUE;
+ if ((flags & ESCAPE_FLAG_NON_PRINTABLE) && ch < 0x20) return TRUE;
+ if ((flags & ESCAPE_FLAG_DEL) && ch == 0x7f) return TRUE;
+ if ((flags & ESCAPE_FLAG_8BIT) && (ch & 0x80)) return TRUE;
+ if ((flags & ESCAPE_FLAG_UNSAFE)) while (*ptr) { if (ch == *ptr++) return TRUE;
}
+ return FALSE;
+}
+
+static DWORD escape_string( const char *src, DWORD len, char *dst, enum escape_flags
flags )
+{
+ static const char hex[] = "0123456789ABCDEF";
+ DWORD i, ret = len;
+ char *ptr = dst;
+
+ for (i = 0; i < len; i++)
+ {
+ if ((flags & ESCAPE_FLAG_STRIP_CRLF) && (src[i] == '\r' ||
src[i] == '\n'))
+ {
+ ret--;
+ continue;
+ }
+ if (need_escape( src[i], flags ))
+ {
+ if (dst)
+ {
+ ptr[0] = '%';
+ ptr[1] = hex[(src[i] >> 4) & 0xf];
+ ptr[2] = hex[src[i] & 0xf];
+ ptr += 3;
+ }
+ ret += 2;
+ }
+ else if (dst) *ptr++ = src[i];
+ }
+
+ if (dst) dst[ret] = 0;
+ return ret;
+}
+
+static DWORD str_to_wire( const WCHAR *src, int src_len, char *dst, enum escape_flags
flags )
+{
+ DWORD len;
+ char *utf8;
+
+ if (src_len < 0) src_len = strlenW( src );
+ len = WideCharToMultiByte( CP_UTF8, 0, src, src_len, NULL, 0, NULL, NULL );
+ if (!(utf8 = heap_alloc( len ))) return 0;
+
+ WideCharToMultiByte( CP_UTF8, 0, src, -1, utf8, len, NULL, NULL );
+ len = escape_string( utf8, len, dst, flags );
+ heap_free( utf8 );
+
+ return len;
+}
+
+static char *build_wire_path( struct request *request, DWORD *ret_len )
+{
+ WCHAR *full_path;
+ const WCHAR *start, *path, *query = NULL;
+ DWORD len, len_path = 0, len_query = 0;
+ enum escape_flags path_flags, query_flags;
+ char *ret;
+
+ if (!strcmpiW( request->connect->hostname, request->connect->servername
)) start = full_path = request->path;
+ else if (!(full_path = build_absolute_request_path( request, &start ))) return
NULL;
+
+ len = strlenW( full_path );
+ if ((path = strchrW( start, '/' )))
+ {
+ len_path = strlenW( path );
+ if ((query = strchrW( path, '?' )))
+ {
+ len_query = strlenW( query );
+ len_path -= len_query;
+ }
+ }
+
+ if (request->hdr.flags & WINHTTP_FLAG_ESCAPE_DISABLE) path_flags =
ESCAPE_MASK_DISABLE;
+ else if (request->hdr.flags & WINHTTP_FLAG_ESCAPE_PERCENT) path_flags =
ESCAPE_MASK_PERCENT;
+ else path_flags = ESCAPE_MASK_DEFAULT;
+
+ if (request->hdr.flags & WINHTTP_FLAG_ESCAPE_DISABLE_QUERY) query_flags =
ESCAPE_MASK_DISABLE;
+ else query_flags = path_flags;
+
+ *ret_len = str_to_wire( full_path, len - len_path - len_query, NULL, 0 );
+ if (path) *ret_len += str_to_wire( path, len_path, NULL, path_flags );
+ if (query) *ret_len += str_to_wire( query, len_query, NULL, query_flags );
+
+ if ((ret = heap_alloc( *ret_len + 1 )))
+ {
+ len = str_to_wire( full_path, len - len_path - len_query, ret, 0 );
+ if (path) len += str_to_wire( path, len_path, ret + len, path_flags );
+ if (query) str_to_wire( query, len_query, ret + len, query_flags );
+ }
+
+ if (full_path != request->path) heap_free( full_path );
+ return ret;
+}
+
+static char *build_wire_request( struct request *request, DWORD *len )
+{
+ char *path, *ptr, *ret;
+ DWORD i, len_path;
+
+ if (!(path = build_wire_path( request, &len_path ))) return NULL;
+
+ *len = str_to_wire( request->verb, -1, NULL, 0 ) + 1; /* ' ' */
+ *len += len_path + 1; /* ' ' */
+ *len += str_to_wire( request->version, -1, NULL, 0 );
+
+ for (i = 0; i < request->num_headers; i++)
+ {
+ if (request->headers[i].is_request)
+ {
+ *len += str_to_wire( request->headers[i].field, -1, NULL, 0 ) + 2; /*
': ' */
+ *len += str_to_wire( request->headers[i].value, -1, NULL, 0 ) + 2; /*
'\r\n' */
+ }
+ }
+ *len += 4; /* '\r\n\r\n' */
+
+ if ((ret = ptr = heap_alloc( *len + 1 )))
+ {
+ ptr += str_to_wire( request->verb, -1, ptr, 0 );
+ *ptr++ = ' ';
+ memcpy( ptr, path, len_path );
+ ptr += len_path;
+ *ptr++ = ' ';
+ ptr += str_to_wire( request->version, -1, ptr, 0 );
+
+ for (i = 0; i < request->num_headers; i++)
+ {
+ if (request->headers[i].is_request)
+ {
+ *ptr++ = '\r';
+ *ptr++ = '\n';
+ ptr += str_to_wire( request->headers[i].field, -1, ptr, 0 );
+ *ptr++ = ':';
+ *ptr++ = ' ';
+ ptr += str_to_wire( request->headers[i].value, -1, ptr, 0 );
+ }
+ }
+ memcpy( ptr, "\r\n\r\n", sizeof("\r\n\r\n") );
+ }
+
+ heap_free( path );
+ return ret;
+}
+
+static BOOL send_request( struct request *request, const WCHAR *headers, DWORD
headers_len, void *optional,
DWORD optional_len, DWORD total_len, DWORD_PTR context, BOOL
async )
{
static const WCHAR keep_alive[] =
{'K','e','e','p','-','A','l','i','v','e',0};
@@ -2070,10 +2257,9 @@ static BOOL send_request( request_t *request, LPCWSTR headers,
DWORD headers_len
static const WCHAR length_fmt[] = {'%','l','d',0};
BOOL ret = FALSE;
- connect_t *connect = request->connect;
- session_t *session = connect->session;
- WCHAR *req = NULL;
- char *req_ascii;
+ struct connect *connect = request->connect;
+ struct session *session = connect->session;
+ char *wire_req;
int bytes_sent;
DWORD len;
@@ -2118,16 +2304,13 @@ static BOOL send_request( request_t *request, LPCWSTR headers,
DWORD headers_len
if (context) request->hdr.context = context;
if (!(ret = open_connection( request ))) goto end;
- if (!(req = build_request_string( request ))) goto end;
-
- if (!(req_ascii = strdupWA( req ))) goto end;
- TRACE("full request: %s\n", debugstr_a(req_ascii));
- len = strlen(req_ascii);
+ if (!(wire_req = build_wire_request( request, &len ))) goto end;
+ TRACE("full request: %s\n", debugstr_a(wire_req));
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST, NULL, 0
);
- ret = netconn_send( request->netconn, req_ascii, len, &bytes_sent );
- heap_free( req_ascii );
+ ret = netconn_send( request->netconn, wire_req, len, &bytes_sent );
+ heap_free( wire_req );
if (!ret) goto end;
if (optional_len)
@@ -2147,17 +2330,16 @@ end:
{
WINHTTP_ASYNC_RESULT result;
result.dwResult = API_SEND_REQUEST;
- result.dwError = get_last_error();
+ result.dwError = GetLastError();
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR,
&result, sizeof(result) );
}
}
- heap_free( req );
return ret;
}
-static void task_send_request( task_header_t *task )
+static void task_send_request( struct task_header *task )
{
- send_request_t *s = (send_request_t *)task;
+ struct send_request *s = (struct send_request *)task;
send_request( s->hdr.request, s->headers, s->headers_len, s->optional,
s->optional_len, s->total_len, s->context, TRUE );
heap_free( s->headers );
}
@@ -2169,20 +2351,20 @@ BOOL WINAPI WinHttpSendRequest( HINTERNET hrequest, LPCWSTR
headers, DWORD heade
LPVOID optional, DWORD optional_len, DWORD total_len,
DWORD_PTR context )
{
BOOL ret;
- request_t *request;
+ struct request *request;
- TRACE("%p, %s, %u, %u, %u, %lx\n", hrequest, debugstr_wn(headers,
headers_len), headers_len, optional_len,
- total_len, context);
+ TRACE("%p, %s, %u, %p, %u, %u, %lx\n", hrequest, debugstr_wn(headers,
headers_len), headers_len, optional,
+ optional_len, total_len, context);
- if (!(request = (request_t *)grab_object( hrequest )))
+ if (!(request = (struct request *)grab_object( hrequest )))
{
- set_last_error( ERROR_INVALID_HANDLE );
+ SetLastError( ERROR_INVALID_HANDLE );
return FALSE;
}
if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST)
{
release_object( &request->hdr );
- set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+ SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
return FALSE;
}
@@ -2190,9 +2372,9 @@ BOOL WINAPI WinHttpSendRequest( HINTERNET hrequest, LPCWSTR headers,
DWORD heade
if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC)
{
- send_request_t *s;
+ struct send_request *s;
- if (!(s = heap_alloc( sizeof(send_request_t) ))) return FALSE;
+ if (!(s = heap_alloc( sizeof(struct send_request) ))) return FALSE;
s->hdr.request = request;
s->hdr.proc = task_send_request;
s->headers = strdupW( headers );
@@ -2203,24 +2385,24 @@ BOOL WINAPI WinHttpSendRequest( HINTERNET hrequest, LPCWSTR
headers, DWORD heade
s->context = context;
addref_object( &request->hdr );
- ret = queue_task( (task_header_t *)s );
+ ret = queue_task( (struct task_header *)s );
}
else
ret = send_request( request, headers, headers_len, optional, optional_len,
total_len, context, FALSE );
release_object( &request->hdr );
- if (ret) set_last_error( ERROR_SUCCESS );
+ if (ret) SetLastError( ERROR_SUCCESS );
return ret;
}
-static BOOL set_credentials( request_t *request, DWORD target, DWORD scheme_flag, const
WCHAR *username,
+static BOOL set_credentials( struct request *request, DWORD target, DWORD scheme_flag,
const WCHAR *username,
const WCHAR *password )
{
enum auth_scheme scheme = scheme_from_flag( scheme_flag );
if (scheme == SCHEME_INVALID || ((scheme == SCHEME_BASIC || scheme == SCHEME_DIGEST)
&& (!username || !password)))
{
- set_last_error( ERROR_INVALID_PARAMETER );
+ SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
switch (target)
@@ -2261,30 +2443,30 @@ BOOL WINAPI WinHttpSetCredentials( HINTERNET hrequest, DWORD
target, DWORD schem
LPCWSTR password, LPVOID params )
{
BOOL ret;
- request_t *request;
+ struct request *request;
TRACE("%p, %x, 0x%08x, %s, %p, %p\n", hrequest, target, scheme,
debugstr_w(username), password, params);
- if (!(request = (request_t *)grab_object( hrequest )))
+ if (!(request = (struct request *)grab_object( hrequest )))
{
- set_last_error( ERROR_INVALID_HANDLE );
+ SetLastError( ERROR_INVALID_HANDLE );
return FALSE;
}
if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST)
{
release_object( &request->hdr );
- set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+ SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
return FALSE;
}
ret = set_credentials( request, target, scheme, username, password );
release_object( &request->hdr );
- if (ret) set_last_error( ERROR_SUCCESS );
+ if (ret) SetLastError( ERROR_SUCCESS );
return ret;
}
-static BOOL handle_authorization( request_t *request, DWORD status )
+static BOOL handle_authorization( struct request *request, DWORD status )
{
DWORD i, schemes, first, level, target;
@@ -2309,7 +2491,7 @@ static BOOL handle_authorization( request_t *request, DWORD status
)
if (do_authorization( request, target, first )) return TRUE;
schemes &= ~first;
- for (i = 0; i < num_auth_schemes; i++)
+ for (i = 0; i < ARRAY_SIZE( auth_schemes ); i++)
{
if (!(schemes & auth_schemes[i].scheme)) continue;
if (do_authorization( request, target, auth_schemes[i].scheme )) return TRUE;
@@ -2318,7 +2500,7 @@ static BOOL handle_authorization( request_t *request, DWORD status
)
}
/* set the request content length based on the headers */
-static DWORD set_content_length( request_t *request, DWORD status )
+static DWORD set_content_length( struct request *request, DWORD status )
{
WCHAR encoding[20];
DWORD buflen = sizeof(request->content_length);
@@ -2345,7 +2527,7 @@ static DWORD set_content_length( request_t *request, DWORD status )
return request->content_length;
}
-static BOOL read_line( request_t *request, char *buffer, DWORD *len )
+static BOOL read_line( struct request *request, char *buffer, DWORD *len )
{
int count, bytes_read, pos = 0;
@@ -2386,7 +2568,7 @@ static BOOL read_line( request_t *request, char *buffer, DWORD *len
)
#define MAX_REPLY_LEN 1460
#define INITIAL_HEADER_BUFFER_LEN 512
-static BOOL read_reply( request_t *request )
+static BOOL read_reply( struct request *request )
{
static const WCHAR crlf[] = {'\r','\n',0};
@@ -2450,7 +2632,7 @@ static BOOL read_reply( request_t *request )
offset = buflen + crlf_len - 1;
for (;;)
{
- header_t *header;
+ struct header *header;
buflen = MAX_REPLY_LEN;
if (!read_line( request, buffer, &buflen )) return TRUE;
@@ -2485,13 +2667,13 @@ static BOOL read_reply( request_t *request )
return TRUE;
}
-static void record_cookies( request_t *request )
+static void record_cookies( struct request *request )
{
unsigned int i;
for (i = 0; i < request->num_headers; i++)
{
- header_t *set_cookie = &request->headers[i];
+ struct header *set_cookie = &request->headers[i];
if (!strcmpiW( set_cookie->field, attr_set_cookie ) &&
!set_cookie->is_request)
{
set_cookies( request, set_cookie->value );
@@ -2499,59 +2681,60 @@ static void record_cookies( request_t *request )
}
}
-static WCHAR *get_redirect_url( request_t *request, DWORD *len )
+static WCHAR *get_redirect_url( struct request *request, DWORD *len )
{
DWORD size;
WCHAR *ret;
query_headers( request, WINHTTP_QUERY_LOCATION, NULL, NULL, &size, NULL );
- if (get_last_error() != ERROR_INSUFFICIENT_BUFFER) return FALSE;
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return NULL;
if (!(ret = heap_alloc( size ))) return NULL;
- *len = size / sizeof(WCHAR);
+ *len = size / sizeof(WCHAR) - 1;
if (query_headers( request, WINHTTP_QUERY_LOCATION, NULL, ret, &size, NULL ))
return ret;
heap_free( ret );
return NULL;
}
-static BOOL handle_redirect( request_t *request, DWORD status )
+static BOOL handle_redirect( struct request *request, DWORD status )
{
BOOL ret = FALSE;
- DWORD len, len_url;
+ DWORD len, len_loc;
URL_COMPONENTS uc;
- connect_t *connect = request->connect;
+ struct connect *connect = request->connect;
INTERNET_PORT port;
WCHAR *hostname = NULL, *location;
int index;
- if (!(location = get_redirect_url( request, &len_url ))) return FALSE;
+ if (!(location = get_redirect_url( request, &len_loc ))) return FALSE;
memset( &uc, 0, sizeof(uc) );
uc.dwStructSize = sizeof(uc);
uc.dwSchemeLength = uc.dwHostNameLength = uc.dwUrlPathLength = uc.dwExtraInfoLength =
~0u;
- if (!WinHttpCrackUrl( location, len_url, 0, &uc )) /* assume relative redirect
*/
+ if (!WinHttpCrackUrl( location, len_loc, 0, &uc )) /* assume relative redirect
*/
{
WCHAR *path, *p;
if (location[0] == '/')
{
- len = strlenW( location );
- if (!(path = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end;
- strcpyW( path, location );
+ if (!(path = heap_alloc( (len_loc + 1) * sizeof(WCHAR) ))) goto end;
+ memcpy( path, location, len_loc * sizeof(WCHAR) );
+ path[len_loc] = 0;
}
else
{
if ((p = strrchrW( request->path, '/' ))) *p = 0;
- len = strlenW( request->path ) + 1 + strlenW( location );
+ len = strlenW( request->path ) + 1 + len_loc;
if (!(path = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end;
strcpyW( path, request->path );
strcatW( path, slashW );
- strcatW( path, location );
+ memcpy( path + strlenW(path), location, len_loc * sizeof(WCHAR) );
+ path[len_loc] = 0;
}
heap_free( request->path );
request->path = path;
- send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REDIRECT, location,
len_url + 1 );
+ send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REDIRECT, location,
len_loc + 1 );
}
else
{
@@ -2567,7 +2750,7 @@ static BOOL handle_redirect( request_t *request, DWORD status )
request->hdr.flags |= WINHTTP_FLAG_SECURE;
}
- send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REDIRECT, location,
len_url + 1 );
+ send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REDIRECT, location,
len_loc + 1 );
len = uc.dwHostNameLength;
if (!(hostname = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end;
@@ -2599,7 +2782,8 @@ static BOOL handle_redirect( request_t *request, DWORD status )
{
len = uc.dwUrlPathLength + uc.dwExtraInfoLength;
if (!(request->path = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end;
- strcpyW( request->path, uc.lpszUrlPath );
+ memcpy( request->path, uc.lpszUrlPath, (len + 1) * sizeof(WCHAR) );
+ request->path[len] = 0;
}
else request->path = strdupW( slashW );
}
@@ -2622,16 +2806,59 @@ end:
return ret;
}
-static BOOL receive_response( request_t *request, BOOL async )
+static BOOL is_passport_request( struct request *request )
+{
+ static const WCHAR passportW[] =
{'P','a','s','s','p','o','r','t','1','.','4'};
+ WCHAR buf[1024];
+ DWORD len = ARRAY_SIZE(buf);
+
+ if (!(request->connect->session->passport_flags &
WINHTTP_ENABLE_PASSPORT_AUTH) ||
+ !query_headers( request, WINHTTP_QUERY_WWW_AUTHENTICATE, NULL, buf, &len,
NULL )) return FALSE;
+
+ if (!strncmpiW( buf, passportW, ARRAY_SIZE(passportW) ) &&
+ (buf[ARRAY_SIZE(passportW)] == ' ' || !buf[ARRAY_SIZE(passportW)]))
return TRUE;
+
+ return FALSE;
+}
+
+static BOOL handle_passport_redirect( struct request *request )
+{
+ static const WCHAR status401W[] = {'4','0','1',0};
+ DWORD flags = WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE;
+ int i, len = strlenW( request->raw_headers );
+ WCHAR *p = request->raw_headers;
+
+ if (!process_header( request, attr_status, status401W, flags, FALSE )) return FALSE;
+
+ for (i = 0; i < len; i++)
+ {
+ if (i <= len - 3 && p[i] == '3' && p[i + 1] ==
'0' && p[i + 2] == '2')
+ {
+ p[i] = '4';
+ p[i + 2] = '1';
+ break;
+ }
+ }
+ return TRUE;
+}
+
+static BOOL receive_response( struct request *request, BOOL async )
{
BOOL ret;
DWORD size, query, status;
+ if (!request->netconn)
+ {
+ SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_STATE );
+ return FALSE;
+ }
+
+ netconn_set_timeout( request->netconn, FALSE, request->receive_response_timeout
);
for (;;)
{
if (!(ret = read_reply( request )))
{
- set_last_error( ERROR_WINHTTP_INVALID_SERVER_RESPONSE );
+ SetLastError( ERROR_WINHTTP_INVALID_SERVER_RESPONSE );
break;
}
size = sizeof(DWORD);
@@ -2642,7 +2869,11 @@ static BOOL receive_response( request_t *request, BOOL async )
if (!(request->hdr.disable_flags & WINHTTP_DISABLE_COOKIES))
record_cookies( request );
- if (status == HTTP_STATUS_MOVED || status == HTTP_STATUS_REDIRECT || status ==
HTTP_STATUS_REDIRECT_KEEP_VERB)
+ if (status == HTTP_STATUS_REDIRECT && is_passport_request( request ))
+ {
+ ret = handle_passport_redirect( request );
+ }
+ else if (status == HTTP_STATUS_MOVED || status == HTTP_STATUS_REDIRECT || status
== HTTP_STATUS_REDIRECT_KEEP_VERB)
{
if (request->hdr.disable_flags & WINHTTP_DISABLE_REDIRECTS ||
request->hdr.redirect_policy == WINHTTP_OPTION_REDIRECT_POLICY_NEVER)
break;
@@ -2664,7 +2895,8 @@ static BOOL receive_response( request_t *request, BOOL async )
break;
}
- if (request->content_length) refill_buffer( request, FALSE );
+ netconn_set_timeout( request->netconn, FALSE, request->receive_timeout );
+ if (request->content_length) ret = refill_buffer( request, FALSE );
if (async)
{
@@ -2673,16 +2905,16 @@ static BOOL receive_response( request_t *request, BOOL async )
{
WINHTTP_ASYNC_RESULT result;
result.dwResult = API_RECEIVE_RESPONSE;
- result.dwError = get_last_error();
+ result.dwError = GetLastError();
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR,
&result, sizeof(result) );
}
}
return ret;
}
-static void task_receive_response( task_header_t *task )
+static void task_receive_response( struct task_header *task )
{
- receive_response_t *r = (receive_response_t *)task;
+ struct receive_response *r = (struct receive_response *)task;
receive_response( r->hdr.request, TRUE );
}
@@ -2692,68 +2924,78 @@ static void task_receive_response( task_header_t *task )
BOOL WINAPI WinHttpReceiveResponse( HINTERNET hrequest, LPVOID reserved )
{
BOOL ret;
- request_t *request;
+ struct request *request;
TRACE("%p, %p\n", hrequest, reserved);
- if (!(request = (request_t *)grab_object( hrequest )))
+ if (!(request = (struct request *)grab_object( hrequest )))
{
- set_last_error( ERROR_INVALID_HANDLE );
+ SetLastError( ERROR_INVALID_HANDLE );
return FALSE;
}
if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST)
{
release_object( &request->hdr );
- set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+ SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
return FALSE;
}
if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC)
{
- receive_response_t *r;
+ struct receive_response *r;
- if (!(r = heap_alloc( sizeof(receive_response_t) ))) return FALSE;
+ if (!(r = heap_alloc( sizeof(struct receive_response) ))) return FALSE;
r->hdr.request = request;
r->hdr.proc = task_receive_response;
addref_object( &request->hdr );
- ret = queue_task( (task_header_t *)r );
+ ret = queue_task( (struct task_header *)r );
}
else
ret = receive_response( request, FALSE );
release_object( &request->hdr );
- if (ret) set_last_error( ERROR_SUCCESS );
+ if (ret) SetLastError( ERROR_SUCCESS );
return ret;
}
-static BOOL query_data_available( request_t *request, DWORD *available, BOOL async )
+static BOOL query_data_available( struct request *request, DWORD *available, BOOL async
)
{
DWORD count = 0;
+ BOOL ret = TRUE;
if (end_of_read_data( request )) goto done;
count = get_available_data( request );
- if (!request->read_chunked && request->netconn)
- count += netconn_query_data_available( request->netconn );
+ if (!request->read_chunked && request->netconn) count +=
netconn_query_data_available( request->netconn );
if (!count)
{
- refill_buffer( request, async );
+ if (!(ret = refill_buffer( request, async ))) goto done;
count = get_available_data( request );
- if (!request->read_chunked && request->netconn)
- count += netconn_query_data_available( request->netconn );
+ if (!request->read_chunked && request->netconn) count +=
netconn_query_data_available( request->netconn );
}
done:
- if (async) send_callback( &request->hdr,
WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE, &count, sizeof(count) );
TRACE("%u bytes available\n", count);
- if (available) *available = count;
- return TRUE;
+ if (async)
+ {
+ if (ret) send_callback( &request->hdr,
WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE, &count, sizeof(count) );
+ else
+ {
+ WINHTTP_ASYNC_RESULT result;
+ result.dwResult = API_QUERY_DATA_AVAILABLE;
+ result.dwError = GetLastError();
+ send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR,
&result, sizeof(result) );
+ }
+ }
+
+ if (ret && available) *available = count;
+ return ret;
}
-static void task_query_data_available( task_header_t *task )
+static void task_query_data_available( struct task_header *task )
{
- query_data_t *q = (query_data_t *)task;
+ struct query_data *q = (struct query_data *)task;
query_data_available( q->hdr.request, q->available, TRUE );
}
@@ -2763,45 +3005,45 @@ static void task_query_data_available( task_header_t *task )
BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available )
{
BOOL ret;
- request_t *request;
+ struct request *request;
TRACE("%p, %p\n", hrequest, available);
- if (!(request = (request_t *)grab_object( hrequest )))
+ if (!(request = (struct request *)grab_object( hrequest )))
{
- set_last_error( ERROR_INVALID_HANDLE );
+ SetLastError( ERROR_INVALID_HANDLE );
return FALSE;
}
if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST)
{
release_object( &request->hdr );
- set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+ SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
return FALSE;
}
if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC)
{
- query_data_t *q;
+ struct query_data *q;
- if (!(q = heap_alloc( sizeof(query_data_t) ))) return FALSE;
+ if (!(q = heap_alloc( sizeof(struct query_data) ))) return FALSE;
q->hdr.request = request;
q->hdr.proc = task_query_data_available;
q->available = available;
addref_object( &request->hdr );
- ret = queue_task( (task_header_t *)q );
+ ret = queue_task( (struct task_header *)q );
}
else
ret = query_data_available( request, available, FALSE );
release_object( &request->hdr );
- if (ret) set_last_error( ERROR_SUCCESS );
+ if (ret) SetLastError( ERROR_SUCCESS );
return ret;
}
-static void task_read_data( task_header_t *task )
+static void task_read_data( struct task_header *task )
{
- read_data_t *r = (read_data_t *)task;
+ struct read_data *r = (struct read_data *)task;
read_data( r->hdr.request, r->buffer, r->to_read, r->read, TRUE );
}
@@ -2811,27 +3053,27 @@ static void task_read_data( task_header_t *task )
BOOL WINAPI WinHttpReadData( HINTERNET hrequest, LPVOID buffer, DWORD to_read, LPDWORD
read )
{
BOOL ret;
- request_t *request;
+ struct request *request;
TRACE("%p, %p, %d, %p\n", hrequest, buffer, to_read, read);
- if (!(request = (request_t *)grab_object( hrequest )))
+ if (!(request = (struct request *)grab_object( hrequest )))
{
- set_last_error( ERROR_INVALID_HANDLE );
+ SetLastError( ERROR_INVALID_HANDLE );
return FALSE;
}
if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST)
{
release_object( &request->hdr );
- set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+ SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
return FALSE;
}
if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC)
{
- read_data_t *r;
+ struct read_data *r;
- if (!(r = heap_alloc( sizeof(read_data_t) ))) return FALSE;
+ if (!(r = heap_alloc( sizeof(struct read_data) ))) return FALSE;
r->hdr.request = request;
r->hdr.proc = task_read_data;
r->buffer = buffer;
@@ -2839,17 +3081,17 @@ BOOL WINAPI WinHttpReadData( HINTERNET hrequest, LPVOID buffer,
DWORD to_read, L
r->read = read;
addref_object( &request->hdr );
- ret = queue_task( (task_header_t *)r );
+ ret = queue_task( (struct task_header *)r );
}
else
ret = read_data( request, buffer, to_read, read, FALSE );
release_object( &request->hdr );
- if (ret) set_last_error( ERROR_SUCCESS );
+ if (ret) SetLastError( ERROR_SUCCESS );
return ret;
}
-static BOOL write_data( request_t *request, LPCVOID buffer, DWORD to_write, LPDWORD
written, BOOL async )
+static BOOL write_data( struct request *request, const void *buffer, DWORD to_write,
DWORD *written, BOOL async )
{
BOOL ret;
int num_bytes;
@@ -2863,7 +3105,7 @@ static BOOL write_data( request_t *request, LPCVOID buffer, DWORD
to_write, LPDW
{
WINHTTP_ASYNC_RESULT result;
result.dwResult = API_WRITE_DATA;
- result.dwError = get_last_error();
+ result.dwError = GetLastError();
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR,
&result, sizeof(result) );
}
}
@@ -2871,9 +3113,9 @@ static BOOL write_data( request_t *request, LPCVOID buffer, DWORD
to_write, LPDW
return ret;
}
-static void task_write_data( task_header_t *task )
+static void task_write_data( struct task_header *task )
{
- write_data_t *w = (write_data_t *)task;
+ struct write_data *w = (struct write_data *)task;
write_data( w->hdr.request, w->buffer, w->to_write, w->written, TRUE );
}
@@ -2883,27 +3125,27 @@ static void task_write_data( task_header_t *task )
BOOL WINAPI WinHttpWriteData( HINTERNET hrequest, LPCVOID buffer, DWORD to_write, LPDWORD
written )
{
BOOL ret;
- request_t *request;
+ struct request *request;
TRACE("%p, %p, %d, %p\n", hrequest, buffer, to_write, written);
- if (!(request = (request_t *)grab_object( hrequest )))
+ if (!(request = (struct request *)grab_object( hrequest )))
{
- set_last_error( ERROR_INVALID_HANDLE );
+ SetLastError( ERROR_INVALID_HANDLE );
return FALSE;
}
if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST)
{
release_object( &request->hdr );
- set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+ SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
return FALSE;
}
if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC)
{
- write_data_t *w;
+ struct write_data *w;
- if (!(w = heap_alloc( sizeof(write_data_t) ))) return FALSE;
+ if (!(w = heap_alloc( sizeof(struct write_data) ))) return FALSE;
w->hdr.request = request;
w->hdr.proc = task_write_data;
w->buffer = buffer;
@@ -2911,19 +3153,18 @@ BOOL WINAPI WinHttpWriteData( HINTERNET hrequest, LPCVOID buffer,
DWORD to_write
w->written = written;
addref_object( &request->hdr );
- ret = queue_task( (task_header_t *)w );
+ ret = queue_task( (struct task_header *)w );
}
else
ret = write_data( request, buffer, to_write, written, FALSE );
release_object( &request->hdr );
- if (ret) set_last_error( ERROR_SUCCESS );
+ if (ret) SetLastError( ERROR_SUCCESS );
return ret;
}
enum request_state
{
- REQUEST_STATE_UNINITIALIZED,
REQUEST_STATE_INITIALIZED,
REQUEST_STATE_CANCELLED,
REQUEST_STATE_OPEN,
@@ -2942,9 +3183,16 @@ struct winhttp_request
HINTERNET hrequest;
VARIANT data;
WCHAR *verb;
+#ifdef __REACTOS__
HANDLE thread;
+#else
+ HANDLE done;
+#endif
HANDLE wait;
HANDLE cancel;
+#ifndef __REACTOS__
+ BOOL proc_running;
+#endif
char *buffer;
DWORD offset;
DWORD bytes_available;
@@ -2978,6 +3226,7 @@ static void cancel_request( struct winhttp_request *request )
{
if (request->state <= REQUEST_STATE_CANCELLED) return;
+#ifdef __REACTOS__
SetEvent( request->cancel );
LeaveCriticalSection( &request->cs );
WaitForSingleObject( request->thread, INFINITE );
@@ -2987,10 +3236,18 @@ static void cancel_request( struct winhttp_request *request )
CloseHandle( request->thread );
request->thread = NULL;
- CloseHandle( request->wait );
- request->wait = NULL;
- CloseHandle( request->cancel );
- request->cancel = NULL;
+#else
+ if (request->proc_running)
+ {
+ SetEvent( request->cancel );
+ LeaveCriticalSection( &request->cs );
+
+ WaitForSingleObject( request->done, INFINITE );
+
+ EnterCriticalSection( &request->cs );
+ }
+ request->state = REQUEST_STATE_CANCELLED;
+#endif
}
/* critical section must be held */
@@ -3000,7 +3257,11 @@ static void free_request( struct winhttp_request *request )
WinHttpCloseHandle( request->hrequest );
WinHttpCloseHandle( request->hconnect );
WinHttpCloseHandle( request->hsession );
+#ifdef __REACTOS__
CloseHandle( request->thread );
+#else
+ CloseHandle( request->done );
+#endif
CloseHandle( request->wait );
CloseHandle( request->cancel );
heap_free( (WCHAR *)request->proxy.lpszProxy );
@@ -3118,7 +3379,7 @@ void release_typelib(void)
{
unsigned i;
- for (i = 0; i < sizeof(winhttp_typeinfo)/sizeof(*winhttp_typeinfo); i++)
+ for (i = 0; i < ARRAY_SIZE(winhttp_typeinfo); i++)
if (winhttp_typeinfo[i])
ITypeInfo_Release(winhttp_typeinfo[i]);
@@ -3318,7 +3579,7 @@ static HRESULT WINAPI winhttp_request_SetCredentials(
}
if (!WinHttpSetCredentials( request->hrequest, target, scheme, username, password,
NULL ))
{
- err = get_last_error();
+ err = GetLastError();
}
done:
LeaveCriticalSection( &request->cs );
@@ -3327,25 +3588,11 @@ done:
static void initialize_request( struct winhttp_request *request )
{
- request->hrequest = NULL;
- request->hconnect = NULL;
- request->hsession = NULL;
- request->thread = NULL;
- request->wait = NULL;
- request->cancel = NULL;
- request->buffer = NULL;
- request->verb = NULL;
- request->offset = 0;
- request->bytes_available = 0;
- request->bytes_read = 0;
- request->error = ERROR_SUCCESS;
- request->async = FALSE;
- request->logon_policy = WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM;
- request->disable_feature = 0;
- request->proxy.dwAccessType = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
- request->proxy.lpszProxy = NULL;
- request->proxy.lpszProxyBypass = NULL;
- request->resolve_timeout = 0;
+ request->wait = CreateEventW( NULL, FALSE, FALSE, NULL );
+ request->cancel = CreateEventW( NULL, FALSE, FALSE, NULL );
+#ifndef __REACTOS__
+ request->done = CreateEventW( NULL, FALSE, FALSE, NULL );
+#endif
request->connect_timeout = 60000;
request->send_timeout = 30000;
request->receive_timeout = 30000;
@@ -3369,8 +3616,17 @@ static void reset_request( struct winhttp_request *request )
request->bytes_available = 0;
request->bytes_read = 0;
request->error = ERROR_SUCCESS;
+ request->logon_policy = 0;
+ request->disable_feature = 0;
request->async = FALSE;
+ request->connect_timeout = 60000;
+ request->send_timeout = 30000;
+ request->receive_timeout = 30000;
request->url_codepage = CP_UTF8;
+ heap_free( request->proxy.lpszProxy );
+ request->proxy.lpszProxy = NULL;
+ heap_free( request->proxy.lpszProxyBypass );
+ request->proxy.lpszProxyBypass = NULL;
VariantClear( &request->data );
request->state = REQUEST_STATE_INITIALIZED;
}
@@ -3404,11 +3660,10 @@ static HRESULT WINAPI winhttp_request_Open(
uc.dwHostNameLength = ~0u;
uc.dwUrlPathLength = ~0u;
uc.dwExtraInfoLength = ~0u;
- if (!WinHttpCrackUrl( url, 0, 0, &uc )) return HRESULT_FROM_WIN32(
get_last_error() );
+ if (!WinHttpCrackUrl( url, 0, 0, &uc )) return HRESULT_FROM_WIN32( GetLastError()
);
EnterCriticalSection( &request->cs );
- if (request->state < REQUEST_STATE_INITIALIZED) initialize_request( request );
- else reset_request( request );
+ reset_request( request );
if (!(hostname = heap_alloc( (uc.dwHostNameLength + 1) * sizeof(WCHAR) ))) goto
error;
memcpy( hostname, uc.lpszHostName, uc.dwHostNameLength * sizeof(WCHAR) );
@@ -3427,31 +3682,31 @@ static HRESULT WINAPI winhttp_request_Open(
if (!(request->hsession = WinHttpOpen( user_agentW,
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, NULL, NULL,
WINHTTP_FLAG_ASYNC )))
{
- err = get_last_error();
+ err = GetLastError();
goto error;
}
if (!(request->hconnect = WinHttpConnect( request->hsession, hostname,
uc.nPort, 0 )))
{
WinHttpCloseHandle( request->hsession );
request->hsession = NULL;
- err = get_last_error();
+ err = GetLastError();
goto error;
}
}
else if (!(request->hconnect = WinHttpConnect( request->hsession, hostname,
uc.nPort, 0 )))
{
- err = get_last_error();
+ err = GetLastError();
goto error;
}
- len = sizeof(httpsW) / sizeof(WCHAR);
+ len = ARRAY_SIZE( httpsW );
if (uc.dwSchemeLength == len && !memcmp( uc.lpszScheme, httpsW, len *
sizeof(WCHAR) ))
{
flags |= WINHTTP_FLAG_SECURE;
}
if (!(request->hrequest = WinHttpOpenRequest( request->hconnect, method, path,
NULL, NULL, acceptW, flags )))
{
- err = get_last_error();
+ err = GetLastError();
goto error;
}
WinHttpSetOption( request->hrequest, WINHTTP_OPTION_CONTEXT_VALUE, &request,
sizeof(request) );
@@ -3510,7 +3765,7 @@ static HRESULT WINAPI winhttp_request_SetRequestHeader(
if (!WinHttpAddRequestHeaders( request->hrequest, str, len,
WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE
))
{
- err = get_last_error();
+ err = GetLastError();
}
heap_free( str );
@@ -3543,7 +3798,7 @@ static HRESULT WINAPI winhttp_request_GetResponseHeader(
size = 0;
if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_CUSTOM, header, NULL,
&size, NULL ))
{
- err = get_last_error();
+ err = GetLastError();
if (err != ERROR_INSUFFICIENT_BUFFER) goto done;
}
if (!(*value = SysAllocStringLen( NULL, size / sizeof(WCHAR) )))
@@ -3554,7 +3809,7 @@ static HRESULT WINAPI winhttp_request_GetResponseHeader(
err = ERROR_SUCCESS;
if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_CUSTOM, header, *value,
&size, NULL ))
{
- err = get_last_error();
+ err = GetLastError();
SysFreeString( *value );
}
done:
@@ -3582,7 +3837,7 @@ static HRESULT WINAPI winhttp_request_GetAllResponseHeaders(
size = 0;
if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL,
NULL, &size, NULL ))
{
- err = get_last_error();
+ err = GetLastError();
if (err != ERROR_INSUFFICIENT_BUFFER) goto done;
}
if (!(*headers = SysAllocStringLen( NULL, size / sizeof(WCHAR) )))
@@ -3593,7 +3848,7 @@ static HRESULT WINAPI winhttp_request_GetAllResponseHeaders(
err = ERROR_SUCCESS;
if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL,
*headers, &size, NULL ))
{
- err = get_last_error();
+ err = GetLastError();
SysFreeString( *headers );
}
done:
@@ -3621,7 +3876,9 @@ static void CALLBACK wait_status_callback( HINTERNET handle,
DWORD_PTR context,
request->error = result->dwError;
break;
}
- default: break;
+ default:
+ request->error = ERROR_SUCCESS;
+ break;
}
SetEvent( request->wait );
}
@@ -3635,19 +3892,38 @@ static void wait_set_status_callback( struct winhttp_request
*request, DWORD sta
static DWORD wait_for_completion( struct winhttp_request *request )
{
HANDLE handles[2] = { request->wait, request->cancel };
+#ifndef __REACTOS__
+ DWORD ret;
+#endif
switch (WaitForMultipleObjects( 2, handles, FALSE, INFINITE ))
{
case WAIT_OBJECT_0:
+#ifndef __REACTOS__
+ ret = request->error;
+#endif
break;
case WAIT_OBJECT_0 + 1:
+#ifdef __REACTOS__
request->error = ERROR_CANCELLED;
+#else
+ ret = request->error = ERROR_CANCELLED;
+ SetEvent( request->done );
+#endif
break;
default:
- request->error = get_last_error();
+#ifdef __REACTOS__
+ request->error = GetLastError();
+#else
+ ret = request->error = GetLastError();
+#endif
break;
}
+#ifdef __REACTOS__
return request->error;
+#else
+ return ret;
+#endif
}
static HRESULT request_receive( struct winhttp_request *request )
@@ -3657,7 +3933,7 @@ static HRESULT request_receive( struct winhttp_request *request )
wait_set_status_callback( request, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE );
if (!WinHttpReceiveResponse( request->hrequest, NULL ))
{
- return HRESULT_FROM_WIN32( get_last_error() );
+ return HRESULT_FROM_WIN32( GetLastError() );
}
if ((err = wait_for_completion( request ))) return HRESULT_FROM_WIN32( err );
if (!strcmpW( request->verb, headW ))
@@ -3673,7 +3949,7 @@ static HRESULT request_receive( struct winhttp_request *request )
wait_set_status_callback( request, WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE );
if (!WinHttpQueryDataAvailable( request->hrequest,
&request->bytes_available ))
{
- err = get_last_error();
+ err = GetLastError();
goto error;
}
if ((err = wait_for_completion( request ))) goto error;
@@ -3694,7 +3970,7 @@ static HRESULT request_receive( struct winhttp_request *request )
if (!WinHttpReadData( request->hrequest, request->buffer +
request->offset,
request->bytes_available, &request->bytes_read
))
{
- err = get_last_error();
+ err = GetLastError();
goto error;
}
if ((err = wait_for_completion( request ))) goto error;
@@ -3713,19 +3989,19 @@ error:
static DWORD request_set_parameters( struct winhttp_request *request )
{
if (!WinHttpSetOption( request->hrequest, WINHTTP_OPTION_PROXY,
&request->proxy,
- sizeof(request->proxy) )) return get_last_error();
+ sizeof(request->proxy) )) return GetLastError();
if (!WinHttpSetOption( request->hrequest, WINHTTP_OPTION_AUTOLOGON_POLICY,
&request->logon_policy,
- sizeof(request->logon_policy) )) return get_last_error();
+ sizeof(request->logon_policy) )) return GetLastError();
if (!WinHttpSetOption( request->hrequest, WINHTTP_OPTION_DISABLE_FEATURE,
&request->disable_feature,
- sizeof(request->disable_feature) )) return
get_last_error();
+ sizeof(request->disable_feature) )) return GetLastError();
if (!WinHttpSetTimeouts( request->hrequest,
request->resolve_timeout,
request->connect_timeout,
request->send_timeout,
- request->receive_timeout )) return get_last_error();
+ request->receive_timeout )) return GetLastError();
return ERROR_SUCCESS;
}
@@ -3790,7 +4066,7 @@ static HRESULT request_send( struct winhttp_request *request )
wait_set_status_callback( request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT );
if (!WinHttpSendRequest( request->hrequest, NULL, 0, ptr, size, size, 0 ))
{
- err = get_last_error();
+ err = GetLastError();
goto error;
}
if ((err = wait_for_completion( request ))) goto error;
@@ -3805,6 +4081,7 @@ error:
return HRESULT_FROM_WIN32( err );
}
+#ifdef __REACTOS__
static HRESULT request_send_and_receive( struct winhttp_request *request )
{
HRESULT hr = request_send( request );
@@ -3817,15 +4094,31 @@ static DWORD CALLBACK send_and_receive_proc( void *arg )
struct winhttp_request *request = (struct winhttp_request *)arg;
return request_send_and_receive( request );
}
+#else
+static void CALLBACK send_and_receive_proc( TP_CALLBACK_INSTANCE *instance, void *ctx )
+{
+ struct winhttp_request *request = (struct winhttp_request *)ctx;
+ if (request_send( request ) == S_OK) request_receive( request );
+ SetEvent( request->done );
+}
+#endif
/* critical section must be held */
static DWORD request_wait( struct winhttp_request *request, DWORD timeout )
{
+#ifdef __REACTOS__
HANDLE thread = request->thread;
+#else
+ HANDLE done = request->done;
+#endif
DWORD err, ret;
LeaveCriticalSection( &request->cs );
+#ifdef __REACTOS__
while ((err = MsgWaitForMultipleObjects( 1, &thread, FALSE, timeout, QS_ALLINPUT
)) == WAIT_OBJECT_0 + 1)
+#else
+ while ((err = MsgWaitForMultipleObjects( 1, &done, FALSE, timeout, QS_ALLINPUT ))
== WAIT_OBJECT_0 + 1)
+#endif
{
MSG msg;
while (PeekMessageW( &msg, NULL, 0, 0, PM_REMOVE ))
@@ -3837,17 +4130,19 @@ static DWORD request_wait( struct winhttp_request *request, DWORD
timeout )
switch (err)
{
case WAIT_OBJECT_0:
- ret = ERROR_SUCCESS;
+ ret = request->error;
break;
case WAIT_TIMEOUT:
ret = ERROR_TIMEOUT;
break;
- case WAIT_FAILED:
default:
- ret = get_last_error();
+ ret = GetLastError();
break;
}
EnterCriticalSection( &request->cs );
+#ifndef __REACTOS__
+ if (err == WAIT_OBJECT_0) request->proc_running = FALSE;
+#endif
return ret;
}
@@ -3877,13 +4172,18 @@ static HRESULT WINAPI winhttp_request_Send(
LeaveCriticalSection( &request->cs );
return hr;
}
+#ifdef __REACTOS__
if (!(request->thread = CreateThread( NULL, 0, send_and_receive_proc, request, 0,
NULL )))
+#else
+ if (!TrySubmitThreadpoolCallback( send_and_receive_proc, request, NULL ))
+#endif
{
LeaveCriticalSection( &request->cs );
- return HRESULT_FROM_WIN32( get_last_error() );
+ return HRESULT_FROM_WIN32( GetLastError() );
}
- request->wait = CreateEventW( NULL, FALSE, FALSE, NULL );
- request->cancel = CreateEventW( NULL, FALSE, FALSE, NULL );
+#ifndef __REACTOS__
+ request->proc_running = TRUE;
+#endif
if (!request->async)
{
hr = HRESULT_FROM_WIN32( request_wait( request, INFINITE ) );
@@ -3912,7 +4212,7 @@ static HRESULT WINAPI winhttp_request_get_Status(
flags = WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER;
if (!WinHttpQueryHeaders( request->hrequest, flags, NULL, &status_code,
&len, &index ))
{
- err = get_last_error();
+ err = GetLastError();
goto done;
}
*status = status_code;
@@ -3941,7 +4241,7 @@ static HRESULT WINAPI winhttp_request_get_StatusText(
}
if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_STATUS_TEXT, NULL,
NULL, &len, &index ))
{
- err = get_last_error();
+ err = GetLastError();
if (err != ERROR_INSUFFICIENT_BUFFER) goto done;
}
if (!(*status = SysAllocStringLen( NULL, len / sizeof(WCHAR) )))
@@ -3953,7 +4253,7 @@ static HRESULT WINAPI winhttp_request_get_StatusText(
err = ERROR_SUCCESS;
if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_STATUS_TEXT, NULL,
*status, &len, &index ))
{
- err = get_last_error();
+ err = GetLastError();
SysFreeString( *status );
}
done:
@@ -3970,12 +4270,12 @@ static DWORD request_get_codepage( struct winhttp_request
*request, UINT *codepa
*codepage = CP_ACP;
if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_CONTENT_TYPE, NULL,
NULL, &size, NULL ) &&
- get_last_error() == ERROR_INSUFFICIENT_BUFFER)
+ GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
if (!(buffer = heap_alloc( size ))) return ERROR_OUTOFMEMORY;
if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_CONTENT_TYPE, NULL,
buffer, &size, NULL ))
{
- return get_last_error();
+ return GetLastError();
}
if ((p = strstrW( buffer, charsetW )))
{
@@ -4372,11 +4672,9 @@ static HRESULT WINAPI winhttp_request_WaitForResponse(
err = ERROR_SUCCESS;
break;
- case ERROR_SUCCESS:
+ default:
if (succeeded) *succeeded = VARIANT_TRUE;
break;
-
- default: break;
}
LeaveCriticalSection( &request->cs );
return HRESULT_FROM_WIN32( err );
@@ -4487,15 +4785,12 @@ HRESULT WinHttpRequest_create( void **obj )
TRACE("%p\n", obj);
- if (!(request = heap_alloc( sizeof(*request) ))) return E_OUTOFMEMORY;
+ if (!(request = heap_alloc_zero( sizeof(*request) ))) return E_OUTOFMEMORY;
request->IWinHttpRequest_iface.lpVtbl = &winhttp_request_vtbl;
request->refs = 1;
- request->state = REQUEST_STATE_UNINITIALIZED;
- request->proxy.lpszProxy = NULL;
- request->proxy.lpszProxyBypass = NULL;
- request->url_codepage = CP_UTF8;
InitializeCriticalSection( &request->cs );
request->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ":
winhttp_request.cs");
+ initialize_request( request );
*obj = &request->IWinHttpRequest_iface;
TRACE("returning iface %p\n", *obj);
diff --git a/dll/win32/winhttp/session.c b/dll/win32/winhttp/session.c
index 7cfc2407585..8e24de736dd 100644
--- a/dll/win32/winhttp/session.c
+++ b/dll/win32/winhttp/session.c
@@ -17,9 +17,6 @@
*/
#include "config.h"
-#include "wine/port.h"
-#include "wine/debug.h"
-
#include <stdarg.h>
#include <stdlib.h>
@@ -29,46 +26,33 @@
#include <CoreServices/CoreServices.h>
#undef GetCurrentThread
#undef LoadResource
-#undef DPRINTF
#endif
#include "windef.h"
#include "winbase.h"
-#ifndef __MINGW32__
-#define USE_WS_PREFIX
-#endif
#include "winsock2.h"
#include "ws2ipdef.h"
+#include "ws2tcpip.h"
#include "winhttp.h"
-#include "wincrypt.h"
#include "winreg.h"
+#include "wine/winternl.h"
#define COBJMACROS
#include "ole2.h"
#include "dispex.h"
#include "activscp.h"
+#include "wine/debug.h"
#include "winhttp_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
-#define DEFAULT_RESOLVE_TIMEOUT 0
-#define DEFAULT_CONNECT_TIMEOUT 20000
-#define DEFAULT_SEND_TIMEOUT 30000
-#define DEFAULT_RECEIVE_TIMEOUT 30000
-
-void set_last_error( DWORD error )
-{
- /* FIXME */
- SetLastError( error );
-}
-
-DWORD get_last_error( void )
-{
- /* FIXME */
- return GetLastError();
-}
+#define DEFAULT_RESOLVE_TIMEOUT 0
+#define DEFAULT_CONNECT_TIMEOUT 20000
+#define DEFAULT_SEND_TIMEOUT 30000
+#define DEFAULT_RECEIVE_TIMEOUT 30000
+#define DEFAULT_RECEIVE_RESPONSE_TIMEOUT ~0u
-void send_callback( object_header_t *hdr, DWORD status, LPVOID info, DWORD buflen )
+void send_callback( struct object_header *hdr, DWORD status, void *info, DWORD buflen )
{
if (hdr->callback && (hdr->notify_mask & status))
{
@@ -90,22 +74,17 @@ BOOL WINAPI WinHttpCheckPlatform( void )
/***********************************************************************
* session_destroy (internal)
*/
-static void session_destroy( object_header_t *hdr )
+static void session_destroy( struct object_header *hdr )
{
- session_t *session = (session_t *)hdr;
- struct list *item, *next;
- domain_t *domain;
+ struct session *session = (struct session *)hdr;
TRACE("%p\n", session);
if (session->unload_event) SetEvent( session->unload_event );
- if (session->cred_handle_initialized) FreeCredentialsHandle(
&session->cred_handle );
+ destroy_cookies( session );
- LIST_FOR_EACH_SAFE( item, next, &session->cookie_cache )
- {
- domain = LIST_ENTRY( item, domain_t, entry );
- delete_domain( domain );
- }
+ session->cs.DebugInfo->Spare[0] = 0;
+ DeleteCriticalSection( &session->cs );
heap_free( session->agent );
heap_free( session->proxy_server );
heap_free( session->proxy_bypass );
@@ -114,9 +93,9 @@ static void session_destroy( object_header_t *hdr )
heap_free( session );
}
-static BOOL session_query_option( object_header_t *hdr, DWORD option, LPVOID buffer,
LPDWORD buflen )
+static BOOL session_query_option( struct object_header *hdr, DWORD option, void *buffer,
DWORD *buflen )
{
- session_t *session = (session_t *)hdr;
+ struct session *session = (struct session *)hdr;
switch (option)
{
@@ -125,7 +104,7 @@ static BOOL session_query_option( object_header_t *hdr, DWORD option,
LPVOID buf
if (!buffer || *buflen < sizeof(DWORD))
{
*buflen = sizeof(DWORD);
- set_last_error( ERROR_INSUFFICIENT_BUFFER );
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
@@ -137,28 +116,37 @@ static BOOL session_query_option( object_header_t *hdr, DWORD
option, LPVOID buf
*(DWORD *)buffer = session->resolve_timeout;
*buflen = sizeof(DWORD);
return TRUE;
+
case WINHTTP_OPTION_CONNECT_TIMEOUT:
*(DWORD *)buffer = session->connect_timeout;
*buflen = sizeof(DWORD);
return TRUE;
+
case WINHTTP_OPTION_SEND_TIMEOUT:
*(DWORD *)buffer = session->send_timeout;
*buflen = sizeof(DWORD);
return TRUE;
+
case WINHTTP_OPTION_RECEIVE_TIMEOUT:
- *(DWORD *)buffer = session->recv_timeout;
+ *(DWORD *)buffer = session->receive_timeout;
+ *buflen = sizeof(DWORD);
+ return TRUE;
+
+ case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
+ *(DWORD *)buffer = session->receive_response_timeout;
*buflen = sizeof(DWORD);
return TRUE;
+
default:
FIXME("unimplemented option %u\n", option);
- set_last_error( ERROR_INVALID_PARAMETER );
+ SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
}
-static BOOL session_set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD
buflen )
+static BOOL session_set_option( struct object_header *hdr, DWORD option, void *buffer,
DWORD buflen )
{
- session_t *session = (session_t *)hdr;
+ struct session *session = (struct session *)hdr;
switch (option)
{
@@ -175,7 +163,7 @@ static BOOL session_set_option( object_header_t *hdr, DWORD option,
LPVOID buffe
if (buflen != sizeof(policy))
{
- set_last_error( ERROR_INSUFFICIENT_BUFFER );
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
@@ -188,72 +176,81 @@ static BOOL session_set_option( object_header_t *hdr, DWORD option,
LPVOID buffe
{
if (buflen != sizeof(session->secure_protocols))
{
- set_last_error( ERROR_INSUFFICIENT_BUFFER );
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
+ EnterCriticalSection( &session->cs );
session->secure_protocols = *(DWORD *)buffer;
+ LeaveCriticalSection( &session->cs );
TRACE("0x%x\n", session->secure_protocols);
return TRUE;
}
case WINHTTP_OPTION_DISABLE_FEATURE:
- set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+ SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
return FALSE;
+
case WINHTTP_OPTION_RESOLVE_TIMEOUT:
session->resolve_timeout = *(DWORD *)buffer;
return TRUE;
+
case WINHTTP_OPTION_CONNECT_TIMEOUT:
session->connect_timeout = *(DWORD *)buffer;
return TRUE;
+
case WINHTTP_OPTION_SEND_TIMEOUT:
session->send_timeout = *(DWORD *)buffer;
return TRUE;
+
case WINHTTP_OPTION_RECEIVE_TIMEOUT:
- session->recv_timeout = *(DWORD *)buffer;
+ session->receive_timeout = *(DWORD *)buffer;
return TRUE;
+
+ case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
+ session->receive_response_timeout = *(DWORD *)buffer;
+ return TRUE;
+
case WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH:
- FIXME("WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH: 0x%x\n", *(DWORD
*)buffer);
+ session->passport_flags = *(DWORD *)buffer;
return TRUE;
+
case WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT:
TRACE("WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT: %p\n", *(HANDLE *)buffer);
session->unload_event = *(HANDLE *)buffer;
return TRUE;
+
case WINHTTP_OPTION_MAX_CONNS_PER_SERVER:
FIXME("WINHTTP_OPTION_MAX_CONNS_PER_SERVER: %d\n", *(DWORD *)buffer);
return TRUE;
+
case WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER:
FIXME("WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER: %d\n", *(DWORD
*)buffer);
return TRUE;
+
default:
FIXME("unimplemented option %u\n", option);
- set_last_error( ERROR_WINHTTP_INVALID_OPTION );
+ SetLastError( ERROR_WINHTTP_INVALID_OPTION );
return FALSE;
}
}
-static const object_vtbl_t session_vtbl =
+static const struct object_vtbl session_vtbl =
{
session_destroy,
session_query_option,
session_set_option
};
-#ifdef __REACTOS__
-BOOL netconn_init_winsock();
-#endif /* __REACTOS__ */
/***********************************************************************
* WinHttpOpen (winhttp.@)
*/
HINTERNET WINAPI WinHttpOpen( LPCWSTR agent, DWORD access, LPCWSTR proxy, LPCWSTR bypass,
DWORD flags )
{
- session_t *session;
+ struct session *session;
HINTERNET handle = NULL;
-#ifdef __REACTOS__
- if (!netconn_init_winsock()) return NULL;
-#endif
TRACE("%s, %u, %s, %s, 0x%08x\n", debugstr_w(agent), access,
debugstr_w(proxy), debugstr_w(bypass), flags);
- if (!(session = heap_alloc_zero( sizeof(session_t) ))) return NULL;
+ if (!(session = heap_alloc_zero( sizeof(struct session) ))) return NULL;
session->hdr.type = WINHTTP_HANDLE_TYPE_SESSION;
session->hdr.vtbl = &session_vtbl;
@@ -264,8 +261,11 @@ HINTERNET WINAPI WinHttpOpen( LPCWSTR agent, DWORD access, LPCWSTR
proxy, LPCWST
session->resolve_timeout = DEFAULT_RESOLVE_TIMEOUT;
session->connect_timeout = DEFAULT_CONNECT_TIMEOUT;
session->send_timeout = DEFAULT_SEND_TIMEOUT;
- session->recv_timeout = DEFAULT_RECEIVE_TIMEOUT;
+ session->receive_timeout = DEFAULT_RECEIVE_TIMEOUT;
+ session->receive_response_timeout = DEFAULT_RECEIVE_RESPONSE_TIMEOUT;
list_init( &session->cookie_cache );
+ InitializeCriticalSection( &session->cs );
+ session->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ":
session.cs");
if (agent && !(session->agent = strdupW( agent ))) goto end;
if (access == WINHTTP_ACCESS_TYPE_DEFAULT_PROXY)
@@ -300,16 +300,16 @@ HINTERNET WINAPI WinHttpOpen( LPCWSTR agent, DWORD access, LPCWSTR
proxy, LPCWST
end:
release_object( &session->hdr );
TRACE("returning %p\n", handle);
- if (handle) set_last_error( ERROR_SUCCESS );
+ if (handle) SetLastError( ERROR_SUCCESS );
return handle;
}
/***********************************************************************
* connect_destroy (internal)
*/
-static void connect_destroy( object_header_t *hdr )
+static void connect_destroy( struct object_header *hdr )
{
- connect_t *connect = (connect_t *)hdr;
+ struct connect *connect = (struct connect *)hdr;
TRACE("%p\n", connect);
@@ -322,9 +322,9 @@ static void connect_destroy( object_header_t *hdr )
heap_free( connect );
}
-static BOOL connect_query_option( object_header_t *hdr, DWORD option, LPVOID buffer,
LPDWORD buflen )
+static BOOL connect_query_option( struct object_header *hdr, DWORD option, void *buffer,
DWORD *buflen )
{
- connect_t *connect = (connect_t *)hdr;
+ struct connect *connect = (struct connect *)hdr;
switch (option)
{
@@ -333,11 +333,11 @@ static BOOL connect_query_option( object_header_t *hdr, DWORD
option, LPVOID buf
if (!buffer || *buflen < sizeof(HINTERNET))
{
*buflen = sizeof(HINTERNET);
- set_last_error( ERROR_INSUFFICIENT_BUFFER );
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
- *(HINTERNET *)buffer = ((object_header_t *)connect->session)->handle;
+ *(HINTERNET *)buffer = ((struct object_header *)connect->session)->handle;
*buflen = sizeof(HINTERNET);
return TRUE;
}
@@ -345,26 +345,35 @@ static BOOL connect_query_option( object_header_t *hdr, DWORD
option, LPVOID buf
*(DWORD *)buffer = connect->session->resolve_timeout;
*buflen = sizeof(DWORD);
return TRUE;
+
case WINHTTP_OPTION_CONNECT_TIMEOUT:
*(DWORD *)buffer = connect->session->connect_timeout;
*buflen = sizeof(DWORD);
return TRUE;
+
case WINHTTP_OPTION_SEND_TIMEOUT:
*(DWORD *)buffer = connect->session->send_timeout;
*buflen = sizeof(DWORD);
return TRUE;
+
case WINHTTP_OPTION_RECEIVE_TIMEOUT:
- *(DWORD *)buffer = connect->session->recv_timeout;
+ *(DWORD *)buffer = connect->session->receive_timeout;
*buflen = sizeof(DWORD);
return TRUE;
+
+ case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
+ *(DWORD *)buffer = connect->session->receive_response_timeout;
+ *buflen = sizeof(DWORD);
+ return TRUE;
+
default:
FIXME("unimplemented option %u\n", option);
- set_last_error( ERROR_INVALID_PARAMETER );
+ SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
}
-static const object_vtbl_t connect_vtbl =
+static const struct object_vtbl connect_vtbl =
{
connect_destroy,
connect_query_option,
@@ -425,7 +434,7 @@ static BOOL domain_matches(LPCWSTR server, LPCWSTR domain)
/* Matches INTERNET_MAX_HOST_NAME_LENGTH in wininet.h, also RFC 1035 */
#define MAX_HOST_NAME_LENGTH 256
-static BOOL should_bypass_proxy(session_t *session, LPCWSTR server)
+static BOOL should_bypass_proxy(struct session *session, LPCWSTR server)
{
LPCWSTR ptr;
BOOL ret = FALSE;
@@ -456,9 +465,9 @@ static BOOL should_bypass_proxy(session_t *session, LPCWSTR server)
return ret;
}
-BOOL set_server_for_hostname( connect_t *connect, LPCWSTR server, INTERNET_PORT port )
+BOOL set_server_for_hostname( struct connect *connect, const WCHAR *server, INTERNET_PORT
port )
{
- session_t *session = connect->session;
+ struct session *session = connect->session;
BOOL ret = TRUE;
if (session->proxy_server && !should_bypass_proxy(session, server))
@@ -523,29 +532,29 @@ end:
*/
HINTERNET WINAPI WinHttpConnect( HINTERNET hsession, LPCWSTR server, INTERNET_PORT port,
DWORD reserved )
{
- connect_t *connect;
- session_t *session;
+ struct connect *connect;
+ struct session *session;
HINTERNET hconnect = NULL;
TRACE("%p, %s, %u, %x\n", hsession, debugstr_w(server), port, reserved);
if (!server)
{
- set_last_error( ERROR_INVALID_PARAMETER );
+ SetLastError( ERROR_INVALID_PARAMETER );
return NULL;
}
- if (!(session = (session_t *)grab_object( hsession )))
+ if (!(session = (struct session *)grab_object( hsession )))
{
- set_last_error( ERROR_INVALID_HANDLE );
+ SetLastError( ERROR_INVALID_HANDLE );
return NULL;
}
if (session->hdr.type != WINHTTP_HANDLE_TYPE_SESSION)
{
release_object( &session->hdr );
- set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+ SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
return NULL;
}
- if (!(connect = heap_alloc_zero( sizeof(connect_t) )))
+ if (!(connect = heap_alloc_zero( sizeof(struct connect) )))
{
release_object( &session->hdr );
return NULL;
@@ -577,32 +586,44 @@ end:
release_object( &connect->hdr );
release_object( &session->hdr );
TRACE("returning %p\n", hconnect);
- if (hconnect) set_last_error( ERROR_SUCCESS );
+ if (hconnect) SetLastError( ERROR_SUCCESS );
return hconnect;
}
/***********************************************************************
* request_destroy (internal)
*/
-static void request_destroy( object_header_t *hdr )
+static void request_destroy( struct object_header *hdr )
{
- request_t *request = (request_t *)hdr;
+ struct request *request = (struct request *)hdr;
unsigned int i, j;
TRACE("%p\n", request);
+#ifdef __REACTOS__
if (request->task_thread)
+#else
+ if (request->task_proc_running)
+#endif
{
- /* Signal to the task proc to quit. It will call
- this again when it does. */
+ /* Signal to the task proc to quit. It will call this again when it does. */
+#ifdef __REACTOS__
HANDLE thread = request->task_thread;
request->task_thread = 0;
SetEvent( request->task_cancel );
CloseHandle( thread );
+#else
+ request->task_proc_running = FALSE;
+ SetEvent( request->task_cancel );
+#endif
return;
}
release_object( &request->connect->hdr );
+ if (request->cred_handle_initialized) FreeCredentialsHandle(
&request->cred_handle );
+ CertFreeCertificateContext( request->server_cert );
+ CertFreeCertificateContext( request->client_cert );
+
destroy_authinfo( request->authinfo );
destroy_authinfo( request->proxy_authinfo );
@@ -652,46 +673,8 @@ 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
)
+static BOOL copy_sockaddr( const struct sockaddr *addr, SOCKADDR_STORAGE *addr_storage )
{
-#if !defined(__MINGW32__) && !defined(_MSC_VER)
- 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:
@@ -714,30 +697,27 @@ static BOOL convert_sockaddr( const struct sockaddr *addr,
SOCKADDR_STORAGE *add
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( struct object_header *hdr, DWORD option, void *buffer,
DWORD *buflen )
{
- request_t *request = (request_t *)hdr;
+ struct request *request = (struct request *)hdr;
switch (option)
{
case WINHTTP_OPTION_SECURITY_FLAGS:
{
- DWORD flags = 0;
+ DWORD flags;
int bits;
if (!buffer || *buflen < sizeof(flags))
{
*buflen = sizeof(flags);
- set_last_error( ERROR_INSUFFICIENT_BUFFER );
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
- flags = 0;
- if (hdr->flags & WINHTTP_FLAG_SECURE) flags |= SECURITY_FLAG_SECURE;
- flags |= request->security_flags;
+ flags = request->security_flags;
if (request->netconn)
{
bits = netconn_get_cipher_strength( request->netconn );
@@ -759,18 +739,18 @@ static BOOL request_query_option( object_header_t *hdr, DWORD
option, LPVOID buf
if (!buffer || *buflen < sizeof(cert))
{
*buflen = sizeof(cert);
- set_last_error( ERROR_INSUFFICIENT_BUFFER );
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
- if (!request->netconn || !(cert = netconn_get_certificate( request->netconn
))) return FALSE;
+ if (!(cert = CertDuplicateCertificateContext( request->server_cert ))) return
FALSE;
*(CERT_CONTEXT **)buffer = (CERT_CONTEXT *)cert;
*buflen = sizeof(cert);
return TRUE;
}
case WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT:
{
- const CERT_CONTEXT *cert;
+ const CERT_CONTEXT *cert = request->server_cert;
const CRYPT_OID_INFO *oidInfo;
WINHTTP_CERTIFICATE_INFO *ci = buffer;
@@ -779,19 +759,17 @@ static BOOL request_query_option( object_header_t *hdr, DWORD
option, LPVOID buf
if (!buffer || *buflen < sizeof(*ci))
{
*buflen = sizeof(*ci);
- set_last_error( ERROR_INSUFFICIENT_BUFFER );
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
- if (!request->netconn || !(cert = netconn_get_certificate( request->netconn
))) return FALSE;
+ if (!cert) return FALSE;
ci->ftExpiry = cert->pCertInfo->NotAfter;
ci->ftStart = cert->pCertInfo->NotBefore;
ci->lpszSubjectInfo = blob_to_str( cert->dwCertEncodingType,
&cert->pCertInfo->Subject );
ci->lpszIssuerInfo = blob_to_str( cert->dwCertEncodingType,
&cert->pCertInfo->Issuer );
ci->lpszProtocolName = NULL;
- oidInfo = CryptFindOIDInfo( CRYPT_OID_INFO_OID_KEY,
- cert->pCertInfo->SignatureAlgorithm.pszObjId,
- 0 );
+ oidInfo = CryptFindOIDInfo( CRYPT_OID_INFO_OID_KEY,
cert->pCertInfo->SignatureAlgorithm.pszObjId, 0 );
if (oidInfo)
ci->lpszSignatureAlgName = (LPWSTR)oidInfo->pwszName;
else
@@ -799,7 +777,6 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option,
LPVOID buf
ci->lpszEncryptionAlgName = NULL;
ci->dwKeySize = request->netconn ? netconn_get_cipher_strength(
request->netconn ) : 0;
- CertFreeCertificateContext( cert );
*buflen = sizeof(*ci);
return TRUE;
}
@@ -808,7 +785,7 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option,
LPVOID buf
if (!buffer || *buflen < sizeof(DWORD))
{
*buflen = sizeof(DWORD);
- set_last_error( ERROR_INSUFFICIENT_BUFFER );
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
@@ -826,17 +803,17 @@ static BOOL request_query_option( object_header_t *hdr, DWORD
option, LPVOID buf
if (!buffer || *buflen < sizeof(*info))
{
*buflen = sizeof(*info);
- set_last_error( ERROR_INSUFFICIENT_BUFFER );
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
if (!request->netconn)
{
- set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_STATE );
+ SetLastError( 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;
+ if (!copy_sockaddr( &local, &info->LocalAddress )) return FALSE;
+ if (!copy_sockaddr( remote, &info->RemoteAddress )) return FALSE;
info->cbSize = sizeof(*info);
return TRUE;
}
@@ -844,16 +821,24 @@ static BOOL request_query_option( object_header_t *hdr, DWORD
option, LPVOID buf
*(DWORD *)buffer = request->resolve_timeout;
*buflen = sizeof(DWORD);
return TRUE;
+
case WINHTTP_OPTION_CONNECT_TIMEOUT:
*(DWORD *)buffer = request->connect_timeout;
*buflen = sizeof(DWORD);
return TRUE;
+
case WINHTTP_OPTION_SEND_TIMEOUT:
*(DWORD *)buffer = request->send_timeout;
*buflen = sizeof(DWORD);
return TRUE;
+
case WINHTTP_OPTION_RECEIVE_TIMEOUT:
- *(DWORD *)buffer = request->recv_timeout;
+ *(DWORD *)buffer = request->receive_timeout;
+ *buflen = sizeof(DWORD);
+ return TRUE;
+
+ case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
+ *(DWORD *)buffer = request->receive_response_timeout;
*buflen = sizeof(DWORD);
return TRUE;
@@ -875,7 +860,7 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option,
LPVOID buf
default:
FIXME("unimplemented option %u\n", option);
- set_last_error( ERROR_INVALID_PARAMETER );
+ SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
}
@@ -889,13 +874,13 @@ static WCHAR *buffer_to_str( WCHAR *buffer, DWORD buflen )
ret[buflen] = 0;
return ret;
}
- set_last_error( ERROR_OUTOFMEMORY );
+ SetLastError( ERROR_OUTOFMEMORY );
return NULL;
}
-static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD
buflen )
+static BOOL request_set_option( struct object_header *hdr, DWORD option, void *buffer,
DWORD buflen )
{
- request_t *request = (request_t *)hdr;
+ struct request *request = (struct request *)hdr;
switch (option)
{
@@ -912,7 +897,7 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option,
LPVOID buffe
if (buflen != sizeof(DWORD))
{
- set_last_error( ERROR_INSUFFICIENT_BUFFER );
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
@@ -927,7 +912,7 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option,
LPVOID buffe
if (buflen != sizeof(DWORD))
{
- set_last_error( ERROR_INSUFFICIENT_BUFFER );
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
@@ -942,7 +927,7 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option,
LPVOID buffe
if (buflen != sizeof(DWORD))
{
- set_last_error( ERROR_INSUFFICIENT_BUFFER );
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
@@ -954,20 +939,21 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option,
LPVOID buffe
case WINHTTP_OPTION_SECURITY_FLAGS:
{
DWORD flags;
+ static const DWORD accepted = SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
+ SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
+ SECURITY_FLAG_IGNORE_UNKNOWN_CA |
+ SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE;
if (buflen < sizeof(DWORD))
{
- set_last_error( ERROR_INSUFFICIENT_BUFFER );
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
flags = *(DWORD *)buffer;
TRACE("0x%x\n", flags);
- if (!(flags & (SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
- SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
- SECURITY_FLAG_IGNORE_UNKNOWN_CA |
- SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE)))
+ if (flags && (flags & ~accepted))
{
- set_last_error( ERROR_INVALID_PARAMETER );
+ SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
request->security_flags = flags;
@@ -976,19 +962,26 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option,
LPVOID buffe
case WINHTTP_OPTION_RESOLVE_TIMEOUT:
request->resolve_timeout = *(DWORD *)buffer;
return TRUE;
+
case WINHTTP_OPTION_CONNECT_TIMEOUT:
request->connect_timeout = *(DWORD *)buffer;
return TRUE;
+
case WINHTTP_OPTION_SEND_TIMEOUT:
request->send_timeout = *(DWORD *)buffer;
return TRUE;
+
case WINHTTP_OPTION_RECEIVE_TIMEOUT:
- request->recv_timeout = *(DWORD *)buffer;
+ request->receive_timeout = *(DWORD *)buffer;
+ return TRUE;
+
+ case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
+ request->receive_response_timeout = *(DWORD *)buffer;
return TRUE;
case WINHTTP_OPTION_USERNAME:
{
- connect_t *connect = request->connect;
+ struct connect *connect = request->connect;
heap_free( connect->username );
if (!(connect->username = buffer_to_str( buffer, buflen ))) return FALSE;
@@ -996,7 +989,7 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option,
LPVOID buffe
}
case WINHTTP_OPTION_PASSWORD:
{
- connect_t *connect = request->connect;
+ struct connect *connect = request->connect;
heap_free( connect->password );
if (!(connect->password = buffer_to_str( buffer, buflen ))) return FALSE;
@@ -1004,7 +997,7 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option,
LPVOID buffe
}
case WINHTTP_OPTION_PROXY_USERNAME:
{
- session_t *session = request->connect->session;
+ struct session *session = request->connect->session;
heap_free( session->proxy_username );
if (!(session->proxy_username = buffer_to_str( buffer, buflen ))) return
FALSE;
@@ -1012,82 +1005,136 @@ static BOOL request_set_option( object_header_t *hdr, DWORD
option, LPVOID buffe
}
case WINHTTP_OPTION_PROXY_PASSWORD:
{
- session_t *session = request->connect->session;
+ struct session *session = request->connect->session;
heap_free( session->proxy_password );
if (!(session->proxy_password = buffer_to_str( buffer, buflen ))) return
FALSE;
return TRUE;
}
case WINHTTP_OPTION_CLIENT_CERT_CONTEXT:
+ {
+ const CERT_CONTEXT *cert;
+
if (!(hdr->flags & WINHTTP_FLAG_SECURE))
{
SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_STATE );
return FALSE;
}
- FIXME("WINHTTP_OPTION_CLIENT_CERT_CONTEXT\n");
+ if (!buffer)
+ {
+ CertFreeCertificateContext( request->client_cert );
+ request->client_cert = NULL;
+ }
+ else if (buflen >= sizeof(cert))
+ {
+ if (!(cert = CertDuplicateCertificateContext( buffer ))) return FALSE;
+ CertFreeCertificateContext( request->client_cert );
+ request->client_cert = cert;
+ }
+ else
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+
+ if (request->cred_handle_initialized)
+ {
+ FreeCredentialsHandle( &request->cred_handle );
+ request->cred_handle_initialized = FALSE;
+ }
+
return TRUE;
+ }
+ case WINHTTP_OPTION_ENABLE_FEATURE:
+ if(buflen == sizeof( DWORD ) && *(DWORD *)buffer ==
WINHTTP_ENABLE_SSL_REVOCATION)
+ {
+ request->check_revocation = TRUE;
+ SetLastError( NO_ERROR );
+ return TRUE;
+ }
+ else
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+
+ case WINHTTP_OPTION_CONNECT_RETRIES:
+ FIXME("WINHTTP_OPTION_CONNECT_RETRIES\n");
+ return TRUE;
+
default:
FIXME("unimplemented option %u\n", option);
- set_last_error( ERROR_WINHTTP_INVALID_OPTION );
+ SetLastError( ERROR_WINHTTP_INVALID_OPTION );
return FALSE;
}
}
-static const object_vtbl_t request_vtbl =
+static const struct object_vtbl request_vtbl =
{
request_destroy,
request_query_option,
request_set_option
};
-static BOOL store_accept_types( request_t *request, const WCHAR **accept_types )
+static BOOL add_accept_types_header( struct request *request, const WCHAR **types )
{
- static const WCHAR attr_accept[] =
{'A','c','c','e','p','t',0};
+ static const WCHAR acceptW[] =
{'A','c','c','e','p','t',0};
static const DWORD flags = WINHTTP_ADDREQ_FLAG_ADD |
WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA;
- const WCHAR **types = accept_types;
if (!types) return TRUE;
while (*types)
{
- process_header( request, attr_accept, *types, flags, TRUE );
+ if (!process_header( request, acceptW, *types, flags, TRUE )) return FALSE;
types++;
}
return TRUE;
}
+static WCHAR *get_request_path( const WCHAR *object )
+{
+ int len = object ? strlenW(object) : 0;
+ WCHAR *p, *ret;
+
+ if (!object || object[0] != '/') len++;
+ if (!(p = ret = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return NULL;
+ if (!object || object[0] != '/') *p++ = '/';
+ if (object) strcpyW( p, object );
+ ret[len] = 0;
+ return ret;
+}
+
/***********************************************************************
* WinHttpOpenRequest (winhttp.@)
*/
HINTERNET WINAPI WinHttpOpenRequest( HINTERNET hconnect, LPCWSTR verb, LPCWSTR object,
LPCWSTR version,
LPCWSTR referrer, LPCWSTR *types, DWORD flags )
{
- request_t *request;
- connect_t *connect;
+ struct request *request;
+ struct connect *connect;
HINTERNET hrequest = NULL;
TRACE("%p, %s, %s, %s, %s, %p, 0x%08x\n", hconnect, debugstr_w(verb),
debugstr_w(object),
debugstr_w(version), debugstr_w(referrer), types, flags);
- if(types && TRACE_ON(winhttp)) {
+ if (types && TRACE_ON(winhttp))
+ {
const WCHAR **iter;
-
TRACE("accept types:\n");
- for(iter = types; *iter; iter++)
- TRACE(" %s\n", debugstr_w(*iter));
+ for (iter = types; *iter; iter++) TRACE(" %s\n",
debugstr_w(*iter));
}
- if (!(connect = (connect_t *)grab_object( hconnect )))
+ if (!(connect = (struct connect *)grab_object( hconnect )))
{
- set_last_error( ERROR_INVALID_HANDLE );
+ SetLastError( ERROR_INVALID_HANDLE );
return NULL;
}
if (connect->hdr.type != WINHTTP_HANDLE_TYPE_CONNECT)
{
release_object( &connect->hdr );
- set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+ SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
return NULL;
}
- if (!(request = heap_alloc_zero( sizeof(request_t) )))
+ if (!(request = heap_alloc_zero( sizeof(struct request) )))
{
release_object( &connect->hdr );
return NULL;
@@ -1110,29 +1157,16 @@ HINTERNET WINAPI WinHttpOpenRequest( HINTERNET hconnect, LPCWSTR
verb, LPCWSTR o
request->resolve_timeout = connect->session->resolve_timeout;
request->connect_timeout = connect->session->connect_timeout;
request->send_timeout = connect->session->send_timeout;
- request->recv_timeout = connect->session->recv_timeout;
+ request->receive_timeout = connect->session->receive_timeout;
+ request->receive_response_timeout =
connect->session->receive_response_timeout;
if (!verb || !verb[0]) verb = getW;
if (!(request->verb = strdupW( verb ))) goto end;
-
- if (object)
- {
- WCHAR *path, *p;
- unsigned int len;
-
- len = strlenW( object ) + 1;
- if (object[0] != '/') len++;
- if (!(p = path = heap_alloc( len * sizeof(WCHAR) ))) goto end;
-
- if (object[0] != '/') *p++ = '/';
- strcpyW( p, object );
- request->path = path;
- }
- else if (!(request->path = strdupW( slashW ))) goto end;
+ if (!(request->path = get_request_path( object ))) goto end;
if (!version || !version[0]) version = http1_1;
if (!(request->version = strdupW( version ))) goto end;
- if (!(store_accept_types( request, types ))) goto end;
+ if (!(add_accept_types_header( request, types ))) goto end;
if (!(hrequest = alloc_handle( &request->hdr ))) goto end;
request->hdr.handle = hrequest;
@@ -1143,7 +1177,7 @@ end:
release_object( &request->hdr );
release_object( &connect->hdr );
TRACE("returning %p\n", hrequest);
- if (hrequest) set_last_error( ERROR_SUCCESS );
+ if (hrequest) SetLastError( ERROR_SUCCESS );
return hrequest;
}
@@ -1152,28 +1186,28 @@ end:
*/
BOOL WINAPI WinHttpCloseHandle( HINTERNET handle )
{
- object_header_t *hdr;
+ struct object_header *hdr;
TRACE("%p\n", handle);
if (!(hdr = grab_object( handle )))
{
- set_last_error( ERROR_INVALID_HANDLE );
+ SetLastError( ERROR_INVALID_HANDLE );
return FALSE;
}
release_object( hdr );
free_handle( handle );
- set_last_error( ERROR_SUCCESS );
+ SetLastError( ERROR_SUCCESS );
return TRUE;
}
-static BOOL query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD
buflen )
+static BOOL query_option( struct object_header *hdr, DWORD option, void *buffer, DWORD
*buflen )
{
BOOL ret = FALSE;
if (!buflen)
{
- set_last_error( ERROR_INVALID_PARAMETER );
+ SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
@@ -1184,7 +1218,7 @@ static BOOL query_option( object_header_t *hdr, DWORD option, LPVOID
buffer, LPD
if (!buffer || *buflen < sizeof(DWORD_PTR))
{
*buflen = sizeof(DWORD_PTR);
- set_last_error( ERROR_INSUFFICIENT_BUFFER );
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
@@ -1197,7 +1231,7 @@ static BOOL query_option( object_header_t *hdr, DWORD option, LPVOID
buffer, LPD
else
{
FIXME("unimplemented option %u\n", option);
- set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+ SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
return FALSE;
}
break;
@@ -1211,30 +1245,30 @@ static BOOL query_option( object_header_t *hdr, DWORD option,
LPVOID buffer, LPD
BOOL WINAPI WinHttpQueryOption( HINTERNET handle, DWORD option, LPVOID buffer, LPDWORD
buflen )
{
BOOL ret = FALSE;
- object_header_t *hdr;
+ struct object_header *hdr;
TRACE("%p, %u, %p, %p\n", handle, option, buffer, buflen);
if (!(hdr = grab_object( handle )))
{
- set_last_error( ERROR_INVALID_HANDLE );
+ SetLastError( ERROR_INVALID_HANDLE );
return FALSE;
}
ret = query_option( hdr, option, buffer, buflen );
release_object( hdr );
- if (ret) set_last_error( ERROR_SUCCESS );
+ if (ret) SetLastError( ERROR_SUCCESS );
return ret;
}
-static BOOL set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD buflen
)
+static BOOL set_option( struct object_header *hdr, DWORD option, void *buffer, DWORD
buflen )
{
BOOL ret = TRUE;
if (!buffer && buflen)
{
- set_last_error( ERROR_INVALID_PARAMETER );
+ SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
@@ -1244,7 +1278,7 @@ static BOOL set_option( object_header_t *hdr, DWORD option, LPVOID
buffer, DWORD
{
if (buflen != sizeof(DWORD_PTR))
{
- set_last_error( ERROR_INSUFFICIENT_BUFFER );
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
@@ -1256,7 +1290,7 @@ static BOOL set_option( object_header_t *hdr, DWORD option, LPVOID
buffer, DWORD
else
{
FIXME("unimplemented option %u\n", option);
- set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+ SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
return FALSE;
}
break;
@@ -1270,20 +1304,20 @@ static BOOL set_option( object_header_t *hdr, DWORD option, LPVOID
buffer, DWORD
BOOL WINAPI WinHttpSetOption( HINTERNET handle, DWORD option, LPVOID buffer, DWORD buflen
)
{
BOOL ret = FALSE;
- object_header_t *hdr;
+ struct object_header *hdr;
TRACE("%p, %u, %p, %u\n", handle, option, buffer, buflen);
if (!(hdr = grab_object( handle )))
{
- set_last_error( ERROR_INVALID_HANDLE );
+ SetLastError( ERROR_INVALID_HANDLE );
return FALSE;
}
ret = set_option( hdr, option, buffer, buflen );
release_object( hdr );
- if (ret) set_last_error( ERROR_SUCCESS );
+ if (ret) SetLastError( ERROR_SUCCESS );
return ret;
}
@@ -1308,17 +1342,13 @@ static BOOL is_domain_suffix( const char *domain, const char
*suffix )
int len_domain = strlen( domain ), len_suffix = strlen( suffix );
if (len_suffix > len_domain) return FALSE;
- if (!strcasecmp( domain + len_domain - len_suffix, suffix )) return TRUE;
+ if (!_strnicmp( domain + len_domain - len_suffix, suffix, -1 )) return TRUE;
return FALSE;
}
static int reverse_lookup( const struct addrinfo *ai, char *hostname, size_t len )
{
- int ret = -1;
-#ifdef HAVE_GETNAMEINFO
- ret = getnameinfo( ai->ai_addr, ai->ai_addrlen, hostname, len, NULL, 0, 0 );
-#endif
- return ret;
+ return getnameinfo( ai->ai_addr, ai->ai_addrlen, hostname, len, NULL, 0, 0 );
}
static WCHAR *build_wpad_url( const char *hostname, const struct addrinfo *ai )
@@ -1391,7 +1421,7 @@ BOOL WINAPI WinHttpDetectAutoProxyConfigUrl( DWORD flags, LPWSTR
*url )
if (!flags || !url)
{
- set_last_error( ERROR_INVALID_PARAMETER );
+ SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
if (get_system_proxy_autoconfig_url( system_url, sizeof(system_url) ))
@@ -1400,7 +1430,7 @@ BOOL WINAPI WinHttpDetectAutoProxyConfigUrl( DWORD flags, LPWSTR
*url )
if (!(urlW = strdupAW( system_url ))) return FALSE;
*url = urlW;
- set_last_error( ERROR_SUCCESS );
+ SetLastError( ERROR_SUCCESS );
return TRUE;
}
if (flags & WINHTTP_AUTO_DETECT_TYPE_DHCP)
@@ -1410,7 +1440,6 @@ BOOL WINAPI WinHttpDetectAutoProxyConfigUrl( DWORD flags, LPWSTR
*url )
}
if (flags & WINHTTP_AUTO_DETECT_TYPE_DNS_A)
{
-#ifdef HAVE_GETADDRINFO
char *fqdn, *domain, *p;
if (!(fqdn = get_computer_name( ComputerNamePhysicalDnsFullyQualified ))) return
FALSE;
@@ -1452,16 +1481,13 @@ BOOL WINAPI WinHttpDetectAutoProxyConfigUrl( DWORD flags, LPWSTR
*url )
}
heap_free( domain );
heap_free( fqdn );
-#else
- FIXME("getaddrinfo not found at build time\n");
-#endif
}
if (!ret)
{
- set_last_error( ERROR_WINHTTP_AUTODETECTION_FAILED );
+ SetLastError( ERROR_WINHTTP_AUTODETECTION_FAILED );
*url = NULL;
}
- else set_last_error( ERROR_SUCCESS );
+ else SetLastError( ERROR_SUCCESS );
return ret;
}
@@ -1620,7 +1646,7 @@ BOOL WINAPI WinHttpGetDefaultProxyConfiguration( WINHTTP_PROXY_INFO
*info )
info->lpszProxy = NULL;
info->lpszProxyBypass = NULL;
}
- set_last_error( ERROR_SUCCESS );
+ SetLastError( ERROR_SUCCESS );
return TRUE;
}
@@ -1640,7 +1666,7 @@ BOOL WINAPI WinHttpGetIEProxyConfigForCurrentUser(
WINHTTP_CURRENT_USER_IE_PROXY
if (!config)
{
- set_last_error( ERROR_INVALID_PARAMETER );
+ SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
memset( config, 0, sizeof(*config) );
@@ -1703,7 +1729,7 @@ done:
GlobalFree( config->lpszProxyBypass );
config->lpszProxyBypass = NULL;
}
- else set_last_error( ERROR_SUCCESS );
+ else SetLastError( ERROR_SUCCESS );
return ret;
}
@@ -1722,7 +1748,7 @@ static BOOL parse_script_result( const char *result,
WINHTTP_PROXY_INFO *info )
p = result;
while (*p == ' ') p++;
len = strlen( p );
- if (len >= 5 && !strncasecmp( p, "PROXY",
sizeof("PROXY") - 1 ))
+ if (len >= 5 && !_strnicmp( p, "PROXY",
sizeof("PROXY") - 1 ))
{
p += 5;
while (*p == ' ') p++;
@@ -1797,7 +1823,7 @@ done:
... 1269 lines suppressed ...