From 45a4774b499a099e868e5c26c19cdb67e094bd3c Mon Sep 17 00:00:00 2001 From: The Wine Synchronizer Date: Thu, 29 Nov 2007 12:52:01 +0000 Subject: [PATCH] Autosyncing with Wine HEAD svn path=/trunk/; revision=30894 --- reactos/dll/win32/wininet/cookie.c | 203 +-- reactos/dll/win32/wininet/dialogs.c | 60 +- reactos/dll/win32/wininet/ftp.c | 1084 ++++++++++----- reactos/dll/win32/wininet/gopher.c | 20 +- reactos/dll/win32/wininet/http.c | 1342 ++++++++++++------ reactos/dll/win32/wininet/internet.c | 1430 +++++++++----------- reactos/dll/win32/wininet/internet.h | 144 +- reactos/dll/win32/wininet/netconnection.c | 202 ++- reactos/dll/win32/wininet/resource.h | 2 +- reactos/dll/win32/wininet/rsrc.rc | 4 +- reactos/dll/win32/wininet/urlcache.c | 630 ++++++--- reactos/dll/win32/wininet/utility.c | 67 +- reactos/dll/win32/wininet/version.rc | 2 +- reactos/dll/win32/wininet/wininet.rbuild | 23 +- reactos/dll/win32/wininet/wininet.spec | 6 +- reactos/dll/win32/wininet/wininet_Bg.rc | 4 +- reactos/dll/win32/wininet/wininet_Cs.rc | 2 +- reactos/dll/win32/wininet/wininet_De.rc | 2 +- reactos/dll/win32/wininet/wininet_En.rc | 4 +- reactos/dll/win32/wininet/wininet_Eo.rc | 46 + reactos/dll/win32/wininet/wininet_Es.rc | 2 +- reactos/dll/win32/wininet/wininet_Fi.rc | 2 +- reactos/dll/win32/wininet/wininet_Fr.rc | 2 +- reactos/dll/win32/wininet/wininet_Hu.rc | 2 +- reactos/dll/win32/wininet/wininet_It.rc | 10 +- reactos/dll/win32/wininet/wininet_Ja.rc | 2 +- reactos/dll/win32/wininet/wininet_Ko.rc | 10 +- reactos/dll/win32/wininet/wininet_Nl.rc | 7 +- reactos/dll/win32/wininet/wininet_No.rc | 4 +- reactos/dll/win32/wininet/wininet_Pl.rc | 28 +- reactos/dll/win32/wininet/wininet_Pt.rc | 37 +- reactos/dll/win32/wininet/wininet_Ru.rc | 2 +- reactos/dll/win32/wininet/wininet_Si.rc | 2 +- reactos/dll/win32/wininet/wininet_Sv.rc | 44 + reactos/dll/win32/wininet/wininet_Tr.rc | 2 +- reactos/dll/win32/wininet/wininet_main.c | 4 +- reactos/dll/win32/wininet/wininet_ros.diff | 344 +++++ 37 files changed, 3677 insertions(+), 2104 deletions(-) create mode 100644 reactos/dll/win32/wininet/wininet_Eo.rc create mode 100644 reactos/dll/win32/wininet/wininet_Sv.rc create mode 100644 reactos/dll/win32/wininet/wininet_ros.diff diff --git a/reactos/dll/win32/wininet/cookie.c b/reactos/dll/win32/wininet/cookie.c index a507ed46921..2eef2d99748 100644 --- a/reactos/dll/win32/wininet/cookie.c +++ b/reactos/dll/win32/wininet/cookie.c @@ -17,7 +17,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include "config.h" @@ -39,8 +39,6 @@ #include "wine/debug.h" #include "internet.h" -#include "wine/list.h" - #define RESPONSE_TIMEOUT 30 /* FROM internet.c */ @@ -176,7 +174,7 @@ static cookie_domain *COOKIE_addDomain(LPCWSTR domain, LPCWSTR path) return newDomain; } -static void COOKIE_crackUrlSimple(LPCWSTR lpszUrl, LPWSTR hostName, int hostNameLen, LPWSTR path, int pathLen) +static BOOL COOKIE_crackUrlSimple(LPCWSTR lpszUrl, LPWSTR hostName, int hostNameLen, LPWSTR path, int pathLen) { URL_COMPONENTSW UrlComponents; @@ -186,10 +184,14 @@ static void COOKIE_crackUrlSimple(LPCWSTR lpszUrl, LPWSTR hostName, int hostName UrlComponents.lpszUrlPath = path; UrlComponents.lpszUserName = NULL; UrlComponents.lpszHostName = hostName; + UrlComponents.dwExtraInfoLength = 0; + UrlComponents.dwPasswordLength = 0; + UrlComponents.dwSchemeLength = 0; + UrlComponents.dwUserNameLength = 0; UrlComponents.dwHostNameLength = hostNameLen; UrlComponents.dwUrlPathLength = pathLen; - InternetCrackUrlW(lpszUrl, 0, 0, &UrlComponents); + return InternetCrackUrlW(lpszUrl, 0, 0, &UrlComponents); } /* match a domain. domain must match if the domain is not NULL. path must match if the path is not NULL */ @@ -202,8 +204,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)) @@ -256,15 +258,23 @@ static void COOKIE_deleteDomain(cookie_domain *deadDomain) BOOL WINAPI InternetGetCookieW(LPCWSTR lpszUrl, LPCWSTR lpszCookieName, LPWSTR lpCookieData, LPDWORD lpdwSize) { + BOOL ret; struct list * cursor; - int cnt = 0, domain_count = 0; - int cookie_count = 0; + unsigned int cnt = 0, domain_count = 0, cookie_count = 0; WCHAR hostName[2048], path[2048]; TRACE("(%s, %s, %p, %p)\n", debugstr_w(lpszUrl),debugstr_w(lpszCookieName), - lpCookieData, lpdwSize); + lpCookieData, lpdwSize); - COOKIE_crackUrlSimple(lpszUrl, hostName, sizeof(hostName)/sizeof(hostName[0]), path, sizeof(path)/sizeof(path[0])); + if (!lpszUrl) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + hostName[0] = 0; + ret = COOKIE_crackUrlSimple(lpszUrl, hostName, sizeof(hostName)/sizeof(hostName[0]), path, sizeof(path)/sizeof(path[0])); + if (!ret || !hostName[0]) return FALSE; LIST_FOR_EACH(cursor, &domain_list) { @@ -274,28 +284,35 @@ BOOL WINAPI InternetGetCookieW(LPCWSTR lpszUrl, LPCWSTR lpszCookieName, struct list * cursor; domain_count++; TRACE("found domain %p\n", cookiesDomain); - + LIST_FOR_EACH(cursor, &cookiesDomain->cookie_list) { cookie *thisCookie = LIST_ENTRY(cursor, cookie, entry); if (lpCookieData == NULL) /* return the size of the buffer required to lpdwSize */ { - if (cookie_count != 0) - cnt += 2; /* '; ' */ + unsigned int len; + + if (cookie_count) cnt += 2; /* '; ' */ cnt += strlenW(thisCookie->lpCookieName); - cnt += 1; /* = */ - cnt += strlenW(thisCookie->lpCookieData); + if ((len = strlenW(thisCookie->lpCookieData))) + { + cnt += 1; /* = */ + cnt += len; + } } else { static const WCHAR szsc[] = { ';',' ',0 }; - static const WCHAR szpseq[] = { '%','s','=','%','s',0 }; - if (cookie_count != 0) - cnt += snprintfW(lpCookieData + cnt, *lpdwSize - cnt, szsc); - cnt += snprintfW(lpCookieData + cnt, *lpdwSize - cnt, szpseq, - thisCookie->lpCookieName, - thisCookie->lpCookieData); - TRACE("Cookie: %s=%s\n", debugstr_w(thisCookie->lpCookieName), debugstr_w(thisCookie->lpCookieData)); + static const WCHAR szname[] = { '%','s',0 }; + static const WCHAR szdata[] = { '=','%','s',0 }; + + if (cookie_count) cnt += snprintfW(lpCookieData + cnt, *lpdwSize - cnt, szsc); + cnt += snprintfW(lpCookieData + cnt, *lpdwSize - cnt, szname, thisCookie->lpCookieName); + + if (thisCookie->lpCookieData[0]) + cnt += snprintfW(lpCookieData + cnt, *lpdwSize - cnt, szdata, thisCookie->lpCookieData); + + TRACE("Cookie: %s\n", debugstr_w(lpCookieData)); } cookie_count++; } @@ -311,15 +328,14 @@ BOOL WINAPI InternetGetCookieW(LPCWSTR lpszUrl, LPCWSTR lpszCookieName, if (lpCookieData == NULL) { - cnt += 1; /* NULL */ - *lpdwSize = cnt*sizeof(WCHAR); - TRACE("returning\n"); - return TRUE; + *lpdwSize = (cnt + 1) * sizeof(WCHAR); + TRACE("returning %u\n", *lpdwSize); + return TRUE; } - *lpdwSize = (cnt + 1)*sizeof(WCHAR); + *lpdwSize = cnt + 1; - TRACE("Returning %i (from %i domains): %s\n", cnt, domain_count, + TRACE("Returning %u (from %u domains): %s\n", cnt, domain_count, debugstr_w(lpCookieData)); return (cnt ? TRUE : FALSE); @@ -365,12 +381,16 @@ BOOL WINAPI InternetGetCookieA(LPCSTR lpszUrl, LPCSTR lpszCookieName, { szCookieData = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); if( !szCookieData ) - return FALSE; + { + r = FALSE; + } + else + { + r = InternetGetCookieW( szUrl, szCookieName, szCookieData, &len ); - r = InternetGetCookieW( szUrl, szCookieName, szCookieData, &len ); - - *lpdwSize = WideCharToMultiByte( CP_ACP, 0, szCookieData, len, - lpCookieData, *lpdwSize, NULL, NULL ); + *lpdwSize = WideCharToMultiByte( CP_ACP, 0, szCookieData, len, + lpCookieData, *lpdwSize, NULL, NULL ); + } } HeapFree( GetProcessHeap(), 0, szCookieData ); @@ -380,6 +400,34 @@ BOOL WINAPI InternetGetCookieA(LPCSTR lpszUrl, LPCSTR lpszCookieName, return r; } +static BOOL set_cookie(LPCWSTR domain, LPCWSTR path, LPCWSTR cookie_name, LPCWSTR cookie_data) +{ + cookie_domain *thisCookieDomain = NULL; + cookie *thisCookie; + struct list *cursor; + + LIST_FOR_EACH(cursor, &domain_list) + { + thisCookieDomain = LIST_ENTRY(cursor, cookie_domain, entry); + if (COOKIE_matchDomain(domain, NULL /* FIXME: path */, thisCookieDomain, FALSE)) + break; + thisCookieDomain = NULL; + } + + if (!thisCookieDomain) + thisCookieDomain = COOKIE_addDomain(domain, path); + + if ((thisCookie = COOKIE_findCookie(thisCookieDomain, cookie_name))) + COOKIE_deleteCookie(thisCookie, FALSE); + + TRACE("setting cookie %s=%s for domain %s\n", debugstr_w(cookie_name), + debugstr_w(cookie_data), debugstr_w(thisCookieDomain->lpCookieDomain)); + + if (!COOKIE_addCookie(thisCookieDomain, cookie_name, cookie_data)) + return FALSE; + + return TRUE; +} /*********************************************************************** * InternetSetCookieW (WININET.@) @@ -394,64 +442,47 @@ BOOL WINAPI InternetGetCookieA(LPCSTR lpszUrl, LPCSTR lpszCookieName, BOOL WINAPI InternetSetCookieW(LPCWSTR lpszUrl, LPCWSTR lpszCookieName, LPCWSTR lpCookieData) { - cookie_domain *thisCookieDomain = NULL; - cookie *thisCookie; + BOOL ret; WCHAR hostName[2048], path[2048]; - struct list * cursor; TRACE("(%s,%s,%s)\n", debugstr_w(lpszUrl), debugstr_w(lpszCookieName), debugstr_w(lpCookieData)); - if (!lpCookieData || !strlenW(lpCookieData)) + if (!lpszUrl || !lpCookieData) { - TRACE("no cookie data, not adding\n"); - return FALSE; + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; } + + hostName[0] = path[0] = 0; + ret = COOKIE_crackUrlSimple(lpszUrl, hostName, sizeof(hostName)/sizeof(hostName[0]), path, sizeof(path)/sizeof(path[0])); + if (!ret || !hostName[0]) return FALSE; + if (!lpszCookieName) { - /* some apps (or is it us??) try to add a cookie with no cookie name, but - * the cookie data in the form of name=data. */ - /* FIXME, probably a bug here, for now I don't care */ - WCHAR *ourCookieName, *ourCookieData; - int ourCookieNameSize; - BOOL ret; + unsigned int len; + WCHAR *cookie, *data; - if (!(ourCookieData = strchrW(lpCookieData, '='))) - { - TRACE("something terribly wrong with cookie data %s\n", - debugstr_w(ourCookieData)); - return FALSE; - } - ourCookieNameSize = ourCookieData - lpCookieData; - ourCookieData += 1; - ourCookieName = HeapAlloc(GetProcessHeap(), 0, - (ourCookieNameSize + 1)*sizeof(WCHAR)); - memcpy(ourCookieName, ourCookieData, ourCookieNameSize * sizeof(WCHAR)); - ourCookieName[ourCookieNameSize] = '\0'; - TRACE("setting (hacked) cookie of %s, %s\n", - debugstr_w(ourCookieName), debugstr_w(ourCookieData)); - ret = InternetSetCookieW(lpszUrl, ourCookieName, ourCookieData); - HeapFree(GetProcessHeap(), 0, ourCookieName); + len = strlenW(lpCookieData); + if (!(cookie = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)))) + { + SetLastError(ERROR_OUTOFMEMORY); + return FALSE; + } + strcpyW(cookie, lpCookieData); + + /* some apps (or is it us??) try to add a cookie with no cookie name, but + * the cookie data in the form of name[=data]. + */ + if (!(data = strchrW(cookie, '='))) data = cookie + len; + else data++; + + ret = set_cookie(hostName, path, cookie, data); + + HeapFree(GetProcessHeap(), 0, cookie); return ret; } - - COOKIE_crackUrlSimple(lpszUrl, hostName, sizeof(hostName)/sizeof(hostName[0]), path, sizeof(path)/sizeof(path[0])); - - LIST_FOR_EACH(cursor, &domain_list) - { - thisCookieDomain = LIST_ENTRY(cursor, cookie_domain, entry); - if (COOKIE_matchDomain(hostName, NULL /* FIXME: path */, thisCookieDomain, FALSE)) - break; - thisCookieDomain = NULL; - } - if (!thisCookieDomain) - thisCookieDomain = COOKIE_addDomain(hostName, path); - - if ((thisCookie = COOKIE_findCookie(thisCookieDomain, lpszCookieName))) - COOKIE_deleteCookie(thisCookie, FALSE); - - thisCookie = COOKIE_addCookie(thisCookieDomain, lpszCookieName, lpCookieData); - return TRUE; + return set_cookie(hostName, path, lpszCookieName, lpCookieData); } @@ -513,7 +544,7 @@ BOOL WINAPI InternetSetCookieA(LPCSTR lpszUrl, LPCSTR lpszCookieName, DWORD WINAPI InternetSetCookieExA( LPCSTR lpszURL, LPCSTR lpszCookieName, LPCSTR lpszCookieData, DWORD dwFlags, DWORD_PTR dwReserved) { - FIXME("(%s, %s, %s, 0x%08lx, 0x%08lx) stub\n", + FIXME("(%s, %s, %s, 0x%08x, 0x%08lx) stub\n", debugstr_a(lpszURL), debugstr_a(lpszCookieName), debugstr_a(lpszCookieData), dwFlags, dwReserved); return TRUE; @@ -532,7 +563,7 @@ DWORD WINAPI InternetSetCookieExA( LPCSTR lpszURL, LPCSTR lpszCookieName, LPCSTR DWORD WINAPI InternetSetCookieExW( LPCWSTR lpszURL, LPCWSTR lpszCookieName, LPCWSTR lpszCookieData, DWORD dwFlags, DWORD_PTR dwReserved) { - FIXME("(%s, %s, %s, 0x%08lx, 0x%08lx) stub\n", + FIXME("(%s, %s, %s, 0x%08x, 0x%08lx) stub\n", debugstr_w(lpszURL), debugstr_w(lpszCookieName), debugstr_w(lpszCookieData), dwFlags, dwReserved); return TRUE; @@ -546,7 +577,7 @@ DWORD WINAPI InternetSetCookieExW( LPCWSTR lpszURL, LPCWSTR lpszCookieName, LPCW BOOL WINAPI InternetGetCookieExA( LPCSTR pchURL, LPCSTR pchCookieName, LPSTR pchCookieData, LPDWORD pcchCookieData, DWORD dwFlags, LPVOID lpReserved) { - FIXME("(%s, %s, %s, %p, 0x%08lx, %p) stub\n", + FIXME("(%s, %s, %s, %p, 0x%08x, %p) stub\n", debugstr_a(pchURL), debugstr_a(pchCookieName), debugstr_a(pchCookieData), pcchCookieData, dwFlags, lpReserved); return FALSE; @@ -565,7 +596,7 @@ BOOL WINAPI InternetGetCookieExA( LPCSTR pchURL, LPCSTR pchCookieName, LPSTR pch BOOL WINAPI InternetGetCookieExW( LPCWSTR pchURL, LPCWSTR pchCookieName, LPWSTR pchCookieData, LPDWORD pcchCookieData, DWORD dwFlags, LPVOID lpReserved) { - FIXME("(%s, %s, %s, %p, 0x%08lx, %p) stub\n", + FIXME("(%s, %s, %s, %p, 0x%08x, %p) stub\n", debugstr_w(pchURL), debugstr_w(pchCookieName), debugstr_w(pchCookieData), pcchCookieData, dwFlags, lpReserved); return FALSE; @@ -641,7 +672,7 @@ BOOL WINAPI InternetGetPerSiteCookieDecisionW( LPCWSTR pwchHostName, unsigned lo */ BOOL WINAPI InternetSetPerSiteCookieDecisionA( LPCSTR pchHostName, DWORD dwDecision ) { - FIXME("(%s, 0x%08lx) stub\n", debugstr_a(pchHostName), dwDecision); + FIXME("(%s, 0x%08x) stub\n", debugstr_a(pchHostName), dwDecision); return FALSE; } @@ -650,6 +681,6 @@ BOOL WINAPI InternetSetPerSiteCookieDecisionA( LPCSTR pchHostName, DWORD dwDecis */ BOOL WINAPI InternetSetPerSiteCookieDecisionW( LPCWSTR pchHostName, DWORD dwDecision ) { - FIXME("(%s, 0x%08lx) stub\n", debugstr_w(pchHostName), dwDecision); + FIXME("(%s, 0x%08x) stub\n", debugstr_w(pchHostName), dwDecision); return FALSE; } diff --git a/reactos/dll/win32/wininet/dialogs.c b/reactos/dll/win32/wininet/dialogs.c index 343d2abbeba..dd5aa315a63 100644 --- a/reactos/dll/win32/wininet/dialogs.c +++ b/reactos/dll/win32/wininet/dialogs.c @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include "config.h" @@ -29,7 +29,6 @@ #include "winreg.h" #include "wininet.h" #include "winnetwk.h" -#include "winnls.h" #include "wine/debug.h" #include "winerror.h" #define NO_SHLWAPI_STREAM @@ -68,11 +67,11 @@ static BOOL WININET_GetProxyServer( HINTERNET hRequest, LPWSTR szBuf, DWORD sz ) if (NULL == lpwhr) return FALSE; - lpwhs = (LPWININETHTTPSESSIONW) lpwhr->hdr.lpwhparent; + lpwhs = lpwhr->lpHttpSession; if (NULL == lpwhs) return FALSE; - hIC = (LPWININETAPPINFOW) lpwhs->hdr.lpwhparent; + hIC = lpwhs->lpAppInfo; if (NULL == hIC) return FALSE; @@ -80,7 +79,7 @@ static BOOL WININET_GetProxyServer( HINTERNET hRequest, LPWSTR szBuf, DWORD sz ) /* FIXME: perhaps it would be better to use InternetCrackUrl here */ p = strchrW(szBuf, ':'); - if(*p) + if (p) *p = 0; return TRUE; @@ -108,19 +107,22 @@ static BOOL WININET_GetAuthRealm( HINTERNET hRequest, LPWSTR szBuf, DWORD sz ) * dealing with 'Basic' Authentication */ p = strchrW( szBuf, ' ' ); - if( p && !strncmpW( p+1, szRealm, strlenW(szRealm) ) ) + if( !p || strncmpW( p+1, szRealm, strlenW(szRealm) ) ) { - /* remove quotes */ - p += 7; - if( *p == '"' ) - { - p++; - q = strrchrW( p, '"' ); - if( q ) - *q = 0; - } + ERR("proxy response wrong? (%s)\n", debugstr_w(szBuf)); + return FALSE; } + + /* remove quotes */ + p += 7; + if( *p == '"' ) + { + p++; + q = strrchrW( p, '"' ); + if( q ) + *q = 0; + } strcpyW( szBuf, p ); return TRUE; @@ -129,7 +131,7 @@ static BOOL WININET_GetAuthRealm( HINTERNET hRequest, LPWSTR szBuf, DWORD sz ) /*********************************************************************** * WININET_GetSetPassword */ -static BOOL WININET_GetSetPassword( HWND hdlg, LPCWSTR szServer, +static BOOL WININET_GetSetPassword( HWND hdlg, LPCWSTR szServer, LPCWSTR szRealm, BOOL bSet ) { WCHAR szResource[0x80], szUserPass[0x40]; @@ -158,11 +160,11 @@ static BOOL WININET_GetSetPassword( HWND hdlg, LPCWSTR szServer, if( bSet ) { szUserPass[0] = 0; - GetWindowTextW( hUserItem, szUserPass, + GetWindowTextW( hUserItem, szUserPass, (sizeof szUserPass-1)/sizeof(WCHAR) ); lstrcatW(szUserPass, szColon); u_len = strlenW( szUserPass ); - GetWindowTextW( hPassItem, szUserPass+u_len, + GetWindowTextW( hPassItem, szUserPass+u_len, (sizeof szUserPass)/sizeof(WCHAR)-u_len ); r_len = (strlenW( szResource ) + 1)*sizeof(WCHAR); @@ -205,27 +207,27 @@ static BOOL WININET_SetProxyAuthorization( HINTERNET hRequest, lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hRequest ); if( !lpwhr ) return FALSE; - - lpwhs = (LPWININETHTTPSESSIONW) lpwhr->hdr.lpwhparent; + + lpwhs = lpwhr->lpHttpSession; if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION) { INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); return FALSE; } - hIC = (LPWININETAPPINFOW) lpwhs->hdr.lpwhparent; + hIC = lpwhs->lpAppInfo; p = HeapAlloc( GetProcessHeap(), 0, (strlenW( username ) + 1)*sizeof(WCHAR) ); if( !p ) return FALSE; - + lstrcpyW( p, username ); hIC->lpszProxyUsername = p; p = HeapAlloc( GetProcessHeap(), 0, (strlenW( password ) + 1)*sizeof(WCHAR) ); if( !p ) return FALSE; - + lstrcpyW( p, password ); hIC->lpszProxyPassword = p; @@ -259,7 +261,7 @@ static INT_PTR WINAPI WININET_ProxyPasswordDialog( } /* extract the name of the proxy server */ - if( WININET_GetProxyServer( params->hRequest, + if( WININET_GetProxyServer( params->hRequest, szServer, sizeof szServer/sizeof(WCHAR)) ) { hitem = GetDlgItem( hdlg, IDC_PROXY ); @@ -285,7 +287,7 @@ static INT_PTR WINAPI WININET_ProxyPasswordDialog( hitem = GetDlgItem( hdlg, IDC_USERNAME ); if( hitem ) GetWindowTextW( hitem, username, sizeof username/sizeof(WCHAR) ); - + password[0] = 0; hitem = GetDlgItem( hdlg, IDC_PASSWORD ); if( hitem ) @@ -296,7 +298,7 @@ static INT_PTR WINAPI WININET_ProxyPasswordDialog( SendMessageW( hitem, BM_GETSTATE, 0, 0 ) && WININET_GetAuthRealm( params->hRequest, szRealm, sizeof szRealm/sizeof(WCHAR)) && - WININET_GetProxyServer( params->hRequest, + WININET_GetProxyServer( params->hRequest, szServer, sizeof szServer/sizeof(WCHAR)) ) { WININET_GetSetPassword( hdlg, szServer, szRealm, TRUE ); @@ -333,7 +335,7 @@ static INT WININET_GetConnectionStatus( HINTERNET hRequest ) return -1; dwStatus = atoiW( szStatus ); - TRACE("request %p status = %ld\n", hRequest, dwStatus ); + TRACE("request %p status = %d\n", hRequest, dwStatus ); return dwStatus; } @@ -349,7 +351,7 @@ DWORD WINAPI InternetErrorDlg(HWND hWnd, HINTERNET hRequest, HMODULE hwininet = GetModuleHandleA( "wininet.dll" ); INT dwStatus; - TRACE("%p %p %ld %08lx %p\n", hWnd, hRequest, dwError, dwFlags, lppvData); + TRACE("%p %p %d %08x %p\n", hWnd, hRequest, dwError, dwFlags, lppvData); params.hWnd = hWnd; params.hRequest = hRequest; @@ -377,7 +379,7 @@ DWORD WINAPI InternetErrorDlg(HWND hWnd, HINTERNET hRequest, case ERROR_INTERNET_POST_IS_NON_SECURE: case ERROR_INTERNET_SEC_CERT_CN_INVALID: case ERROR_INTERNET_SEC_CERT_DATE_INVALID: - FIXME("Need to display dialog for error %ld\n", dwError); + FIXME("Need to display dialog for error %d\n", dwError); return ERROR_SUCCESS; } return ERROR_INVALID_PARAMETER; diff --git a/reactos/dll/win32/wininet/ftp.c b/reactos/dll/win32/wininet/ftp.c index 46320dabe46..ad42abc49c5 100644 --- a/reactos/dll/win32/wininet/ftp.c +++ b/reactos/dll/win32/wininet/ftp.c @@ -4,6 +4,7 @@ * Copyright 1999 Corel Corporation * Copyright 2004 Mike McCormack for CodeWeavers * Copyright 2004 Kevin Koltzau + * Copyright 2007 Hans Leidekker * * Ulrich Czekalla * Noureddine Jemmali @@ -23,7 +24,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include "config.h" @@ -57,6 +58,7 @@ #include "wine/debug.h" #include "internet.h" +typedef size_t socklen_t; WINE_DEFAULT_DEBUG_CHANNEL(wininet); @@ -64,6 +66,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(wininet); #define szCRLF "\r\n" #define MAX_BACKLOG 5 +/* Testing shows that Windows only accepts dwFlags where the last + * 3 (yes 3) bits define FTP_TRANSFER_TYPE_UNKNOWN, FTP_TRANSFER_TYPE_ASCII or FTP_TRANSFER_TYPE_BINARY. + */ +#define FTP_CONDITION_MASK 0x0007 + typedef enum { /* FTP commands with arguments. */ FTP_CMD_ACCT, @@ -90,7 +97,7 @@ typedef enum { FTP_CMD_QUIT, } FTP_COMMAND; -static const CHAR *szFtpCommands[] = { +static const CHAR *const szFtpCommands[] = { "ACCT", "CWD", "DELE", @@ -118,21 +125,21 @@ static const WCHAR szNoAccount[] = {'n','o','a','c','c','o','u','n','t','\0'}; static void FTP_CloseFileTransferHandle(LPWININETHANDLEHEADER hdr); static void FTP_CloseSessionHandle(LPWININETHANDLEHEADER hdr); +static void FTP_CloseConnection(LPWININETHANDLEHEADER hdr); static void FTP_CloseFindNextHandle(LPWININETHANDLEHEADER hdr); static BOOL FTP_SendCommand(INT nSocket, FTP_COMMAND ftpCmd, LPCWSTR lpszParam, - INTERNET_STATUS_CALLBACK lpfnStatusCB, LPWININETHANDLEHEADER hdr, DWORD dwContext); + INTERNET_STATUS_CALLBACK lpfnStatusCB, LPWININETHANDLEHEADER hdr, DWORD_PTR dwContext); static BOOL FTP_SendStore(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, DWORD dwType); static BOOL FTP_GetDataSocket(LPWININETFTPSESSIONW lpwfs, LPINT nDataSocket); static BOOL FTP_SendData(LPWININETFTPSESSIONW lpwfs, INT nDataSocket, HANDLE hFile); -static INT FTP_ReceiveResponse(LPWININETFTPSESSIONW lpwfs, DWORD dwContext); -static DWORD FTP_SendRetrieve(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, DWORD dwType); -static BOOL FTP_RetrieveFileData(LPWININETFTPSESSIONW lpwfs, INT nDataSocket, DWORD nBytes, HANDLE hFile); +static INT FTP_ReceiveResponse(LPWININETFTPSESSIONW lpwfs, DWORD_PTR dwContext); +static BOOL FTP_SendRetrieve(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, DWORD dwType); +static BOOL FTP_RetrieveFileData(LPWININETFTPSESSIONW lpwfs, INT nDataSocket, HANDLE hFile); static BOOL FTP_InitListenSocket(LPWININETFTPSESSIONW lpwfs); static BOOL FTP_ConnectToHost(LPWININETFTPSESSIONW lpwfs); static BOOL FTP_SendPassword(LPWININETFTPSESSIONW lpwfs); static BOOL FTP_SendAccount(LPWININETFTPSESSIONW lpwfs); static BOOL FTP_SendType(LPWININETFTPSESSIONW lpwfs, DWORD dwType); -static BOOL FTP_GetFileSize(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, DWORD *dwSize); static BOOL FTP_SendPort(LPWININETFTPSESSIONW lpwfs); static BOOL FTP_DoPassive(LPWININETFTPSESSIONW lpwfs); static BOOL FTP_SendPortOrPasv(LPWININETFTPSESSIONW lpwfs); @@ -141,7 +148,7 @@ static BOOL FTP_ParseNextFile(INT nSocket, LPCWSTR lpszSearchFile, LPFILEPROPERT static BOOL FTP_ParseDirectory(LPWININETFTPSESSIONW lpwfs, INT nSocket, LPCWSTR lpszSearchFile, LPFILEPROPERTIESW *lpafp, LPDWORD dwfp); static HINTERNET FTP_ReceiveFileList(LPWININETFTPSESSIONW lpwfs, INT nSocket, LPCWSTR lpszSearchFile, - LPWIN32_FIND_DATAW lpFindFileData, DWORD dwContext); + LPWIN32_FIND_DATAW lpFindFileData, DWORD_PTR dwContext); static DWORD FTP_SetResponseError(DWORD dwResponse); /*********************************************************************** @@ -155,12 +162,12 @@ static DWORD FTP_SetResponseError(DWORD dwResponse); * */ BOOL WINAPI FtpPutFileA(HINTERNET hConnect, LPCSTR lpszLocalFile, - LPCSTR lpszNewRemoteFile, DWORD dwFlags, DWORD dwContext) + LPCSTR lpszNewRemoteFile, DWORD dwFlags, DWORD_PTR dwContext) { LPWSTR lpwzLocalFile; LPWSTR lpwzNewRemoteFile; BOOL ret; - + lpwzLocalFile = lpszLocalFile?WININET_strdup_AtoW(lpszLocalFile):NULL; lpwzNewRemoteFile = lpszNewRemoteFile?WININET_strdup_AtoW(lpszNewRemoteFile):NULL; ret = FtpPutFileW(hConnect, lpwzLocalFile, lpwzNewRemoteFile, @@ -170,6 +177,20 @@ BOOL WINAPI FtpPutFileA(HINTERNET hConnect, LPCSTR lpszLocalFile, return ret; } +static void AsyncFtpPutFileProc(WORKREQUEST *workRequest) +{ + struct WORKREQ_FTPPUTFILEW const *req = &workRequest->u.FtpPutFileW; + LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr; + + TRACE("%p\n", lpwfs); + + FTP_FtpPutFileW(lpwfs, req->lpszLocalFile, + req->lpszNewRemoteFile, req->dwFlags, req->dwContext); + + HeapFree(GetProcessHeap(), 0, req->lpszLocalFile); + HeapFree(GetProcessHeap(), 0, req->lpszNewRemoteFile); +} + /*********************************************************************** * FtpPutFileW (WININET.@) * @@ -181,27 +202,51 @@ BOOL WINAPI FtpPutFileA(HINTERNET hConnect, LPCSTR lpszLocalFile, * */ BOOL WINAPI FtpPutFileW(HINTERNET hConnect, LPCWSTR lpszLocalFile, - LPCWSTR lpszNewRemoteFile, DWORD dwFlags, DWORD dwContext) + LPCWSTR lpszNewRemoteFile, DWORD dwFlags, DWORD_PTR dwContext) { LPWININETFTPSESSIONW lpwfs; LPWININETAPPINFOW hIC = NULL; BOOL r = FALSE; + if (!lpszLocalFile || !lpszNewRemoteFile) + { + INTERNET_SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hConnect ); - if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype) + if (!lpwfs) + { + INTERNET_SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + if (WH_HFTPSESSION != lpwfs->hdr.htype) { INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); goto lend; } - hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent; + if (lpwfs->download_in_progress != NULL) + { + INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS); + goto lend; + } + + if ((dwFlags & FTP_CONDITION_MASK) > FTP_TRANSFER_TYPE_BINARY) + { + INTERNET_SetLastError(ERROR_INVALID_PARAMETER); + goto lend; + } + + hIC = lpwfs->lpAppInfo; if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) { WORKREQUEST workRequest; struct WORKREQ_FTPPUTFILEW *req = &workRequest.u.FtpPutFileW; - workRequest.asyncall = FTPPUTFILEW; - workRequest.hdr = WININET_AddRef( &lpwfs->hdr ); + workRequest.asyncproc = AsyncFtpPutFileProc; + workRequest.hdr = WININET_AddRef( &lpwfs->hdr ); req->lpszLocalFile = WININET_strdupW(lpszLocalFile); req->lpszNewRemoteFile = WININET_strdupW(lpszNewRemoteFile); req->dwFlags = dwFlags; @@ -216,8 +261,7 @@ BOOL WINAPI FtpPutFileW(HINTERNET hConnect, LPCWSTR lpszLocalFile, } lend: - if( lpwfs ) - WININET_Release( &lpwfs->hdr ); + WININET_Release( &lpwfs->hdr ); return r; } @@ -233,35 +277,26 @@ lend: * */ BOOL WINAPI FTP_FtpPutFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszLocalFile, - LPCWSTR lpszNewRemoteFile, DWORD dwFlags, DWORD dwContext) + LPCWSTR lpszNewRemoteFile, DWORD dwFlags, DWORD_PTR dwContext) { - HANDLE hFile = NULL; + HANDLE hFile; BOOL bSuccess = FALSE; LPWININETAPPINFOW hIC = NULL; INT nResCode; TRACE(" lpszLocalFile(%s) lpszNewRemoteFile(%s)\n", debugstr_w(lpszLocalFile), debugstr_w(lpszNewRemoteFile)); - if (!lpszLocalFile || !lpszNewRemoteFile) - { - INTERNET_SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - assert( WH_HFTPSESSION == lpwfs->hdr.htype); - /* Clear any error information */ INTERNET_SetLastError(0); /* Open file to be uploaded */ if (INVALID_HANDLE_VALUE == (hFile = CreateFileW(lpszLocalFile, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0))) - { - INTERNET_SetLastError(ERROR_FILE_NOT_FOUND); - goto lend; - } + /* Let CreateFile set the appropriate error */ + return FALSE; + + hIC = lpwfs->lpAppInfo; - hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent; SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0); if (FTP_SendStore(lpwfs, lpszNewRemoteFile, dwFlags)) @@ -284,7 +319,6 @@ BOOL WINAPI FTP_FtpPutFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszLocalFile, } } -lend: if (lpwfs->lstnSocket != -1) closesocket(lpwfs->lstnSocket); @@ -298,8 +332,7 @@ lend: &iar, sizeof(INTERNET_ASYNC_RESULT)); } - if (hFile) - CloseHandle(hFile); + CloseHandle(hFile); return bSuccess; } @@ -319,7 +352,7 @@ BOOL WINAPI FtpSetCurrentDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory) { LPWSTR lpwzDirectory; BOOL ret; - + lpwzDirectory = lpszDirectory?WININET_strdup_AtoW(lpszDirectory):NULL; ret = FtpSetCurrentDirectoryW(hConnect, lpwzDirectory); HeapFree(GetProcessHeap(), 0, lpwzDirectory); @@ -327,6 +360,17 @@ BOOL WINAPI FtpSetCurrentDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory) } +static void AsyncFtpSetCurrentDirectoryProc(WORKREQUEST *workRequest) +{ + struct WORKREQ_FTPSETCURRENTDIRECTORYW const *req = &workRequest->u.FtpSetCurrentDirectoryW; + LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr; + + TRACE("%p\n", lpwfs); + + FTP_FtpSetCurrentDirectoryW(lpwfs, req->lpszDirectory); + HeapFree(GetProcessHeap(), 0, req->lpszDirectory); +} + /*********************************************************************** * FtpSetCurrentDirectoryW (WININET.@) * @@ -339,10 +383,16 @@ BOOL WINAPI FtpSetCurrentDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory) */ BOOL WINAPI FtpSetCurrentDirectoryW(HINTERNET hConnect, LPCWSTR lpszDirectory) { - LPWININETFTPSESSIONW lpwfs; + LPWININETFTPSESSIONW lpwfs = NULL; LPWININETAPPINFOW hIC = NULL; BOOL r = FALSE; + if (!lpszDirectory) + { + INTERNET_SetLastError(ERROR_INVALID_PARAMETER); + goto lend; + } + lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hConnect ); if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype) { @@ -350,16 +400,22 @@ BOOL WINAPI FtpSetCurrentDirectoryW(HINTERNET hConnect, LPCWSTR lpszDirectory) goto lend; } + if (lpwfs->download_in_progress != NULL) + { + INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS); + goto lend; + } + TRACE("lpszDirectory(%s)\n", debugstr_w(lpszDirectory)); - hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent; + hIC = lpwfs->lpAppInfo; if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) { WORKREQUEST workRequest; struct WORKREQ_FTPSETCURRENTDIRECTORYW *req; - workRequest.asyncall = FTPSETCURRENTDIRECTORYW; - workRequest.hdr = WININET_AddRef( &lpwfs->hdr ); + workRequest.asyncproc = AsyncFtpSetCurrentDirectoryProc; + workRequest.hdr = WININET_AddRef( &lpwfs->hdr ); req = &workRequest.u.FtpSetCurrentDirectoryW; req->lpszDirectory = WININET_strdupW(lpszDirectory); @@ -396,16 +452,10 @@ BOOL WINAPI FTP_FtpSetCurrentDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpsz TRACE("lpszDirectory(%s)\n", debugstr_w(lpszDirectory)); - if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype) - { - INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); - return FALSE; - } - /* Clear any error information */ INTERNET_SetLastError(0); - hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent; + hIC = lpwfs->lpAppInfo; if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_CWD, lpszDirectory, lpwfs->hdr.lpfnStatusCB, &lpwfs->hdr, lpwfs->hdr.dwContext)) goto lend; @@ -448,7 +498,7 @@ BOOL WINAPI FtpCreateDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory) { LPWSTR lpwzDirectory; BOOL ret; - + lpwzDirectory = lpszDirectory?WININET_strdup_AtoW(lpszDirectory):NULL; ret = FtpCreateDirectoryW(hConnect, lpwzDirectory); HeapFree(GetProcessHeap(), 0, lpwzDirectory); @@ -456,6 +506,17 @@ BOOL WINAPI FtpCreateDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory) } +static void AsyncFtpCreateDirectoryProc(WORKREQUEST *workRequest) +{ + struct WORKREQ_FTPCREATEDIRECTORYW const *req = &workRequest->u.FtpCreateDirectoryW; + LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr; + + TRACE(" %p\n", lpwfs); + + FTP_FtpCreateDirectoryW(lpwfs, req->lpszDirectory); + HeapFree(GetProcessHeap(), 0, req->lpszDirectory); +} + /*********************************************************************** * FtpCreateDirectoryW (WININET.@) * @@ -473,20 +534,38 @@ BOOL WINAPI FtpCreateDirectoryW(HINTERNET hConnect, LPCWSTR lpszDirectory) BOOL r = FALSE; lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hConnect ); - if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype) + if (!lpwfs) + { + INTERNET_SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + if (WH_HFTPSESSION != lpwfs->hdr.htype) { INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); goto lend; } - hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent; + if (lpwfs->download_in_progress != NULL) + { + INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS); + goto lend; + } + + if (!lpszDirectory) + { + INTERNET_SetLastError(ERROR_INVALID_PARAMETER); + goto lend; + } + + hIC = lpwfs->lpAppInfo; if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) { WORKREQUEST workRequest; struct WORKREQ_FTPCREATEDIRECTORYW *req; - workRequest.asyncall = FTPCREATEDIRECTORYW; - workRequest.hdr = WININET_AddRef( &lpwfs->hdr ); + workRequest.asyncproc = AsyncFtpCreateDirectoryProc; + workRequest.hdr = WININET_AddRef( &lpwfs->hdr ); req = &workRequest.u.FtpCreateDirectoryW; req->lpszDirectory = WININET_strdupW(lpszDirectory); @@ -497,8 +576,7 @@ BOOL WINAPI FtpCreateDirectoryW(HINTERNET hConnect, LPCWSTR lpszDirectory) r = FTP_FtpCreateDirectoryW(lpwfs, lpszDirectory); } lend: - if( lpwfs ) - WININET_Release( &lpwfs->hdr ); + WININET_Release( &lpwfs->hdr ); return r; } @@ -522,12 +600,6 @@ BOOL WINAPI FTP_FtpCreateDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDire TRACE("lpszDirectory(%s)\n", debugstr_w(lpszDirectory)); - if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype) - { - INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); - return FALSE; - } - /* Clear any error information */ INTERNET_SetLastError(0); @@ -544,7 +616,7 @@ BOOL WINAPI FTP_FtpCreateDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDire } lend: - hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent; + hIC = lpwfs->lpAppInfo; if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) { INTERNET_ASYNC_RESULT iar; @@ -569,18 +641,18 @@ lend: * */ HINTERNET WINAPI FtpFindFirstFileA(HINTERNET hConnect, - LPCSTR lpszSearchFile, LPWIN32_FIND_DATAA lpFindFileData, DWORD dwFlags, DWORD dwContext) + LPCSTR lpszSearchFile, LPWIN32_FIND_DATAA lpFindFileData, DWORD dwFlags, DWORD_PTR dwContext) { LPWSTR lpwzSearchFile; WIN32_FIND_DATAW wfd; LPWIN32_FIND_DATAW lpFindFileDataW; HINTERNET ret; - + lpwzSearchFile = lpszSearchFile?WININET_strdup_AtoW(lpszSearchFile):NULL; lpFindFileDataW = lpFindFileData?&wfd:NULL; ret = FtpFindFirstFileW(hConnect, lpwzSearchFile, lpFindFileDataW, dwFlags, dwContext); HeapFree(GetProcessHeap(), 0, lpwzSearchFile); - + if(lpFindFileData) { WININET_find_data_WtoA(lpFindFileDataW, lpFindFileData); } @@ -588,6 +660,18 @@ HINTERNET WINAPI FtpFindFirstFileA(HINTERNET hConnect, } +static void AsyncFtpFindFirstFileProc(WORKREQUEST *workRequest) +{ + struct WORKREQ_FTPFINDFIRSTFILEW const *req = &workRequest->u.FtpFindFirstFileW; + LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr; + + TRACE("%p\n", lpwfs); + + FTP_FtpFindFirstFileW(lpwfs, req->lpszSearchFile, + req->lpFindFileData, req->dwFlags, req->dwContext); + HeapFree(GetProcessHeap(), 0, req->lpszSearchFile); +} + /*********************************************************************** * FtpFindFirstFileW (WININET.@) * @@ -599,7 +683,7 @@ HINTERNET WINAPI FtpFindFirstFileA(HINTERNET hConnect, * */ HINTERNET WINAPI FtpFindFirstFileW(HINTERNET hConnect, - LPCWSTR lpszSearchFile, LPWIN32_FIND_DATAW lpFindFileData, DWORD dwFlags, DWORD dwContext) + LPCWSTR lpszSearchFile, LPWIN32_FIND_DATAW lpFindFileData, DWORD dwFlags, DWORD_PTR dwContext) { LPWININETFTPSESSIONW lpwfs; LPWININETAPPINFOW hIC = NULL; @@ -612,14 +696,20 @@ HINTERNET WINAPI FtpFindFirstFileW(HINTERNET hConnect, goto lend; } - hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent; + if (lpwfs->download_in_progress != NULL) + { + INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS); + goto lend; + } + + hIC = lpwfs->lpAppInfo; if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) { WORKREQUEST workRequest; struct WORKREQ_FTPFINDFIRSTFILEW *req; - workRequest.asyncall = FTPFINDFIRSTFILEW; - workRequest.hdr = WININET_AddRef( &lpwfs->hdr ); + workRequest.asyncproc = AsyncFtpFindFirstFileProc; + workRequest.hdr = WININET_AddRef( &lpwfs->hdr ); req = &workRequest.u.FtpFindFirstFileW; req->lpszSearchFile = (lpszSearchFile == NULL) ? NULL : WININET_strdupW(lpszSearchFile); req->lpFindFileData = lpFindFileData; @@ -653,7 +743,7 @@ lend: * */ HINTERNET WINAPI FTP_FtpFindFirstFileW(LPWININETFTPSESSIONW lpwfs, - LPCWSTR lpszSearchFile, LPWIN32_FIND_DATAW lpFindFileData, DWORD dwFlags, DWORD dwContext) + LPCWSTR lpszSearchFile, LPWIN32_FIND_DATAW lpFindFileData, DWORD dwFlags, DWORD_PTR dwContext) { INT nResCode; LPWININETAPPINFOW hIC = NULL; @@ -661,8 +751,6 @@ HINTERNET WINAPI FTP_FtpFindFirstFileW(LPWININETFTPSESSIONW lpwfs, TRACE("\n"); - assert(WH_HFTPSESSION == lpwfs->hdr.htype); - /* Clear any error information */ INTERNET_SetLastError(0); @@ -675,7 +763,6 @@ HINTERNET WINAPI FTP_FtpFindFirstFileW(LPWININETFTPSESSIONW lpwfs, if (!FTP_SendPortOrPasv(lpwfs)) goto lend; - hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent; if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_LIST, NULL, lpwfs->hdr.lpfnStatusCB, &lpwfs->hdr, lpwfs->hdr.dwContext)) goto lend; @@ -705,6 +792,7 @@ lend: if (lpwfs->lstnSocket != -1) closesocket(lpwfs->lstnSocket); + hIC = lpwfs->lpAppInfo; if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) { INTERNET_ASYNC_RESULT iar; @@ -740,21 +828,44 @@ lend: BOOL WINAPI FtpGetCurrentDirectoryA(HINTERNET hFtpSession, LPSTR lpszCurrentDirectory, LPDWORD lpdwCurrentDirectory) { - WCHAR dir[MAX_PATH]; + WCHAR *dir = NULL; DWORD len; BOOL ret; - if(lpdwCurrentDirectory) len = *lpdwCurrentDirectory; + if(lpdwCurrentDirectory) { + len = *lpdwCurrentDirectory; + if(lpszCurrentDirectory) + { + dir = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (NULL == dir) + { + INTERNET_SetLastError(ERROR_OUTOFMEMORY); + return FALSE; + } + } + } ret = FtpGetCurrentDirectoryW(hFtpSession, lpszCurrentDirectory?dir:NULL, lpdwCurrentDirectory?&len:NULL); if(lpdwCurrentDirectory) { *lpdwCurrentDirectory = len; - if(lpszCurrentDirectory) + if(lpszCurrentDirectory) { WideCharToMultiByte(CP_ACP, 0, dir, len, lpszCurrentDirectory, *lpdwCurrentDirectory, NULL, NULL); + HeapFree(GetProcessHeap(), 0, dir); + } } return ret; } +static void AsyncFtpGetCurrentDirectoryProc(WORKREQUEST *workRequest) +{ + struct WORKREQ_FTPGETCURRENTDIRECTORYW const *req = &workRequest->u.FtpGetCurrentDirectoryW; + LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr; + + TRACE("%p\n", lpwfs); + + FTP_FtpGetCurrentDirectoryW(lpwfs, req->lpszDirectory, req->lpdwDirectory); +} + /*********************************************************************** * FtpGetCurrentDirectoryW (WININET.@) * @@ -772,7 +883,7 @@ BOOL WINAPI FtpGetCurrentDirectoryW(HINTERNET hFtpSession, LPWSTR lpszCurrentDir LPWININETAPPINFOW hIC = NULL; BOOL r = FALSE; - TRACE("len(%ld)\n", *lpdwCurrentDirectory); + TRACE("len(%d)\n", *lpdwCurrentDirectory); lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hFtpSession ); if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype) @@ -781,14 +892,20 @@ BOOL WINAPI FtpGetCurrentDirectoryW(HINTERNET hFtpSession, LPWSTR lpszCurrentDir goto lend; } - hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent; + if (lpwfs->download_in_progress != NULL) + { + INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS); + goto lend; + } + + hIC = lpwfs->lpAppInfo; if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) { WORKREQUEST workRequest; struct WORKREQ_FTPGETCURRENTDIRECTORYW *req; - workRequest.asyncall = FTPGETCURRENTDIRECTORYW; - workRequest.hdr = WININET_AddRef( &lpwfs->hdr ); + workRequest.asyncproc = AsyncFtpGetCurrentDirectoryProc; + workRequest.hdr = WININET_AddRef( &lpwfs->hdr ); req = &workRequest.u.FtpGetCurrentDirectoryW; req->lpszDirectory = lpszCurrentDirectory; req->lpdwDirectory = lpdwCurrentDirectory; @@ -810,7 +927,7 @@ lend: /*********************************************************************** - * FTP_FtpGetCurrentDirectoryA (Internal) + * FTP_FtpGetCurrentDirectoryW (Internal) * * Retrieves the current directory * @@ -826,20 +943,14 @@ BOOL WINAPI FTP_FtpGetCurrentDirectoryW(LPWININETFTPSESSIONW lpwfs, LPWSTR lpszC LPWININETAPPINFOW hIC = NULL; DWORD bSuccess = FALSE; - TRACE("len(%ld)\n", *lpdwCurrentDirectory); - - if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype) - { - INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); - return FALSE; - } + TRACE("len(%d)\n", *lpdwCurrentDirectory); /* Clear any error information */ INTERNET_SetLastError(0); ZeroMemory(lpszCurrentDirectory, *lpdwCurrentDirectory); - hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent; + hIC = lpwfs->lpAppInfo; if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_PWD, NULL, lpwfs->hdr.lpfnStatusCB, &lpwfs->hdr, lpwfs->hdr.dwContext)) goto lend; @@ -899,11 +1010,11 @@ lend: */ HINTERNET WINAPI FtpOpenFileA(HINTERNET hFtpSession, LPCSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags, - DWORD dwContext) + DWORD_PTR dwContext) { LPWSTR lpwzFileName; HINTERNET ret; - + lpwzFileName = lpszFileName?WININET_strdup_AtoW(lpszFileName):NULL; ret = FtpOpenFileW(hFtpSession, lpwzFileName, fdwAccess, dwFlags, dwContext); HeapFree(GetProcessHeap(), 0, lpwzFileName); @@ -911,6 +1022,18 @@ HINTERNET WINAPI FtpOpenFileA(HINTERNET hFtpSession, } +static void AsyncFtpOpenFileProc(WORKREQUEST *workRequest) +{ + struct WORKREQ_FTPOPENFILEW const *req = &workRequest->u.FtpOpenFileW; + LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr; + + TRACE("%p\n", lpwfs); + + FTP_FtpOpenFileW(lpwfs, req->lpszFilename, + req->dwAccess, req->dwFlags, req->dwContext); + HeapFree(GetProcessHeap(), 0, req->lpszFilename); +} + /*********************************************************************** * FtpOpenFileW (WININET.@) * @@ -923,34 +1046,50 @@ HINTERNET WINAPI FtpOpenFileA(HINTERNET hFtpSession, */ HINTERNET WINAPI FtpOpenFileW(HINTERNET hFtpSession, LPCWSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags, - DWORD dwContext) + DWORD_PTR dwContext) { LPWININETFTPSESSIONW lpwfs; LPWININETAPPINFOW hIC = NULL; HINTERNET r = NULL; - - TRACE("(%p,%s,0x%08lx,0x%08lx,0x%08lx)\n", hFtpSession, + + TRACE("(%p,%s,0x%08x,0x%08x,0x%08lx)\n", hFtpSession, debugstr_w(lpszFileName), fdwAccess, dwFlags, dwContext); lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hFtpSession ); - if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype) + if (!lpwfs) + { + INTERNET_SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + if (WH_HFTPSESSION != lpwfs->hdr.htype) { INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); goto lend; } - if (lpwfs->download_in_progress != NULL) { - INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS); - goto lend; + if ((!lpszFileName) || + ((fdwAccess != GENERIC_READ) && (fdwAccess != GENERIC_WRITE)) || + ((dwFlags & FTP_CONDITION_MASK) > FTP_TRANSFER_TYPE_BINARY)) + { + INTERNET_SetLastError(ERROR_INVALID_PARAMETER); + goto lend; } - hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent; + + if (lpwfs->download_in_progress != NULL) + { + INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS); + goto lend; + } + + hIC = lpwfs->lpAppInfo; if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) { WORKREQUEST workRequest; struct WORKREQ_FTPOPENFILEW *req; - workRequest.asyncall = FTPOPENFILEW; - workRequest.hdr = WININET_AddRef( &lpwfs->hdr ); + workRequest.asyncproc = AsyncFtpOpenFileProc; + workRequest.hdr = WININET_AddRef( &lpwfs->hdr ); req = &workRequest.u.FtpOpenFileW; req->lpszFilename = WININET_strdupW(lpszFileName); req->dwAccess = fdwAccess; @@ -966,8 +1105,7 @@ HINTERNET WINAPI FtpOpenFileW(HINTERNET hFtpSession, } lend: - if( lpwfs ) - WININET_Release( &lpwfs->hdr ); + WININET_Release( &lpwfs->hdr ); return r; } @@ -985,18 +1123,16 @@ lend: */ HINTERNET FTP_FtpOpenFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags, - DWORD dwContext) + DWORD_PTR dwContext) { INT nDataSocket; BOOL bSuccess = FALSE; - LPWININETFILE lpwh = NULL; + LPWININETFTPFILE lpwh = NULL; LPWININETAPPINFOW hIC = NULL; HINTERNET handle = NULL; TRACE("\n"); - assert (WH_HFTPSESSION == lpwfs->hdr.htype); - /* Clear any error information */ INTERNET_SetLastError(0); @@ -1014,17 +1150,21 @@ HINTERNET FTP_FtpOpenFileW(LPWININETFTPSESSIONW lpwfs, /* Get data socket to server */ if (bSuccess && FTP_GetDataSocket(lpwfs, &nDataSocket)) { - lpwh = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFILE)); + lpwh = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFTPFILE)); lpwh->hdr.htype = WH_HFILE; lpwh->hdr.dwFlags = dwFlags; lpwh->hdr.dwContext = dwContext; - lpwh->hdr.lpwhparent = WININET_AddRef( &lpwfs->hdr ); lpwh->hdr.dwRefCount = 1; + lpwh->hdr.close_connection = NULL; lpwh->hdr.destroy = FTP_CloseFileTransferHandle; lpwh->hdr.lpfnStatusCB = lpwfs->hdr.lpfnStatusCB; lpwh->nDataSocket = nDataSocket; lpwh->session_deleted = FALSE; + WININET_AddRef( &lpwfs->hdr ); + lpwh->lpFtpSession = lpwfs; + list_add_head( &lpwfs->hdr.children, &lpwh->hdr.entry ); + handle = WININET_AllocHandle( &lpwh->hdr ); if( !handle ) goto lend; @@ -1036,7 +1176,7 @@ HINTERNET FTP_FtpOpenFileW(LPWININETFTPSESSIONW lpwfs, if (lpwfs->lstnSocket != -1) closesocket(lpwfs->lstnSocket); - hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent; + hIC = lpwfs->lpAppInfo; if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) { INTERNET_ASYNC_RESULT iar; @@ -1075,12 +1215,12 @@ lend: */ BOOL WINAPI FtpGetFileA(HINTERNET hInternet, LPCSTR lpszRemoteFile, LPCSTR lpszNewFile, BOOL fFailIfExists, DWORD dwLocalFlagsAttribute, DWORD dwInternetFlags, - DWORD dwContext) + DWORD_PTR dwContext) { LPWSTR lpwzRemoteFile; LPWSTR lpwzNewFile; BOOL ret; - + lpwzRemoteFile = lpszRemoteFile?WININET_strdup_AtoW(lpszRemoteFile):NULL; lpwzNewFile = lpszNewFile?WININET_strdup_AtoW(lpszNewFile):NULL; ret = FtpGetFileW(hInternet, lpwzRemoteFile, lpwzNewFile, fFailIfExists, @@ -1091,6 +1231,21 @@ BOOL WINAPI FtpGetFileA(HINTERNET hInternet, LPCSTR lpszRemoteFile, LPCSTR lpszN } +static void AsyncFtpGetFileProc(WORKREQUEST *workRequest) +{ + struct WORKREQ_FTPGETFILEW const *req = &workRequest->u.FtpGetFileW; + LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr; + + TRACE("%p\n", lpwfs); + + FTP_FtpGetFileW(lpwfs, req->lpszRemoteFile, + req->lpszNewFile, req->fFailIfExists, + req->dwLocalFlagsAttribute, req->dwFlags, req->dwContext); + HeapFree(GetProcessHeap(), 0, req->lpszRemoteFile); + HeapFree(GetProcessHeap(), 0, req->lpszNewFile); +} + + /*********************************************************************** * FtpGetFileW (WININET.@) * @@ -1103,32 +1258,51 @@ BOOL WINAPI FtpGetFileA(HINTERNET hInternet, LPCSTR lpszRemoteFile, LPCSTR lpszN */ BOOL WINAPI FtpGetFileW(HINTERNET hInternet, LPCWSTR lpszRemoteFile, LPCWSTR lpszNewFile, BOOL fFailIfExists, DWORD dwLocalFlagsAttribute, DWORD dwInternetFlags, - DWORD dwContext) + DWORD_PTR dwContext) { LPWININETFTPSESSIONW lpwfs; LPWININETAPPINFOW hIC = NULL; BOOL r = FALSE; + if (!lpszRemoteFile || !lpszNewFile) + { + INTERNET_SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hInternet ); - if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype) + if (!lpwfs) + { + INTERNET_SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + if (WH_HFTPSESSION != lpwfs->hdr.htype) { INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); goto lend; } - if (lpwfs->download_in_progress != NULL) { - INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS); + if ((dwInternetFlags & FTP_CONDITION_MASK) > FTP_TRANSFER_TYPE_BINARY) + { + INTERNET_SetLastError(ERROR_INVALID_PARAMETER); goto lend; } - hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent; + if (lpwfs->download_in_progress != NULL) + { + INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS); + goto lend; + } + + hIC = lpwfs->lpAppInfo; if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) { WORKREQUEST workRequest; struct WORKREQ_FTPGETFILEW *req; - workRequest.asyncall = FTPGETFILEW; - workRequest.hdr = WININET_AddRef( &lpwfs->hdr ); + workRequest.asyncproc = AsyncFtpGetFileProc; + workRequest.hdr = WININET_AddRef( &lpwfs->hdr ); req = &workRequest.u.FtpGetFileW; req->lpszRemoteFile = WININET_strdupW(lpszRemoteFile); req->lpszNewFile = WININET_strdupW(lpszNewFile); @@ -1146,8 +1320,7 @@ BOOL WINAPI FtpGetFileW(HINTERNET hInternet, LPCWSTR lpszRemoteFile, LPCWSTR lps } lend: - if( lpwfs ) - WININET_Release( &lpwfs->hdr ); + WININET_Release( &lpwfs->hdr ); return r; } @@ -1165,17 +1338,14 @@ lend: */ BOOL WINAPI FTP_FtpGetFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, LPCWSTR lpszNewFile, BOOL fFailIfExists, DWORD dwLocalFlagsAttribute, DWORD dwInternetFlags, - DWORD dwContext) + DWORD_PTR dwContext) { - DWORD nBytes; BOOL bSuccess = FALSE; HANDLE hFile; LPWININETAPPINFOW hIC = NULL; TRACE("lpszRemoteFile(%s) lpszNewFile(%s)\n", debugstr_w(lpszRemoteFile), debugstr_w(lpszNewFile)); - assert (WH_HFTPSESSION == lpwfs->hdr.htype); - /* Clear any error information */ INTERNET_SetLastError(0); @@ -1183,12 +1353,10 @@ BOOL WINAPI FTP_FtpGetFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, hFile = CreateFileW(lpszNewFile, GENERIC_WRITE, 0, 0, fFailIfExists ? CREATE_NEW : CREATE_ALWAYS, dwLocalFlagsAttribute, 0); if (INVALID_HANDLE_VALUE == hFile) - goto lend; + return FALSE; /* Set up socket to retrieve data */ - nBytes = FTP_SendRetrieve(lpwfs, lpszRemoteFile, dwInternetFlags); - - if (nBytes > 0) + if (FTP_SendRetrieve(lpwfs, lpszRemoteFile, dwInternetFlags)) { INT nDataSocket; @@ -1198,27 +1366,26 @@ BOOL WINAPI FTP_FtpGetFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, INT nResCode; /* Receive data */ - FTP_RetrieveFileData(lpwfs, nDataSocket, nBytes, hFile); + FTP_RetrieveFileData(lpwfs, nDataSocket, hFile); + closesocket(nDataSocket); + nResCode = FTP_ReceiveResponse(lpwfs, dwContext); if (nResCode) { if (nResCode == 226) bSuccess = TRUE; - else + else FTP_SetResponseError(nResCode); } - closesocket(nDataSocket); } } -lend: if (lpwfs->lstnSocket != -1) closesocket(lpwfs->lstnSocket); - if (hFile) - CloseHandle(hFile); + CloseHandle(hFile); - hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent; + hIC = lpwfs->lpAppInfo; if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) { INTERNET_ASYNC_RESULT iar; @@ -1259,13 +1426,24 @@ BOOL WINAPI FtpDeleteFileA(HINTERNET hFtpSession, LPCSTR lpszFileName) { LPWSTR lpwzFileName; BOOL ret; - + lpwzFileName = lpszFileName?WININET_strdup_AtoW(lpszFileName):NULL; ret = FtpDeleteFileW(hFtpSession, lpwzFileName); HeapFree(GetProcessHeap(), 0, lpwzFileName); return ret; } +static void AsyncFtpDeleteFileProc(WORKREQUEST *workRequest) +{ + struct WORKREQ_FTPDELETEFILEW const *req = &workRequest->u.FtpDeleteFileW; + LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr; + + TRACE("%p\n", lpwfs); + + FTP_FtpDeleteFileW(lpwfs, req->lpszFilename); + HeapFree(GetProcessHeap(), 0, req->lpszFilename); +} + /*********************************************************************** * FtpDeleteFileW (WININET.@) * @@ -1283,20 +1461,38 @@ BOOL WINAPI FtpDeleteFileW(HINTERNET hFtpSession, LPCWSTR lpszFileName) BOOL r = FALSE; lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hFtpSession ); - if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype) + if (!lpwfs) + { + INTERNET_SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + if (WH_HFTPSESSION != lpwfs->hdr.htype) { INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); goto lend; } - hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent; + if (lpwfs->download_in_progress != NULL) + { + INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS); + goto lend; + } + + if (!lpszFileName) + { + INTERNET_SetLastError(ERROR_INVALID_PARAMETER); + goto lend; + } + + hIC = lpwfs->lpAppInfo; if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) { WORKREQUEST workRequest; struct WORKREQ_FTPDELETEFILEW *req; - workRequest.asyncall = FTPDELETEFILEW; - workRequest.hdr = WININET_AddRef( &lpwfs->hdr ); + workRequest.asyncproc = AsyncFtpDeleteFileProc; + workRequest.hdr = WININET_AddRef( &lpwfs->hdr ); req = &workRequest.u.FtpDeleteFileW; req->lpszFilename = WININET_strdupW(lpszFileName); @@ -1304,12 +1500,11 @@ BOOL WINAPI FtpDeleteFileW(HINTERNET hFtpSession, LPCWSTR lpszFileName) } else { - r = FTP_FtpDeleteFileW(hFtpSession, lpszFileName); + r = FTP_FtpDeleteFileW(lpwfs, lpszFileName); } lend: - if( lpwfs ) - WININET_Release( &lpwfs->hdr ); + WININET_Release( &lpwfs->hdr ); return r; } @@ -1332,8 +1527,6 @@ BOOL FTP_FtpDeleteFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszFileName) TRACE("%p\n", lpwfs); - assert (WH_HFTPSESSION == lpwfs->hdr.htype); - /* Clear any error information */ INTERNET_SetLastError(0); @@ -1349,7 +1542,7 @@ BOOL FTP_FtpDeleteFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszFileName) FTP_SetResponseError(nResCode); } lend: - hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent; + hIC = lpwfs->lpAppInfo; if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) { INTERNET_ASYNC_RESULT iar; @@ -1378,13 +1571,24 @@ BOOL WINAPI FtpRemoveDirectoryA(HINTERNET hFtpSession, LPCSTR lpszDirectory) { LPWSTR lpwzDirectory; BOOL ret; - + lpwzDirectory = lpszDirectory?WININET_strdup_AtoW(lpszDirectory):NULL; ret = FtpRemoveDirectoryW(hFtpSession, lpwzDirectory); HeapFree(GetProcessHeap(), 0, lpwzDirectory); return ret; } +static void AsyncFtpRemoveDirectoryProc(WORKREQUEST *workRequest) +{ + struct WORKREQ_FTPREMOVEDIRECTORYW const *req = &workRequest->u.FtpRemoveDirectoryW; + LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr; + + TRACE("%p\n", lpwfs); + + FTP_FtpRemoveDirectoryW(lpwfs, req->lpszDirectory); + HeapFree(GetProcessHeap(), 0, req->lpszDirectory); +} + /*********************************************************************** * FtpRemoveDirectoryW (WININET.@) * @@ -1402,20 +1606,38 @@ BOOL WINAPI FtpRemoveDirectoryW(HINTERNET hFtpSession, LPCWSTR lpszDirectory) BOOL r = FALSE; lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hFtpSession ); - if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype) + if (!lpwfs) + { + INTERNET_SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + if (WH_HFTPSESSION != lpwfs->hdr.htype) { INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); goto lend; } - hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent; + if (lpwfs->download_in_progress != NULL) + { + INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS); + goto lend; + } + + if (!lpszDirectory) + { + INTERNET_SetLastError(ERROR_INVALID_PARAMETER); + goto lend; + } + + hIC = lpwfs->lpAppInfo; if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) { WORKREQUEST workRequest; struct WORKREQ_FTPREMOVEDIRECTORYW *req; - workRequest.asyncall = FTPREMOVEDIRECTORYW; - workRequest.hdr = WININET_AddRef( &lpwfs->hdr ); + workRequest.asyncproc = AsyncFtpRemoveDirectoryProc; + workRequest.hdr = WININET_AddRef( &lpwfs->hdr ); req = &workRequest.u.FtpRemoveDirectoryW; req->lpszDirectory = WININET_strdupW(lpszDirectory); @@ -1427,8 +1649,7 @@ BOOL WINAPI FtpRemoveDirectoryW(HINTERNET hFtpSession, LPCWSTR lpszDirectory) } lend: - if( lpwfs ) - WININET_Release( &lpwfs->hdr ); + WININET_Release( &lpwfs->hdr ); return r; } @@ -1451,8 +1672,6 @@ BOOL FTP_FtpRemoveDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDirectory) TRACE("\n"); - assert (WH_HFTPSESSION == lpwfs->hdr.htype); - /* Clear any error information */ INTERNET_SetLastError(0); @@ -1469,7 +1688,7 @@ BOOL FTP_FtpRemoveDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDirectory) } lend: - hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent; + hIC = lpwfs->lpAppInfo; if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) { INTERNET_ASYNC_RESULT iar; @@ -1499,7 +1718,7 @@ BOOL WINAPI FtpRenameFileA(HINTERNET hFtpSession, LPCSTR lpszSrc, LPCSTR lpszDes LPWSTR lpwzSrc; LPWSTR lpwzDest; BOOL ret; - + lpwzSrc = lpszSrc?WININET_strdup_AtoW(lpszSrc):NULL; lpwzDest = lpszDest?WININET_strdup_AtoW(lpszDest):NULL; ret = FtpRenameFileW(hFtpSession, lpwzSrc, lpwzDest); @@ -1508,6 +1727,18 @@ BOOL WINAPI FtpRenameFileA(HINTERNET hFtpSession, LPCSTR lpszSrc, LPCSTR lpszDes return ret; } +static void AsyncFtpRenameFileProc(WORKREQUEST *workRequest) +{ + struct WORKREQ_FTPRENAMEFILEW const *req = &workRequest->u.FtpRenameFileW; + LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr; + + TRACE("%p\n", lpwfs); + + FTP_FtpRenameFileW(lpwfs, req->lpszSrcFile, req->lpszDestFile); + HeapFree(GetProcessHeap(), 0, req->lpszSrcFile); + HeapFree(GetProcessHeap(), 0, req->lpszDestFile); +} + /*********************************************************************** * FtpRenameFileW (WININET.@) * @@ -1525,20 +1756,38 @@ BOOL WINAPI FtpRenameFileW(HINTERNET hFtpSession, LPCWSTR lpszSrc, LPCWSTR lpszD BOOL r = FALSE; lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hFtpSession ); - if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype) + if (!lpwfs) + { + INTERNET_SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + if (WH_HFTPSESSION != lpwfs->hdr.htype) { INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); goto lend; } - hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent; + if (lpwfs->download_in_progress != NULL) + { + INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS); + goto lend; + } + + if (!lpszSrc || !lpszDest) + { + INTERNET_SetLastError(ERROR_INVALID_PARAMETER); + goto lend; + } + + hIC = lpwfs->lpAppInfo; if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) { WORKREQUEST workRequest; struct WORKREQ_FTPRENAMEFILEW *req; - workRequest.asyncall = FTPRENAMEFILEW; - workRequest.hdr = WININET_AddRef( &lpwfs->hdr ); + workRequest.asyncproc = AsyncFtpRenameFileProc; + workRequest.hdr = WININET_AddRef( &lpwfs->hdr ); req = &workRequest.u.FtpRenameFileW; req->lpszSrcFile = WININET_strdupW(lpszSrc); req->lpszDestFile = WININET_strdupW(lpszDest); @@ -1547,18 +1796,17 @@ BOOL WINAPI FtpRenameFileW(HINTERNET hFtpSession, LPCWSTR lpszSrc, LPCWSTR lpszD } else { - r = FTP_FtpRenameFileW(hFtpSession, lpszSrc, lpszDest); + r = FTP_FtpRenameFileW(lpwfs, lpszSrc, lpszDest); } lend: - if( lpwfs ) - WININET_Release( &lpwfs->hdr ); + WININET_Release( &lpwfs->hdr ); return r; } /*********************************************************************** - * FTP_FtpRenameFileA (Internal) + * FTP_FtpRenameFileW (Internal) * * Rename a file on the ftp server * @@ -1576,8 +1824,6 @@ BOOL FTP_FtpRenameFileW( LPWININETFTPSESSIONW lpwfs, TRACE("\n"); - assert (WH_HFTPSESSION == lpwfs->hdr.htype); - /* Clear any error information */ INTERNET_SetLastError(0); @@ -1599,7 +1845,7 @@ BOOL FTP_FtpRenameFileW( LPWININETFTPSESSIONW lpwfs, FTP_SetResponseError(nResCode); lend: - hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent; + hIC = lpwfs->lpAppInfo; if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) { INTERNET_ASYNC_RESULT iar; @@ -1619,10 +1865,34 @@ lend: BOOL WINAPI FtpCommandA( HINTERNET hConnect, BOOL fExpectResponse, DWORD dwFlags, LPCSTR lpszCommand, DWORD_PTR dwContext, HINTERNET* phFtpCommand ) { - FIXME("%p %d 0x%08lx %s 0x%08lx %p\n", hConnect, fExpectResponse, dwFlags, + BOOL r; + WCHAR *cmdW; + + TRACE("%p %d 0x%08x %s 0x%08lx %p\n", hConnect, fExpectResponse, dwFlags, debugstr_a(lpszCommand), dwContext, phFtpCommand); - return TRUE; + if (fExpectResponse) + { + FIXME("data connection not supported\n"); + return FALSE; + } + + if (!lpszCommand || !lpszCommand[0]) + { + INTERNET_SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (!(cmdW = WININET_strdup_AtoW(lpszCommand))) + { + INTERNET_SetLastError(ERROR_OUTOFMEMORY); + return FALSE; + } + + r = FtpCommandW(hConnect, fExpectResponse, dwFlags, cmdW, dwContext, phFtpCommand); + + HeapFree(GetProcessHeap(), 0, cmdW); + return r; } /*********************************************************************** @@ -1631,10 +1901,82 @@ BOOL WINAPI FtpCommandA( HINTERNET hConnect, BOOL fExpectResponse, DWORD dwFlags BOOL WINAPI FtpCommandW( HINTERNET hConnect, BOOL fExpectResponse, DWORD dwFlags, LPCWSTR lpszCommand, DWORD_PTR dwContext, HINTERNET* phFtpCommand ) { - FIXME("%p %d 0x%08lx %s 0x%08lx %p\n", hConnect, fExpectResponse, dwFlags, - debugstr_w(lpszCommand), dwContext, phFtpCommand); + BOOL r = FALSE; + LPWININETFTPSESSIONW lpwfs; + LPSTR cmd = NULL; + DWORD len, nBytesSent= 0; + INT nResCode, nRC = 0; - return TRUE; + TRACE("%p %d 0x%08x %s 0x%08lx %p\n", hConnect, fExpectResponse, dwFlags, + debugstr_w(lpszCommand), dwContext, phFtpCommand); + + if (!lpszCommand || !lpszCommand[0]) + { + INTERNET_SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (fExpectResponse) + { + FIXME("data connection not supported\n"); + return FALSE; + } + + lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hConnect ); + if (!lpwfs) + { + INTERNET_SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + if (WH_HFTPSESSION != lpwfs->hdr.htype) + { + INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); + goto lend; + } + + if (lpwfs->download_in_progress != NULL) + { + INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS); + goto lend; + } + + len = WideCharToMultiByte(CP_ACP, 0, lpszCommand, -1, NULL, 0, NULL, NULL) + strlen(szCRLF); + if ((cmd = HeapAlloc(GetProcessHeap(), 0, len ))) + WideCharToMultiByte(CP_ACP, 0, lpszCommand, -1, cmd, len, NULL, NULL); + else + { + INTERNET_SetLastError(ERROR_OUTOFMEMORY); + goto lend; + } + + strcat(cmd, szCRLF); + len--; + + TRACE("Sending (%s) len(%d)\n", cmd, len); + while ((nBytesSent < len) && (nRC != -1)) + { + nRC = send(lpwfs->sndSocket, cmd + nBytesSent, len - nBytesSent, 0); + if (nRC != -1) + { + nBytesSent += nRC; + TRACE("Sent %d bytes\n", nRC); + } + } + + if (nBytesSent) + { + nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext); + if (nResCode > 0 && nResCode < 400) + r = TRUE; + else + FTP_SetResponseError(nResCode); + } + +lend: + WININET_Release( &lpwfs->hdr ); + HeapFree(GetProcessHeap(), 0, cmd); + return r; } /*********************************************************************** @@ -1646,15 +1988,30 @@ BOOL WINAPI FtpCommandW( HINTERNET hConnect, BOOL fExpectResponse, DWORD dwFlags * HINTERNET a session handle on success * NULL on failure * + * NOTES: + * + * Windows uses 'anonymous' as the username, when given a NULL username + * and a NULL password. The password is first looked up in: + * + * HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\EmailName + * + * If this entry is not present it uses the current username as the password. + * */ HINTERNET FTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName, INTERNET_PORT nServerPort, LPCWSTR lpszUserName, - LPCWSTR lpszPassword, DWORD dwFlags, DWORD dwContext, + LPCWSTR lpszPassword, DWORD dwFlags, DWORD_PTR dwContext, DWORD dwInternalFlags) { + static const WCHAR szKey[] = {'S','o','f','t','w','a','r','e','\\', + 'M','i','c','r','o','s','o','f','t','\\', + 'W','i','n','d','o','w','s','\\', + 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', + 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s',0}; + static const WCHAR szValue[] = {'E','m','a','i','l','N','a','m','e',0}; static const WCHAR szDefaultUsername[] = {'a','n','o','n','y','m','o','u','s','\0'}; - static const WCHAR szDefaultPassword[] = {'u','s','e','r','@','s','e','r','v','e','r','\0'}; + static const WCHAR szEmpty[] = {'\0'}; struct sockaddr_in socketAddr; INT nsocket = -1; UINT sock_namelen; @@ -1673,7 +2030,7 @@ HINTERNET FTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName, INTERNET_SetLastError(ERROR_INVALID_PARAMETER); goto lerror; } - + lpwfs = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFTPSESSIONW)); if (NULL == lpwfs) { @@ -1685,14 +2042,21 @@ HINTERNET FTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName, nServerPort = INTERNET_DEFAULT_FTP_PORT; lpwfs->hdr.htype = WH_HFTPSESSION; - lpwfs->hdr.lpwhparent = WININET_AddRef( &hIC->hdr ); lpwfs->hdr.dwFlags = dwFlags; lpwfs->hdr.dwContext = dwContext; lpwfs->hdr.dwInternalFlags = dwInternalFlags; lpwfs->hdr.dwRefCount = 1; + lpwfs->hdr.close_connection = FTP_CloseConnection; lpwfs->hdr.destroy = FTP_CloseSessionHandle; lpwfs->hdr.lpfnStatusCB = hIC->hdr.lpfnStatusCB; lpwfs->download_in_progress = NULL; + lpwfs->sndSocket = -1; + lpwfs->lstnSocket = -1; + lpwfs->pasvSocket = -1; + + WININET_AddRef( &hIC->hdr ); + lpwfs->lpAppInfo = hIC; + list_add_head( &hIC->hdr.children, &lpwfs->hdr.entry ); handle = WININET_AllocHandle( &lpwfs->hdr ); if( !handle ) @@ -1709,14 +2073,34 @@ HINTERNET FTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName, FIXME("Proxy bypass is ignored.\n"); } if ( !lpszUserName) { + HKEY key; + WCHAR szPassword[MAX_PATH]; + DWORD len = sizeof(szPassword); + lpwfs->lpszUserName = WININET_strdupW(szDefaultUsername); - lpwfs->lpszPassword = WININET_strdupW(szDefaultPassword); + + RegOpenKeyW(HKEY_CURRENT_USER, szKey, &key); + if (RegQueryValueExW(key, szValue, NULL, NULL, (LPBYTE)szPassword, &len)) { + /* Nothing in the registry, get the username and use that as the password */ + if (!GetUserNameW(szPassword, &len)) { + /* Should never get here, but use an empty password as failsafe */ + strcpyW(szPassword, szEmpty); + } + } + RegCloseKey(key); + + TRACE("Password used for anonymous ftp : (%s)\n", debugstr_w(szPassword)); + lpwfs->lpszPassword = WININET_strdupW(szPassword); } else { lpwfs->lpszUserName = WININET_strdupW(lpszUserName); - lpwfs->lpszPassword = WININET_strdupW(lpszPassword); - } + if (lpszPassword) + lpwfs->lpszPassword = WININET_strdupW(lpszPassword); + else + lpwfs->lpszPassword = WININET_strdupW(szEmpty); + } + /* Don't send a handle created callback if this handle was created with InternetOpenUrl */ if (!(lpwfs->hdr.dwInternalFlags & INET_OPENURL)) { @@ -1729,7 +2113,7 @@ HINTERNET FTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName, INTERNET_STATUS_HANDLE_CREATED, &iar, sizeof(INTERNET_ASYNC_RESULT)); } - + SendAsyncCallback(&hIC->hdr, dwContext, INTERNET_STATUS_RESOLVING_NAME, (LPWSTR) lpszServerName, strlenW(lpszServerName)); @@ -1775,21 +2159,19 @@ HINTERNET FTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName, } lerror: - if (!bSuccess && nsocket == -1) - closesocket(nsocket); + if (lpwfs) WININET_Release( &lpwfs->hdr ); - if (!bSuccess && lpwfs) + if (!bSuccess && handle) { - HeapFree(GetProcessHeap(), 0, lpwfs); WININET_FreeHandle( handle ); - lpwfs = NULL; + handle = NULL; } if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) { INTERNET_ASYNC_RESULT iar; - iar.dwResult = (DWORD)lpwfs; + iar.dwResult = bSuccess ? (DWORD_PTR)lpwfs : 0; iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError(); SendAsyncCallback(&hIC->hdr, dwContext, INTERNET_STATUS_REQUEST_COMPLETE, &iar, sizeof(INTERNET_ASYNC_RESULT)); @@ -1853,7 +2235,7 @@ lend: * */ static BOOL FTP_SendCommandA(INT nSocket, FTP_COMMAND ftpCmd, LPCSTR lpszParam, - INTERNET_STATUS_CALLBACK lpfnStatusCB, LPWININETHANDLEHEADER hdr, DWORD dwContext) + INTERNET_STATUS_CALLBACK lpfnStatusCB, LPWININETHANDLEHEADER hdr, DWORD_PTR dwContext) { DWORD len; CHAR *buf; @@ -1865,12 +2247,7 @@ static BOOL FTP_SendCommandA(INT nSocket, FTP_COMMAND ftpCmd, LPCSTR lpszParam, if (lpfnStatusCB) { - HINTERNET hHandle = WININET_FindHandle( hdr ); - if( hHandle ) - { - lpfnStatusCB(hHandle, dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0); - WININET_Release( hdr ); - } + lpfnStatusCB(hdr->hInternet, dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0); } dwParamLen = lpszParam?strlen(lpszParam)+1:0; @@ -1883,7 +2260,7 @@ static BOOL FTP_SendCommandA(INT nSocket, FTP_COMMAND ftpCmd, LPCSTR lpszParam, sprintf(buf, "%s%s%s%s", szFtpCommands[ftpCmd], dwParamLen ? " " : "", dwParamLen ? lpszParam : "", szCRLF); - TRACE("Sending (%s) len(%ld)\n", buf, len); + TRACE("Sending (%s) len(%d)\n", buf, len); while((nBytesSent < len) && (nRC != -1)) { nRC = send(nSocket, buf+nBytesSent, len - nBytesSent, 0); @@ -1894,16 +2271,11 @@ static BOOL FTP_SendCommandA(INT nSocket, FTP_COMMAND ftpCmd, LPCSTR lpszParam, if (lpfnStatusCB) { - HINTERNET hHandle = WININET_FindHandle( hdr ); - if( hHandle ) - { - lpfnStatusCB(hHandle, dwContext, INTERNET_STATUS_REQUEST_SENT, - &nBytesSent, sizeof(DWORD)); - WININET_Release( hdr ); - } + lpfnStatusCB(hdr->hInternet, dwContext, INTERNET_STATUS_REQUEST_SENT, + &nBytesSent, sizeof(DWORD)); } - TRACE("Sent %ld bytes\n", nBytesSent); + TRACE("Sent %d bytes\n", nBytesSent); return (nRC != -1); } @@ -1918,7 +2290,7 @@ static BOOL FTP_SendCommandA(INT nSocket, FTP_COMMAND ftpCmd, LPCSTR lpszParam, * */ static BOOL FTP_SendCommand(INT nSocket, FTP_COMMAND ftpCmd, LPCWSTR lpszParam, - INTERNET_STATUS_CALLBACK lpfnStatusCB, LPWININETHANDLEHEADER hdr, DWORD dwContext) + INTERNET_STATUS_CALLBACK lpfnStatusCB, LPWININETHANDLEHEADER hdr, DWORD_PTR dwContext) { BOOL ret; LPSTR lpszParamA = lpszParam?WININET_strdup_WtoA(lpszParam):NULL; @@ -1937,7 +2309,7 @@ static BOOL FTP_SendCommand(INT nSocket, FTP_COMMAND ftpCmd, LPCWSTR lpszParam, * 0 on failure * */ -INT FTP_ReceiveResponse(LPWININETFTPSESSIONW lpwfs, DWORD dwContext) +INT FTP_ReceiveResponse(LPWININETFTPSESSIONW lpwfs, DWORD_PTR dwContext) { LPSTR lpszResponse = INTERNET_GetResponseBuffer(); DWORD nRecv; @@ -1948,7 +2320,7 @@ INT FTP_ReceiveResponse(LPWININETFTPSESSIONW lpwfs, DWORD dwContext) TRACE("socket(%d)\n", lpwfs->sndSocket); - hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent; + hIC = lpwfs->lpAppInfo; SendAsyncCallback(&lpwfs->hdr, dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0); while(1) @@ -2092,7 +2464,7 @@ static BOOL FTP_SendStore(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, DW nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext); if (nResCode) { - if (nResCode == 150) + if (nResCode == 150 || nResCode == 125) bSuccess = TRUE; else FTP_SetResponseError(nResCode); @@ -2122,7 +2494,7 @@ lend: static BOOL FTP_InitListenSocket(LPWININETFTPSESSIONW lpwfs) { BOOL bSuccess = FALSE; - size_t namelen = sizeof(struct sockaddr_in); + socklen_t namelen = sizeof(struct sockaddr_in); TRACE("\n"); @@ -2155,7 +2527,7 @@ static BOOL FTP_InitListenSocket(LPWININETFTPSESSIONW lpwfs) bSuccess = TRUE; lend: - if (!bSuccess && lpwfs->lstnSocket == -1) + if (!bSuccess && lpwfs->lstnSocket != -1) { closesocket(lpwfs->lstnSocket); lpwfs->lstnSocket = -1; @@ -2204,6 +2576,8 @@ lend: return bSuccess; } + +#if 0 /* FIXME: should probably be used for FtpGetFileSize */ /*********************************************************************** * FTP_GetFileSize (internal) * @@ -2235,7 +2609,7 @@ static BOOL FTP_GetFileSize(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, for (i = 0; (lpszResponseBuffer[i] != ' ') && (lpszResponseBuffer[i] != '\0'); i++) ; if (lpszResponseBuffer[i] == '\0') return FALSE; *dwSize = atol(&(lpszResponseBuffer[i + 1])); - + bSuccess = TRUE; } else { FTP_SetResponseError(nResCode); @@ -2245,6 +2619,7 @@ static BOOL FTP_GetFileSize(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, lend: return bSuccess; } +#endif /*********************************************************************** @@ -2324,18 +2699,11 @@ static BOOL FTP_DoPassive(LPWININETFTPSESSIONW lpwfs) struct sockaddr_in dataSocketAddress; p = lpszResponseBuffer+4; /* skip status code */ + while (*p != '\0' && (*p < '0' || *p > '9')) p++; - /* do a very strict check; we can improve that later. */ - - if (strncmp(p, "Entering Passive Mode", 21)) + if (*p == '\0') { - ERR("unknown response '%.*s', aborting\n", 21, p); - goto lend; - } - p += 21; /* skip string */ - if ((*p++ != ' ') || (*p++ != '(')) - { - ERR("unknown response format, aborting\n"); + ERR("no address found in response, aborting\n"); goto lend; } @@ -2365,6 +2733,7 @@ static BOOL FTP_DoPassive(LPWININETFTPSESSIONW lpwfs) if (connect(nsocket, (struct sockaddr *)&dataSocketAddress, sizeof(dataSocketAddress))) { ERR("can't connect passive FTP data port.\n"); + closesocket(nsocket); goto lend; } lpwfs->pasvSocket = nsocket; @@ -2411,7 +2780,7 @@ static BOOL FTP_SendPortOrPasv(LPWININETFTPSESSIONW lpwfs) static BOOL FTP_GetDataSocket(LPWININETFTPSESSIONW lpwfs, LPINT nDataSocket) { struct sockaddr_in saddr; - size_t addrlen = sizeof(struct sockaddr); + socklen_t addrlen = sizeof(struct sockaddr); TRACE("\n"); if (lpwfs->hdr.dwFlags & INTERNET_FLAG_PASSIVE) @@ -2451,8 +2820,7 @@ static BOOL FTP_SendData(LPWININETFTPSESSIONW lpwfs, INT nDataSocket, HANDLE hFi CHAR *lpszBuffer; TRACE("\n"); - lpszBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(CHAR)*DATA_PACKET_SIZE); - memset(lpszBuffer, 0, sizeof(CHAR)*DATA_PACKET_SIZE); + lpszBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CHAR)*DATA_PACKET_SIZE); /* Get the size of the file. */ GetFileInformationByHandle(hFile, &fi); @@ -2490,13 +2858,13 @@ static BOOL FTP_SendData(LPWININETFTPSESSIONW lpwfs, INT nDataSocket, HANDLE hFi nSeconds = e_long_time - s_long_time; if( nSeconds / 60 > 0 ) { - TRACE( "%ld bytes of %ld bytes (%ld%%) in %ld min %ld sec estimated remaining time %ld sec\n", + TRACE( "%d bytes of %d bytes (%d%%) in %d min %d sec estimated remaining time %d sec\n", nTotalSent, fi.nFileSizeLow, nTotalSent*100/fi.nFileSizeLow, nSeconds / 60, nSeconds % 60, (fi.nFileSizeLow - nTotalSent) * nSeconds / nTotalSent ); } else { - TRACE( "%ld bytes of %ld bytes (%ld%%) in %ld sec estimated remaining time %ld sec\n", + TRACE( "%d bytes of %d bytes (%d%%) in %d sec estimated remaining time %d sec\n", nTotalSent, fi.nFileSizeLow, nTotalSent*100/fi.nFileSizeLow, nSeconds, (fi.nFileSizeLow - nTotalSent) * nSeconds / nTotalSent); } @@ -2520,43 +2888,39 @@ static BOOL FTP_SendData(LPWININETFTPSESSIONW lpwfs, INT nDataSocket, HANDLE hFi * 0 on failure * */ -static DWORD FTP_SendRetrieve(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, DWORD dwType) +static BOOL FTP_SendRetrieve(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, DWORD dwType) { INT nResCode; - DWORD nResult = 0; + BOOL ret; TRACE("\n"); - if (!FTP_InitListenSocket(lpwfs)) + if (!(ret = FTP_InitListenSocket(lpwfs))) goto lend; - if (!FTP_SendType(lpwfs, dwType)) + if (!(ret = FTP_SendType(lpwfs, dwType))) goto lend; - if (!FTP_SendPortOrPasv(lpwfs)) + if (!(ret = FTP_SendPortOrPasv(lpwfs))) goto lend; - if (!FTP_GetFileSize(lpwfs, lpszRemoteFile, &nResult)) - goto lend; - - TRACE("Waiting to receive %ld bytes\n", nResult); - - if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_RETR, lpszRemoteFile, 0, 0, 0)) + if (!(ret = FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_RETR, lpszRemoteFile, 0, 0, 0))) goto lend; nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext); if ((nResCode != 125) && (nResCode != 150)) { /* That means that we got an error getting the file. */ - nResult = 0; + FTP_SetResponseError(nResCode); + ret = FALSE; } lend: - if (0 == nResult && lpwfs->lstnSocket != -1) + if (!ret && lpwfs->lstnSocket != -1) { closesocket(lpwfs->lstnSocket); lpwfs->lstnSocket = -1; } - return nResult; + return ret; } @@ -2570,7 +2934,7 @@ lend: * FALSE on failure * */ -static BOOL FTP_RetrieveFileData(LPWININETFTPSESSIONW lpwfs, INT nDataSocket, DWORD nBytes, HANDLE hFile) +static BOOL FTP_RetrieveFileData(LPWININETFTPSESSIONW lpwfs, INT nDataSocket, HANDLE hFile) { DWORD nBytesWritten; DWORD nBytesReceived = 0; @@ -2579,9 +2943,6 @@ static BOOL FTP_RetrieveFileData(LPWININETFTPSESSIONW lpwfs, INT nDataSocket, DW TRACE("\n"); - if (INVALID_HANDLE_VALUE == hFile) - return FALSE; - lpszBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CHAR)*DATA_PACKET_SIZE); if (NULL == lpszBuffer) { @@ -2589,7 +2950,7 @@ static BOOL FTP_RetrieveFileData(LPWININETFTPSESSIONW lpwfs, INT nDataSocket, DW return FALSE; } - while (nBytesReceived < nBytes && nRC != -1) + while (nRC != -1) { nRC = recv(nDataSocket, lpszBuffer, DATA_PACKET_SIZE, 0); if (nRC != -1) @@ -2600,28 +2961,51 @@ static BOOL FTP_RetrieveFileData(LPWININETFTPSESSIONW lpwfs, INT nDataSocket, DW WriteFile(hFile, lpszBuffer, nRC, &nBytesWritten, NULL); nBytesReceived += nRC; } - - TRACE("%ld bytes of %ld (%ld%%)\r", nBytesReceived, nBytes, - nBytesReceived * 100 / nBytes); } TRACE("Data transfer complete\n"); - HeapFree(GetProcessHeap(), 0, lpszBuffer); recv_end: + HeapFree(GetProcessHeap(), 0, lpszBuffer); + return (nRC != -1); } +/*********************************************************************** + * FTP_CloseConnection (internal) + * + * Close connections + */ +static void FTP_CloseConnection(LPWININETHANDLEHEADER hdr) +{ + LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) hdr; + + TRACE("\n"); + + SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, + INTERNET_STATUS_CLOSING_CONNECTION, 0, 0); + + if (lpwfs->download_in_progress != NULL) + lpwfs->download_in_progress->session_deleted = TRUE; + + if (lpwfs->sndSocket != -1) + closesocket(lpwfs->sndSocket); + + if (lpwfs->lstnSocket != -1) + closesocket(lpwfs->lstnSocket); + + if (lpwfs->pasvSocket != -1) + closesocket(lpwfs->pasvSocket); + + SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, + INTERNET_STATUS_CONNECTION_CLOSED, 0, 0); +} + /*********************************************************************** * FTP_CloseSessionHandle (internal) * * Deallocate session handle - * - * RETURNS - * TRUE on success - * FALSE on failure - * */ static void FTP_CloseSessionHandle(LPWININETHANDLEHEADER hdr) { @@ -2629,14 +3013,7 @@ static void FTP_CloseSessionHandle(LPWININETHANDLEHEADER hdr) TRACE("\n"); - if (lpwfs->download_in_progress != NULL) - lpwfs->download_in_progress->session_deleted = TRUE; - - if (lpwfs->sndSocket != -1) - closesocket(lpwfs->sndSocket); - - if (lpwfs->lstnSocket != -1) - closesocket(lpwfs->lstnSocket); + WININET_Release(&lpwfs->lpAppInfo->hdr); HeapFree(GetProcessHeap(), 0, lpwfs->lpszPassword); HeapFree(GetProcessHeap(), 0, lpwfs->lpszUserName); @@ -2644,6 +3021,62 @@ static void FTP_CloseSessionHandle(LPWININETHANDLEHEADER hdr) } +/*********************************************************************** + * FTP_FindNextFileW (Internal) + * + * Continues a file search from a previous call to FindFirstFile + * + * RETURNS + * TRUE on success + * FALSE on failure + * + */ +BOOL WINAPI FTP_FindNextFileW(LPWININETFTPFINDNEXTW lpwh, LPVOID lpvFindData) +{ + BOOL bSuccess = TRUE; + LPWIN32_FIND_DATAW lpFindFileData; + + TRACE("index(%d) size(%d)\n", lpwh->index, lpwh->size); + + assert (lpwh->hdr.htype == WH_HFTPFINDNEXT); + + /* Clear any error information */ + INTERNET_SetLastError(0); + + lpFindFileData = (LPWIN32_FIND_DATAW) lpvFindData; + ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA)); + + if (lpwh->index >= lpwh->size) + { + INTERNET_SetLastError(ERROR_NO_MORE_FILES); + bSuccess = FALSE; + goto lend; + } + + FTP_ConvertFileProp(&lpwh->lpafp[lpwh->index], lpFindFileData); + lpwh->index++; + + TRACE("\nName: %s\nSize: %d\n", debugstr_w(lpFindFileData->cFileName), lpFindFileData->nFileSizeLow); + +lend: + + if (lpwh->hdr.dwFlags & INTERNET_FLAG_ASYNC) + { + INTERNET_ASYNC_RESULT iar; + + iar.dwResult = (DWORD)bSuccess; + iar.dwError = iar.dwError = bSuccess ? ERROR_SUCCESS : + INTERNET_GetLastError(); + + INTERNET_SendCallback(&lpwh->hdr, lpwh->hdr.dwContext, + INTERNET_STATUS_REQUEST_COMPLETE, &iar, + sizeof(INTERNET_ASYNC_RESULT)); + } + + return bSuccess; +} + + /*********************************************************************** * FTP_CloseFindNextHandle (internal) * @@ -2656,11 +3089,13 @@ static void FTP_CloseSessionHandle(LPWININETHANDLEHEADER hdr) */ static void FTP_CloseFindNextHandle(LPWININETHANDLEHEADER hdr) { - LPWININETFINDNEXTW lpwfn = (LPWININETFINDNEXTW) hdr; + LPWININETFTPFINDNEXTW lpwfn = (LPWININETFTPFINDNEXTW) hdr; DWORD i; TRACE("\n"); + WININET_Release(&lpwfn->lpFtpSession->hdr); + for (i = 0; i < lpwfn->size; i++) { HeapFree(GetProcessHeap(), 0, lpwfn->lpafp[i].lpszName); @@ -2674,30 +3109,28 @@ static void FTP_CloseFindNextHandle(LPWININETHANDLEHEADER hdr) * FTP_CloseFileTransferHandle (internal) * * Closes the file transfer handle. This also 'cleans' the data queue of - * the 'transfer conplete' message (this is a bit of a hack though :-/ ) + * the 'transfer complete' message (this is a bit of a hack though :-/ ) * */ static void FTP_CloseFileTransferHandle(LPWININETHANDLEHEADER hdr) { - LPWININETFILE lpwh = (LPWININETFILE) hdr; - LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) lpwh->hdr.lpwhparent; + LPWININETFTPFILE lpwh = (LPWININETFTPFILE) hdr; + LPWININETFTPSESSIONW lpwfs = lpwh->lpFtpSession; INT nResCode; TRACE("\n"); + WININET_Release(&lpwh->lpFtpSession->hdr); + if (!lpwh->session_deleted) - lpwfs->download_in_progress = NULL; - - /* This just serves to flush the control socket of any spurrious lines written - to it (like '226 Transfer complete.'). - - Wonder what to do if the server sends us an error code though... - */ - nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext); + lpwfs->download_in_progress = NULL; if (lpwh->nDataSocket != -1) closesocket(lpwh->nDataSocket); + nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext); + if (nResCode > 0 && nResCode != 226) WARN("server reports failed transfer\n"); + HeapFree(GetProcessHeap(), 0, lpwh); } @@ -2712,33 +3145,37 @@ static void FTP_CloseFileTransferHandle(LPWININETHANDLEHEADER hdr) * */ static HINTERNET FTP_ReceiveFileList(LPWININETFTPSESSIONW lpwfs, INT nSocket, LPCWSTR lpszSearchFile, - LPWIN32_FIND_DATAW lpFindFileData, DWORD dwContext) + LPWIN32_FIND_DATAW lpFindFileData, DWORD_PTR dwContext) { DWORD dwSize = 0; LPFILEPROPERTIESW lpafp = NULL; - LPWININETFINDNEXTW lpwfn = NULL; + LPWININETFTPFINDNEXTW lpwfn = NULL; HINTERNET handle = 0; - TRACE("(%p,%d,%s,%p,%ld)\n", lpwfs, nSocket, debugstr_w(lpszSearchFile), lpFindFileData, dwContext); + TRACE("(%p,%d,%s,%p,%08lx)\n", lpwfs, nSocket, debugstr_w(lpszSearchFile), lpFindFileData, dwContext); if (FTP_ParseDirectory(lpwfs, nSocket, lpszSearchFile, &lpafp, &dwSize)) { if(lpFindFileData) FTP_ConvertFileProp(lpafp, lpFindFileData); - lpwfn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WININETFINDNEXTW)); + lpwfn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WININETFTPFINDNEXTW)); if (lpwfn) { - lpwfn->hdr.htype = WH_HFINDNEXT; - lpwfn->hdr.lpwhparent = WININET_AddRef( &lpwfs->hdr ); + lpwfn->hdr.htype = WH_HFTPFINDNEXT; lpwfn->hdr.dwContext = dwContext; lpwfn->hdr.dwRefCount = 1; + lpwfn->hdr.close_connection = NULL; lpwfn->hdr.destroy = FTP_CloseFindNextHandle; lpwfn->hdr.lpfnStatusCB = lpwfs->hdr.lpfnStatusCB; lpwfn->index = 1; /* Next index is 1 since we return index 0 */ lpwfn->size = dwSize; lpwfn->lpafp = lpafp; + WININET_AddRef( &lpwfs->hdr ); + lpwfn->lpFtpSession = lpwfs; + list_add_head( &lpwfs->hdr.children, &lpwfn->hdr.entry ); + handle = WININET_AllocHandle( &lpwfn->hdr ); } } @@ -2746,7 +3183,7 @@ static HINTERNET FTP_ReceiveFileList(LPWININETFTPSESSIONW lpwfs, INT nSocket, LP if( lpwfn ) WININET_Release( &lpwfn->hdr ); - TRACE("Matched %ld files\n", dwSize); + TRACE("Matched %d files\n", dwSize); return handle; } @@ -2774,7 +3211,7 @@ BOOL FTP_ConvertFileProp(LPFILEPROPERTIESW lpafp, LPWIN32_FIND_DATAW lpFindFileD (LARGE_INTEGER *) &(lpFindFileData->ftLastAccessTime)); lpFindFileData->ftLastWriteTime = lpFindFileData->ftLastAccessTime; lpFindFileData->ftCreationTime = lpFindFileData->ftLastAccessTime; - + /* Not all fields are filled in */ lpFindFileData->nFileSizeHigh = 0; /* We do not handle files bigger than 0xFFFFFFFF bytes yet :-) */ lpFindFileData->nFileSizeLow = lpafp->nSize; @@ -2809,12 +3246,12 @@ static BOOL FTP_ParseNextFile(INT nSocket, LPCWSTR lpszSearchFile, LPFILEPROPERT char *pszTmp; BOOL found = FALSE; int i; - + lpfp->lpszName = NULL; do { if(!(pszLine = INTERNET_GetNextLine(nSocket, &nBufLen))) return FALSE; - + pszToken = strtok(pszLine, szSpace); /* ls format *