[WININET]

* Sync with Wine 1.5.26.
* Update wininet_ros.diff.
[PSDK]
* Update wininet.h and winineti.h.

svn path=/trunk/; revision=59061
This commit is contained in:
Amine Khaldi 2013-05-20 21:42:26 +00:00
parent e73afacf0f
commit 7f2d1fc323
14 changed files with 3648 additions and 2652 deletions

View file

@ -28,9 +28,10 @@
//#include "wine/port.h"
#include <stdarg.h>
//#include <stdio.h>
#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
#include <assert.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
@ -53,8 +54,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(wininet);
/* FIXME
* Cookies are currently memory only.
* Cookies are NOT THREAD SAFE
* Cookies could use A LOT OF MEMORY. We need some kind of memory management here!
*/
@ -69,7 +68,9 @@ struct _cookie
LPWSTR lpCookieName;
LPWSTR lpCookieData;
DWORD flags;
FILETIME expiry;
FILETIME create;
};
struct _cookie_domain
@ -81,27 +82,300 @@ struct _cookie_domain
struct list cookie_list;
};
static CRITICAL_SECTION cookie_cs;
static CRITICAL_SECTION_DEBUG cookie_cs_debug =
{
0, 0, &cookie_cs,
{ &cookie_cs_debug.ProcessLocksList, &cookie_cs_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": cookie_cs") }
};
static CRITICAL_SECTION cookie_cs = { &cookie_cs_debug, -1, 0, 0, 0, 0 };
static struct list domain_list = LIST_INIT(domain_list);
static cookie *COOKIE_addCookie(cookie_domain *domain, LPCWSTR name, LPCWSTR data, FILETIME expiry);
static cookie *COOKIE_addCookie(cookie_domain *domain, LPCWSTR name, LPCWSTR data,
FILETIME expiry, FILETIME create, DWORD flags);
static cookie *COOKIE_findCookie(cookie_domain *domain, LPCWSTR lpszCookieName);
static void COOKIE_deleteCookie(cookie *deadCookie, BOOL deleteDomain);
static cookie_domain *COOKIE_addDomain(LPCWSTR domain, LPCWSTR path);
static void COOKIE_deleteDomain(cookie_domain *deadDomain);
static BOOL COOKIE_matchDomain(LPCWSTR lpszCookieDomain, LPCWSTR lpszCookiePath,
cookie_domain *searchDomain, BOOL allow_partial);
static BOOL create_cookie_url(LPCWSTR domain, LPCWSTR path, WCHAR *buf, DWORD buf_len)
{
static const WCHAR cookie_prefix[] = {'C','o','o','k','i','e',':'};
WCHAR *p;
DWORD len;
if(buf_len < sizeof(cookie_prefix)/sizeof(WCHAR))
return FALSE;
memcpy(buf, cookie_prefix, sizeof(cookie_prefix));
buf += sizeof(cookie_prefix)/sizeof(WCHAR);
buf_len -= sizeof(cookie_prefix)/sizeof(WCHAR);
p = buf;
len = buf_len;
if(!GetUserNameW(buf, &len))
return FALSE;
buf += len-1;
buf_len -= len-1;
if(!buf_len)
return FALSE;
*(buf++) = '@';
buf_len--;
len = strlenW(domain);
if(len >= buf_len)
return FALSE;
memcpy(buf, domain, len*sizeof(WCHAR));
buf += len;
buf_len -= len;
len = strlenW(path);
if(len >= buf_len)
return FALSE;
memcpy(buf, path, len*sizeof(WCHAR));
buf += len;
*buf = 0;
for(; *p; p++)
*p = tolowerW(*p);
return TRUE;
}
static BOOL load_persistent_cookie(LPCWSTR domain, LPCWSTR path)
{
INTERNET_CACHE_ENTRY_INFOW *info;
cookie_domain *domain_container = NULL;
cookie *old_cookie;
struct list *iter;
WCHAR cookie_url[MAX_PATH];
HANDLE cookie;
char *str = NULL, *pbeg, *pend;
DWORD size, flags;
WCHAR *name, *data;
FILETIME expiry, create, time;
if (!create_cookie_url(domain, path, cookie_url, sizeof(cookie_url)/sizeof(cookie_url[0])))
return FALSE;
size = 0;
RetrieveUrlCacheEntryStreamW(cookie_url, NULL, &size, FALSE, 0);
if(GetLastError() != ERROR_INSUFFICIENT_BUFFER)
return TRUE;
info = heap_alloc(size);
if(!info)
return FALSE;
cookie = RetrieveUrlCacheEntryStreamW(cookie_url, info, &size, FALSE, 0);
size = info->dwSizeLow;
heap_free(info);
if(!cookie)
return FALSE;
if(!(str = heap_alloc(size+1)) || !ReadUrlCacheEntryStream(cookie, 0, str, &size, 0)) {
UnlockUrlCacheEntryStream(cookie, 0);
heap_free(str);
return FALSE;
}
str[size] = 0;
UnlockUrlCacheEntryStream(cookie, 0);
LIST_FOR_EACH(iter, &domain_list)
{
domain_container = LIST_ENTRY(iter, cookie_domain, entry);
if(COOKIE_matchDomain(domain, path, domain_container, FALSE))
break;
domain_container = NULL;
}
if(!domain_container)
domain_container = COOKIE_addDomain(domain, path);
if(!domain_container) {
heap_free(str);
return FALSE;
}
GetSystemTimeAsFileTime(&time);
for(pbeg=str; pbeg && *pbeg; name=data=NULL) {
pend = strchr(pbeg, '\n');
if(!pend)
break;
*pend = 0;
name = heap_strdupAtoW(pbeg);
pbeg = pend+1;
pend = strchr(pbeg, '\n');
if(!pend)
break;
*pend = 0;
data = heap_strdupAtoW(pbeg);
pbeg = pend+1;
pbeg = strchr(pend+1, '\n');
if(!pbeg)
break;
sscanf(pbeg, "%u %u %u %u %u", &flags, &expiry.dwLowDateTime, &expiry.dwHighDateTime,
&create.dwLowDateTime, &create.dwHighDateTime);
/* skip "*\n" */
pbeg = strchr(pbeg, '*');
if(pbeg) {
pbeg++;
if(*pbeg)
pbeg++;
}
if(!name || !data)
break;
if(CompareFileTime(&time, &expiry) <= 0) {
if((old_cookie = COOKIE_findCookie(domain_container, name)))
COOKIE_deleteCookie(old_cookie, FALSE);
COOKIE_addCookie(domain_container, name, data, expiry, create, flags);
}
heap_free(name);
heap_free(data);
}
heap_free(name);
heap_free(data);
return TRUE;
}
static BOOL save_persistent_cookie(cookie_domain *domain)
{
static const WCHAR txtW[] = {'t','x','t',0};
WCHAR cookie_url[MAX_PATH], cookie_file[MAX_PATH];
HANDLE cookie_handle;
cookie *cookie_container = NULL, *cookie_iter;
BOOL do_save = FALSE;
char buf[64], *dyn_buf;
FILETIME time;
DWORD dwBytesWritten;
if (!create_cookie_url(domain->lpCookieDomain, domain->lpCookiePath, cookie_url, sizeof(cookie_url)/sizeof(cookie_url[0])))
return FALSE;
/* check if there's anything to save */
GetSystemTimeAsFileTime(&time);
LIST_FOR_EACH_ENTRY_SAFE(cookie_container, cookie_iter, &domain->cookie_list, cookie, entry)
{
if((cookie_container->expiry.dwLowDateTime || cookie_container->expiry.dwHighDateTime)
&& CompareFileTime(&time, &cookie_container->expiry) > 0) {
COOKIE_deleteCookie(cookie_container, FALSE);
continue;
}
if(!(cookie_container->flags & INTERNET_COOKIE_IS_SESSION)) {
do_save = TRUE;
break;
}
}
if(!do_save) {
DeleteUrlCacheEntryW(cookie_url);
return TRUE;
}
if(!CreateUrlCacheEntryW(cookie_url, 0, txtW, cookie_file, 0))
return FALSE;
cookie_handle = CreateFileW(cookie_file, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if(cookie_handle == INVALID_HANDLE_VALUE) {
DeleteFileW(cookie_file);
return FALSE;
}
LIST_FOR_EACH_ENTRY(cookie_container, &domain->cookie_list, cookie, entry)
{
if(cookie_container->flags & INTERNET_COOKIE_IS_SESSION)
continue;
dyn_buf = heap_strdupWtoA(cookie_container->lpCookieName);
if(!dyn_buf || !WriteFile(cookie_handle, dyn_buf, strlen(dyn_buf), &dwBytesWritten, NULL)) {
heap_free(dyn_buf);
do_save = FALSE;
break;
}
heap_free(dyn_buf);
if(!WriteFile(cookie_handle, "\n", 1, &dwBytesWritten, NULL)) {
do_save = FALSE;
break;
}
dyn_buf = heap_strdupWtoA(cookie_container->lpCookieData);
if(!dyn_buf || !WriteFile(cookie_handle, dyn_buf, strlen(dyn_buf), &dwBytesWritten, NULL)) {
heap_free(dyn_buf);
do_save = FALSE;
break;
}
heap_free(dyn_buf);
if(!WriteFile(cookie_handle, "\n", 1, &dwBytesWritten, NULL)) {
do_save = FALSE;
break;
}
dyn_buf = heap_strdupWtoA(domain->lpCookieDomain);
if(!dyn_buf || !WriteFile(cookie_handle, dyn_buf, strlen(dyn_buf), &dwBytesWritten, NULL)) {
heap_free(dyn_buf);
do_save = FALSE;
break;
}
heap_free(dyn_buf);
dyn_buf = heap_strdupWtoA(domain->lpCookiePath);
if(!dyn_buf || !WriteFile(cookie_handle, dyn_buf, strlen(dyn_buf), &dwBytesWritten, NULL)) {
heap_free(dyn_buf);
do_save = FALSE;
break;
}
heap_free(dyn_buf);
sprintf(buf, "\n%u\n%u\n%u\n%u\n%u\n*\n", cookie_container->flags,
cookie_container->expiry.dwLowDateTime, cookie_container->expiry.dwHighDateTime,
cookie_container->create.dwLowDateTime, cookie_container->create.dwHighDateTime);
if(!WriteFile(cookie_handle, buf, strlen(buf), &dwBytesWritten, NULL)) {
do_save = FALSE;
break;
}
}
CloseHandle(cookie_handle);
if(!do_save) {
ERR("error saving cookie file\n");
DeleteFileW(cookie_file);
return FALSE;
}
memset(&time, 0, sizeof(time));
return CommitUrlCacheEntryW(cookie_url, cookie_file, time, time, 0, NULL, 0, txtW, 0);
}
/* adds a cookie to the domain */
static cookie *COOKIE_addCookie(cookie_domain *domain, LPCWSTR name, LPCWSTR data, FILETIME expiry)
static cookie *COOKIE_addCookie(cookie_domain *domain, LPCWSTR name, LPCWSTR data,
FILETIME expiry, FILETIME create, DWORD flags)
{
cookie *newCookie = heap_alloc(sizeof(cookie));
if (!newCookie)
return NULL;
list_init(&newCookie->entry);
newCookie->lpCookieName = NULL;
newCookie->lpCookieData = NULL;
newCookie->expiry = expiry;
newCookie->lpCookieName = heap_strdupW(name);
newCookie->lpCookieData = heap_strdupW(data);
if (!newCookie->lpCookieName || !newCookie->lpCookieData)
{
heap_free(newCookie->lpCookieName);
heap_free(newCookie->lpCookieData);
heap_free(newCookie);
return NULL;
}
newCookie->flags = flags;
newCookie->expiry = expiry;
newCookie->create = create;
TRACE("added cookie %p (data is %s)\n", newCookie, debugstr_w(data) );
list_add_tail(&domain->cookie_list, &newCookie->entry);
@ -153,8 +427,6 @@ static cookie_domain *COOKIE_addDomain(LPCWSTR domain, LPCWSTR path)
list_init(&newDomain->entry);
list_init(&newDomain->cookie_list);
newDomain->lpCookieDomain = NULL;
newDomain->lpCookiePath = NULL;
newDomain->lpCookieDomain = heap_strdupW(domain);
newDomain->lpCookiePath = heap_strdupW(path);
@ -215,8 +487,8 @@ static BOOL COOKIE_matchDomain(LPCWSTR lpszCookieDomain, LPCWSTR lpszCookiePath,
if (!searchDomain->lpCookieDomain)
return FALSE;
TRACE("comparing domain %s with %s\n",
debugstr_w(lpszCookieDomain),
TRACE("comparing domain %s with %s\n",
debugstr_w(lpszCookieDomain),
debugstr_w(searchDomain->lpCookieDomain));
if (allow_partial && !strstrW(lpszCookieDomain, searchDomain->lpCookieDomain))
@ -263,14 +535,19 @@ static void COOKIE_deleteDomain(cookie_domain *deadDomain)
heap_free(deadDomain);
}
BOOL get_cookie(const WCHAR *host, const WCHAR *path, WCHAR *cookie_data, DWORD *size)
DWORD get_cookie(const WCHAR *host, const WCHAR *path, WCHAR *cookie_data, DWORD *size)
{
unsigned cnt = 0, len, domain_count = 0, cookie_count = 0;
unsigned cnt = 0, len, name_len, domain_count = 0, cookie_count = 0;
WCHAR *ptr = cookie_data;
cookie_domain *domain;
FILETIME tm;
GetSystemTimeAsFileTime(&tm);
EnterCriticalSection(&cookie_cs);
load_persistent_cookie(host, path);
LIST_FOR_EACH_ENTRY(domain, &domain_list, cookie_domain, entry) {
struct list *cursor, *cursor2;
@ -279,7 +556,7 @@ BOOL get_cookie(const WCHAR *host, const WCHAR *path, WCHAR *cookie_data, DWORD
domain_count++;
TRACE("found domain %p\n", domain);
LIST_FOR_EACH_SAFE(cursor, cursor2, &domain->cookie_list) {
cookie *cookie_iter = LIST_ENTRY(cursor, cookie, entry);
@ -292,47 +569,62 @@ BOOL get_cookie(const WCHAR *host, const WCHAR *path, WCHAR *cookie_data, DWORD
continue;
}
if(!cookie_data) { /* return the size of the buffer required to lpdwSize */
if (cookie_count)
cnt += 2; /* '; ' */
cnt += strlenW(cookie_iter->lpCookieName);
if ((len = strlenW(cookie_iter->lpCookieData))) {
cnt += 1; /* = */
cnt += len;
}
}else {
static const WCHAR szsc[] = { ';',' ',0 };
static const WCHAR szname[] = { '%','s',0 };
static const WCHAR szdata[] = { '=','%','s',0 };
if (cookie_count) cnt += snprintfW(cookie_data + cnt, *size - cnt, szsc);
cnt += snprintfW(cookie_data + cnt, *size - cnt, szname, cookie_iter->lpCookieName);
if (cookie_iter->lpCookieData[0])
cnt += snprintfW(cookie_data + cnt, *size - cnt, szdata, cookie_iter->lpCookieData);
TRACE("Cookie: %s\n", debugstr_w(cookie_data));
if (cookie_count)
cnt += 2; /* '; ' */
cnt += name_len = strlenW(cookie_iter->lpCookieName);
if ((len = strlenW(cookie_iter->lpCookieData))) {
cnt += 1; /* = */
cnt += len;
}
if(ptr) {
if(*size > cnt) {
if(cookie_count) {
*ptr++ = ';';
*ptr++ = ' ';
}
memcpy(ptr, cookie_iter->lpCookieName, name_len*sizeof(WCHAR));
ptr += name_len;
if(len) {
*ptr++ = '=';
memcpy(ptr, cookie_iter->lpCookieData, len*sizeof(WCHAR));
ptr += len;
}
assert(cookie_data+cnt == ptr);
TRACE("Cookie: %s\n", debugstr_wn(cookie_data, cnt));
}else {
/* Stop writing data, just compute the size */
ptr = NULL;
}
}
cookie_count++;
}
}
if (!domain_count) {
LeaveCriticalSection(&cookie_cs);
if(ptr)
*ptr = 0;
if (!cnt) {
TRACE("no cookies found for %s\n", debugstr_w(host));
SetLastError(ERROR_NO_MORE_ITEMS);
return FALSE;
return ERROR_NO_MORE_ITEMS;
}
if(!cookie_data) {
if(!cookie_data || !ptr) {
*size = (cnt + 1) * sizeof(WCHAR);
TRACE("returning %u\n", *size);
return TRUE;
return cookie_data ? ERROR_INSUFFICIENT_BUFFER : ERROR_SUCCESS;
}
*size = cnt + 1;
TRACE("Returning %u (from %u domains): %s\n", cnt, domain_count, debugstr_w(cookie_data));
return cnt != 0;
return ERROR_SUCCESS;
}
/***********************************************************************
@ -352,6 +644,7 @@ BOOL WINAPI InternetGetCookieW(LPCWSTR lpszUrl, LPCWSTR lpszCookieName,
LPWSTR lpCookieData, LPDWORD lpdwSize)
{
WCHAR host[INTERNET_MAX_HOST_NAME_LENGTH], path[INTERNET_MAX_PATH_LENGTH];
DWORD res;
BOOL ret;
TRACE("(%s, %s, %p, %p)\n", debugstr_w(lpszUrl),debugstr_w(lpszCookieName), lpCookieData, lpdwSize);
@ -364,9 +657,15 @@ BOOL WINAPI InternetGetCookieW(LPCWSTR lpszUrl, LPCWSTR lpszCookieName,
host[0] = 0;
ret = COOKIE_crackUrlSimple(lpszUrl, host, sizeof(host)/sizeof(host[0]), path, sizeof(path)/sizeof(path[0]));
if (!ret || !host[0]) return FALSE;
if (!ret || !host[0]) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return get_cookie(host, path, lpCookieData, lpdwSize);
res = get_cookie(host, path, lpCookieData, lpdwSize);
if(res != ERROR_SUCCESS)
SetLastError(res);
return res == ERROR_SUCCESS;
}
@ -383,12 +682,12 @@ BOOL WINAPI InternetGetCookieW(LPCWSTR lpszUrl, LPCWSTR lpszCookieName,
BOOL WINAPI InternetGetCookieA(LPCSTR lpszUrl, LPCSTR lpszCookieName,
LPSTR lpCookieData, LPDWORD lpdwSize)
{
DWORD len;
LPWSTR szCookieData = NULL, url, name;
WCHAR *url, *name;
DWORD len, size;
BOOL r;
TRACE("(%s,%s,%p)\n", debugstr_a(lpszUrl), debugstr_a(lpszCookieName),
lpCookieData);
TRACE("(%s %s %p %p(%u))\n", debugstr_a(lpszUrl), debugstr_a(lpszCookieName),
lpCookieData, lpdwSize, lpdwSize ? *lpdwSize : 0);
url = heap_strdupAtoW(lpszUrl);
name = heap_strdupAtoW(lpszCookieName);
@ -396,6 +695,8 @@ BOOL WINAPI InternetGetCookieA(LPCSTR lpszUrl, LPCSTR lpszCookieName,
r = InternetGetCookieW( url, name, NULL, &len );
if( r )
{
WCHAR *szCookieData;
szCookieData = heap_alloc(len * sizeof(WCHAR));
if( !szCookieData )
{
@ -405,16 +706,64 @@ BOOL WINAPI InternetGetCookieA(LPCSTR lpszUrl, LPCSTR lpszCookieName,
{
r = InternetGetCookieW( url, name, szCookieData, &len );
*lpdwSize = WideCharToMultiByte( CP_ACP, 0, szCookieData, len,
lpCookieData, *lpdwSize, NULL, NULL );
if(r) {
size = WideCharToMultiByte( CP_ACP, 0, szCookieData, len, NULL, 0, NULL, NULL);
if(lpCookieData) {
if(*lpdwSize >= size) {
WideCharToMultiByte( CP_ACP, 0, szCookieData, len, lpCookieData, *lpdwSize, NULL, NULL);
}else {
SetLastError(ERROR_INSUFFICIENT_BUFFER);
r = FALSE;
}
}
*lpdwSize = size;
}
heap_free( szCookieData );
}
}
heap_free( szCookieData );
heap_free( name );
heap_free( url );
return r;
}
/***********************************************************************
* IsDomainLegalCookieDomainW (WININET.@)
*/
BOOL WINAPI IsDomainLegalCookieDomainW( LPCWSTR s1, LPCWSTR s2 )
{
DWORD s1_len, s2_len;
FIXME("(%s, %s) semi-stub\n", debugstr_w(s1), debugstr_w(s2));
if (!s1 || !s2)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (s1[0] == '.' || !s1[0] || s2[0] == '.' || !s2[0])
{
SetLastError(ERROR_INVALID_NAME);
return FALSE;
}
if(!strchrW(s1, '.') || !strchrW(s2, '.'))
return FALSE;
s1_len = strlenW(s1);
s2_len = strlenW(s2);
if (s1_len > s2_len)
return FALSE;
if (strncmpiW(s1, s2+s2_len-s1_len, s1_len) || (s2_len>s1_len && s2[s2_len-s1_len-1]!='.'))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return TRUE;
}
BOOL set_cookie(LPCWSTR domain, LPCWSTR path, LPCWSTR cookie_name, LPCWSTR cookie_data)
{
cookie_domain *thisCookieDomain = NULL;
@ -422,8 +771,9 @@ BOOL set_cookie(LPCWSTR domain, LPCWSTR path, LPCWSTR cookie_name, LPCWSTR cooki
struct list *cursor;
LPWSTR data, value;
WCHAR *ptr;
FILETIME expiry;
BOOL expired = FALSE;
FILETIME expiry, create;
BOOL expired = FALSE, update_persistent = FALSE;
DWORD flags = 0;
value = data = heap_strdupW(cookie_data);
if (!data)
@ -433,6 +783,7 @@ BOOL set_cookie(LPCWSTR domain, LPCWSTR path, LPCWSTR cookie_name, LPCWSTR cooki
}
memset(&expiry,0,sizeof(expiry));
GetSystemTimeAsFileTime(&create);
/* lots of information can be parsed out of the cookie value */
@ -462,7 +813,26 @@ BOOL set_cookie(LPCWSTR domain, LPCWSTR path, LPCWSTR cookie_name, LPCWSTR cooki
if (strncmpiW(ptr, szDomain, 7) == 0)
{
ptr+=strlenW(szDomain);
WCHAR *end_ptr;
ptr += sizeof(szDomain)/sizeof(szDomain[0])-1;
if(*ptr == '.')
ptr++;
end_ptr = strchrW(ptr, ';');
if(end_ptr)
*end_ptr = 0;
if(!IsDomainLegalCookieDomainW(ptr, domain))
{
if(value != data)
heap_free(value);
heap_free(data);
return FALSE;
}
if(end_ptr)
*end_ptr = ';';
domain = ptr;
TRACE("Parsing new domain %s\n",debugstr_w(domain));
}
@ -474,16 +844,13 @@ BOOL set_cookie(LPCWSTR domain, LPCWSTR path, LPCWSTR cookie_name, LPCWSTR cooki
}
else if (strncmpiW(ptr, szExpires, 8) == 0)
{
FILETIME ft;
SYSTEMTIME st;
FIXME("persistent cookies not handled (%s)\n",debugstr_w(ptr));
ptr+=strlenW(szExpires);
if (InternetTimeToSystemTimeW(ptr, &st, 0))
{
SystemTimeToFileTime(&st, &expiry);
GetSystemTimeAsFileTime(&ft);
if (CompareFileTime(&ft,&expiry) > 0)
if (CompareFileTime(&create,&expiry) > 0)
{
TRACE("Cookie already expired.\n");
expired = TRUE;
@ -507,6 +874,10 @@ BOOL set_cookie(LPCWSTR domain, LPCWSTR path, LPCWSTR cookie_name, LPCWSTR cooki
}
}
EnterCriticalSection(&cookie_cs);
load_persistent_cookie(domain, path);
LIST_FOR_EACH(cursor, &domain_list)
{
thisCookieDomain = LIST_ENTRY(cursor, cookie_domain, entry);
@ -523,25 +894,43 @@ BOOL set_cookie(LPCWSTR domain, LPCWSTR path, LPCWSTR cookie_name, LPCWSTR cooki
{
heap_free(data);
if (value != data) heap_free(value);
LeaveCriticalSection(&cookie_cs);
return TRUE;
}
}
if(!expiry.dwLowDateTime && !expiry.dwHighDateTime)
flags |= INTERNET_COOKIE_IS_SESSION;
else
update_persistent = TRUE;
if ((thisCookie = COOKIE_findCookie(thisCookieDomain, cookie_name)))
{
if (!(thisCookie->flags & INTERNET_COOKIE_IS_SESSION))
update_persistent = TRUE;
COOKIE_deleteCookie(thisCookie, FALSE);
}
TRACE("setting cookie %s=%s for domain %s path %s\n", debugstr_w(cookie_name),
debugstr_w(value), debugstr_w(thisCookieDomain->lpCookieDomain),debugstr_w(thisCookieDomain->lpCookiePath));
if (!expired && !COOKIE_addCookie(thisCookieDomain, cookie_name, value, expiry))
if (!expired && !COOKIE_addCookie(thisCookieDomain, cookie_name, value, expiry, create, flags))
{
heap_free(data);
if (value != data) heap_free(value);
LeaveCriticalSection(&cookie_cs);
return FALSE;
}
heap_free(data);
if (value != data) heap_free(value);
return TRUE;
if (!update_persistent || save_persistent_cookie(thisCookieDomain))
{
LeaveCriticalSection(&cookie_cs);
return TRUE;
}
LeaveCriticalSection(&cookie_cs);
return FALSE;
}
/***********************************************************************
@ -787,27 +1176,7 @@ BOOL WINAPI InternetSetPerSiteCookieDecisionW( LPCWSTR pchHostName, DWORD dwDeci
return FALSE;
}
/***********************************************************************
* IsDomainLegalCookieDomainW (WININET.@)
*/
BOOL WINAPI IsDomainLegalCookieDomainW( LPCWSTR s1, LPCWSTR s2 )
void free_cookie(void)
{
const WCHAR *p;
FIXME("(%s, %s)\n", debugstr_w(s1), debugstr_w(s2));
if (!s1 || !s2)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (s1[0] == '.' || !s1[0] || s2[0] == '.' || !s2[0])
{
SetLastError(ERROR_INVALID_NAME);
return FALSE;
}
if (!(p = strchrW(s2, '.'))) return FALSE;
if (strchrW(p + 1, '.') && !strcmpW(p + 1, s1)) return TRUE;
else if (!strcmpW(s1, s2)) return TRUE;
return FALSE;
DeleteCriticalSection(&cookie_cs);
}

View file

@ -42,6 +42,8 @@
#include <ws2tcpip.h>
#endif
#include <cryptuiapi.h>
#include "internet.h"
//#include "wine/unicode.h"
@ -54,80 +56,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(wininet);
struct WININET_ErrorDlgParams
{
http_request_t *req;
HWND hWnd;
HINTERNET hRequest;
DWORD dwError;
DWORD dwFlags;
LPVOID* lppvData;
};
/***********************************************************************
* WININET_GetProxyServer
*
* Determine the name of the proxy server the request is using
*/
static BOOL WININET_GetProxyServer( HINTERNET hRequest, LPWSTR szBuf, DWORD sz )
{
http_request_t *request;
http_session_t *session = NULL;
appinfo_t *hIC = NULL;
BOOL ret = FALSE;
LPWSTR p;
request = (http_request_t*) get_handle_object( hRequest );
if (NULL == request)
return FALSE;
session = request->session;
if (NULL == session)
goto done;
hIC = session->appInfo;
if (NULL == hIC)
goto done;
lstrcpynW(szBuf, hIC->proxy, sz);
/* FIXME: perhaps it would be better to use InternetCrackUrl here */
p = strchrW(szBuf, ':');
if (p)
*p = 0;
ret = TRUE;
done:
WININET_Release( &request->hdr );
return ret;
}
/***********************************************************************
* WININET_GetServer
*
* Determine the name of the web server
*/
static BOOL WININET_GetServer( HINTERNET hRequest, LPWSTR szBuf, DWORD sz )
{
http_request_t *request;
http_session_t *session = NULL;
BOOL ret = FALSE;
request = (http_request_t*) get_handle_object( hRequest );
if (NULL == request)
return FALSE;
session = request->session;
if (NULL == session)
goto done;
lstrcpynW(szBuf, session->hostName, sz);
ret = TRUE;
done:
WININET_Release( &request->hdr );
return ret;
}
/***********************************************************************
* WININET_GetAuthRealm
*
@ -246,34 +181,21 @@ static BOOL WININET_GetSetPassword( HWND hdlg, LPCWSTR szServer,
/***********************************************************************
* WININET_SetAuthorization
*/
static BOOL WININET_SetAuthorization( HINTERNET hRequest, LPWSTR username,
static BOOL WININET_SetAuthorization( http_request_t *request, LPWSTR username,
LPWSTR password, BOOL proxy )
{
http_request_t *request;
http_session_t *session;
BOOL ret = FALSE;
http_session_t *session = request->session;
LPWSTR p, q;
request = (http_request_t*) get_handle_object( hRequest );
if( !request )
return FALSE;
session = request->session;
if (NULL == session || session->hdr.htype != WH_HHTTPSESSION)
{
INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
goto done;
}
p = heap_strdupW(username);
if( !p )
goto done;
return FALSE;
q = heap_strdupW(password);
if( !q )
{
heap_free(username);
goto done;
heap_free(p);
return FALSE;
}
if (proxy)
@ -295,11 +217,7 @@ static BOOL WININET_SetAuthorization( HINTERNET hRequest, LPWSTR username,
session->password = q;
}
ret = TRUE;
done:
WININET_Release( &request->hdr );
return ret;
return TRUE;
}
/***********************************************************************
@ -321,20 +239,15 @@ static INT_PTR WINAPI WININET_ProxyPasswordDialog(
SetWindowLongPtrW( hdlg, GWLP_USERDATA, lParam );
/* extract the Realm from the proxy response and show it */
if( WININET_GetAuthRealm( params->hRequest,
if( WININET_GetAuthRealm( params->req->hdr.hInternet,
szRealm, sizeof szRealm/sizeof(WCHAR), TRUE ) )
{
hitem = GetDlgItem( hdlg, IDC_REALM );
SetWindowTextW( hitem, szRealm );
}
/* extract the name of the proxy server */
if( WININET_GetProxyServer( params->hRequest,
szServer, sizeof szServer/sizeof(WCHAR)) )
{
hitem = GetDlgItem( hdlg, IDC_PROXY );
SetWindowTextW( hitem, szServer );
}
hitem = GetDlgItem( hdlg, IDC_PROXY );
SetWindowTextW( hitem, params->req->session->appInfo->proxy );
WININET_GetSetPassword( hdlg, szServer, szRealm, FALSE );
@ -364,14 +277,10 @@ static INT_PTR WINAPI WININET_ProxyPasswordDialog(
hitem = GetDlgItem( hdlg, IDC_SAVEPASSWORD );
if( hitem &&
SendMessageW( hitem, BM_GETSTATE, 0, 0 ) &&
WININET_GetAuthRealm( params->hRequest,
szRealm, sizeof szRealm/sizeof(WCHAR), TRUE ) &&
WININET_GetProxyServer( params->hRequest,
szServer, sizeof szServer/sizeof(WCHAR)) )
{
WININET_GetSetPassword( hdlg, szServer, szRealm, TRUE );
}
WININET_SetAuthorization( params->hRequest, username, password, TRUE );
WININET_GetAuthRealm( params->req->hdr.hInternet,
szRealm, sizeof szRealm/sizeof(WCHAR), TRUE) )
WININET_GetSetPassword( hdlg, params->req->session->appInfo->proxy, szRealm, TRUE );
WININET_SetAuthorization( params->req, username, password, TRUE );
EndDialog( hdlg, ERROR_INTERNET_FORCE_RETRY );
return TRUE;
@ -405,20 +314,15 @@ static INT_PTR WINAPI WININET_PasswordDialog(
SetWindowLongPtrW( hdlg, GWLP_USERDATA, lParam );
/* extract the Realm from the response and show it */
if( WININET_GetAuthRealm( params->hRequest,
if( WININET_GetAuthRealm( params->req->hdr.hInternet,
szRealm, sizeof szRealm/sizeof(WCHAR), FALSE ) )
{
hitem = GetDlgItem( hdlg, IDC_REALM );
SetWindowTextW( hitem, szRealm );
}
/* extract the name of the server */
if( WININET_GetServer( params->hRequest,
szServer, sizeof szServer/sizeof(WCHAR)) )
{
hitem = GetDlgItem( hdlg, IDC_SERVER );
SetWindowTextW( hitem, szServer );
}
hitem = GetDlgItem( hdlg, IDC_SERVER );
SetWindowTextW( hitem, params->req->session->hostName );
WININET_GetSetPassword( hdlg, szServer, szRealm, FALSE );
@ -448,14 +352,12 @@ static INT_PTR WINAPI WININET_PasswordDialog(
hitem = GetDlgItem( hdlg, IDC_SAVEPASSWORD );
if( hitem &&
SendMessageW( hitem, BM_GETSTATE, 0, 0 ) &&
WININET_GetAuthRealm( params->hRequest,
szRealm, sizeof szRealm/sizeof(WCHAR), FALSE ) &&
WININET_GetServer( params->hRequest,
szServer, sizeof szServer/sizeof(WCHAR)) )
WININET_GetAuthRealm( params->req->hdr.hInternet,
szRealm, sizeof szRealm/sizeof(WCHAR), FALSE ))
{
WININET_GetSetPassword( hdlg, szServer, szRealm, TRUE );
WININET_GetSetPassword( hdlg, params->req->session->hostName, szRealm, TRUE );
}
WININET_SetAuthorization( params->hRequest, username, password, FALSE );
WININET_SetAuthorization( params->req, username, password, FALSE );
EndDialog( hdlg, ERROR_INTERNET_FORCE_RETRY );
return TRUE;
@ -528,9 +430,10 @@ static INT_PTR WINAPI WININET_InvalidCertificateDialog(
if( params->dwFlags & FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS )
{
http_request_t *req = params->req;
DWORD flags, size = sizeof(flags);
InternetQueryOptionW( params->hRequest, INTERNET_OPTION_SECURITY_FLAGS, &flags, &size );
InternetQueryOptionW( req->hdr.hInternet, INTERNET_OPTION_SECURITY_FLAGS, &flags, &size );
switch( params->dwError )
{
case ERROR_INTERNET_INVALID_CA:
@ -542,19 +445,25 @@ static INT_PTR WINAPI WININET_InvalidCertificateDialog(
case ERROR_INTERNET_SEC_CERT_CN_INVALID:
flags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
break;
case ERROR_INTERNET_SEC_CERT_REV_FAILED:
flags |= SECURITY_FLAG_IGNORE_REVOCATION;
break;
case ERROR_INTERNET_SEC_CERT_ERRORS:
FIXME("Should only add ignore flags as needed.\n");
flags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
SECURITY_FLAG_IGNORE_UNKNOWN_CA;
/* FIXME: ERROR_INTERNET_SEC_CERT_ERRORS also
* seems to set the corresponding DLG_* flags.
*/
if(flags & _SECURITY_FLAG_CERT_REV_FAILED)
flags |= SECURITY_FLAG_IGNORE_REVOCATION;
if(flags & _SECURITY_FLAG_CERT_INVALID_CA)
flags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
if(flags & _SECURITY_FLAG_CERT_INVALID_CN)
flags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
if(flags & _SECURITY_FLAG_CERT_INVALID_DATE)
flags |= SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
break;
}
res = InternetSetOptionW( params->hRequest, INTERNET_OPTION_SECURITY_FLAGS, &flags, size );
if(!res)
WARN("InternetSetOption(INTERNET_OPTION_SECURITY_FLAGS) failed.\n");
/* FIXME: Use helper function */
flags |= SECURITY_FLAG_SECURE;
req->security_flags |= flags;
if(req->netconn)
req->netconn->security_flags |= flags;
}
EndDialog( hdlg, res ? ERROR_SUCCESS : ERROR_NOT_SUPPORTED );
@ -573,29 +482,6 @@ static INT_PTR WINAPI WININET_InvalidCertificateDialog(
return FALSE;
}
/***********************************************************************
* WININET_GetConnectionStatus
*/
static INT WININET_GetConnectionStatus( HINTERNET hRequest )
{
WCHAR szStatus[0x20];
DWORD sz, index, dwStatus;
TRACE("%p\n", hRequest );
sz = sizeof szStatus;
index = 0;
if( !HttpQueryInfoW( hRequest, HTTP_QUERY_STATUS_CODE,
szStatus, &sz, &index))
return -1;
dwStatus = atoiW( szStatus );
TRACE("request %p status = %d\n", hRequest, dwStatus );
return dwStatus;
}
/***********************************************************************
* InternetErrorDlg
*/
@ -603,15 +489,24 @@ DWORD WINAPI InternetErrorDlg(HWND hWnd, HINTERNET hRequest,
DWORD dwError, DWORD dwFlags, LPVOID* lppvData)
{
struct WININET_ErrorDlgParams params;
INT dwStatus;
http_request_t *req = NULL;
DWORD res = ERROR_SUCCESS;
TRACE("%p %p %d %08x %p\n", hWnd, hRequest, dwError, dwFlags, lppvData);
if( !hWnd && !(dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI) )
return ERROR_INVALID_HANDLE;
if(hRequest) {
req = (http_request_t*)get_handle_object(hRequest);
if(!req)
return ERROR_INVALID_HANDLE;
if(req->hdr.htype != WH_HHTTPREQ)
return ERROR_SUCCESS; /* Yes, that was tested */
}
params.req = req;
params.hWnd = hWnd;
params.hRequest = hRequest;
params.dwError = dwError;
params.dwFlags = dwFlags;
params.lppvData = lppvData;
@ -619,40 +514,100 @@ DWORD WINAPI InternetErrorDlg(HWND hWnd, HINTERNET hRequest,
switch( dwError )
{
case ERROR_SUCCESS:
case ERROR_INTERNET_INCORRECT_PASSWORD:
case ERROR_INTERNET_INCORRECT_PASSWORD: {
if( !dwError && !(dwFlags & FLAGS_ERROR_UI_FILTER_FOR_ERRORS ) )
return 0;
break;
if(!req)
return ERROR_INVALID_HANDLE;
dwStatus = WININET_GetConnectionStatus( hRequest );
switch (dwStatus)
{
switch(req->status_code) {
case HTTP_STATUS_PROXY_AUTH_REQ:
return DialogBoxParamW( WININET_hModule, MAKEINTRESOURCEW( IDD_PROXYDLG ),
hWnd, WININET_ProxyPasswordDialog, (LPARAM) &params );
res = DialogBoxParamW( WININET_hModule, MAKEINTRESOURCEW( IDD_PROXYDLG ),
hWnd, WININET_ProxyPasswordDialog, (LPARAM) &params );
break;
case HTTP_STATUS_DENIED:
return DialogBoxParamW( WININET_hModule, MAKEINTRESOURCEW( IDD_AUTHDLG ),
res = DialogBoxParamW( WININET_hModule, MAKEINTRESOURCEW( IDD_AUTHDLG ),
hWnd, WININET_PasswordDialog, (LPARAM) &params );
break;
default:
WARN("unhandled status %u\n", dwStatus);
return 0;
WARN("unhandled status %u\n", req->status_code);
}
break;
}
case ERROR_INTERNET_SEC_CERT_ERRORS:
case ERROR_INTERNET_SEC_CERT_CN_INVALID:
case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
case ERROR_INTERNET_INVALID_CA:
if( dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI )
return ERROR_CANCELLED;
case ERROR_INTERNET_SEC_CERT_REV_FAILED:
if( dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI ) {
res = ERROR_CANCELLED;
break;
}
if(!req)
return ERROR_INVALID_HANDLE;
if( dwFlags & ~FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS )
FIXME("%08x contains unsupported flags.\n", dwFlags);
return DialogBoxParamW( WININET_hModule, MAKEINTRESOURCEW( IDD_INVCERTDLG ),
hWnd, WININET_InvalidCertificateDialog, (LPARAM) &params );
res = DialogBoxParamW( WININET_hModule, MAKEINTRESOURCEW( IDD_INVCERTDLG ),
hWnd, WININET_InvalidCertificateDialog, (LPARAM) &params );
break;
case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR:
case ERROR_INTERNET_POST_IS_NON_SECURE:
FIXME("Need to display dialog for error %d\n", dwError);
return ERROR_SUCCESS;
res = ERROR_SUCCESS;
break;
default:
res = ERROR_NOT_SUPPORTED;
}
return ERROR_NOT_SUPPORTED;
if(req)
WININET_Release(&req->hdr);
return res;
}
/***********************************************************************
* InternetShowSecurityInfoByURLA (@)
*/
BOOL WINAPI InternetShowSecurityInfoByURLA(LPCSTR url, HWND window)
{
FIXME("stub: %s %p\n", url, window);
return FALSE;
}
/***********************************************************************
* InternetShowSecurityInfoByURLW (@)
*/
BOOL WINAPI InternetShowSecurityInfoByURLW(LPCWSTR url, HWND window)
{
FIXME("stub: %s %p\n", debugstr_w(url), window);
return FALSE;
}
/***********************************************************************
* ShowX509EncodedCertificate (@)
*/
DWORD WINAPI ShowX509EncodedCertificate(HWND parent, LPBYTE cert, DWORD len)
{
PCCERT_CONTEXT certContext = CertCreateCertificateContext(X509_ASN_ENCODING,
cert, len);
DWORD ret;
if (certContext)
{
CRYPTUI_VIEWCERTIFICATE_STRUCTW view;
memset(&view, 0, sizeof(view));
view.hwndParent = parent;
view.pCertContext = certContext;
if (CryptUIDlgViewCertificateW(&view, NULL))
ret = ERROR_SUCCESS;
else
ret = GetLastError();
CertFreeCertificateContext(certContext);
}
else
ret = GetLastError();
return ret;
}

View file

@ -255,18 +255,26 @@ BOOL WINAPI FtpPutFileA(HINTERNET hConnect, LPCSTR lpszLocalFile,
return ret;
}
static void AsyncFtpPutFileProc(WORKREQUEST *workRequest)
typedef struct {
task_header_t hdr;
WCHAR *local_file;
WCHAR *remote_file;
DWORD flags;
DWORD_PTR context;
} put_file_task_t;
static void AsyncFtpPutFileProc(task_header_t *hdr)
{
struct WORKREQ_FTPPUTFILEW const *req = &workRequest->u.FtpPutFileW;
ftp_session_t *lpwfs = (ftp_session_t*) workRequest->hdr;
put_file_task_t *task = (put_file_task_t*)hdr;
ftp_session_t *session = (ftp_session_t*)task->hdr.hdr;
TRACE("%p\n", lpwfs);
TRACE("%p\n", session);
FTP_FtpPutFileW(lpwfs, req->lpszLocalFile,
req->lpszNewRemoteFile, req->dwFlags, req->dwContext);
FTP_FtpPutFileW(session, task->local_file, task->remote_file,
task->flags, task->context);
heap_free(req->lpszLocalFile);
heap_free(req->lpszNewRemoteFile);
heap_free(task->local_file);
heap_free(task->remote_file);
}
/***********************************************************************
@ -320,17 +328,14 @@ BOOL WINAPI FtpPutFileW(HINTERNET hConnect, LPCWSTR lpszLocalFile,
hIC = lpwfs->lpAppInfo;
if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
{
WORKREQUEST workRequest;
struct WORKREQ_FTPPUTFILEW *req = &workRequest.u.FtpPutFileW;
put_file_task_t *task = alloc_async_task(&lpwfs->hdr, AsyncFtpPutFileProc, sizeof(*task));
workRequest.asyncproc = AsyncFtpPutFileProc;
workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
req->lpszLocalFile = heap_strdupW(lpszLocalFile);
req->lpszNewRemoteFile = heap_strdupW(lpszNewRemoteFile);
req->dwFlags = dwFlags;
req->dwContext = dwContext;
task->local_file = heap_strdupW(lpszLocalFile);
task->remote_file = heap_strdupW(lpszNewRemoteFile);
task->flags = dwFlags;
task->context = dwContext;
r = res_to_le(INTERNET_AsyncCall(&workRequest));
r = res_to_le(INTERNET_AsyncCall(&task->hdr));
}
else
{
@ -440,16 +445,20 @@ BOOL WINAPI FtpSetCurrentDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory)
return ret;
}
typedef struct {
task_header_t hdr;
WCHAR *directory;
} directory_task_t;
static void AsyncFtpSetCurrentDirectoryProc(WORKREQUEST *workRequest)
static void AsyncFtpSetCurrentDirectoryProc(task_header_t *hdr)
{
struct WORKREQ_FTPSETCURRENTDIRECTORYW const *req = &workRequest->u.FtpSetCurrentDirectoryW;
ftp_session_t *lpwfs = (ftp_session_t*) workRequest->hdr;
directory_task_t *task = (directory_task_t*)hdr;
ftp_session_t *session = (ftp_session_t*)task->hdr.hdr;
TRACE("%p\n", lpwfs);
TRACE("%p\n", session);
FTP_FtpSetCurrentDirectoryW(lpwfs, req->lpszDirectory);
heap_free(req->lpszDirectory);
FTP_FtpSetCurrentDirectoryW(session, task->directory);
heap_free(task->directory);
}
/***********************************************************************
@ -492,15 +501,12 @@ BOOL WINAPI FtpSetCurrentDirectoryW(HINTERNET hConnect, LPCWSTR lpszDirectory)
hIC = lpwfs->lpAppInfo;
if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
{
WORKREQUEST workRequest;
struct WORKREQ_FTPSETCURRENTDIRECTORYW *req;
directory_task_t *task;
workRequest.asyncproc = AsyncFtpSetCurrentDirectoryProc;
workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
req = &workRequest.u.FtpSetCurrentDirectoryW;
req->lpszDirectory = heap_strdupW(lpszDirectory);
task = alloc_async_task(&lpwfs->hdr, AsyncFtpSetCurrentDirectoryProc, sizeof(*task));
task->directory = heap_strdupW(lpszDirectory);
r = res_to_le(INTERNET_AsyncCall(&workRequest));
r = res_to_le(INTERNET_AsyncCall(&task->hdr));
}
else
{
@ -587,15 +593,15 @@ BOOL WINAPI FtpCreateDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory)
}
static void AsyncFtpCreateDirectoryProc(WORKREQUEST *workRequest)
static void AsyncFtpCreateDirectoryProc(task_header_t *hdr)
{
struct WORKREQ_FTPCREATEDIRECTORYW const *req = &workRequest->u.FtpCreateDirectoryW;
ftp_session_t *lpwfs = (ftp_session_t*) workRequest->hdr;
directory_task_t *task = (directory_task_t*)hdr;
ftp_session_t *session = (ftp_session_t*)task->hdr.hdr;
TRACE(" %p\n", lpwfs);
TRACE(" %p\n", session);
FTP_FtpCreateDirectoryW(lpwfs, req->lpszDirectory);
heap_free(req->lpszDirectory);
FTP_FtpCreateDirectoryW(session, task->directory);
heap_free(task->directory);
}
/***********************************************************************
@ -642,15 +648,12 @@ BOOL WINAPI FtpCreateDirectoryW(HINTERNET hConnect, LPCWSTR lpszDirectory)
hIC = lpwfs->lpAppInfo;
if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
{
WORKREQUEST workRequest;
struct WORKREQ_FTPCREATEDIRECTORYW *req;
directory_task_t *task;
workRequest.asyncproc = AsyncFtpCreateDirectoryProc;
workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
req = &workRequest.u.FtpCreateDirectoryW;
req->lpszDirectory = heap_strdupW(lpszDirectory);
task = alloc_async_task(&lpwfs->hdr, AsyncFtpCreateDirectoryProc, sizeof(*task));
task->directory = heap_strdupW(lpszDirectory);
r = res_to_le(INTERNET_AsyncCall(&workRequest));
r = res_to_le(INTERNET_AsyncCall(&task->hdr));
}
else
{
@ -740,17 +743,23 @@ HINTERNET WINAPI FtpFindFirstFileA(HINTERNET hConnect,
return ret;
}
typedef struct {
task_header_t hdr;
WCHAR *search_file;
WIN32_FIND_DATAW *find_file_data;
DWORD flags;
DWORD_PTR context;
} find_first_file_task_t;
static void AsyncFtpFindFirstFileProc(WORKREQUEST *workRequest)
static void AsyncFtpFindFirstFileProc(task_header_t *hdr)
{
struct WORKREQ_FTPFINDFIRSTFILEW const *req = &workRequest->u.FtpFindFirstFileW;
ftp_session_t *lpwfs = (ftp_session_t*) workRequest->hdr;
find_first_file_task_t *task = (find_first_file_task_t*)hdr;
ftp_session_t *session = (ftp_session_t*)task->hdr.hdr;
TRACE("%p\n", lpwfs);
TRACE("%p\n", session);
FTP_FtpFindFirstFileW(lpwfs, req->lpszSearchFile,
req->lpFindFileData, req->dwFlags, req->dwContext);
heap_free(req->lpszSearchFile);
FTP_FtpFindFirstFileW(session, task->search_file, task->find_file_data, task->flags, task->context);
heap_free(task->search_file);
}
/***********************************************************************
@ -786,19 +795,16 @@ HINTERNET WINAPI FtpFindFirstFileW(HINTERNET hConnect,
hIC = lpwfs->lpAppInfo;
if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
{
WORKREQUEST workRequest;
struct WORKREQ_FTPFINDFIRSTFILEW *req;
find_first_file_task_t *task;
workRequest.asyncproc = AsyncFtpFindFirstFileProc;
workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
req = &workRequest.u.FtpFindFirstFileW;
req->lpszSearchFile = (lpszSearchFile == NULL) ? NULL : heap_strdupW(lpszSearchFile);
req->lpFindFileData = lpFindFileData;
req->dwFlags = dwFlags;
req->dwContext= dwContext;
task = alloc_async_task(&lpwfs->hdr, AsyncFtpFindFirstFileProc, sizeof(*task));
task->search_file = heap_strdupW(lpszSearchFile);
task->find_file_data = lpFindFileData;
task->flags = dwFlags;
task->context = dwContext;
INTERNET_AsyncCall(&workRequest);
r = NULL;
INTERNET_AsyncCall(&task->hdr);
r = NULL;
}
else
{
@ -938,15 +944,20 @@ BOOL WINAPI FtpGetCurrentDirectoryA(HINTERNET hFtpSession, LPSTR lpszCurrentDire
return ret;
}
typedef struct {
task_header_t hdr;
WCHAR *directory;
DWORD *directory_len;
} get_current_dir_task_t;
static void AsyncFtpGetCurrentDirectoryProc(WORKREQUEST *workRequest)
static void AsyncFtpGetCurrentDirectoryProc(task_header_t *hdr)
{
struct WORKREQ_FTPGETCURRENTDIRECTORYW const *req = &workRequest->u.FtpGetCurrentDirectoryW;
ftp_session_t *lpwfs = (ftp_session_t*) workRequest->hdr;
get_current_dir_task_t *task = (get_current_dir_task_t*)hdr;
ftp_session_t *session = (ftp_session_t*)task->hdr.hdr;
TRACE("%p\n", lpwfs);
TRACE("%p\n", session);
FTP_FtpGetCurrentDirectoryW(lpwfs, req->lpszDirectory, req->lpdwDirectory);
FTP_FtpGetCurrentDirectoryW(session, task->directory, task->directory_len);
}
/***********************************************************************
@ -1002,16 +1013,13 @@ BOOL WINAPI FtpGetCurrentDirectoryW(HINTERNET hFtpSession, LPWSTR lpszCurrentDir
hIC = lpwfs->lpAppInfo;
if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
{
WORKREQUEST workRequest;
struct WORKREQ_FTPGETCURRENTDIRECTORYW *req;
get_current_dir_task_t *task;
workRequest.asyncproc = AsyncFtpGetCurrentDirectoryProc;
workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
req = &workRequest.u.FtpGetCurrentDirectoryW;
req->lpszDirectory = lpszCurrentDirectory;
req->lpdwDirectory = lpdwCurrentDirectory;
task = alloc_async_task(&lpwfs->hdr, AsyncFtpGetCurrentDirectoryProc, sizeof(*task));
task->directory = lpszCurrentDirectory;
task->directory_len = lpdwCurrentDirectory;
r = res_to_le(INTERNET_AsyncCall(&workRequest));
r = res_to_le(INTERNET_AsyncCall(&task->hdr));
}
else
{
@ -1205,16 +1213,10 @@ static DWORD FTPFILE_ReadFile(object_header_t *hdr, void *buffer, DWORD size, DW
return error;
}
static DWORD FTPFILE_ReadFileExA(object_header_t *hdr, INTERNET_BUFFERSA *buffers,
static DWORD FTPFILE_ReadFileEx(object_header_t *hdr, void *buf, DWORD size, DWORD *ret_size,
DWORD flags, DWORD_PTR context)
{
return FTPFILE_ReadFile(hdr, buffers->lpvBuffer, buffers->dwBufferLength, &buffers->dwBufferLength);
}
static DWORD FTPFILE_ReadFileExW(object_header_t *hdr, INTERNET_BUFFERSW *buffers,
DWORD flags, DWORD_PTR context)
{
return FTPFILE_ReadFile(hdr, buffers->lpvBuffer, buffers->dwBufferLength, &buffers->dwBufferLength);
return FTPFILE_ReadFile(hdr, buf, size, ret_size);
}
static DWORD FTPFILE_WriteFile(object_header_t *hdr, const void *buffer, DWORD size, DWORD *written)
@ -1250,9 +1252,9 @@ static void FTP_ReceiveRequestData(ftp_file_t *file, BOOL first_notif)
sizeof(INTERNET_ASYNC_RESULT));
}
static void FTPFILE_AsyncQueryDataAvailableProc(WORKREQUEST *workRequest)
static void FTPFILE_AsyncQueryDataAvailableProc(task_header_t *task)
{
ftp_file_t *file = (ftp_file_t*)workRequest->hdr;
ftp_file_t *file = (ftp_file_t*)task->hdr;
FTP_ReceiveRequestData(file, FALSE);
}
@ -1281,13 +1283,10 @@ static DWORD FTPFILE_QueryDataAvailable(object_header_t *hdr, DWORD *available,
retval = recv(file->nDataSocket, &byte, 1, MSG_PEEK);
if(retval > 0) {
WORKREQUEST workRequest;
task_header_t *task;
*available = 0;
workRequest.asyncproc = FTPFILE_AsyncQueryDataAvailableProc;
workRequest.hdr = WININET_AddRef( &file->hdr );
INTERNET_AsyncCall(&workRequest);
task = alloc_async_task(&file->hdr, FTPFILE_AsyncQueryDataAvailableProc, sizeof(*task));
INTERNET_AsyncCall(task);
return ERROR_IO_PENDING;
}
@ -1303,8 +1302,7 @@ static const object_vtbl_t FTPFILEVtbl = {
FTPFILE_QueryOption,
INET_SetOption,
FTPFILE_ReadFile,
FTPFILE_ReadFileExA,
FTPFILE_ReadFileExW,
FTPFILE_ReadFileEx,
FTPFILE_WriteFile,
FTPFILE_QueryDataAvailable,
NULL
@ -1459,17 +1457,23 @@ HINTERNET WINAPI FtpOpenFileA(HINTERNET hFtpSession,
return ret;
}
typedef struct {
task_header_t hdr;
WCHAR *file_name;
DWORD access;
DWORD flags;
DWORD_PTR context;
} open_file_task_t;
static void AsyncFtpOpenFileProc(WORKREQUEST *workRequest)
static void AsyncFtpOpenFileProc(task_header_t *hdr)
{
struct WORKREQ_FTPOPENFILEW const *req = &workRequest->u.FtpOpenFileW;
ftp_session_t *lpwfs = (ftp_session_t*) workRequest->hdr;
open_file_task_t *task = (open_file_task_t*)hdr;
ftp_session_t *session = (ftp_session_t*)task->hdr.hdr;
TRACE("%p\n", lpwfs);
TRACE("%p\n", session);
FTP_FtpOpenFileW(lpwfs, req->lpszFilename,
req->dwAccess, req->dwFlags, req->dwContext);
heap_free(req->lpszFilename);
FTP_FtpOpenFileW(session, task->file_name, task->access, task->flags, task->context);
heap_free(task->file_name);
}
/***********************************************************************
@ -1523,19 +1527,16 @@ HINTERNET WINAPI FtpOpenFileW(HINTERNET hFtpSession,
hIC = lpwfs->lpAppInfo;
if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
{
WORKREQUEST workRequest;
struct WORKREQ_FTPOPENFILEW *req;
open_file_task_t *task;
workRequest.asyncproc = AsyncFtpOpenFileProc;
workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
req = &workRequest.u.FtpOpenFileW;
req->lpszFilename = heap_strdupW(lpszFileName);
req->dwAccess = fdwAccess;
req->dwFlags = dwFlags;
req->dwContext = dwContext;
task = alloc_async_task(&lpwfs->hdr, AsyncFtpOpenFileProc, sizeof(*task));
task->file_name = heap_strdupW(lpszFileName);
task->access = fdwAccess;
task->flags = dwFlags;
task->context = dwContext;
INTERNET_AsyncCall(&workRequest);
r = NULL;
INTERNET_AsyncCall(&task->hdr);
r = NULL;
}
else
{
@ -1576,19 +1577,27 @@ BOOL WINAPI FtpGetFileA(HINTERNET hInternet, LPCSTR lpszRemoteFile, LPCSTR lpszN
return ret;
}
typedef struct {
task_header_t hdr;
WCHAR *remote_file;
WCHAR *new_file;
BOOL fail_if_exists;
DWORD local_attr;
DWORD flags;
DWORD_PTR context;
} get_file_task_t;
static void AsyncFtpGetFileProc(WORKREQUEST *workRequest)
static void AsyncFtpGetFileProc(task_header_t *hdr)
{
struct WORKREQ_FTPGETFILEW const *req = &workRequest->u.FtpGetFileW;
ftp_session_t *lpwfs = (ftp_session_t*) workRequest->hdr;
get_file_task_t *task = (get_file_task_t*)hdr;
ftp_session_t *session = (ftp_session_t*)task->hdr.hdr;
TRACE("%p\n", lpwfs);
TRACE("%p\n", session);
FTP_FtpGetFileW(lpwfs, req->lpszRemoteFile,
req->lpszNewFile, req->fFailIfExists,
req->dwLocalFlagsAttribute, req->dwFlags, req->dwContext);
heap_free(req->lpszRemoteFile);
heap_free(req->lpszNewFile);
FTP_FtpGetFileW(session, task->remote_file, task->new_file, task->fail_if_exists,
task->local_attr, task->flags, task->context);
heap_free(task->remote_file);
heap_free(task->new_file);
}
@ -1644,20 +1653,17 @@ BOOL WINAPI FtpGetFileW(HINTERNET hInternet, LPCWSTR lpszRemoteFile, LPCWSTR lps
hIC = lpwfs->lpAppInfo;
if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
{
WORKREQUEST workRequest;
struct WORKREQ_FTPGETFILEW *req;
get_file_task_t *task;
workRequest.asyncproc = AsyncFtpGetFileProc;
workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
req = &workRequest.u.FtpGetFileW;
req->lpszRemoteFile = heap_strdupW(lpszRemoteFile);
req->lpszNewFile = heap_strdupW(lpszNewFile);
req->dwLocalFlagsAttribute = dwLocalFlagsAttribute;
req->fFailIfExists = fFailIfExists;
req->dwFlags = dwInternetFlags;
req->dwContext = dwContext;
task = alloc_async_task(&lpwfs->hdr, AsyncFtpGetFileProc, sizeof(*task));
task->remote_file = heap_strdupW(lpszRemoteFile);
task->new_file = heap_strdupW(lpszNewFile);
task->local_attr = dwLocalFlagsAttribute;
task->fail_if_exists = fFailIfExists;
task->flags = dwInternetFlags;
task->context = dwContext;
r = res_to_le(INTERNET_AsyncCall(&workRequest));
r = res_to_le(INTERNET_AsyncCall(&task->hdr));
}
else
{
@ -1783,15 +1789,20 @@ BOOL WINAPI FtpDeleteFileA(HINTERNET hFtpSession, LPCSTR lpszFileName)
return ret;
}
static void AsyncFtpDeleteFileProc(WORKREQUEST *workRequest)
typedef struct {
task_header_t hdr;
WCHAR *file_name;
} delete_file_task_t;
static void AsyncFtpDeleteFileProc(task_header_t *hdr)
{
struct WORKREQ_FTPDELETEFILEW const *req = &workRequest->u.FtpDeleteFileW;
ftp_session_t *lpwfs = (ftp_session_t*) workRequest->hdr;
delete_file_task_t *task = (delete_file_task_t*)hdr;
ftp_session_t *session = (ftp_session_t*)task->hdr.hdr;
TRACE("%p\n", lpwfs);
TRACE("%p\n", session);
FTP_FtpDeleteFileW(lpwfs, req->lpszFilename);
heap_free(req->lpszFilename);
FTP_FtpDeleteFileW(session, task->file_name);
heap_free(task->file_name);
}
/***********************************************************************
@ -1838,15 +1849,12 @@ BOOL WINAPI FtpDeleteFileW(HINTERNET hFtpSession, LPCWSTR lpszFileName)
hIC = lpwfs->lpAppInfo;
if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
{
WORKREQUEST workRequest;
struct WORKREQ_FTPDELETEFILEW *req;
delete_file_task_t *task;
workRequest.asyncproc = AsyncFtpDeleteFileProc;
workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
req = &workRequest.u.FtpDeleteFileW;
req->lpszFilename = heap_strdupW(lpszFileName);
task = alloc_async_task(&lpwfs->hdr, AsyncFtpDeleteFileProc, sizeof(*task));
task->file_name = heap_strdupW(lpszFileName);
r = res_to_le(INTERNET_AsyncCall(&workRequest));
r = res_to_le(INTERNET_AsyncCall(&task->hdr));
}
else
{
@ -1928,15 +1936,15 @@ BOOL WINAPI FtpRemoveDirectoryA(HINTERNET hFtpSession, LPCSTR lpszDirectory)
return ret;
}
static void AsyncFtpRemoveDirectoryProc(WORKREQUEST *workRequest)
static void AsyncFtpRemoveDirectoryProc(task_header_t *hdr)
{
struct WORKREQ_FTPREMOVEDIRECTORYW const *req = &workRequest->u.FtpRemoveDirectoryW;
ftp_session_t *lpwfs = (ftp_session_t*) workRequest->hdr;
directory_task_t *task = (directory_task_t*)hdr;
ftp_session_t *session = (ftp_session_t*)task->hdr.hdr;
TRACE("%p\n", lpwfs);
TRACE("%p\n", session);
FTP_FtpRemoveDirectoryW(lpwfs, req->lpszDirectory);
heap_free(req->lpszDirectory);
FTP_FtpRemoveDirectoryW(session, task->directory);
heap_free(task->directory);
}
/***********************************************************************
@ -1983,15 +1991,12 @@ BOOL WINAPI FtpRemoveDirectoryW(HINTERNET hFtpSession, LPCWSTR lpszDirectory)
hIC = lpwfs->lpAppInfo;
if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
{
WORKREQUEST workRequest;
struct WORKREQ_FTPREMOVEDIRECTORYW *req;
directory_task_t *task;
workRequest.asyncproc = AsyncFtpRemoveDirectoryProc;
workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
req = &workRequest.u.FtpRemoveDirectoryW;
req->lpszDirectory = heap_strdupW(lpszDirectory);
task = alloc_async_task(&lpwfs->hdr, AsyncFtpRemoveDirectoryProc, sizeof(*task));
task->directory = heap_strdupW(lpszDirectory);
r = res_to_le(INTERNET_AsyncCall(&workRequest));
r = res_to_le(INTERNET_AsyncCall(&task->hdr));
}
else
{
@ -2077,16 +2082,22 @@ BOOL WINAPI FtpRenameFileA(HINTERNET hFtpSession, LPCSTR lpszSrc, LPCSTR lpszDes
return ret;
}
static void AsyncFtpRenameFileProc(WORKREQUEST *workRequest)
typedef struct {
task_header_t hdr;
WCHAR *src_file;
WCHAR *dst_file;
} rename_file_task_t;
static void AsyncFtpRenameFileProc(task_header_t *hdr)
{
struct WORKREQ_FTPRENAMEFILEW const *req = &workRequest->u.FtpRenameFileW;
ftp_session_t *lpwfs = (ftp_session_t*) workRequest->hdr;
rename_file_task_t *task = (rename_file_task_t*)hdr;
ftp_session_t *session = (ftp_session_t*)task->hdr.hdr;
TRACE("%p\n", lpwfs);
TRACE("%p\n", session);
FTP_FtpRenameFileW(lpwfs, req->lpszSrcFile, req->lpszDestFile);
heap_free(req->lpszSrcFile);
heap_free(req->lpszDestFile);
FTP_FtpRenameFileW(session, task->src_file, task->dst_file);
heap_free(task->src_file);
heap_free(task->dst_file);
}
/***********************************************************************
@ -2133,16 +2144,13 @@ BOOL WINAPI FtpRenameFileW(HINTERNET hFtpSession, LPCWSTR lpszSrc, LPCWSTR lpszD
hIC = lpwfs->lpAppInfo;
if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
{
WORKREQUEST workRequest;
struct WORKREQ_FTPRENAMEFILEW *req;
rename_file_task_t *task;
workRequest.asyncproc = AsyncFtpRenameFileProc;
workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
req = &workRequest.u.FtpRenameFileW;
req->lpszSrcFile = heap_strdupW(lpszSrc);
req->lpszDestFile = heap_strdupW(lpszDest);
task = alloc_async_task(&lpwfs->hdr, AsyncFtpRenameFileProc, sizeof(*task));
task->src_file = heap_strdupW(lpszSrc);
task->dst_file = heap_strdupW(lpszDest);
r = res_to_le(INTERNET_AsyncCall(&workRequest));
r = res_to_le(INTERNET_AsyncCall(&task->hdr));
}
else
{
@ -3428,11 +3436,16 @@ static DWORD FTPFINDNEXT_FindNextFileProc(WININETFTPFINDNEXTW *find, LPVOID data
return res;
}
static void FTPFINDNEXT_AsyncFindNextFileProc(WORKREQUEST *workRequest)
{
struct WORKREQ_FTPFINDNEXTW *req = &workRequest->u.FtpFindNextW;
typedef struct {
task_header_t hdr;
WIN32_FIND_DATAW *find_data;
} find_next_task_t;
FTPFINDNEXT_FindNextFileProc((WININETFTPFINDNEXTW*)workRequest->hdr, req->lpFindFileData);
static void FTPFINDNEXT_AsyncFindNextFileProc(task_header_t *hdr)
{
find_next_task_t *task = (find_next_task_t*)hdr;
FTPFINDNEXT_FindNextFileProc((WININETFTPFINDNEXTW*)task->hdr.hdr, task->find_data);
}
static DWORD FTPFINDNEXT_QueryOption(object_header_t *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
@ -3458,16 +3471,12 @@ static DWORD FTPFINDNEXT_FindNextFileW(object_header_t *hdr, void *data)
if (find->lpFtpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC)
{
WORKREQUEST workRequest;
struct WORKREQ_FTPFINDNEXTW *req;
find_next_task_t *task;
workRequest.asyncproc = FTPFINDNEXT_AsyncFindNextFileProc;
workRequest.hdr = WININET_AddRef( &find->hdr );
req = &workRequest.u.FtpFindNextW;
req->lpFindFileData = data;
INTERNET_AsyncCall(&workRequest);
task = alloc_async_task(&find->hdr, FTPFINDNEXT_AsyncFindNextFileProc, sizeof(*task));
task->find_data = data;
INTERNET_AsyncCall(&task->hdr);
return ERROR_SUCCESS;
}
@ -3483,7 +3492,6 @@ static const object_vtbl_t FTPFINDNEXTVtbl = {
NULL,
NULL,
NULL,
NULL,
FTPFINDNEXT_FindNextFileW
};

File diff suppressed because it is too large Load diff

View file

@ -113,6 +113,7 @@ typedef struct
} proxyinfo_t;
static ULONG max_conns = 2, max_1_0_conns = 4;
static ULONG connect_timeout = 60000;
static const WCHAR szInternetSettings[] =
{ 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
@ -314,9 +315,10 @@ BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
break;
case DLL_PROCESS_DETACH:
collect_connections(TRUE);
collect_connections(COLLECT_CLEANUP);
NETCON_unload();
URLCacheContainers_DeleteAll();
free_urlcache();
free_cookie();
if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
{
@ -431,11 +433,11 @@ BOOL INTERNET_FindProxyForProtocol(LPCWSTR szProxy, LPCWSTR proto, WCHAR *foundP
/* It wasn't found: look for no protocol */
for (ptr = szProxy; !ret && ptr && *ptr; )
{
LPCWSTR end, equal;
LPCWSTR end;
if (!(end = strchrW(ptr, ' ')))
end = ptr + strlenW(ptr);
if (!(equal = strchrW(ptr, '=')))
if (!strchrW(ptr, '='))
{
if (end - ptr + 1 > *foundProxyLen)
{
@ -825,7 +827,7 @@ static DWORD APPINFO_QueryOption(object_header_t *hdr, DWORD option, void *buffe
proxyBytesRequired = (lstrlenW(ai->proxy) + 1) * sizeof(WCHAR);
if (ai->proxyBypass)
proxyBypassBytesRequired = (lstrlenW(ai->proxyBypass) + 1) * sizeof(WCHAR);
if (*size < sizeof(INTERNET_PROXY_INFOW) + proxyBytesRequired + proxyBypassBytesRequired)
if (!pi || *size < sizeof(INTERNET_PROXY_INFOW) + proxyBytesRequired + proxyBypassBytesRequired)
{
*size = sizeof(INTERNET_PROXY_INFOW) + proxyBytesRequired + proxyBypassBytesRequired;
return ERROR_INSUFFICIENT_BUFFER;
@ -858,7 +860,7 @@ static DWORD APPINFO_QueryOption(object_header_t *hdr, DWORD option, void *buffe
if (ai->proxyBypass)
proxyBypassBytesRequired = WideCharToMultiByte(CP_ACP, 0, ai->proxyBypass, -1,
NULL, 0, NULL, NULL);
if (*size < sizeof(INTERNET_PROXY_INFOA) + proxyBytesRequired + proxyBypassBytesRequired)
if (!pi || *size < sizeof(INTERNET_PROXY_INFOA) + proxyBytesRequired + proxyBypassBytesRequired)
{
*size = sizeof(INTERNET_PROXY_INFOA) + proxyBytesRequired + proxyBypassBytesRequired;
return ERROR_INSUFFICIENT_BUFFER;
@ -883,17 +885,51 @@ static DWORD APPINFO_QueryOption(object_header_t *hdr, DWORD option, void *buffe
*size = sizeof(INTERNET_PROXY_INFOA) + proxyBytesRequired + proxyBypassBytesRequired;
return ERROR_SUCCESS;
}
case INTERNET_OPTION_CONNECT_TIMEOUT:
TRACE("INTERNET_OPTION_CONNECT_TIMEOUT\n");
if (*size < sizeof(ULONG))
return ERROR_INSUFFICIENT_BUFFER;
*(ULONG*)buffer = ai->connect_timeout;
*size = sizeof(ULONG);
return ERROR_SUCCESS;
}
return INET_QueryOption(hdr, option, buffer, size, unicode);
}
static DWORD APPINFO_SetOption(object_header_t *hdr, DWORD option, void *buf, DWORD size)
{
appinfo_t *ai = (appinfo_t*)hdr;
switch(option) {
case INTERNET_OPTION_CONNECT_TIMEOUT:
TRACE("INTERNET_OPTION_CONNECT_TIMEOUT\n");
if(size != sizeof(connect_timeout))
return ERROR_INTERNET_BAD_OPTION_LENGTH;
if(!*(ULONG*)buf)
return ERROR_BAD_ARGUMENTS;
ai->connect_timeout = *(ULONG*)buf;
return ERROR_SUCCESS;
case INTERNET_OPTION_USER_AGENT:
heap_free(ai->agent);
if (!(ai->agent = heap_strdupW(buf))) return ERROR_OUTOFMEMORY;
return ERROR_SUCCESS;
}
return INET_SetOption(hdr, option, buf, size);
}
static const object_vtbl_t APPINFOVtbl = {
APPINFO_Destroy,
NULL,
APPINFO_QueryOption,
INET_SetOption,
NULL,
APPINFO_SetOption,
NULL,
NULL,
NULL,
@ -960,6 +996,7 @@ HINTERNET WINAPI InternetOpenW(LPCWSTR lpszAgent, DWORD dwAccessType,
lpwai->accessType = dwAccessType;
lpwai->proxyUsername = NULL;
lpwai->proxyPassword = NULL;
lpwai->connect_timeout = connect_timeout;
lpwai->agent = heap_strdupW(lpszAgent);
if(dwAccessType == INTERNET_OPEN_TYPE_PRECONFIG)
@ -1191,7 +1228,7 @@ HINTERNET WINAPI InternetConnectW(HINTERNET hInternet,
HINTERNET rc = NULL;
DWORD res = ERROR_SUCCESS;
TRACE("(%p, %s, %i, %s, %s, %i, %i, %lx)\n", hInternet, debugstr_w(lpszServerName),
TRACE("(%p, %s, %i, %s, %s, %i, %x, %lx)\n", hInternet, debugstr_w(lpszServerName),
nServerPort, debugstr_w(lpszUserName), debugstr_w(lpszPassword),
dwService, dwFlags, dwContext);
@ -1621,9 +1658,9 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR
*
*/
LPCWSTR lpszParam = NULL;
BOOL bIsAbsolute = FALSE;
BOOL found_colon = FALSE;
LPCWSTR lpszap, lpszUrl = lpszUrl_orig;
LPCWSTR lpszcp = NULL;
LPCWSTR lpszcp = NULL, lpszNetLoc;
LPWSTR lpszUrl_decode = NULL;
DWORD dwUrlLength = dwUrlLength_orig;
@ -1673,9 +1710,9 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR
lpszap++;
continue;
}
if ((*lpszap == ':') && (lpszap - lpszUrl >= 2))
if (*lpszap == ':')
{
bIsAbsolute = TRUE;
found_colon = TRUE;
lpszcp = lpszap;
}
else
@ -1686,155 +1723,147 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR
break;
}
if(!found_colon){
SetLastError(ERROR_INTERNET_UNRECOGNIZED_SCHEME);
return 0;
}
lpUC->nScheme = INTERNET_SCHEME_UNKNOWN;
lpUC->nPort = INTERNET_INVALID_PORT_NUMBER;
/* Parse <params> */
lpszParam = memchrW(lpszap, ';', dwUrlLength - (lpszap - lpszUrl));
if(!lpszParam)
lpszParam = memchrW(lpszap, '?', dwUrlLength - (lpszap - lpszUrl));
lpszParam = memchrW(lpszap, '?', dwUrlLength - (lpszap - lpszUrl));
if(!lpszParam)
lpszParam = memchrW(lpszap, '#', dwUrlLength - (lpszap - lpszUrl));
SetUrlComponentValueW(&lpUC->lpszExtraInfo, &lpUC->dwExtraInfoLength,
lpszParam, lpszParam ? dwUrlLength-(lpszParam-lpszUrl) : 0);
if (bIsAbsolute) /* Parse <protocol>:[//<net_loc>] */
/* Get scheme first. */
lpUC->nScheme = GetInternetSchemeW(lpszUrl, lpszcp - lpszUrl);
SetUrlComponentValueW(&lpUC->lpszScheme, &lpUC->dwSchemeLength,
lpszUrl, lpszcp - lpszUrl);
/* Eat ':' in protocol. */
lpszcp++;
/* double slash indicates the net_loc portion is present */
if ((lpszcp[0] == '/') && (lpszcp[1] == '/'))
{
LPCWSTR lpszNetLoc;
lpszcp += 2;
/* Get scheme first. */
lpUC->nScheme = GetInternetSchemeW(lpszUrl, lpszcp - lpszUrl);
SetUrlComponentValueW(&lpUC->lpszScheme, &lpUC->dwSchemeLength,
lpszUrl, lpszcp - lpszUrl);
/* Eat ':' in protocol. */
lpszcp++;
/* double slash indicates the net_loc portion is present */
if ((lpszcp[0] == '/') && (lpszcp[1] == '/'))
lpszNetLoc = memchrW(lpszcp, '/', dwUrlLength - (lpszcp - lpszUrl));
if (lpszParam)
{
lpszcp += 2;
lpszNetLoc = memchrW(lpszcp, '/', dwUrlLength - (lpszcp - lpszUrl));
if (lpszParam)
{
if (lpszNetLoc)
lpszNetLoc = min(lpszNetLoc, lpszParam);
else
lpszNetLoc = lpszParam;
}
else if (!lpszNetLoc)
lpszNetLoc = lpszcp + dwUrlLength-(lpszcp-lpszUrl);
/* Parse net-loc */
if (lpszNetLoc)
lpszNetLoc = min(lpszNetLoc, lpszParam);
else
lpszNetLoc = lpszParam;
}
else if (!lpszNetLoc)
lpszNetLoc = lpszcp + dwUrlLength-(lpszcp-lpszUrl);
/* Parse net-loc */
if (lpszNetLoc)
{
LPCWSTR lpszHost;
LPCWSTR lpszPort;
/* [<user>[<:password>]@]<host>[:<port>] */
/* First find the user and password if they exist */
lpszHost = memchrW(lpszcp, '@', dwUrlLength - (lpszcp - lpszUrl));
if (lpszHost == NULL || lpszHost > lpszNetLoc)
{
LPCWSTR lpszHost;
LPCWSTR lpszPort;
/* username and password not specified. */
SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0);
SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0);
}
else /* Parse out username and password */
{
LPCWSTR lpszUser = lpszcp;
LPCWSTR lpszPasswd = lpszHost;
/* [<user>[<:password>]@]<host>[:<port>] */
/* First find the user and password if they exist */
lpszHost = memchrW(lpszcp, '@', dwUrlLength - (lpszcp - lpszUrl));
if (lpszHost == NULL || lpszHost > lpszNetLoc)
while (lpszcp < lpszHost)
{
/* username and password not specified. */
SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0);
SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0);
}
else /* Parse out username and password */
{
LPCWSTR lpszUser = lpszcp;
LPCWSTR lpszPasswd = lpszHost;
if (*lpszcp == ':')
lpszPasswd = lpszcp;
while (lpszcp < lpszHost)
{
if (*lpszcp == ':')
lpszPasswd = lpszcp;
lpszcp++;
}
SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength,
lpszUser, lpszPasswd - lpszUser);
if (lpszPasswd != lpszHost)
lpszPasswd++;
SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength,
lpszPasswd == lpszHost ? NULL : lpszPasswd,
lpszHost - lpszPasswd);
lpszcp++; /* Advance to beginning of host */
lpszcp++;
}
/* Parse <host><:port> */
SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength,
lpszUser, lpszPasswd - lpszUser);
lpszHost = lpszcp;
lpszPort = lpszNetLoc;
if (lpszPasswd != lpszHost)
lpszPasswd++;
SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength,
lpszPasswd == lpszHost ? NULL : lpszPasswd,
lpszHost - lpszPasswd);
/* special case for res:// URLs: there is no port here, so the host is the
entire string up to the first '/' */
if(lpUC->nScheme==INTERNET_SCHEME_RES)
lpszcp++; /* Advance to beginning of host */
}
/* Parse <host><:port> */
lpszHost = lpszcp;
lpszPort = lpszNetLoc;
/* special case for res:// URLs: there is no port here, so the host is the
entire string up to the first '/' */
if(lpUC->nScheme==INTERNET_SCHEME_RES)
{
SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
lpszHost, lpszPort - lpszHost);
lpszcp=lpszNetLoc;
}
else
{
while (lpszcp < lpszNetLoc)
{
if (*lpszcp == ':')
lpszPort = lpszcp;
lpszcp++;
}
/* If the scheme is "file" and the host is just one letter, it's not a host */
if(lpUC->nScheme==INTERNET_SCHEME_FILE && lpszPort <= lpszHost+1)
{
lpszcp=lpszHost;
SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
NULL, 0);
}
else
{
SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
lpszHost, lpszPort - lpszHost);
lpszcp=lpszNetLoc;
}
else
{
while (lpszcp < lpszNetLoc)
if (lpszPort != lpszNetLoc)
lpUC->nPort = atoiW(++lpszPort);
else switch (lpUC->nScheme)
{
if (*lpszcp == ':')
lpszPort = lpszcp;
lpszcp++;
}
/* If the scheme is "file" and the host is just one letter, it's not a host */
if(lpUC->nScheme==INTERNET_SCHEME_FILE && lpszPort <= lpszHost+1)
{
lpszcp=lpszHost;
SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
NULL, 0);
}
else
{
SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
lpszHost, lpszPort - lpszHost);
if (lpszPort != lpszNetLoc)
lpUC->nPort = atoiW(++lpszPort);
else switch (lpUC->nScheme)
{
case INTERNET_SCHEME_HTTP:
lpUC->nPort = INTERNET_DEFAULT_HTTP_PORT;
break;
case INTERNET_SCHEME_HTTPS:
lpUC->nPort = INTERNET_DEFAULT_HTTPS_PORT;
break;
case INTERNET_SCHEME_FTP:
lpUC->nPort = INTERNET_DEFAULT_FTP_PORT;
break;
case INTERNET_SCHEME_GOPHER:
lpUC->nPort = INTERNET_DEFAULT_GOPHER_PORT;
break;
default:
break;
}
case INTERNET_SCHEME_HTTP:
lpUC->nPort = INTERNET_DEFAULT_HTTP_PORT;
break;
case INTERNET_SCHEME_HTTPS:
lpUC->nPort = INTERNET_DEFAULT_HTTPS_PORT;
break;
case INTERNET_SCHEME_FTP:
lpUC->nPort = INTERNET_DEFAULT_FTP_PORT;
break;
case INTERNET_SCHEME_GOPHER:
lpUC->nPort = INTERNET_DEFAULT_GOPHER_PORT;
break;
default:
break;
}
}
}
}
else
{
SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0);
SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0);
SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength, NULL, 0);
}
}
else
{
SetUrlComponentValueW(&lpUC->lpszScheme, &lpUC->dwSchemeLength, NULL, 0);
SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0);
SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0);
SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength, NULL, 0);
@ -1940,6 +1969,32 @@ DWORD WINAPI InternetAttemptConnect(DWORD dwReserved)
}
/***********************************************************************
* convert_url_canonicalization_flags
*
* Helper for InternetCanonicalizeUrl
*
* PARAMS
* dwFlags [I] Flags suitable for InternetCanonicalizeUrl
*
* RETURNS
* Flags suitable for UrlCanonicalize
*/
static DWORD convert_url_canonicalization_flags(DWORD dwFlags)
{
DWORD dwUrlFlags = URL_WININET_COMPATIBILITY | URL_ESCAPE_UNSAFE;
if (dwFlags & ICU_BROWSER_MODE) dwUrlFlags |= URL_BROWSER_MODE;
if (dwFlags & ICU_DECODE) dwUrlFlags |= URL_UNESCAPE;
if (dwFlags & ICU_ENCODE_PERCENT) dwUrlFlags |= URL_ESCAPE_PERCENT;
if (dwFlags & ICU_ENCODE_SPACES_ONLY) dwUrlFlags |= URL_ESCAPE_SPACES_ONLY;
/* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
if (dwFlags & ICU_NO_ENCODE) dwUrlFlags ^= URL_ESCAPE_UNSAFE;
if (dwFlags & ICU_NO_META) dwUrlFlags |= URL_NO_META;
return dwUrlFlags;
}
/***********************************************************************
* InternetCanonicalizeUrlA (WININET.@)
*
@ -1954,43 +2009,16 @@ BOOL WINAPI InternetCanonicalizeUrlA(LPCSTR lpszUrl, LPSTR lpszBuffer,
LPDWORD lpdwBufferLength, DWORD dwFlags)
{
HRESULT hr;
DWORD dwURLFlags = URL_WININET_COMPATIBILITY | URL_ESCAPE_UNSAFE;
TRACE("(%s, %p, %p, 0x%08x) bufferlength: %d\n", debugstr_a(lpszUrl), lpszBuffer,
lpdwBufferLength, dwFlags, lpdwBufferLength ? *lpdwBufferLength : -1);
if(dwFlags & ICU_DECODE)
{
dwURLFlags |= URL_UNESCAPE;
dwFlags &= ~ICU_DECODE;
}
if(dwFlags & ICU_ESCAPE)
{
dwURLFlags |= URL_UNESCAPE;
dwFlags &= ~ICU_ESCAPE;
}
if(dwFlags & ICU_BROWSER_MODE)
{
dwURLFlags |= URL_BROWSER_MODE;
dwFlags &= ~ICU_BROWSER_MODE;
}
if(dwFlags & ICU_NO_ENCODE)
{
/* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
dwURLFlags ^= URL_ESCAPE_UNSAFE;
dwFlags &= ~ICU_NO_ENCODE;
}
if (dwFlags) FIXME("Unhandled flags 0x%08x\n", dwFlags);
hr = UrlCanonicalizeA(lpszUrl, lpszBuffer, lpdwBufferLength, dwURLFlags);
dwFlags = convert_url_canonicalization_flags(dwFlags);
hr = UrlCanonicalizeA(lpszUrl, lpszBuffer, lpdwBufferLength, dwFlags);
if (hr == E_POINTER) SetLastError(ERROR_INSUFFICIENT_BUFFER);
if (hr == E_INVALIDARG) SetLastError(ERROR_INVALID_PARAMETER);
return (hr == S_OK) ? TRUE : FALSE;
return hr == S_OK;
}
/***********************************************************************
@ -2007,43 +2035,16 @@ BOOL WINAPI InternetCanonicalizeUrlW(LPCWSTR lpszUrl, LPWSTR lpszBuffer,
LPDWORD lpdwBufferLength, DWORD dwFlags)
{
HRESULT hr;
DWORD dwURLFlags = URL_WININET_COMPATIBILITY | URL_ESCAPE_UNSAFE;
TRACE("(%s, %p, %p, 0x%08x) bufferlength: %d\n", debugstr_w(lpszUrl), lpszBuffer,
lpdwBufferLength, dwFlags, lpdwBufferLength ? *lpdwBufferLength : -1);
if(dwFlags & ICU_DECODE)
{
dwURLFlags |= URL_UNESCAPE;
dwFlags &= ~ICU_DECODE;
}
if(dwFlags & ICU_ESCAPE)
{
dwURLFlags |= URL_UNESCAPE;
dwFlags &= ~ICU_ESCAPE;
}
if(dwFlags & ICU_BROWSER_MODE)
{
dwURLFlags |= URL_BROWSER_MODE;
dwFlags &= ~ICU_BROWSER_MODE;
}
if(dwFlags & ICU_NO_ENCODE)
{
/* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
dwURLFlags ^= URL_ESCAPE_UNSAFE;
dwFlags &= ~ICU_NO_ENCODE;
}
if (dwFlags) FIXME("Unhandled flags 0x%08x\n", dwFlags);
hr = UrlCanonicalizeW(lpszUrl, lpszBuffer, lpdwBufferLength, dwURLFlags);
dwFlags = convert_url_canonicalization_flags(dwFlags);
hr = UrlCanonicalizeW(lpszUrl, lpszBuffer, lpdwBufferLength, dwFlags);
if (hr == E_POINTER) SetLastError(ERROR_INSUFFICIENT_BUFFER);
if (hr == E_INVALIDARG) SetLastError(ERROR_INVALID_PARAMETER);
return (hr == S_OK) ? TRUE : FALSE;
return hr == S_OK;
}
/* #################################################### */
@ -2240,14 +2241,20 @@ BOOL WINAPI InternetReadFileExA(HINTERNET hFile, LPINTERNET_BUFFERSA lpBuffersOu
TRACE("(%p %p 0x%x 0x%lx)\n", hFile, lpBuffersOut, dwFlags, dwContext);
if (lpBuffersOut->dwStructSize != sizeof(*lpBuffersOut)) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
hdr = get_handle_object(hFile);
if (!hdr) {
INTERNET_SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if(hdr->vtbl->ReadFileExA)
res = hdr->vtbl->ReadFileExA(hdr, lpBuffersOut, dwFlags, dwContext);
if(hdr->vtbl->ReadFileEx)
res = hdr->vtbl->ReadFileEx(hdr, lpBuffersOut->lpvBuffer, lpBuffersOut->dwBufferLength,
&lpBuffersOut->dwBufferLength, dwFlags, dwContext);
WININET_Release(hdr);
@ -2272,14 +2279,20 @@ BOOL WINAPI InternetReadFileExW(HINTERNET hFile, LPINTERNET_BUFFERSW lpBuffer,
TRACE("(%p %p 0x%x 0x%lx)\n", hFile, lpBuffer, dwFlags, dwContext);
if (lpBuffer->dwStructSize != sizeof(*lpBuffer)) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
hdr = get_handle_object(hFile);
if (!hdr) {
INTERNET_SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if(hdr->vtbl->ReadFileExW)
res = hdr->vtbl->ReadFileExW(hdr, lpBuffer, dwFlags, dwContext);
if(hdr->vtbl->ReadFileEx)
res = hdr->vtbl->ReadFileEx(hdr, lpBuffer->lpvBuffer, lpBuffer->dwBufferLength, &lpBuffer->dwBufferLength,
dwFlags, dwContext);
WININET_Release(hdr);
@ -2296,17 +2309,6 @@ static DWORD query_global_option(DWORD option, void *buffer, DWORD *size, BOOL u
/* FIXME: This function currently handles more options than it should. Options requiring
* proper handles should be moved to proper functions */
switch(option) {
case INTERNET_OPTION_REQUEST_FLAGS:
TRACE("INTERNET_OPTION_REQUEST_FLAGS\n");
if (*size < sizeof(ULONG))
return ERROR_INSUFFICIENT_BUFFER;
*(ULONG*)buffer = 4;
*size = sizeof(ULONG);
return ERROR_SUCCESS;
case INTERNET_OPTION_HTTP_VERSION:
if (*size < sizeof(HTTP_VERSION_INFO))
return ERROR_INSUFFICIENT_BUFFER;
@ -2448,10 +2450,22 @@ static DWORD query_global_option(DWORD option, void *buffer, DWORD *size, BOOL u
return res;
}
case INTERNET_OPTION_REQUEST_FLAGS:
case INTERNET_OPTION_USER_AGENT:
*size = 0;
return ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
case INTERNET_OPTION_POLICY:
return ERROR_INVALID_PARAMETER;
case INTERNET_OPTION_CONNECT_TIMEOUT:
TRACE("INTERNET_OPTION_CONNECT_TIMEOUT\n");
if (*size < sizeof(ULONG))
return ERROR_INSUFFICIENT_BUFFER;
*(ULONG*)buffer = connect_timeout;
*size = sizeof(ULONG);
return ERROR_SUCCESS;
}
FIXME("Stub for %d\n", option);
@ -2476,6 +2490,11 @@ DWORD INET_QueryOption(object_header_t *hdr, DWORD option, void *buffer, DWORD *
*size = sizeof(DWORD_PTR);
return ERROR_SUCCESS;
case INTERNET_OPTION_REQUEST_FLAGS:
WARN("INTERNET_OPTION_REQUEST_FLAGS\n");
*size = sizeof(DWORD);
return ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
case INTERNET_OPTION_MAX_CONNS_PER_SERVER:
case INTERNET_OPTION_MAX_CONNS_PER_1_0_SERVER:
WARN("Called on global option %u\n", option);
@ -2595,6 +2614,22 @@ static DWORD set_global_option(DWORD option, void *buf, DWORD size)
max_1_0_conns = *(ULONG*)buf;
return ERROR_SUCCESS;
case INTERNET_OPTION_CONNECT_TIMEOUT:
TRACE("INTERNET_OPTION_CONNECT_TIMEOUT\n");
if(size != sizeof(connect_timeout))
return ERROR_INTERNET_BAD_OPTION_LENGTH;
if(!*(ULONG*)buf)
return ERROR_BAD_ARGUMENTS;
connect_timeout = *(ULONG*)buf;
return ERROR_SUCCESS;
case INTERNET_OPTION_SETTINGS_CHANGED:
FIXME("INTERNETOPTION_SETTINGS_CHANGED semi-stub\n");
collect_connections(COLLECT_CONNECTIONS);
return ERROR_SUCCESS;
}
return ERROR_INTERNET_INVALID_OPTION;
@ -2657,6 +2692,7 @@ BOOL WINAPI InternetSetOptionW(HINTERNET hInternet, DWORD dwOption,
SetLastError(ERROR_INTERNET_BAD_OPTION_LENGTH);
ret = FALSE;
} else
TRACE("INTERNET_OPTION_ERROR_MASK: %x\n", *(ULONG*)lpBuffer);
lpwhh->ErrorMask = *(ULONG*)lpBuffer;
}
break;
@ -2811,7 +2847,7 @@ BOOL WINAPI InternetSetOptionW(HINTERNET hInternet, DWORD dwOption,
case INTERNET_OPTION_PER_CONNECTION_OPTION: {
INTERNET_PER_CONN_OPTION_LISTW *con = lpBuffer;
LONG res;
int i;
unsigned int i;
proxyinfo_t pi;
INTERNET_LoadProxySettings(&pi);
@ -2925,7 +2961,7 @@ BOOL WINAPI InternetSetOptionA(HINTERNET hInternet, DWORD dwOption,
wbuffer, wlen );
break;
case INTERNET_OPTION_PER_CONNECTION_OPTION: {
int i;
unsigned int i;
INTERNET_PER_CONN_OPTION_LISTW *listW;
INTERNET_PER_CONN_OPTION_LISTA *listA = lpBuffer;
wlen = sizeof(INTERNET_PER_CONN_OPTION_LISTW);
@ -2994,7 +3030,7 @@ BOOL WINAPI InternetSetOptionA(HINTERNET hInternet, DWORD dwOption,
if (dwOption == INTERNET_OPTION_PER_CONNECTION_OPTION)
{
INTERNET_PER_CONN_OPTION_LISTW *list = wbuffer;
int i;
unsigned int i;
for (i = 0; i < list->dwOptionCount; ++i) {
INTERNET_PER_CONN_OPTIONW *opt = list->pOptions + i;
switch (opt->dwOption) {
@ -3472,17 +3508,25 @@ static HINTERNET INTERNET_InternetOpenUrlW(appinfo_t *hIC, LPCWSTR lpszUrl,
* RETURNS
* handle of connection or NULL on failure
*/
static void AsyncInternetOpenUrlProc(WORKREQUEST *workRequest)
typedef struct {
task_header_t hdr;
WCHAR *url;
WCHAR *headers;
DWORD headers_len;
DWORD flags;
DWORD_PTR context;
} open_url_task_t;
static void AsyncInternetOpenUrlProc(task_header_t *hdr)
{
struct WORKREQ_INTERNETOPENURLW const *req = &workRequest->u.InternetOpenUrlW;
appinfo_t *hIC = (appinfo_t*) workRequest->hdr;
open_url_task_t *task = (open_url_task_t*)hdr;
TRACE("%p\n", hIC);
TRACE("%p\n", task->hdr.hdr);
INTERNET_InternetOpenUrlW(hIC, req->lpszUrl,
req->lpszHeaders, req->dwHeadersLength, req->dwFlags, req->dwContext);
heap_free(req->lpszUrl);
heap_free(req->lpszHeaders);
INTERNET_InternetOpenUrlW((appinfo_t*)task->hdr.hdr, task->url, task->headers,
task->headers_len, task->flags, task->context);
heap_free(task->url);
heap_free(task->headers);
}
HINTERNET WINAPI InternetOpenUrlW(HINTERNET hInternet, LPCWSTR lpszUrl,
@ -3511,23 +3555,17 @@ HINTERNET WINAPI InternetOpenUrlW(HINTERNET hInternet, LPCWSTR lpszUrl,
}
if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) {
WORKREQUEST workRequest;
struct WORKREQ_INTERNETOPENURLW *req;
open_url_task_t *task;
workRequest.asyncproc = AsyncInternetOpenUrlProc;
workRequest.hdr = WININET_AddRef( &hIC->hdr );
req = &workRequest.u.InternetOpenUrlW;
req->lpszUrl = heap_strdupW(lpszUrl);
req->lpszHeaders = heap_strdupW(lpszHeaders);
req->dwHeadersLength = dwHeadersLength;
req->dwFlags = dwFlags;
req->dwContext = dwContext;
task = alloc_async_task(&hIC->hdr, AsyncInternetOpenUrlProc, sizeof(*task));
task->url = heap_strdupW(lpszUrl);
task->headers = heap_strdupW(lpszHeaders);
task->headers_len = dwHeadersLength;
task->flags = dwFlags;
task->context = dwContext;
INTERNET_AsyncCall(&workRequest);
/*
* This is from windows.
*/
SetLastError(ERROR_IO_PENDING);
INTERNET_AsyncCall(&task->hdr);
SetLastError(ERROR_IO_PENDING);
} else {
ret = INTERNET_InternetOpenUrlW(hIC, lpszUrl, lpszHeaders, dwHeadersLength, dwFlags, dwContext);
}
@ -3651,16 +3689,13 @@ DWORD INTERNET_GetLastError(void)
*/
static DWORD CALLBACK INTERNET_WorkerThreadFunc(LPVOID lpvParam)
{
LPWORKREQUEST lpRequest = lpvParam;
WORKREQUEST workRequest;
task_header_t *task = lpvParam;
TRACE("\n");
workRequest = *lpRequest;
heap_free(lpRequest);
workRequest.asyncproc(&workRequest);
WININET_Release( workRequest.hdr );
task->proc(task);
WININET_Release(task->hdr);
heap_free(task);
if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
{
@ -3670,6 +3705,18 @@ static DWORD CALLBACK INTERNET_WorkerThreadFunc(LPVOID lpvParam)
return TRUE;
}
void *alloc_async_task(object_header_t *hdr, async_task_proc_t proc, size_t size)
{
task_header_t *task;
task = heap_alloc(size);
if(!task)
return NULL;
task->hdr = WININET_AddRef(hdr);
task->proc = proc;
return task;
}
/***********************************************************************
* INTERNET_AsyncCall (internal)
@ -3679,23 +3726,16 @@ static DWORD CALLBACK INTERNET_WorkerThreadFunc(LPVOID lpvParam)
* RETURNS
*
*/
DWORD INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest)
DWORD INTERNET_AsyncCall(task_header_t *task)
{
BOOL bSuccess;
LPWORKREQUEST lpNewRequest;
TRACE("\n");
lpNewRequest = heap_alloc(sizeof(WORKREQUEST));
if (!lpNewRequest)
return ERROR_OUTOFMEMORY;
*lpNewRequest = *lpWorkRequest;
bSuccess = QueueUserWorkItem(INTERNET_WorkerThreadFunc, lpNewRequest, WT_EXECUTELONGFUNCTION);
bSuccess = QueueUserWorkItem(INTERNET_WorkerThreadFunc, task, WT_EXECUTELONGFUNCTION);
if (!bSuccess)
{
heap_free(lpNewRequest);
heap_free(task);
return ERROR_INTERNET_ASYNC_THREAD_FAILED;
}
return ERROR_SUCCESS;
@ -3797,13 +3837,13 @@ lend:
* data is available.
*/
BOOL WINAPI InternetQueryDataAvailable( HINTERNET hFile,
LPDWORD lpdwNumberOfBytesAvailble,
LPDWORD lpdwNumberOfBytesAvailable,
DWORD dwFlags, DWORD_PTR dwContext)
{
object_header_t *hdr;
DWORD res;
TRACE("(%p %p %x %lx)\n", hFile, lpdwNumberOfBytesAvailble, dwFlags, dwContext);
TRACE("(%p %p %x %lx)\n", hFile, lpdwNumberOfBytesAvailable, dwFlags, dwContext);
hdr = get_handle_object( hFile );
if (!hdr) {
@ -3812,7 +3852,7 @@ BOOL WINAPI InternetQueryDataAvailable( HINTERNET hFile,
}
if(hdr->vtbl->QueryDataAvailable) {
res = hdr->vtbl->QueryDataAvailable(hdr, lpdwNumberOfBytesAvailble, dwFlags, dwContext);
res = hdr->vtbl->QueryDataAvailable(hdr, lpdwNumberOfBytesAvailable, dwFlags, dwContext);
}else {
WARN("wrong handle\n");
res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
@ -4372,6 +4412,71 @@ DWORD WINAPI PrivacyGetZonePreferenceW( DWORD zone, DWORD type, LPDWORD template
return 0;
}
/***********************************************************************
* InternetGetSecurityInfoByURLA (WININET.@)
*/
BOOL WINAPI InternetGetSecurityInfoByURLA(LPSTR lpszURL, PCCERT_CHAIN_CONTEXT *ppCertChain, DWORD *pdwSecureFlags)
{
WCHAR *url;
BOOL res;
TRACE("(%s %p %p)\n", debugstr_a(lpszURL), ppCertChain, pdwSecureFlags);
url = heap_strdupAtoW(lpszURL);
if(!url)
return FALSE;
res = InternetGetSecurityInfoByURLW(url, ppCertChain, pdwSecureFlags);
heap_free(url);
return res;
}
/***********************************************************************
* InternetGetSecurityInfoByURLW (WININET.@)
*/
BOOL WINAPI InternetGetSecurityInfoByURLW(LPCWSTR lpszURL, PCCERT_CHAIN_CONTEXT *ppCertChain, DWORD *pdwSecureFlags)
{
WCHAR hostname[INTERNET_MAX_HOST_NAME_LENGTH];
URL_COMPONENTSW url = {sizeof(url)};
server_t *server;
BOOL res = FALSE;
TRACE("(%s %p %p)\n", debugstr_w(lpszURL), ppCertChain, pdwSecureFlags);
url.lpszHostName = hostname;
url.dwHostNameLength = sizeof(hostname)/sizeof(WCHAR);
res = InternetCrackUrlW(lpszURL, 0, 0, &url);
if(!res || url.nScheme != INTERNET_SCHEME_HTTPS) {
SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND);
return FALSE;
}
server = get_server(hostname, url.nPort, TRUE, FALSE);
if(!server) {
SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND);
return FALSE;
}
if(server->cert_chain) {
const CERT_CHAIN_CONTEXT *chain_dup;
chain_dup = CertDuplicateCertificateChain(server->cert_chain);
if(chain_dup) {
*ppCertChain = chain_dup;
*pdwSecureFlags = server->security_flags & _SECURITY_ERROR_FLAGS_MASK;
}else {
res = FALSE;
}
}else {
SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND);
res = FALSE;
}
server_release(server);
return res;
}
DWORD WINAPI InternetDialA( HWND hwndParent, LPSTR lpszConnectoid, DWORD dwFlags,
DWORD_PTR* lpdwConnection, DWORD dwReserved )
{

View file

@ -47,6 +47,8 @@
#define ioctlsocket ioctl
#endif /* __MINGW32__ */
#include <winineti.h>
extern HMODULE WININET_hModule DECLSPEC_HIDDEN;
#ifndef INET6_ADDRSTRLEN
@ -56,12 +58,19 @@ extern HMODULE WININET_hModule DECLSPEC_HIDDEN;
typedef struct {
WCHAR *name;
INTERNET_PORT port;
BOOL is_https;
struct sockaddr_storage addr;
socklen_t addr_len;
char addr_str[INET6_ADDRSTRLEN];
WCHAR *scheme_host_port;
const WCHAR *host_port;
const WCHAR *canon_host_port;
LONG ref;
DWORD64 keep_until;
DWORD security_flags;
const CERT_CHAIN_CONTEXT *cert_chain;
struct list entry;
struct list conn_pool;
@ -69,16 +78,23 @@ typedef struct {
void server_addref(server_t*) DECLSPEC_HIDDEN;
void server_release(server_t*) DECLSPEC_HIDDEN;
BOOL collect_connections(BOOL) DECLSPEC_HIDDEN;
typedef enum {
COLLECT_TIMEOUT,
COLLECT_CONNECTIONS,
COLLECT_CLEANUP
} collect_type_t;
BOOL collect_connections(collect_type_t) DECLSPEC_HIDDEN;
/* used for netconnection.c stuff */
typedef struct
{
BOOL useSSL;
int socketFD;
int socket;
BOOL secure;
void *ssl_s;
server_t *server;
DWORD security_flags;
BOOL mask_errors;
BOOL keep_alive;
DWORD64 keep_until;
@ -217,8 +233,7 @@ typedef struct {
DWORD (*QueryOption)(object_header_t*,DWORD,void*,DWORD*,BOOL);
DWORD (*SetOption)(object_header_t*,DWORD,void*,DWORD);
DWORD (*ReadFile)(object_header_t*,void*,DWORD,DWORD*);
DWORD (*ReadFileExA)(object_header_t*,INTERNET_BUFFERSA*,DWORD,DWORD_PTR);
DWORD (*ReadFileExW)(object_header_t*,INTERNET_BUFFERSW*,DWORD,DWORD_PTR);
DWORD (*ReadFileEx)(object_header_t*,void*,DWORD,DWORD*,DWORD,DWORD_PTR);
DWORD (*WriteFile)(object_header_t*,const void*,DWORD,DWORD*);
DWORD (*QueryDataAvailable)(object_header_t*,DWORD*,DWORD,DWORD_PTR);
DWORD (*FindNextFileW)(object_header_t*,void*);
@ -253,6 +268,7 @@ typedef struct
LPWSTR proxyUsername;
LPWSTR proxyPassword;
DWORD accessType;
DWORD connect_timeout;
} appinfo_t;
typedef struct
@ -260,11 +276,9 @@ typedef struct
object_header_t hdr;
appinfo_t *appInfo;
LPWSTR hostName; /* the final destination of the request */
LPWSTR serverName; /* the name of the server we directly connect to */
LPWSTR userName;
LPWSTR password;
INTERNET_PORT hostPort; /* the final destination port of the request */
INTERNET_PORT serverPort; /* the port of the server we directly connect to */
DWORD connect_timeout;
DWORD send_timeout;
DWORD receive_timeout;
@ -303,6 +317,8 @@ typedef struct
{
object_header_t hdr;
http_session_t *session;
server_t *server;
server_t *proxy;
LPWSTR path;
LPWSTR verb;
LPWSTR rawHeaders;
@ -338,149 +354,16 @@ typedef struct
netconn_stream_t netconn_stream;
} http_request_t;
typedef struct task_header_t task_header_t;
typedef void (*async_task_proc_t)(task_header_t*);
struct WORKREQ_FTPPUTFILEW
struct task_header_t
{
LPWSTR lpszLocalFile;
LPWSTR lpszNewRemoteFile;
DWORD dwFlags;
DWORD_PTR dwContext;
};
struct WORKREQ_FTPSETCURRENTDIRECTORYW
{
LPWSTR lpszDirectory;
};
struct WORKREQ_FTPCREATEDIRECTORYW
{
LPWSTR lpszDirectory;
};
struct WORKREQ_FTPFINDFIRSTFILEW
{
LPWSTR lpszSearchFile;
LPWIN32_FIND_DATAW lpFindFileData;
DWORD dwFlags;
DWORD_PTR dwContext;
};
struct WORKREQ_FTPGETCURRENTDIRECTORYW
{
LPWSTR lpszDirectory;
DWORD *lpdwDirectory;
};
struct WORKREQ_FTPOPENFILEW
{
LPWSTR lpszFilename;
DWORD dwAccess;
DWORD dwFlags;
DWORD_PTR dwContext;
};
struct WORKREQ_FTPGETFILEW
{
LPWSTR lpszRemoteFile;
LPWSTR lpszNewFile;
BOOL fFailIfExists;
DWORD dwLocalFlagsAttribute;
DWORD dwFlags;
DWORD_PTR dwContext;
};
struct WORKREQ_FTPDELETEFILEW
{
LPWSTR lpszFilename;
};
struct WORKREQ_FTPREMOVEDIRECTORYW
{
LPWSTR lpszDirectory;
};
struct WORKREQ_FTPRENAMEFILEW
{
LPWSTR lpszSrcFile;
LPWSTR lpszDestFile;
};
struct WORKREQ_FTPFINDNEXTW
{
LPWIN32_FIND_DATAW lpFindFileData;
};
struct WORKREQ_HTTPSENDREQUESTW
{
LPWSTR lpszHeader;
DWORD dwHeaderLength;
LPVOID lpOptional;
DWORD dwOptionalLength;
DWORD dwContentLength;
BOOL bEndRequest;
};
struct WORKREQ_HTTPENDREQUESTW
{
DWORD dwFlags;
DWORD_PTR dwContext;
};
struct WORKREQ_SENDCALLBACK
{
DWORD_PTR dwContext;
DWORD dwInternetStatus;
LPVOID lpvStatusInfo;
DWORD dwStatusInfoLength;
};
struct WORKREQ_INTERNETOPENURLW
{
HINTERNET hInternet;
LPWSTR lpszUrl;
LPWSTR lpszHeaders;
DWORD dwHeadersLength;
DWORD dwFlags;
DWORD_PTR dwContext;
};
struct WORKREQ_INTERNETREADFILEEXA
{
LPINTERNET_BUFFERSA lpBuffersOut;
};
struct WORKREQ_INTERNETREADFILEEXW
{
LPINTERNET_BUFFERSW lpBuffersOut;
};
typedef struct WORKREQ
{
void (*asyncproc)(struct WORKREQ*);
async_task_proc_t proc;
object_header_t *hdr;
};
union {
struct WORKREQ_FTPPUTFILEW FtpPutFileW;
struct WORKREQ_FTPSETCURRENTDIRECTORYW FtpSetCurrentDirectoryW;
struct WORKREQ_FTPCREATEDIRECTORYW FtpCreateDirectoryW;
struct WORKREQ_FTPFINDFIRSTFILEW FtpFindFirstFileW;
struct WORKREQ_FTPGETCURRENTDIRECTORYW FtpGetCurrentDirectoryW;
struct WORKREQ_FTPOPENFILEW FtpOpenFileW;
struct WORKREQ_FTPGETFILEW FtpGetFileW;
struct WORKREQ_FTPDELETEFILEW FtpDeleteFileW;
struct WORKREQ_FTPREMOVEDIRECTORYW FtpRemoveDirectoryW;
struct WORKREQ_FTPRENAMEFILEW FtpRenameFileW;
struct WORKREQ_FTPFINDNEXTW FtpFindNextW;
struct WORKREQ_HTTPSENDREQUESTW HttpSendRequestW;
struct WORKREQ_HTTPENDREQUESTW HttpEndRequestW;
struct WORKREQ_SENDCALLBACK SendCallback;
struct WORKREQ_INTERNETOPENURLW InternetOpenUrlW;
struct WORKREQ_INTERNETREADFILEEXA InternetReadFileExA;
struct WORKREQ_INTERNETREADFILEEXW InternetReadFileExW;
} u;
} WORKREQUEST, *LPWORKREQUEST;
void *alloc_async_task(object_header_t*,async_task_proc_t,size_t) DECLSPEC_HIDDEN;
void *alloc_object(object_header_t*,const object_vtbl_t*,size_t) DECLSPEC_HIDDEN;
object_header_t *get_handle_object( HINTERNET hinternet ) DECLSPEC_HIDDEN;
@ -505,12 +388,12 @@ DWORD HTTP_Connect(appinfo_t*,LPCWSTR,
BOOL GetAddress(LPCWSTR lpszServerName, INTERNET_PORT nServerPort,
struct sockaddr *psa, socklen_t *sa_len) DECLSPEC_HIDDEN;
BOOL get_cookie(const WCHAR*,const WCHAR*,WCHAR*,DWORD*) DECLSPEC_HIDDEN;
DWORD get_cookie(const WCHAR*,const WCHAR*,WCHAR*,DWORD*) DECLSPEC_HIDDEN;
BOOL set_cookie(const WCHAR*,const WCHAR*,const WCHAR*,const WCHAR*) DECLSPEC_HIDDEN;
void INTERNET_SetLastError(DWORD dwError) DECLSPEC_HIDDEN;
DWORD INTERNET_GetLastError(void) DECLSPEC_HIDDEN;
DWORD INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest) DECLSPEC_HIDDEN;
DWORD INTERNET_AsyncCall(task_header_t*) DECLSPEC_HIDDEN;
LPSTR INTERNET_GetResponseBuffer(void) DECLSPEC_HIDDEN;
LPSTR INTERNET_GetNextLine(INT nSocket, LPDWORD dwLen) DECLSPEC_HIDDEN;
@ -523,10 +406,10 @@ VOID INTERNET_SendCallback(object_header_t *hdr, DWORD_PTR dwContext,
DWORD dwStatusInfoLength) DECLSPEC_HIDDEN;
BOOL INTERNET_FindProxyForProtocol(LPCWSTR szProxy, LPCWSTR proto, WCHAR *foundProxy, DWORD *foundProxyLen) DECLSPEC_HIDDEN;
DWORD create_netconn(BOOL, server_t *, DWORD, DWORD, netconn_t **) DECLSPEC_HIDDEN;
DWORD create_netconn(BOOL,server_t*,DWORD,BOOL,DWORD,netconn_t**) DECLSPEC_HIDDEN;
void free_netconn(netconn_t*) DECLSPEC_HIDDEN;
void NETCON_unload(void) DECLSPEC_HIDDEN;
DWORD NETCON_secure_connect(netconn_t *connection) DECLSPEC_HIDDEN;
DWORD NETCON_secure_connect(netconn_t*,server_t*) DECLSPEC_HIDDEN;
DWORD NETCON_send(netconn_t *connection, const void *msg, size_t len, int flags,
int *sent /* out */) DECLSPEC_HIDDEN;
DWORD NETCON_recv(netconn_t *connection, void *buf, size_t len, int flags,
@ -561,8 +444,11 @@ static inline int unix_getsockopt(int socket, int level, int option_name, void *
#define getsockopt unix_getsockopt
#endif
extern void URLCacheContainers_CreateDefaults(void) DECLSPEC_HIDDEN;
extern void URLCacheContainers_DeleteAll(void) DECLSPEC_HIDDEN;
server_t *get_server(const WCHAR*,INTERNET_PORT,BOOL,BOOL);
BOOL init_urlcache(void) DECLSPEC_HIDDEN;
void free_urlcache(void) DECLSPEC_HIDDEN;
void free_cookie(void) DECLSPEC_HIDDEN;
#define MAX_REPLY_LEN 0x5B4
@ -573,4 +459,16 @@ typedef struct
const char* name;
} wininet_flag_info;
/* Undocumented security flags */
#define _SECURITY_FLAG_CERT_REV_FAILED 0x00800000
#define _SECURITY_FLAG_CERT_INVALID_CA 0x01000000
#define _SECURITY_FLAG_CERT_INVALID_CN 0x02000000
#define _SECURITY_FLAG_CERT_INVALID_DATE 0x04000000
#define _SECURITY_ERROR_FLAGS_MASK \
(_SECURITY_FLAG_CERT_REV_FAILED \
|_SECURITY_FLAG_CERT_INVALID_CA \
|_SECURITY_FLAG_CERT_INVALID_CN \
|_SECURITY_FLAG_CERT_INVALID_DATE)
#endif /* _WINE_INTERNET_H_ */

View file

@ -129,8 +129,10 @@ MAKE_FUNCPTR(SSL_load_error_strings);
MAKE_FUNCPTR(SSLv23_method);
MAKE_FUNCPTR(SSL_CTX_free);
MAKE_FUNCPTR(SSL_CTX_new);
MAKE_FUNCPTR(SSL_CTX_ctrl);
MAKE_FUNCPTR(SSL_new);
MAKE_FUNCPTR(SSL_free);
MAKE_FUNCPTR(SSL_ctrl);
MAKE_FUNCPTR(SSL_set_fd);
MAKE_FUNCPTR(SSL_connect);
MAKE_FUNCPTR(SSL_shutdown);
@ -218,95 +220,161 @@ static PCCERT_CONTEXT X509_to_cert_context(X509 *cert)
return ret;
}
static DWORD netconn_verify_cert(PCCERT_CONTEXT cert, HCERTSTORE store,
WCHAR *server, DWORD security_flags)
static DWORD netconn_verify_cert(netconn_t *conn, PCCERT_CONTEXT cert, HCERTSTORE store)
{
BOOL ret;
CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } };
PCCERT_CHAIN_CONTEXT chain;
char oid_server_auth[] = szOID_PKIX_KP_SERVER_AUTH;
char *server_auth[] = { oid_server_auth };
DWORD err = ERROR_SUCCESS, chainFlags = 0;
DWORD err = ERROR_SUCCESS, errors;
static const DWORD supportedErrors =
CERT_TRUST_IS_NOT_TIME_VALID |
CERT_TRUST_IS_UNTRUSTED_ROOT |
CERT_TRUST_IS_PARTIAL_CHAIN |
CERT_TRUST_IS_NOT_VALID_FOR_USAGE;
TRACE("verifying %s\n", debugstr_w(conn->server->name));
TRACE("verifying %s\n", debugstr_w(server));
chainPara.RequestedUsage.Usage.cUsageIdentifier = 1;
chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = server_auth;
if (!(security_flags & SECURITY_FLAG_IGNORE_REVOCATION))
chainFlags |= CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
if ((ret = CertGetCertificateChain(NULL, cert, NULL, store, &chainPara,
chainFlags, NULL, &chain)))
{
if (chain->TrustStatus.dwErrorStatus)
{
static const DWORD supportedErrors =
CERT_TRUST_IS_NOT_TIME_VALID |
CERT_TRUST_IS_UNTRUSTED_ROOT |
CERT_TRUST_IS_PARTIAL_CHAIN |
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 &&
!(security_flags & SECURITY_FLAG_IGNORE_CERT_DATE_INVALID))
err = ERROR_INTERNET_SEC_CERT_DATE_INVALID;
else if (chain->TrustStatus.dwErrorStatus &
(CERT_TRUST_IS_UNTRUSTED_ROOT | CERT_TRUST_IS_PARTIAL_CHAIN) &&
!(security_flags & SECURITY_FLAG_IGNORE_UNKNOWN_CA))
err = ERROR_INTERNET_INVALID_CA;
else if (!(security_flags & SECURITY_FLAG_IGNORE_REVOCATION) &&
((chain->TrustStatus.dwErrorStatus &
CERT_TRUST_IS_OFFLINE_REVOCATION) ||
(chain->TrustStatus.dwErrorStatus &
CERT_TRUST_REVOCATION_STATUS_UNKNOWN)))
err = ERROR_INTERNET_SEC_CERT_NO_REV;
else if (!(security_flags & SECURITY_FLAG_IGNORE_REVOCATION) &&
(chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_REVOKED))
err = ERROR_INTERNET_SEC_CERT_REVOKED;
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 if (chain->TrustStatus.dwErrorStatus & ~supportedErrors)
err = ERROR_INTERNET_SEC_INVALID_CERT;
}
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,
&chainCopy, &policyPara, &policyStatus);
/* Any error in the policy status indicates that the
* policy couldn't be verified.
*/
if (ret && policyStatus.dwError)
{
if (policyStatus.dwError == CERT_E_CN_NO_MATCH)
err = ERROR_INTERNET_SEC_CERT_CN_INVALID;
else
err = ERROR_INTERNET_SEC_INVALID_CERT;
}
}
CertFreeCertificateChain(chain);
if (!(ret = CertGetCertificateChain(NULL, cert, NULL, store, &chainPara, 0, NULL, &chain))) {
TRACE("failed\n");
return GetLastError();
}
TRACE("returning %08x\n", err);
return err;
errors = chain->TrustStatus.dwErrorStatus;
do {
/* This seems strange, but that's what tests show */
if(errors & CERT_TRUST_IS_PARTIAL_CHAIN) {
WARN("ERROR_INTERNET_SEC_CERT_REV_FAILED\n");
err = ERROR_INTERNET_SEC_CERT_REV_FAILED;
if(conn->mask_errors)
conn->security_flags |= _SECURITY_FLAG_CERT_REV_FAILED;
if(!(conn->security_flags & SECURITY_FLAG_IGNORE_REVOCATION))
break;
}
if (chain->TrustStatus.dwErrorStatus & ~supportedErrors) {
WARN("error status %x\n", chain->TrustStatus.dwErrorStatus & ~supportedErrors);
err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_SEC_INVALID_CERT;
errors &= supportedErrors;
if(!conn->mask_errors)
break;
WARN("unknown error flags\n");
}
if(errors & CERT_TRUST_IS_NOT_TIME_VALID) {
WARN("CERT_TRUST_IS_NOT_TIME_VALID\n");
if(!(conn->security_flags & SECURITY_FLAG_IGNORE_CERT_DATE_INVALID)) {
err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_SEC_CERT_DATE_INVALID;
if(!conn->mask_errors)
break;
conn->security_flags |= _SECURITY_FLAG_CERT_INVALID_DATE;
}
errors &= ~CERT_TRUST_IS_NOT_TIME_VALID;
}
if(errors & CERT_TRUST_IS_UNTRUSTED_ROOT) {
WARN("CERT_TRUST_IS_UNTRUSTED_ROOT\n");
if(!(conn->security_flags & SECURITY_FLAG_IGNORE_UNKNOWN_CA)) {
err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_INVALID_CA;
if(!conn->mask_errors)
break;
conn->security_flags |= _SECURITY_FLAG_CERT_INVALID_CA;
}
errors &= ~CERT_TRUST_IS_UNTRUSTED_ROOT;
}
if(errors & CERT_TRUST_IS_PARTIAL_CHAIN) {
WARN("CERT_TRUST_IS_PARTIAL_CHAIN\n");
if(!(conn->security_flags & SECURITY_FLAG_IGNORE_UNKNOWN_CA)) {
err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_INVALID_CA;
if(!conn->mask_errors)
break;
conn->security_flags |= _SECURITY_FLAG_CERT_INVALID_CA;
}
errors &= ~CERT_TRUST_IS_PARTIAL_CHAIN;
}
if(errors & CERT_TRUST_IS_NOT_VALID_FOR_USAGE) {
WARN("CERT_TRUST_IS_NOT_VALID_FOR_USAGE\n");
if(!(conn->security_flags & SECURITY_FLAG_IGNORE_WRONG_USAGE)) {
err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_SEC_INVALID_CERT;
if(!conn->mask_errors)
break;
WARN("CERT_TRUST_IS_NOT_VALID_FOR_USAGE, unknown error flags\n");
}
errors &= ~CERT_TRUST_IS_NOT_VALID_FOR_USAGE;
}
if(err == ERROR_INTERNET_SEC_CERT_REV_FAILED) {
assert(conn->security_flags & SECURITY_FLAG_IGNORE_REVOCATION);
err = ERROR_SUCCESS;
}
}while(0);
if(!err || conn->mask_errors) {
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 = conn->server->name;
sslExtraPolicyPara.fdwChecks = conn->security_flags;
policyPara.cbSize = sizeof(policyPara);
policyPara.dwFlags = 0;
policyPara.pvExtraPolicyPara = &sslExtraPolicyPara;
ret = CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL,
&chainCopy, &policyPara, &policyStatus);
/* Any error in the policy status indicates that the
* policy couldn't be verified.
*/
if(ret) {
if(policyStatus.dwError == CERT_E_CN_NO_MATCH) {
WARN("CERT_E_CN_NO_MATCH\n");
if(conn->mask_errors)
conn->security_flags |= _SECURITY_FLAG_CERT_INVALID_CN;
err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_SEC_CERT_CN_INVALID;
}else if(policyStatus.dwError) {
WARN("policyStatus.dwError %x\n", policyStatus.dwError);
if(conn->mask_errors)
WARN("unknown error flags for policy status %x\n", policyStatus.dwError);
err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_SEC_INVALID_CERT;
}
}else {
err = GetLastError();
}
}
if(err) {
WARN("failed %u\n", err);
CertFreeCertificateChain(chain);
if(conn->server->cert_chain) {
CertFreeCertificateChain(conn->server->cert_chain);
conn->server->cert_chain = NULL;
}
if(conn->mask_errors)
conn->server->security_flags |= conn->security_flags & _SECURITY_ERROR_FLAGS_MASK;
return err;
}
/* FIXME: Reuse cached chain */
if(conn->server->cert_chain)
CertFreeCertificateChain(chain);
else
conn->server->cert_chain = chain;
return ERROR_SUCCESS;
}
static int netconn_secure_verify(int preverify_ok, X509_STORE_CTX *ctx)
@ -343,8 +411,7 @@ static int netconn_secure_verify(int preverify_ok, X509_STORE_CTX *ctx)
if (!endCert) ret = FALSE;
if (ret)
{
DWORD_PTR err = netconn_verify_cert(endCert, store, conn->server->name,
conn->security_flags);
DWORD_PTR err = netconn_verify_cert(conn, endCert, store);
if (err)
{
@ -358,7 +425,49 @@ static int netconn_secure_verify(int preverify_ok, X509_STORE_CTX *ctx)
return ret;
}
static long get_tls_option(void) {
long tls_option = SSL_OP_NO_SSLv2; /* disable SSLv2 for security reason, secur32/Schannel(GnuTLS) don't support it */
#ifdef SSL_OP_NO_TLSv1_2
DWORD type, val, size;
HKEY hkey,tls12_client,tls11_client;
LONG res;
const WCHAR Schannel_Prot[] = { /* SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCANNEL\\Protocols */
'S','Y','S','T','E','M','\\',
'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
'C','o','n','t','r','o','l','\\',
'S','e','c','u','r','i','t','y','P','r','o','v','i','d','e','r','s','\\',
'S','C','H','A','N','N','E','L','\\',
'P','r','o','t','o','c','o','l','s',0 };
const WCHAR TLS12_Client[] = {'T','L','S',' ','1','.','2','\\','C','l','i','e','n','t',0};
const WCHAR TLS11_Client[] = {'T','L','S',' ','1','.','1','\\','C','l','i','e','n','t',0};
const WCHAR DisabledByDefault[] = {'D','i','s','a','b','l','e','d','B','y','D','e','f','a','u','l','t',0};
res = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
Schannel_Prot,
0, KEY_READ, &hkey);
if (res != ERROR_SUCCESS) { /* enabled TLSv1.1/1.2 when no registry entry */
return tls_option;
}
if (RegOpenKeyExW(hkey, TLS12_Client, 0, KEY_READ, &tls12_client) == ERROR_SUCCESS) {
size = sizeof(DWORD);
if (RegQueryValueExW(tls12_client, DisabledByDefault, NULL, &type, (LPBYTE) &val, &size) == ERROR_SUCCESS
&& type == REG_DWORD) {
tls_option |= val?SSL_OP_NO_TLSv1_2:0;
}
RegCloseKey(tls12_client);
}
if (RegOpenKeyExW(hkey, TLS11_Client, 0, KEY_READ, &tls11_client) == ERROR_SUCCESS) {
size = sizeof(DWORD);
if (RegQueryValueExW(tls11_client, DisabledByDefault, NULL, &type, (LPBYTE) &val, &size) == ERROR_SUCCESS
&& type == REG_DWORD) {
tls_option |= val?SSL_OP_NO_TLSv1_1:0;
}
RegCloseKey(tls11_client);
}
RegCloseKey(hkey);
#endif
return tls_option;
}
static CRITICAL_SECTION init_ssl_cs;
static CRITICAL_SECTION_DEBUG init_ssl_cs_debug =
@ -372,8 +481,8 @@ static CRITICAL_SECTION init_ssl_cs = { &init_ssl_cs_debug, -1, 0, 0, 0, 0 };
static DWORD init_openssl(void)
{
#if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
int i;
#ifdef SONAME_LIBCRYPTO
unsigned int i;
if(OpenSSL_ssl_handle)
return ERROR_SUCCESS;
@ -403,8 +512,10 @@ static DWORD init_openssl(void)
DYNSSL(SSLv23_method);
DYNSSL(SSL_CTX_free);
DYNSSL(SSL_CTX_new);
DYNSSL(SSL_CTX_ctrl);
DYNSSL(SSL_new);
DYNSSL(SSL_free);
DYNSSL(SSL_ctrl);
DYNSSL(SSL_set_fd);
DYNSSL(SSL_connect);
DYNSSL(SSL_shutdown);
@ -446,12 +557,18 @@ static DWORD init_openssl(void)
DYNCRYPTO(sk_value);
#undef DYNCRYPTO
#define pSSL_CTX_set_options(ctx,op) \
pSSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL)
#define pSSL_set_options(ssl,op) \
pSSL_ctrl((ssl),SSL_CTRL_OPTIONS,(op),NULL)
pSSL_library_init();
pSSL_load_error_strings();
pBIO_new_fp(stderr, BIO_NOCLOSE); /* FIXME: should use winedebug stuff */
meth = pSSLv23_method();
ctx = pSSL_CTX_new(meth);
pSSL_CTX_set_options(ctx, get_tls_option());
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));
@ -487,16 +604,76 @@ static DWORD init_openssl(void)
return ERROR_SUCCESS;
#else
FIXME("can't use SSL, not compiled in.\n");
FIXME("can't use SSL, libcrypto not compiled in.\n");
return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
#endif
}
#endif /* SONAME_LIBSSL */
DWORD create_netconn(BOOL useSSL, server_t *server, DWORD security_flags, DWORD timeout, netconn_t **ret)
static DWORD create_netconn_socket(server_t *server, netconn_t *netconn, DWORD timeout)
{
int result;
ULONG flag;
assert(server->addr_len);
result = netconn->socket = socket(server->addr.ss_family, SOCK_STREAM, 0);
if(result != -1) {
flag = 1;
ioctlsocket(netconn->socket, FIONBIO, &flag);
result = connect(netconn->socket, (struct sockaddr*)&server->addr, server->addr_len);
if(result == -1)
{
if (sock_get_error(errno) == WSAEINPROGRESS) {
// ReactOS: use select instead of poll
fd_set outfd;
struct timeval tv;
int res;
FD_ZERO(&outfd);
FD_SET(netconn->socket, &outfd);
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
res = select(0, NULL, &outfd, NULL, &tv);
if (!res)
{
closesocket(netconn->socket);
return ERROR_INTERNET_CANNOT_CONNECT;
}
else if (res > 0)
{
int err;
socklen_t len = sizeof(err);
if (!getsockopt(netconn->socket, SOL_SOCKET, SO_ERROR, (void *)&err, &len) && !err)
result = 0;
}
}
}
if(result == -1)
closesocket(netconn->socket);
else {
flag = 0;
ioctlsocket(netconn->socket, FIONBIO, &flag);
}
}
if(result == -1)
return ERROR_INTERNET_CANNOT_CONNECT;
#ifdef TCP_NODELAY
flag = 1;
result = setsockopt(netconn->socket, IPPROTO_TCP, TCP_NODELAY, (void*)&flag, sizeof(flag));
if(result < 0)
WARN("setsockopt(TCP_NODELAY) failed\n");
#endif
return ERROR_SUCCESS;
}
DWORD create_netconn(BOOL useSSL, server_t *server, DWORD security_flags, BOOL mask_errors, DWORD timeout, netconn_t **ret)
{
netconn_t *netconn;
int result, flag;
int result;
#ifdef SONAME_LIBSSL
if(useSSL) {
DWORD res;
@ -508,88 +685,41 @@ DWORD create_netconn(BOOL useSSL, server_t *server, DWORD security_flags, DWORD
if(res != ERROR_SUCCESS)
return res;
}
#endif
netconn = heap_alloc_zero(sizeof(*netconn));
if(!netconn)
return ERROR_OUTOFMEMORY;
netconn->useSSL = useSSL;
netconn->socketFD = -1;
netconn->security_flags = security_flags;
netconn->socket = -1;
netconn->security_flags = security_flags | server->security_flags;
netconn->mask_errors = mask_errors;
list_init(&netconn->pool_entry);
assert(server->addr_len);
result = netconn->socketFD = socket(server->addr.ss_family, SOCK_STREAM, 0);
if(result != -1) {
flag = 1;
ioctlsocket(netconn->socketFD, FIONBIO, &flag);
result = connect(netconn->socketFD, (struct sockaddr*)&server->addr, server->addr_len);
if(result == -1)
{
if (sock_get_error(errno) == WSAEINPROGRESS) {
// ReactOS: use select instead of poll
fd_set outfd;
struct timeval tv;
int res;
FD_ZERO(&outfd);
FD_SET(netconn->socketFD, &outfd);
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
res = select(0, NULL, &outfd, NULL, &tv);
if (!res)
{
closesocket(netconn->socketFD);
heap_free(netconn);
return ERROR_INTERNET_CANNOT_CONNECT;
}
else if (res > 0)
{
int err;
socklen_t len = sizeof(err);
if (!getsockopt(netconn->socketFD, SOL_SOCKET, SO_ERROR, &err, &len) && !err)
result = 0;
}
}
}
if(result == -1)
closesocket(netconn->socketFD);
else {
flag = 0;
ioctlsocket(netconn->socketFD, FIONBIO, &flag);
}
}
if(result == -1) {
result = create_netconn_socket(server, netconn, timeout);
if (result != ERROR_SUCCESS) {
heap_free(netconn);
return sock_get_error(errno);
return result;
}
#ifdef TCP_NODELAY
flag = 1;
result = setsockopt(netconn->socketFD, IPPROTO_TCP, TCP_NODELAY, (void*)&flag, sizeof(flag));
if(result < 0)
WARN("setsockopt(TCP_NODELAY) failed\n");
#endif
server_addref(server);
netconn->server = server;
*ret = netconn;
return ERROR_SUCCESS;
return result;
}
void free_netconn(netconn_t *netconn)
{
server_release(netconn->server);
if (netconn->secure) {
#ifdef SONAME_LIBSSL
if (netconn->ssl_s) {
pSSL_shutdown(netconn->ssl_s);
pSSL_free(netconn->ssl_s);
}
#endif
}
closesocket(netconn->socketFD);
closesocket(netconn->socket);
heap_free(netconn);
}
@ -609,7 +739,7 @@ void NETCON_unload(void)
}
if (ssl_locks)
{
int i;
unsigned int i;
for (i = 0; i < num_ssl_locks; i++)
{
ssl_locks[i].DebugInfo->Spare[0] = 0;
@ -689,22 +819,12 @@ int sock_get_error( int err )
}
#endif
/******************************************************************************
* NETCON_secure_connect
* Initiates a secure connection over an existing plaintext connection.
*/
DWORD NETCON_secure_connect(netconn_t *connection)
{
DWORD res = ERROR_NOT_SUPPORTED;
#ifdef SONAME_LIBSSL
static DWORD netcon_secure_connect_setup(netconn_t *connection, long tls_option)
{
void *ssl_s;
/* can't connect if we are already connected */
if (connection->ssl_s)
{
ERR("already connected\n");
return ERROR_INTERNET_CANNOT_CONNECT;
}
DWORD res;
int bits;
ssl_s = pSSL_new(ctx);
if (!ssl_s)
@ -714,7 +834,8 @@ DWORD NETCON_secure_connect(netconn_t *connection)
return ERROR_OUTOFMEMORY;
}
if (!pSSL_set_fd(ssl_s, connection->socketFD))
pSSL_set_options(ssl_s, tls_option);
if (!pSSL_set_fd(ssl_s, connection->socket))
{
ERR("SSL_set_fd failed: %s\n",
pERR_error_string(pERR_get_error(), 0));
@ -739,6 +860,19 @@ DWORD NETCON_secure_connect(netconn_t *connection)
}
connection->ssl_s = ssl_s;
connection->secure = TRUE;
bits = NETCON_GetCipherStrength(connection);
if (bits >= 128)
connection->security_flags |= SECURITY_FLAG_STRENGTH_STRONG;
else if (bits >= 56)
connection->security_flags |= SECURITY_FLAG_STRENGTH_MEDIUM;
else
connection->security_flags |= SECURITY_FLAG_STRENGTH_WEAK;
connection->security_flags |= SECURITY_FLAG_SECURE;
if(connection->mask_errors)
connection->server->security_flags = connection->security_flags;
return ERROR_SUCCESS;
fail:
@ -747,6 +881,51 @@ fail:
pSSL_shutdown(ssl_s);
pSSL_free(ssl_s);
}
return res;
}
#endif
/******************************************************************************
* NETCON_secure_connect
* Initiates a secure connection over an existing plaintext connection.
*/
DWORD NETCON_secure_connect(netconn_t *connection, server_t *server)
{
DWORD res = ERROR_NOT_SUPPORTED;
/* can't connect if we are already connected */
if(connection->secure) {
ERR("already connected\n");
return ERROR_INTERNET_CANNOT_CONNECT;
}
if(server != connection->server) {
server_release(connection->server);
server_addref(server);
connection->server = server;
}
#ifdef SONAME_LIBSSL
/* connect with given TLS options */
res = netcon_secure_connect_setup(connection, get_tls_option());
if (res == ERROR_SUCCESS)
return res;
#ifdef SSL_OP_NO_TLSv1_2
/* FIXME: when got version alert and FIN from server */
/* fallback to connect without TLSv1.1/TLSv1.2 */
if (res == ERROR_INTERNET_SECURITY_CHANNEL_ERROR)
{
closesocket(connection->socket);
pSSL_CTX_set_options(ctx,SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2);
res = create_netconn_socket(connection->server, connection, 500);
if (res != ERROR_SUCCESS)
return res;
res = netcon_secure_connect_setup(connection, get_tls_option()|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2);
}
#endif
#else
FIXME("Cannot connect, OpenSSL not available.\n");
#endif
return res;
}
@ -759,9 +938,9 @@ fail:
DWORD NETCON_send(netconn_t *connection, const void *msg, size_t len, int flags,
int *sent /* out */)
{
if (!connection->useSSL)
if(!connection->secure)
{
*sent = send(connection->socketFD, msg, len, flags);
*sent = send(connection->socket, msg, len, flags);
if (*sent == -1)
return sock_get_error(errno);
return ERROR_SUCCESS;
@ -769,7 +948,7 @@ DWORD NETCON_send(netconn_t *connection, const void *msg, size_t len, int flags,
else
{
#ifdef SONAME_LIBSSL
if(!connection->ssl_s) {
if(!connection->secure) {
FIXME("not connected\n");
return ERROR_NOT_SUPPORTED;
}
@ -780,6 +959,7 @@ DWORD NETCON_send(netconn_t *connection, const void *msg, size_t len, int flags,
return ERROR_INTERNET_CONNECTION_ABORTED;
return ERROR_SUCCESS;
#else
FIXME("not supported on this platform\n");
return ERROR_NOT_SUPPORTED;
#endif
}
@ -790,21 +970,21 @@ DWORD NETCON_send(netconn_t *connection, const void *msg, size_t len, int flags,
* Basically calls 'recv()' unless we should use SSL
* number of chars received is put in *recvd
*/
DWORD NETCON_recv(netconn_t *connection, void *buf, size_t len, int flags,
int *recvd /* out */)
DWORD NETCON_recv(netconn_t *connection, void *buf, size_t len, int flags, int *recvd)
{
*recvd = 0;
if (!len)
return ERROR_SUCCESS;
if (!connection->useSSL)
if (!connection->secure)
{
*recvd = recv(connection->socketFD, buf, len, flags);
*recvd = recv(connection->socket, buf, len, flags);
return *recvd == -1 ? sock_get_error(errno) : ERROR_SUCCESS;
}
else
{
#ifdef SONAME_LIBSSL
if(!connection->ssl_s) {
if(!connection->secure) {
FIXME("not connected\n");
return ERROR_NOT_SUPPORTED;
}
@ -817,6 +997,7 @@ DWORD NETCON_recv(netconn_t *connection, void *buf, size_t len, int flags,
return *recvd > 0 ? ERROR_SUCCESS : ERROR_INTERNET_CONNECTION_ABORTED;
#else
FIXME("not supported on this platform\n");
return ERROR_NOT_SUPPORTED;
#endif
}
@ -831,11 +1012,11 @@ BOOL NETCON_query_data_available(netconn_t *connection, DWORD *available)
{
*available = 0;
if (!connection->useSSL)
if(!connection->secure)
{
#ifdef FIONREAD
int unread;
int retval = ioctlsocket(connection->socketFD, FIONREAD, &unread);
ULONG unread;
int retval = ioctlsocket(connection->socket, FIONREAD, &unread);
if (!retval)
{
TRACE("%d bytes of queued, but unread data\n", unread);
@ -846,7 +1027,10 @@ BOOL NETCON_query_data_available(netconn_t *connection, DWORD *available)
else
{
#ifdef SONAME_LIBSSL
*available = connection->ssl_s ? pSSL_pending(connection->ssl_s) : 0;
*available = pSSL_pending(connection->ssl_s);
#else
FIXME("not supported on this platform\n");
return FALSE;
#endif
}
return TRUE;
@ -858,7 +1042,7 @@ BOOL NETCON_is_alive(netconn_t *netconn)
ssize_t len;
BYTE b;
len = recv(netconn->socketFD, &b, 1, MSG_PEEK|MSG_DONTWAIT);
len = recv(netconn->socket, &b, 1, MSG_PEEK|MSG_DONTWAIT);
return len == 1 || (len == -1 && errno == EWOULDBLOCK);
#elif defined(__MINGW32__) || defined(_MSC_VER)
ULONG mode;
@ -866,13 +1050,13 @@ BOOL NETCON_is_alive(netconn_t *netconn)
char b;
mode = 1;
if(!ioctlsocket(netconn->socketFD, FIONBIO, &mode))
if(!ioctlsocket(netconn->socket, FIONBIO, &mode))
return FALSE;
len = recv(netconn->socketFD, &b, 1, MSG_PEEK);
len = recv(netconn->socket, &b, 1, MSG_PEEK);
mode = 0;
if(!ioctlsocket(netconn->socketFD, FIONBIO, &mode))
if(!ioctlsocket(netconn->socket, FIONBIO, &mode))
return FALSE;
return len == 1 || (len == -1 && errno == WSAEWOULDBLOCK);
@ -888,13 +1072,14 @@ LPCVOID NETCON_GetCert(netconn_t *connection)
X509* cert;
LPCVOID r = NULL;
if (!connection->ssl_s)
if (!connection->secure)
return NULL;
cert = pSSL_get_peer_certificate(connection->ssl_s);
r = X509_to_cert_context(cert);
return r;
#else
FIXME("not supported on this platform\n");
return NULL;
#endif
}
@ -909,7 +1094,7 @@ int NETCON_GetCipherStrength(netconn_t *connection)
#endif
int bits = 0;
if (!connection->ssl_s)
if (!connection->secure)
return 0;
cipher = pSSL_get_current_cipher(connection->ssl_s);
if (!cipher)
@ -917,6 +1102,7 @@ int NETCON_GetCipherStrength(netconn_t *connection)
pSSL_CIPHER_get_bits(cipher, &bits);
return bits;
#else
FIXME("not supported on this platform\n");
return 0;
#endif
}
@ -937,7 +1123,7 @@ DWORD NETCON_set_timeout(netconn_t *connection, BOOL send, DWORD value)
tv.tv_sec = value / 1000;
tv.tv_usec = (value % 1000) * 1000;
}
result = setsockopt(connection->socketFD, SOL_SOCKET,
result = setsockopt(connection->socket, SOL_SOCKET,
send ? SO_SNDTIMEO : SO_RCVTIMEO, (void*)&tv,
sizeof(tv));
if (result == -1)

File diff suppressed because it is too large Load diff

View file

@ -290,76 +290,80 @@ static const char *get_callback_name(DWORD dwInternetStatus) {
return "Unknown";
}
VOID INTERNET_SendCallback(object_header_t *hdr, DWORD_PTR dwContext,
DWORD dwInternetStatus, LPVOID lpvStatusInfo,
DWORD dwStatusInfoLength)
static const char *debugstr_status_info(DWORD status, void *info)
{
LPVOID lpvNewInfo = NULL;
switch(status) {
case INTERNET_STATUS_REQUEST_COMPLETE: {
INTERNET_ASYNC_RESULT *iar = info;
return wine_dbg_sprintf("{%s, %d}", wine_dbgstr_longlong(iar->dwResult), iar->dwError);
}
default:
return wine_dbg_sprintf("%p", info);
}
}
void INTERNET_SendCallback(object_header_t *hdr, DWORD_PTR context, DWORD status, void *info, DWORD info_len)
{
void *new_info = info;
if( !hdr->lpfnStatusCB )
return;
/* the IE5 version of wininet does not
send callbacks if dwContext is zero */
if( !dwContext )
if(!context)
return;
lpvNewInfo = lpvStatusInfo;
if(hdr->dwInternalFlags & INET_CALLBACKW) {
switch(dwInternetStatus) {
case INTERNET_STATUS_NAME_RESOLVED:
case INTERNET_STATUS_CONNECTING_TO_SERVER:
case INTERNET_STATUS_CONNECTED_TO_SERVER:
lpvNewInfo = heap_strdupAtoW(lpvStatusInfo);
dwStatusInfoLength *= sizeof(WCHAR);
switch(status) {
case INTERNET_STATUS_NAME_RESOLVED:
case INTERNET_STATUS_CONNECTING_TO_SERVER:
case INTERNET_STATUS_CONNECTED_TO_SERVER:
new_info = heap_alloc(info_len);
if(new_info)
memcpy(new_info, info, info_len);
break;
case INTERNET_STATUS_RESOLVING_NAME:
case INTERNET_STATUS_REDIRECT:
if(hdr->dwInternalFlags & INET_CALLBACKW) {
new_info = heap_strdupW(info);
break;
case INTERNET_STATUS_RESOLVING_NAME:
case INTERNET_STATUS_REDIRECT:
lpvNewInfo = heap_strdupW(lpvStatusInfo);
break;
}
}else {
switch(dwInternetStatus)
{
case INTERNET_STATUS_NAME_RESOLVED:
case INTERNET_STATUS_CONNECTING_TO_SERVER:
case INTERNET_STATUS_CONNECTED_TO_SERVER:
lpvNewInfo = heap_alloc(strlen(lpvStatusInfo) + 1);
if (lpvNewInfo) strcpy(lpvNewInfo, lpvStatusInfo);
break;
case INTERNET_STATUS_RESOLVING_NAME:
case INTERNET_STATUS_REDIRECT:
lpvNewInfo = heap_strdupWtoA(lpvStatusInfo);
dwStatusInfoLength /= sizeof(WCHAR);
}else {
new_info = heap_strdupWtoA(info);
info_len = strlen(new_info)+1;
break;
}
}
TRACE(" callback(%p) (%p (%p), %08lx, %d (%s), %p, %d)\n",
hdr->lpfnStatusCB, hdr->hInternet, hdr, dwContext, dwInternetStatus, get_callback_name(dwInternetStatus),
lpvNewInfo, dwStatusInfoLength);
TRACE(" callback(%p) (%p (%p), %08lx, %d (%s), %s, %d)\n",
hdr->lpfnStatusCB, hdr->hInternet, hdr, context, status, get_callback_name(status),
debugstr_status_info(status, new_info), info_len);
hdr->lpfnStatusCB(hdr->hInternet, dwContext, dwInternetStatus,
lpvNewInfo, dwStatusInfoLength);
hdr->lpfnStatusCB(hdr->hInternet, context, status, new_info, info_len);
TRACE(" end callback().\n");
if(lpvNewInfo != lpvStatusInfo)
heap_free(lpvNewInfo);
if(new_info != info)
heap_free(new_info);
}
static void SendAsyncCallbackProc(WORKREQUEST *workRequest)
typedef struct {
task_header_t hdr;
DWORD_PTR context;
DWORD status;
LPVOID status_info;
DWORD status_info_len;
} send_callback_task_t;
static void SendAsyncCallbackProc(task_header_t *hdr)
{
struct WORKREQ_SENDCALLBACK const *req = &workRequest->u.SendCallback;
send_callback_task_t *task = (send_callback_task_t*)hdr;
TRACE("%p\n", workRequest->hdr);
TRACE("%p\n", task->hdr.hdr);
INTERNET_SendCallback(workRequest->hdr,
req->dwContext, req->dwInternetStatus, req->lpvStatusInfo,
req->dwStatusInfoLength);
INTERNET_SendCallback(task->hdr.hdr, task->context, task->status, task->status_info, task->status_info_len);
/* And frees the copy of the status info */
heap_free(req->lpvStatusInfo);
heap_free(task->status_info);
}
void SendAsyncCallback(object_header_t *hdr, DWORD_PTR dwContext,
@ -377,25 +381,22 @@ void SendAsyncCallback(object_header_t *hdr, DWORD_PTR dwContext,
if (hdr->dwFlags & INTERNET_FLAG_ASYNC)
{
WORKREQUEST workRequest;
struct WORKREQ_SENDCALLBACK *req;
void *lpvStatusInfo_copy = lpvStatusInfo;
send_callback_task_t *task;
void *lpvStatusInfo_copy = lpvStatusInfo;
if (lpvStatusInfo)
{
lpvStatusInfo_copy = heap_alloc(dwStatusInfoLength);
memcpy(lpvStatusInfo_copy, lpvStatusInfo, dwStatusInfoLength);
}
if (lpvStatusInfo)
{
lpvStatusInfo_copy = heap_alloc(dwStatusInfoLength);
memcpy(lpvStatusInfo_copy, lpvStatusInfo, dwStatusInfoLength);
}
workRequest.asyncproc = SendAsyncCallbackProc;
workRequest.hdr = WININET_AddRef( hdr );
req = &workRequest.u.SendCallback;
req->dwContext = dwContext;
req->dwInternetStatus = dwInternetStatus;
req->lpvStatusInfo = lpvStatusInfo_copy;
req->dwStatusInfoLength = dwStatusInfoLength;
task = alloc_async_task(hdr, SendAsyncCallbackProc, sizeof(*task));
task->context = dwContext;
task->status = dwInternetStatus;
task->status_info = lpvStatusInfo_copy;
task->status_info_len = dwStatusInfoLength;
INTERNET_AsyncCall(&workRequest);
INTERNET_AsyncCall(&task->hdr);
}
else
INTERNET_SendCallback(hdr, dwContext, dwInternetStatus,

View file

@ -31,6 +31,7 @@
@ stdcall DeleteUrlCacheEntryA(str)
@ stdcall DeleteUrlCacheEntryW(wstr)
@ stdcall DeleteUrlCacheGroup(int64 long ptr)
@ stdcall DeleteWpadCacheForNetworks(long)
@ stdcall DetectAutoProxyUrl(str long long)
@ stdcall -private DllInstall(long wstr)
@ stdcall FindCloseUrlCache(long)
@ -157,6 +158,9 @@
@ stdcall InternetGetLastResponseInfoW(ptr ptr ptr)
@ stdcall InternetGetPerSiteCookieDecisionA(str ptr)
@ stdcall InternetGetPerSiteCookieDecisionW(wstr ptr)
@ stdcall InternetGetSecurityInfoByURL(str ptr ptr) InternetGetSecurityInfoByURLA
@ stdcall InternetGetSecurityInfoByURLA(str ptr ptr)
@ stdcall InternetGetSecurityInfoByURLW(wstr ptr ptr)
@ stdcall InternetGoOnline(str long long) InternetGoOnlineA
@ stdcall InternetGoOnlineA(str long long)
@ stdcall InternetGoOnlineW(wstr long long)
@ -211,7 +215,7 @@
@ stdcall IsHostInProxyBypassList(long str long)
@ stdcall IsUrlCacheEntryExpiredA(str long ptr)
@ stdcall IsUrlCacheEntryExpiredW(wstr long ptr)
@ stub LoadUrlCacheContent
@ stdcall LoadUrlCacheContent()
@ stub ParseX509EncodedCertificateForListBoxEntry
@ stdcall PrivacyGetZonePreferenceW(long long ptr ptr ptr)
@ stdcall PrivacySetZonePreferenceW(long long long wstr)

View file

@ -1,6 +1,194 @@
--- wine-1.5.4/dlls/wininet/internet.h 2012-06-20 14:38:39 +0200
+++ dll/win32/wininet/internet.h 2012-06-23 17:25:14 +0200
@@ -536,7 +536,30 @@ BOOL NETCON_is_alive(netconn_t*) DECLSPE
diff -prudN e:\Wine\dlls\wininet/cookie.c e:\reactos-clean\dll\win32\wininet/cookie.c
--- e:\Wine\dlls\wininet/cookie.c 2013-03-02 14:18:01.994544800 +0100
+++ e:\reactos-clean\dll\win32\wininet/cookie.c 2013-05-20 20:45:34.175815800 +0100
@@ -250,6 +254,7 @@ static BOOL save_persistent_cookie(cooki
BOOL do_save = FALSE;
char buf[64], *dyn_buf;
FILETIME time;
+ DWORD dwBytesWritten;
if (!create_cookie_url(domain->lpCookieDomain, domain->lpCookiePath, cookie_url, sizeof(cookie_url)/sizeof(cookie_url[0])))
return FALSE;
@@ -288,31 +293,31 @@ static BOOL save_persistent_cookie(cooki
continue;
dyn_buf = heap_strdupWtoA(cookie_container->lpCookieName);
- if(!dyn_buf || !WriteFile(cookie_handle, dyn_buf, strlen(dyn_buf), NULL, NULL)) {
+ if(!dyn_buf || !WriteFile(cookie_handle, dyn_buf, strlen(dyn_buf), &dwBytesWritten, NULL)) {
heap_free(dyn_buf);
do_save = FALSE;
break;
}
heap_free(dyn_buf);
- if(!WriteFile(cookie_handle, "\n", 1, NULL, NULL)) {
+ if(!WriteFile(cookie_handle, "\n", 1, &dwBytesWritten, NULL)) {
do_save = FALSE;
break;
}
dyn_buf = heap_strdupWtoA(cookie_container->lpCookieData);
- if(!dyn_buf || !WriteFile(cookie_handle, dyn_buf, strlen(dyn_buf), NULL, NULL)) {
+ if(!dyn_buf || !WriteFile(cookie_handle, dyn_buf, strlen(dyn_buf), &dwBytesWritten, NULL)) {
heap_free(dyn_buf);
do_save = FALSE;
break;
}
heap_free(dyn_buf);
- if(!WriteFile(cookie_handle, "\n", 1, NULL, NULL)) {
+ if(!WriteFile(cookie_handle, "\n", 1, &dwBytesWritten, NULL)) {
do_save = FALSE;
break;
}
dyn_buf = heap_strdupWtoA(domain->lpCookieDomain);
- if(!dyn_buf || !WriteFile(cookie_handle, dyn_buf, strlen(dyn_buf), NULL, NULL)) {
+ if(!dyn_buf || !WriteFile(cookie_handle, dyn_buf, strlen(dyn_buf), &dwBytesWritten, NULL)) {
heap_free(dyn_buf);
do_save = FALSE;
break;
@@ -320,7 +325,7 @@ static BOOL save_persistent_cookie(cooki
heap_free(dyn_buf);
dyn_buf = heap_strdupWtoA(domain->lpCookiePath);
- if(!dyn_buf || !WriteFile(cookie_handle, dyn_buf, strlen(dyn_buf), NULL, NULL)) {
+ if(!dyn_buf || !WriteFile(cookie_handle, dyn_buf, strlen(dyn_buf), &dwBytesWritten, NULL)) {
heap_free(dyn_buf);
do_save = FALSE;
break;
@@ -330,7 +335,7 @@ static BOOL save_persistent_cookie(cooki
sprintf(buf, "\n%u\n%u\n%u\n%u\n%u\n*\n", cookie_container->flags,
cookie_container->expiry.dwLowDateTime, cookie_container->expiry.dwHighDateTime,
cookie_container->create.dwLowDateTime, cookie_container->create.dwHighDateTime);
- if(!WriteFile(cookie_handle, buf, strlen(buf), NULL, NULL)) {
+ if(!WriteFile(cookie_handle, buf, strlen(buf), &dwBytesWritten, NULL)) {
do_save = FALSE;
break;
}
diff -prudN e:\Wine\dlls\wininet/http.c e:\reactos-clean\dll\win32\wininet/http.c
--- e:\Wine\dlls\wininet/http.c 2013-03-16 11:54:52.608610100 +0100
+++ e:\reactos-clean\dll\win32\wininet/http.c 2013-05-20 16:36:21.826074500 +0100
@@ -242,7 +249,13 @@ void server_release(server_t *server)
if(InterlockedDecrement(&server->ref))
return;
+#ifdef __REACTOS__
+ EnterCriticalSection(&connection_pool_cs);
+#endif
list_remove(&server->entry);
+#ifdef __REACTOS__
+ LeaveCriticalSection(&connection_pool_cs);
+#endif
if(server->cert_chain)
CertFreeCertificateChain(server->cert_chain);
@@ -324,7 +337,7 @@ BOOL collect_connections(collect_type_t
BOOL remaining = FALSE;
DWORD64 now;
- now = GetTickCount64();
+ now = GetTickCount();
LIST_FOR_EACH_ENTRY_SAFE(server, server_safe, &connection_pool, server_t, entry) {
LIST_FOR_EACH_ENTRY_SAFE(netconn, netconn_safe, &server->conn_pool, netconn_t, pool_entry) {
@@ -1870,13 +1883,14 @@ static void http_release_netconn(http_re
if(!req->netconn)
return;
+#ifndef __REACTOS__
if(reuse && req->netconn->keep_alive) {
BOOL run_collector;
EnterCriticalSection(&connection_pool_cs);
list_add_head(&req->netconn->server->conn_pool, &req->netconn->pool_entry);
- req->netconn->keep_until = GetTickCount64() + COLLECT_TIME;
+ req->netconn->keep_until = (DWORD64)GetTickCount() + COLLECT_TIME;
req->netconn = NULL;
run_collector = !collector_running;
@@ -1904,6 +1918,10 @@ static void http_release_netconn(http_re
}
return;
}
+#else
+ // silence unused function warning
+ (void)collect_connections_proc;
+#endif
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext,
INTERNET_STATUS_CLOSING_CONNECTION, 0, 0);
diff -prudN e:\Wine\dlls\wininet/internet.c e:\reactos-clean\dll\win32\wininet/internet.c
--- e:\Wine\dlls\wininet/internet.c 2013-03-16 11:54:52.609610800 +0100
+++ e:\reactos-clean\dll\win32\wininet/internet.c 2013-05-20 16:43:55.864085500 +0100
@@ -292,11 +297,9 @@ BOOL WINAPI DllMain (HINSTANCE hinstDLL,
if (g_dwTlsErrIndex == TLS_OUT_OF_INDEXES)
return FALSE;
- if(!init_urlcache())
- {
- TlsFree(g_dwTlsErrIndex);
- return FALSE;
- }
+#ifndef __REACTOS__
+ URLCacheContainers_CreateDefaults();
+#endif
WININET_hModule = hinstDLL;
break;
@@ -750,6 +753,9 @@ static VOID APPINFO_Destroy(object_heade
heap_free(lpwai->proxyBypass);
heap_free(lpwai->proxyUsername);
heap_free(lpwai->proxyPassword);
+#ifdef __REACTOS__
+ WSACleanup();
+#endif
}
static DWORD APPINFO_QueryOption(object_header_t *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
@@ -945,6 +951,11 @@ HINTERNET WINAPI InternetOpenW(LPCWSTR l
LPCWSTR lpszProxy, LPCWSTR lpszProxyBypass, DWORD dwFlags)
{
appinfo_t *lpwai = NULL;
+#ifdef __REACTOS__
+ WSADATA wsaData;
+ int error = WSAStartup(MAKEWORD(2, 2), &wsaData);
+ if (error) ERR("WSAStartup failed: %d\n", error);
+#endif
if (TRACE_ON(wininet)) {
#define FE(x) { x, #x }
@@ -3759,19 +3770,23 @@ LPSTR INTERNET_GetResponseBuffer(void)
LPSTR INTERNET_GetNextLine(INT nSocket, LPDWORD dwLen)
{
- struct pollfd pfd;
+ // ReactOS: use select instead of poll
+ fd_set infd;
+ struct timeval tv;
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(0, &infd, NULL, NULL, &tv) > 0)
{
if (recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0)
{
diff -prudN e:\Wine\dlls\wininet/internet.h e:\reactos-clean\dll\win32\wininet/internet.h
--- e:\Wine\dlls\wininet/internet.h 2013-03-02 14:18:02.010553900 +0100
+++ e:\reactos-clean\dll\win32\wininet/internet.h 2013-05-20 17:12:12.531037400 +0100
@@ -419,7 +419,30 @@ BOOL NETCON_is_alive(netconn_t*) DECLSPE
LPCVOID NETCON_GetCert(netconn_t *connection) DECLSPEC_HIDDEN;
int NETCON_GetCipherStrength(netconn_t*) DECLSPEC_HIDDEN;
DWORD NETCON_set_timeout(netconn_t *connection, BOOL send, DWORD value) DECLSPEC_HIDDEN;
@ -29,11 +217,12 @@
+#define getsockopt unix_getsockopt
+#endif
extern void URLCacheContainers_CreateDefaults(void) DECLSPEC_HIDDEN;
extern void URLCacheContainers_DeleteAll(void) DECLSPEC_HIDDEN;
--- wine-1.5.4/dlls/wininet/netconnection.c 2012-06-20 14:38:39 +0200
+++ dll/win32/wininet/netconnection.c 2012-06-20 15:50:06 +0200
@@ -523,12 +523,16 @@ DWORD create_netconn(BOOL useSSL, server
server_t *get_server(const WCHAR*,INTERNET_PORT,BOOL,BOOL);
diff -prudN e:\Wine\dlls\wininet/netconnection.c e:\reactos-clean\dll\win32\wininet/netconnection.c
--- e:\Wine\dlls\wininet/netconnection.c 2013-03-16 11:54:52.610611400 +0100
+++ e:\reactos-clean\dll\win32\wininet/netconnection.c 2013-05-20 17:12:51.246334100 +0100
@@ -619,12 +624,16 @@ static DWORD create_netconn_socket(serve
if(result == -1)
{
if (sock_get_error(errno) == WSAEINPROGRESS) {
@ -43,18 +232,18 @@
+ struct timeval tv;
int res;
- pfd.fd = netconn->socketFD;
- pfd.fd = netconn->socket;
- pfd.events = POLLOUT;
- res = poll(&pfd, 1, timeout);
+ FD_ZERO(&outfd);
+ FD_SET(netconn->socketFD, &outfd);
+ FD_SET(netconn->socket, &outfd);
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ res = select(0, NULL, &outfd, NULL, &tv);
if (!res)
{
closesocket(netconn->socketFD);
@@ -612,6 +616,7 @@ void NETCON_unload(void)
closesocket(netconn->socket);
@@ -741,6 +750,7 @@ void NETCON_unload(void)
#endif
}
@ -62,79 +251,18 @@
/* translate a unix error code into a winsock one */
int sock_get_error( int err )
{
@@ -678,6 +683,7 @@ int sock_get_error( int err )
@@ -807,6 +817,7 @@ int sock_get_error( int err )
#endif
return err;
}
+#endif
/******************************************************************************
* NETCON_secure_connect
--- wine-1.5.4/dlls/wininet/internet.c 2012-06-20 14:38:38 +0200
+++ dll/win32/wininet/internet.c 2012-06-23 17:45:14 +0200
@@ -292,7 +292,9 @@ BOOL WINAPI DllMain (HINSTANCE hinstDLL,
if (g_dwTlsErrIndex == TLS_OUT_OF_INDEXES)
return FALSE;
+#ifndef __REACTOS__
URLCacheContainers_CreateDefaults();
+#endif
WININET_hModule = hinstDLL;
break;
@@ -745,6 +747,9 @@ static VOID APPINFO_Destroy(object_heade
heap_free(lpwai->proxyBypass);
heap_free(lpwai->proxyUsername);
heap_free(lpwai->proxyPassword);
+#ifdef __REACTOS__
+ WSACleanup();
+#endif
}
static DWORD APPINFO_QueryOption(object_header_t *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
@@ -906,6 +911,11 @@ HINTERNET WINAPI InternetOpenW(LPCWSTR l
LPCWSTR lpszProxy, LPCWSTR lpszProxyBypass, DWORD dwFlags)
{
appinfo_t *lpwai = NULL;
+#ifdef __REACTOS__
+ WSADATA wsaData;
+ int error = WSAStartup(MAKEWORD(2, 2), &wsaData);
+ if (error) ERR("WSAStartup failed: %d\n", error);
+#endif
if (TRACE_ON(wininet)) {
#define FE(x) { x, #x }
@@ -3716,19 +3726,23 @@ LPSTR INTERNET_GetResponseBuffer(void)
LPSTR INTERNET_GetNextLine(INT nSocket, LPDWORD dwLen)
{
- struct pollfd pfd;
+ // ReactOS: use select instead of poll
+ fd_set infd;
+ struct timeval tv;
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(0, &infd, NULL, NULL, &tv) > 0)
{
if (recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0)
{
--- wine-1.5.4/dlls/wininet/urlcache.c 2012-06-20 14:30:41 +0200
+++ dll/win32/wininet/urlcache.c 2012-06-20 15:50:06 +0200
@@ -189,6 +189,8 @@ typedef struct _URLCACHECONTAINER
#ifdef SONAME_LIBSSL
static DWORD netcon_secure_connect_setup(netconn_t *connection, long tls_option)
diff -prudN e:\Wine\dlls\wininet/urlcache.c e:\reactos-clean\dll\win32\wininet/urlcache.c
--- e:\Wine\dlls\wininet/urlcache.c 2013-03-16 11:54:52.613613400 +0100
+++ e:\reactos-clean\dll\win32\wininet/urlcache.c 2013-05-20 17:05:34.969949600 +0100
@@ -201,6 +205,8 @@ typedef struct _URLCACHECONTAINER
/* List of all containers available */
static struct list UrlContainers = LIST_INIT(UrlContainers);
@ -143,7 +271,7 @@
static DWORD URLCache_CreateHashTable(LPURLCACHE_HEADER pHeader, HASH_CACHEFILE_ENTRY *pPrevHash, HASH_CACHEFILE_ENTRY **ppHash);
@@ -538,6 +540,8 @@ void URLCacheContainers_CreateDefaults(v
@@ -587,6 +593,8 @@ static void URLCacheContainers_CreateDef
static const WCHAR HistoryPrefix[] = {'V','i','s','i','t','e','d',':',0};
static const WCHAR CookieSuffix[] = {0};
static const WCHAR CookiePrefix[] = {'C','o','o','k','i','e',':',0};
@ -152,7 +280,7 @@
static const struct
{
int nFolder; /* CSIDL_* constant */
@@ -551,6 +555,13 @@ void URLCacheContainers_CreateDefaults(v
@@ -601,6 +609,13 @@ static void URLCacheContainers_CreateDef
};
DWORD i;
@ -166,7 +294,7 @@
for (i = 0; i < sizeof(DefaultContainerData) / sizeof(DefaultContainerData[0]); i++)
{
WCHAR wszCachePath[MAX_PATH];
@@ -604,6 +615,10 @@ static DWORD URLCacheContainers_FindCont
@@ -655,6 +670,10 @@ static DWORD URLCacheContainers_FindCont
if(!lpwszUrl)
return ERROR_INVALID_PARAMETER;
@ -177,7 +305,7 @@
LIST_FOR_EACH_ENTRY(pContainer, &UrlContainers, URLCACHECONTAINER, entry)
{
int prefix_len = strlenW(pContainer->cache_prefix);
@@ -642,6 +657,10 @@ static BOOL URLCacheContainers_Enum(LPCW
@@ -693,6 +712,10 @@ static BOOL URLCacheContainers_Enum(LPCW
if (lpwszSearchPattern && dwIndex > 0)
return FALSE;
@ -188,81 +316,3 @@
LIST_FOR_EACH_ENTRY(pContainer, &UrlContainers, URLCACHECONTAINER, entry)
{
if (lpwszSearchPattern)
@@ -1579,6 +1598,10 @@ BOOL WINAPI FreeUrlCacheSpaceW(LPCWSTR l
return FALSE;
}
+ // ReactOS r54992
+ if (!bDefaultContainersAdded)
+ URLCacheContainers_CreateDefaults();
+
LIST_FOR_EACH_ENTRY(pContainer, &UrlContainers, URLCACHECONTAINER, entry)
{
/* The URL cache has prefix L"" (unlike Cookies and History) */
--- wine-1.5.4/dlls/wininet/http.c 2012-06-20 15:19:57 +0200
+++ dll/win32/wininet/http.c 2012-06-20 16:24:11 +0200
@@ -73,6 +73,9 @@
#include "wine/exception.h"
#include "wine/unicode.h"
+// ReactOS
+#include "inet_ntop.c"
+
WINE_DEFAULT_DEBUG_CHANNEL(wininet);
static const WCHAR g_szHttp1_0[] = {'H','T','T','P','/','1','.','0',0};
@@ -241,8 +244,17 @@ void server_release(server_t *server)
if(InterlockedDecrement(&server->ref))
return;
+#ifndef __REACTOS__
if(!server->ref)
- server->keep_until = GetTickCount64() + COLLECT_TIME;
+ server->keep_until = (DWORD64)GetTickCount() + COLLECT_TIME;
+#else
+ EnterCriticalSection(&connection_pool_cs);
+ list_remove(&server->entry);
+ LeaveCriticalSection(&connection_pool_cs);
+
+ heap_free(server->name);
+ heap_free(server);
+#endif
}
static server_t *get_server(const WCHAR *name, INTERNET_PORT port)
@@ -288,7 +300,7 @@ BOOL collect_connections(BOOL collect_al
BOOL remaining = FALSE;
DWORD64 now;
- now = GetTickCount64();
+ now = GetTickCount();
LIST_FOR_EACH_ENTRY_SAFE(server, server_safe, &connection_pool, server_t, entry) {
LIST_FOR_EACH_ENTRY_SAFE(netconn, netconn_safe, &server->conn_pool, netconn_t, pool_entry) {
@@ -1854,13 +1866,14 @@ static void http_release_netconn(http_re
if(!req->netconn)
return;
+#ifndef __REACTOS__
if(reuse && req->netconn->keep_alive) {
BOOL run_collector;
EnterCriticalSection(&connection_pool_cs);
list_add_head(&req->netconn->server->conn_pool, &req->netconn->pool_entry);
- req->netconn->keep_until = GetTickCount64() + COLLECT_TIME;
+ req->netconn->keep_until = (DWORD64)GetTickCount() + COLLECT_TIME;
req->netconn = NULL;
run_collector = !collector_running;
@@ -1888,6 +1901,10 @@ static void http_release_netconn(http_re
}
return;
}
+#else
+ // silence unused function warning
+ (void)collect_connections_proc;
+#endif
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext,
INTERNET_STATUS_CLOSING_CONNECTION, 0, 0);

View file

@ -421,6 +421,7 @@ BOOLAPI InternetCombineUrlW(LPCWSTR ,LPCWSTR ,LPWSTR ,LPDWORD ,DWORD);
#define ICU_NO_META 0x08000000
#define ICU_ENCODE_SPACES_ONLY 0x04000000
#define ICU_BROWSER_MODE 0x02000000
#define ICU_ENCODE_PERCENT 0x00001000
INTERNETAPI HINTERNET WINAPI InternetOpenA(LPCSTR ,DWORD ,LPCSTR ,LPCSTR ,DWORD);
INTERNETAPI HINTERNET WINAPI InternetOpenW(LPCWSTR ,DWORD ,LPCWSTR ,LPCWSTR ,DWORD);
@ -805,17 +806,17 @@ DECL_WINELIB_TYPE_AW(LPGOPHER_FIND_DATA)
#define GOPHER_TYPE_ASK 0x40000000
#define GOPHER_TYPE_GOPHER_PLUS 0x80000000
#define IS_GOPHER_FILE(type) (BOOL)(((type) & GOPHER_TYPE_FILE_MASK) ? TRUE : FALSE)
#define IS_GOPHER_DIRECTORY(type) (BOOL)(((type) & GOPHER_TYPE_DIRECTORY) ? TRUE : FALSE)
#define IS_GOPHER_PHONE_SERVER(type) (BOOL)(((type) & GOPHER_TYPE_CSO) ? TRUE : FALSE)
#define IS_GOPHER_ERROR(type) (BOOL)(((type) & GOPHER_TYPE_ERROR) ? TRUE : FALSE)
#define IS_GOPHER_INDEX_SERVER(type) (BOOL)(((type) & GOPHER_TYPE_INDEX_SERVER) ? TRUE : FALSE)
#define IS_GOPHER_TELNET_SESSION(type) (BOOL)(((type) & GOPHER_TYPE_TELNET) ? TRUE : FALSE)
#define IS_GOPHER_BACKUP_SERVER(type) (BOOL)(((type) & GOPHER_TYPE_REDUNDANT) ? TRUE : FALSE)
#define IS_GOPHER_TN3270_SESSION(type) (BOOL)(((type) & GOPHER_TYPE_TN3270) ? TRUE : FALSE)
#define IS_GOPHER_ASK(type) (BOOL)(((type) & GOPHER_TYPE_ASK) ? TRUE : FALSE)
#define IS_GOPHER_PLUS(type) (BOOL)(((type) & GOPHER_TYPE_GOPHER_PLUS) ? TRUE : FALSE)
#define IS_GOPHER_TYPE_KNOWN(type) (BOOL)(((type) & GOPHER_TYPE_UNKNOWN) ? FALSE : TRUE)
#define IS_GOPHER_FILE(type) (BOOL)(((type) & GOPHER_TYPE_FILE_MASK) != 0)
#define IS_GOPHER_DIRECTORY(type) (BOOL)(((type) & GOPHER_TYPE_DIRECTORY) != 0)
#define IS_GOPHER_PHONE_SERVER(type) (BOOL)(((type) & GOPHER_TYPE_CSO) != 0)
#define IS_GOPHER_ERROR(type) (BOOL)(((type) & GOPHER_TYPE_ERROR) != 0)
#define IS_GOPHER_INDEX_SERVER(type) (BOOL)(((type) & GOPHER_TYPE_INDEX_SERVER) != 0)
#define IS_GOPHER_TELNET_SESSION(type) (BOOL)(((type) & GOPHER_TYPE_TELNET) != 0)
#define IS_GOPHER_BACKUP_SERVER(type) (BOOL)(((type) & GOPHER_TYPE_REDUNDANT) != 0)
#define IS_GOPHER_TN3270_SESSION(type) (BOOL)(((type) & GOPHER_TYPE_TN3270) != 0)
#define IS_GOPHER_ASK(type) (BOOL)(((type) & GOPHER_TYPE_ASK) != 0)
#define IS_GOPHER_PLUS(type) (BOOL)(((type) & GOPHER_TYPE_GOPHER_PLUS) != 0)
#define IS_GOPHER_TYPE_KNOWN(type) (BOOL)(!((type) & GOPHER_TYPE_UNKNOWN))
#define GOPHER_TYPE_FILE_MASK (GOPHER_TYPE_TEXT_FILE \
| GOPHER_TYPE_MAC_BINHEX \
| GOPHER_TYPE_DOS_ARCHIVE \
@ -1496,7 +1497,6 @@ INTERNETAPI DWORD WINAPI PrivacyGetZonePreferenceW(DWORD,DWORD,LPDWORD,LPWSTR,LP
#define EDITED_CACHE_ENTRY 0x00000008
#define COOKIE_CACHE_ENTRY 0x00100000
#define URLHISTORY_CACHE_ENTRY 0x00200000
#define DELETED_CACHE_ENTRY 0x00400000
#define TRACK_OFFLINE_CACHE_ENTRY 0x00000010
#define TRACK_ONLINE_CACHE_ENTRY 0x00000020
#define SPARSE_CACHE_ENTRY 0x00010000

View file

@ -123,6 +123,9 @@ BOOL WINAPI IsUrlCacheEntryExpiredW(LPCWSTR,DWORD,FILETIME*);
BOOL WINAPI SetUrlCacheConfigInfoA(LPINTERNET_CACHE_CONFIG_INFOA,DWORD);
BOOL WINAPI SetUrlCacheConfigInfoW(LPINTERNET_CACHE_CONFIG_INFOW,DWORD);
#define SetUrlCacheConfigInfo WINELIB_NAME_AW(SetUrlCacheConfigInfo)
BOOL WINAPI InternetGetSecurityInfoByURLA(LPSTR,PCCERT_CHAIN_CONTEXT*,DWORD*);
BOOL WINAPI InternetGetSecurityInfoByURLW(LPCWSTR,PCCERT_CHAIN_CONTEXT*,DWORD*);
#define InternetGetSecurityInfoByURL WINELIB_NAME_AW(InternetGetSecurityInfoByURL)
#ifdef __cplusplus
}

View file

@ -191,7 +191,7 @@ reactos/dll/win32/windowscodecs # Synced to Wine-1.5.19
reactos/dll/win32/winemp3.acm # Synced to Wine-1.5.19
reactos/dll/win32/wing32 # Out of sync
reactos/dll/win32/winhttp # Synced to Wine-1.5.4
reactos/dll/win32/wininet # Synced to Wine-1.5.4
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
reactos/dll/win32/winmm/wavemap # Forked at Wine-20050628