Hi all, With this, Ragnarok Online's patcher tool (which uses a lot of FTP transfer) now works perfectly. Let's hope FTP transfer on Unix system or in non-passive mode still work though. Lionel Changelog: - fix multiple consecutive downloads (by flushing when needed the command socket) - detect attempts to download multiple files at the same time - fix size / date reporting when enumerating files - fix Y2K problem in NT parsing of files -- Lionel Ulmer - http://www.bbrox.org/
--- dlls/wininet/ftp.c_sent Sat Jul 19 17:59:23 2003 +++ dlls/wininet/ftp.c Sat Jul 19 23:14:44 2003 @@ -46,6 +46,7 @@ #include "wininet.h" #include "winnls.h" #include "winerror.h" +#include "winternl.h" #include "wine/debug.h" #include "internet.h" @@ -835,6 +836,11 @@ return FALSE; } + if (lpwfs->download_in_progress != NULL) { + INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS); + return FALSE; + } + hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent; if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) { @@ -927,6 +933,10 @@ hFile->hdr.dwContext = dwContext; hFile->hdr.lpwhparent = hFtpSession; hFile->nDataSocket = nDataSocket; + hFile->session_deleted = FALSE; + + /* Indicate that a download is currently in progress */ + lpwfs->download_in_progress = hFile; } if (lpwfs->lstnSocket != -1) @@ -978,6 +988,11 @@ return FALSE; } + if (lpwfs->download_in_progress != NULL) { + INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS); + return FALSE; + } + hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent; if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) { @@ -1485,6 +1500,7 @@ lpwfs->hdr.dwContext = dwContext; lpwfs->hdr.lpwhparent = (LPWININETHANDLEHEADER)hInternet; lpwfs->sndSocket = nsocket; + lpwfs->download_in_progress = NULL; sock_namelen = sizeof(lpwfs->socketAddress); getsockname(nsocket, (struct sockaddr *) &lpwfs->socketAddress, &sock_namelen); lpwfs->phostent = phe; @@ -2348,6 +2364,9 @@ BOOL FTP_CloseSessionHandle(LPWININETFTPSESSIONA lpwfs) { TRACE("\n"); + + if (lpwfs->download_in_progress != NULL) + lpwfs->download_in_progress->session_deleted = TRUE; if (lpwfs->sndSocket != -1) close(lpwfs->sndSocket); @@ -2396,7 +2415,7 @@ } /*********************************************************************** - * FTP_CloseFindNextHandle (internal) + * 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 :-/ ) @@ -2408,7 +2427,21 @@ */ BOOL FTP_CloseFileTransferHandle(LPWININETFILE lpwh) { + LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) lpwh->hdr.lpwhparent; + INT nResCode; + TRACE("\n"); + + 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->sndSocket, INTERNET_GetResponseBuffer(), + MAX_REPLY_LEN, 0, 0, 0); if (lpwh->nDataSocket != -1) close(lpwh->nDataSocket); @@ -2476,13 +2509,13 @@ if (lpafp) { - DWORD access = mktime(&lpafp->tmLastModified); - + /* Convert 'Unix' time to Windows time */ + RtlSecondsSince1970ToTime(mktime(&lpafp->tmLastModified), + (LARGE_INTEGER *) &(lpFindFileData->ftLastAccessTime)); + /* Not all fields are filled in */ - lpFindFileData->ftLastAccessTime.dwHighDateTime = HIWORD(access); - lpFindFileData->ftLastAccessTime.dwLowDateTime = LOWORD(access); - lpFindFileData->nFileSizeHigh = HIWORD(lpafp->nSize); - lpFindFileData->nFileSizeLow = LOWORD(lpafp->nSize); + lpFindFileData->nFileSizeHigh = 0; /* We do not handle files bigger than 0xFFFFFFFF bytes yet :-) */ + lpFindFileData->nFileSizeLow = lpafp->nSize; if (lpafp->bIsDirectory) lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY; @@ -2661,7 +2694,11 @@ sscanf(pszToken, "%d-%d-%d", &curFileProp->tmLastModified.tm_mon, &curFileProp->tmLastModified.tm_mday, - &curFileProp->tmLastModified.tm_year); /* Do we check for Y2K problems ? */ + &curFileProp->tmLastModified.tm_year); + + /* Hacky and bad Y2K protection :-) */ + if (curFileProp->tmLastModified.tm_year < 70) + curFileProp->tmLastModified.tm_year += 100; pszToken = strtok(NULL, " \t"); if (pszToken == NULL) { @@ -2678,7 +2715,8 @@ TRACE("Mod time: %2d:%2d:%2d %2d/%2d/%2d\n", curFileProp->tmLastModified.tm_hour, curFileProp->tmLastModified.tm_min, curFileProp->tmLastModified.tm_sec, - curFileProp->tmLastModified.tm_year, curFileProp->tmLastModified.tm_mon, curFileProp->tmLastModified.tm_mday); + (curFileProp->tmLastModified.tm_year >= 100) ? curFileProp->tmLastModified.tm_year - 100 : curFileProp->tmLastModified.tm_year, + curFileProp->tmLastModified.tm_mon, curFileProp->tmLastModified.tm_mday); pszToken = strtok(NULL, " \t"); if (pszToken == NULL) { --- dlls/wininet/internet.h_sent Sat Jul 19 17:59:32 2003 +++ dlls/wininet/internet.h Sat Jul 19 22:30:45 2003 @@ -117,22 +117,24 @@ typedef struct { WININETHANDLEHEADER hdr; + BOOL session_deleted; + int nDataSocket; +} WININETFILE, *LPWININETFILE; + + +typedef struct +{ + WININETHANDLEHEADER hdr; int sndSocket; int lstnSocket; int pasvSocket; /* data socket connected by us in case of passive FTP */ + LPWININETFILE download_in_progress; struct sockaddr_in socketAddress; struct sockaddr_in lstnSocketAddress; struct hostent *phostent; LPSTR lpszPassword; LPSTR lpszUserName; } WININETFTPSESSIONA, *LPWININETFTPSESSIONA; - - -typedef struct -{ - WININETHANDLEHEADER hdr; - int nDataSocket; -} WININETFILE, *LPWININETFILE; typedef struct