Hans Leidekker : msi: Make sure target paths are normalized.

Alexandre Julliard julliard at winehq.org
Wed Jan 18 14:03:41 CST 2012


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

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Wed Jan 18 12:58:15 2012 +0100

msi: Make sure target paths are normalized.

Fix for the Lotus Notes 6.5.1 installer.

---

 dlls/msi/action.c        |   47 +++++++++++++++++++--------------------------
 dlls/msi/install.c       |   17 ++-------------
 dlls/msi/msipriv.h       |    2 +-
 dlls/msi/tests/package.c |   16 +++++++++++++++
 4 files changed, 40 insertions(+), 42 deletions(-)

diff --git a/dlls/msi/action.c b/dlls/msi/action.c
index 5444dfc..baebdc2 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -2214,11 +2214,15 @@ static UINT calculate_file_cost( MSIPACKAGE *package )
     return ERROR_SUCCESS;
 }
 
-void msi_clean_path( WCHAR *p )
+WCHAR *msi_normalize_path( const WCHAR *in )
 {
-    WCHAR *q = p;
-    int n, len = 0;
+    const WCHAR *p = in;
+    WCHAR *q, *ret;
+    int n, len = strlenW( in ) + 2;
 
+    if (!(q = ret = msi_alloc( len * sizeof(WCHAR) ))) return NULL;
+
+    len = 0;
     while (1)
     {
         /* copy until the end of the string or a space */
@@ -2245,32 +2249,20 @@ void msi_clean_path( WCHAR *p )
         else  /* copy n spaces */
             while (n && (*q++ = *p++)) n--;
     }
-}
-
-static WCHAR *get_target_dir_property( MSIDATABASE *db )
-{
-    int len;
-    WCHAR *path, *target_dir = msi_dup_property( db, szTargetDir );
-
-    if (!target_dir) return NULL;
-
-    len = strlenW( target_dir );
-    if (target_dir[len - 1] == '\\') return target_dir;
-    if ((path = msi_alloc( (len + 2) * sizeof(WCHAR) )))
+    while (q - ret > 0 && q[-1] == ' ') q--;
+    if (q - ret > 0 && q[-1] != '\\')
     {
-        strcpyW( path, target_dir );
-        path[len] = '\\';
-        path[len + 1] = 0;
+        q[0] = '\\';
+        q[1] = 0;
     }
-    msi_free( target_dir );
-    return path;
+    return ret;
 }
 
 void msi_resolve_target_folder( MSIPACKAGE *package, const WCHAR *name, BOOL load_prop )
 {
     FolderList *fl;
     MSIFOLDER *folder, *parent, *child;
-    WCHAR *path;
+    WCHAR *path, *normalized_path;
 
     TRACE("resolving %s\n", debugstr_w(name));
 
@@ -2278,7 +2270,7 @@ void msi_resolve_target_folder( MSIPACKAGE *package, const WCHAR *name, BOOL loa
 
     if (!strcmpW( folder->Directory, szTargetDir )) /* special resolving for target root dir */
     {
-        if (!load_prop || !(path = get_target_dir_property( package->db )))
+        if (!load_prop || !(path = msi_dup_property( package->db, szTargetDir )))
         {
             path = msi_dup_property( package->db, szRootDrive );
         }
@@ -2293,16 +2285,17 @@ void msi_resolve_target_folder( MSIPACKAGE *package, const WCHAR *name, BOOL loa
         else
             path = msi_build_directory_name( 2, folder->TargetDefault, NULL );
     }
-    msi_clean_path( path );
-    if (folder->ResolvedTarget && !strcmpiW( path, folder->ResolvedTarget ))
+    normalized_path = msi_normalize_path( path );
+    msi_free( path );
+    if (folder->ResolvedTarget && !strcmpiW( normalized_path, folder->ResolvedTarget ))
     {
         TRACE("%s already resolved to %s\n", debugstr_w(name), debugstr_w(folder->ResolvedTarget));
-        msi_free( path );
+        msi_free( normalized_path );
         return;
     }
-    msi_set_property( package->db, folder->Directory, path );
+    msi_set_property( package->db, folder->Directory, normalized_path );
     msi_free( folder->ResolvedTarget );
-    folder->ResolvedTarget = path;
+    folder->ResolvedTarget = normalized_path;
 
     LIST_FOR_EACH_ENTRY( fl, &folder->children, FolderList, entry )
     {
diff --git a/dlls/msi/install.c b/dlls/msi/install.c
index 2428ef5..83b8b7d 100644
--- a/dlls/msi/install.c
+++ b/dlls/msi/install.c
@@ -553,8 +553,7 @@ static void set_target_path( MSIPACKAGE *package, MSIFOLDER *folder, const WCHAR
     MSIFOLDER *child;
     WCHAR *target_path;
 
-    if (!(target_path = strdupW( path ))) return;
-    msi_clean_path( target_path );
+    if (!(target_path = msi_normalize_path( path ))) return;
     if (strcmpW( target_path, folder->ResolvedTarget ))
     {
         msi_free( folder->ResolvedTarget );
@@ -572,7 +571,7 @@ static void set_target_path( MSIPACKAGE *package, MSIFOLDER *folder, const WCHAR
 
 UINT MSI_SetTargetPathW( MSIPACKAGE *package, LPCWSTR szFolder, LPCWSTR szFolderPath )
 {
-    DWORD attrib, len;
+    DWORD attrib;
     MSIFOLDER *folder;
     MSIFILE *file;
 
@@ -587,17 +586,7 @@ UINT MSI_SetTargetPathW( MSIPACKAGE *package, LPCWSTR szFolder, LPCWSTR szFolder
     }
     if (!(folder = msi_get_loaded_folder( package, szFolder ))) return ERROR_DIRECTORY;
 
-    len = strlenW( szFolderPath );
-    if (len && szFolderPath[len - 1] != '\\')
-    {
-        WCHAR *path = msi_alloc( (len + 2) * sizeof(WCHAR) );
-        memcpy( path, szFolderPath, len * sizeof(WCHAR) );
-        path[len] = '\\';
-        path[len + 1] = 0;
-        set_target_path( package, folder, path );
-        msi_free( path );
-    }
-    else set_target_path( package, folder, szFolderPath );
+    set_target_path( package, folder, szFolderPath );
 
     LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
     {
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 589e4a1..2c9385a 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -998,7 +998,7 @@ extern UINT msi_get_property( MSIDATABASE *, LPCWSTR, LPWSTR, LPDWORD ) DECLSPEC
 extern int msi_get_property_int( MSIDATABASE *package, LPCWSTR prop, int def ) DECLSPEC_HIDDEN;
 extern WCHAR *msi_resolve_source_folder(MSIPACKAGE *package, const WCHAR *name, MSIFOLDER **folder) DECLSPEC_HIDDEN;
 extern void msi_resolve_target_folder(MSIPACKAGE *package, const WCHAR *name, BOOL load_prop) DECLSPEC_HIDDEN;
-extern void msi_clean_path( WCHAR *p ) DECLSPEC_HIDDEN;
+extern WCHAR *msi_normalize_path(const WCHAR *) DECLSPEC_HIDDEN;
 extern WCHAR *msi_resolve_file_source(MSIPACKAGE *package, MSIFILE *file) DECLSPEC_HIDDEN;
 extern const WCHAR *msi_get_target_folder(MSIPACKAGE *package, const WCHAR *name) DECLSPEC_HIDDEN;
 extern void msi_reset_folders( MSIPACKAGE *package, BOOL source ) DECLSPEC_HIDDEN;
diff --git a/dlls/msi/tests/package.c b/dlls/msi/tests/package.c
index 34d5eff..9808dfa 100644
--- a/dlls/msi/tests/package.c
+++ b/dlls/msi/tests/package.c
@@ -1134,6 +1134,7 @@ static void test_settargetpath(void)
     r = MsiSetTargetPath( hpkg, "TARGETDIR", tempdir );
     ok( r == ERROR_SUCCESS, "MsiSetTargetPath on subsubdir returned %d\n", r );
 
+    buffer[0] = 0;
     sz = sizeof buffer - 1;
     lstrcat( tempdir, "\\" );
     r = MsiGetTargetPath( hpkg, "TARGETDIR", buffer, &sz );
@@ -1144,6 +1145,7 @@ static void test_settargetpath(void)
     query_file_path( hpkg, "[#RootFile]", buffer );
     ok( !lstrcmp(buffer, file), "Expected %s, got %s\n", file, buffer);
 
+    buffer[0] = 0;
     sz = sizeof(buffer);
     r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
@@ -1153,16 +1155,19 @@ static void test_settargetpath(void)
     r = MsiSetTargetPath( hpkg, "TestParent", "C:\\one\\two" );
     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
 
+    buffer[0] = 0;
     sz = sizeof(buffer);
     r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
     ok( lstrcmpi(buffer, "C:\\one\\two\\TestDir\\"),
         "Expected \"C:\\one\\two\\TestDir\\\", got \"%s\"\n", buffer );
 
+    buffer[0] = 0;
     query_file_path( hpkg, "[#TestFile]", buffer );
     ok( !lstrcmpi(buffer, "C:\\one\\two\\TestDir\\testfile.txt"),
         "Expected C:\\one\\two\\TestDir\\testfile.txt, got %s\n", buffer );
 
+    buffer[0] = 0;
     sz = sizeof buffer - 1;
     r = MsiGetTargetPath( hpkg, "TestParent", buffer, &sz );
     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
@@ -1171,6 +1176,7 @@ static void test_settargetpath(void)
     r = MsiSetTargetPath( hpkg, "TestParent", "C:\\one\\two\\three" );
     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
 
+    buffer[0] = 0;
     sz = sizeof buffer - 1;
     r = MsiGetTargetPath( hpkg, "TestParent", buffer, &sz );
     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
@@ -1179,11 +1185,21 @@ static void test_settargetpath(void)
     r = MsiSetTargetPath( hpkg, "TestParent", "C:\\\\one\\\\two  " );
     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
 
+    buffer[0] = 0;
     sz = sizeof buffer - 1;
     r = MsiGetTargetPath( hpkg, "TestParent", buffer, &sz );
     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
     ok( !lstrcmpi(buffer, "C:\\one\\two\\"), "Expected \"C:\\one\\two\\\", got %s\n", buffer);
 
+    r = MsiSetTargetPath( hpkg, "TestParent", "C:\\\\ Program Files \\\\ " );
+    ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
+
+    buffer[0] = 0;
+    sz = sizeof buffer - 1;
+    r = MsiGetTargetPath( hpkg, "TestParent", buffer, &sz );
+    ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
+    ok( !lstrcmpi(buffer, "C:\\Program Files\\"), "Expected \"C:\\Program Files\\\", got %s\n", buffer);
+
     MsiCloseHandle( hpkg );
 }
 




More information about the wine-cvs mailing list