Hans Leidekker : msi: Make a second pass to determine which files to install in the InstallFiles action .

Alexandre Julliard julliard at winehq.org
Tue Mar 8 11:03:51 CST 2011


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

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Tue Mar  8 10:08:16 2011 +0100

msi: Make a second pass to determine which files to install in the InstallFiles action.

This is needed because the target path can still change after CostFinalize
is executed. This happens in the .NET 1.1 Service Pack 1 installer where a
custom action calls SetTargetPath.

---

 dlls/msi/action.c  |   52 +++++++--------------------------
 dlls/msi/files.c   |   81 ++++++++++++++++++++++++++++++++++++++++++++-------
 dlls/msi/msipriv.h |    4 ++-
 3 files changed, 84 insertions(+), 53 deletions(-)

diff --git a/dlls/msi/action.c b/dlls/msi/action.c
index 86aa33f..a003f5e 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -2178,7 +2178,7 @@ int msi_compare_file_versions( VS_FIXEDFILEINFO *fi, const WCHAR *version )
     return 0;
 }
 
-static int msi_compare_font_versions( const WCHAR *ver1, const WCHAR *ver2 )
+int msi_compare_font_versions( const WCHAR *ver1, const WCHAR *ver2 )
 {
     DWORD ms1, ms2;
 
@@ -2190,7 +2190,7 @@ static int msi_compare_font_versions( const WCHAR *ver1, const WCHAR *ver2 )
     return 0;
 }
 
-static DWORD get_disk_file_size( LPCWSTR filename )
+DWORD msi_get_disk_file_size( LPCWSTR filename )
 {
     HANDLE file;
     DWORD size;
@@ -2206,7 +2206,7 @@ static DWORD get_disk_file_size( LPCWSTR filename )
     return size;
 }
 
-static BOOL hash_matches( MSIFILE *file )
+BOOL msi_file_hash_matches( MSIFILE *file )
 {
     UINT r;
     MSIFILEHASHINFO hash;
@@ -2256,7 +2256,7 @@ static void set_target_path( MSIPACKAGE *package, MSIFILE *file )
     TRACE("resolves to %s\n", debugstr_w(file->TargetPath));
 }
 
-static UINT set_file_install_states( MSIPACKAGE *package )
+static UINT calculate_file_cost( MSIPACKAGE *package )
 {
     VS_FIXEDFILEINFO *file_version;
     WCHAR *font_version;
@@ -2277,67 +2277,37 @@ static UINT set_file_install_states( MSIPACKAGE *package )
         if ((comp->assembly && !comp->assembly->installed) ||
             GetFileAttributesW(file->TargetPath) == INVALID_FILE_ATTRIBUTES)
         {
-            file->state = msifs_missing;
             comp->Cost += file->FileSize;
             continue;
         }
+        file_size = msi_get_disk_file_size( file->TargetPath );
+
         if (file->Version)
         {
             if ((file_version = msi_get_disk_file_version( file->TargetPath )))
             {
-                TRACE("new %s old %u.%u.%u.%u\n", debugstr_w(file->Version),
-                      HIWORD(file_version->dwFileVersionMS),
-                      LOWORD(file_version->dwFileVersionMS),
-                      HIWORD(file_version->dwFileVersionLS),
-                      LOWORD(file_version->dwFileVersionLS));
-
                 if (msi_compare_file_versions( file_version, file->Version ) < 0)
                 {
-                    file->state = msifs_overwrite;
-                    comp->Cost += file->FileSize;
-                }
-                else
-                {
-                    TRACE("Destination file version equal or greater, not overwriting\n");
-                    file->state = msifs_present;
+                    comp->Cost += file->FileSize - file_size;
                 }
                 msi_free( file_version );
                 continue;
             }
             else if ((font_version = font_version_from_file( file->TargetPath )))
             {
-                TRACE("new %s old %s\n", debugstr_w(file->Version), debugstr_w(font_version));
-
                 if (msi_compare_font_versions( font_version, file->Version ) < 0)
                 {
-                    file->state = msifs_overwrite;
-                    comp->Cost += file->FileSize;
-                }
-                else
-                {
-                    TRACE("Destination file version equal or greater, not overwriting\n");
-                    file->state = msifs_present;
+                    comp->Cost += file->FileSize - file_size;
                 }
                 msi_free( font_version );
                 continue;
             }
         }
-        if ((file_size = get_disk_file_size( file->TargetPath )) != file->FileSize)
+        if (file_size != file->FileSize)
         {
-            file->state = msifs_overwrite;
             comp->Cost += file->FileSize - file_size;
-            continue;
         }
-        if (file->hash.dwFileHashInfoSize && hash_matches( file ))
-        {
-            TRACE("File hashes match, not overwriting\n");
-            file->state = msifs_present;
-            continue;
-        }
-        file->state = msifs_overwrite;
-        comp->Cost += file->FileSize - file_size;
     }
-
     return ERROR_SUCCESS;
 }
 
@@ -2404,8 +2374,8 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
         }
     }
 
-    TRACE("Calculating file install states\n");
-    set_file_install_states( package );
+    TRACE("Calculating file cost\n");
+    calculate_file_cost( package );
 
     msi_set_property( package->db, szCosting, szOne );
     /* set default run level if not set */
