Jacek Caban : appwiz.cpl: Cache downloaded addon MSI files.

Alexandre Julliard julliard at winehq.org
Tue Oct 9 13:12:35 CDT 2012


Module: wine
Branch: master
Commit: d18465088705bfbb39e5ee50bd7660773c9de51f
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=d18465088705bfbb39e5ee50bd7660773c9de51f

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Tue Oct  9 15:48:47 2012 +0200

appwiz.cpl: Cache downloaded addon MSI files.

---

 dlls/appwiz.cpl/addons.c |  126 ++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 111 insertions(+), 15 deletions(-)

diff --git a/dlls/appwiz.cpl/addons.c b/dlls/appwiz.cpl/addons.c
index 82a6797..efb6cf0 100644
--- a/dlls/appwiz.cpl/addons.c
+++ b/dlls/appwiz.cpl/addons.c
@@ -17,10 +17,12 @@
  */
 
 #include "config.h"
+#include "wine/port.h"
 
 #include <stdarg.h>
 #include <fcntl.h>
 #include <stdio.h>
+#include <errno.h>
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif
@@ -105,6 +107,10 @@ static const addon_info_t *addon;
 static HWND install_dialog = NULL;
 static LPWSTR url = NULL;
 
+static WCHAR * (CDECL *p_wine_get_dos_file_name)(const char*);
+static const WCHAR kernel32_dllW[] = {'k','e','r','n','e','l','3','2','.','d','l','l',0};
+
+
 /* SHA definitions are copied from advapi32. They aren't available in headers. */
 
 typedef struct {
@@ -153,13 +159,7 @@ static BOOL sha_check(const WCHAR *file_name)
         sprintf(buf + i*2, "%02x", *((unsigned char*)sha+i));
 
     if(strcmp(buf, addon->sha)) {
-        WCHAR message[256];
-
         WARN("Got %s, expected %s\n", buf, addon->sha);
-
-        if(LoadStringW(hInst, IDS_INVALID_SHA, message, sizeof(message)/sizeof(WCHAR)))
-            MessageBoxW(NULL, message, NULL, MB_ICONERROR);
-
         return FALSE;
     }
 
@@ -201,9 +201,6 @@ static enum install_res install_from_unix_file(const char *dir, const char *subd
     int fd, len;
     enum install_res ret;
 
-    static WCHAR * (CDECL *wine_get_dos_file_name)(const char*);
-    static const WCHAR kernel32W[] = {'k','e','r','n','e','l','3','2','.','d','l','l',0};
-
     len = strlen(dir);
     file_path = heap_alloc(len+strlen(subdir)+strlen(file_name)+3);
     if(!file_path)
@@ -228,11 +225,8 @@ static enum install_res install_from_unix_file(const char *dir, const char *subd
 
     close(fd);
 
-    if(!wine_get_dos_file_name)
-        wine_get_dos_file_name = (void*)GetProcAddress(GetModuleHandleW(kernel32W), "wine_get_dos_file_name");
-
-    if(wine_get_dos_file_name) { /* Wine UNIX mode */
-	dos_file_name = wine_get_dos_file_name(file_path);
+    if(p_wine_get_dos_file_name) { /* Wine UNIX mode */
+	dos_file_name = p_wine_get_dos_file_name(file_path);
 	if(!dos_file_name) {
 	    ERR("Could not get dos file name of %s\n", debugstr_a(file_path));
             heap_free(file_path);
@@ -334,6 +328,90 @@ static enum install_res install_from_default_dir(void)
     return ret;
 }
 
+static WCHAR *get_cache_file_name(BOOL ensure_exists)
+{
+    const char *home_dir = NULL, *xdg_cache_dir;
+    size_t len, size = strlen(addon->file_name) + 7; /* strlen("/wine/"), '\0' */
+    char *cache_file_name;
+    WCHAR *ret;
+
+    /* non-Wine (eg. Windows) cache is currently not supported */
+    if(!p_wine_get_dos_file_name)
+        return NULL;
+
+    xdg_cache_dir = getenv("XDG_CACHE_HOME");
+    if(xdg_cache_dir && *xdg_cache_dir) {
+        size += strlen(xdg_cache_dir);
+    }else {
+        home_dir = getenv("HOME");
+        if(!home_dir)
+            return NULL;
+
+        size += strlen(home_dir) + 8; /* strlen("/.cache/") */
+    }
+
+    cache_file_name = heap_alloc(size);
+    if(!cache_file_name)
+        return NULL;
+
+    if(xdg_cache_dir && *xdg_cache_dir) {
+        len = strlen(xdg_cache_dir);
+        if(len > 1 && xdg_cache_dir[len-1] == '/')
+            len--;
+        memcpy(cache_file_name, xdg_cache_dir, len);
+        cache_file_name[len] = 0;
+    }else {
+        len = strlen(home_dir);
+        memcpy(cache_file_name, home_dir, len);
+        strcpy(cache_file_name+len, "/.cache");
+        len += 7;
+    }
+
+    if(ensure_exists && mkdir(cache_file_name, 0777) && errno != EEXIST) {
+        WARN("%s does not exist and could not be created: %s\n", cache_file_name, strerror(errno));
+        heap_free(cache_file_name);
+        return NULL;
+    }
+
+    strcpy(cache_file_name+len, "/wine");
+    len += 5;
+
+    if(ensure_exists && mkdir(cache_file_name, 0777) && errno != EEXIST) {
+        WARN("%s does not exist and could not be created: %s\n", cache_file_name, strerror(errno));
+        return NULL;
+    }
+
+    cache_file_name[len++] = '/';
+    strcpy(cache_file_name+len, addon->file_name);
+    ret = p_wine_get_dos_file_name(cache_file_name);
+
+    TRACE("%s -> %s\n", cache_file_name, debugstr_w(ret));
+
+    heap_free(cache_file_name);
+    return ret;
+}
+
+static enum install_res install_from_cache(void)
+{
+    WCHAR *cache_file_name;
+    enum install_res res;
+
+    cache_file_name = get_cache_file_name(FALSE);
+    if(!cache_file_name)
+        return INSTALL_NEXT;
+
+    if(!sha_check(cache_file_name)) {
+        WARN("could not validate check sum\n");
+        DeleteFileW(cache_file_name);
+        heap_free(cache_file_name);
+        return INSTALL_NEXT;
+    }
+
+    res = install_file(cache_file_name);
+    heap_free(cache_file_name);
+    return res;
+}
+
 static HRESULT WINAPI InstallCallback_QueryInterface(IBindStatusCallback *iface,
         REFIID riid, void **ppv)
 {
@@ -501,8 +579,23 @@ static DWORD WINAPI download_proc(PVOID arg)
         return 0;
     }
 
-    if(sha_check(tmp_file))
+    if(sha_check(tmp_file)) {
+        WCHAR *cache_file_name;
+
         install_file(tmp_file);
+
+        cache_file_name = get_cache_file_name(TRUE);
+        if(cache_file_name) {
+            MoveFileW(tmp_file, cache_file_name);
+            heap_free(cache_file_name);
+        }
+    }else {
+        WCHAR message[256];
+
+        if(LoadStringW(hInst, IDS_INVALID_SHA, message, sizeof(message)/sizeof(WCHAR)))
+            MessageBoxW(NULL, message, NULL, MB_ICONERROR);
+    }
+
     DeleteFileW(tmp_file);
     EndDialog(install_dialog, 0);
     return 0;
@@ -589,6 +682,8 @@ BOOL install_addon(addon_t addon_type)
 
     addon = addons_info+addon_type;
 
+    p_wine_get_dos_file_name = (void*)GetProcAddress(GetModuleHandleW(kernel32_dllW), "wine_get_dos_file_name");
+
     /*
      * Try to find addon .msi file in following order:
      * - directory stored in $dir_config_key value of HKCU/Wine/Software/$config_key key
@@ -599,6 +694,7 @@ BOOL install_addon(addon_t addon_type)
      */
     if (install_from_registered_dir() == INSTALL_NEXT
         && install_from_default_dir() == INSTALL_NEXT
+        && install_from_cache() == INSTALL_NEXT
         && (url = get_url()))
         DialogBoxW(hInst, addon->dialog_template, 0, installer_proc);
 




More information about the wine-cvs mailing list