diff --git a/dll/win32/winhttp/cookie.c b/dll/win32/winhttp/cookie.c index b4b2530..40c11c6 100644 --- a/dll/win32/winhttp/cookie.c +++ b/dll/win32/winhttp/cookie.c @@ -17,24 +17,39 @@ */ #include "config.h" +#include "ws2tcpip.h" #include -#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 6026a49..6711cd9 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 #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 a63f28c..e6c084b9 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 #include "windef.h" diff --git a/dll/win32/winhttp/net.c b/dll/win32/winhttp/net.c index e9ff86a..fcec7ad 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 #include -#include #include -#include -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -#ifdef HAVE_SYS_IOCTL_H -# include -#endif -#ifdef HAVE_SYS_FILIO_H -# include -#endif -#ifdef HAVE_POLL_H -# include -#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,47 @@ 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(); } -#endif - -void netconn_unload( void ) +static BOOL WINAPI winsock_startup( INIT_ONCE *once, void *param, void **ctx ) { -#ifndef HAVE_GETADDRINFO - DeleteCriticalSection(&cs_gethostbyname); -#endif + int ret; + WSADATA data; + if (!(ret = WSAStartup( MAKEWORD(1,1), &data ))) winsock_loaded = TRUE; + else ERR( "WSAStartup failed: %d\n", ret ); + return TRUE; +} + #ifdef __REACTOS__ - if(winsock_initialized) - WSACleanup(); +void winsock_init(void) +#else +static void winsock_init(void) #endif +{ + static INIT_ONCE once = INIT_ONCE_STATIC_INIT; + InitOnceExecuteOnce( &once, winsock_startup, NULL, NULL ); } -netconn_t *netconn_create( hostdata_t *host, const struct sockaddr_storage *sockaddr, int timeout ) +static void set_blocking( struct netconn *conn, BOOL blocking ) { - netconn_t *conn; + ULONG state = !blocking; + ioctlsocket( conn->socket, FIONBIO, &state ); +} + +struct netconn *netconn_create( struct hostdata *host, const struct sockaddr_storage *sockaddr, int timeout ) +{ + struct netconn *conn; unsigned int addr_len; BOOL ret = FALSE; - int res; - ULONG state; + +#ifndef __REACTOS__ + winsock_init(); +#endif conn = heap_alloc_zero(sizeof(*conn)); if (!conn) return NULL; @@ -311,8 +199,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 +216,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) + DWORD err = WSAGetLastError(); + if (err == WSAEWOULDBLOCK || err == WSAEINPROGRESS) { - 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; + 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 ); } - else - { - ret = TRUE; - break; - } - } - 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 +256,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 +358,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 +384,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 +395,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 +403,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 +421,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 +442,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 +505,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 +522,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 +536,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 +585,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 +653,12 @@ static DWORD resolve_hostname( const WCHAR *hostnameW, INTERNET_PORT port, struc break; } - freeaddrinfo( 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 ); + FreeAddrInfoW( res ); return ERROR_SUCCESS; -#endif } +#ifdef __REACTOS__ + struct resolve_args { const WCHAR *hostname; @@ -919,13 +698,64 @@ BOOL netconn_resolve( WCHAR *hostname, INTERNET_PORT port, struct sockaddr_stora if (ret) { - set_last_error( ret ); + SetLastError( ret ); + return FALSE; + } + return TRUE; +} + +#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; } -const void *netconn_get_certificate( netconn_t *conn ) +#endif /* __REACTOS__ */ + +const void *netconn_get_certificate( struct netconn *conn ) { const CERT_CONTEXT *ret; SECURITY_STATUS res; @@ -935,7 +765,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 5bb5b09..da28f7b 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 #include -#ifdef HAVE_ARPA_INET_H -# include -#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 7cfc240..4392f02 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 #include @@ -29,46 +26,33 @@ #include #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,49 +176,64 @@ 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, @@ -238,22 +241,20 @@ static const object_vtbl_t session_vtbl = }; #ifdef __REACTOS__ -BOOL netconn_init_winsock(); -#endif /* __REACTOS__ */ +void winsock_init(void); +#endif + /*********************************************************************** * 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 +265,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) @@ -297,19 +301,23 @@ HINTERNET WINAPI WinHttpOpen( LPCWSTR agent, DWORD access, LPCWSTR proxy, LPCWST if (!(handle = alloc_handle( &session->hdr ))) goto end; session->hdr.handle = handle; +#ifdef __REACTOS__ + winsock_init(); +#endif + 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 +330,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 +341,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 +353,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 +442,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 +473,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 +540,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 +594,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 +681,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 +705,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 +747,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 +767,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 +785,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 +793,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 +811,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 +829,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 +868,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 +882,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 +905,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 +920,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 +935,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 +947,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 +970,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 +997,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 +1005,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 +1013,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 +1165,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 +1185,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 +1194,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 +1226,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 +1239,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 +1253,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 +1286,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 +1298,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 +1312,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 +1350,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 +1429,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 +1438,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 +1448,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 +1489,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 +1654,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 +1674,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 +1737,7 @@ done: GlobalFree( config->lpszProxyBypass ); config->lpszProxyBypass = NULL; } - else set_last_error( ERROR_SUCCESS ); + else SetLastError( ERROR_SUCCESS ); return ret; } @@ -1722,7 +1756,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 +1831,7 @@ done: WinHttpCloseHandle( con ); WinHttpCloseHandle( ses ); heap_free( hostname ); - if (!buffer) set_last_error( ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT ); + if (!buffer) SetLastError( ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT ); return buffer; } @@ -1860,22 +1894,22 @@ BOOL WINAPI WinHttpGetProxyForUrl( HINTERNET hsession, LPCWSTR url, WINHTTP_AUTO { WCHAR *detected_pac_url = NULL; const WCHAR *pac_url; - session_t *session; + struct session *session; char *script; DWORD size; BOOL ret = FALSE; TRACE("%p, %s, %p, %p\n", hsession, debugstr_w(url), options, info); - 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 FALSE; } 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 FALSE; } if (!url || !options || !info || @@ -1885,7 +1919,7 @@ BOOL WINAPI WinHttpGetProxyForUrl( HINTERNET hsession, LPCWSTR url, WINHTTP_AUTO (options->dwFlags & WINHTTP_AUTOPROXY_CONFIG_URL))) { release_object( &session->hdr ); - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } if (options->dwFlags & WINHTTP_AUTOPROXY_AUTO_DETECT && @@ -1904,7 +1938,7 @@ BOOL WINAPI WinHttpGetProxyForUrl( HINTERNET hsession, LPCWSTR url, WINHTTP_AUTO done: GlobalFree( detected_pac_url ); release_object( &session->hdr ); - if (ret) set_last_error( ERROR_SUCCESS ); + if (ret) SetLastError( ERROR_SUCCESS ); return ret; } @@ -1922,7 +1956,7 @@ BOOL WINAPI WinHttpSetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info ) if (!info) { - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } switch (info->dwAccessType) @@ -1932,14 +1966,14 @@ BOOL WINAPI WinHttpSetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info ) case WINHTTP_ACCESS_TYPE_NAMED_PROXY: if (!info->lpszProxy) { - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } /* Only ASCII characters are allowed */ for (src = info->lpszProxy; *src; src++) if (*src > 0x7f) { - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } if (info->lpszProxyBypass) @@ -1947,13 +1981,13 @@ BOOL WINAPI WinHttpSetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info ) for (src = info->lpszProxyBypass; *src; src++) if (*src > 0x7f) { - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } } break; default: - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } @@ -2012,7 +2046,7 @@ BOOL WINAPI WinHttpSetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info ) } RegCloseKey( key ); } - if (ret) set_last_error( ERROR_SUCCESS ); + if (ret) SetLastError( ERROR_SUCCESS ); return ret; } @@ -2022,14 +2056,14 @@ BOOL WINAPI WinHttpSetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info ) WINHTTP_STATUS_CALLBACK WINAPI WinHttpSetStatusCallback( HINTERNET handle, WINHTTP_STATUS_CALLBACK callback, DWORD flags, DWORD_PTR reserved ) { - object_header_t *hdr; + struct object_header *hdr; WINHTTP_STATUS_CALLBACK ret; TRACE("%p, %p, 0x%08x, 0x%lx\n", handle, callback, flags, reserved); if (!(hdr = grab_object( handle ))) { - set_last_error( ERROR_INVALID_HANDLE ); + SetLastError( ERROR_INVALID_HANDLE ); return WINHTTP_INVALID_STATUS_CALLBACK; } ret = hdr->callback; @@ -2037,7 +2071,7 @@ WINHTTP_STATUS_CALLBACK WINAPI WinHttpSetStatusCallback( HINTERNET handle, WINHT hdr->notify_mask = flags; release_object( hdr ); - set_last_error( ERROR_SUCCESS ); + SetLastError( ERROR_SUCCESS ); return ret; } @@ -2047,66 +2081,66 @@ WINHTTP_STATUS_CALLBACK WINAPI WinHttpSetStatusCallback( HINTERNET handle, WINHT BOOL WINAPI WinHttpSetTimeouts( HINTERNET handle, int resolve, int connect, int send, int receive ) { BOOL ret = TRUE; - object_header_t *hdr; - request_t *request; - session_t *session; + struct object_header *hdr; TRACE("%p, %d, %d, %d, %d\n", handle, resolve, connect, send, receive); if (resolve < -1 || connect < -1 || send < -1 || receive < -1) { - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } if (!(hdr = grab_object( handle ))) { - set_last_error( ERROR_INVALID_HANDLE ); + SetLastError( ERROR_INVALID_HANDLE ); return FALSE; } switch(hdr->type) { - case WINHTTP_HANDLE_TYPE_REQUEST: - request = (request_t *)hdr; - request->connect_timeout = connect; - - if (resolve < 0) resolve = 0; - request->resolve_timeout = resolve; + case WINHTTP_HANDLE_TYPE_REQUEST: + { + struct request *request = (struct request *)hdr; + request->connect_timeout = connect; - if (send < 0) send = 0; - request->send_timeout = send; + if (resolve < 0) resolve = 0; + request->resolve_timeout = resolve; - if (receive < 0) receive = 0; - request->recv_timeout = receive; + if (send < 0) send = 0; + request->send_timeout = send; - if (request->netconn) - { - if (netconn_set_timeout( request->netconn, TRUE, send )) ret = FALSE; - if (netconn_set_timeout( request->netconn, FALSE, receive )) ret = FALSE; - } - break; + if (receive < 0) receive = 0; + request->receive_timeout = receive; - case WINHTTP_HANDLE_TYPE_SESSION: - session = (session_t *)hdr; - session->connect_timeout = connect; - - if (resolve < 0) resolve = 0; - session->resolve_timeout = resolve; + if (request->netconn) + { + if (netconn_set_timeout( request->netconn, TRUE, send )) ret = FALSE; + if (netconn_set_timeout( request->netconn, FALSE, receive )) ret = FALSE; + } + break; + } + case WINHTTP_HANDLE_TYPE_SESSION: + { + struct session *session = (struct session *)hdr; + session->connect_timeout = connect; - if (send < 0) send = 0; - session->send_timeout = send; + if (resolve < 0) resolve = 0; + session->resolve_timeout = resolve; - if (receive < 0) receive = 0; - session->recv_timeout = receive; - break; + if (send < 0) send = 0; + session->send_timeout = send; - default: - set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); - ret = FALSE; + if (receive < 0) receive = 0; + session->receive_timeout = receive; + break; + } + default: + SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); + ret = FALSE; } release_object( hdr ); - if (ret) set_last_error( ERROR_SUCCESS ); + if (ret) SetLastError( ERROR_SUCCESS ); return ret; } @@ -2131,7 +2165,7 @@ BOOL WINAPI WinHttpTimeFromSystemTime( const SYSTEMTIME *time, LPWSTR string ) if (!time || !string) { - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } @@ -2144,7 +2178,7 @@ BOOL WINAPI WinHttpTimeFromSystemTime( const SYSTEMTIME *time, LPWSTR string ) time->wMinute, time->wSecond ); - set_last_error( ERROR_SUCCESS ); + SetLastError( ERROR_SUCCESS ); return TRUE; } @@ -2161,7 +2195,7 @@ BOOL WINAPI WinHttpTimeToSystemTime( LPCWSTR string, SYSTEMTIME *time ) if (!string || !time) { - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } @@ -2172,7 +2206,7 @@ BOOL WINAPI WinHttpTimeToSystemTime( LPCWSTR string, SYSTEMTIME *time ) * a SYSTEMTIME structure. */ - set_last_error( ERROR_SUCCESS ); + SetLastError( ERROR_SUCCESS ); while (*s && !isalphaW( *s )) s++; if (s[0] == '\0' || s[1] == '\0' || s[2] == '\0') return TRUE; diff --git a/dll/win32/winhttp/url.c b/dll/win32/winhttp/url.c index 32b30da..e1255bd 100644 --- a/dll/win32/winhttp/url.c +++ b/dll/win32/winhttp/url.c @@ -17,16 +17,16 @@ */ #include "config.h" +#include "ws2tcpip.h" #include -#include "wine/debug.h" - #include "windef.h" #include "winbase.h" #include "winreg.h" #include "winhttp.h" #include "shlwapi.h" +#include "wine/debug.h" #include "winhttp_private.h" WINE_DEFAULT_DEBUG_CHANNEL(winhttp); @@ -34,27 +34,33 @@ WINE_DEFAULT_DEBUG_CHANNEL(winhttp); static const WCHAR scheme_http[] = {'h','t','t','p',0}; static const WCHAR scheme_https[] = {'h','t','t','p','s',0}; -static DWORD set_component( WCHAR **str, DWORD *str_len, WCHAR *value, DWORD len, DWORD flags, BOOL *overflow ) +struct url_component +{ + WCHAR **str; + DWORD *len; +}; + +static DWORD set_component( struct url_component *comp, WCHAR *value, DWORD len, DWORD flags, BOOL *overflow ) { - if (*str && !*str_len) return ERROR_INVALID_PARAMETER; - if (!*str_len) return ERROR_SUCCESS; - if (!*str) + if (*comp->str && !*comp->len) return ERROR_INVALID_PARAMETER; + if (!*comp->len) return ERROR_SUCCESS; + if (!*comp->str) { - if (len && *str_len && (flags & (ICU_DECODE|ICU_ESCAPE))) return ERROR_INVALID_PARAMETER; - *str = value; - *str_len = len; + if (len && *comp->len && (flags & (ICU_DECODE|ICU_ESCAPE))) return ERROR_INVALID_PARAMETER; + *comp->str = value; + *comp->len = len; } else { - if (len >= *str_len) + if (len >= *comp->len) { - *str_len = len+1; + *comp->len = len + 1; *overflow = TRUE; return ERROR_SUCCESS; } - memcpy( *str, value, len * sizeof(WCHAR) ); - (*str)[len] = 0; - *str_len = len; + memcpy( *comp->str, value, len * sizeof(WCHAR) ); + (*comp->str)[len] = 0; + *comp->len = len; } return ERROR_SUCCESS; } @@ -87,81 +93,71 @@ static WCHAR *decode_url( LPCWSTR url, DWORD *len ) return ret; } -static BOOL need_escape( WCHAR c ) +static inline BOOL need_escape( WCHAR ch ) { - if (isalnumW( c )) return FALSE; + static const WCHAR escapes[] = {' ','"','#','%','<','>','[','\\',']','^','`','{','|','}','~',0}; + const WCHAR *p = escapes; - if (c <= 31 || c >= 127) return TRUE; - else + if (ch <= 31 || ch >= 127) return TRUE; + while (*p) { - switch (c) - { - case ' ': - case '"': - case '#': - case '%': - case '<': - case '>': - case ']': - case '\\': - case '[': - case '^': - case '`': - case '{': - case '|': - case '}': - case '~': - return TRUE; - default: - return FALSE; - } + if (ch == *p++) return TRUE; } + return FALSE; } -static DWORD copy_escape( WCHAR *dst, const WCHAR *src, DWORD len ) +static BOOL escape_string( const WCHAR *src, DWORD src_len, WCHAR *dst, DWORD *dst_len ) { static const WCHAR hex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; - DWORD ret = len; - unsigned int i; WCHAR *p = dst; + DWORD i; - for (i = 0; i < len; i++, p++) + *dst_len = src_len; + for (i = 0; i < src_len; i++) { + if (src[i] > 0xff) return FALSE; if (need_escape( src[i] )) { - p[0] = '%'; - p[1] = hex[(src[i] >> 4) & 0xf]; - p[2] = hex[src[i] & 0xf]; - ret += 2; - p += 2; + if (dst) + { + p[0] = '%'; + p[1] = hex[(src[i] >> 4) & 0xf]; + p[2] = hex[src[i] & 0xf]; + p += 3; + } + *dst_len += 2; } - else *p = src[i]; + else if (dst) *p++ = src[i]; } - dst[ret] = 0; - return ret; + + if (dst) dst[*dst_len] = 0; + return TRUE; } -static WCHAR *escape_url( LPCWSTR url, DWORD *len ) +static DWORD escape_url( const WCHAR *url, DWORD *len, WCHAR **ret ) { - WCHAR *ret; - const WCHAR *p, *q; + const WCHAR *p; + DWORD len_base, len_path; - if ((p = q = strrchrW( url, '/' ))) + if ((p = strrchrW( url, '/' ))) { - while (*q) - { - if (need_escape( *q )) *len += 2; - q++; - } + len_base = p - url; + if (!escape_string( p, *len - len_base, NULL, &len_path )) return ERROR_INVALID_PARAMETER; } - if (!(ret = heap_alloc( (*len + 1) * sizeof(WCHAR) ))) return NULL; - if (!p) strcpyW( ret, url ); else { - memcpy( ret, url, (p - url) * sizeof(WCHAR) ); - copy_escape( ret + (p - url), p, q - p ); + len_base = *len; + len_path = 0; } - return ret; + + if (!(*ret = heap_alloc( (len_base + len_path + 1) * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY; + memcpy( *ret, url, len_base * sizeof(WCHAR) ); + + if (p) escape_string( p, *len - (p - url), *ret + len_base, &len_path ); + (*ret)[len_base + len_path] = 0; + + *len = len_base + len_path; + return ERROR_SUCCESS; } static DWORD parse_port( const WCHAR *str, DWORD len, INTERNET_PORT *ret ) @@ -183,24 +179,25 @@ static DWORD parse_port( const WCHAR *str, DWORD len, INTERNET_PORT *ret ) BOOL WINAPI WinHttpCrackUrl( LPCWSTR url, DWORD len, DWORD flags, LPURL_COMPONENTSW uc ) { WCHAR *p, *q, *r, *url_decoded = NULL, *url_escaped = NULL; - INTERNET_SCHEME scheme = 0; + INTERNET_SCHEME scheme_number = 0; + struct url_component scheme, username, password, hostname, path, extra; BOOL overflow = FALSE; DWORD err; TRACE("%s, %d, %x, %p\n", debugstr_wn(url, len), len, flags, uc); - if (!url || !uc || uc->dwStructSize != sizeof(URL_COMPONENTS)) + if (!url || !uc || uc->dwStructSize != sizeof(*uc)) { - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } if (!len) len = strlenW( url ); if (flags & ICU_ESCAPE) { - if (!(url_escaped = escape_url( url, &len ))) + if ((err = escape_url( url, &len, &url_escaped ))) { - set_last_error( ERROR_OUTOFMEMORY ); + SetLastError( err ); return FALSE; } url = url_escaped; @@ -209,25 +206,28 @@ BOOL WINAPI WinHttpCrackUrl( LPCWSTR url, DWORD len, DWORD flags, LPURL_COMPONEN { if (!(url_decoded = decode_url( url, &len ))) { - set_last_error( ERROR_OUTOFMEMORY ); + SetLastError( ERROR_OUTOFMEMORY ); return FALSE; } url = url_decoded; } if (!(p = strchrW( url, ':' ))) { - set_last_error( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ); + SetLastError( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ); return FALSE; } - if (p - url == 4 && !strncmpiW( url, scheme_http, 4 )) scheme = INTERNET_SCHEME_HTTP; - else if (p - url == 5 && !strncmpiW( url, scheme_https, 5 )) scheme = INTERNET_SCHEME_HTTPS; + if (p - url == 4 && !strncmpiW( url, scheme_http, 4 )) scheme_number = INTERNET_SCHEME_HTTP; + else if (p - url == 5 && !strncmpiW( url, scheme_https, 5 )) scheme_number = INTERNET_SCHEME_HTTPS; else { err = ERROR_WINHTTP_UNRECOGNIZED_SCHEME; goto exit; } - if ((err = set_component( &uc->lpszScheme, &uc->dwSchemeLength, (WCHAR *)url, p - url, flags, &overflow ))) goto exit; + scheme.str = &uc->lpszScheme; + scheme.len = &uc->dwSchemeLength; + + if ((err = set_component( &scheme, (WCHAR *)url, p - url, flags, &overflow ))) goto exit; p++; /* skip ':' */ if (!p[0] || p[0] != '/' || p[1] != '/') @@ -241,83 +241,105 @@ BOOL WINAPI WinHttpCrackUrl( LPCWSTR url, DWORD len, DWORD flags, LPURL_COMPONEN err = ERROR_WINHTTP_INVALID_URL; goto exit; } + + username.str = &uc->lpszUserName; + username.len = &uc->dwUserNameLength; + + password.str = &uc->lpszPassword; + password.len = &uc->dwPasswordLength; + if ((q = memchrW( p, '@', len - (p - url) )) && !(memchrW( p, '/', q - p ))) { + if ((r = memchrW( p, ':', q - p ))) { - if ((err = set_component( &uc->lpszUserName, &uc->dwUserNameLength, p, r - p, flags, &overflow ))) goto exit; + if ((err = set_component( &username, p, r - p, flags, &overflow ))) goto exit; r++; - if ((err = set_component( &uc->lpszPassword, &uc->dwPasswordLength, r, q - r, flags, &overflow ))) goto exit; + if ((err = set_component( &password, r, q - r, flags, &overflow ))) goto exit; } else { - if ((err = set_component( &uc->lpszUserName, &uc->dwUserNameLength, p, q - p, flags, &overflow ))) goto exit; - if ((err = set_component( &uc->lpszPassword, &uc->dwPasswordLength, NULL, 0, flags, &overflow ))) goto exit; + if ((err = set_component( &username, p, q - p, flags, &overflow ))) goto exit; + if ((err = set_component( &password, NULL, 0, flags, &overflow ))) goto exit; } p = q + 1; } else { - if ((err = set_component( &uc->lpszUserName, &uc->dwUserNameLength, NULL, 0, flags, &overflow ))) goto exit; - if ((err = set_component( &uc->lpszPassword, &uc->dwPasswordLength, NULL, 0, flags, &overflow ))) goto exit; + if ((err = set_component( &username, NULL, 0, flags, &overflow ))) goto exit; + if ((err = set_component( &password, NULL, 0, flags, &overflow ))) goto exit; } + + hostname.str = &uc->lpszHostName; + hostname.len = &uc->dwHostNameLength; + + path.str = &uc->lpszUrlPath; + path.len = &uc->dwUrlPathLength; + + extra.str = &uc->lpszExtraInfo; + extra.len = &uc->dwExtraInfoLength; + if ((q = memchrW( p, '/', len - (p - url) ))) { if ((r = memchrW( p, ':', q - p ))) { - if ((err = set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, r - p, flags, &overflow ))) goto exit; + if ((err = set_component( &hostname, p, r - p, flags, &overflow ))) goto exit; r++; if ((err = parse_port( r, q - r, &uc->nPort ))) goto exit; } else { - if ((err = set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, q - p, flags, &overflow ))) goto exit; - if (scheme == INTERNET_SCHEME_HTTP) uc->nPort = INTERNET_DEFAULT_HTTP_PORT; - if (scheme == INTERNET_SCHEME_HTTPS) uc->nPort = INTERNET_DEFAULT_HTTPS_PORT; + if ((err = set_component( &hostname, p, q - p, flags, &overflow ))) goto exit; + if (scheme_number == INTERNET_SCHEME_HTTP) uc->nPort = INTERNET_DEFAULT_HTTP_PORT; + if (scheme_number == INTERNET_SCHEME_HTTPS) uc->nPort = INTERNET_DEFAULT_HTTPS_PORT; } if ((r = memchrW( q, '?', len - (q - url) ))) { - if ((err = set_component( &uc->lpszUrlPath, &uc->dwUrlPathLength, q, r - q, flags, &overflow ))) goto exit; - if ((err = set_component( &uc->lpszExtraInfo, &uc->dwExtraInfoLength, r, len - (r - url), flags, &overflow ))) goto exit; + if (*extra.len) + { + if ((err = set_component( &path, q, r - q, flags, &overflow ))) goto exit; + if ((err = set_component( &extra, r, len - (r - url), flags, &overflow ))) goto exit; + } + else if ((err = set_component( &path, q, len - (q - url), flags, &overflow ))) goto exit; } else { - if ((err = set_component( &uc->lpszUrlPath, &uc->dwUrlPathLength, q, len - (q - url), flags, &overflow ))) goto exit; - if ((err = set_component( &uc->lpszExtraInfo, &uc->dwExtraInfoLength, (WCHAR *)url + len, 0, flags, &overflow ))) goto exit; + if ((err = set_component( &path, q, len - (q - url), flags, &overflow ))) goto exit; + if ((err = set_component( &extra, (WCHAR *)url + len, 0, flags, &overflow ))) goto exit; } } else { if ((r = memchrW( p, ':', len - (p - url) ))) { - if ((err = set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, r - p, flags, &overflow ))) goto exit; + if ((err = set_component( &hostname, p, r - p, flags, &overflow ))) goto exit; r++; if ((err = parse_port( r, len - (r - url), &uc->nPort ))) goto exit; } else { - if ((err = set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, len - (p - url), flags, &overflow ))) goto exit; - if (scheme == INTERNET_SCHEME_HTTP) uc->nPort = INTERNET_DEFAULT_HTTP_PORT; - if (scheme == INTERNET_SCHEME_HTTPS) uc->nPort = INTERNET_DEFAULT_HTTPS_PORT; + if ((err = set_component( &hostname, p, len - (p - url), flags, &overflow ))) goto exit; + if (scheme_number == INTERNET_SCHEME_HTTP) uc->nPort = INTERNET_DEFAULT_HTTP_PORT; + if (scheme_number == INTERNET_SCHEME_HTTPS) uc->nPort = INTERNET_DEFAULT_HTTPS_PORT; } - if ((err = set_component( &uc->lpszUrlPath, &uc->dwUrlPathLength, (WCHAR *)url + len, 0, flags, &overflow ))) goto exit; - if ((err = set_component( &uc->lpszExtraInfo, &uc->dwExtraInfoLength, (WCHAR *)url + len, 0, flags, &overflow ))) goto exit; + if ((err = set_component( &path, (WCHAR *)url + len, 0, flags, &overflow ))) goto exit; + if ((err = set_component( &extra, (WCHAR *)url + len, 0, flags, &overflow ))) goto exit; } - TRACE("scheme(%s) host(%s) port(%d) path(%s) extra(%s)\n", debugstr_wn( uc->lpszScheme, uc->dwSchemeLength ), - debugstr_wn( uc->lpszHostName, uc->dwHostNameLength ), uc->nPort, debugstr_wn( uc->lpszUrlPath, uc->dwUrlPathLength ), - debugstr_wn( uc->lpszExtraInfo, uc->dwExtraInfoLength )); + TRACE("scheme(%s) host(%s) port(%d) path(%s) extra(%s)\n", debugstr_wn(*scheme.str, *scheme.len), + debugstr_wn(*hostname.str, *hostname.len ), uc->nPort, debugstr_wn(*path.str, *path.len), + debugstr_wn(*extra.str, *extra.len)); exit: if (!err) { if (overflow) err = ERROR_INSUFFICIENT_BUFFER; - uc->nScheme = scheme; + uc->nScheme = scheme_number; } heap_free( url_decoded ); heap_free( url_escaped ); - set_last_error( err ); + SetLastError( err ); return !err; } @@ -342,7 +364,7 @@ static BOOL uses_default_port( INTERNET_SCHEME scheme, INTERNET_PORT port ) return FALSE; } -static DWORD comp_length( DWORD len, DWORD flags, WCHAR *comp ) +static DWORD get_comp_length( DWORD len, DWORD flags, WCHAR *comp ) { DWORD ret; unsigned int i; @@ -353,7 +375,7 @@ static DWORD comp_length( DWORD len, DWORD flags, WCHAR *comp ) return ret; } -static BOOL calc_length( URL_COMPONENTS *uc, DWORD flags, LPDWORD len ) +static BOOL get_url_length( URL_COMPONENTS *uc, DWORD flags, DWORD *len ) { static const WCHAR formatW[] = {'%','u',0}; INTERNET_SCHEME scheme; @@ -361,7 +383,7 @@ static BOOL calc_length( URL_COMPONENTS *uc, DWORD flags, LPDWORD len ) *len = 0; if (uc->lpszScheme) { - DWORD scheme_len = comp_length( uc->dwSchemeLength, 0, uc->lpszScheme ); + DWORD scheme_len = get_comp_length( uc->dwSchemeLength, 0, uc->lpszScheme ); *len += scheme_len; scheme = get_scheme( uc->lpszScheme, scheme_len ); } @@ -371,30 +393,29 @@ static BOOL calc_length( URL_COMPONENTS *uc, DWORD flags, LPDWORD len ) if (!scheme) scheme = INTERNET_SCHEME_HTTP; *len += strlenW( get_scheme_string( scheme ) ); } - *len += 1; /* ':' */ - if (uc->lpszHostName) *len += 2; /* "//" */ + *len += 3; /* "://" */ if (uc->lpszUserName) { - *len += comp_length( uc->dwUserNameLength, 0, uc->lpszUserName ); + *len += get_comp_length( uc->dwUserNameLength, 0, uc->lpszUserName ); *len += 1; /* "@" */ } else { if (uc->lpszPassword) { - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } } if (uc->lpszPassword) { *len += 1; /* ":" */ - *len += comp_length( uc->dwPasswordLength, 0, uc->lpszPassword ); + *len += get_comp_length( uc->dwPasswordLength, 0, uc->lpszPassword ); } if (uc->lpszHostName) { - *len += comp_length( uc->dwHostNameLength, 0, uc->lpszHostName ); + *len += get_comp_length( uc->dwHostNameLength, 0, uc->lpszHostName ); if (!uses_default_port( scheme, uc->nPort )) { @@ -405,8 +426,8 @@ static BOOL calc_length( URL_COMPONENTS *uc, DWORD flags, LPDWORD len ) } if (uc->lpszUrlPath && *uc->lpszUrlPath != '/') *len += 1; /* '/' */ } - if (uc->lpszUrlPath) *len += comp_length( uc->dwUrlPathLength, flags, uc->lpszUrlPath ); - if (uc->lpszExtraInfo) *len += comp_length( uc->dwExtraInfoLength, flags, uc->lpszExtraInfo ); + if (uc->lpszUrlPath) *len += get_comp_length( uc->dwUrlPathLength, flags, uc->lpszUrlPath ); + if (uc->lpszExtraInfo) *len += get_comp_length( uc->dwExtraInfoLength, flags, uc->lpszExtraInfo ); return TRUE; } @@ -416,29 +437,28 @@ static BOOL calc_length( URL_COMPONENTS *uc, DWORD flags, LPDWORD len ) BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDWORD required ) { static const WCHAR formatW[] = {'%','u',0}; - static const WCHAR twoslashW[] = {'/','/'}; - DWORD len; + DWORD len, len_escaped; INTERNET_SCHEME scheme; TRACE("%p, 0x%08x, %p, %p\n", uc, flags, url, required); if (!uc || uc->dwStructSize != sizeof(URL_COMPONENTS) || !required) { - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } - if (!calc_length( uc, flags, &len )) return FALSE; + if (!get_url_length( uc, flags, &len )) return FALSE; if (*required < len) { *required = len + 1; - set_last_error( ERROR_INSUFFICIENT_BUFFER ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); return FALSE; } if (!url) { - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } @@ -446,7 +466,7 @@ BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDW *required = len; if (uc->lpszScheme) { - len = comp_length( uc->dwSchemeLength, 0, uc->lpszScheme ); + len = get_comp_length( uc->dwSchemeLength, 0, uc->lpszScheme ); memcpy( url, uc->lpszScheme, len * sizeof(WCHAR) ); url += len; @@ -465,58 +485,55 @@ BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDW url += len; } - /* all schemes are followed by at least a colon */ - *url = ':'; - url++; + *url++ = ':'; + *url++ = '/'; + *url++ = '/'; - if (uc->lpszHostName) - { - memcpy( url, twoslashW, sizeof(twoslashW) ); - url += sizeof(twoslashW) / sizeof(twoslashW[0]); - } if (uc->lpszUserName) { - len = comp_length( uc->dwUserNameLength, 0, uc->lpszUserName ); + len = get_comp_length( uc->dwUserNameLength, 0, uc->lpszUserName ); memcpy( url, uc->lpszUserName, len * sizeof(WCHAR) ); url += len; if (uc->lpszPassword) { - *url = ':'; - url++; - - len = comp_length( uc->dwPasswordLength, 0, uc->lpszPassword ); + *url++ = ':'; + len = get_comp_length( uc->dwPasswordLength, 0, uc->lpszPassword ); memcpy( url, uc->lpszPassword, len * sizeof(WCHAR) ); url += len; } - *url = '@'; - url++; + *url++ = '@'; } if (uc->lpszHostName) { - len = comp_length( uc->dwHostNameLength, 0, uc->lpszHostName ); + len = get_comp_length( uc->dwHostNameLength, 0, uc->lpszHostName ); memcpy( url, uc->lpszHostName, len * sizeof(WCHAR) ); url += len; if (!uses_default_port( scheme, uc->nPort )) { - *url = ':'; - url++; - + *url++ = ':'; url += sprintfW( url, formatW, uc->nPort ); } /* add slash between hostname and path if necessary */ if (uc->lpszUrlPath && *uc->lpszUrlPath != '/') { - *url = '/'; - url++; + *url++ = '/'; } } if (uc->lpszUrlPath) { - len = comp_length( uc->dwUrlPathLength, 0, uc->lpszUrlPath ); - if (flags & ICU_ESCAPE) url += copy_escape( url, uc->lpszUrlPath, len ); + len = get_comp_length( uc->dwUrlPathLength, 0, uc->lpszUrlPath ); + if (flags & ICU_ESCAPE) + { + if (!escape_string( uc->lpszUrlPath, len, url, &len_escaped )) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + url += len_escaped; + } else { memcpy( url, uc->lpszUrlPath, len * sizeof(WCHAR) ); @@ -525,8 +542,16 @@ BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDW } if (uc->lpszExtraInfo) { - len = comp_length( uc->dwExtraInfoLength, 0, uc->lpszExtraInfo ); - if (flags & ICU_ESCAPE) url += copy_escape( url, uc->lpszExtraInfo, len ); + len = get_comp_length( uc->dwExtraInfoLength, 0, uc->lpszExtraInfo ); + if (flags & ICU_ESCAPE) + { + if (!escape_string( uc->lpszExtraInfo, len, url, &len_escaped )) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + url += len_escaped; + } else { memcpy( url, uc->lpszExtraInfo, len * sizeof(WCHAR) ); @@ -534,6 +559,6 @@ BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDW } } *url = 0; - set_last_error( ERROR_SUCCESS ); + SetLastError( ERROR_SUCCESS ); return TRUE; } diff --git a/dll/win32/winhttp/winhttp_private.h b/dll/win32/winhttp/winhttp_private.h index d5ec9ca..3732dfa 100644 --- a/dll/win32/winhttp/winhttp_private.h +++ b/dll/win32/winhttp/winhttp_private.h @@ -27,25 +27,9 @@ #include "wine/list.h" #include "wine/unicode.h" -#include -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -#ifdef HAVE_NETINET_IN_H -# include -#endif -#ifdef HAVE_NETDB_H -# include -#endif -#if defined(__MINGW32__) || defined (_MSC_VER) -# include -#else -# define closesocket close -# define ioctlsocket ioctl -#endif - #include "ole2.h" #include "sspi.h" +#include "wincrypt.h" static const WCHAR getW[] = {'G','E','T',0}; static const WCHAR postW[] = {'P','O','S','T',0}; @@ -55,20 +39,19 @@ static const WCHAR http1_0[] = {'H','T','T','P','/','1','.','0',0}; static const WCHAR http1_1[] = {'H','T','T','P','/','1','.','1',0}; static const WCHAR chunkedW[] = {'c','h','u','n','k','e','d',0}; -typedef struct _object_header_t object_header_t; - -typedef struct +struct object_header; +struct object_vtbl { - void (*destroy)( object_header_t * ); - BOOL (*query_option)( object_header_t *, DWORD, void *, DWORD * ); - BOOL (*set_option)( object_header_t *, DWORD, void *, DWORD ); -} object_vtbl_t; + void (*destroy)( struct object_header * ); + BOOL (*query_option)( struct object_header *, DWORD, void *, DWORD * ); + BOOL (*set_option)( struct object_header *, DWORD, void *, DWORD ); +}; -struct _object_header_t +struct object_header { DWORD type; HINTERNET handle; - const object_vtbl_t *vtbl; + const struct object_vtbl *vtbl; DWORD flags; DWORD disable_flags; DWORD logon_policy; @@ -82,71 +65,58 @@ struct _object_header_t struct list children; }; -typedef struct +struct hostdata { struct list entry; - WCHAR *name; - struct list cookies; -} domain_t; - -typedef struct -{ - struct list entry; - WCHAR *name; - WCHAR *value; - WCHAR *path; -} cookie_t; - -typedef struct { - struct list entry; LONG ref; WCHAR *hostname; INTERNET_PORT port; BOOL secure; struct list connections; -} hostdata_t; +}; -typedef struct +struct session { - object_header_t hdr; - LPWSTR agent; + struct object_header hdr; + CRITICAL_SECTION cs; + WCHAR *agent; DWORD access; int resolve_timeout; int connect_timeout; int send_timeout; - int recv_timeout; - LPWSTR proxy_server; - LPWSTR proxy_bypass; - LPWSTR proxy_username; - LPWSTR proxy_password; + int receive_timeout; + int receive_response_timeout; + WCHAR *proxy_server; + WCHAR *proxy_bypass; + WCHAR *proxy_username; + WCHAR *proxy_password; struct list cookie_cache; HANDLE unload_event; - CredHandle cred_handle; - BOOL cred_handle_initialized; DWORD secure_protocols; -} session_t; + DWORD passport_flags; +}; -typedef struct +struct connect { - object_header_t hdr; - session_t *session; - LPWSTR hostname; /* final destination of the request */ - LPWSTR servername; /* name of the server we directly connect to */ - LPWSTR username; - LPWSTR password; + struct object_header hdr; + struct session *session; + WCHAR *hostname; /* final destination of the request */ + WCHAR *servername; /* name of the server we directly connect to */ + WCHAR *username; + WCHAR *password; INTERNET_PORT hostport; INTERNET_PORT serverport; struct sockaddr_storage sockaddr; BOOL resolved; -} connect_t; +}; -typedef struct +struct netconn { struct list entry; int socket; struct sockaddr_storage sockaddr; BOOL secure; /* SSL active on connection? */ - hostdata_t *host; + struct hostdata *host; ULONGLONG keep_until; CtxtHandle ssl_ctx; SecPkgContext_StreamSizes ssl_sizes; @@ -156,14 +126,14 @@ typedef struct char *peek_msg; char *peek_msg_mem; size_t peek_len; -} netconn_t; +}; -typedef struct +struct header { - LPWSTR field; - LPWSTR value; + WCHAR *field; + WCHAR *value; BOOL is_request; /* part of request headers? */ -} header_t; +}; enum auth_target { @@ -197,23 +167,29 @@ struct authinfo BOOL finished; /* finished authenticating */ }; -typedef struct +struct request { - object_header_t hdr; - connect_t *connect; - LPWSTR verb; - LPWSTR path; - LPWSTR version; - LPWSTR raw_headers; + struct object_header hdr; + struct connect *connect; + WCHAR *verb; + WCHAR *path; + WCHAR *version; + WCHAR *raw_headers; void *optional; DWORD optional_len; - netconn_t *netconn; + struct netconn *netconn; DWORD security_flags; + BOOL check_revocation; + const CERT_CONTEXT *server_cert; + const CERT_CONTEXT *client_cert; + CredHandle cred_handle; + BOOL cred_handle_initialized; int resolve_timeout; int connect_timeout; int send_timeout; - int recv_timeout; - LPWSTR status_text; + int receive_timeout; + int receive_response_timeout; + WCHAR *status_text; DWORD content_length; /* total number of bytes to be read */ DWORD content_read; /* bytes read so far */ BOOL read_chunked; /* are we reading in chunked mode? */ @@ -222,13 +198,17 @@ typedef struct DWORD read_pos; /* current read position in read_buf */ DWORD read_size; /* valid data size in read_buf */ char read_buf[8192]; /* buffer for already read but not returned data */ - header_t *headers; + struct header *headers; DWORD num_headers; struct authinfo *authinfo; struct authinfo *proxy_authinfo; HANDLE task_wait; HANDLE task_cancel; +#ifdef __REACTOS__ HANDLE task_thread; +#else + BOOL task_proc_running; +#endif struct list task_queue; CRITICAL_SECTION task_cs; struct @@ -236,89 +216,84 @@ typedef struct WCHAR *username; WCHAR *password; } creds[TARGET_MAX][SCHEME_MAX]; -} request_t; - -typedef struct _task_header_t task_header_t; +}; -struct _task_header_t +struct task_header { struct list entry; - request_t *request; - void (*proc)( task_header_t * ); + struct request *request; + void (*proc)( struct task_header * ); }; -typedef struct +struct send_request { - task_header_t hdr; - LPWSTR headers; + struct task_header hdr; + WCHAR *headers; DWORD headers_len; - LPVOID optional; + void *optional; DWORD optional_len; DWORD total_len; DWORD_PTR context; -} send_request_t; +}; -typedef struct +struct receive_response { - task_header_t hdr; -} receive_response_t; + struct task_header hdr; +}; -typedef struct +struct query_data { - task_header_t hdr; - LPDWORD available; -} query_data_t; + struct task_header hdr; + DWORD *available; +}; -typedef struct +struct read_data { - task_header_t hdr; - LPVOID buffer; + struct task_header hdr; + void *buffer; DWORD to_read; - LPDWORD read; -} read_data_t; + DWORD *read; +}; -typedef struct +struct write_data { - task_header_t hdr; - LPCVOID buffer; + struct task_header hdr; + const void *buffer; DWORD to_write; - LPDWORD written; -} write_data_t; + DWORD *written; +}; -object_header_t *addref_object( object_header_t * ) DECLSPEC_HIDDEN; -object_header_t *grab_object( HINTERNET ) DECLSPEC_HIDDEN; -void release_object( object_header_t * ) DECLSPEC_HIDDEN; -HINTERNET alloc_handle( object_header_t * ) DECLSPEC_HIDDEN; +struct object_header *addref_object( struct object_header * ) DECLSPEC_HIDDEN; +struct object_header *grab_object( HINTERNET ) DECLSPEC_HIDDEN; +void release_object( struct object_header * ) DECLSPEC_HIDDEN; +HINTERNET alloc_handle( struct object_header * ) DECLSPEC_HIDDEN; BOOL free_handle( HINTERNET ) DECLSPEC_HIDDEN; -void set_last_error( DWORD ) DECLSPEC_HIDDEN; -DWORD get_last_error( void ) DECLSPEC_HIDDEN; -void send_callback( object_header_t *, DWORD, LPVOID, DWORD ) DECLSPEC_HIDDEN; -void close_connection( request_t * ) DECLSPEC_HIDDEN; +void send_callback( struct object_header *, DWORD, LPVOID, DWORD ) DECLSPEC_HIDDEN; +void close_connection( struct request * ) DECLSPEC_HIDDEN; -BOOL netconn_close( netconn_t * ) DECLSPEC_HIDDEN; -netconn_t *netconn_create( hostdata_t *, const struct sockaddr_storage *, int ) DECLSPEC_HIDDEN; +void netconn_close( struct netconn * ) DECLSPEC_HIDDEN; +struct netconn *netconn_create( struct hostdata *, const struct sockaddr_storage *, int ) DECLSPEC_HIDDEN; void netconn_unload( void ) DECLSPEC_HIDDEN; -ULONG netconn_query_data_available( netconn_t * ) DECLSPEC_HIDDEN; -BOOL netconn_recv( netconn_t *, void *, size_t, int, int * ) DECLSPEC_HIDDEN; +ULONG netconn_query_data_available( struct netconn * ) DECLSPEC_HIDDEN; +BOOL netconn_recv( struct netconn *, void *, size_t, int, int * ) DECLSPEC_HIDDEN; BOOL netconn_resolve( WCHAR *, INTERNET_PORT, struct sockaddr_storage *, int ) DECLSPEC_HIDDEN; -BOOL netconn_secure_connect( netconn_t *, WCHAR *, DWORD, CredHandle * ) DECLSPEC_HIDDEN; -BOOL netconn_send( netconn_t *, const void *, size_t, int * ) DECLSPEC_HIDDEN; -DWORD netconn_set_timeout( netconn_t *, BOOL, int ) DECLSPEC_HIDDEN; -BOOL netconn_is_alive( netconn_t * ) DECLSPEC_HIDDEN; -const void *netconn_get_certificate( netconn_t * ) DECLSPEC_HIDDEN; -int netconn_get_cipher_strength( netconn_t * ) DECLSPEC_HIDDEN; - -BOOL set_cookies( request_t *, const WCHAR * ) DECLSPEC_HIDDEN; -BOOL add_cookie_headers( request_t * ) DECLSPEC_HIDDEN; -BOOL add_request_headers( request_t *, LPCWSTR, DWORD, DWORD ) DECLSPEC_HIDDEN; -void delete_domain( domain_t * ) DECLSPEC_HIDDEN; -BOOL set_server_for_hostname( connect_t *, LPCWSTR, INTERNET_PORT ) DECLSPEC_HIDDEN; +BOOL netconn_secure_connect( struct netconn *, WCHAR *, DWORD, CredHandle *, BOOL ) DECLSPEC_HIDDEN; +BOOL netconn_send( struct netconn *, const void *, size_t, int * ) DECLSPEC_HIDDEN; +DWORD netconn_set_timeout( struct netconn *, BOOL, int ) DECLSPEC_HIDDEN; +BOOL netconn_is_alive( struct netconn * ) DECLSPEC_HIDDEN; +const void *netconn_get_certificate( struct netconn * ) DECLSPEC_HIDDEN; +int netconn_get_cipher_strength( struct netconn * ) DECLSPEC_HIDDEN; + +BOOL set_cookies( struct request *, const WCHAR * ) DECLSPEC_HIDDEN; +BOOL add_cookie_headers( struct request * ) DECLSPEC_HIDDEN; +BOOL add_request_headers( struct request *, const WCHAR *, DWORD, DWORD ) DECLSPEC_HIDDEN; +void destroy_cookies( struct session * ) DECLSPEC_HIDDEN; +BOOL set_server_for_hostname( struct connect *, const WCHAR *, INTERNET_PORT ) DECLSPEC_HIDDEN; void destroy_authinfo( struct authinfo * ) DECLSPEC_HIDDEN; -void release_host( hostdata_t *host ) DECLSPEC_HIDDEN; - -BOOL process_header( request_t *request, LPCWSTR field, LPCWSTR value, DWORD flags, BOOL request_only ) DECLSPEC_HIDDEN; +void release_host( struct hostdata * ) DECLSPEC_HIDDEN; +BOOL process_header( struct request *, const WCHAR *, const WCHAR *, DWORD, BOOL ) DECLSPEC_HIDDEN; extern HRESULT WinHttpRequest_create( void ** ) DECLSPEC_HIDDEN; void release_typelib( void ) DECLSPEC_HIDDEN;