[ros-diffs] [cwittich] 41333: sync urlmon and winhttp with wine 1.1.23

cwittich at svn.reactos.org cwittich at svn.reactos.org
Sun Jun 7 14:32:06 CEST 2009


Author: cwittich
Date: Sun Jun  7 16:32:05 2009
New Revision: 41333

URL: http://svn.reactos.org/svn/reactos?rev=41333&view=rev
Log:
sync urlmon and winhttp with wine 1.1.23

Added:
    trunk/reactos/dll/win32/winhttp/cookie.c   (with props)
    trunk/reactos/dll/win32/winhttp/url.c   (with props)
Modified:
    trunk/reactos/dll/win32/urlmon/bindprot.c
    trunk/reactos/dll/win32/urlmon/http.c
    trunk/reactos/dll/win32/urlmon/urlmon_main.c
    trunk/reactos/dll/win32/winhttp/main.c
    trunk/reactos/dll/win32/winhttp/net.c
    trunk/reactos/dll/win32/winhttp/request.c
    trunk/reactos/dll/win32/winhttp/session.c
    trunk/reactos/dll/win32/winhttp/winhttp.rbuild
    trunk/reactos/dll/win32/winhttp/winhttp_private.h
    trunk/reactos/include/psdk/winhttp.h

Modified: trunk/reactos/dll/win32/urlmon/bindprot.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/bindprot.c?rev=41333&r1=41332&r2=41333&view=diff
==============================================================================
--- trunk/reactos/dll/win32/urlmon/bindprot.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/urlmon/bindprot.c [iso-8859-1] Sun Jun  7 16:32:05 2009
@@ -608,10 +608,14 @@
 static HRESULT WINAPI ProtocolHandler_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
 {
     BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
+    HRESULT hres;
 
     TRACE("(%p)->(%p)\n", This, pProtocolData);
 
-    return IInternetProtocol_Continue(This->protocol, pProtocolData);
+    hres = IInternetProtocol_Continue(This->protocol, pProtocolData);
+
+    heap_free(pProtocolData);
+    return hres;
 }
 
 static HRESULT WINAPI ProtocolHandler_Abort(IInternetProtocol *iface, HRESULT hrReason,
@@ -874,14 +878,14 @@
 
 typedef struct {
     task_header_t header;
-    PROTOCOLDATA data;
+    PROTOCOLDATA *data;
 } switch_task_t;
 
 static void switch_proc(BindProtocol *bind, task_header_t *t)
 {
     switch_task_t *task = (switch_task_t*)t;
 
-    IInternetProtocol_Continue(bind->protocol_handler, &task->data);
+    IInternetProtocol_Continue(bind->protocol_handler, task->data);
 
     heap_free(task);
 }
@@ -890,11 +894,17 @@
         PROTOCOLDATA *pProtocolData)
 {
     BindProtocol *This = PROTSINK_THIS(iface);
+    PROTOCOLDATA *data;
 
     TRACE("(%p)->(%p)\n", This, pProtocolData);
 
     TRACE("flags %x state %x data %p cb %u\n", pProtocolData->grfFlags, pProtocolData->dwState,
           pProtocolData->pData, pProtocolData->cbData);
+
+    data = heap_alloc(sizeof(PROTOCOLDATA));
+    if(!data)
+        return E_OUTOFMEMORY;
+    memcpy(data, pProtocolData, sizeof(PROTOCOLDATA));
 
     if(!do_direct_notif(This)) {
         switch_task_t *task;
@@ -903,18 +913,18 @@
         if(!task)
             return E_OUTOFMEMORY;
 
-        task->data = *pProtocolData;
+        task->data = data;
 
         push_task(This, &task->header, switch_proc);
         return S_OK;
     }
 
     if(!This->protocol_sink) {
-        IInternetProtocol_Continue(This->protocol_handler, pProtocolData);
+        IInternetProtocol_Continue(This->protocol_handler, data);
         return S_OK;
     }
 
-    return IInternetProtocolSink_Switch(This->protocol_sink, pProtocolData);
+    return IInternetProtocolSink_Switch(This->protocol_sink, data);
 }
 
 static void report_progress(BindProtocol *This, ULONG status_code, LPCWSTR status_text)

Modified: trunk/reactos/dll/win32/urlmon/http.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/http.c?rev=41333&r1=41332&r2=41333&view=diff
==============================================================================
--- trunk/reactos/dll/win32/urlmon/http.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/urlmon/http.c [iso-8859-1] Sun Jun  7 16:32:05 2009
@@ -85,7 +85,7 @@
     BYTE security_id[512];
     DWORD len = 0;
     ULONG num = 0;
-    BOOL res;
+    BOOL res, b;
     HRESULT hres;
 
     static const WCHAR wszBindVerb[BINDVERB_CUSTOM][5] =
@@ -208,6 +208,11 @@
         else
             optional = (LPWSTR)This->base.bind_info.stgmedData.u.hGlobal;
     }
+
+    b = TRUE;
+    res = InternetSetOptionW(This->base.request, INTERNET_OPTION_HTTP_DECODING, &b, sizeof(b));
+    if(!res)
+        WARN("InternetSetOption(INTERNET_OPTION_HTTP_DECODING) failed: %08x\n", GetLastError());
 
     res = HttpSendRequestW(This->base.request, This->full_header, lstrlenW(This->full_header),
             optional, optional ? This->base.bind_info.cbstgmedData : 0);

Modified: trunk/reactos/dll/win32/urlmon/urlmon_main.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/urlmon_main.c?rev=41333&r1=41332&r2=41333&view=diff
==============================================================================
--- trunk/reactos/dll/win32/urlmon/urlmon_main.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/urlmon/urlmon_main.c [iso-8859-1] Sun Jun  7 16:32:05 2009
@@ -36,7 +36,7 @@
 
 HINSTANCE URLMON_hInstance = 0;
 static HMODULE hCabinet = NULL;
-static DWORD urlmon_tls;
+static DWORD urlmon_tls = TLS_OUT_OF_INDEXES;
 
 static void init_session(BOOL);
 
@@ -56,9 +56,12 @@
 {
     tls_data_t *data;
 
-    if(!urlmon_tls) {
+    if(urlmon_tls == TLS_OUT_OF_INDEXES) {
         DWORD tls = TlsAlloc();
-        tls = InterlockedCompareExchange((LONG*)&urlmon_tls, tls, 0);
+        if(tls == TLS_OUT_OF_INDEXES)
+            return NULL;
+
+        tls = InterlockedCompareExchange((LONG*)&urlmon_tls, tls, TLS_OUT_OF_INDEXES);
         if(tls != urlmon_tls)
             TlsFree(tls);
     }
@@ -83,7 +86,7 @@
 {
     tls_data_t *data;
 
-    if(!urlmon_tls)
+    if(urlmon_tls == TLS_OUT_OF_INDEXES)
         return;
 
     while(!list_empty(&tls_list)) {
@@ -99,7 +102,7 @@
 {
     tls_data_t *data;
 
-    if(!urlmon_tls)
+    if(urlmon_tls == TLS_OUT_OF_INDEXES)
         return;
 
     data = TlsGetValue(urlmon_tls);

Added: trunk/reactos/dll/win32/winhttp/cookie.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/cookie.c?rev=41333&view=auto
==============================================================================
--- trunk/reactos/dll/win32/winhttp/cookie.c (added)
+++ trunk/reactos/dll/win32/winhttp/cookie.c [iso-8859-1] Sun Jun  7 16:32:05 2009
@@ -1,0 +1,281 @@
+/*
+ * Copyright 2008 Hans Leidekker for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include <stdarg.h>
+
+#include "wine/debug.h"
+#include "wine/list.h"
+
+#include "windef.h"
+#include "winbase.h"
+#include "winhttp.h"
+
+#include "winhttp_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
+
+static domain_t *add_domain( session_t *session, WCHAR *name )
+{
+    domain_t *domain;
+
+    if (!(domain = heap_alloc_zero( sizeof(domain_t) ))) return NULL;
+
+    list_init( &domain->entry );
+    list_init( &domain->cookies );
+
+    domain->name = name;
+    list_add_tail( &session->cookie_cache, &domain->entry );
+
+    TRACE("%s\n", debugstr_w(domain->name));
+    return domain;
+}
+
+static cookie_t *find_cookie( domain_t *domain, const WCHAR *path, const WCHAR *name )
+{
+    struct list *item;
+    cookie_t *cookie;
+
+    LIST_FOR_EACH( item, &domain->cookies )
+    {
+        cookie = LIST_ENTRY( item, cookie_t, entry );
+        if (!strcmpW( cookie->path, path ) && !strcmpiW( cookie->name, name ))
+        {
+            TRACE("found %s=%s\n", debugstr_w(cookie->name), debugstr_w(cookie->value));
+            return cookie;
+         }
+    }
+    return NULL;
+}
+
+static BOOL domain_match( const WCHAR *name, domain_t *domain, BOOL partial )
+{
+    TRACE("comparing %s with %s\n", debugstr_w(name), debugstr_w(domain->name));
+
+    if (partial && !strstrW( name, domain->name )) return FALSE;
+    else if (!partial && strcmpW( name, domain->name )) return FALSE;
+    return TRUE;
+}
+
+static void free_cookie( cookie_t *cookie )
+{
+    heap_free( cookie->name );
+    heap_free( cookie->value );
+    heap_free( cookie->path );
+    heap_free( cookie );
+}
+
+static void delete_cookie( cookie_t *cookie )
+{
+    list_remove( &cookie->entry );
+    free_cookie( cookie );
+}
+
+void delete_domain( domain_t *domain )
+{
+    cookie_t *cookie;
+    struct list *item, *next;
+
+    LIST_FOR_EACH_SAFE( item, next, &domain->cookies )
+    {
+        cookie = LIST_ENTRY( item, cookie_t, entry );
+        delete_cookie( cookie );
+    }
+
+    list_remove( &domain->entry );
+    heap_free( domain->name );
+    heap_free( domain );
+}
+
+static BOOL add_cookie( session_t *session, cookie_t *cookie, WCHAR *domain_name, WCHAR *path )
+{
+    domain_t *domain = NULL;
+    cookie_t *old_cookie;
+    struct list *item;
+
+    LIST_FOR_EACH( item, &session->cookie_cache )
+    {
+        domain = LIST_ENTRY( item, domain_t, entry );
+        if (domain_match( domain_name, domain, FALSE )) break;
+        domain = NULL;
+    }
+    if (!domain)
+    {
+        if (!(domain = add_domain( session, domain_name ))) return FALSE;
+    }
+    else if ((old_cookie = find_cookie( domain, path, cookie->name ))) delete_cookie( old_cookie );
+
+    cookie->path = path;
+    list_add_tail( &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));
+    return TRUE;
+}
+
+static cookie_t *parse_cookie( const WCHAR *string )
+{
+    cookie_t *cookie;
+    const WCHAR *p;
+    int len;
+
+    if (!(cookie = heap_alloc_zero( sizeof(cookie_t) ))) return NULL;
+
+    list_init( &cookie->entry );
+
+    if (!(p = strchrW( string, '=' )))
+    {
+        WARN("no '=' in %s\n", debugstr_w(string));
+        return NULL;
+    }
+    if (p == string)
+    {
+        WARN("empty cookie name in %s\n", debugstr_w(string));
+        return NULL;
+    }
+    len = p - string;
+    if (!(cookie->name = heap_alloc( (len + 1) * sizeof(WCHAR) )))
+    {
+        heap_free( cookie );
+        return NULL;
+    }
+    memcpy( cookie->name, string, len * sizeof(WCHAR) );
+    cookie->name[len] = 0;
+
+    p++; /* skip '=' */
+    while (*p == ' ') p++;
+
+    len = strlenW( p );
+    if (!(cookie->value = heap_alloc( (len + 1) * sizeof(WCHAR) )))
+    {
+        free_cookie( cookie );
+        return NULL;
+    }
+    memcpy( cookie->value, p, len * sizeof(WCHAR) );
+    cookie->value[len] = 0;
+
+    return cookie;
+}
+
+BOOL set_cookies( request_t *request, const WCHAR *cookies )
+{
+    static const WCHAR pathW[] = {'p','a','t','h',0};
+    static const WCHAR domainW[] = {'d','o','m','a','i','n',0};
+
+    BOOL ret = FALSE;
+    WCHAR *buffer, *p, *q, *r;
+    WCHAR *cookie_domain = NULL, *cookie_path = NULL;
+    session_t *session = request->connect->session;
+    cookie_t *cookie;
+    int len;
+
+    len = strlenW( cookies );
+    if (!(buffer = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return FALSE;
+    strcpyW( buffer, cookies );
+
+    p = buffer;
+    while (*p && *p != ';') p++;
+    if (*p == ';') *p++ = 0;
+    if (!(cookie = parse_cookie( buffer )))
+    {
+        heap_free( buffer );
+        return FALSE;
+    }
+    if ((q = strstrW( p, domainW ))) /* FIXME: do real attribute parsing */
+    {
+        while (*q && *q != '=') q++;
+        if (!*q) goto end;
+
+        r = ++q;
+        while (*r && *r != ';') r++;
+        len = r - q;
+
+        if (!(cookie_domain = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end;
+        memcpy( cookie_domain, q, len * sizeof(WCHAR) );
+        cookie_domain[len] = 0;
+
+    }
+    if ((q = strstrW( p, pathW )))
+    {
+        while (*q && *q != '=') q++;
+        if (!*q) goto end;
+
+        r = ++q;
+        while (*r && *r != ';') r++;
+        len = r - q;
+
+        if (!(cookie_path = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end;
+        memcpy( cookie_path, q, len * sizeof(WCHAR) );
+        cookie_path[len] = 0;
+    }
+    if (!cookie_domain && !(cookie_domain = strdupW( request->connect->servername ))) goto end;
+    if (!cookie_path && !(cookie_path = strdupW( request->path ))) goto end;
+
+    if ((p = strrchrW( cookie_path, '/' )) && p != cookie_path) *p = 0;
+    ret = add_cookie( session, cookie, cookie_domain, cookie_path );
+
+end:
+    if (!ret)
+    {
+        free_cookie( cookie );
+        heap_free( cookie_domain );
+        heap_free( cookie_path );
+    }
+    heap_free( buffer );
+    return ret;
+}
+
+BOOL add_cookie_headers( request_t *request )
+{
+    struct list *domain_cursor;
+    session_t *session = request->connect->session;
+
+    LIST_FOR_EACH( domain_cursor, &session->cookie_cache )
+    {
+        domain_t *domain = LIST_ENTRY( domain_cursor, domain_t, entry );
+        if (domain_match( request->connect->servername, domain, TRUE ))
+        {
+            struct list *cookie_cursor;
+            TRACE("found domain %s\n", debugstr_w(domain->name));
+
+            LIST_FOR_EACH( cookie_cursor, &domain->cookies )
+            {
+                cookie_t *cookie = LIST_ENTRY( cookie_cursor, cookie_t, 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 format[] = {'C','o','o','k','i','e',':',' ','%','s','=','%','s',0};
+                    int len;
+                    WCHAR *header;
+
+                    len = strlenW( cookie->name ) + strlenW( format ) + strlenW( cookie->value );
+                    if (!(header = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return FALSE;
+
+                    sprintfW( header, format, cookie->name, cookie->value );
+
+                    TRACE("%s\n", debugstr_w(header));
+                    add_request_headers( request, header, len, WINHTTP_ADDREQ_FLAG_ADD );
+                    heap_free( header );
+                }
+            }
+        }
+    }
+    return TRUE;
+}

Propchange: trunk/reactos/dll/win32/winhttp/cookie.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: trunk/reactos/dll/win32/winhttp/main.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/main.c?rev=41333&r1=41332&r2=41333&view=diff
==============================================================================
--- trunk/reactos/dll/win32/winhttp/main.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/winhttp/main.c [iso-8859-1] Sun Jun  7 16:32:05 2009
@@ -38,8 +38,6 @@
 {
     switch(fdwReason)
     {
-    case DLL_WINE_PREATTACH:
-        return FALSE;  /* prefer native version */
     case DLL_PROCESS_ATTACH:
         DisableThreadLibraryCalls(hInstDLL);
         break;
@@ -84,41 +82,3 @@
     FIXME("()\n");
     return S_OK;
 }
-
-#define SCHEME_HTTP  3
-#define SCHEME_HTTPS 4
-
-BOOL WINAPI InternetCrackUrlW( LPCWSTR, DWORD, DWORD, LPURL_COMPONENTSW );
-BOOL WINAPI InternetCreateUrlW( LPURL_COMPONENTS, DWORD, LPWSTR, LPDWORD );
-
-/***********************************************************************
- *          WinHttpCrackUrl (winhttp.@)
- */
-BOOL WINAPI WinHttpCrackUrl( LPCWSTR url, DWORD len, DWORD flags, LPURL_COMPONENTSW components )
-{
-    BOOL ret;
-
-    TRACE("%s, %d, %x, %p\n", debugstr_w(url), len, flags, components);
-
-    if ((ret = InternetCrackUrlW( url, len, flags, components )))
-    {
-        /* fix up an incompatibility between wininet and winhttp */
-        if (components->nScheme == SCHEME_HTTP) components->nScheme = INTERNET_SCHEME_HTTP;
-        else if (components->nScheme == SCHEME_HTTPS) components->nScheme = INTERNET_SCHEME_HTTPS;
-        else
-        {
-            set_last_error( ERROR_WINHTTP_UNRECOGNIZED_SCHEME );
-            return FALSE;
-        }
-    }
-    return ret;
-}
-
-/***********************************************************************
- *          WinHttpCreateUrl (winhttp.@)
- */
-BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS comps, DWORD flags, LPWSTR url, LPDWORD len )
-{
-    TRACE("%p, 0x%08x, %p, %p\n", comps, flags, url, len);
-    return InternetCreateUrlW( comps, flags, url, len );
-}

Modified: trunk/reactos/dll/win32/winhttp/net.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/net.c?rev=41333&r1=41332&r2=41333&view=diff
==============================================================================
--- trunk/reactos/dll/win32/winhttp/net.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/winhttp/net.c [iso-8859-1] Sun Jun  7 16:32:05 2009
@@ -48,12 +48,13 @@
 #include "windef.h"
 #include "winbase.h"
 #include "winhttp.h"
+#include "wincrypt.h"
+
+#include "winhttp_private.h"
 
 /* to avoid conflicts with the Unix socket headers */
 #define USE_WS_PREFIX
 #include "winsock2.h"
-
-#include "winhttp_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
 
@@ -83,6 +84,7 @@
 static void *libcrypto_handle;
 
 static SSL_METHOD *method;
+static SSL_CTX *ctx;
 
 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
 
@@ -90,7 +92,6 @@
 MAKE_FUNCPTR( SSL_load_error_strings );
 MAKE_FUNCPTR( SSLv23_method );
 MAKE_FUNCPTR( SSL_CTX_new );
-MAKE_FUNCPTR( SSL_CTX_free );
 MAKE_FUNCPTR( SSL_new );
 MAKE_FUNCPTR( SSL_free );
 MAKE_FUNCPTR( SSL_set_fd );
@@ -107,14 +108,15 @@
 MAKE_FUNCPTR( BIO_new_fp );
 MAKE_FUNCPTR( ERR_get_error );
 MAKE_FUNCPTR( ERR_error_string );
+MAKE_FUNCPTR( i2d_X509 );
 #undef MAKE_FUNCPTR
 
 #endif
 
-#if 0
 /* translate a unix error code into a winsock error code */
 static int sock_get_error( int err )
 {
+#if !defined(__MINGW32__) && !defined (_MSC_VER)
     switch (err)
     {
         case EINTR:             return WSAEINTR;
@@ -174,11 +176,9 @@
 #endif
     default: errno = err; perror( "sock_set_error" ); return WSAEFAULT;
     }
+#endif
     return err;
 }
-#else
-#define sock_get_error(x) WSAGetLastError()
-#endif
 
 BOOL netconn_init( netconn_t *conn, BOOL secure )
 {
@@ -210,7 +210,6 @@
     LOAD_FUNCPTR( SSL_load_error_strings );
     LOAD_FUNCPTR( SSLv23_method );
     LOAD_FUNCPTR( SSL_CTX_new );
-    LOAD_FUNCPTR( SSL_CTX_free );
     LOAD_FUNCPTR( SSL_new );
     LOAD_FUNCPTR( SSL_free );
     LOAD_FUNCPTR( SSL_set_fd );
@@ -235,6 +234,7 @@
     LOAD_FUNCPTR( BIO_new_fp );
     LOAD_FUNCPTR( ERR_get_error );
     LOAD_FUNCPTR( ERR_error_string );
+    LOAD_FUNCPTR( i2d_X509 );
 #undef LOAD_FUNCPTR
 
     pSSL_library_init();
@@ -242,8 +242,6 @@
     pBIO_new_fp( stderr, BIO_NOCLOSE );
 
     method = pSSLv23_method();
-    conn->ssl_ctx = pSSL_CTX_new( method );
-
 #else
     WARN("SSL support not compiled in.\n");
     set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
@@ -314,13 +312,14 @@
     X509 *cert;
     long res;
 
-    if (!pSSL_CTX_set_default_verify_paths( conn->ssl_ctx ))
+    ctx = pSSL_CTX_new( method );
+    if (!pSSL_CTX_set_default_verify_paths( ctx ))
     {
         ERR("SSL_CTX_set_default_verify_paths failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
         set_last_error( ERROR_OUTOFMEMORY );
         return FALSE;
     }
-    if (!(conn->ssl_conn = pSSL_new( conn->ssl_ctx )))
+    if (!(conn->ssl_conn = pSSL_new( ctx )))
     {
         ERR("SSL_new failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
         set_last_error( ERROR_OUTOFMEMORY );
@@ -468,11 +467,7 @@
         return TRUE;
     }
 #ifdef FIONREAD
-    if (!(ret = ioctlsocket( conn->socket, FIONREAD, &unread )))
-    {
-        TRACE("%d bytes of queued, but unread data\n", unread);
-        *available += unread;
-    }
+    if (!(ret = ioctlsocket( conn->socket, FIONREAD, &unread ))) *available = unread;
 #endif
     return TRUE;
 }
@@ -491,8 +486,8 @@
 #ifdef SONAME_LIBSSL
         long timeout;
 
-        timeout = pSSL_CTX_get_timeout( conn->ssl_ctx );
-        pSSL_CTX_set_timeout( conn->ssl_ctx, DEFAULT_RECEIVE_TIMEOUT );
+        timeout = pSSL_CTX_get_timeout( ctx );
+        pSSL_CTX_set_timeout( ctx, DEFAULT_RECEIVE_TIMEOUT );
 
         while (recvd < *buflen)
         {
@@ -509,7 +504,7 @@
             }
             if (buffer[recvd] != '\r') recvd++;
         }
-        pSSL_CTX_set_timeout( conn->ssl_ctx, timeout );
+        pSSL_CTX_set_timeout( ctx, timeout );
         if (ret)
         {
             buffer[recvd++] = 0;
@@ -567,7 +562,7 @@
     tv.tv_sec = value / 1000;
     tv.tv_usec = (value % 1000) * 1000;
 
-    if ((res = setsockopt( netconn->socket, SOL_SOCKET, send ? SO_SNDTIMEO : SO_RCVTIMEO, &tv, sizeof(tv) ) == -1))
+    if ((res = setsockopt( netconn->socket, SOL_SOCKET, send ? SO_SNDTIMEO : SO_RCVTIMEO, (void*)&tv, sizeof(tv) ) == -1))
     {
         WARN("setsockopt failed (%s)\n", strerror( errno ));
         return sock_get_error( errno );
@@ -595,7 +590,7 @@
     heap_free( hostname );
     if (ret != 0)
     {
-        TRACE("failed to get address of %s (%s)\n", debugstr_a(hostname), gai_strerror(ret));
+        TRACE("failed to get address of %s (%s)\n", debugstr_w(hostnameW), gai_strerror(ret));
         return FALSE;
     }
     memset( sa, 0, sizeof(struct sockaddr_in) );
@@ -611,12 +606,12 @@
     heap_free( hostname );
     if (!he)
     {
-        TRACE("failed to get address of %s (%d)\n", debugstr_a(hostname), h_errno);
+        TRACE("failed to get address of %s (%d)\n", debugstr_w(hostnameW), h_errno);
         LeaveCriticalSection( &cs_gethostbyname );
         return FALSE;
     }
     memset( sa, 0, sizeof(struct sockaddr_in) );
-    memcpy( (char *)&sa->sin_addr, he->h_addr, he->h_length );
+    memcpy( &sa->sin_addr, he->h_addr, he->h_length );
     sa->sin_family = he->h_addrtype;
     sa->sin_port = htons( port );
 
@@ -624,3 +619,46 @@
 #endif
     return TRUE;
 }
+
+const void *netconn_get_certificate( netconn_t *conn )
+{
+#ifdef SONAME_LIBSSL
+    X509 *cert;
+    unsigned char *buffer, *p;
+    int len;
+    BOOL malloc = FALSE;
+    const CERT_CONTEXT *ret;
+
+    if (!conn->secure) return NULL;
+
+    if (!(cert = pSSL_get_peer_certificate( conn->ssl_conn ))) return NULL;
+    p = NULL;
+    if ((len = pi2d_X509( cert, &p )) < 0) return NULL;
+    /*
+     * SSL 0.9.7 and above malloc the buffer if it is null.
+     * however earlier version do not and so we would need to alloc the buffer.
+     *
+     * see the i2d_X509 man page for more details.
+     */
+    if (!p)
+    {
+        if (!(buffer = heap_alloc( len ))) return NULL;
+        p = buffer;
+        len = pi2d_X509( cert, &p );
+    }
+    else
+    {
+        buffer = p;
+        malloc = TRUE;
+    }
+
+    ret = CertCreateCertificateContext( X509_ASN_ENCODING, buffer, len );
+
+    if (malloc) free( buffer );
+    else heap_free( buffer );
+
+    return ret;
+#else
+    return NULL;
+#endif
+}

Modified: trunk/reactos/dll/win32/winhttp/request.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/request.c?rev=41333&r1=41332&r2=41333&view=diff
==============================================================================
--- trunk/reactos/dll/win32/winhttp/request.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/winhttp/request.c [iso-8859-1] Sun Jun  7 16:32:05 2009
@@ -175,6 +175,22 @@
     NULL                            /* WINHTTP_QUERY_PASSPORT_CONFIG            = 78 */
 };
 
+static DWORD CALLBACK task_thread( LPVOID param )
+{
+    task_header_t *task = param;
+
+    task->proc( task );
+
+    release_object( &task->request->hdr );
+    heap_free( task );
+    return ERROR_SUCCESS;
+}
+
+static BOOL queue_task( task_header_t *task )
+{
+    return QueueUserWorkItem( task_thread, task, WT_EXECUTELONGFUNCTION );
+}
+
 static void free_header( header_t *header )
 {
     heap_free( header->field );
@@ -391,13 +407,13 @@
     return TRUE;
 }
 
-static BOOL add_request_headers( request_t *request, LPCWSTR headers, DWORD len, DWORD flags )
+BOOL add_request_headers( request_t *request, LPCWSTR headers, DWORD len, DWORD flags )
 {
     BOOL ret = FALSE;
     WCHAR *buffer, *p, *q;
     header_t *header;
 
-    if (len == ~0UL) len = strlenW( headers );
+    if (len == ~0u) len = strlenW( headers );
     if (!(buffer = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return FALSE;
     strcpyW( buffer, headers );
 
@@ -467,28 +483,20 @@
     static const WCHAR crlf[]    = {'\r','\n',0};
     static const WCHAR colon[]   = {':',' ',0};
     static const WCHAR twocrlf[] = {'\r','\n','\r','\n',0};
-    static const WCHAR get[]     = {'G','E','T',0};
-    static const WCHAR slash[]   = {'/',0};
-    static const WCHAR http1_1[] = {'H','T','T','P','/','1','.','1',0};
 
     WCHAR *ret;
     const WCHAR **headers, **p;
-    const WCHAR *verb = get, *path = slash, *version = http1_1;
     unsigned int len, i = 0, j;
-
-    if (request->verb && request->verb[0]) verb = request->verb;
-    if (request->path && request->path[0]) path = request->path;
-    if (request->version && request->version[0]) version = request->version;
 
     /* 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;
 
-    headers[i++] = verb;
+    headers[i++] = request->verb;
     headers[i++] = space;
-    headers[i++] = path;
+    headers[i++] = request->path;
     headers[i++] = space;
-    headers[i++] = version;
+    headers[i++] = request->version;
 
     for (j = 0; j < request->num_headers; j++)
     {
@@ -561,7 +569,7 @@
         }
         else if (buffer)
         {
-            for (p = headers, q = (WCHAR *)buffer; *p; p++, q++)
+            for (p = headers, q = buffer; *p; p++, q++)
             {
                 if (*p != '\r') *q = *p;
                 else
@@ -571,7 +579,7 @@
                 }
             }
             *q = 0;
-            TRACE("returning data: %s\n", debugstr_wn((WCHAR *)buffer, len));
+            TRACE("returning data: %s\n", debugstr_wn(buffer, len));
             ret = TRUE;
         }
         *buflen = len * sizeof(WCHAR);
@@ -606,7 +614,7 @@
     }
     default:
     {
-        if (attr > sizeof(attribute_table)/sizeof(attribute_table[0]) || !attribute_table[attr])
+        if (attr >= sizeof(attribute_table)/sizeof(attribute_table[0]) || !attribute_table[attr])
         {
             FIXME("attribute %u not implemented\n", attr);
             return FALSE;
@@ -710,13 +718,16 @@
     connect_t *connect;
     char address[32];
     WCHAR *addressW;
+    INTERNET_PORT port;
 
     if (netconn_connected( &request->netconn )) return TRUE;
+
     connect = request->connect;
+    port = connect->hostport ? connect->hostport : (request->hdr.flags & WINHTTP_FLAG_SECURE ? 443 : 80);
 
     send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, connect->servername, strlenW(connect->servername) + 1 );
 
-    if (!netconn_resolve( connect->servername, connect->serverport, &connect->sockaddr )) return FALSE;
+    if (!netconn_resolve( connect->servername, port, &connect->sockaddr )) return FALSE;
     inet_ntop( connect->sockaddr.sin_family, &connect->sockaddr.sin_addr, address, sizeof(address) );
     addressW = strdupAW( address );
 
@@ -759,32 +770,35 @@
     send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, 0, 0 );
 }
 
-static BOOL add_host_header( request_t *request, WCHAR *hostname, INTERNET_PORT port, DWORD modifier )
+static BOOL add_host_header( request_t *request, DWORD modifier )
 {
     BOOL ret;
     DWORD len;
     WCHAR *host;
     static const WCHAR fmt[] = {'%','s',':','%','u',0};
+    connect_t *connect = request->connect;
+    INTERNET_PORT port;
+
+    port = connect->hostport ? connect->hostport : (request->hdr.flags & WINHTTP_FLAG_SECURE ? 443 : 80);
 
     if (port == INTERNET_DEFAULT_HTTP_PORT || port == INTERNET_DEFAULT_HTTPS_PORT)
     {
-        return process_header( request, attr_host, hostname, modifier, TRUE );
-    }
-    len = strlenW( hostname ) + 7; /* sizeof(":65335") */
+        return process_header( request, attr_host, connect->hostname, modifier, TRUE );
+    }
+    len = strlenW( connect->hostname ) + 7; /* sizeof(":65335") */
     if (!(host = heap_alloc( len * sizeof(WCHAR) ))) return FALSE;
-    sprintfW( host, fmt, hostname, port );
+    sprintfW( host, fmt, connect->hostname, port );
     ret = process_header( request, attr_host, host, modifier, TRUE );
     heap_free( host );
     return ret;
 }
 
 static BOOL send_request( request_t *request, LPCWSTR headers, DWORD headers_len, LPVOID optional,
-                          DWORD optional_len, DWORD total_len, DWORD_PTR context )
+                          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};
     static const WCHAR no_cache[]   = {'n','o','-','c','a','c','h','e',0};
     static const WCHAR length_fmt[] = {'%','l','d',0};
-    static const WCHAR post[]       = {'P','O','S','T',0};
 
     BOOL ret = FALSE;
     connect_t *connect = request->connect;
@@ -798,9 +812,9 @@
         process_header( request, attr_user_agent, session->agent, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE );
 
     if (connect->hostname)
-        add_host_header( request, connect->hostname, connect->hostport, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW );
-
-    if (total_len || (request->verb && !strcmpW( request->verb, post )))
+        add_host_header( request, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW );
+
+    if (total_len || (request->verb && !strcmpW( request->verb, postW )))
     {
         WCHAR length[21]; /* decimal long int + null */
         sprintfW( length, length_fmt, total_len );
@@ -820,6 +834,11 @@
         TRACE("failed to add request headers\n");
         return FALSE;
     }
+    if (!(request->hdr.disable_flags & WINHTTP_DISABLE_COOKIES) && !add_cookie_headers( request ))
+    {
+        WARN("failed to add cookie headers\n");
+        return FALSE;
+    }
 
     if (!(ret = open_connection( request ))) goto end;
     if (!(req = build_request_string( request ))) goto end;
@@ -840,8 +859,26 @@
     send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_SENT, &len, sizeof(DWORD) );
 
 end:
+    if (async)
+    {
+        if (ret) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE, NULL, 0 );
+        else
+        {
+            WINHTTP_ASYNC_RESULT result;
+            result.dwResult = API_SEND_REQUEST;
+            result.dwError  = get_last_error();
+            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 )
+{
+    send_request_t *s = (send_request_t *)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 );
 }
 
 /***********************************************************************
@@ -868,7 +905,25 @@
         return FALSE;
     }
 
-    ret = send_request( request, headers, headers_len, optional, optional_len, total_len, context );
+    if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC)
+    {
+        send_request_t *s;
+
+        if (!(s = heap_alloc( sizeof(send_request_t) ))) return FALSE;
+        s->hdr.request  = request;
+        s->hdr.proc     = task_send_request;
+        s->headers      = strdupW( headers );
+        s->headers_len  = headers_len;
+        s->optional     = optional;
+        s->optional_len = optional_len;
+        s->total_len    = total_len;
+        s->context      = context;
+
+        addref_object( &request->hdr );
+        ret = queue_task( (task_header_t *)s );
+    }
+    else
+        ret = send_request( request, headers, headers_len, optional, optional_len, total_len, context, FALSE );
 
     release_object( &request->hdr );
     return ret;
@@ -889,9 +944,9 @@
 }
 
 #define MAX_REPLY_LEN   1460
-#define INITIAL_HEADER_BUFFER_SIZE  512
-
-static BOOL receive_response( request_t *request, BOOL clear )
+#define INITIAL_HEADER_BUFFER_LEN  512
+
+static BOOL read_reply( request_t *request )
 {
     static const WCHAR crlf[] = {'\r','\n',0};
 
@@ -902,9 +957,6 @@
     WCHAR status_codeW[4]; /* sizeof("nnn") */
 
     if (!netconn_connected( &request->netconn )) return FALSE;
-
-    /* clear old response headers (eg. from a redirect response) */
-    if (clear) clear_response_headers( request );
 
     send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE, NULL, 0 );
 
@@ -949,7 +1001,7 @@
     heap_free( request->status_text );
     request->status_text = status_textW;
 
-    len = max( buflen + crlf_len, INITIAL_HEADER_BUFFER_SIZE );
+    len = max( buflen + crlf_len, INITIAL_HEADER_BUFFER_LEN );
     if (!(raw_headers = heap_alloc( len * sizeof(WCHAR) ))) return FALSE;
     MultiByteToWideChar( CP_ACP, 0, buffer, buflen, raw_headers, buflen );
     memcpy( raw_headers + buflen - 1, crlf, sizeof(crlf) );
@@ -1002,6 +1054,7 @@
     connect_t *connect = request->connect;
     INTERNET_PORT port;
     WCHAR *hostname = NULL, *location = NULL;
+    int index;
 
     size = 0;
     query_headers( request, WINHTTP_QUERY_LOCATION, NULL, NULL, &size, NULL );
@@ -1012,48 +1065,73 @@
 
     memset( &uc, 0, sizeof(uc) );
     uc.dwStructSize = sizeof(uc);
-    uc.dwSchemeLength = uc.dwHostNameLength = uc.dwUrlPathLength = uc.dwExtraInfoLength = ~0UL;
-
-    if (!(ret = WinHttpCrackUrl( location, size / sizeof(WCHAR), 0, &uc ))) goto end;
-
-    if (uc.nScheme == INTERNET_SCHEME_HTTP && request->hdr.flags & WINHTTP_FLAG_SECURE)
-    {
-        TRACE("redirect from secure page to non-secure page\n");
-        request->hdr.flags &= ~WINHTTP_FLAG_SECURE;
-    }
-    else if (uc.nScheme == INTERNET_SCHEME_HTTPS && !(request->hdr.flags & WINHTTP_FLAG_SECURE))
-    {
-        TRACE("redirect from non-secure page to secure page\n");
-        request->hdr.flags |= WINHTTP_FLAG_SECURE;
-    }
-
-    len = uc.dwHostNameLength;
-    if (!(hostname = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end;
-    memcpy( hostname, uc.lpszHostName, len * sizeof(WCHAR) );
-    hostname[len] = 0;
-
-    port = uc.nPort ? uc.nPort : (uc.nScheme == INTERNET_SCHEME_HTTPS ? 443 : 80);
-    if (strcmpiW( connect->servername, hostname ) || connect->serverport != port)
-    {
-        heap_free( connect->servername );
-        connect->servername = hostname;
-        connect->serverport = connect->hostport = port;
-
-        netconn_close( &request->netconn );
-        if (!(ret = netconn_init( &request->netconn, request->hdr.flags & WINHTTP_FLAG_SECURE ))) goto end;
-    }
-    if (!(ret = add_host_header( request, hostname, port, WINHTTP_ADDREQ_FLAG_REPLACE ))) goto end;
-    if (!(ret = open_connection( request ))) goto end;
-
-    heap_free( request->path );
-    request->path = NULL;
-    if (uc.lpszUrlPath)
-    {
-        len = uc.dwUrlPathLength + uc.dwExtraInfoLength;
-        if (!(request->path = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end;
-        strcpyW( request->path, uc.lpszUrlPath );
-    }
-
+    uc.dwSchemeLength = uc.dwHostNameLength = uc.dwUrlPathLength = uc.dwExtraInfoLength = ~0u;
+
+    if (!WinHttpCrackUrl( location, size / sizeof(WCHAR), 0, &uc )) /* assume relative redirect */
+    {
+        WCHAR *path, *p;
+
+        len = strlenW( location ) + 1;
+        if (location[0] != '/') len++;
+        if (!(p = path = heap_alloc( len * sizeof(WCHAR) ))) goto end;
+
+        if (location[0] != '/') *p++ = '/';
+        strcpyW( p, location );
+
+        heap_free( request->path );
+        request->path = path;
+    }
+    else
+    {
+        if (uc.nScheme == INTERNET_SCHEME_HTTP && request->hdr.flags & WINHTTP_FLAG_SECURE)
+        {
+            TRACE("redirect from secure page to non-secure page\n");
+            request->hdr.flags &= ~WINHTTP_FLAG_SECURE;
+        }
+        else if (uc.nScheme == INTERNET_SCHEME_HTTPS && !(request->hdr.flags & WINHTTP_FLAG_SECURE))
+        {
+            TRACE("redirect from non-secure page to secure page\n");
+            request->hdr.flags |= WINHTTP_FLAG_SECURE;
+        }
+
+        len = uc.dwHostNameLength;
+        if (!(hostname = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end;
+        memcpy( hostname, uc.lpszHostName, len * sizeof(WCHAR) );
+        hostname[len] = 0;
+
+        port = uc.nPort ? uc.nPort : (uc.nScheme == INTERNET_SCHEME_HTTPS ? 443 : 80);
+        if (strcmpiW( connect->servername, hostname ) || connect->serverport != port)
+        {
+            heap_free( connect->hostname );
+            connect->hostname = hostname;
+            heap_free( connect->servername );
+            connect->servername = strdupW( connect->hostname );
+            connect->serverport = connect->hostport = port;
+
+            netconn_close( &request->netconn );
+            if (!(ret = netconn_init( &request->netconn, request->hdr.flags & WINHTTP_FLAG_SECURE ))) goto end;
+        }
+        if (!(ret = add_host_header( request, WINHTTP_ADDREQ_FLAG_REPLACE ))) goto end;
+        if (!(ret = open_connection( request ))) goto end;
+
+        heap_free( request->path );
+        request->path = NULL;
+        if (uc.dwUrlPathLength)
+        {
+            len = uc.dwUrlPathLength + uc.dwExtraInfoLength;
+            if (!(request->path = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end;
+            strcpyW( request->path, uc.lpszUrlPath );
+        }
+        else request->path = strdupW( slashW );
+    }
+
+    /* remove content-type/length headers */
+    if ((index = get_header_index( request, attr_content_type, 0, TRUE )) >= 0) delete_header( request, index );
+    if ((index = get_header_index( request, attr_content_length, 0, TRUE )) >= 0 ) delete_header( request, index );
+
+    /* redirects are always GET requests */
+    heap_free( request->verb );
+    request->verb = strdupW( getW );
     ret = TRUE;
 
 end:
@@ -1062,7 +1140,7 @@
     return ret;
 }
 
-static BOOL read_data( request_t *request, void *buffer, DWORD size, DWORD *read, BOOL async )
+static BOOL receive_data( request_t *request, void *buffer, DWORD size, DWORD *read, BOOL async )
 {
     DWORD to_read;
     int bytes_read;
@@ -1081,99 +1159,6 @@
     request->content_read += bytes_read;
     *read = bytes_read;
     return TRUE;
-}
-
-/* read any content returned by the server so that the connection can be reused */
-static void drain_content( request_t *request )
-{
-    DWORD bytes_read;
-    char buffer[2048];
-
-    if (request->content_length == ~0UL) return;
-    for (;;)
-    {
-        if (!read_data( request, buffer, sizeof(buffer), &bytes_read, FALSE ) || !bytes_read) return;
-    }
-}
-
-/***********************************************************************
- *          WinHttpReceiveResponse (winhttp.@)
- */
-BOOL WINAPI WinHttpReceiveResponse( HINTERNET hrequest, LPVOID reserved )
-{
-    BOOL ret = TRUE;
-    request_t *request;
-    DWORD size, query, status;
-
-    TRACE("%p, %p\n", hrequest, reserved);
-
-    if (!(request = (request_t *)grab_object( hrequest )))
-    {
-        set_last_error( 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 );
-        return FALSE;
-    }
-
-    for (;;)
-    {
-        if (!(ret = receive_response( request, TRUE ))) break;
-
-        size = sizeof(DWORD);
-        query = WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER;
-        if (!(ret = query_headers( request, query, NULL, &status, &size, NULL ))) break;
-
-        size = sizeof(DWORD);
-        query = WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER;
-        if (!query_headers( request, query, NULL, &request->content_length, &size, NULL ))
-            request->content_length = ~0UL;
-
-        if (status == 200) break;
-        if (status == 301 || status == 302)
-        {
-            if (request->hdr.disable_flags & WINHTTP_DISABLE_REDIRECTS) break;
-            drain_content( request );
-            if (!(ret = handle_redirect( request ))) break;
-        }
-        ret = send_request( request, NULL, 0, NULL, 0, 0, 0 );
-    }
-
-    release_object( &request->hdr );
-    return ret;
-}
-
-/***********************************************************************
- *          WinHttpQueryDataAvailable (winhttp.@)
- */
-BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available )
-{
-    BOOL ret;
-    DWORD num_bytes;
-    request_t *request;
-
-    TRACE("%p, %p\n", hrequest, available);
-
-    if (!(request = (request_t *)grab_object( hrequest )))
-    {
-        set_last_error( 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 );
-        return FALSE;
-    }
-
-    ret = netconn_query_data_available( &request->netconn, &num_bytes );
-
-    if (ret && available) *available = num_bytes;
-    release_object( &request->hdr );
-    return ret;
 }
 
 static DWORD get_chunk_size( const char *buffer )
@@ -1191,7 +1176,7 @@
     return size;
 }
 
-static BOOL read_data_chunked( request_t *request, void *buffer, DWORD size, DWORD *read, BOOL async )
+static BOOL receive_data_chunked( request_t *request, void *buffer, DWORD size, DWORD *read, BOOL async )
 {
     char reply[MAX_REPLY_LEN], *p = buffer;
     DWORD buflen, to_read, to_write = size;
@@ -1202,7 +1187,7 @@
     {
         if (*read == size) break;
 
-        if (request->content_length == ~0UL) /* new chunk */
+        if (request->content_length == ~0u) /* new chunk */
         {
             buflen = sizeof(reply);
             if (!netconn_get_next_line( &request->netconn, reply, &buflen )) break;
@@ -1210,7 +1195,7 @@
             if (!(request->content_length = get_chunk_size( reply )))
             {
                 /* zero sized chunk marks end of transfer; read any trailing headers and return */
-                receive_response( request, FALSE );
+                read_reply( request );
                 break;
             }
         }
@@ -1236,7 +1221,7 @@
         if (request->content_read == request->content_length) /* chunk complete */
         {
             request->content_read = 0;
-            request->content_length = ~0UL;
+            request->content_length = ~0u;
 
             buflen = sizeof(reply);
             if (!netconn_get_next_line( &request->netconn, reply, &buflen ))
@@ -1250,17 +1235,285 @@
     return TRUE;
 }
 
+static void finished_reading( request_t *request )
+{
+    static const WCHAR closeW[] = {'c','l','o','s','e',0};
+
+    BOOL close = FALSE;
+    WCHAR connection[20];
+    DWORD size = sizeof(connection);
+
+    if (request->hdr.disable_flags & WINHTTP_DISABLE_KEEP_ALIVE) close = TRUE;
+    else if (query_headers( request, WINHTTP_QUERY_CONNECTION, NULL, connection, &size, NULL ) ||
+             query_headers( request, WINHTTP_QUERY_PROXY_CONNECTION, NULL, connection, &size, NULL ))
+    {
+        if (!strcmpiW( connection, closeW )) close = TRUE;
+    }
+    else if (!strcmpW( request->version, http1_0 )) close = TRUE;
+
+    if (close) close_connection( request );
+    request->content_length = ~0u;
+    request->content_read = 0;
+}
+
+static BOOL read_data( request_t *request, void *buffer, DWORD to_read, DWORD *read, BOOL async )
+{
+    static const WCHAR chunked[] = {'c','h','u','n','k','e','d',0};
+
+    BOOL ret;
+    WCHAR encoding[20];
+    DWORD num_bytes, buflen = sizeof(encoding);
+
+    if (query_headers( request, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, encoding, &buflen, NULL ) &&
+        !strcmpiW( encoding, chunked ))
+    {
+        ret = receive_data_chunked( request, buffer, to_read, &num_bytes, async );
+    }
+    else
+        ret = receive_data( request, buffer, to_read, &num_bytes, async );
+
+    if (async)
+    {
+        if (ret) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, buffer, num_bytes );
+        else
+        {
+            WINHTTP_ASYNC_RESULT result;
+            result.dwResult = API_READ_DATA;
+            result.dwError  = get_last_error();
+            send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) );
+        }
+    }
+    if (ret)
+    {
+        if (read) *read = num_bytes;
+        if (!num_bytes) finished_reading( request );
+    }
+    return ret;
+}
+
+/* read any content returned by the server so that the connection can be reused */
+static void drain_content( request_t *request )
+{
+    DWORD bytes_read;
+    char buffer[2048];
+
+    if (!request->content_length) return;
+    for (;;)
+    {
+        if (!read_data( request, buffer, sizeof(buffer), &bytes_read, FALSE ) || !bytes_read) return;
+    }
+}
+
+static void record_cookies( request_t *request )
+{
+    unsigned int i;
+
+    for (i = 0; i < request->num_headers; i++)
+    {
+        header_t *set_cookie = &request->headers[i];
+        if (!strcmpiW( set_cookie->field, attr_set_cookie ) && !set_cookie->is_request)
+        {
+            set_cookies( request, set_cookie->value );
+        }
+    }
+}
+
+static BOOL receive_response( request_t *request, BOOL async )
+{
+    BOOL ret;
+    DWORD size, query, status;
+
+    for (;;)
+    {
+        if (!(ret = read_reply( request ))) break;
+
+        size = sizeof(DWORD);
+        query = WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER;
+        if (!(ret = query_headers( request, query, NULL, &status, &size, NULL ))) break;
+
+        size = sizeof(DWORD);
+        query = WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER;
+        if (!query_headers( request, query, NULL, &request->content_length, &size, NULL ))
+            request->content_length = ~0u;
+
+        if (!(request->hdr.disable_flags & WINHTTP_DISABLE_COOKIES)) record_cookies( request );
+
+        if (status == 301 || status == 302)
+        {
+            if (request->hdr.disable_flags & WINHTTP_DISABLE_REDIRECTS) break;
+
+            drain_content( request );
+            if (!(ret = handle_redirect( request ))) break;
+
+            clear_response_headers( request );
+            ret = send_request( request, NULL, 0, NULL, 0, 0, 0, FALSE ); /* recurse synchronously */
+            continue;
+        }
+        if (status == 401) FIXME("authentication not supported\n");
+        break;
+    }
+
+    if (async)
+    {
+        if (ret) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE, NULL, 0 );
+        else
+        {
+            WINHTTP_ASYNC_RESULT result;
+            result.dwResult = API_RECEIVE_RESPONSE;
+            result.dwError  = get_last_error();
+            send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) );
+        }
+    }
+    return ret;
+}
+
+static void task_receive_response( task_header_t *task )
+{
+    receive_response_t *r = (receive_response_t *)task;
+    receive_response( r->hdr.request, TRUE );
+}
+
+/***********************************************************************
+ *          WinHttpReceiveResponse (winhttp.@)
+ */
+BOOL WINAPI WinHttpReceiveResponse( HINTERNET hrequest, LPVOID reserved )
+{
+    BOOL ret;
+    request_t *request;
+
+    TRACE("%p, %p\n", hrequest, reserved);
+
+    if (!(request = (request_t *)grab_object( hrequest )))
+    {
+        set_last_error( 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 );
+        return FALSE;
+    }
+
+    if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC)
+    {
+        receive_response_t *r;
+
+        if (!(r = heap_alloc( sizeof(receive_response_t) ))) return FALSE;
+        r->hdr.request = request;
+        r->hdr.proc    = task_receive_response;
+
+        addref_object( &request->hdr );
+        ret = queue_task( (task_header_t *)r );
+    }
+    else
+        ret = receive_response( request, FALSE );
+
+    release_object( &request->hdr );
+    return ret;
+}
+
+static BOOL query_data( request_t *request, LPDWORD available, BOOL async )
+{
+    BOOL ret;
+    DWORD num_bytes;
+
+    if ((ret = netconn_query_data_available( &request->netconn, &num_bytes )))
+    {
+        if (request->content_read < request->content_length)
+        {
+            if (!num_bytes)
+            {
+                char buffer[4096];
+                size_t to_read = min( sizeof(buffer), request->content_length - request->content_read );
+
+                ret = netconn_recv( &request->netconn, buffer, to_read, MSG_PEEK, (int *)&num_bytes );
+                if (ret && !num_bytes) WARN("expected more data to be available\n");
+            }
+        }
+        else if (num_bytes)
+        {
+            WARN("extra data available %u\n", num_bytes);
+            ret = FALSE;
+        }
+    }
+    TRACE("%u bytes available\n", num_bytes);
+
+    if (async)
+    {
+        if (ret) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE, &num_bytes, sizeof(DWORD) );
+        else
+        {
+            WINHTTP_ASYNC_RESULT result;
+            result.dwResult = API_QUERY_DATA_AVAILABLE;
+            result.dwError  = get_last_error();
+            send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) );
+        }
+    }
+    if (ret && available) *available = num_bytes;
+    return ret;
+}
+
+static void task_query_data( task_header_t *task )
+{
+    query_data_t *q = (query_data_t *)task;
+    query_data( q->hdr.request, q->available, TRUE );
+}
+
+/***********************************************************************
+ *          WinHttpQueryDataAvailable (winhttp.@)
+ */
+BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available )
+{
+    BOOL ret;
+    request_t *request;
+
+    TRACE("%p, %p\n", hrequest, available);
+
+    if (!(request = (request_t *)grab_object( hrequest )))
+    {
+        set_last_error( 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 );
+        return FALSE;
+    }
+
+    if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC)
+    {
+        query_data_t *q;
+
+        if (!(q = heap_alloc( sizeof(query_data_t) ))) return FALSE;
+        q->hdr.request = request;
+        q->hdr.proc    = task_query_data;
+        q->available   = available;
+
+        addref_object( &request->hdr );
+        ret = queue_task( (task_header_t *)q );
+    }
+    else
+        ret = query_data( request, available, FALSE );
+
+    release_object( &request->hdr );
+    return ret;
+}
+
+static void task_read_data( task_header_t *task )
+{
+    read_data_t *r = (read_data_t *)task;
+    read_data( r->hdr.request, r->buffer, r->to_read, r->read, TRUE );
+}
+
 /***********************************************************************
  *          WinHttpReadData (winhttp.@)
  */
 BOOL WINAPI WinHttpReadData( HINTERNET hrequest, LPVOID buffer, DWORD to_read, LPDWORD read )
 {
-    static const WCHAR chunked[] = {'c','h','u','n','k','e','d',0};
-
     BOOL ret;
     request_t *request;
-    WCHAR encoding[20];
-    DWORD num_bytes, buflen = sizeof(encoding);
 
     TRACE("%p, %p, %d, %p\n", hrequest, buffer, to_read, read);
 
@@ -1276,17 +1529,53 @@
         return FALSE;
     }
 
-    if (query_headers( request, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, encoding, &buflen, NULL ) &&
-        !strcmpiW( encoding, chunked ))
-    {
-        ret = read_data_chunked( request, buffer, to_read, &num_bytes, request->hdr.flags & WINHTTP_FLAG_ASYNC );
+    if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC)
+    {
+        read_data_t *r;
+
+        if (!(r = heap_alloc( sizeof(read_data_t) ))) return FALSE;
+        r->hdr.request = request;
+        r->hdr.proc    = task_read_data;
+        r->buffer      = buffer;
+        r->to_read     = to_read;
+        r->read        = read;
+
+        addref_object( &request->hdr );
+        ret = queue_task( (task_header_t *)r );
     }
     else
-        ret = read_data( request, buffer, to_read, &num_bytes, request->hdr.flags & WINHTTP_FLAG_ASYNC );
-
-    if (ret && read) *read = num_bytes;
+        ret = read_data( request, buffer, to_read, read, FALSE );
+
     release_object( &request->hdr );
     return ret;
+}
+
+static BOOL write_data( request_t *request, LPCVOID buffer, DWORD to_write, LPDWORD written, BOOL async )
+{
+    BOOL ret;
+    int num_bytes;
+
+    ret = netconn_send( &request->netconn, buffer, to_write, 0, &num_bytes );
+
+    if (async)
+    {
+        if (ret) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE, &num_bytes, sizeof(DWORD) );
+        else
+        {
+            WINHTTP_ASYNC_RESULT result;
+            result.dwResult = API_WRITE_DATA;
+            result.dwError  = get_last_error();
+            send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) );
+        }
+    }
+    if (ret && written) *written = num_bytes;
+    return ret;
+}
+
+static void task_write_data( task_header_t *task )
+{
+    write_data_t *w = (write_data_t *)task;
+    write_data( w->hdr.request, w->buffer, w->to_write, w->written, TRUE );
 }
 
 /***********************************************************************
@@ -1311,7 +1600,22 @@
         return FALSE;
     }
 
-    ret = netconn_send( &request->netconn, buffer, to_write, 0, (int *)written );
+    if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC)
+    {
+        write_data_t *w;
+
+        if (!(w = heap_alloc( sizeof(write_data_t) ))) return FALSE;
+        w->hdr.request = request;
+        w->hdr.proc    = task_write_data;
+        w->buffer      = buffer;
+        w->to_write    = to_write;
+        w->written     = written;
+
+        addref_object( &request->hdr );
+        ret = queue_task( (task_header_t *)w );
+    }
+    else
+        ret = write_data( request, buffer, to_write, written, FALSE );
 
     release_object( &request->hdr );
     return ret;

Modified: trunk/reactos/dll/win32/winhttp/session.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/session.c?rev=41333&r1=41332&r2=41333&view=diff
==============================================================================
--- trunk/reactos/dll/win32/winhttp/session.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/winhttp/session.c [iso-8859-1] Sun Jun  7 16:32:05 2009
@@ -25,6 +25,7 @@
 #include "windef.h"
 #include "winbase.h"
 #include "winhttp.h"
+#include "wincrypt.h"
 
 #include "winhttp_private.h"
 
@@ -36,11 +37,17 @@
     SetLastError( error );
 }
 
+DWORD get_last_error( void )
+{
+    /* FIXME */
+    return GetLastError();
+}
+
 void send_callback( object_header_t *hdr, DWORD status, LPVOID info, DWORD buflen )
 {
     TRACE("%p, 0x%08x, %p, %u\n", hdr, status, info, buflen);
 
-    if (hdr->notify_mask & status) hdr->callback( hdr->handle, hdr->context, status, info, buflen );
+    if (hdr->callback && (hdr->notify_mask & status)) hdr->callback( hdr->handle, hdr->context, status, info, buflen );
 }
 
 /***********************************************************************
@@ -58,9 +65,16 @@
 static void session_destroy( object_header_t *hdr )
 {
     session_t *session = (session_t *)hdr;
+    struct list *item, *next;
+    domain_t *domain;
 
     TRACE("%p\n", session);
 
+    LIST_FOR_EACH_SAFE( item, next, &session->cookie_cache )
+    {
+        domain = LIST_ENTRY( item, domain_t, entry );
+        delete_domain( domain );
+    }
     heap_free( session->agent );
     heap_free( session->proxy_server );
     heap_free( session->proxy_bypass );
@@ -69,6 +83,30 @@
     heap_free( session );
 }
 
+static BOOL session_query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD buflen )
+{
+    switch (option)
+    {
+    case WINHTTP_OPTION_REDIRECT_POLICY:
+    {
+        if (!buffer || *buflen < sizeof(DWORD))
+        {
+            *buflen = sizeof(DWORD);
+            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            return FALSE;
+        }
+
+        *(DWORD *)buffer = hdr->redirect_policy;
+        *buflen = sizeof(DWORD);
+        return TRUE;
+    }
+    default:
+        FIXME("unimplemented option %u\n", option);
+        set_last_error( ERROR_INVALID_PARAMETER );
+        return FALSE;
+    }
+}
+
 static BOOL session_set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD buflen )
 {
     switch (option)
@@ -82,22 +120,33 @@
     }
     case WINHTTP_OPTION_REDIRECT_POLICY:
     {
-        DWORD policy = *(DWORD *)buffer;
-
+        DWORD policy;
+
+        if (buflen != sizeof(policy))
+        {
+            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            return FALSE;
+        }
+
+        policy = *(DWORD *)buffer;
         TRACE("0x%x\n", policy);
         hdr->redirect_policy = policy;
         return TRUE;
     }
+    case WINHTTP_OPTION_DISABLE_FEATURE:
+        set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+        return FALSE;
     default:
         FIXME("unimplemented option %u\n", option);
-        return TRUE;
+        set_last_error( ERROR_INVALID_PARAMETER );
+        return FALSE;
     }
 }
 
 static const object_vtbl_t session_vtbl =
 {
     session_destroy,
-    NULL,
+    session_query_option,
     session_set_option
 };
 
@@ -118,6 +167,8 @@
     session->hdr.flags = flags;
     session->hdr.refs = 1;
     session->access = access;
+    session->hdr.redirect_policy = WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP;
+    list_init( &session->cookie_cache );
 
     if (agent && !(session->agent = strdupW( agent ))) goto end;
     if (proxy && !(session->proxy_server = strdupW( proxy ))) goto end;
@@ -202,10 +253,10 @@
     list_add_head( &session->hdr.children, &connect->hdr.entry );
 
     if (server && !(connect->hostname = strdupW( server ))) goto end;
-    connect->hostport = port ? port : (connect->hdr.flags & WINHTTP_FLAG_SECURE ? 443 : 80);
+    connect->hostport = port;
 
     if (server && !(connect->servername = strdupW( server ))) goto end;
-    connect->serverport = port ? port : (connect->hdr.flags & WINHTTP_FLAG_SECURE ? 443 : 80);
+    connect->serverport = port;
 
     if (!(hconnect = alloc_handle( &connect->hdr ))) goto end;
     connect->hdr.handle = hconnect;
@@ -225,7 +276,7 @@
 static void request_destroy( object_header_t *hdr )
 {
     request_t *request = (request_t *)hdr;
-    int i;
+    DWORD i;
 
     TRACE("%p\n", request);
 
@@ -251,15 +302,54 @@
     {
     case WINHTTP_OPTION_SECURITY_FLAGS:
     {
-        DWORD flags = 0;
-
+        DWORD flags;
+
+        if (!buffer || *buflen < sizeof(flags))
+        {
+            *buflen = sizeof(flags);
+            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            return FALSE;
+        }
+
+        flags = 0;
         if (hdr->flags & WINHTTP_FLAG_SECURE) flags |= SECURITY_FLAG_SECURE;
         *(DWORD *)buffer = flags;
+        *buflen = sizeof(flags);
+        return TRUE;
+    }
+    case WINHTTP_OPTION_SERVER_CERT_CONTEXT:
+    {
+        const CERT_CONTEXT *cert;
+        request_t *request = (request_t *)hdr;
+
+        if (!buffer || *buflen < sizeof(cert))
+        {
+            *buflen = sizeof(cert);
+            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            return FALSE;
+        }
+
+        if (!(cert = netconn_get_certificate( &request->netconn ))) return FALSE;
+        *(CERT_CONTEXT **)buffer = (CERT_CONTEXT *)cert;
+        *buflen = sizeof(cert);
+        return TRUE;
+    }
+    case WINHTTP_OPTION_SECURITY_KEY_BITNESS:
+    {
+        if (!buffer || *buflen < sizeof(DWORD))
+        {
+            *buflen = sizeof(DWORD);
+            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            return FALSE;
+        }
+
+        *(DWORD *)buffer = 128; /* FIXME */
         *buflen = sizeof(DWORD);
         return TRUE;
     }
     default:
         FIXME("unimplemented option %u\n", option);
