msi: Download install cabinet files if the msi package is remote

James Hawkins truiken at gmail.com
Wed Aug 9 17:02:49 CDT 2006


Hi,

This fixes bugs 5681 and 5893.  Both the Ability Office installer and
the MS Platform SDK installer expect MSI to download cab files from
the location where the msi package was downloaded from.  If the
cabinet file already exists in the SourceDir, that cabinet is used
instead of downloading a new one.  If the cabinet is downloaded, and
it doesn't exist anymore, then that cab is silently skipped.  I guess
the logic behind this is that files on a server can change randomly,
so we shouldn't rely on the server for our success or failure.
Ability Office requires this "feature" because Mail.cab is no longer
provided.  None of the files in Mail.cab are installed in windows
either.

http://bugs.winehq.org/show_bug.cgi?id=5681
http://bugs.winehq.org/show_bug.cgi?id=5893

Changelog:
* Download install cabinet files if the msi package is remote and the
cabs don't already exist on the filesystem.

 dlls/msi/files.c   |   61 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 dlls/msi/package.c |    4 ++-
 2 files changed, 62 insertions(+), 3 deletions(-)

-- 
James Hawkins
-------------- next part --------------
diff --git a/dlls/msi/files.c b/dlls/msi/files.c
index 914b699..443e6c3 100644
--- a/dlls/msi/files.c
+++ b/dlls/msi/files.c
@@ -42,6 +42,8 @@ #include "msidefs.h"
 #include "msvcrt/fcntl.h"
 #include "msipriv.h"
 #include "winuser.h"
+#include "winreg.h"
+#include "shlwapi.h"
 #include "wine/unicode.h"
 #include "action.h"
 
@@ -56,6 +58,7 @@ extern const WCHAR szRemoveFiles[];
 
 static const WCHAR cszTempFolder[]= {'T','e','m','p','F','o','l','d','e','r',0};
 
+extern LPCWSTR msi_download_file( LPCWSTR szUrl, LPWSTR filename );
 
 /*
  * This is a helper function for handling embedded cabinet media
@@ -378,6 +381,52 @@ static void free_media_info( struct medi
     msi_free( mi );
 }
 
+/* downloads a remote cabinet and extracts it if it exists */
+static UINT msi_extract_remote_cabinet( MSIPACKAGE *package, struct media_info *mi )
+{
+    FDICABINETINFO cabinfo;
+    WCHAR temppath[MAX_PATH];
+    WCHAR src[MAX_PATH];
+    LPSTR cabpath;
+    LPCWSTR file;
+    LPWSTR ptr;
+    HFDI hfdi;
+    ERF erf;
+    int hf;
+
+    /* the URL is the path prefix of the package URL and the filename
+     * of the file to download
+     */
+    ptr = strrchrW(package->PackagePath, '/');
+    lstrcpynW(src, package->PackagePath, ptr - package->PackagePath + 2);
+    ptr = strrchrW(mi->source, '\\');
+    lstrcatW(src, ptr + 1);
+
+    file = msi_download_file( src, temppath );
+    lstrcpyW(mi->source, file);
+
+    /* check if the remote cabinet still exists, ignore if it doesn't */
+    hfdi = FDICreate(cabinet_alloc, cabinet_free, cabinet_open, cabinet_read,
+                     cabinet_write, cabinet_close, cabinet_seek, 0, &erf);
+    if (!hfdi)
+    {
+        ERR("FDICreate failed\n");
+        return ERROR_FUNCTION_FAILED;
+    }
+
+    cabpath = strdupWtoA(mi->source);
+    hf = cabinet_open(cabpath, _O_RDONLY, 0);
+    if (!FDIIsCabinet(hfdi, hf, &cabinfo))
+    {
+        WARN("Remote cabinet %s does not exist.\n", debugstr_w(mi->source));
+        msi_free(cabpath);
+        return ERROR_SUCCESS;
+    }
+
+    msi_free(cabpath);
+    return !extract_cabinet_file(package, mi->source, mi->last_path);
+}
+
 static UINT ready_media_for_file( MSIPACKAGE *package, struct media_info *mi,
                                   MSIFILE *file )
 {
@@ -488,7 +537,17 @@ static UINT ready_media_for_file( MSIPAC
                     GetTempPathW(MAX_PATH,mi->last_path);
             }
         }
-        rc = !extract_cabinet_file(package, mi->source, mi->last_path);
+
+        /* only download the remote cabinet file if a local copy does not exist */
+        if (GetFileAttributesW(mi->source) == INVALID_FILE_ATTRIBUTES &&
+            UrlIsW(package->PackagePath, URLIS_URL))
+        {
+            rc = msi_extract_remote_cabinet(package, mi);
+        }
+        else
+        {
+            rc = !extract_cabinet_file(package, mi->source, mi->last_path);
+        }
     }
     else
     {
diff --git a/dlls/msi/package.c b/dlls/msi/package.c
index 4065ffb..d172c50 100644
--- a/dlls/msi/package.c
+++ b/dlls/msi/package.c
@@ -485,7 +485,7 @@ static LPCWSTR copy_package_to_temp( LPC
     return filename;
 }
 
-static LPCWSTR msi_download_package( LPCWSTR szUrl, LPWSTR filename )
+LPCWSTR msi_download_file( LPCWSTR szUrl, LPWSTR filename )
 {
     LPINTERNET_CACHE_ENTRY_INFOW cache_entry;
     DWORD size = 0;
@@ -539,7 +539,7 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage,
         LPCWSTR file;
 
         if ( UrlIsW( szPackage, URLIS_URL ) )
-            file = msi_download_package( szPackage, temppath );
+            file = msi_download_file( szPackage, temppath );
         else
             file = copy_package_to_temp( szPackage, temppath );
 
-- 
1.3.3



More information about the wine-patches mailing list