From f5af1ca39957353b191c9f86ead1994c2789d4fb Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Fri, 5 Feb 2010 14:48:20 +0100 Subject: [PATCH] msi: Implement the SelfUnregModules standard action. --- dlls/msi/action.c | 89 ++++++++++++++++++++++++++++++++++++++++++++---- dlls/msi/tests/install.c | 66 +++++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+), 6 deletions(-) diff --git a/dlls/msi/action.c b/dlls/msi/action.c index 39db2ca03fd..d94d842cae1 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -3705,6 +3705,89 @@ static UINT ACTION_SelfRegModules(MSIPACKAGE *package) return ERROR_SUCCESS; } +static UINT ITERATE_SelfUnregModules( MSIRECORD *row, LPVOID param ) +{ + static const WCHAR regsvr32[] = + {'r','e','g','s','v','r','3','2','.','e','x','e',' ','/','u',' ','\"',0}; + static const WCHAR close[] = {'\"',0}; + MSIPACKAGE *package = param; + LPCWSTR filename; + LPWSTR cmdline; + MSIFILE *file; + DWORD len; + STARTUPINFOW si; + PROCESS_INFORMATION pi; + BOOL ret; + MSIRECORD *uirow; + LPWSTR uipath, p; + + memset( &si, 0, sizeof(STARTUPINFOW) ); + + filename = MSI_RecordGetString( row, 1 ); + file = get_loaded_file( package, filename ); + + if (!file) + { + ERR("Unable to find file id %s\n", debugstr_w(filename)); + return ERROR_SUCCESS; + } + + len = strlenW( regsvr32 ) + strlenW( file->TargetPath ) + 2; + + cmdline = msi_alloc( len * sizeof(WCHAR) ); + strcpyW( cmdline, regsvr32 ); + strcatW( cmdline, file->TargetPath ); + strcatW( cmdline, close ); + + TRACE("Unregistering %s\n", debugstr_w(cmdline)); + + ret = CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, 0, NULL, c_colon, &si, &pi ); + if (ret) + { + CloseHandle( pi.hThread ); + msi_dialog_check_messages( pi.hProcess ); + CloseHandle( pi.hProcess ); + } + + msi_free( cmdline ); + + uirow = MSI_CreateRecord( 2 ); + uipath = strdupW( file->TargetPath ); + if ((p = strrchrW( uipath, '\\' ))) + { + *p = 0; + MSI_RecordSetStringW( uirow, 1, ++p ); + } + MSI_RecordSetStringW( uirow, 2, uipath ); + ui_actiondata( package, szSelfUnregModules, uirow ); + msiobj_release( &uirow->hdr ); + msi_free( uipath ); + /* FIXME call ui_progress? */ + + return ERROR_SUCCESS; +} + +static UINT ACTION_SelfUnregModules( MSIPACKAGE *package ) +{ + UINT rc; + MSIQUERY *view; + static const WCHAR query[] = + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + '`','S','e','l','f','R','e','g','`',0}; + + rc = MSI_DatabaseOpenViewW( package->db, query, &view ); + if (rc != ERROR_SUCCESS) + { + TRACE("no SelfReg table\n"); + return ERROR_SUCCESS; + } + + MSI_IterateRecords( view, NULL, ITERATE_SelfUnregModules, package ); + msiobj_release( &view->hdr ); + + return ERROR_SUCCESS; +} + static UINT ACTION_PublishFeatures(MSIPACKAGE *package) { MSIFEATURE *feature; @@ -6111,12 +6194,6 @@ static UINT ACTION_MigrateFeatureStates( MSIPACKAGE *package ) return msi_unimplemented_action_stub( package, "MigrateFeatureStates", table ); } -static UINT ACTION_SelfUnregModules( MSIPACKAGE *package ) -{ - static const WCHAR table[] = { 'S','e','l','f','R','e','g',0 }; - return msi_unimplemented_action_stub( package, "SelfUnregModules", table ); -} - static UINT ACTION_ValidateProductID( MSIPACKAGE *package ) { static const WCHAR table[] = { diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c index e3f61a03851..a3f1897352e 100644 --- a/dlls/msi/tests/install.c +++ b/dlls/msi/tests/install.c @@ -1145,6 +1145,30 @@ static const CHAR rf_install_exec_seq_dat[] = "Action\tCondition\tSequence\n" "InstallValidate\t\t1400\n" "LaunchConditions\t\t100\n"; + +static const CHAR sr_selfreg_dat[] = "File_\tCost\n" + "s72\tI2\n" + "SelfReg\tFile_\n" + "one.txt\t1\n"; + +static const CHAR sr_install_exec_seq_dat[] = "Action\tCondition\tSequence\n" + "s72\tS255\tI2\n" + "InstallExecuteSequence\tAction\n" + "CostFinalize\t\t1000\n" + "CostInitialize\t\t800\n" + "FileCost\t\t900\n" + "ResolveSource\t\t950\n" + "MoveFiles\t\t1700\n" + "SelfUnregModules\t\t3900\n" + "InstallFiles\t\t4000\n" + "DuplicateFiles\t\t4500\n" + "WriteEnvironmentStrings\t\t4550\n" + "CreateShortcuts\t\t4600\n" + "InstallFinalize\t\t6600\n" + "InstallInitialize\t\t1500\n" + "InstallValidate\t\t1400\n" + "LaunchConditions\t\t100\n"; + typedef struct _msi_table { const CHAR *filename; @@ -1902,6 +1926,19 @@ static const msi_table sds_tables[] = ADD_TABLE(property) }; +static const msi_table sr_tables[] = +{ + ADD_TABLE(component), + ADD_TABLE(directory), + ADD_TABLE(feature), + ADD_TABLE(feature_comp), + ADD_TABLE(file), + ADD_TABLE(sr_selfreg), + ADD_TABLE(sr_install_exec_seq), + ADD_TABLE(media), + ADD_TABLE(property) +}; + /* cabinet definitions */ /* make the max size large so there is only one cab file */ @@ -7635,6 +7672,34 @@ static void test_delete_services(void) delete_test_files(); } +static void test_self_registration(void) +{ + UINT r; + + create_test_files(); + create_database(msifile, sr_tables, sizeof(sr_tables) / sizeof(msi_table)); + + MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL); + + r = MsiInstallProductA(msifile, NULL); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n"); + ok(delete_pf("msitest\\cabout\\new", FALSE), "Directory not created\n"); + ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n"); + ok(delete_pf("msitest\\cabout", FALSE), "Directory not created\n"); + ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n"); + ok(delete_pf("msitest\\changed", FALSE), "Directory not created\n"); + ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n"); + ok(delete_pf("msitest\\first", FALSE), "Directory not created\n"); + ok(delete_pf("msitest\\filename", TRUE), "File not installed\n"); + ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n"); + ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n"); + ok(delete_pf("msitest", FALSE), "Directory not created\n"); + + delete_test_files(); +} + START_TEST(install) { DWORD len; @@ -7730,6 +7795,7 @@ START_TEST(install) test_remove_folder(); test_start_services(); test_delete_services(); + test_self_registration(); DeleteFileA(log_file); -- 2.11.4.GIT