[1/2] wininet: Also cache files transferred over ftp.

Hans Leidekker hans at codeweavers.com
Tue Dec 1 10:00:39 CST 2009


Fix for http://bugs.winehq.org/show_bug.cgi?id=20855
---
 dlls/wininet/ftp.c |   68 ++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 63 insertions(+), 5 deletions(-)

diff --git a/dlls/wininet/ftp.c b/dlls/wininet/ftp.c
index 338f743..ea5b355 100644
--- a/dlls/wininet/ftp.c
+++ b/dlls/wininet/ftp.c
@@ -76,6 +76,8 @@ typedef struct
     ftp_session_t *lpFtpSession;
     BOOL session_deleted;
     int nDataSocket;
+    WCHAR *cache_file;
+    HANDLE cache_file_handle;
 } ftp_file_t;
 
 struct _ftp_session_t
@@ -88,6 +90,8 @@ struct _ftp_session_t
     ftp_file_t *download_in_progress;
     struct sockaddr_in socketAddress;
     struct sockaddr_in lstnSocketAddress;
+    LPWSTR servername;
+    INTERNET_PORT serverport;
     LPWSTR  lpszPassword;
     LPWSTR  lpszUserName;
 };
@@ -1098,6 +1102,11 @@ static void FTPFILE_Destroy(object_header_t *hdr)
 
     TRACE("\n");
 
+    if (lpwh->cache_file_handle != INVALID_HANDLE_VALUE)
+        CloseHandle(lpwh->cache_file_handle);
+
+    HeapFree(GetProcessHeap(), 0, lpwh->cache_file);
+
     if (!lpwh->session_deleted)
         lpwfs->download_in_progress = NULL;
 