+        set_last_error( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
 }
@@ -277,30 +367,52 @@
     }
     case WINHTTP_OPTION_DISABLE_FEATURE:
     {
-        DWORD disable = *(DWORD *)buffer;
-
+        DWORD disable;
+
+        if (buflen != sizeof(DWORD))
+        {
+            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            return FALSE;
+        }
+
+        disable = *(DWORD *)buffer;
         TRACE("0x%x\n", disable);
-        hdr->disable_flags &= disable;
+        hdr->disable_flags |= disable;
         return TRUE;
     }
     case WINHTTP_OPTION_AUTOLOGON_POLICY:
     {
-        DWORD policy = *(DWORD *)buffer;
-
+        DWORD policy;
+
+        if (buflen != sizeof(DWORD))
+        {
+            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            return FALSE;
+        }
+
+        policy = *(DWORD *)buffer;
         TRACE("0x%x\n", policy);
         hdr->logon_policy = policy;
         return TRUE;
     }
     case WINHTTP_OPTION_REDIRECT_POLICY:
     {
-        DWORD policy = *(DWORD *)buffer;
-
+        DWORD policy;
+
+        if (buflen != sizeof(DWORD))
+        {
+            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            return FALSE;
+        }
+
+        policy = *(DWORD *)buffer;
         TRACE("0x%x\n", policy);
         hdr->redirect_policy = policy;
         return TRUE;
     }
     default:
         FIXME("unimplemented option %u\n", option);
+        set_last_error( ERROR_INVALID_PARAMETER );
         return TRUE;
     }
 }
@@ -355,9 +467,26 @@
 
     if (!netconn_init( &request->netconn, request->hdr.flags & WINHTTP_FLAG_SECURE )) goto end;
 
-    if (verb && !(request->verb = strdupW( verb ))) goto end;
-    if (object && !(request->path = strdupW( object ))) goto end;
-    if (version && !(request->version = strdupW( version ))) goto end;
+    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 (!version || !version[0]) version = http1_1;
+    if (!(request->version = strdupW( version ))) goto end;
 
     if (!(hrequest = alloc_handle( &request->hdr ))) goto end;
     request->hdr.handle = hrequest;
@@ -394,19 +523,36 @@
 {
     BOOL ret = FALSE;
 
+    if (!buflen)
+    {
+        set_last_error( ERROR_INVALID_PARAMETER );
+        return FALSE;
+    }
+
     switch (option)
     {
     case WINHTTP_OPTION_CONTEXT_VALUE:
     {
+        if (!buffer || *buflen < sizeof(DWORD_PTR))
+        {
+            *buflen = sizeof(DWORD_PTR);
+            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            return FALSE;
+        }
+
         *(DWORD_PTR *)buffer = hdr->context;
         *buflen = sizeof(DWORD_PTR);
         return TRUE;
     }
     default:
-    {
         if (hdr->vtbl->query_option) ret = hdr->vtbl->query_option( hdr, option, buffer, buflen );
-        else FIXME("unimplemented option %u\n", option);
-    }
+        else
+        {
+            FIXME("unimplemented option %u\n", option);
+            set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+            return FALSE;
+        }
+        break;
     }
     return ret;
 }