diff --git a/dlls/msi/files.c b/dlls/msi/files.c
index df765e5..e88a0c6 100644
--- a/dlls/msi/files.c
+++ b/dlls/msi/files.c
@@ -60,6 +60,73 @@ static void msi_file_update_ui( MSIPACKAGE *package, MSIFILE *f, const WCHAR *ac
     ui_progress( package, 2, f->FileSize, 0, 0 );
 }
 
+static msi_file_state calculate_install_state( MSIFILE *file )
+{
+    MSICOMPONENT *comp = file->Component;
+    VS_FIXEDFILEINFO *file_version;
+    WCHAR *font_version;
+    msi_file_state state;
+    DWORD file_size;
+
+    if (comp->ActionRequest != INSTALLSTATE_LOCAL || !comp->Enabled ||
+        (comp->assembly && comp->assembly->installed))
+    {
+        TRACE("file %s is not scheduled for install\n", debugstr_w(file->File));
+        return msifs_skipped;
+    }
+    if ((comp->assembly && !comp->assembly->installed) ||
+        GetFileAttributesW( file->TargetPath ) == INVALID_FILE_ATTRIBUTES)
+    {
+        TRACE("file %s is missing\n", debugstr_w(file->File));
+        return msifs_missing;
+    }
+    if (file->Version)
+    {
+        if ((file_version = msi_get_disk_file_version( file->TargetPath )))
+        {
+            TRACE("new %s old %u.%u.%u.%u\n", debugstr_w(file->Version),
+                  HIWORD(file_version->dwFileVersionMS),
+                  LOWORD(file_version->dwFileVersionMS),
+                  HIWORD(file_version->dwFileVersionLS),
+                  LOWORD(file_version->dwFileVersionLS));
+
+            if (msi_compare_file_versions( file_version, file->Version ) < 0)
+                state = msifs_overwrite;
+            else
+            {
+                TRACE("destination file version equal or greater, not overwriting\n");
+                state = msifs_present;
+            }
+            msi_free( file_version );
+            return state;
+        }
+        else if ((font_version = font_version_from_file( file->TargetPath )))
+        {
+            TRACE("new %s old %s\n", debugstr_w(file->Version), debugstr_w(font_version));
+
+            if (msi_compare_font_versions( font_version, file->Version ) < 0)
+                state = msifs_overwrite;
+            else
+            {
+                TRACE("destination file version equal or greater, not overwriting\n");
+                state = msifs_present;
+            }
+            msi_free( font_version );
+            return state;
+        }
+    }
+    if ((file_size = msi_get_disk_file_size( file->TargetPath )) != file->FileSize)
+    {
+        return msifs_overwrite;
+    }
+    if (file->hash.dwFileHashInfoSize && msi_file_hash_matches( file ))
+    {
+        TRACE("file hashes match, not overwriting\n");
+        return msifs_present;
+    }
+    return msifs_overwrite;
+}
+
 static void schedule_install_files(MSIPACKAGE *package)
 {
     MSIFILE *file;
@@ -68,22 +135,14 @@ static void schedule_install_files(MSIPACKAGE *package)
     {
         MSICOMPONENT *comp = file->Component;
 
-        if (comp->ActionRequest != INSTALLSTATE_LOCAL || !comp->Enabled ||
-            (comp->assembly && comp->assembly->installed))
+        file->state = calculate_install_state( file );
+        if (file->state == msifs_overwrite && (comp->Attributes & msidbComponentAttributesNeverOverwrite))
         {
-            TRACE("File %s is not scheduled for install\n", debugstr_w(file->File));
+            TRACE("not overwriting %s\n", debugstr_w(file->TargetPath));
             file->state = msifs_skipped;
-            continue;
         }
         comp->Action = INSTALLSTATE_LOCAL;
         ui_progress( package, 2, file->FileSize, 0, 0 );
-
-        if (file->state == msifs_overwrite &&
-            (comp->Attributes & msidbComponentAttributesNeverOverwrite))
-        {
-            TRACE("not overwriting %s\n", debugstr_w(file->TargetPath));
-            file->state = msifs_skipped;
-        }
     }
 }
 
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 7c25ec9..9ddcaeb 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -856,7 +856,9 @@ extern DWORD msi_version_str_to_dword(LPCWSTR p);
 extern void msi_parse_version_string(LPCWSTR, PDWORD, PDWORD);
 extern VS_FIXEDFILEINFO *msi_get_disk_file_version(LPCWSTR);
 extern int msi_compare_file_versions(VS_FIXEDFILEINFO *, const WCHAR *);
-
+extern int msi_compare_font_versions(const WCHAR *, const WCHAR *);
+extern DWORD msi_get_disk_file_size(LPCWSTR);
+extern BOOL msi_file_hash_matches(MSIFILE *);
 
 extern LONG msi_reg_set_val_str( HKEY hkey, LPCWSTR name, LPCWSTR value );
 extern LONG msi_reg_set_val_multi_str( HKEY hkey, LPCWSTR name, LPCWSTR value );




More information about the wine-cvs mailing list