Hans Leidekker : msi: Move all file comparisons to CostFinalize.

Alexandre Julliard julliard at winehq.org
Wed Apr 28 16:35:51 CDT 2010


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

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Tue Apr 27 13:30:32 2010 +0200

msi: Move all file comparisons to CostFinalize.

File costing can't be done correctly on upgrades unless we know
which files are going to be overwritten.

---

 dlls/msi/action.c |   74 ++++++++++++++++++++++++++++++++++++++---------------
 dlls/msi/files.c  |   29 --------------------
 2 files changed, 53 insertions(+), 50 deletions(-)

diff --git a/dlls/msi/action.c b/dlls/msi/action.c
index 5168cf9..0b23656 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -1909,7 +1909,7 @@ static UINT ITERATE_CostFinalizeConditions(MSIRECORD *row, LPVOID param)
     return ERROR_SUCCESS;
 }
 
-static LPWSTR msi_get_disk_file_version( LPCWSTR filename )
+static LPWSTR get_disk_file_version( LPCWSTR filename )
 {
     static const WCHAR name_fmt[] =
         {'%','u','.','%','u','.','%','u','.','%','u',0};
@@ -1947,7 +1947,36 @@ static LPWSTR msi_get_disk_file_version( LPCWSTR filename )
     return strdupW( filever );
 }
 
-static UINT msi_check_file_install_states( MSIPACKAGE *package )
+static DWORD get_disk_file_size( LPCWSTR filename )
+{
+    HANDLE file;
+    DWORD size;
+
+    TRACE("%s\n", debugstr_w(filename));
+
+    file = CreateFileW( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
+    if (file == INVALID_HANDLE_VALUE)
+        return INVALID_FILE_SIZE;
+
+    size = GetFileSize( file, NULL );
+    CloseHandle( file );
+    return size;
+}
+
+static BOOL hash_matches( MSIFILE *file )
+{
+    UINT r;
+    MSIFILEHASHINFO hash;
+
+    hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
+    r = MsiGetFileHashW( file->TargetPath, 0, &hash );
+    if (r != ERROR_SUCCESS)
+        return FALSE;
+
+    return !memcmp( &hash, &file->hash, sizeof(MSIFILEHASHINFO) );
+}
+
+static UINT set_file_install_states( MSIPACKAGE *package )
 {
     LPWSTR file_version;
     MSIFILE *file;
@@ -1955,6 +1984,7 @@ static UINT msi_check_file_install_states( MSIPACKAGE *package )
     LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
     {
         MSICOMPONENT* comp = file->Component;
+        DWORD file_size;
         LPWSTR p;
 
         if (!comp)
@@ -1978,41 +2008,43 @@ static UINT msi_check_file_install_states( MSIPACKAGE *package )
         TRACE("file %s resolves to %s\n",
                debugstr_w(file->File), debugstr_w(file->TargetPath));
 
-        /* don't check files of components that aren't installed */
-        if (comp->Installed == INSTALLSTATE_UNKNOWN ||
-            comp->Installed == INSTALLSTATE_ABSENT)
-        {
-            file->state = msifs_missing;  /* assume files are missing */
-            continue;
-        }
-
         if (GetFileAttributesW(file->TargetPath) == INVALID_FILE_ATTRIBUTES)
         {
             file->state = msifs_missing;
             comp->Cost += file->FileSize;
             continue;
         }
-
-        if (file->Version &&
-            (file_version = msi_get_disk_file_version( file->TargetPath )))
+        if (file->Version && (file_version = get_disk_file_version( file->TargetPath )))
         {
-            TRACE("new %s old %s\n", debugstr_w(file->Version),
-                  debugstr_w(file_version));
-            /* FIXME: seems like a bad way to compare version numbers */
-            if (lstrcmpiW(file_version, file->Version)<0)
+            TRACE("new %s old %s\n", debugstr_w(file->Version), debugstr_w(file_version));
+
+            if (strcmpiW(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;
+            }
             msi_free( file_version );
+            continue;
         }
-        else
+        if ((file_size = get_disk_file_size( file->TargetPath )) != file->FileSize)
         {
             file->state = msifs_overwrite;
-            comp->Cost += file->FileSize;
+            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;
@@ -2057,8 +2089,8 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
     ACTION_GetComponentInstallStates(package);
     ACTION_GetFeatureInstallStates(package);
 
-    TRACE("File calculations\n");
-    msi_check_file_install_states( package );
+    TRACE("Calculating file install states\n");
+    set_file_install_states( package );
 
     if (!process_overrides( package, msi_get_property_int( package->db, szlevel, 1 ) ))
     {
diff --git a/dlls/msi/files.c b/dlls/msi/files.c
index 14366f4..4445773 100644
--- a/dlls/msi/files.c
+++ b/dlls/msi/files.c
@@ -175,22 +175,6 @@ static UINT copy_install_file(MSIPACKAGE *package, MSIFILE *file, LPWSTR source)
     return gle;
 }
 
-static BOOL check_dest_hash_matches(MSIFILE *file)
-{
-    MSIFILEHASHINFO hash;
-    UINT r;
-
-    if (!file->hash.dwFileHashInfoSize)
-        return FALSE;
-
-    hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
-    r = MsiGetFileHashW(file->TargetPath, 0, &hash);
-    if (r != ERROR_SUCCESS)
-        return FALSE;
-
-    return !memcmp(&hash, &file->hash, sizeof(MSIFILEHASHINFO));
-}
-
 static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action,
                             LPWSTR *path, DWORD *attrs, PVOID user)
 {
@@ -258,19 +242,6 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
         if (file->state != msifs_missing && !mi->is_continuous && file->state != msifs_overwrite)
             continue;
 
-        if (check_dest_hash_matches(file))
-        {
-            TRACE("File hashes match, not overwriting\n");
-            continue;
-        }
-
-        if (MsiGetFileVersionW(file->TargetPath, NULL, NULL, NULL, NULL) == ERROR_SUCCESS &&
-            msi_compare_file_version(file) >= 0)
-        {
-            TRACE("Destination file version greater, not overwriting\n");
-            continue;
-        }
-
         if (file->Sequence > mi->last_sequence || mi->is_continuous ||
             (file->IsCompressed && !mi->is_extracted))
         {




More information about the wine-cvs mailing list