diff --git a/dlls/msi/action.c b/dlls/msi/action.c index 5444dfc05a..baebdc2145 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 2428ef5098..83b8b7d173 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 589e4a12d9..2c9385a2a5 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 34d5eff373..9808dfa712 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 ); }