mirror of
https://github.com/reactos/reactos.git
synced 2025-05-16 15:50:24 +00:00
[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:
parent
e73afacf0f
commit
7f2d1fc323
14 changed files with 3648 additions and 2652 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) ¶ms );
|
||||
res = DialogBoxParamW( WININET_hModule, MAKEINTRESOURCEW( IDD_PROXYDLG ),
|
||||
hWnd, WININET_ProxyPasswordDialog, (LPARAM) ¶ms );
|
||||
break;
|
||||
case HTTP_STATUS_DENIED:
|
||||
return DialogBoxParamW( WININET_hModule, MAKEINTRESOURCEW( IDD_AUTHDLG ),
|
||||
res = DialogBoxParamW( WININET_hModule, MAKEINTRESOURCEW( IDD_AUTHDLG ),
|
||||
hWnd, WININET_PasswordDialog, (LPARAM) ¶ms );
|
||||
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) ¶ms );
|
||||
res = DialogBoxParamW( WININET_hModule, MAKEINTRESOURCEW( IDD_INVCERTDLG ),
|
||||
hWnd, WININET_InvalidCertificateDialog, (LPARAM) ¶ms );
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue