- use SIZE command to retrieve the file size (as the file size is not
  part of the WinNT acknowledgement string)
- free the handle / close the socket on end of download
- fix InternetReadFile in the FTP case
- fix FTP_ReceiveResponse

diff --git a/dlls/wininet/ftp.c b/dlls/wininet/ftp.c
index ab72434..2cea458 100644
--- a/dlls/wininet/ftp.c
+++ b/dlls/wininet/ftp.c
@@ -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)
diff --git a/dlls/wininet/internet.c b/dlls/wininet/internet.c
index 0f72543..1d9232e 100644
--- a/dlls/wininet/internet.c
+++ b/dlls/wininet/internet.c
@@ -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;
 }
 
diff --git a/dlls/wininet/internet.h b/dlls/wininet/internet.h
index 6e8e0d9..1394f01 100644
--- a/dlls/wininet/internet.h
+++ b/dlls/wininet/internet.h
@@ -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);