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.…
==============================================================================
--- 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?re…
==============================================================================
--- 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_ma…
==============================================================================
--- 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…
==============================================================================
--- 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?r…
==============================================================================
--- 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?re…
==============================================================================
--- 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.…
==============================================================================
--- 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.…
==============================================================================
--- 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?re…
==============================================================================
--- 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.…
==============================================================================
--- 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_…
==============================================================================
--- 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…
==============================================================================
--- 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