Author: akhaldi
Date: Sat Sep 28 15:23:56 2013
New Revision: 60426
URL:
http://svn.reactos.org/svn/reactos?rev=60426&view=rev
Log:
[WINHTTP]
* Sync with Wine 1.7.1.
CORE-7469
Modified:
trunk/reactos/dll/win32/winhttp/CMakeLists.txt
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_private.h
trunk/reactos/media/doc/README.WINE
Modified: trunk/reactos/dll/win32/winhttp/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/CMakeLis…
==============================================================================
--- trunk/reactos/dll/win32/winhttp/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/winhttp/CMakeLists.txt [iso-8859-1] Sat Sep 28 15:23:56 2013
@@ -1,11 +1,8 @@
-
-add_typelib(winhttp_tlb.idl)
add_definitions(
-D__WINESRC__
-D_WINE)
include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine)
-
spec2def(winhttp.dll winhttp.spec ADD_IMPORTLIB)
list(APPEND SOURCE
@@ -16,19 +13,14 @@
request.c
session.c
url.c
- rsrc.rc
${CMAKE_CURRENT_BINARY_DIR}/winhttp.def)
set_source_files_properties(rsrc.rc PROPERTIES OBJECT_DEPENDS
${CMAKE_CURRENT_BINARY_DIR}/winhttp_tlb.tlb)
-
-add_library(winhttp SHARED ${SOURCE})
-
+add_typelib(winhttp_tlb.idl)
+add_library(winhttp SHARED ${SOURCE} rsrc.rc)
set_module_type(winhttp win32dll)
target_link_libraries(winhttp uuid wine)
add_delay_importlibs(winhttp oleaut32 ole32 crypt32 secur32)
add_importlibs(winhttp user32 advapi32 ws2_32 msvcrt kernel32 ntdll)
-
-# wininet_tlb.tlb needs stdole2.tlb
-add_dependencies(winhttp stdole2)
-
+add_dependencies(winhttp stdole2) # wininet_tlb.tlb needs stdole2.tlb
add_cd_file(TARGET winhttp DESTINATION reactos/system32 FOR all)
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] Sat Sep 28 15:23:56 2013
@@ -50,6 +50,7 @@
DisableThreadLibraryCalls(hInstDLL);
break;
case DLL_PROCESS_DETACH:
+ if (lpv) break;
netconn_unload();
break;
}
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] Sat Sep 28 15:23:56 2013
@@ -426,7 +426,7 @@
size = send(conn->socket, out_buf.pvBuffer, out_buf.cbBuffer, 0);
if(size != out_buf.cbBuffer) {
ERR("send failed\n");
- status = ERROR_WINHTTP_SECURE_CHANNEL_ERROR;
+ res = ERROR_WINHTTP_SECURE_CHANNEL_ERROR;
break;
}
@@ -551,15 +551,13 @@
return TRUE;
}
-BOOL netconn_send( netconn_t *conn, const void *msg, size_t len, int flags, int *sent )
+BOOL netconn_send( netconn_t *conn, const void *msg, size_t len, int *sent )
{
if (!netconn_connected( conn )) return FALSE;
if (conn->secure)
{
const BYTE *ptr = msg;
size_t chunk_size;
-
- if (flags) FIXME("flags %08x not supported in SSL\n", flags);
*sent = 0;
@@ -575,7 +573,7 @@
return TRUE;
}
- if ((*sent = send( conn->socket, msg, len, flags )) == -1)
+ if ((*sent = send( conn->socket, msg, len, 0 )) == -1)
{
set_last_error( sock_get_error( errno ) );
return FALSE;
@@ -687,17 +685,7 @@
SIZE_T size, cread;
BOOL res, eof;
- if (flags & ~(MSG_PEEK | MSG_WAITALL))
- FIXME("SSL_read does not support the following flags: %08x\n",
flags);
-
- if (flags & MSG_PEEK && conn->peek_msg)
- {
- if (len < conn->peek_len) FIXME("buffer isn't big enough,
should we wrap?\n");
- *recvd = min( len, conn->peek_len );
- memcpy( buf, conn->peek_msg, *recvd );
- return TRUE;
- }
- else if (conn->peek_msg)
+ if (conn->peek_msg)
{
*recvd = min( len, conn->peek_len );
memcpy( buf, conn->peek_msg, *recvd );
@@ -711,7 +699,7 @@
conn->peek_msg = NULL;
}
/* check if we have enough data from the peek buffer */
- if (!(flags & MSG_WAITALL) || (*recvd == len)) return TRUE;
+ if (!(flags & MSG_WAITALL) || *recvd == len) return TRUE;
}
size = *recvd;
@@ -732,14 +720,6 @@
size += cread;
}while(!size || ((flags & MSG_WAITALL) && size < len));
- if(size && (flags & MSG_PEEK)) {
- conn->peek_msg_mem = conn->peek_msg = heap_alloc(size);
- if(!conn->peek_msg)
- return FALSE;
-
- memcpy(conn->peek_msg, buf, size);
- }
-
TRACE("received %ld bytes\n", size);
*recvd = size;
return TRUE;
@@ -770,84 +750,6 @@
if (!(ret = ioctlsocket( conn->socket, FIONREAD, &unread ))) *available =
unread;
#endif
return TRUE;
-}
-
-BOOL netconn_get_next_line( netconn_t *conn, char *buffer, DWORD *buflen )
-{
- // ReactOS: use select instead of poll
- fd_set infd;
- BOOL ret = FALSE;
- DWORD recvd = 0;
-
- if (!netconn_connected( conn )) return FALSE;
-
- if (conn->secure)
- {
- while (recvd < *buflen)
- {
- int dummy;
- if (!netconn_recv( conn, &buffer[recvd], 1, 0, &dummy ))
- {
- set_last_error( ERROR_CONNECTION_ABORTED );
- break;
- }
- if (buffer[recvd] == '\n')
- {
- ret = TRUE;
- break;
- }
- if (buffer[recvd] != '\r') recvd++;
- }
- if (ret)
- {
- buffer[recvd++] = 0;
- *buflen = recvd;
- TRACE("received line %s\n", debugstr_a(buffer));
- }
- return ret;
- }
-
- FD_ZERO(&infd);
- FD_SET(conn->socket, &infd);
-
- while (recvd < *buflen)
- {
- int res;
- struct timeval tv, *ptv;
- socklen_t len = sizeof(tv);
-
- if ((res = getsockopt( conn->socket, SOL_SOCKET, SO_RCVTIMEO, (void*)&tv,
&len ) != -1))
- ptv = &tv;
- else
- ptv = NULL;
-
- if (select( 0, &infd, NULL, NULL, ptv ) > 0)
- {
- if ((res = recv( conn->socket, &buffer[recvd], 1, 0 )) <= 0)
- {
- if (res == -1) set_last_error( sock_get_error( errno ) );
- break;
- }
- if (buffer[recvd] == '\n')
- {
- ret = TRUE;
- break;
- }
- if (buffer[recvd] != '\r') recvd++;
- }
- else
- {
- set_last_error( ERROR_WINHTTP_TIMEOUT );
- break;
- }
- }
- if (ret)
- {
- buffer[recvd++] = 0;
- *buflen = recvd;
- TRACE("received line %s\n", debugstr_a(buffer));
- }
- return ret;
}
DWORD netconn_set_timeout( netconn_t *netconn, BOOL send, int value )
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] Sat Sep 28 15:23:56 2013
@@ -906,7 +906,7 @@
{
int len = strlen( req_ascii ), bytes_sent;
- ret = netconn_send( &request->netconn, req_ascii, len, 0,
&bytes_sent );
+ ret = netconn_send( &request->netconn, req_ascii, len,
&bytes_sent );
heap_free( req_ascii );
if (ret)
ret = read_reply( request );
@@ -950,7 +950,7 @@
struct sockaddr *saddr;
DWORD len;
- if (netconn_connected( &request->netconn )) return TRUE;
+ if (netconn_connected( &request->netconn )) goto done;
connect = request->connect;
port = connect->serverport ? connect->serverport : (request->hdr.flags &
WINHTTP_FLAG_SECURE ? 443 : 80);
@@ -1008,6 +1008,9 @@
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER,
addressW, strlenW(addressW) + 1 );
+done:
+ request->read_pos = request->read_size = 0;
+ request->read_chunked = FALSE;
heap_free( addressW );
return TRUE;
}
@@ -1123,13 +1126,17 @@
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST, NULL, 0
);
- ret = netconn_send( &request->netconn, req_ascii, len, 0, &bytes_sent );
+ ret = netconn_send( &request->netconn, req_ascii, len, &bytes_sent );
heap_free( req_ascii );
if (!ret) goto end;
- if (optional_len && !netconn_send( &request->netconn, optional,
optional_len, 0, &bytes_sent )) goto end;
- len += optional_len;
-
+ if (optional_len)
+ {
+ if (!netconn_send( &request->netconn, optional, optional_len,
&bytes_sent )) goto end;
+ request->optional = optional;
+ request->optional_len = optional_len;
+ len += optional_len;
+ }
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_SENT, &len,
sizeof(DWORD) );
end:
@@ -1205,29 +1212,45 @@
#define ARRAYSIZE(array) (sizeof(array) / sizeof((array)[0]))
+static const WCHAR basicW[] =
{'B','a','s','i','c',0};
+static const WCHAR ntlmW[] = {'N','T','L','M',0};
+static const WCHAR passportW[] =
{'P','a','s','s','p','o','r','t',0};
+static const WCHAR digestW[] =
{'D','i','g','e','s','t',0};
+static const WCHAR negotiateW[] =
{'N','e','g','o','t','i','a','t','e',0};
+
+static const struct
+{
+ const WCHAR *str;
+ unsigned int len;
+ DWORD scheme;
+}
+auth_schemes[] =
+{
+ { basicW, ARRAYSIZE(basicW) - 1, WINHTTP_AUTH_SCHEME_BASIC },
+ { ntlmW, ARRAYSIZE(ntlmW) - 1, WINHTTP_AUTH_SCHEME_NTLM },
+ { passportW, ARRAYSIZE(passportW) - 1, WINHTTP_AUTH_SCHEME_PASSPORT },
+ { digestW, ARRAYSIZE(digestW) - 1, WINHTTP_AUTH_SCHEME_DIGEST },
+ { negotiateW, ARRAYSIZE(negotiateW) - 1, WINHTTP_AUTH_SCHEME_NEGOTIATE }
+};
+static const unsigned int num_auth_schemes =
sizeof(auth_schemes)/sizeof(auth_schemes[0]);
+
+static enum auth_scheme scheme_from_flag( DWORD flag )
+{
+ int i;
+
+ for (i = 0; i < num_auth_schemes; i++) if (flag == auth_schemes[i].scheme) return
i;
+ return SCHEME_INVALID;
+}
+
static DWORD auth_scheme_from_header( WCHAR *header )
{
- static const WCHAR basic[] =
{'B','a','s','i','c'};
- static const WCHAR ntlm[] = {'N','T','L','M'};
- static const WCHAR passport[] =
{'P','a','s','s','p','o','r','t'};
- static const WCHAR digest[] =
{'D','i','g','e','s','t'};
- static const WCHAR negotiate[] =
{'N','e','g','o','t','i','a','t','e'};
-
- if (!strncmpiW( header, basic, ARRAYSIZE(basic) ) &&
- (header[ARRAYSIZE(basic)] == ' ' || !header[ARRAYSIZE(basic)])) return
WINHTTP_AUTH_SCHEME_BASIC;
-
- if (!strncmpiW( header, ntlm, ARRAYSIZE(ntlm) ) &&
- (header[ARRAYSIZE(ntlm)] == ' ' || !header[ARRAYSIZE(ntlm)])) return
WINHTTP_AUTH_SCHEME_NTLM;
-
- if (!strncmpiW( header, passport, ARRAYSIZE(passport) ) &&
- (header[ARRAYSIZE(passport)] == ' ' || !header[ARRAYSIZE(passport)]))
return WINHTTP_AUTH_SCHEME_PASSPORT;
-
- if (!strncmpiW( header, digest, ARRAYSIZE(digest) ) &&
- (header[ARRAYSIZE(digest)] == ' ' || !header[ARRAYSIZE(digest)])) return
WINHTTP_AUTH_SCHEME_DIGEST;
-
- if (!strncmpiW( header, negotiate, ARRAYSIZE(negotiate) ) &&
- (header[ARRAYSIZE(negotiate)] == ' ' || !header[ARRAYSIZE(negotiate)]))
return WINHTTP_AUTH_SCHEME_NEGOTIATE;
-
+ unsigned int i;
+
+ for (i = 0; i < num_auth_schemes; i++)
+ {
+ if (!strncmpiW( header, auth_schemes[i].str, auth_schemes[i].len ) &&
+ (header[auth_schemes[i].len] == ' ' || !header[auth_schemes[i].len]))
return auth_schemes[i].scheme;
+ }
return 0;
}
@@ -1253,10 +1276,14 @@
return FALSE;
}
scheme = auth_scheme_from_header( buffer );
- if (first && index == 1) *first = scheme;
- *supported |= scheme;
-
heap_free( buffer );
+ if (!scheme) break;
+
+ if (first && index == 1)
+ *first = *supported = scheme;
+ else
+ *supported |= scheme;
+
ret = TRUE;
}
return ret;
@@ -1283,6 +1310,13 @@
set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
return FALSE;
}
+ if (!supported || !first || !target)
+ {
+ release_object( &request->hdr );
+ set_last_error( ERROR_INVALID_PARAMETER );
+ return FALSE;
+
+ }
if (query_auth_schemes( request, WINHTTP_QUERY_WWW_AUTHENTICATE, supported, first ))
{
@@ -1340,72 +1374,350 @@
return n;
}
-static BOOL set_credentials( request_t *request, DWORD target, DWORD scheme, LPCWSTR
username, LPCWSTR password )
-{
- static const WCHAR basic[] =
{'B','a','s','i','c',' ',0};
- const WCHAR *auth_scheme, *auth_target;
- WCHAR *auth_header;
- DWORD len, auth_data_len;
- char *auth_data;
+static inline char decode_char( WCHAR c )
+{
+ if (c >= 'A' && c <= 'Z') return c - 'A';
+ if (c >= 'a' && c <= 'z') return c - 'a' + 26;
+ if (c >= '0' && c <= '9') return c - '0' + 52;
+ if (c == '+') return 62;
+ if (c == '/') return 63;
+ return 64;
+}
+
+static unsigned int decode_base64( const WCHAR *base64, unsigned int len, char *buf )
+{
+ unsigned int i = 0;
+ char c0, c1, c2, c3;
+ const WCHAR *p = base64;
+
+ while (len >= 4)
+ {
+ if ((c0 = decode_char( p[0] )) > 63) return 0;
+ if ((c1 = decode_char( p[1] )) > 63) return 0;
+ if ((c2 = decode_char( p[2] )) > 63) return 0;
+ if ((c3 = decode_char( p[3] )) > 63) return 0;
+
+ if (buf)
+ {
+ buf[i + 0] = (c0 << 2) | (c1 >> 4);
+ buf[i + 1] = (c1 << 4) | (c2 >> 2);
+ buf[i + 2] = (c2 << 6) | c3;
+ }
+ len -= 4;
+ i += 3;
+ p += 4;
+ }
+ if (p[2] == '=')
+ {
+ if ((c0 = decode_char( p[0] )) > 63) return 0;
+ if ((c1 = decode_char( p[1] )) > 63) return 0;
+
+ if (buf) buf[i] = (c0 << 2) | (c1 >> 4);
+ i++;
+ }
+ else if (p[3] == '=')
+ {
+ if ((c0 = decode_char( p[0] )) > 63) return 0;
+ if ((c1 = decode_char( p[1] )) > 63) return 0;
+ if ((c2 = decode_char( p[2] )) > 63) return 0;
+
+ if (buf)
+ {
+ buf[i + 0] = (c0 << 2) | (c1 >> 4);
+ buf[i + 1] = (c1 << 4) | (c2 >> 2);
+ }
+ i += 2;
+ }
+ return i;
+}
+
+static struct authinfo *alloc_authinfo(void)
+{
+ struct authinfo *ret;
+
+ if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
+
+ SecInvalidateHandle( &ret->cred );
+ SecInvalidateHandle( &ret->ctx );
+ memset( &ret->exp, 0, sizeof(ret->exp) );
+ ret->scheme = 0;
+ ret->attr = 0;
+ ret->max_token = 0;
+ ret->data = NULL;
+ ret->data_len = 0;
+ ret->finished = FALSE;
+ return ret;
+}
+
+void destroy_authinfo( struct authinfo *authinfo )
+{
+ if (!authinfo) return;
+
+ if (SecIsValidHandle( &authinfo->ctx ))
+ DeleteSecurityContext( &authinfo->ctx );
+ if (SecIsValidHandle( &authinfo->cred ))
+ FreeCredentialsHandle( &authinfo->cred );
+
+ heap_free( authinfo->data );
+ heap_free( authinfo );
+}
+
+static BOOL get_authvalue( request_t *request, DWORD level, DWORD scheme, WCHAR *buffer,
DWORD len )
+{
+ DWORD size, index = 0;
+ for (;;)
+ {
+ size = len;
+ if (!query_headers( request, level, NULL, buffer, &size, &index )) return
FALSE;
+ if (auth_scheme_from_header( buffer ) == scheme) break;
+ }
+ return TRUE;
+}
+
+static BOOL do_authorization( request_t *request, DWORD target, DWORD scheme_flag )
+{
+ struct authinfo *authinfo, **auth_ptr;
+ enum auth_scheme scheme = scheme_from_flag( scheme_flag );
+ const WCHAR *auth_target, *username, *password;
+ WCHAR auth_value[2048], *auth_reply;
+ DWORD len = sizeof(auth_value), len_scheme, flags;
BOOL ret;
- if (!username || !password)
- {
- set_last_error( ERROR_INVALID_PARAMETER );
- return FALSE;
- }
+ if (scheme == SCHEME_INVALID) return FALSE;
switch (target)
{
- case WINHTTP_AUTH_TARGET_SERVER: auth_target = attr_authorization; break;
- case WINHTTP_AUTH_TARGET_PROXY: auth_target = attr_proxy_authorization; break;
+ case WINHTTP_AUTH_TARGET_SERVER:
+ if (!get_authvalue( request, WINHTTP_QUERY_WWW_AUTHENTICATE, scheme_flag,
auth_value, len ))
+ return FALSE;
+ auth_ptr = &request->authinfo;
+ auth_target = attr_authorization;
+ username = request->connect->username;
+ password = request->connect->password;
+ break;
+
+ case WINHTTP_AUTH_TARGET_PROXY:
+ if (!get_authvalue( request, WINHTTP_QUERY_PROXY_AUTHENTICATE, scheme_flag,
auth_value, len ))
+ return FALSE;
+ auth_ptr = &request->proxy_authinfo;
+ auth_target = attr_proxy_authorization;
+ username = request->connect->session->proxy_username;
+ password = request->connect->session->proxy_password;
+ break;
+
default:
WARN("unknown target %x\n", target);
return FALSE;
}
+ authinfo = *auth_ptr;
+
switch (scheme)
{
- case WINHTTP_AUTH_SCHEME_BASIC:
- {
- int userlen = WideCharToMultiByte( CP_UTF8, 0, username, strlenW( username ),
NULL, 0, NULL, NULL );
- int passlen = WideCharToMultiByte( CP_UTF8, 0, password, strlenW( password ),
NULL, 0, NULL, NULL );
-
- TRACE("basic authentication\n");
-
- auth_scheme = basic;
- auth_data_len = userlen + 1 + passlen;
- if (!(auth_data = heap_alloc( auth_data_len ))) return FALSE;
-
- WideCharToMultiByte( CP_UTF8, 0, username, -1, auth_data, userlen, NULL, NULL );
- auth_data[userlen] = ':';
- WideCharToMultiByte( CP_UTF8, 0, password, -1, auth_data + userlen + 1, passlen,
NULL, NULL );
+ case SCHEME_BASIC:
+ {
+ int userlen, passlen;
+
+ if (!username || !password) return FALSE;
+ if ((!authinfo && !(authinfo = alloc_authinfo())) ||
authinfo->finished) return FALSE;
+
+ userlen = WideCharToMultiByte( CP_UTF8, 0, username, strlenW( username ), NULL,
0, NULL, NULL );
+ passlen = WideCharToMultiByte( CP_UTF8, 0, password, strlenW( password ), NULL,
0, NULL, NULL );
+
+ authinfo->data_len = userlen + 1 + passlen;
+ if (!(authinfo->data = heap_alloc( authinfo->data_len ))) return FALSE;
+
+ WideCharToMultiByte( CP_UTF8, 0, username, -1, authinfo->data, userlen, NULL,
NULL );
+ authinfo->data[userlen] = ':';
+ WideCharToMultiByte( CP_UTF8, 0, password, -1, authinfo->data + userlen + 1,
passlen, NULL, NULL );
+
+ authinfo->scheme = SCHEME_BASIC;
+ authinfo->finished = TRUE;
break;
}
- case WINHTTP_AUTH_SCHEME_NTLM:
- case WINHTTP_AUTH_SCHEME_PASSPORT:
- case WINHTTP_AUTH_SCHEME_DIGEST:
- case WINHTTP_AUTH_SCHEME_NEGOTIATE:
- FIXME("unimplemented authentication scheme %x\n", scheme);
+ case SCHEME_NTLM:
+ case SCHEME_NEGOTIATE:
+ {
+ SECURITY_STATUS status;
+ SecBufferDesc out_desc, in_desc;
+ SecBuffer out, in;
+ ULONG flags =
ISC_REQ_CONNECTION|ISC_REQ_USE_DCE_STYLE|ISC_REQ_MUTUAL_AUTH|ISC_REQ_DELEGATE;
+ const WCHAR *p;
+ BOOL first = FALSE;
+
+ if (!authinfo)
+ {
+ TimeStamp exp;
+ SEC_WINNT_AUTH_IDENTITY_W id;
+ WCHAR *domain, *user;
+
+ if (!username || !password || !(authinfo = alloc_authinfo())) return FALSE;
+
+ first = TRUE;
+ domain = (WCHAR *)username;
+ user = strchrW( username, '\\' );
+
+ if (user) user++;
+ else
+ {
+ user = (WCHAR *)username;
+ domain = NULL;
+ }
+ id.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
+ id.User = user;
+ id.UserLength = strlenW( user );
+ id.Domain = domain;
+ id.DomainLength = domain ? user - domain - 1 : 0;
+ id.Password = (WCHAR *)password;
+ id.PasswordLength = strlenW( password );
+
+ status = AcquireCredentialsHandleW( NULL, (SEC_WCHAR
*)auth_schemes[scheme].str,
+ SECPKG_CRED_OUTBOUND, NULL, &id,
NULL, NULL,
+ &authinfo->cred, &exp );
+ if (status == SEC_E_OK)
+ {
+ PSecPkgInfoW info;
+ status = QuerySecurityPackageInfoW( (SEC_WCHAR
*)auth_schemes[scheme].str, &info );
+ if (status == SEC_E_OK)
+ {
+ authinfo->max_token = info->cbMaxToken;
+ FreeContextBuffer( info );
+ }
+ }
+ if (status != SEC_E_OK)
+ {
+ WARN("AcquireCredentialsHandleW for scheme %s failed with error
0x%08x\n",
+ debugstr_w(auth_schemes[scheme].str), status);
+ heap_free( authinfo );
+ return FALSE;
+ }
+ authinfo->scheme = scheme;
+ }
+ else if (authinfo->finished) return FALSE;
+
+ if ((strlenW( auth_value ) < auth_schemes[authinfo->scheme].len ||
+ strncmpiW( auth_value, auth_schemes[authinfo->scheme].str,
auth_schemes[authinfo->scheme].len )))
+ {
+ ERR("authentication scheme changed from %s to %s\n",
+ debugstr_w(auth_schemes[authinfo->scheme].str),
debugstr_w(auth_value));
+ destroy_authinfo( authinfo );
+ *auth_ptr = NULL;
+ return FALSE;
+ }
+ in.BufferType = SECBUFFER_TOKEN;
+ in.cbBuffer = 0;
+ in.pvBuffer = NULL;
+
+ in_desc.ulVersion = 0;
+ in_desc.cBuffers = 1;
+ in_desc.pBuffers = ∈
+
+ p = auth_value + auth_schemes[scheme].len;
+ if (*p == ' ')
+ {
+ int len = strlenW( ++p );
+ in.cbBuffer = decode_base64( p, len, NULL );
+ if (!(in.pvBuffer = heap_alloc( in.cbBuffer ))) return FALSE;
+ decode_base64( p, len, in.pvBuffer );
+ }
+ out.BufferType = SECBUFFER_TOKEN;
+ out.cbBuffer = authinfo->max_token;
+ if (!(out.pvBuffer = heap_alloc( authinfo->max_token )))
+ {
+ heap_free( in.pvBuffer );
+ return FALSE;
+ }
+ out_desc.ulVersion = 0;
+ out_desc.cBuffers = 1;
+ out_desc.pBuffers = &out;
+
+ status = InitializeSecurityContextW( first ? &authinfo->cred : NULL, first
? NULL : &authinfo->ctx,
+ first ? request->connect->servername :
NULL, flags, 0,
+ SECURITY_NETWORK_DREP, in.pvBuffer ?
&in_desc : NULL, 0,
+ &authinfo->ctx, &out_desc,
&authinfo->attr, &authinfo->exp );
+ heap_free( in.pvBuffer );
+ if (status == SEC_E_OK)
+ {
+ heap_free( authinfo->data );
+ authinfo->data = out.pvBuffer;
+ authinfo->data_len = out.cbBuffer;
+ authinfo->finished = TRUE;
+ TRACE("sending last auth packet\n");
+ }
+ else if (status == SEC_I_CONTINUE_NEEDED)
+ {
+ heap_free( authinfo->data );
+ authinfo->data = out.pvBuffer;
+ authinfo->data_len = out.cbBuffer;
+ TRACE("sending next auth packet\n");
+ }
+ else
+ {
+ ERR("InitializeSecurityContextW failed with error 0x%08x\n",
status);
+ heap_free( out.pvBuffer );
+ destroy_authinfo( authinfo );
+ *auth_ptr = NULL;
+ return FALSE;
+ }
+ break;
+ }
+ default:
+ ERR("invalid scheme %u\n", scheme);
return FALSE;
+ }
+ *auth_ptr = authinfo;
+
+ len_scheme = auth_schemes[authinfo->scheme].len;
+ len = len_scheme + 1 + ((authinfo->data_len + 2) * 4) / 3;
+ if (!(auth_reply = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return FALSE;
+
+ memcpy( auth_reply, auth_schemes[authinfo->scheme].str, len_scheme * sizeof(WCHAR)
);
+ auth_reply[len_scheme] = ' ';
+ encode_base64( authinfo->data, authinfo->data_len, auth_reply + len_scheme + 1
);
+
+ flags = WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE;
+ ret = process_header( request, auth_target, auth_reply, flags, TRUE );
+ heap_free( auth_reply );
+ return ret;
+}
+
+static BOOL set_credentials( request_t *request, DWORD target, DWORD scheme, const WCHAR
*username,
+ const WCHAR *password )
+{
+ if ((scheme == WINHTTP_AUTH_SCHEME_BASIC || scheme == WINHTTP_AUTH_SCHEME_DIGEST)
&&
+ (!username || !password))
+ {
+ set_last_error( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+ switch (target)
+ {
+ case WINHTTP_AUTH_TARGET_SERVER:
+ {
+ heap_free( request->connect->username );
+ if (!username) request->connect->username = NULL;
+ else if (!(request->connect->username = strdupW( username ))) return
FALSE;
+
+ heap_free( request->connect->password );
+ if (!password) request->connect->password = NULL;
+ else if (!(request->connect->password = strdupW( password ))) return
FALSE;
+ break;
+ }
+ case WINHTTP_AUTH_TARGET_PROXY:
+ {
+ heap_free( request->connect->session->proxy_username );
+ if (!username) request->connect->session->proxy_username = NULL;
+ else if (!(request->connect->session->proxy_username = strdupW( username
))) return FALSE;
+
+ heap_free( request->connect->session->proxy_password );
+ if (!password) request->connect->session->proxy_password = NULL;
+ else if (!(request->connect->session->proxy_password = strdupW( password
))) return FALSE;
+ break;
+ }
default:
- WARN("unknown authentication scheme %x\n", scheme);
+ WARN("unknown target %u\n", target);
return FALSE;
}
-
- len = strlenW( auth_scheme ) + ((auth_data_len + 2) * 4) / 3;
- if (!(auth_header = heap_alloc( (len + 1) * sizeof(WCHAR) )))
- {
- heap_free( auth_data );
- return FALSE;
- }
- strcpyW( auth_header, auth_scheme );
- encode_base64( auth_data, auth_data_len, auth_header + strlenW( auth_header ) );
-
- ret = process_header( request, auth_target, auth_header, WINHTTP_ADDREQ_FLAG_ADD |
WINHTTP_ADDREQ_FLAG_REPLACE, TRUE );
-
- heap_free( auth_data );
- heap_free( auth_header );
- return ret;
+ return TRUE;
}
/***********************************************************************
@@ -1439,8 +1751,7 @@
static BOOL handle_authorization( request_t *request, DWORD status )
{
- DWORD schemes, level, target;
- const WCHAR *username, *password;
+ DWORD i, schemes, first, level, target;
switch (status)
{
@@ -1459,24 +1770,191 @@
return FALSE;
}
- if (!query_auth_schemes( request, level, &schemes, NULL )) return FALSE;
-
- if (target == WINHTTP_AUTH_TARGET_SERVER)
- {
- username = request->connect->username;
- password = request->connect->password;
- }
- else
- {
- username = request->connect->session->proxy_username;
- password = request->connect->session->proxy_password;
- }
-
- if (schemes & WINHTTP_AUTH_SCHEME_BASIC)
- return set_credentials( request, target, WINHTTP_AUTH_SCHEME_BASIC, username,
password );
-
- FIXME("unsupported authentication scheme\n");
+ if (!query_auth_schemes( request, level, &schemes, &first )) return FALSE;
+ if (do_authorization( request, target, first )) return TRUE;
+
+ schemes &= ~first;
+ for (i = 0; i < num_auth_schemes; i++)
+ {
+ if (!(schemes & auth_schemes[i].scheme)) continue;
+ if (do_authorization( request, target, auth_schemes[i].scheme )) return TRUE;
+ }
return FALSE;
+}
+
+/* set the request content length based on the headers */
+static DWORD set_content_length( request_t *request )
+{
+ WCHAR encoding[20];
+ DWORD buflen;
+
+ buflen = sizeof(request->content_length);
+ if (!query_headers( request, WINHTTP_QUERY_CONTENT_LENGTH|WINHTTP_QUERY_FLAG_NUMBER,
+ NULL, &request->content_length, &buflen, NULL ))
+ request->content_length = ~0u;
+
+ buflen = sizeof(encoding);
+ if (query_headers( request, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, encoding,
&buflen, NULL ) &&
+ !strcmpiW( encoding, chunkedW ))
+ {
+ request->content_length = ~0u;
+ request->read_chunked = TRUE;
+ }
+ request->content_read = 0;
+ return request->content_length;
+}
+
+/* read some more data into the read buffer */
+static BOOL read_more_data( request_t *request, int maxlen )
+{
+ int len;
+
+ if (request->read_size && request->read_pos)
+ {
+ /* move existing data to the start of the buffer */
+ memmove( request->read_buf, request->read_buf + request->read_pos,
request->read_size );
+ request->read_pos = 0;
+ }
+ if (maxlen == -1) maxlen = sizeof(request->read_buf);
+ if (!netconn_recv( &request->netconn, request->read_buf +
request->read_size,
+ maxlen - request->read_size, 0, &len )) return FALSE;
+ request->read_size += len;
+ return TRUE;
+}
+
+/* remove some amount of data from the read buffer */
+static void remove_data( request_t *request, int count )
+{
+ if (!(request->read_size -= count)) request->read_pos = 0;
+ else request->read_pos += count;
+}
+
+static BOOL read_line( request_t *request, char *buffer, DWORD *len )
+{
+ int count, bytes_read, pos = 0;
+
+ for (;;)
+ {
+ char *eol = memchr( request->read_buf + request->read_pos, '\n',
request->read_size );
+ if (eol)
+ {
+ count = eol - (request->read_buf + request->read_pos);
+ bytes_read = count + 1;
+ }
+ else count = bytes_read = request->read_size;
+
+ count = min( count, *len - pos );
+ memcpy( buffer + pos, request->read_buf + request->read_pos, count );
+ pos += count;
+ remove_data( request, bytes_read );
+ if (eol) break;
+
+ if (!read_more_data( request, -1 )) return FALSE;
+ if (!request->read_size)
+ {
+ *len = 0;
+ TRACE("returning empty string\n");
+ return FALSE;
+ }
+ }
+ if (pos < *len)
+ {
+ if (pos && buffer[pos - 1] == '\r') pos--;
+ *len = pos + 1;
+ }
+ buffer[*len - 1] = 0;
+ TRACE("returning %s\n", debugstr_a(buffer));
+ return TRUE;
+}
+
+/* discard data contents until we reach end of line */
+static BOOL discard_eol( request_t *request )
+{
+ do
+ {
+ char *eol = memchr( request->read_buf + request->read_pos, '\n',
request->read_size );
+ if (eol)
+ {
+ remove_data( request, (eol + 1) - (request->read_buf +
request->read_pos) );
+ break;
+ }
+ request->read_pos = request->read_size = 0; /* discard everything */
+ if (!read_more_data( request, -1 )) return FALSE;
+ } while (request->read_size);
+ return TRUE;
+}
+
+/* read the size of the next chunk */
+static BOOL start_next_chunk( request_t *request )
+{
+ DWORD chunk_size = 0;
+
+ if (!request->content_length) return TRUE;
+ if (request->content_length == request->content_read)
+ {
+ /* read terminator for the previous chunk */
+ if (!discard_eol( request )) return FALSE;
+ request->content_length = ~0u;
+ request->content_read = 0;
+ }
+ for (;;)
+ {
+ while (request->read_size)
+ {
+ char ch = request->read_buf[request->read_pos];
+ if (ch >= '0' && ch <= '9') chunk_size =
chunk_size * 16 + ch - '0';
+ else if (ch >= 'a' && ch <= 'f') chunk_size =
chunk_size * 16 + ch - 'a' + 10;
+ else if (ch >= 'A' && ch <= 'F') chunk_size =
chunk_size * 16 + ch - 'A' + 10;
+ else if (ch == ';' || ch == '\r' || ch == '\n')
+ {
+ TRACE("reading %u byte chunk\n", chunk_size);
+ request->content_length = chunk_size;
+ request->content_read = 0;
+ if (!discard_eol( request )) return FALSE;
+ return TRUE;
+ }
+ remove_data( request, 1 );
+ }
+ if (!read_more_data( request, -1 )) return FALSE;
+ if (!request->read_size)
+ {
+ request->content_length = request->content_read = 0;
+ return TRUE;
+ }
+ }
+}
+
+/* return the size of data available to be read immediately */
+static DWORD get_available_data( request_t *request )
+{
+ if (request->read_chunked &&
+ (request->content_length == ~0u || request->content_length ==
request->content_read))
+ return 0;
+ return min( request->read_size, request->content_length -
request->content_read );
+}
+
+/* check if we have reached the end of the data to read */
+static BOOL end_of_read_data( request_t *request )
+{
+ if (request->read_chunked) return (request->content_length == 0);
+ if (request->content_length == ~0u) return FALSE;
+ return (request->content_length == request->content_read);
+}
+
+static BOOL refill_buffer( request_t *request )
+{
+ int len = sizeof(request->read_buf);
+
+ if (request->read_chunked &&
+ (request->content_length == ~0u || request->content_length ==
request->content_read))
+ {
+ if (!start_next_chunk( request )) return FALSE;
+ }
+ if (request->content_length != ~0u) len = min( len, request->content_length -
request->content_read );
+ if (len <= request->read_size) return TRUE;
+ if (!read_more_data( request, len )) return FALSE;
+ if (!request->read_size) request->content_length = request->content_read =
0;
+ return TRUE;
}
#define MAX_REPLY_LEN 1460
@@ -1500,7 +1978,7 @@
do
{
buflen = MAX_REPLY_LEN;
- if (!netconn_get_next_line( &request->netconn, buffer, &buflen ))
return FALSE;
+ if (!read_line( request, buffer, &buflen )) return FALSE;
received_len += buflen;
/* first line should look like 'HTTP/1.x nnn OK' where nnn is the status
code */
@@ -1551,7 +2029,7 @@
header_t *header;
buflen = MAX_REPLY_LEN;
- if (!netconn_get_next_line( &request->netconn, buffer, &buflen )) goto
end;
+ if (!read_line( request, buffer, &buflen )) goto end;
received_len += buflen;
if (!*buffer) break;
@@ -1582,101 +2060,6 @@
return TRUE;
}
-static BOOL receive_data( request_t *request, void *buffer, DWORD size, DWORD *read, BOOL
async )
-{
- DWORD to_read;
- int bytes_read;
-
- to_read = min( size, request->content_length - request->content_read );
- if (!netconn_recv( &request->netconn, buffer, to_read, async ? 0 :
MSG_WAITALL, &bytes_read ))
- {
- if (bytes_read != to_read)
- {
- ERR("not all data received %d/%d\n", bytes_read, to_read);
- }
- /* always return success, even if the network layer returns an error */
- *read = 0;
- return TRUE;
- }
- request->content_read += bytes_read;
- *read = bytes_read;
- return TRUE;
-}
-
-static DWORD get_chunk_size( const char *buffer )
-{
- const char *p;
- DWORD size = 0;
-
- for (p = buffer; *p; p++)
- {
- if (*p >= '0' && *p <= '9') size = size * 16 + *p -
'0';
- else if (*p >= 'a' && *p <= 'f') size = size * 16 +
*p - 'a' + 10;
- else if (*p >= 'A' && *p <= 'F') size = size * 16 +
*p - 'A' + 10;
- else if (*p == ';') break;
- }
- return size;
-}
-
-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;
- int bytes_read;
-
- *read = 0;
- for (;;)
- {
- if (*read == size) break;
-
- if (request->content_length == ~0u) /* new chunk */
- {
- buflen = sizeof(reply);
- if (!netconn_get_next_line( &request->netconn, reply, &buflen ))
break;
-
- if (!(request->content_length = get_chunk_size( reply )))
- {
- /* zero sized chunk marks end of transfer; read any trailing headers and
return */
- read_reply( request );
- break;
- }
- }
- to_read = min( to_write, request->content_length - request->content_read
);
-
- if (!netconn_recv( &request->netconn, p, to_read, async ? 0 : MSG_WAITALL,
&bytes_read ))
- {
- if (bytes_read != to_read)
- {
- ERR("Not all data received %d/%d\n", bytes_read, to_read);
- }
- /* always return success, even if the network layer returns an error */
- *read = 0;
- break;
- }
- if (!bytes_read) break;
-
- request->content_read += bytes_read;
- to_write -= bytes_read;
- *read += bytes_read;
- p += bytes_read;
-
- if (request->content_read == request->content_length) /* chunk complete */
- {
- request->content_read = 0;
- request->content_length = ~0u;
-
- buflen = sizeof(reply);
- if (!netconn_get_next_line( &request->netconn, reply, &buflen ))
- {
- ERR("Malformed chunk\n");
- *read = 0;
- break;
- }
- }
- }
- return TRUE;
-}
-
static void finished_reading( request_t *request )
{
static const WCHAR closeW[] =
{'c','l','o','s','e',0};
@@ -1692,31 +2075,40 @@
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 );
-
+}
+
+static BOOL read_data( request_t *request, void *buffer, DWORD size, DWORD *read, BOOL
async )
+{
+ BOOL ret = TRUE;
+ int len, bytes_read = 0;
+
+ if (request->read_chunked &&
+ (request->content_length == ~0u || request->content_length ==
request->content_read))
+ {
+ if (!start_next_chunk( request )) goto done;
+ }
+ if (request->content_length != ~0u) size = min( size, request->content_length -
request->content_read );
+
+ if (request->read_size)
+ {
+ bytes_read = min( request->read_size, size );
+ memcpy( buffer, request->read_buf + request->read_pos, bytes_read );
+ remove_data( request, bytes_read );
+ }
+ if (size > bytes_read && (!bytes_read || !async))
+ {
+ if ((ret = netconn_recv( &request->netconn, (char *)buffer + bytes_read,
size - bytes_read,
+ async ? 0 : MSG_WAITALL, &len )))
+ bytes_read += len;
+ }
+
+done:
+ request->content_read += bytes_read;
+ TRACE( "retrieved %u bytes (%u/%u)\n", bytes_read,
request->content_read, request->content_length );
if (async)
{
- if (ret) send_callback( &request->hdr,
WINHTTP_CALLBACK_STATUS_READ_COMPLETE, buffer, num_bytes );
+ if (ret) send_callback( &request->hdr,
WINHTTP_CALLBACK_STATUS_READ_COMPLETE, buffer, bytes_read );
else
{
WINHTTP_ASYNC_RESULT result;
@@ -1725,11 +2117,8 @@
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 );
- }
+ if (read) *read = bytes_read;
+ if (!bytes_read && request->content_read == request->content_length)
finished_reading( request );
return ret;
}
@@ -1739,7 +2128,7 @@
DWORD bytes_read;
char buffer[2048];
- if (!request->content_length)
+ if (request->content_length == ~0u)
{
finished_reading( request );
return;
@@ -1843,6 +2232,8 @@
netconn_close( &request->netconn );
if (!(ret = netconn_init( &request->netconn ))) goto end;
+ request->read_pos = request->read_size = 0;
+ request->read_chunked = FALSE;
}
if (!(ret = add_host_header( request, WINHTTP_ADDREQ_FLAG_REPLACE ))) goto end;
if (!(ret = open_connection( request ))) goto end;
@@ -1866,6 +2257,8 @@
{
heap_free( request->verb );
request->verb = strdupW( getW );
+ request->optional = NULL;
+ request->optional_len = 0;
}
ret = TRUE;
@@ -1891,10 +2284,7 @@
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;
+ set_content_length( request );
if (!(request->hdr.disable_flags & WINHTTP_DISABLE_COOKIES))
record_cookies( request );
@@ -1905,7 +2295,8 @@
if (!(ret = handle_redirect( request, status ))) break;
- send_request( request, NULL, 0, NULL, 0, 0, 0, FALSE ); /* recurse
synchronously */
+ /* recurse synchronously */
+ send_request( request, NULL, 0, request->optional,
request->optional_len, 0, 0, FALSE );
continue;
}
else if (status == HTTP_STATUS_DENIED || status == HTTP_STATUS_PROXY_AUTH_REQ)
@@ -1918,7 +2309,8 @@
ret = TRUE;
break;
}
- send_request( request, NULL, 0, NULL, 0, 0, 0, FALSE );
+ /* recurse synchronously */
+ send_request( request, NULL, 0, request->optional,
request->optional_len, 0, 0, FALSE );
continue;
}
break;
@@ -1984,35 +2376,33 @@
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);
-
+static BOOL query_data_available( request_t *request, DWORD *available, BOOL async )
+{
+ BOOL ret = TRUE;
+ DWORD count;
+
+ if (!(count = get_available_data( request )))
+ {
+ if (end_of_read_data( request ))
+ {
+ if (available) *available = 0;
+ return TRUE;
+ }
+ }
+ refill_buffer( request );
+ count = get_available_data( request );
+
+ if (count == sizeof(request->read_buf)) /* check if we have even more pending in
the socket */
+ {
+ DWORD extra;
+ if ((ret = netconn_query_data_available( &request->netconn, &extra
)))
+ {
+ count = min( count + extra, request->content_length -
request->content_read );
+ }
+ }
if (async)
{
- if (ret) send_callback( &request->hdr,
WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE, &num_bytes, sizeof(DWORD) );
+ if (ret) send_callback( &request->hdr,
WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE, &count, sizeof(count) );
else
{
WINHTTP_ASYNC_RESULT result;
@@ -2021,14 +2411,18 @@
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR,
&result, sizeof(result) );
}
}
- if (ret && available) *available = num_bytes;
+ if (ret)
+ {
+ TRACE("%u bytes available\n", count);
+ if (available) *available = count;
+ }
return ret;
}
-static void task_query_data( task_header_t *task )
+static void task_query_data_available( task_header_t *task )
{
query_data_t *q = (query_data_t *)task;
- query_data( q->hdr.request, q->available, TRUE );
+ query_data_available( q->hdr.request, q->available, TRUE );
}
/***********************************************************************
@@ -2059,14 +2453,14 @@
if (!(q = heap_alloc( sizeof(query_data_t) ))) return FALSE;
q->hdr.request = request;
- q->hdr.proc = task_query_data;
+ q->hdr.proc = task_query_data_available;
q->available = available;
addref_object( &request->hdr );
ret = queue_task( (task_header_t *)q );
}
else
- ret = query_data( request, available, FALSE );
+ ret = query_data_available( request, available, FALSE );
release_object( &request->hdr );
return ret;
@@ -2126,7 +2520,7 @@
BOOL ret;
int num_bytes;
- ret = netconn_send( &request->netconn, buffer, to_write, 0, &num_bytes );
+ ret = netconn_send( &request->netconn, buffer, to_write, &num_bytes );
if (async)
{
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] Sat Sep 28 15:23:56 2013
@@ -559,6 +559,9 @@
TRACE("%p\n", request);
release_object( &request->connect->hdr );
+
+ destroy_authinfo( request->authinfo );
+ destroy_authinfo( request->proxy_authinfo );
heap_free( request->verb );
heap_free( request->path );
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] Sat Sep 28 15:23:56
2013
@@ -51,6 +51,7 @@
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};
+static const WCHAR chunkedW[] =
{'c','h','u','n','k','e','d',0};
typedef struct _object_header_t object_header_t;
@@ -146,6 +147,29 @@
BOOL is_request; /* part of request headers? */
} header_t;
+enum auth_scheme
+{
+ SCHEME_INVALID = -1,
+ SCHEME_BASIC,
+ SCHEME_NTLM,
+ SCHEME_PASSPORT,
+ SCHEME_DIGEST,
+ SCHEME_NEGOTIATE
+};
+
+struct authinfo
+{
+ enum auth_scheme scheme;
+ CredHandle cred;
+ CtxtHandle ctx;
+ TimeStamp exp;
+ ULONG attr;
+ ULONG max_token;
+ char *data;
+ unsigned int data_len;
+ BOOL finished; /* finished authenticating */
+};
+
typedef struct
{
object_header_t hdr;
@@ -154,6 +178,8 @@
LPWSTR path;
LPWSTR version;
LPWSTR raw_headers;
+ void *optional;
+ DWORD optional_len;
netconn_t netconn;
int resolve_timeout;
int connect_timeout;
@@ -162,10 +188,16 @@
LPWSTR status_text;
DWORD content_length; /* total number of bytes to be read (per chunk) */
DWORD content_read; /* bytes read so far */
+ BOOL read_chunked; /* are we reading in chunked mode? */
+ DWORD read_pos; /* current read position in read_buf */
+ DWORD read_size; /* valid data size in read_buf */
+ char read_buf[4096]; /* buffer for already read but not returned data */
header_t *headers;
DWORD num_headers;
WCHAR **accept_types;
DWORD num_accept_types;
+ struct authinfo *authinfo;
+ struct authinfo *proxy_authinfo;
} request_t;
typedef struct _task_header_t task_header_t;
@@ -229,14 +261,13 @@
BOOL netconn_connect( netconn_t *, const struct sockaddr *, unsigned int, int )
DECLSPEC_HIDDEN;
BOOL netconn_connected( netconn_t * ) DECLSPEC_HIDDEN;
BOOL netconn_create( netconn_t *, int, int, int ) DECLSPEC_HIDDEN;
-BOOL netconn_get_next_line( netconn_t *, char *, DWORD * ) DECLSPEC_HIDDEN;
BOOL netconn_init( netconn_t * ) DECLSPEC_HIDDEN;
void netconn_unload( void ) DECLSPEC_HIDDEN;
BOOL netconn_query_data_available( netconn_t *, DWORD * ) DECLSPEC_HIDDEN;
BOOL netconn_recv( netconn_t *, void *, size_t, int, int * ) DECLSPEC_HIDDEN;
BOOL netconn_resolve( WCHAR *, INTERNET_PORT, struct sockaddr *, socklen_t *, int )
DECLSPEC_HIDDEN;
BOOL netconn_secure_connect( netconn_t *, WCHAR * ) DECLSPEC_HIDDEN;
-BOOL netconn_send( netconn_t *, const void *, size_t, int, int * ) DECLSPEC_HIDDEN;
+BOOL netconn_send( netconn_t *, const void *, size_t, int * ) DECLSPEC_HIDDEN;
DWORD netconn_set_timeout( netconn_t *, BOOL, int ) DECLSPEC_HIDDEN;
const void *netconn_get_certificate( netconn_t * ) DECLSPEC_HIDDEN;
int netconn_get_cipher_strength( netconn_t * ) DECLSPEC_HIDDEN;
@@ -245,7 +276,8 @@
BOOL add_cookie_headers( request_t * ) DECLSPEC_HIDDEN;
BOOL add_request_headers( request_t *, LPCWSTR, DWORD, DWORD ) DECLSPEC_HIDDEN;
void delete_domain( domain_t * ) DECLSPEC_HIDDEN;
-BOOL set_server_for_hostname( connect_t *connect, LPCWSTR server, INTERNET_PORT port )
DECLSPEC_HIDDEN;
+BOOL set_server_for_hostname( connect_t *, LPCWSTR, INTERNET_PORT ) DECLSPEC_HIDDEN;
+void destroy_authinfo( struct authinfo * ) DECLSPEC_HIDDEN;
extern HRESULT WinHttpRequest_create( IUnknown *, void ** ) DECLSPEC_HIDDEN;
Modified: trunk/reactos/media/doc/README.WINE
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/media/doc/README.WINE?rev=…
==============================================================================
--- trunk/reactos/media/doc/README.WINE [iso-8859-1] (original)
+++ trunk/reactos/media/doc/README.WINE [iso-8859-1] Sat Sep 28 15:23:56 2013
@@ -202,7 +202,7 @@
reactos/dll/win32/windowscodecs # Synced to Wine-1.7.1
reactos/dll/win32/winemp3.acm # Synced to Wine-1.7.1
reactos/dll/win32/wing32 # Out of sync
-reactos/dll/win32/winhttp # Synced to Wine-1.5.26
+reactos/dll/win32/winhttp # Synced to Wine-1.7.1
reactos/dll/win32/wininet # Synced to Wine-1.5.26
reactos/dll/win32/winmm # Forked at Wine-20050628
reactos/dll/win32/winmm/midimap # Forked at Wine-20050628