@@ -437,18 +583,34 @@
 {
     BOOL ret = TRUE;
 
+    if (!buffer)
+    {
+        set_last_error( ERROR_INVALID_PARAMETER );
+        return FALSE;
+    }
+
     switch (option)
     {
     case WINHTTP_OPTION_CONTEXT_VALUE:
     {
+        if (buflen != sizeof(DWORD_PTR))
+        {
+            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            return FALSE;
+        }
+
         hdr->context = *(DWORD_PTR *)buffer;
         return TRUE;
     }
     default:
-    {
         if (hdr->vtbl->set_option) ret = hdr->vtbl->set_option( hdr, option, buffer, buflen );
-        else FIXME("unimplemented option %u\n", option);
-    }
+        else
+        {
+            FIXME("unimplemented option %u\n", option);
+            set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+            return FALSE;
+        }
+        break;
     }
     return ret;
 }

Added: trunk/reactos/dll/win32/winhttp/url.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/url.c?rev=41333&view=auto
==============================================================================
--- trunk/reactos/dll/win32/winhttp/url.c (added)
+++ trunk/reactos/dll/win32/winhttp/url.c [iso-8859-1] Sun Jun  7 16:32:05 2009
@@ -1,0 +1,484 @@
+/*
+ * Copyright 2008 Hans Leidekker for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include <stdarg.h>
+
+#include "wine/debug.h"
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "winhttp.h"
+#include "shlwapi.h"
+
+#include "winhttp_private.h"
+
+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 BOOL set_component( WCHAR **str, DWORD *str_len, WCHAR *value, DWORD len, DWORD flags )
+{
+    if (!*str)
+    {
+        if (len && (flags & ICU_DECODE))
+        {
+            set_last_error( ERROR_INVALID_PARAMETER );
+            return FALSE;
+        }
+        *str = value;
+        *str_len = len;
+    }
+    else
+    {
+        if (len > (*str_len) - 1)
+        {
+            *str_len = len + 1;
+            set_last_error( ERROR_INSUFFICIENT_BUFFER );
+            return FALSE;
+        }
+        memcpy( *str, value, len * sizeof(WCHAR) );
+        (*str)[len] = 0;
+        *str_len = len;
+    }
+    return TRUE;
+}
+
+static BOOL decode_url( LPCWSTR url, LPWSTR buffer, LPDWORD buflen )
+{
+    HRESULT hr = UrlCanonicalizeW( url, buffer, buflen, URL_WININET_COMPATIBILITY | URL_UNESCAPE );
+    if (hr == E_POINTER) set_last_error( ERROR_INSUFFICIENT_BUFFER );
+    if (hr == E_INVALIDARG) set_last_error( ERROR_INVALID_PARAMETER );
+    return (SUCCEEDED(hr)) ? TRUE : FALSE;
+}
+
+/***********************************************************************
+ *          WinHttpCrackUrl (winhttp.@)
+ */
+BOOL WINAPI WinHttpCrackUrl( LPCWSTR url, DWORD len, DWORD flags, LPURL_COMPONENTSW uc )
+{
+    BOOL ret = FALSE;
+    WCHAR *p, *q, *r;
+    WCHAR *url_decoded = NULL;
+
+    TRACE("%s, %d, %x, %p\n", debugstr_w(url), len, flags, uc);
+
+    if (flags & ICU_ESCAPE) FIXME("flag ICU_ESCAPE not supported\n");
+
+    if (!url || !uc || uc->dwStructSize != sizeof(URL_COMPONENTS))
+    {
+        set_last_error( ERROR_INVALID_PARAMETER );
+        return FALSE;
+    }
+    if (!len) len = strlenW( url );
+
+    if (flags & ICU_DECODE)
+    {
+        WCHAR *url_tmp;
+        DWORD url_len = len + 1;
+
+        if (!(url_tmp = HeapAlloc( GetProcessHeap(), 0, url_len * sizeof(WCHAR) )))
+        {
+            set_last_error( ERROR_OUTOFMEMORY );
+            return FALSE;
+        }
+        memcpy( url_tmp, url, len * sizeof(WCHAR) );
+        url_tmp[len] = 0;
+        if (!(url_decoded = HeapAlloc( GetProcessHeap(), 0, url_len * sizeof(WCHAR) )))
+        {
+            HeapFree( GetProcessHeap(), 0, url_tmp );
+            set_last_error( ERROR_OUTOFMEMORY );
+            return FALSE;
+        }
+        if (decode_url( url_tmp, url_decoded, &url_len ))
+        {
+            len = url_len;
+            url = url_decoded;
+        }
+        HeapFree( GetProcessHeap(), 0, url_tmp );
+    }
+    if (!(p = strchrW( url, ':' )))
+    {
+        set_last_error( ERROR_WINHTTP_UNRECOGNIZED_SCHEME );
+        return FALSE;
+    }
+    if (p - url == 4 && !strncmpiW( url, scheme_http, 4 )) uc->nScheme = INTERNET_SCHEME_HTTP;
+    else if (p - url == 5 && !strncmpiW( url, scheme_https, 5 )) uc->nScheme = INTERNET_SCHEME_HTTPS;
+    else
+    {
+        set_last_error( ERROR_WINHTTP_UNRECOGNIZED_SCHEME );
+        goto exit;
+    }
+    if (!(set_component( &uc->lpszScheme, &uc->dwSchemeLength, (WCHAR *)url, p - url, flags ))) goto exit;
+
+    p++; /* skip ':' */
+    if (!p[0] || p[0] != '/' || p[1] != '/') goto exit;
+    p += 2;
+
+    if (!p[0]) goto exit;
+    if ((q = memchrW( p, '@', len - (p - url) )))
+    {
+        if ((r = memchrW( p, ':', q - p )))
+        {
+            if (!(set_component( &uc->lpszUserName, &uc->dwUserNameLength, p, r - p, flags ))) goto exit;
+            r++;
+            if (!(set_component( &uc->lpszPassword, &uc->dwPasswordLength, r, q - r, flags ))) goto exit;
+        }
+        else
+        {
+            if (!(set_component( &uc->lpszUserName, &uc->dwUserNameLength, p, q - p, flags ))) goto exit;
+            if (!(set_component( &uc->lpszPassword, &uc->dwPasswordLength, NULL, 0, flags ))) goto exit;
+        }
+        p = q + 1;
+    }
+    else
+    {
+        if (!(set_component( &uc->lpszUserName, &uc->dwUserNameLength, NULL, 0, flags ))) goto exit;
+        if (!(set_component( &uc->lpszPassword, &uc->dwPasswordLength, NULL, 0, flags ))) goto exit;
+    }
+    if ((q = memchrW( p, '/', len - (p - url) )))
+    {
+        if ((r = memchrW( p, ':', q - p )))
+        {
+            if (!(set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, r - p, flags ))) goto exit;
+            r++;
+            uc->nPort = atoiW( r );
+        }
+        else
+        {
+            if (!(set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, q - p, flags ))) goto exit;
+            if (uc->nScheme == INTERNET_SCHEME_HTTP) uc->nPort = INTERNET_DEFAULT_HTTP_PORT;
+            if (uc->nScheme == INTERNET_SCHEME_HTTPS) uc->nPort = INTERNET_DEFAULT_HTTPS_PORT;
+        }
+
+        if ((r = memchrW( q, '?', len - (q - url) )))
+        {
+            if (!(set_component( &uc->lpszUrlPath, &uc->dwUrlPathLength, q, r - q, flags ))) goto exit;
+            if (!(set_component( &uc->lpszExtraInfo, &uc->dwExtraInfoLength, r, len - (r - url), flags ))) goto exit;
+        }
+        else
+        {
+            if (!(set_component( &uc->lpszUrlPath, &uc->dwUrlPathLength, q, len - (q - url), flags ))) goto exit;
+            if (!(set_component( &uc->lpszExtraInfo, &uc->dwExtraInfoLength, (WCHAR *)url + len, 0, flags ))) goto exit;
+        }
+    }
+    else
+    {
+        if ((r = memchrW( p, ':', len - (p - url) )))
+        {
+            if (!(set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, r - p, flags ))) goto exit;
+            r++;
+            uc->nPort = atoiW( r );
+        }
+        else
+        {
+            if (!(set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, len - (p - url), flags ))) goto exit;
+            if (uc->nScheme == INTERNET_SCHEME_HTTP) uc->nPort = INTERNET_DEFAULT_HTTP_PORT;
+            if (uc->nScheme == INTERNET_SCHEME_HTTPS) uc->nPort = INTERNET_DEFAULT_HTTPS_PORT;
+        }
+        if (!(set_component( &uc->lpszUrlPath, &uc->dwUrlPathLength, (WCHAR *)url + len, 0, flags ))) goto exit;
+        if (!(set_component( &uc->lpszExtraInfo, &uc->dwExtraInfoLength, (WCHAR *)url + len, 0, flags ))) goto exit;
+    }
+
+    ret = TRUE;
+
+    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 ));
+
+exit:
+    HeapFree( GetProcessHeap(), 0, url_decoded );
+    return ret;
+}
+
+static INTERNET_SCHEME get_scheme( const WCHAR *scheme, DWORD len )
+{
+    if (!strncmpW( scheme, scheme_http, len )) return INTERNET_SCHEME_HTTP;
+    if (!strncmpW( scheme, scheme_https, len )) return INTERNET_SCHEME_HTTPS;
+    return 0;
+}
+
+static const WCHAR *get_scheme_string( INTERNET_SCHEME scheme )
+{
+    if (scheme == INTERNET_SCHEME_HTTP) return scheme_http;
+    if (scheme == INTERNET_SCHEME_HTTPS) return scheme_https;
+    return NULL;
+}
+
+static BOOL uses_default_port( INTERNET_SCHEME scheme, INTERNET_PORT port )
+{
+    if ((scheme == INTERNET_SCHEME_HTTP) && (port == INTERNET_DEFAULT_HTTP_PORT)) return TRUE;
+    if ((scheme == INTERNET_SCHEME_HTTPS) && (port == INTERNET_DEFAULT_HTTPS_PORT)) return TRUE;
+    return FALSE;
+}
+
+static BOOL need_escape( WCHAR c )
+{
+    if (isalnumW( c )) return FALSE;
+
+    if (c <= 31 || c >= 127) return TRUE;
+    else
+    {
+        switch (c)
+        {
+        case ' ':
+        case '"':
+        case '#':
+        case '%':
+        case '<':
+        case '>':
+        case ']':
+        case '\\':
+        case '[':
+        case '^':
+        case '`':
+        case '{':
+        case '|':
+        case '}':
+        case '~':
+            return TRUE;
+        default:
+            return FALSE;
+        }
+    }
+}
+
+static DWORD copy_escape( WCHAR *dst, const WCHAR *src, DWORD 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;
+
+    for (i = 0; i < len; i++, p++)
+    {
+        if (need_escape( src[i] ))
+        {
+            p[0] = '%';
+            p[1] = hex[(src[i] >> 4) & 0xf];
+            p[2] = hex[src[i] & 0xf];
+            ret += 2;
+            p += 2;
+        }
+        else *p = src[i];
+    }
+    dst[ret] = 0;
+    return ret;
+}
+
+static DWORD comp_length( DWORD len, DWORD flags, WCHAR *comp )
+{
+    DWORD ret;
+    unsigned int i;
+
+    ret = len ? len : strlenW( comp );
+    if (!(flags & ICU_ESCAPE)) return ret;
+    for (i = 0; i < len; i++) if (need_escape( comp[i] )) ret += 2;
+    return ret;
+}
+
+static BOOL calc_length( URL_COMPONENTS *uc, DWORD flags, LPDWORD len )
+{
+    static const WCHAR formatW[] = {'%','d',0};
+    INTERNET_SCHEME scheme;
+
+    *len = 0;
+    if (uc->lpszScheme)
+    {
+        DWORD scheme_len = comp_length( uc->dwSchemeLength, 0, uc->lpszScheme );
+        *len += scheme_len;
+        scheme = get_scheme( uc->lpszScheme, scheme_len );
+    }
+    else
+    {
+        scheme = uc->nScheme;
+        if (!scheme) scheme = INTERNET_SCHEME_HTTP;
+        *len += strlenW( get_scheme_string( scheme ) );
+    }
+    *len += 1; /* ':' */
+    if (uc->lpszHostName) *len += 2; /* "//" */
+
+    if (uc->lpszUserName)
+    {
+        *len += comp_length( uc->dwUserNameLength, 0, uc->lpszUserName );
+        *len += 1; /* "@" */
+    }
+    else
+    {
+        if (uc->lpszPassword)
+        {
+            set_last_error( ERROR_INVALID_PARAMETER );
+            return FALSE;
+        }
+    }
+    if (uc->lpszPassword)
+    {
+        *len += 1; /* ":" */
+        *len += comp_length( uc->dwPasswordLength, 0, uc->lpszPassword );
+    }
+    if (uc->lpszHostName)
+    {
+        *len += comp_length( uc->dwHostNameLength, 0, uc->lpszHostName );
+
+        if (!uses_default_port( scheme, uc->nPort ))
+        {
+            WCHAR port[sizeof("65535")];
+
+            sprintfW( port, formatW, uc->nPort );
+            *len += strlenW( port );
+            *len += 1; /* ":" */
+        }
+        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 );
+    return TRUE;
+}
+
+/***********************************************************************
+ *          WinHttpCreateUrl (winhttp.@)
+ */
+BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDWORD required )
+{
+    static const WCHAR formatW[] = {'%','d',0};
+    static const WCHAR twoslashW[] = {'/','/'};
+
+    DWORD len;
+    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 );
+        return FALSE;
+    }
+
+    if (!calc_length( uc, flags, &len )) return FALSE;
+
+    if (!url || *required < len)
+    {
+        *required = len + 1;
+        set_last_error( ERROR_INSUFFICIENT_BUFFER );
+        return FALSE;
+    }
+
+    url[0] = 0;
+    *required = len;
+    if (uc->lpszScheme)
+    {
+        len = comp_length( uc->dwSchemeLength, 0, uc->lpszScheme );
+        memcpy( url, uc->lpszScheme, len * sizeof(WCHAR) );
+        url += len;
+
+        scheme = get_scheme( uc->lpszScheme, len );
+    }
+    else
+    {
+        const WCHAR *schemeW;
+        scheme = uc->nScheme;
+
+        if (!scheme) scheme = INTERNET_SCHEME_HTTP;
+
+        schemeW = get_scheme_string( scheme );
+        len = strlenW( schemeW );
+        memcpy( url, schemeW, len * sizeof(WCHAR) );
+        url += len;
+    }
+
+    /* all schemes are followed by at least a colon */
+    *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 );
+        memcpy( url, uc->lpszUserName, len * sizeof(WCHAR) );
+        url += len;
+
+        if (uc->lpszPassword)
+        {
+            *url = ':';
+            url++;
+
+            len = comp_length( uc->dwPasswordLength, 0, uc->lpszPassword );
+            memcpy( url, uc->lpszPassword, len * sizeof(WCHAR) );
+            url += len;
+        }
+        *url = '@';
+        url++;
+    }
+    if (uc->lpszHostName)
+    {
+        len = comp_length( uc->dwHostNameLength, 0, uc->lpszHostName );
+        memcpy( url, uc->lpszHostName, len * sizeof(WCHAR) );
+        url += len;
+
+        if (!uses_default_port( scheme, uc->nPort ))
+        {
+            WCHAR port[sizeof("65535")];
+
+            sprintfW( port, formatW, uc->nPort );
+            *url = ':';
+            url++;
+
+            len = strlenW( port );
+            memcpy( url, port, len * sizeof(WCHAR) );
+            url += len;
+        }
+
+        /* add slash between hostname and path if necessary */
+        if (uc->lpszUrlPath && *uc->lpszUrlPath != '/')
+        {
+            *url = '/';
+            url++;
+        }
+    }
+    if (uc->lpszUrlPath)
+    {
+        len = comp_length( uc->dwUrlPathLength, 0, uc->lpszUrlPath );
+        if (flags & ICU_ESCAPE) url += copy_escape( url, uc->lpszUrlPath, len );
+        else
+        {
+            memcpy( url, uc->lpszUrlPath, len * sizeof(WCHAR) );
+            url += len;
+        }
+    }
+    if (uc->lpszExtraInfo)
+    {
+        len = comp_length( uc->dwExtraInfoLength, 0, uc->lpszExtraInfo );
+        if (flags & ICU_ESCAPE) url += copy_escape( url, uc->lpszExtraInfo, len );
+        else
+        {
+            memcpy( url, uc->lpszExtraInfo, len * sizeof(WCHAR) );
+            url += len;
+        }
+    }
+    *url = 0;
+    return TRUE;
+}

Propchange: trunk/reactos/dll/win32/winhttp/url.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: trunk/reactos/dll/win32/winhttp/winhttp.rbuild
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/winhttp.rbuild?rev=41333&r1=41332&r2=41333&view=diff
==============================================================================
--- trunk/reactos/dll/win32/winhttp/winhttp.rbuild [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/winhttp/winhttp.rbuild [iso-8859-1] Sun Jun  7 16:32:05 2009
@@ -7,12 +7,15 @@
 	<include base="winhttp">.</include>
 	<include base="ReactOS">include/reactos/wine</include>
 	<define name="__WINESRC__" />
+	<file>cookie.c</file>
 	<file>handle.c</file>
 	<file>main.c</file>
 	<file>net.c</file>
 	<file>request.c</file>
 	<file>session.c</file>
+	<file>url.c</file>
 	<library>wine</library>
+	<library>shlwapi</library>
 	<library>wininet</library>
 	<library>ws2_32</library>
 	<library>kernel32</library>

Modified: trunk/reactos/dll/win32/winhttp/winhttp_private.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/winhttp_private.h?rev=41333&r1=41332&r2=41333&view=diff
==============================================================================
--- trunk/reactos/dll/win32/winhttp/winhttp_private.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/winhttp/winhttp_private.h [iso-8859-1] Sun Jun  7 16:32:05 2009
@@ -26,6 +26,7 @@
 #include "wine/list.h"
 #include "wine/unicode.h"
 
+#include <sys/types.h>
 #ifdef HAVE_NETINET_IN_H
 # include <netinet/in.h>
 #endif
@@ -33,14 +34,17 @@
 # include <netdb.h>
 #endif
 #if defined(__MINGW32__) || defined (_MSC_VER)
-#  include "ws2tcpip.h"
-#  ifndef MSG_WAITALL
-#  define MSG_WAITALL 0
-#  endif
+# include <ws2tcpip.h>
 #else
-#  define closesocket close
-#  define ioctlsocket ioctl
-#endif /* __MINGW32__ */
+# define closesocket close
+# define ioctlsocket ioctl
+#endif
+
+static const WCHAR getW[]    = {'G','E','T',0};
+static const WCHAR postW[]   = {'P','O','S','T',0};
+static const WCHAR slashW[]  = {'/',0};
+static const WCHAR http1_0[] = {'H','T','T','P','/','1','.','0',0};
+static const WCHAR http1_1[] = {'H','T','T','P','/','1','.','1',0};
 
 typedef struct _object_header_t object_header_t;
 
@@ -71,6 +75,21 @@
 
 typedef struct
 {
+    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
+{
     object_header_t hdr;
     LPWSTR agent;
     DWORD access;
@@ -78,6 +97,7 @@
     LPWSTR proxy_bypass;
     LPWSTR proxy_username;
     LPWSTR proxy_password;
+    struct list cookie_cache;
 } session_t;
 
 typedef struct
@@ -97,7 +117,6 @@
 {
     int socket;
     BOOL secure; /* SSL active on connection? */
-    void *ssl_ctx;
     void *ssl_conn;
     char *peek_msg;
     char *peek_msg_mem;
@@ -127,6 +146,52 @@
     DWORD num_headers;
 } request_t;
 
+typedef struct _task_header_t task_header_t;
+
+struct _task_header_t
+{
+    request_t *request;
+    void (*proc)( task_header_t * );
+};
+
+typedef struct
+{
+    task_header_t hdr;
+    LPWSTR headers;
+    DWORD headers_len;
+    LPVOID optional;
+    DWORD optional_len;
+    DWORD total_len;
+    DWORD_PTR context;
+} send_request_t;
+
+typedef struct
+{
+    task_header_t hdr;
+} receive_response_t;
+
+typedef struct
+{
+    task_header_t hdr;
+    LPDWORD available;
+} query_data_t;
+
+typedef struct
+{
+    task_header_t hdr;
+    LPVOID buffer;
+    DWORD to_read;
+    LPDWORD read;
+} read_data_t;
+
+typedef struct
+{
+    task_header_t hdr;
+    LPCVOID buffer;
+    DWORD to_write;
+    LPDWORD written;
+} write_data_t;
+
 object_header_t *addref_object( object_header_t * );
 object_header_t *grab_object( HINTERNET );
 void release_object( object_header_t * );
@@ -134,6 +199,7 @@
 BOOL free_handle( HINTERNET );
 
 void set_last_error( DWORD );
+DWORD get_last_error( void );
 void send_callback( object_header_t *, DWORD, LPVOID, DWORD );
 void close_connection( request_t * );
 
@@ -148,6 +214,12 @@
 BOOL netconn_resolve( WCHAR *, INTERNET_PORT, struct sockaddr_in * );
 BOOL netconn_secure_connect( netconn_t * );
 BOOL netconn_send( netconn_t *, const void *, size_t, int, int * );
+const void *netconn_get_certificate( netconn_t * );
+
+BOOL set_cookies( request_t *, const WCHAR * );
+BOOL add_cookie_headers( request_t * );
+BOOL add_request_headers( request_t *, LPCWSTR, DWORD, DWORD );
+void delete_domain( domain_t * );
 
 static inline void *heap_alloc( SIZE_T size )
 {

Modified: trunk/reactos/include/psdk/winhttp.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/psdk/winhttp.h?rev=41333&r1=41332&r2=41333&view=diff
==============================================================================
--- trunk/reactos/include/psdk/winhttp.h [iso-8859-1] (original)
+++ trunk/reactos/include/psdk/winhttp.h [iso-8859-1] Sun Jun  7 16:32:05 2009
@@ -35,6 +35,8 @@
 #define INTERNET_SCHEME_HTTP            1
 #define INTERNET_SCHEME_HTTPS           2
 typedef int INTERNET_SCHEME, *LPINTERNET_SCHEME;
+
+#define ICU_ESCAPE  0x80000000
 
 /* flags for WinHttpOpen */
 #define WINHTTP_FLAG_ASYNC                  0x10000000



More information about the Ros-diffs mailing list