Module: wine Branch: master Commit: e98a52e58509529a364c9b12fb9a9b3b6265b1ca URL: http://source.winehq.org/git/wine.git/?a=commit;h=e98a52e58509529a364c9b12fb...
Author: Alexandre Julliard julliard@winehq.org Date: Wed Sep 9 12:19:28 2009 +0200
msi: Force overwriting of read-only files when extracting a cabinet, with tests.
---
dlls/msi/media.c | 16 +++++++-- dlls/msi/tests/install.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 4 deletions(-)
diff --git a/dlls/msi/media.c b/dlls/msi/media.c index 2de3252..7c9dc15 100644 --- a/dlls/msi/media.c +++ b/dlls/msi/media.c @@ -333,11 +333,19 @@ static INT_PTR cabinet_copy_file(FDINOTIFICATIONTYPE fdint, NULL, CREATE_ALWAYS, attrs, NULL); if (handle == INVALID_HANDLE_VALUE) { - if (GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES) - ERR("failed to create %s (error %d)\n", - debugstr_w(path), GetLastError()); + DWORD err = GetLastError(); + DWORD attrs = GetFileAttributesW(path);
- goto done; + if (attrs == INVALID_FILE_ATTRIBUTES) + ERR("failed to create %s (error %d)\n", debugstr_w(path), err); + else if (err == ERROR_ACCESS_DENIED && (attrs & FILE_ATTRIBUTE_READONLY)) + { + TRACE("removing read-only attribute on %s\n", debugstr_w(path)); + SetFileAttributesW( path, attrs & ~FILE_ATTRIBUTE_READONLY ); + handle = CreateFileW(path, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, attrs, NULL); + } + else + WARN("failed to create %s (error %d)\n", debugstr_w(path), err); }
done: diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c index 0a54ea6..beb0630 100644 --- a/dlls/msi/tests/install.c +++ b/dlls/msi/tests/install.c @@ -381,6 +381,16 @@ static const CHAR rof_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\t "Media\tDiskId\n" "1\t1\t\t\tDISK1\t\n";
+static const CHAR rofc_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n" + "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n" + "File\tFile\n" + "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1"; + +static const CHAR rofc_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n" + "i2\ti4\tL64\tS255\tS32\tS72\n" + "Media\tDiskId\n" + "1\t1\t\ttest1.cab\tDISK1\t\n"; + static const CHAR sdp_install_exec_seq_dat[] = "Action\tCondition\tSequence\n" "s72\tS255\tI2\n" "InstallExecuteSequence\tAction\n" @@ -1078,6 +1088,18 @@ static const msi_table rof_tables[] = ADD_TABLE(property), };
+static const msi_table rofc_tables[] = +{ + ADD_TABLE(rof_component), + ADD_TABLE(directory), + ADD_TABLE(rof_feature), + ADD_TABLE(rof_feature_comp), + ADD_TABLE(rofc_file), + ADD_TABLE(install_exec_seq), + ADD_TABLE(rofc_media), + ADD_TABLE(property), +}; + static const msi_table sdp_tables[] = { ADD_TABLE(rof_component), @@ -2578,6 +2600,55 @@ static void test_readonlyfile(void) DeleteFile(msifile); }
+static void test_readonlyfile_cab(void) +{ + UINT r; + DWORD size; + HANDLE file; + CHAR path[MAX_PATH]; + CHAR buf[16]; + + CreateDirectoryA("msitest", NULL); + create_file("maximus", 500); + create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0"); + DeleteFile("maximus"); + + create_database(msifile, rofc_tables, sizeof(rofc_tables) / sizeof(msi_table)); + + MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL); + + lstrcpy(path, PROG_FILES_DIR); + lstrcat(path, "\msitest"); + CreateDirectory(path, NULL); + + lstrcat(path, "\maximus"); + file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, CREATE_NEW, FILE_ATTRIBUTE_READONLY, NULL); + + WriteFile(file, "readonlyfile", strlen("readonlyfile"), &size, NULL); + CloseHandle(file); + + r = MsiInstallProductA(msifile, NULL); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + memset( buf, 0, sizeof(buf) ); + if ((file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) + { + ReadFile(file, buf, sizeof(buf) - 1, &size, NULL); + CloseHandle(file); + } + ok( !lstrcmp( buf, "maximus" ), "Expected file to be overwritten, got '%s'\n", buf ); + ok(delete_pf("msitest\maximus", TRUE), "File not installed\n"); + ok(delete_pf("msitest", FALSE), "File not installed\n"); + + /* Delete the files in the temp (current) folder */ + delete_cab_files(); + DeleteFile("msitest\maximus"); + RemoveDirectory("msitest"); + DeleteFile(msifile); +} + static void test_setdirproperty(void) { UINT r; @@ -6160,6 +6231,7 @@ START_TEST(install) test_samesequence(); test_uiLevelFlags(); test_readonlyfile(); + test_readonlyfile_cab(); test_setdirproperty(); test_cabisextracted(); test_concurrentinstall();