@@ -1133,6 +1142,7 @@ static DWORD FTPFILE_ReadFile(object_header_t *hdr, void *buffer, DWORD size, DW
 {
     ftp_file_t *file = (ftp_file_t*)hdr;
     int res;
+    DWORD error;
 
     if (file->nDataSocket == -1)
         return ERROR_INTERNET_DISCONNECTED;
@@ -1141,7 +1151,15 @@ static DWORD FTPFILE_ReadFile(object_header_t *hdr, void *buffer, DWORD size, DW
     res = recv(file->nDataSocket, buffer, size, MSG_WAITALL);
     *read = res>0 ? res : 0;
 
-    return res>=0 ? ERROR_SUCCESS : INTERNET_ERROR_BASE; /* FIXME*/
+    error = res >= 0 ? ERROR_SUCCESS : INTERNET_ERROR_BASE; /* FIXME */
+    if (error == ERROR_SUCCESS && file->cache_file)
+    {
+        DWORD bytes_written;
+
+        if (!WriteFile(file->cache_file_handle, buffer, *read, &bytes_written, NULL))
+            WARN("WriteFile failed: %u\n", GetLastError());
+    }
+    return error;
 }
 
 static DWORD FTPFILE_ReadFileExA(object_header_t *hdr, INTERNET_BUFFERSA *buffers,
@@ -1297,7 +1315,9 @@ HINTERNET FTP_FtpOpenFileW(ftp_session_t *lpwfs,
         lpwh->hdr.refs = 1;
         lpwh->hdr.lpfnStatusCB = lpwfs->hdr.lpfnStatusCB;
         lpwh->nDataSocket = nDataSocket;
-	lpwh->session_deleted = FALSE;
+        lpwh->cache_file = NULL;
+        lpwh->cache_file_handle = INVALID_HANDLE_VALUE;
+        lpwh->session_deleted = FALSE;
 
         WININET_AddRef( &lpwfs->hdr );
         lpwh->lpFtpSession = lpwfs;
@@ -1317,6 +1337,41 @@ HINTERNET FTP_FtpOpenFileW(ftp_session_t *lpwfs,
         lpwfs->lstnSocket = -1;
     }
 
+    if (bSuccess && fdwAccess == GENERIC_READ)
+    {
+        WCHAR filename[MAX_PATH + 1];
+        URL_COMPONENTSW uc;
+        DWORD len;
+
+        memset(&uc, 0, sizeof(uc));
+        uc.dwStructSize = sizeof(uc);
+        uc.nScheme      = INTERNET_SCHEME_FTP;
+        uc.lpszHostName = lpwfs->servername;
+        uc.nPort        = lpwfs->serverport;
+        uc.lpszUserName = lpwfs->lpszUserName;
+        uc.lpszUrlPath  = heap_strdupW(lpszFileName);
+
+        if (!InternetCreateUrlW(&uc, 0, NULL, &len) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+        {
+            WCHAR *url = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+
+            if (url && InternetCreateUrlW(&uc, 0, url, &len) && CreateUrlCacheEntryW(url, 0, NULL, filename, 0))
+            {
+                lpwh->cache_file = heap_strdupW(filename);
+                lpwh->cache_file_handle = CreateFileW(filename, GENERIC_WRITE, FILE_SHARE_READ,
+                                                      NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+                if (lpwh->cache_file_handle == INVALID_HANDLE_VALUE)
+                {
+                    WARN("Could not create cache file: %u\n", GetLastError());
+                    HeapFree(GetProcessHeap(), 0, lpwh->cache_file);
+                    lpwh->cache_file = NULL;
+                }
+                HeapFree(GetProcessHeap(), 0, url);
+            }
+        }
+        HeapFree(GetProcessHeap(), 0, uc.lpszUrlPath);
+    }
+
     hIC = lpwfs->lpAppInfo;
     if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
     {
@@ -2256,6 +2311,7 @@ static void FTPSESSION_Destroy(object_header_t *hdr)
 
     HeapFree(GetProcessHeap(), 0, lpwfs->lpszPassword);
     HeapFree(GetProcessHeap(), 0, lpwfs->lpszUserName);
+    HeapFree(GetProcessHeap(), 0, lpwfs->servername);
     HeapFree(GetProcessHeap(), 0, lpwfs);
 }
 
@@ -2374,7 +2430,9 @@ HINTERNET FTP_Connect(appinfo_t *hIC, LPCWSTR lpszServerName,
     }
 
     if (nServerPort == INTERNET_INVALID_PORT_NUMBER)
-	nServerPort = INTERNET_DEFAULT_FTP_PORT;
+        lpwfs->serverport = INTERNET_DEFAULT_FTP_PORT;
+    else
+        lpwfs->serverport = nServerPort;
 
     lpwfs->hdr.htype = WH_HFTPSESSION;
     lpwfs->hdr.vtbl = &FTPSESSIONVtbl;
@@ -2430,6 +2488,7 @@ HINTERNET FTP_Connect(appinfo_t *hIC, LPCWSTR lpszServerName,
         lpwfs->lpszUserName = heap_strdupW(lpszUserName);
         lpwfs->lpszPassword = heap_strdupW(lpszPassword ? lpszPassword : szEmpty);
     }
+    lpwfs->servername = heap_strdupW(lpszServerName);
     
     /* Don't send a handle created callback if this handle was created with InternetOpenUrl */
     if (!(lpwfs->hdr.dwInternalFlags & INET_OPENURL))
@@ -2448,8 +2507,7 @@ HINTERNET FTP_Connect(appinfo_t *hIC, LPCWSTR lpszServerName,
         (LPWSTR) lpszServerName, strlenW(lpszServerName));
 
     sock_namelen = sizeof(socketAddr);
-    if (!GetAddress(lpszServerName, nServerPort,
-        (struct sockaddr *)&socketAddr, &sock_namelen))
+    if (!GetAddress(lpszServerName, lpwfs->serverport, (struct sockaddr *)&socketAddr, &sock_namelen))
     {
 	INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED);
         goto lerror;
-- 
1.6.3.3





More information about the wine-patches mailing list