[WININET]

- Sync wininet to WINE 1.3.4
- Regenerate wininet_ros.diff so that it actually applies against current WINE head

svn path=/trunk/; revision=49081
This commit is contained in:
Cameron Gutman 2010-10-09 20:08:18 +00:00
parent f39c42c8c2
commit c95d5d74b8
7 changed files with 516 additions and 257 deletions

View file

@ -431,7 +431,7 @@ static BOOL set_cookie(LPCWSTR domain, LPCWSTR path, LPCWSTR cookie_name, LPCWST
value = data = heap_strdupW(cookie_data);
if (!data)
{
ERR("could not allocate %zu bytes for the cookie data buffer\n", (strlenW(cookie_data) + 1) * sizeof(WCHAR));
ERR("could not allocate the cookie data buffer\n");
return FALSE;
}
@ -457,7 +457,7 @@ static BOOL set_cookie(LPCWSTR domain, LPCWSTR path, LPCWSTR cookie_name, LPCWST
if (value == NULL)
{
HeapFree(GetProcessHeap(), 0, data);
ERR("could not allocate %zu bytes for the cookie value buffer\n", (ptr - data) * sizeof(WCHAR));
ERR("could not allocate the cookie value buffer\n");
return FALSE;
}
strcpyW(value, data);

View file

@ -181,7 +181,7 @@ struct gzip_stream_t {
BOOL end_of_data;
};
typedef struct _authorizationData
typedef struct _basicAuthorizationData
{
struct list entry;
@ -189,9 +189,24 @@ typedef struct _authorizationData
LPWSTR lpszwRealm;
LPSTR lpszAuthorization;
UINT AuthorizationLen;
} basicAuthorizationData;
typedef struct _authorizationData
{
struct list entry;
LPWSTR host;
LPWSTR scheme;
LPWSTR domain;
UINT domain_len;
LPWSTR user;
UINT user_len;
LPWSTR password;
UINT password_len;
} authorizationData;
static struct list basicAuthorizationCache = LIST_INIT(basicAuthorizationCache);
static struct list authorizationCache = LIST_INIT(authorizationCache);
static CRITICAL_SECTION authcache_cs;
static CRITICAL_SECTION_DEBUG critsect_debug =
@ -572,13 +587,13 @@ static void destroy_authinfo( struct HttpAuthInfo *authinfo )
static UINT retrieve_cached_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR *auth_data)
{
authorizationData *ad;
basicAuthorizationData *ad;
UINT rc = 0;
TRACE("Looking for authorization for %s:%s\n",debugstr_w(host),debugstr_w(realm));
EnterCriticalSection(&authcache_cs);
LIST_FOR_EACH_ENTRY(ad, &basicAuthorizationCache, authorizationData, entry)
LIST_FOR_EACH_ENTRY(ad, &basicAuthorizationCache, basicAuthorizationData, entry)
{
if (!strcmpiW(host,ad->lpszwHost) && !strcmpW(realm,ad->lpszwRealm))
{
@ -596,14 +611,14 @@ static UINT retrieve_cached_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR
static void cache_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR auth_data, UINT auth_data_len)
{
struct list *cursor;
authorizationData* ad = NULL;
basicAuthorizationData* ad = NULL;
TRACE("caching authorization for %s:%s = %s\n",debugstr_w(host),debugstr_w(realm),debugstr_an(auth_data,auth_data_len));
EnterCriticalSection(&authcache_cs);
LIST_FOR_EACH(cursor, &basicAuthorizationCache)
{
authorizationData *check = LIST_ENTRY(cursor,authorizationData,entry);
basicAuthorizationData *check = LIST_ENTRY(cursor,basicAuthorizationData,entry);
if (!strcmpiW(host,check->lpszwHost) && !strcmpW(realm,check->lpszwRealm))
{
ad = check;
@ -621,7 +636,7 @@ static void cache_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR auth_data
}
else
{
ad = HeapAlloc(GetProcessHeap(),0,sizeof(authorizationData));
ad = HeapAlloc(GetProcessHeap(),0,sizeof(basicAuthorizationData));
ad->lpszwHost = heap_strdupW(host);
ad->lpszwRealm = heap_strdupW(realm);
ad->lpszAuthorization = HeapAlloc(GetProcessHeap(),0,auth_data_len);
@ -633,6 +648,95 @@ static void cache_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR auth_data
LeaveCriticalSection(&authcache_cs);
}
static BOOL retrieve_cached_authorization(LPWSTR host, LPWSTR scheme,
SEC_WINNT_AUTH_IDENTITY_W *nt_auth_identity)
{
authorizationData *ad;
TRACE("Looking for authorization for %s:%s\n", debugstr_w(host), debugstr_w(scheme));
EnterCriticalSection(&authcache_cs);
LIST_FOR_EACH_ENTRY(ad, &authorizationCache, authorizationData, entry) {
if(!strcmpiW(host, ad->host) && !strcmpiW(scheme, ad->scheme)) {
TRACE("Authorization found in cache\n");
nt_auth_identity->User = heap_strdupW(ad->user);
nt_auth_identity->Password = heap_strdupW(ad->password);
nt_auth_identity->Domain = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*ad->domain_len);
if(!nt_auth_identity->User || !nt_auth_identity->Password ||
(!nt_auth_identity->Domain && ad->domain_len)) {
HeapFree(GetProcessHeap(), 0, nt_auth_identity->User);
HeapFree(GetProcessHeap(), 0, nt_auth_identity->Password);
HeapFree(GetProcessHeap(), 0, nt_auth_identity->Domain);
break;
}
nt_auth_identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
nt_auth_identity->UserLength = ad->user_len;
nt_auth_identity->PasswordLength = ad->password_len;
memcpy(nt_auth_identity->Domain, ad->domain, sizeof(WCHAR)*ad->domain_len);
nt_auth_identity->DomainLength = ad->domain_len;
LeaveCriticalSection(&authcache_cs);
return TRUE;
}
}
LeaveCriticalSection(&authcache_cs);
return FALSE;
}
static void cache_authorization(LPWSTR host, LPWSTR scheme,
SEC_WINNT_AUTH_IDENTITY_W *nt_auth_identity)
{
authorizationData *ad;
BOOL found = FALSE;
TRACE("Caching authorization for %s:%s\n", debugstr_w(host), debugstr_w(scheme));
EnterCriticalSection(&authcache_cs);
LIST_FOR_EACH_ENTRY(ad, &authorizationCache, authorizationData, entry)
if(!strcmpiW(host, ad->host) && !strcmpiW(scheme, ad->scheme)) {
found = TRUE;
break;
}
if(found) {
HeapFree(GetProcessHeap(), 0, ad->user);
HeapFree(GetProcessHeap(), 0, ad->password);
HeapFree(GetProcessHeap(), 0, ad->domain);
} else {
ad = HeapAlloc(GetProcessHeap(), 0, sizeof(authorizationData));
if(!ad) {
LeaveCriticalSection(&authcache_cs);
return;
}
ad->host = heap_strdupW(host);
ad->scheme = heap_strdupW(scheme);
list_add_head(&authorizationCache, &ad->entry);
}
ad->user = heap_strndupW(nt_auth_identity->User, nt_auth_identity->UserLength);
ad->password = heap_strndupW(nt_auth_identity->Password, nt_auth_identity->PasswordLength);
ad->domain = heap_strndupW(nt_auth_identity->Domain, nt_auth_identity->DomainLength);
ad->user_len = nt_auth_identity->UserLength;
ad->password_len = nt_auth_identity->PasswordLength;
ad->domain_len = nt_auth_identity->DomainLength;
if(!ad->host || !ad->scheme || !ad->user || !ad->password
|| (nt_auth_identity->Domain && !ad->domain)) {
HeapFree(GetProcessHeap(), 0, ad->host);
HeapFree(GetProcessHeap(), 0, ad->scheme);
HeapFree(GetProcessHeap(), 0, ad->user);
HeapFree(GetProcessHeap(), 0, ad->password);
HeapFree(GetProcessHeap(), 0, ad->domain);
list_remove(&ad->entry);
HeapFree(GetProcessHeap(), 0, ad);
}
LeaveCriticalSection(&authcache_cs);
}
static BOOL HTTP_DoAuthorization( http_request_t *lpwhr, LPCWSTR pszAuthValue,
struct HttpAuthInfo **ppAuthInfo,
LPWSTR domain_and_username, LPWSTR password,
@ -707,7 +811,11 @@ static BOOL HTTP_DoAuthorization( http_request_t *lpwhr, LPCWSTR pszAuthValue,
nt_auth_identity.DomainLength = domain ? user - domain - 1 : 0;
nt_auth_identity.Password = password;
nt_auth_identity.PasswordLength = strlenW(nt_auth_identity.Password);
cache_authorization(host, pAuthInfo->scheme, &nt_auth_identity);
}
else if(retrieve_cached_authorization(host, pAuthInfo->scheme, &nt_auth_identity))
pAuthData = &nt_auth_identity;
else
/* use default credentials */
pAuthData = NULL;
@ -717,6 +825,13 @@ static BOOL HTTP_DoAuthorization( http_request_t *lpwhr, LPCWSTR pszAuthValue,
pAuthData, NULL,
NULL, &pAuthInfo->cred,
&exp);
if(pAuthData && !domain_and_username) {
HeapFree(GetProcessHeap(), 0, nt_auth_identity.User);
HeapFree(GetProcessHeap(), 0, nt_auth_identity.Domain);
HeapFree(GetProcessHeap(), 0, nt_auth_identity.Password);
}
if (sec_status == SEC_E_OK)
{
PSecPkgInfoW sec_pkg_info;
@ -1426,6 +1541,20 @@ static DWORD HTTP_ResolveName(http_request_t *lpwhr)
return ERROR_SUCCESS;
}
static BOOL HTTP_GetRequestURL(http_request_t *req, LPWSTR buf)
{
LPHTTPHEADERW host_header;
static const WCHAR formatW[] = {'h','t','t','p',':','/','/','%','s','%','s',0};
host_header = HTTP_GetHeader(req, hostW);
if(!host_header)
return FALSE;
sprintfW(buf, formatW, host_header->lpszValue, req->lpszPath); /* FIXME */
return TRUE;
}
/***********************************************************************
* HTTPREQ_Destroy (internal)
@ -1440,9 +1569,19 @@ static void HTTPREQ_Destroy(object_header_t *hdr)
TRACE("\n");
if(lpwhr->hCacheFile)
if(lpwhr->hCacheFile) {
WCHAR url[INTERNET_MAX_URL_LENGTH];
FILETIME ft;
CloseHandle(lpwhr->hCacheFile);
memset(&ft, 0, sizeof(FILETIME));
if(HTTP_GetRequestURL(lpwhr, url)) {
CommitUrlCacheEntryW(url, lpwhr->lpszCacheFile, ft, ft,
NORMAL_CACHE_ENTRY, NULL, 0, NULL, 0);
}
}
HeapFree(GetProcessHeap(), 0, lpwhr->lpszCacheFile);
DeleteCriticalSection( &lpwhr->read_section );
@ -1493,20 +1632,6 @@ static void HTTPREQ_CloseConnection(object_header_t *hdr)
INTERNET_STATUS_CONNECTION_CLOSED, 0, 0);
}
static BOOL HTTP_GetRequestURL(http_request_t *req, LPWSTR buf)
{
LPHTTPHEADERW host_header;
static const WCHAR formatW[] = {'h','t','t','p',':','/','/','%','s','%','s',0};
host_header = HTTP_GetHeader(req, hostW);
if(!host_header)
return FALSE;
sprintfW(buf, formatW, host_header->lpszValue, req->lpszPath); /* FIXME */
return TRUE;
}
static BOOL HTTP_KeepAlive(http_request_t *lpwhr)
{
WCHAR szVersion[10];
@ -1567,18 +1692,25 @@ static DWORD HTTPREQ_QueryOption(object_header_t *hdr, DWORD option, void *buffe
case INTERNET_OPTION_SECURITY_FLAGS:
{
http_session_t *lpwhs;
lpwhs = req->lpHttpSession;
DWORD flags;
int bits;
if (*size < sizeof(ULONG))
return ERROR_INSUFFICIENT_BUFFER;
*size = sizeof(DWORD);
if (lpwhs->hdr.dwFlags & INTERNET_FLAG_SECURE)
*(DWORD*)buffer = SECURITY_FLAG_SECURE;
flags = 0;
if (req->hdr.dwFlags & INTERNET_FLAG_SECURE)
flags |= SECURITY_FLAG_SECURE;
flags |= req->netConnection.security_flags;
bits = NETCON_GetCipherStrength(&req->netConnection);
if (bits >= 128)
flags |= SECURITY_FLAG_STRENGTH_STRONG;
else if (bits >= 56)
flags |= SECURITY_FLAG_STRENGTH_MEDIUM;
else
*(DWORD*)buffer = 0;
FIXME("Semi-STUB INTERNET_OPTION_SECURITY_FLAGS: %x\n",*(DWORD*)buffer);
flags |= SECURITY_FLAG_STRENGTH_WEAK;
*(DWORD *)buffer = flags;
return ERROR_SUCCESS;
}
@ -1696,60 +1828,34 @@ static DWORD HTTPREQ_QueryOption(object_header_t *hdr, DWORD option, void *buffe
case INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT: {
PCCERT_CONTEXT context;
if(*size < sizeof(INTERNET_CERTIFICATE_INFOW)) {
*size = sizeof(INTERNET_CERTIFICATE_INFOW);
if(*size < sizeof(INTERNET_CERTIFICATE_INFOA)) {
*size = sizeof(INTERNET_CERTIFICATE_INFOA);
return ERROR_INSUFFICIENT_BUFFER;
}
context = (PCCERT_CONTEXT)NETCON_GetCert(&(req->netConnection));
if(context) {
INTERNET_CERTIFICATE_INFOW *info = (INTERNET_CERTIFICATE_INFOW*)buffer;
INTERNET_CERTIFICATE_INFOA *info = (INTERNET_CERTIFICATE_INFOA*)buffer;
DWORD len;
memset(info, 0, sizeof(INTERNET_CERTIFICATE_INFOW));
info->ftExpiry = context->pCertInfo->NotAfter;
info->ftStart = context->pCertInfo->NotBefore;
if(unicode) {
len = CertNameToStrW(context->dwCertEncodingType,
&context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, NULL, 0);
info->lpszSubjectInfo = LocalAlloc(0, len*sizeof(WCHAR));
if(info->lpszSubjectInfo)
CertNameToStrW(context->dwCertEncodingType,
&context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR,
info->lpszSubjectInfo, len);
len = CertNameToStrW(context->dwCertEncodingType,
&context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR, NULL, 0);
info->lpszIssuerInfo = LocalAlloc(0, len*sizeof(WCHAR));
if (info->lpszIssuerInfo)
CertNameToStrW(context->dwCertEncodingType,
&context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR,
info->lpszIssuerInfo, len);
}else {
INTERNET_CERTIFICATE_INFOA *infoA = (INTERNET_CERTIFICATE_INFOA*)info;
len = CertNameToStrA(context->dwCertEncodingType,
&context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, NULL, 0);
infoA->lpszSubjectInfo = LocalAlloc(0, len);
if(infoA->lpszSubjectInfo)
CertNameToStrA(context->dwCertEncodingType,
&context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR,
infoA->lpszSubjectInfo, len);
len = CertNameToStrA(context->dwCertEncodingType,
&context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR, NULL, 0);
infoA->lpszIssuerInfo = LocalAlloc(0, len);
if(infoA->lpszIssuerInfo)
CertNameToStrA(context->dwCertEncodingType,
&context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR,
infoA->lpszIssuerInfo, len);
}
/*
* Contrary to MSDN, these do not appear to be set.
* lpszProtocolName
* lpszSignatureAlgName
* lpszEncryptionAlgName
* dwKeySize
*/
len = CertNameToStrA(context->dwCertEncodingType,
&context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, NULL, 0);
info->lpszSubjectInfo = LocalAlloc(0, len);
if(info->lpszSubjectInfo)
CertNameToStrA(context->dwCertEncodingType,
&context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR,
info->lpszSubjectInfo, len);
len = CertNameToStrA(context->dwCertEncodingType,
&context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR, NULL, 0);
info->lpszIssuerInfo = LocalAlloc(0, len);
if(info->lpszIssuerInfo)
CertNameToStrA(context->dwCertEncodingType,
&context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR,
info->lpszIssuerInfo, len);
info->dwKeySize = NETCON_GetCipherStrength(&req->netConnection);
CertFreeCertificateContext(context);
return ERROR_SUCCESS;
}
@ -1764,6 +1870,17 @@ static DWORD HTTPREQ_SetOption(object_header_t *hdr, DWORD option, void *buffer,
http_request_t *req = (http_request_t*)hdr;
switch(option) {
case INTERNET_OPTION_SECURITY_FLAGS:
{
DWORD flags;
if (!buffer || size != sizeof(DWORD))
return ERROR_INVALID_PARAMETER;
flags = *(DWORD *)buffer;
TRACE("%08x\n", flags);
req->netConnection.security_flags = flags;
return ERROR_SUCCESS;
}
case INTERNET_OPTION_SEND_TIMEOUT:
case INTERNET_OPTION_RECEIVE_TIMEOUT:
TRACE("INTERNET_OPTION_SEND/RECEIVE_TIMEOUT\n");
@ -1970,6 +2087,9 @@ static DWORD read_gzip_data(http_request_t *req, BYTE *buf, int size, BOOL sync,
break;
}
if(req->dwContentRead == req->dwContentLength)
break;
buf_avail = req->dwContentLength == ~0 ? req->read_size : min(req->read_size, req->dwContentLength-req->dwContentRead);
zstream->next_in = req->read_buf+req->read_pos;
@ -2125,7 +2245,18 @@ done:
static DWORD HTTPREQ_ReadFile(object_header_t *hdr, void *buffer, DWORD size, DWORD *read)
{
http_request_t *req = (http_request_t*)hdr;
return HTTPREQ_Read(req, buffer, size, read, TRUE);
DWORD res;
EnterCriticalSection( &req->read_section );
if(hdr->dwError == INTERNET_HANDLE_IN_USE)
hdr->dwError = ERROR_INTERNET_INTERNAL_ERROR;
res = HTTPREQ_Read(req, buffer, size, read, TRUE);
if(res == ERROR_SUCCESS)
res = hdr->dwError;
LeaveCriticalSection( &req->read_section );
return res;
}
static void HTTPREQ_AsyncReadFileExAProc(WORKREQUEST *workRequest)
@ -2152,7 +2283,7 @@ static DWORD HTTPREQ_ReadFileExA(object_header_t *hdr, INTERNET_BUFFERSA *buffer
DWORD flags, DWORD_PTR context)
{
http_request_t *req = (http_request_t*)hdr;
DWORD res;
DWORD res, size, read, error = ERROR_SUCCESS;
if (flags & ~(IRF_ASYNC|IRF_NO_WAIT))
FIXME("these dwFlags aren't implemented: 0x%x\n", flags & ~(IRF_ASYNC|IRF_NO_WAIT));
@ -2162,7 +2293,7 @@ static DWORD HTTPREQ_ReadFileExA(object_header_t *hdr, INTERNET_BUFFERSA *buffer
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
if ((hdr->dwFlags & INTERNET_FLAG_ASYNC) && !get_avail_data(req))
if (hdr->dwFlags & INTERNET_FLAG_ASYNC)
{
WORKREQUEST workRequest;
@ -2172,6 +2303,7 @@ static DWORD HTTPREQ_ReadFileExA(object_header_t *hdr, INTERNET_BUFFERSA *buffer
{
res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength,
&buffers->dwBufferLength, FALSE);
size = buffers->dwBufferLength;
LeaveCriticalSection( &req->read_section );
goto done;
}
@ -2187,17 +2319,52 @@ static DWORD HTTPREQ_ReadFileExA(object_header_t *hdr, INTERNET_BUFFERSA *buffer
return ERROR_IO_PENDING;
}
res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength, &buffers->dwBufferLength,
!(flags & IRF_NO_WAIT));
read = 0;
size = buffers->dwBufferLength;
EnterCriticalSection( &req->read_section );
if(hdr->dwError == ERROR_SUCCESS)
hdr->dwError = INTERNET_HANDLE_IN_USE;
else if(hdr->dwError == INTERNET_HANDLE_IN_USE)
hdr->dwError = ERROR_INTERNET_INTERNAL_ERROR;
while(1) {
res = HTTPREQ_Read(req, (char*)buffers->lpvBuffer+read, size-read,
&buffers->dwBufferLength, !(flags & IRF_NO_WAIT));
if(res == ERROR_SUCCESS)
read += buffers->dwBufferLength;
else
break;
if(!req->read_chunked || read==size || req->dwContentLength!=req->dwContentRead
|| !req->dwContentLength || (req->gzip_stream && req->gzip_stream->end_of_data))
break;
LeaveCriticalSection( &req->read_section );
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
&buffers->dwBufferLength, sizeof(buffers->dwBufferLength));
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext,
INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
EnterCriticalSection( &req->read_section );
}
if(hdr->dwError == INTERNET_HANDLE_IN_USE)
hdr->dwError = ERROR_SUCCESS;
else
error = hdr->dwError;
LeaveCriticalSection( &req->read_section );
size = buffers->dwBufferLength;
buffers->dwBufferLength = read;
done:
if (res == ERROR_SUCCESS) {
DWORD size = buffers->dwBufferLength;
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
&size, sizeof(size));
}
return res;
return res==ERROR_SUCCESS ? error : res;
}
static void HTTPREQ_AsyncReadFileExWProc(WORKREQUEST *workRequest)
@ -2225,7 +2392,7 @@ static DWORD HTTPREQ_ReadFileExW(object_header_t *hdr, INTERNET_BUFFERSW *buffer
{
http_request_t *req = (http_request_t*)hdr;
DWORD res;
DWORD res, size, read, error = ERROR_SUCCESS;
if (flags & ~(IRF_ASYNC|IRF_NO_WAIT))
FIXME("these dwFlags aren't implemented: 0x%x\n", flags & ~(IRF_ASYNC|IRF_NO_WAIT));
@ -2245,6 +2412,7 @@ static DWORD HTTPREQ_ReadFileExW(object_header_t *hdr, INTERNET_BUFFERSW *buffer
{
res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength,
&buffers->dwBufferLength, FALSE);
size = buffers->dwBufferLength;
LeaveCriticalSection( &req->read_section );
goto done;
}
@ -2260,17 +2428,52 @@ static DWORD HTTPREQ_ReadFileExW(object_header_t *hdr, INTERNET_BUFFERSW *buffer
return ERROR_IO_PENDING;
}
res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength, &buffers->dwBufferLength,
!(flags & IRF_NO_WAIT));
read = 0;
size = buffers->dwBufferLength;
EnterCriticalSection( &req->read_section );
if(hdr->dwError == ERROR_SUCCESS)
hdr->dwError = INTERNET_HANDLE_IN_USE;
else if(hdr->dwError == INTERNET_HANDLE_IN_USE)
hdr->dwError = ERROR_INTERNET_INTERNAL_ERROR;
while(1) {
res = HTTPREQ_Read(req, (char*)buffers->lpvBuffer+read, size-read,
&buffers->dwBufferLength, !(flags & IRF_NO_WAIT));
if(res == ERROR_SUCCESS)
read += buffers->dwBufferLength;
else
break;
if(!req->read_chunked || read==size || req->dwContentLength!=req->dwContentRead
|| !req->dwContentLength || (req->gzip_stream && req->gzip_stream->end_of_data))
break;
LeaveCriticalSection( &req->read_section );
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
&buffers->dwBufferLength, sizeof(buffers->dwBufferLength));
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext,
INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
EnterCriticalSection( &req->read_section );
}
if(hdr->dwError == INTERNET_HANDLE_IN_USE)
hdr->dwError = ERROR_SUCCESS;
else
error = hdr->dwError;
LeaveCriticalSection( &req->read_section );
size = buffers->dwBufferLength;
buffers->dwBufferLength = read;
done:
if (res == ERROR_SUCCESS) {
DWORD size = buffers->dwBufferLength;
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
&size, sizeof(size));
}
return res;
return res==ERROR_SUCCESS ? error : res;
}
static DWORD HTTPREQ_WriteFile(object_header_t *hdr, const void *buffer, DWORD size, DWORD *written)
@ -3456,6 +3659,7 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *lpwhr, LPCWSTR lpszHeaders,
do
{
DWORD len;
BOOL reusing_connection;
char *ascii_req;
loop_next = FALSE;
@ -3506,6 +3710,11 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *lpwhr, LPCWSTR lpszHeaders,
TRACE("Request header -> %s\n", debugstr_w(requestString) );
/* Send the request and store the results */
if(NETCON_connected(&lpwhr->netConnection))
reusing_connection = TRUE;
else
reusing_connection = FALSE;
if ((res = HTTP_OpenConnection(lpwhr)) != ERROR_SUCCESS)
goto lend;
@ -3547,6 +3756,13 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *lpwhr, LPCWSTR lpszHeaders,
goto lend;
responseLen = HTTP_GetResponseHeaders(lpwhr, TRUE);
/* FIXME: We should know that connection is closed before sending
* headers. Otherwise wrong callbacks are executed */
if(!responseLen && reusing_connection) {
TRACE("Connection closed by server, reconnecting\n");
loop_next = TRUE;
continue;
}
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen,
@ -3565,7 +3781,9 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *lpwhr, LPCWSTR lpszHeaders,
{
WCHAR *new_url, szNewLocation[INTERNET_MAX_URL_LENGTH];
dwBufferSize=sizeof(szNewLocation);
if ((dwStatusCode==HTTP_STATUS_REDIRECT || dwStatusCode==HTTP_STATUS_MOVED) &&
if ((dwStatusCode == HTTP_STATUS_REDIRECT ||
dwStatusCode == HTTP_STATUS_MOVED ||
dwStatusCode == HTTP_STATUS_REDIRECT_METHOD) &&
HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_LOCATION,szNewLocation,&dwBufferSize,NULL) == ERROR_SUCCESS)
{
if (strcmpW(lpwhr->lpszVerb, szGET) && strcmpW(lpwhr->lpszVerb, szHEAD))
@ -3610,6 +3828,12 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *lpwhr, LPCWSTR lpszHeaders,
break;
}
}
if(!loop_next) {
TRACE("Cleaning wrong authorization data\n");
destroy_authinfo(lpwhr->pAuthInfo);
lpwhr->pAuthInfo = NULL;
}
}
if (dwStatusCode == HTTP_STATUS_PROXY_AUTH_REQ)
{
@ -3626,6 +3850,12 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *lpwhr, LPCWSTR lpszHeaders,
break;
}
}
if(!loop_next) {
TRACE("Cleaning wrong proxy authorization data\n");
destroy_authinfo(lpwhr->pProxyAuthInfo);
lpwhr->pProxyAuthInfo = NULL;
}
}
}
}
@ -3674,7 +3904,7 @@ lend:
HTTP_ReceiveRequestData(lpwhr, TRUE);
else
{
iar.dwResult = 0;
iar.dwResult = (res==ERROR_SUCCESS ? (DWORD_PTR)lpwhr->hdr.hInternet : 0);
iar.dwError = res;
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
@ -3758,7 +3988,7 @@ static DWORD HTTP_HttpEndRequestW(http_request_t *lpwhr, DWORD dwFlags, DWORD_PT
}
}
iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet;
iar.dwResult = (res==ERROR_SUCCESS ? (DWORD_PTR)lpwhr->hdr.hInternet : 0);
iar.dwError = res;
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
@ -4459,9 +4689,6 @@ static INT HTTP_GetResponseHeaders(http_request_t *lpwhr, BOOL clear)
TRACE("-->\n");
/* clear old response headers (eg. from a redirect response) */
if (clear) HTTP_clear_response_headers( lpwhr );
if (!NETCON_connected(&lpwhr->netConnection))
goto lend;
@ -4473,6 +4700,13 @@ static INT HTTP_GetResponseHeaders(http_request_t *lpwhr, BOOL clear)
buflen = MAX_REPLY_LEN;
if (!read_line(lpwhr, bufferA, &buflen))
goto lend;
/* clear old response headers (eg. from a redirect response) */
if (clear) {
HTTP_clear_response_headers( lpwhr );
clear = FALSE;
}
rc += buflen;
MultiByteToWideChar( CP_ACP, 0, bufferA, buflen, buffer, MAX_REPLY_LEN );
/* check is this a status code line? */

View file

@ -3569,8 +3569,8 @@ LPSTR INTERNET_GetResponseBuffer(void)
LPSTR INTERNET_GetNextLine(INT nSocket, LPDWORD dwLen)
{
struct timeval tv;
fd_set infd;
struct timeval tv;
BOOL bSuccess = FALSE;
INT nRecv = 0;
LPSTR lpszBuffer = INTERNET_GetResponseBuffer();
@ -3578,13 +3578,13 @@ LPSTR INTERNET_GetNextLine(INT nSocket, LPDWORD dwLen)
TRACE("\n");
FD_ZERO(&infd);
FD_SET(nSocket, &infd);
tv.tv_sec=RESPONSE_TIMEOUT;
tv.tv_usec=0;
FD_SET(nSocket,&infd);
tv.tv_sec = RESPONSE_TIMEOUT;
tv.tv_usec = 0;
while (nRecv < MAX_REPLY_LEN)
{
if (select(nSocket+1,&infd,NULL,NULL,&tv) > 0)
if (select(0, &infd, NULL, NULL, &tv) > 0)
{
if (recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0)
{

View file

@ -53,6 +53,7 @@ typedef struct
BOOL useSSL;
int socketFD;
void *ssl_s;
DWORD security_flags;
} WININET_NETCONNECTION;
static inline LPWSTR heap_strdupW(LPCWSTR str)
@ -71,6 +72,27 @@ static inline LPWSTR heap_strdupW(LPCWSTR str)
return ret;
}
static inline LPWSTR heap_strndupW(LPCWSTR str, UINT max_len)
{
LPWSTR ret;
UINT len;
if(!str)
return NULL;
for(len=0; len<max_len; len++)
if(str[len] == '\0')
break;
ret = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(len+1));
if(ret) {
memcpy(ret, str, sizeof(WCHAR)*len);
ret[len] = '\0';
}
return ret;
}
static inline WCHAR *heap_strdupAtoW(const char *str)
{
LPWSTR ret = NULL;
@ -148,6 +170,8 @@ typedef struct {
DWORD (*FindNextFileW)(object_header_t*,void*);
} object_vtbl_t;
#define INTERNET_HANDLE_IN_USE 1
struct _object_header_t
{
WH_TYPE htype;
@ -436,6 +460,7 @@ DWORD NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int
int *recvd /* out */);
BOOL NETCON_query_data_available(WININET_NETCONNECTION *connection, DWORD *available);
LPCVOID NETCON_GetCert(WININET_NETCONNECTION *connection);
int NETCON_GetCipherStrength(WININET_NETCONNECTION *connection);
DWORD NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value);
#define sock_get_error(x) WSAGetLastError()

View file

@ -60,6 +60,7 @@
#endif
#ifdef HAVE_OPENSSL_SSL_H
# include <openssl/ssl.h>
# include <openssl/opensslv.h>
#undef FAR
#undef DSA
#endif
@ -113,10 +114,15 @@ static CRITICAL_SECTION init_ssl_cs = { &init_ssl_cs_debug, -1, 0, 0, 0, 0 };
static void *OpenSSL_ssl_handle;
static void *OpenSSL_crypto_handle;
#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER> 0x1000000)
static const SSL_METHOD *meth;
#else
static SSL_METHOD *meth;
#endif
static SSL_CTX *ctx;
static int hostname_idx;
static int error_idx;
static int conn_idx;
#define MAKE_FUNCPTR(f) static typeof(f) * p##f
@ -139,12 +145,13 @@ MAKE_FUNCPTR(SSL_get_ex_new_index);
MAKE_FUNCPTR(SSL_get_ex_data);
MAKE_FUNCPTR(SSL_set_ex_data);
MAKE_FUNCPTR(SSL_get_ex_data_X509_STORE_CTX_idx);
MAKE_FUNCPTR(SSL_get_verify_result);
MAKE_FUNCPTR(SSL_get_peer_certificate);
MAKE_FUNCPTR(SSL_CTX_get_timeout);
MAKE_FUNCPTR(SSL_CTX_set_timeout);
MAKE_FUNCPTR(SSL_CTX_set_default_verify_paths);
MAKE_FUNCPTR(SSL_CTX_set_verify);
MAKE_FUNCPTR(SSL_get_current_cipher);
MAKE_FUNCPTR(SSL_CIPHER_get_bits);
MAKE_FUNCPTR(X509_STORE_CTX_get_ex_data);
/* OpenSSL's libcrypto functions that we use */
@ -214,7 +221,7 @@ static PCCERT_CONTEXT X509_to_cert_context(X509 *cert)
}
static DWORD netconn_verify_cert(PCCERT_CONTEXT cert, HCERTSTORE store,
WCHAR *server)
WCHAR *server, DWORD security_flags)
{
BOOL ret;
CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } };
@ -231,38 +238,58 @@ static DWORD netconn_verify_cert(PCCERT_CONTEXT cert, HCERTSTORE store,
{
if (chain->TrustStatus.dwErrorStatus)
{
static const DWORD supportedErrors =
CERT_TRUST_IS_NOT_TIME_VALID |
CERT_TRUST_IS_UNTRUSTED_ROOT |
CERT_TRUST_IS_OFFLINE_REVOCATION |
CERT_TRUST_REVOCATION_STATUS_UNKNOWN |
CERT_TRUST_IS_REVOKED |
CERT_TRUST_IS_NOT_VALID_FOR_USAGE;
if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_NOT_TIME_VALID)
err = ERROR_INTERNET_SEC_CERT_DATE_INVALID;
else if (chain->TrustStatus.dwErrorStatus &
CERT_TRUST_IS_UNTRUSTED_ROOT)
CERT_TRUST_IS_UNTRUSTED_ROOT &&
!(security_flags & SECURITY_FLAG_IGNORE_UNKNOWN_CA))
err = ERROR_INTERNET_INVALID_CA;
else if ((chain->TrustStatus.dwErrorStatus &
else if (!(security_flags & SECURITY_FLAG_IGNORE_REVOCATION) &&
((chain->TrustStatus.dwErrorStatus &
CERT_TRUST_IS_OFFLINE_REVOCATION) ||
(chain->TrustStatus.dwErrorStatus &
CERT_TRUST_REVOCATION_STATUS_UNKNOWN))
(chain->TrustStatus.dwErrorStatus &
CERT_TRUST_REVOCATION_STATUS_UNKNOWN)))
err = ERROR_INTERNET_SEC_CERT_NO_REV;
else if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_REVOKED)
else if (!(security_flags & SECURITY_FLAG_IGNORE_REVOCATION) &&
(chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_REVOKED))
err = ERROR_INTERNET_SEC_CERT_REVOKED;
else if (chain->TrustStatus.dwErrorStatus &
CERT_TRUST_IS_NOT_VALID_FOR_USAGE)
else if (!(security_flags & SECURITY_FLAG_IGNORE_WRONG_USAGE) &&
(chain->TrustStatus.dwErrorStatus &
CERT_TRUST_IS_NOT_VALID_FOR_USAGE))
err = ERROR_INTERNET_SEC_INVALID_CERT;
else
else if (chain->TrustStatus.dwErrorStatus & ~supportedErrors)
err = ERROR_INTERNET_SEC_INVALID_CERT;
}
else
if (!err)
{
CERT_CHAIN_POLICY_PARA policyPara;
SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslExtraPolicyPara;
CERT_CHAIN_POLICY_STATUS policyStatus;
CERT_CHAIN_CONTEXT chainCopy;
/* Clear chain->TrustStatus.dwErrorStatus so
* CertVerifyCertificateChainPolicy will verify additional checks
* rather than stopping with an existing, ignored error.
*/
memcpy(&chainCopy, chain, sizeof(chainCopy));
chainCopy.TrustStatus.dwErrorStatus = 0;
sslExtraPolicyPara.u.cbSize = sizeof(sslExtraPolicyPara);
sslExtraPolicyPara.dwAuthType = AUTHTYPE_SERVER;
sslExtraPolicyPara.pwszServerName = server;
sslExtraPolicyPara.fdwChecks = security_flags;
policyPara.cbSize = sizeof(policyPara);
policyPara.dwFlags = 0;
policyPara.pvExtraPolicyPara = &sslExtraPolicyPara;
ret = CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL,
chain, &policyPara, &policyStatus);
&chainCopy, &policyPara, &policyStatus);
/* Any error in the policy status indicates that the
* policy couldn't be verified.
*/
@ -285,55 +312,52 @@ static int netconn_secure_verify(int preverify_ok, X509_STORE_CTX *ctx)
SSL *ssl;
WCHAR *server;
BOOL ret = FALSE;
HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
CERT_STORE_CREATE_NEW_FLAG, NULL);
WININET_NETCONNECTION *conn;
ssl = pX509_STORE_CTX_get_ex_data(ctx,
pSSL_get_ex_data_X509_STORE_CTX_idx());
server = pSSL_get_ex_data(ssl, hostname_idx);
if (preverify_ok)
conn = pSSL_get_ex_data(ssl, conn_idx);
if (store)
{
HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
CERT_STORE_CREATE_NEW_FLAG, NULL);
X509 *cert;
int i;
PCCERT_CONTEXT endCert = NULL;
if (store)
ret = TRUE;
for (i = 0; ret && i < psk_num((struct stack_st *)ctx->chain); i++)
{
X509 *cert;
int i;
PCCERT_CONTEXT endCert = NULL;
PCCERT_CONTEXT context;
ret = TRUE;
for (i = 0; ret && i < psk_num((struct stack_st *)ctx->chain); i++)
cert = (X509 *)psk_value((struct stack_st *)ctx->chain, i);
if ((context = X509_to_cert_context(cert)))
{
PCCERT_CONTEXT context;
cert = (X509 *)psk_value((struct stack_st *)ctx->chain, i);
if ((context = X509_to_cert_context(cert)))
{
if (i == 0)
ret = CertAddCertificateContextToStore(store, context,
CERT_STORE_ADD_ALWAYS, &endCert);
else
ret = CertAddCertificateContextToStore(store, context,
CERT_STORE_ADD_ALWAYS, NULL);
CertFreeCertificateContext(context);
}
if (i == 0)
ret = CertAddCertificateContextToStore(store, context,
CERT_STORE_ADD_ALWAYS, &endCert);
else
ret = CertAddCertificateContextToStore(store, context,
CERT_STORE_ADD_ALWAYS, NULL);
CertFreeCertificateContext(context);
}
if (!endCert) ret = FALSE;
if (ret)
{
DWORD_PTR err = netconn_verify_cert(endCert, store, server);
if (err)
{
pSSL_set_ex_data(ssl, error_idx, (void *)err);
ret = FALSE;
}
}
CertFreeCertificateContext(endCert);
CertCloseStore(store, 0);
}
} else
pSSL_set_ex_data(ssl, error_idx, (void *)ERROR_INTERNET_SEC_CERT_ERRORS);
if (!endCert) ret = FALSE;
if (ret)
{
DWORD_PTR err = netconn_verify_cert(endCert, store, server,
conn->security_flags);
if (err)
{
pSSL_set_ex_data(ssl, error_idx, (void *)err);
ret = FALSE;
}
}
CertFreeCertificateContext(endCert);
CertCloseStore(store, 0);
}
return ret;
}
@ -400,12 +424,13 @@ DWORD NETCON_init(WININET_NETCONNECTION *connection, BOOL useSSL)
DYNSSL(SSL_get_ex_data);
DYNSSL(SSL_set_ex_data);
DYNSSL(SSL_get_ex_data_X509_STORE_CTX_idx);
DYNSSL(SSL_get_verify_result);
DYNSSL(SSL_get_peer_certificate);
DYNSSL(SSL_CTX_get_timeout);
DYNSSL(SSL_CTX_set_timeout);
DYNSSL(SSL_CTX_set_default_verify_paths);
DYNSSL(SSL_CTX_set_verify);
DYNSSL(SSL_get_current_cipher);
DYNSSL(SSL_CIPHER_get_bits);
DYNSSL(X509_STORE_CTX_get_ex_data);
#undef DYNSSL
@ -460,6 +485,15 @@ DWORD NETCON_init(WININET_NETCONNECTION *connection, BOOL useSSL)
LeaveCriticalSection(&init_ssl_cs);
return ERROR_OUTOFMEMORY;
}
conn_idx = pSSL_get_ex_new_index(0, (void *)"netconn index",
NULL, NULL, NULL);
if (conn_idx == -1)
{
ERR("SSL_get_ex_new_index failed; %s\n",
pERR_error_string(pERR_get_error(), 0));
LeaveCriticalSection(&init_ssl_cs);
return ERROR_OUTOFMEMORY;
}
pSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, netconn_secure_verify);
pCRYPTO_set_id_callback(ssl_thread_id);
@ -637,10 +671,8 @@ DWORD NETCON_close(WININET_NETCONNECTION *connection)
DWORD NETCON_secure_connect(WININET_NETCONNECTION *connection, LPWSTR hostname)
{
DWORD res = ERROR_NOT_SUPPORTED;
#ifdef SONAME_LIBSSL
long verify_res;
X509 *cert;
#ifdef SONAME_LIBSSL
/* can't connect if we are already connected */
if (connection->useSSL)
{
@ -665,6 +697,20 @@ DWORD NETCON_secure_connect(WININET_NETCONNECTION *connection, LPWSTR hostname)
goto fail;
}
if (!pSSL_set_ex_data(connection->ssl_s, hostname_idx, hostname))
{
ERR("SSL_set_ex_data failed: %s\n",
pERR_error_string(pERR_get_error(), 0));
res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
goto fail;
}
if (!pSSL_set_ex_data(connection->ssl_s, conn_idx, connection))
{
ERR("SSL_set_ex_data failed: %s\n",
pERR_error_string(pERR_get_error(), 0));
res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
goto fail;
}
if (pSSL_connect(connection->ssl_s) <= 0)
{
res = (DWORD_PTR)pSSL_get_ex_data(connection->ssl_s, error_idx);
@ -673,22 +719,6 @@ DWORD NETCON_secure_connect(WININET_NETCONNECTION *connection, LPWSTR hostname)
ERR("SSL_connect failed: %d\n", res);
goto fail;
}
pSSL_set_ex_data(connection->ssl_s, hostname_idx, hostname);
cert = pSSL_get_peer_certificate(connection->ssl_s);
if (!cert)
{
ERR("no certificate for server %s\n", debugstr_w(hostname));
/* FIXME: is this the best error? */
res = ERROR_INTERNET_INVALID_CA;
goto fail;
}
verify_res = pSSL_get_verify_result(connection->ssl_s);
if (verify_res != X509_V_OK)
{
ERR("couldn't verify the security of the connection, %ld\n", verify_res);
/* FIXME: we should set an error and return, but we only warn at
* the moment */
}
connection->useSSL = TRUE;
return ERROR_SUCCESS;
@ -772,6 +802,8 @@ DWORD NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int
if (!connection->useSSL)
{
*recvd = recv(connection->socketFD, buf, len, flags);
if(!*recvd)
NETCON_close(connection);
return *recvd == -1 ? sock_get_error(errno) : ERROR_SUCCESS;
}
else
@ -781,8 +813,10 @@ DWORD NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int
/* Check if EOF was received */
if(!*recvd && (pSSL_get_error(connection->ssl_s, *recvd)==SSL_ERROR_ZERO_RETURN
|| pSSL_get_error(connection->ssl_s, *recvd)==SSL_ERROR_SYSCALL))
|| pSSL_get_error(connection->ssl_s, *recvd)==SSL_ERROR_SYSCALL)) {
NETCON_close(connection);
return ERROR_SUCCESS;
}
return *recvd > 0 ? ERROR_SUCCESS : ERROR_INTERNET_CONNECTION_ABORTED;
#else
@ -840,6 +874,24 @@ LPCVOID NETCON_GetCert(WININET_NETCONNECTION *connection)
#endif
}
int NETCON_GetCipherStrength(WININET_NETCONNECTION *connection)
{
#ifdef SONAME_LIBSSL
SSL_CIPHER *cipher;
int bits = 0;
if (!connection->useSSL)
return 0;
cipher = pSSL_get_current_cipher(connection->ssl_s);
if (!cipher)
return 0;
pSSL_CIPHER_get_bits(cipher, &bits);
return bits;
#else
return 0;
#endif
}
DWORD NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value)
{
int result;

View file

@ -2184,14 +2184,17 @@ BOOL WINAPI CreateUrlCacheEntryA(
)
{
WCHAR *url_name;
WCHAR *file_extension;
WCHAR *file_extension = NULL;
WCHAR file_name[MAX_PATH];
BOOL bSuccess = FALSE;
DWORD dwError = 0;
TRACE("(%s %d %s %p %d)\n", debugstr_a(lpszUrlName), dwExpectedFileSize,
debugstr_a(lpszFileExtension), lpszFileName, dwReserved);
if (lpszUrlName && (url_name = heap_strdupAtoW(lpszUrlName)))
{
if (lpszFileExtension && (file_extension = heap_strdupAtoW(lpszFileExtension)))
if (!lpszFileExtension || (file_extension = heap_strdupAtoW(lpszFileExtension)))
{
if (CreateUrlCacheEntryW(url_name, dwExpectedFileSize, file_extension, file_name, dwReserved))
{
@ -2268,6 +2271,12 @@ BOOL WINAPI CreateUrlCacheEntryW(
if (((lpszUrlEnd - lpszUrlName) > 1) && (*(lpszUrlEnd - 1) == '/' || *(lpszUrlEnd - 1) == '\\'))
lpszUrlEnd--;
lpszUrlPart = memchrW(lpszUrlName, '?', lpszUrlEnd - lpszUrlName);
if (!lpszUrlPart)
lpszUrlPart = memchrW(lpszUrlName, '#', lpszUrlEnd - lpszUrlName);
if (lpszUrlPart)
lpszUrlEnd = lpszUrlPart;
for (lpszUrlPart = lpszUrlEnd;
(lpszUrlPart >= lpszUrlName);
lpszUrlPart--)
@ -2278,10 +2287,6 @@ BOOL WINAPI CreateUrlCacheEntryW(
lpszUrlPart++;
break;
}
else if(*lpszUrlPart == '?' || *lpszUrlPart == '#')
{
lpszUrlEnd = lpszUrlPart;
}
}
if (!lstrcmpW(lpszUrlPart, szWWW))
{
@ -2327,7 +2332,13 @@ BOOL WINAPI CreateUrlCacheEntryW(
CacheDir = (BYTE)(rand() % pHeader->DirectoryCount);
lBufferSize = MAX_PATH * sizeof(WCHAR);
URLCache_LocalFileNameToPathW(pContainer, pHeader, szFile, CacheDir, lpszFileName, &lBufferSize);
if (!URLCache_LocalFileNameToPathW(pContainer, pHeader, szFile, CacheDir, lpszFileName, &lBufferSize))
{
WARN("Failed to get full path for filename %s, needed %u bytes.\n",
debugstr_a(szFile), lBufferSize);
URLCacheContainer_UnlockIndex(pContainer, pHeader);
return FALSE;
}
URLCacheContainer_UnlockIndex(pContainer, pHeader);

View file

@ -1,7 +1,18 @@
--- D:/Wine-CVS/wine/dlls/wininet/http.c Wed May 28 14:33:28 2008
+++ D:/ReactOS-Trunk/reactos/dll/win32/wininet/http.c Sun Jun 15 18:16:06 2008
@@ -61,6 +61,8 @@
#include "wine/debug.h"
--- wine-1.3.4/dlls/wininet/internet.h 2010-10-01 14:46:44.000000000 -0400
+++ dll/win32/wininet/internet.h 2010-10-09 15:34:13.000000000 -0400
@@ -462,7 +462,7 @@
LPCVOID NETCON_GetCert(WININET_NETCONNECTION *connection);
int NETCON_GetCipherStrength(WININET_NETCONNECTION *connection);
DWORD NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value);
-int sock_get_error(int);
+#define sock_get_error(x) WSAGetLastError()
extern void URLCacheContainers_CreateDefaults(void);
extern void URLCacheContainers_DeleteAll(void);
--- wine-1.3.4/dlls/wininet/http.c 2010-10-01 14:46:44.000000000 -0400
+++ dll/win32/wininet/http.c 2010-10-09 15:28:29.000000000 -0400
@@ -69,6 +69,8 @@
#include "wine/exception.h"
#include "wine/unicode.h"
+#include "inet_ntop.c"
@ -9,95 +20,21 @@
WINE_DEFAULT_DEBUG_CHANNEL(wininet);
static const WCHAR g_szHttp1_0[] = {'H','T','T','P','/','1','.','0',0};
--- D:/Wine-CVS/wine/dlls/wininet/internet.c Wed May 28 14:33:28 2008
+++ D:/ReactOS-Trunk/reactos/dll/win32/wininet/internet.c Fri May 30 18:04:29 2008
@@ -3101,19 +3101,22 @@
LPSTR INTERNET_GetNextLine(INT nSocket, LPDWORD dwLen)
{
- struct pollfd pfd;
+ struct timeval tv;
+ fd_set infd;
BOOL bSuccess = FALSE;
INT nRecv = 0;
LPSTR lpszBuffer = INTERNET_GetResponseBuffer();
TRACE("\n");
- pfd.fd = nSocket;
- pfd.events = POLLIN;
+ FD_ZERO(&infd);
+ FD_SET(nSocket, &infd);
+ tv.tv_sec=RESPONSE_TIMEOUT;
+ tv.tv_usec=0;
while (nRecv < MAX_REPLY_LEN)
{
- if (poll(&pfd,1, RESPONSE_TIMEOUT * 1000) > 0)
+ if (select(nSocket+1,&infd,NULL,NULL,&tv) > 0)
{
if (recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0)
{
--- D:/Wine-CVS/wine/dlls/wininet/internet.h Fri Mar 28 20:13:36 2008
+++ D:/ReactOS-Trunk/reactos/dll/win32/wininet/internet.h Thu May 29 19:01:31 2008
@@ -23,6 +23,9 @@
#ifndef _WINE_INTERNET_H_
#define _WINE_INTERNET_H_
+/* ReactOS-specific definitions */
+#define CP_UNIXCP CP_THREAD_ACP
+
#ifndef __WINE_CONFIG_H
# error You must include config.h to use this header
#endif
--- D:/Wine-CVS/wine/dlls/wininet/netconnection.c Sat May 17 12:09:49 2008
+++ D:/ReactOS-Trunk/reactos/dll/win32/wininet/netconnection.c Sat May 31 12:01:55 2008
@@ -64,7 +64,7 @@
#include "winsock2.h"
#define RESPONSE_TIMEOUT 30 /* FROM internet.c */
-
+#define sock_get_error(x) WSAGetLastError()
WINE_DEFAULT_DEBUG_CHANNEL(wininet);
@@ -206,6 +206,7 @@
--- wine-1.3.4/dlls/wininet/netconnection.c 2010-10-01 14:46:44.000000000 -0400
+++ dll/win32/wininet/netconnection.c 2010-10-09 15:33:53.000000000 -0400
@@ -547,6 +547,7 @@
return TRUE;
}
+#if 0
/* translate a unix error code into a winsock one */
static int sock_get_error( int err )
int sock_get_error( int err )
{
@@ -272,6 +273,7 @@
@@ -613,6 +614,7 @@
#endif
return err;
}
+#endif
/******************************************************************************
* NETCON_create
@@ -616,16 +618,19 @@
if (!connection->useSSL)
{
- struct pollfd pfd;
+ struct timeval tv;
+ fd_set infd;
BOOL bSuccess = FALSE;
DWORD nRecv = 0;
- pfd.fd = connection->socketFD;
- pfd.events = POLLIN;
+ FD_ZERO(&infd);
+ FD_SET(connection->socketFD, &infd);
+ tv.tv_sec=RESPONSE_TIMEOUT;
+ tv.tv_usec=0;
while (nRecv < *dwBuffer)
{
- if (poll(&pfd,1, RESPONSE_TIMEOUT * 1000) > 0)
+ if (select(connection->socketFD+1,&infd,NULL,NULL,&tv) > 0)
{
if (recv(connection->socketFD, &lpszBuffer[nRecv], 1, 0) <= 0)
{
* NETCON_create