[2/2] msi: Implement the SelfUnregModules standard action.

Hans Leidekker hans at codeweavers.com
Fri Feb 5 07:48:20 CST 2010


---
 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 39db2ca..d94d842 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 e3f61a0..a3f1897 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);
 
-- 
1.6.3.3




More information about the wine-patches mailing list