Hi all, This is the next step in getting Ragnarok Online patcher to work fine... I now manage to download fine the first file. There is still a problem with the second file, but that will be part of a second patch (because I feel the change to be a bit more controversial than in this one). If anyone wants to write some unit test code for the FTP functions, feel free, I think that they need it :) Lionel Changelog: - use SIZE command to retrieve the file size (as the file size is not part of the WinNT acknowledgement string) - frees the handle / close the socket on end of download - fix InternetReadFile in the FTP case - fix FTP_ReceiveResponse -- Lionel Ulmer - http://www.bbrox.org/
Index: dlls/wininet/ftp.c =================================================================== RCS file: /home/wine/wine/dlls/wininet/ftp.c,v retrieving revision 1.29 diff -u -r1.29 ftp.c --- dlls/wininet/ftp.c 15 Jul 2003 20:51:02 -0000 1.29 +++ dlls/wininet/ftp.c 19 Jul 2003 15:50:54 -0000 @@ -72,6 +72,7 @@ FTP_CMD_STOR, FTP_CMD_TYPE, FTP_CMD_USER, + FTP_CMD_SIZE, /* FTP commands without arguments. */ FTP_CMD_ABOR, @@ -96,6 +97,7 @@ "STOR", "TYPE", "USER", + "SIZE", "ABOR", "LIST", "NLST", @@ -120,6 +122,7 @@ BOOL FTP_SendPassword(LPWININETFTPSESSIONA lpwfs); BOOL FTP_SendAccount(LPWININETFTPSESSIONA lpwfs); BOOL FTP_SendType(LPWININETFTPSESSIONA lpwfs, DWORD dwType); +BOOL FTP_GetFileSize(LPWININETFTPSESSIONA lpwfs, LPCSTR lpszRemoteFile, DWORD *dwSize); BOOL FTP_SendPort(LPWININETFTPSESSIONA lpwfs); BOOL FTP_DoPassive(LPWININETFTPSESSIONA lpwfs); BOOL FTP_SendPortOrPasv(LPWININETFTPSESSIONA lpwfs); @@ -1690,7 +1693,6 @@ if (nRecv >= 3) { - lpszResponse[nRecv] = '\0'; rc = atoi(lpszResponse); if (lpfnStatusCB) @@ -1896,7 +1898,7 @@ BOOL FTP_SendType(LPWININETFTPSESSIONA lpwfs, DWORD dwType) { INT nResCode; - CHAR type[2] = { "I\0" }; + CHAR type[2] = { "I" }; BOOL bSuccess = FALSE; TRACE("\n"); @@ -1920,6 +1922,49 @@ return bSuccess; } +/*********************************************************************** + * FTP_GetFileSize (internal) + * + * Retrieves from the server the size of the given file + * + * RETURNS + * TRUE on success + * FALSE on failure + * + */ +BOOL FTP_GetFileSize(LPWININETFTPSESSIONA lpwfs, LPCSTR lpszRemoteFile, DWORD *dwSize) +{ + INT nResCode; + BOOL bSuccess = FALSE; + + TRACE("\n"); + + if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_SIZE, lpszRemoteFile, 0, 0, 0)) + goto lend; + + nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(), + MAX_REPLY_LEN, 0, 0, 0); + if (nResCode) + { + if (nResCode == 213) { + /* Now parses the output to get the actual file size */ + int i; + LPSTR lpszResponseBuffer = INTERNET_GetResponseBuffer(); + + 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); + } + } + +lend: + return bSuccess; +} + /*********************************************************************** * FTP_SendPort (internal) @@ -2210,33 +2255,19 @@ if (!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)) goto lend; nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(), MAX_REPLY_LEN, 0, 0, 0); - if (nResCode) - { - if (nResCode == 125 || nResCode == 150) - { - /* Parse size of data to be retrieved */ - INT i, sizepos = -1; - LPSTR lpszResponseBuffer = INTERNET_GetResponseBuffer(); - for (i = strlen(lpszResponseBuffer) - 1; i >= 0; i--) - { - if ('(' == lpszResponseBuffer[i]) - { - sizepos = i; - break; - } - } - - if (sizepos >= 0) - { - nResult = atol(&lpszResponseBuffer[sizepos+1]); - TRACE("Waiting to receive %ld bytes\n", nResult); - } - } + if ((nResCode != 125) && (nResCode != 150)) { + /* That means that we got an error getting the file. */ + nResult = 0; } lend: @@ -2316,6 +2347,8 @@ */ BOOL FTP_CloseSessionHandle(LPWININETFTPSESSIONA lpwfs) { + TRACE("\n"); + if (lpwfs->sndSocket != -1) close(lpwfs->sndSocket); @@ -2335,7 +2368,7 @@ /*********************************************************************** - * FTP_CloseSessionHandle (internal) + * FTP_CloseFindNextHandle (internal) * * Deallocate session handle * @@ -2362,6 +2395,28 @@ return TRUE; } +/*********************************************************************** + * FTP_CloseFindNextHandle (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 :-/ ) + * + * RETURNS + * TRUE on success + * FALSE on failure + * + */ +BOOL FTP_CloseFileTransferHandle(LPWININETFILE lpwh) +{ + TRACE("\n"); + + if (lpwh->nDataSocket != -1) + close(lpwh->nDataSocket); + + HeapFree(GetProcessHeap(), 0, lpwh); + + return TRUE; +} /*********************************************************************** * FTP_ReceiveFileList (internal) Index: dlls/wininet/internet.c =================================================================== RCS file: /home/wine/wine/dlls/wininet/internet.c,v retrieving revision 1.61 diff -u -r1.61 internet.c --- dlls/wininet/internet.c 9 Jul 2003 22:15:33 -0000 1.61 +++ dlls/wininet/internet.c 19 Jul 2003 15:50:55 -0000 @@ -701,6 +701,10 @@ retval = FTP_CloseFindNextHandle((LPWININETFINDNEXTA) lpwh); break; + case WH_HFILE: + retval = FTP_CloseFileTransferHandle((LPWININETFILE) lpwh); + break; + default: break; } @@ -1331,12 +1335,6 @@ break; } - if (nSocket != -1) - { - int res = recv(nSocket, lpBuffer, dwNumOfBytesToRead, 0); - retval = (res >= 0); - *dwNumOfBytesRead = retval ? res : 0; - } return retval; } Index: dlls/wininet/internet.h =================================================================== RCS file: /home/wine/wine/dlls/wininet/internet.h,v retrieving revision 1.11 diff -u -r1.11 internet.h --- dlls/wininet/internet.h 20 Jun 2003 23:26:56 -0000 1.11 +++ dlls/wininet/internet.h 19 Jul 2003 15:50:55 -0000 @@ -243,6 +243,7 @@ BOOL FTP_CloseSessionHandle(LPWININETFTPSESSIONA lpwfs); BOOL FTP_CloseFindNextHandle(LPWININETFINDNEXTA lpwfn); +BOOL FTP_CloseFileTransferHandle(LPWININETFILE lpwfn); BOOLAPI FTP_FtpPutFileA(HINTERNET hConnect, LPCSTR lpszLocalFile, LPCSTR lpszNewRemoteFile, DWORD dwFlags, DWORD dwContext); BOOLAPI FTP_FtpSetCurrentDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory);