[RESEND] msi: Force files' target paths recompute on MsiSetTargetPath

Andrey Turkin pancha at Mail.nnov.ru
Sun Jun 25 13:31:12 CDT 2006


When folder's target path changes, files' target paths should be updated 
too. However, Wine don't flush any cached target paths, so files would 
be installed in incorrect directories. This patch fixes it, and removes 
TARGETDIR special handling because TARGETDIR can be changed by 
MsiSetTargetPath as well as any other path.
This patch diffed against wine-0.9.16 and depends on previous patch 
(disable checks in MsiSetTargetPath) because of changed tests

ChangeLog:
Force files' target paths update on MsiSetTargetPath (with tests)

-------------- next part --------------
--- wine-0.9.16-orig/dlls/msi/install.c	2006-06-25 15:28:43.000000000 +0400
+++ wine-0.9.16/dlls/msi/install.c	2006-06-25 15:31:17.000000000 +0400
@@ -362,6 +362,7 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *pack
     else
     {
         MSIFOLDER *f;
+        MSIFILE *file; 
 
         LIST_FOR_EACH_ENTRY( f, &package->folders, MSIFOLDER, entry )
         {
@@ -374,6 +375,28 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *pack
             path2 = resolve_folder(package, f->Directory, FALSE, TRUE, NULL);
             msi_free(path2);
         }
+
+        LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
+        {
+            MSICOMPONENT* comp = file->Component;
+            LPWSTR p;
+            
+            if (!comp)
+                continue;
+            
+            /* FIXME: do not reset file target path if component directory hasn't changed */
+            
+            p = resolve_folder(package, comp->Directory, FALSE, FALSE, NULL);
+            
+            msi_free(file->TargetPath);
+            file->TargetPath = build_directory_name(2, p, file->FileName);
+
+            msi_free(p);
+
+            if (GetFileAttributesW(file->TargetPath) == INVALID_FILE_ATTRIBUTES)
+                file->state = msifs_missing;
+            /* I don't know what else should be done in case of changed target path */
+        }
     }
     msi_free(path);
 
--- wine-0.9.16-orig/dlls/msi/helpers.c	2006-06-25 11:44:19.000000000 +0400
+++ wine-0.9.16/dlls/msi/helpers.c	2006-06-25 15:31:17.000000000 +0400
@@ -278,29 +278,13 @@ LPWSTR resolve_folder(MSIPACKAGE *packag
     if (!name)
         return NULL;
 
-    /* special resolving for Target and Source root dir */
-    if (strcmpW(name,cszTargetDir)==0 || strcmpW(name,cszSourceDir)==0)
+    /* special resolving for Source root dir */
+    if ( strcmpW(name,cszSourceDir)==0)
     {
-        if (!source)
-        {
-            LPWSTR check_path;
-            check_path = msi_dup_property( package, cszTargetDir );
-            if (!check_path)
-            {
-                check_path = msi_dup_property( package, cszRootDrive );
-                if (set_prop)
-                    MSI_SetPropertyW(package,cszTargetDir,check_path);
-            }
-
-            /* correct misbuilt target dir */
-            path = build_directory_name(2, check_path, NULL);
-            clean_spaces_from_path( path );
-            if (strcmpiW(path,check_path)!=0)
-                MSI_SetPropertyW(package,cszTargetDir,path);
-            msi_free(check_path);
-        }
-        else
+        if (source)
             path = get_source_root( package );
+        else
+            path = NULL;
         if (folder)
             *folder = get_loaded_folder( package, name );
         return path;
@@ -313,6 +297,11 @@ LPWSTR resolve_folder(MSIPACKAGE *packag
     if (folder)
         *folder = f;
 
+    if (strcmpW(name, cszTargetDir)==0 && !f->ResolvedTarget && !f->Property)
+    {
+        f->Property =  msi_dup_property( package, cszRootDrive );
+    }
+
     if (!source && f->ResolvedTarget)
     {
         path = strdupW( f->ResolvedTarget );
--- wine-0.9.16-orig/dlls/msi/tests/package.c	2006-06-25 15:28:43.000000000 +0400
+++ wine-0.9.16/dlls/msi/tests/package.c	2006-06-25 21:52:08.000000000 +0400
@@ -331,9 +331,37 @@ static void test_gettargetpath_bad(void)
     DeleteFile(msifile);
 }
 
+static UINT get_file_targetpath(MSIHANDLE hpkg, const char *file, char *buffer, DWORD size)
+{
+    UINT r;
+    MSIHANDLE rec;
+
+    buffer[0] = 0;
+
+    rec = MsiCreateRecord(1);
+    ok( rec, "cannot create record\n");
+
+    r = MsiRecordSetString( rec, 0, file );
+    if (r)
+    {
+        MsiCloseHandle( rec );
+        return r;
+    }
+
+    r = MsiFormatRecord( hpkg, rec, buffer, &size );
+    if ( r == S_OK )
+    {
+        char *t = strrchr( buffer, '\\' );
+        if ( t )
+            t[1] = 0;
+    }
+    MsiCloseHandle( rec );
+    return r;
+}
+
 static void test_settargetpath(void)
 {
-    char tempdir[MAX_PATH+8], buffer[MAX_PATH];
+    char tempdir[MAX_PATH+8], buffer[MAX_PATH], filebuffer[MAX_PATH];
     DWORD sz;
     MSIHANDLE hpkg;
     UINT r;
@@ -359,7 +387,7 @@ static void test_settargetpath(void)
     r = run_query( hdb,
             "INSERT INTO `Component`  "
             "(`Component`, `ComponentId`, `Directory_`, `Attributes`, `Condition`, `KeyPath`) "
-            "VALUES( 'WinWorkAround', '{83e2694d-0864-4124-9323-6d37630912a1}', 'TARGETDIR', 8, '', 'FL_dummycomponent')" );
+            "VALUES( 'WinWorkAround', '', 'TARGETDIR', 8, '', 'FL_TestFile')" );
     ok( r == S_OK, "cannot add dummy component: %d\n", r );
 
     r = run_query( hdb,
@@ -375,12 +403,56 @@ static void test_settargetpath(void)
             "PRIMARY KEY `Feature`)" );
     ok( r == S_OK, "cannot create Feature table: %d\n", r );
 
+    r = run_query( hdb, "INSERT INTO `Feature` "
+            "(`Feature`, `Feature_Parent`, `Display`, `Level`, `Attributes`) "
+            "VALUES( 'TestFeature', '', 0, 1, 0 )" );
+
+ 
+     r = run_query( hdb, "CREATE TABLE `FeatureComponents` (`Feature_` CHAR(38) NOT NULL, `Component_` CHAR(72) NOT NULL PRIMARY KEY `Feature_` )" );
+     ok( r == S_OK, "cannot create FeatureComponents table: %d\n", r );
+     r = run_query( hdb, "INSERT INTO `FeatureComponents` "
+             "(`Feature_`, `Component_`) VALUES( 'TestFeature', 'WinWorkAround' )" );
+     ok( r == S_OK, "cannot insert component into feature: %d\n", r );
+  
+     r = run_query( hdb, "CREATE TABLE `File` ( "
+             "`File` CHAR(72) NOT NULL, "
+             "`Component_` CHAR(72) NOT NULL, "
+             "`FileName` CHAR(255) NOT NULL, "
+             "`FileSize` LONG NOT NULL, "
+             "`Version` CHAR(72), "
+             "`Language` CHAR(20), "
+             "`Attributes` SHORT, "
+             "`Sequence` SHORT NOT NULL "
+            "PRIMARY KEY `File`)" );
+     ok( r == S_OK, "cannot create File table: %d\n", r );
+     r = run_query( hdb, "INSERT INTO `File` "
+             "(`File`, `Component_`, `FileName`, `FileSize`, `Version`, `Language`, `Attributes`, `Sequence`) "
+             "VALUES( 'FL_TestFile', 'WinWorkAround', 'winetest.fil', 128, '', '1033', 8, 1 )" );
+     ok( r == S_OK, "cannot add file: %d\n", r );
+ 
+     r = run_query( hdb, "CREATE TABLE `Media` ( "
+             "`DiskId` SHORT NOT NULL, "
+             "`LastSequence` SHORT NOT NULL, "
+             "`DiskPrompt` CHAR(64), "
+             "`Cabinet` CHAR(255), "
+             "`VolumeLabel` CHAR(32), "
+             "`Source` CHAR(72) "
+             "PRIMARY KEY `DiskId`)" );
+     ok( r == S_OK, "cannot create Media table: %d\n", r );
+     r = run_query( hdb, "INSERT INTO `Media` "
+             "(`DiskId`, `LastSequence`) "
+             "VALUES( 1, 1)" );
+     ok( r == S_OK, "cannot add media: %d\n", r );
+
     hpkg = package_from_db( hdb );
     ok( hpkg, "failed to create package\n");
 
     r = MsiDoAction( hpkg, "CostInitialize");
     ok( r == ERROR_SUCCESS, "cost init failed\n");
 
+    r = MsiDoAction( hpkg, "FileCost" );
+    ok( r == ERROR_SUCCESS, "file cost failed\n" );
+ 
     r = MsiDoAction( hpkg, "CostFinalize");
     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
 
@@ -398,32 +470,46 @@ static void test_settargetpath(void)
 
     sz = sizeof tempdir - 1;
     r = MsiGetTargetPath( hpkg, "TARGETDIR", tempdir, &sz );
-    if ( r == S_OK )
+    ok( r == S_OK, "get_file_targetpath failed: %d\n", r );
+
+    r = get_file_targetpath(hpkg, "[#FL_TestFile]", filebuffer, sizeof filebuffer-1 );
+    ok( r == S_OK, "get_file_targetpath failed: %d\n", r );
+
+    ok( strcmp(filebuffer, tempdir) == 0, "directories differ: dir path: '%s', file path: '%s'\n", tempdir, filebuffer );
+
+    if ( GetTempFileName( tempdir, "_wt", 0, buffer ) && buffer[0] )
     {
-        if ( GetTempFileName( tempdir, "_wt", 0, buffer ) )
+        char *bufend = buffer + strlen( buffer ) - 1;
+        if ( bufend[0] != '\\' )
         {
-            sprintf( tempdir, "%s\\subdir", buffer );
-            r = MsiSetTargetPath( hpkg, "TARGETDIR", buffer );
-            ok( r == ERROR_SUCCESS, "MsiSetTargetPath on file returned %d\n", r );
+            bufend[1] = '\\';
+            bufend[2] = 0;
+        }
 
-            r = MsiSetTargetPath( hpkg, "TARGETDIR", tempdir );
-            ok( r == ERROR_SUCCESS, "MsiSetTargetPath on 'subdir' of file returned %d\n", r );
+        sprintf( tempdir, "%ssubdir\\", buffer );
+        r = MsiSetTargetPath( hpkg, "TARGETDIR", buffer );
+        ok( r == ERROR_SUCCESS, "MsiSetTargetPath on file returned %d\n", r );
 
-            DeleteFile( buffer );
+        r = MsiSetTargetPath( hpkg, "TARGETDIR", tempdir );
+        ok( r == ERROR_SUCCESS, "MsiSetTargetPath on 'subdir' of file returned %d\n", r );
 
-            r = MsiSetTargetPath( hpkg, "TARGETDIR", buffer );
-            ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
+        DeleteFile( buffer );
 
-            r = GetFileAttributes( buffer );
-            ok ( r == INVALID_FILE_ATTRIBUTES, "file/directory exists after MsiSetTargetPath. Attributes: %08X\n", r );
+        r = MsiSetTargetPath( hpkg, "TARGETDIR", buffer );
+        ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
 
-            r = MsiSetTargetPath( hpkg, "TARGETDIR", tempdir );
-            ok( r == ERROR_SUCCESS, "MsiSetTargetPath on subsubdir returned %d\n", r );
-        } else {
-            trace("GetTempFileName failed, cannot do some tests\n");
-        }
+        r = GetFileAttributes( buffer );
+        ok ( r == 0xFFFFFFFF, "file/directory exists after MsiSetTargetPath. Attributes: %08X\n", r );
+
+        r = get_file_targetpath(hpkg, "[#FL_TestFile]", filebuffer, sizeof filebuffer-1 );
+        ok( r == S_OK, "get_file_targetpath failed\n" );
+
+        ok( strcmp(filebuffer, buffer) == 0, "directories differ: dir path: '%s', file path: '%s'\n", buffer, filebuffer );
+
+        r = MsiSetTargetPath( hpkg, "TARGETDIR", tempdir );
+        ok( r == ERROR_SUCCESS, "MsiSetTargetPath on subsubdir returned %d\n", r );
     } else {
-        trace( "MsiGetTargetPath failed: %d\n", r );
+        trace("GetTempFileName failed, cannot do some tests\n");
     }
     
     MsiCloseHandle( hpkg );


More information about the wine-patches mailing list