https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5bd6580fc63bb886686b62...
commit 5bd6580fc63bb886686b62caf26f3ea99a173922 Author: Amine Khaldi amine.khaldi@reactos.org AuthorDate: Sat Dec 7 13:05:48 2019 +0100 Commit: Amine Khaldi amine.khaldi@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 ...