msi: Fix the compressed files logic [RESEND]

James Hawkins truiken at gmail.com
Mon Aug 7 13:37:49 CDT 2006


Hi,

This patch wasn't committed, so I'll explain it more this time.  With
the current compressed files logic, any installer that installs files
from cabinets but doesn't set the compressed file attribute in the
database will fail to install those files.  The problem is that we
have never taken into account the Word Count property of the install
package.  According to msdn and tests, if the file attributes are not
set (msidbFileAttributesNoncompressed, msidbFileAttributesCompressed)
then the Word Count property is used to determine if files are
compressed or not.  We're specifically checking bit 1; if it's set,
the files are compressed, uncompressed otherwise.  This patch
determines at file load time whether the file is compressed or not,
using the variable IsCompressed, and this var is used when installing
the file instead of always checking the file attributes (which aren't
always set.)  If there is anything wrong with this patch, please let
me know as many installers are now failing to install all their files.
 Fixes at least bug 5866.  http://bugs.winehq.org/show_bug.cgi?id=5866

Changelog:
* If the compressed file attribute is not set, use the Word Count
property to determine if files are compressed.

 dlls/msi/action.c  |   16 ++++++++++++++++
 dlls/msi/action.h  |    1 +
 dlls/msi/files.c   |    6 +++---
 dlls/msi/msipriv.h |    8 ++++++++
 dlls/msi/package.c |   30 ++++++++++++++++++++++++++++++
 5 files changed, 58 insertions(+), 3 deletions(-)

-- 
James Hawkins
-------------- next part --------------
diff --git a/dlls/msi/action.c b/dlls/msi/action.c
index e2d78b1..a90096e 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -1326,8 +1326,24 @@ static UINT load_file(MSIRECORD *row, LP
 
     file->state = msifs_invalid;
 
+    /* if the compressed bits are not set in the file attributes,
+     * then read the information from the package word count property
+     */
     if (file->Attributes & msidbFileAttributesCompressed)
     {
+        file->IsCompressed = TRUE;
+    }
+    else if (file->Attributes & msidbFileAttributesNoncompressed)
+    {
+        file->IsCompressed = FALSE;
+    }
+    else
+    {
+        file->IsCompressed = package->WordCount & MSIWORDCOUNT_COMPRESSED;
+    }
+
+    if (file->IsCompressed)
+    {
         file->Component->ForceLocalState = TRUE;
         file->Component->Action = INSTALLSTATE_LOCAL;
         file->Component->ActionRequest = INSTALLSTATE_LOCAL;
diff --git a/dlls/msi/action.h b/dlls/msi/action.h
index 93d28c6..22ad1be 100644
--- a/dlls/msi/action.h
+++ b/dlls/msi/action.h
@@ -120,6 +120,7 @@ typedef struct tagMSIFILE
     msi_file_state state;
     LPWSTR  SourcePath;
     LPWSTR  TargetPath;
+    BOOL IsCompressed;
 } MSIFILE;
 
 typedef struct tagMSITEMPFILE
diff --git a/dlls/msi/files.c b/dlls/msi/files.c
index 36caba7..914b699 100644
--- a/dlls/msi/files.c
+++ b/dlls/msi/files.c
@@ -330,7 +330,7 @@ static BOOL extract_cabinet_file(MSIPACK
 static VOID set_file_source(MSIPACKAGE* package, MSIFILE* file, MSICOMPONENT*
         comp, LPCWSTR path)
 {
-    if (!(file->Attributes & msidbFileAttributesCompressed))
+    if (!file->IsCompressed)
     {
         LPWSTR p, path;
         p = resolve_folder(package, comp->Directory, TRUE, FALSE, NULL);
@@ -419,7 +419,7 @@ static UINT ready_media_for_file( MSIPAC
     msi_free(mi->last_path);
     mi->last_path = NULL;
 
-    if (!(file->Attributes & msidbFileAttributesCompressed))
+    if (!file->IsCompressed)
     {
         mi->last_path = resolve_folder(package, comp->Directory, TRUE, FALSE, NULL);
         set_file_source(package,file,comp,mi->last_path);
@@ -605,7 +605,7 @@ UINT ACTION_InstallFiles(MSIPACKAGE *pac
             continue;
 
         /* compressed files are extracted in ready_media_for_file */
-        if (file->Attributes & msidbFileAttributesCompressed)
+        if (file->IsCompressed)
         {
             if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW(file->TargetPath))
                 ERR("compressed file wasn't extracted (%s)\n",
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 5d2c21e..c565b67 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -39,6 +39,12 @@ #define MSITYPE_STRING   0x0800
 #define MSITYPE_NULLABLE 0x1000
 #define MSITYPE_KEY      0x2000
 
+/* Word Count masks */
+#define MSIWORDCOUNT_SHORTFILENAMES     0x0001
+#define MSIWORDCOUNT_COMPRESSED         0x0002
+#define MSIWORDCOUNT_ADMINISTRATIVE     0x0004
+#define MSIWORDCOUNT_PRIVILEGES         0x0008
+
 #define MSITYPE_IS_BINARY(type) (((type) & ~MSITYPE_NULLABLE) == (MSITYPE_STRING|MSITYPE_VALID))
 
 struct tagMSITABLE;
@@ -223,6 +229,8 @@ typedef struct tagMSIPACKAGE
     UINT CurrentInstallState;
     msi_dialog *dialog;
     LPWSTR next_dialog;
+
+    UINT WordCount;
     
     struct list subscriptions;
 } MSIPACKAGE;
diff --git a/dlls/msi/package.c b/dlls/msi/package.c
index 283b0a6..6b468e5 100644
--- a/dlls/msi/package.c
+++ b/dlls/msi/package.c
@@ -40,6 +40,7 @@ #include "urlmon.h"
 #include "shlobj.h"
 #include "wine/unicode.h"
 #include "objbase.h"
+#include "msidefs.h"
 
 #include "msipriv.h"
 #include "action.h"
@@ -376,6 +377,33 @@ static VOID set_installer_properties(MSI
     ReleaseDC(0, dc);
 }
 
+static UINT msi_get_word_count( MSIPACKAGE *package )
+{
+    UINT rc, word_count;
+    MSIHANDLE suminfo;
+    MSIHANDLE hdb = alloc_msihandle( &package->db->hdr );
+
+    rc = MsiGetSummaryInformationW( hdb, NULL, 0, &suminfo );
+    MsiCloseHandle(hdb);
+    if (rc != ERROR_SUCCESS)
+    {
+        ERR("Unable to open Summary Information\n");
+        return 0;
+    }
+
+    rc = MsiSummaryInfoGetPropertyW( suminfo, PID_WORDCOUNT, NULL,
+                                     &word_count, NULL, NULL, NULL );
+    if (rc != ERROR_SUCCESS)
+    {
+        ERR("Unable to query word count\n");
+        MsiCloseHandle(suminfo);
+        return 0;
+    }
+
+    MsiCloseHandle(suminfo);
+    return word_count;
+}
+
 MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db )
 {
     static const WCHAR szLevel[] = { 'U','I','L','e','v','e','l',0 };
@@ -411,6 +439,8 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABA
         list_init( &package->progids );
         list_init( &package->RunningActions );
 
+        package->WordCount = msi_get_word_count( package );
+
         /* OK, here is where we do a slew of things to the database to 
          * prep for all that is to come as a package */
 
-- 
1.3.3


More information about the wine-patches mailing list