Hans Leidekker : msi: Properly handle service control events in Start/ StopService.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Dec 2 13:40:21 CST 2014


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

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Tue Dec  2 12:41:26 2014 +0100

msi: Properly handle service control events in Start/StopService.

---

 dlls/msi/action.c       | 33 +++++++++++++++------------------
 dlls/msi/tests/action.c | 36 ++++++++++++++++++++++++++++++------
 2 files changed, 45 insertions(+), 24 deletions(-)

diff --git a/dlls/msi/action.c b/dlls/msi/action.c
index 939e426..1e527da 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -5952,24 +5952,21 @@ static UINT ITERATE_StartService(MSIRECORD *rec, LPVOID param)
     if (!comp)
         return ERROR_SUCCESS;
 
+    event = MSI_RecordGetInteger( rec, 3 );
+    deformat_string( package, MSI_RecordGetString( rec, 2 ), &name );
+
     comp->Action = msi_get_component_action( package, comp );
-    if (comp->Action != INSTALLSTATE_LOCAL)
+    if (!(comp->Action == INSTALLSTATE_LOCAL && (event & msidbServiceControlEventStart)) &&
+        !(comp->Action == INSTALLSTATE_ABSENT && (event & msidbServiceControlEventUninstallStart)))
     {
-        TRACE("component not scheduled for installation %s\n", debugstr_w(component));
+        TRACE("not starting %s\n", debugstr_w(name));
+        msi_free( name );
         return ERROR_SUCCESS;
     }
 
-    deformat_string(package, MSI_RecordGetString(rec, 2), &name);
     deformat_string(package, MSI_RecordGetString(rec, 4), &args);
-    event = MSI_RecordGetInteger(rec, 3);
     wait = MSI_RecordGetInteger(rec, 5);
 
-    if (!(event & msidbServiceControlEventStart))
-    {
-        r = ERROR_SUCCESS;
-        goto done;
-    }
-
     scm = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
     if (!scm)
     {
@@ -6159,23 +6156,24 @@ static UINT ITERATE_StopService( MSIRECORD *rec, LPVOID param )
     MSICOMPONENT *comp;
     MSIRECORD *uirow;
     LPCWSTR component;
-    LPWSTR name = NULL, display_name = NULL;
+    WCHAR *name, *display_name = NULL;
     DWORD event, len;
     SC_HANDLE scm;
 
-    event = MSI_RecordGetInteger( rec, 3 );
-    if (!(event & msidbServiceControlEventStop))
-        return ERROR_SUCCESS;
-
     component = MSI_RecordGetString( rec, 6 );
     comp = msi_get_loaded_component( package, component );
     if (!comp)
         return ERROR_SUCCESS;
 
+    event = MSI_RecordGetInteger( rec, 3 );
+    deformat_string( package, MSI_RecordGetString( rec, 2 ), &name );
+
     comp->Action = msi_get_component_action( package, comp );
-    if (comp->Action != INSTALLSTATE_ABSENT)
+    if (!(comp->Action == INSTALLSTATE_LOCAL && (event & msidbServiceControlEventStop)) &&
+        !(comp->Action == INSTALLSTATE_ABSENT && (event & msidbServiceControlEventUninstallStop)))
     {
-        TRACE("component not scheduled for removal %s\n", debugstr_w(component));
+        TRACE("not stopping %s\n", debugstr_w(name));
+        msi_free( name );
         return ERROR_SUCCESS;
     }
 
@@ -6195,7 +6193,6 @@ static UINT ITERATE_StopService( MSIRECORD *rec, LPVOID param )
     }
     CloseServiceHandle( scm );
 
-    deformat_string( package, MSI_RecordGetString( rec, 2 ), &name );
     stop_service( name );
 
 done:
diff --git a/dlls/msi/tests/action.c b/dlls/msi/tests/action.c
index bd074a2..60562f1 100644
--- a/dlls/msi/tests/action.c
+++ b/dlls/msi/tests/action.c
@@ -247,7 +247,10 @@ static const char sss_service_control_dat[] =
     "ServiceControl\tName\tEvent\tArguments\tWait\tComponent_\n"
     "s72\tl255\ti2\tL255\tI2\ts72\n"
     "ServiceControl\tServiceControl\n"
-    "ServiceControl\tSpooler\t1\t\t0\tservice_comp";
+    "ServiceControl\tSpooler\t1\t\t1\tservice_comp\n"
+    "ServiceControl2\tSpooler\t2\t\t1\tservice_comp\n"
+    "ServiceControl3\tSpooler\t16\t\t1\tservice_comp\n"
+    "ServiceControl4\tSpooler\t32\t\t1\tservice_comp\n";
 
 static const char sss_install_exec_seq_dat[] =
     "Action\tCondition\tSequence\n"
@@ -260,11 +263,15 @@ static const char sss_install_exec_seq_dat[] =
     "CostFinalize\t\t1000\n"
     "InstallValidate\t\t1400\n"
     "InstallInitialize\t\t1500\n"
+    "StopServices\t\t4000\n"
     "DeleteServices\t\t5000\n"
     "MoveFiles\t\t5100\n"
     "InstallFiles\t\t5200\n"
     "DuplicateFiles\t\t5300\n"
     "StartServices\t\t5400\n"
+    "RegisterProduct\t\t5500\n"
+    "PublishFeatures\t\t5600\n"
+    "PublishProduct\t\t5700\n"
     "InstallFinalize\t\t6000\n";
 
 static const char sds_install_exec_seq_dat[] =
@@ -5310,7 +5317,7 @@ error:
     DeleteFileA(msifile);
 }
 
-static void test_start_services(void)
+static void test_start_stop_services(void)
 {
     UINT r;
     SC_HANDLE scm, service;
@@ -5359,6 +5366,23 @@ static void test_start_services(void)
     r = MsiInstallProductA(msifile, NULL);
     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
 
+    if (error == ERROR_SUCCESS)
+    {
+        SERVICE_STATUS status;
+
+        scm = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+        service = OpenServiceA(scm, "Spooler", SC_MANAGER_ALL_ACCESS);
+
+        ret = ControlService(service, SERVICE_CONTROL_STOP, &status);
+        ok(ret, "ControlService failed %u\n", GetLastError());
+
+        CloseServiceHandle(service);
+        CloseServiceHandle(scm);
+    }
+
+    r = MsiInstallProductA(msifile, "REMOVE=ALL");
+    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");
@@ -5373,9 +5397,6 @@ static void test_start_services(void)
     ok(delete_pf("msitest\\service2.exe", TRUE), "File not installed\n");
     ok(delete_pf("msitest", FALSE), "Directory not created\n");
 
-    delete_test_files();
-    DeleteFileA(msifile);
-
     if (error == ERROR_SUCCESS)
     {
         SERVICE_STATUS status;
@@ -5389,6 +5410,9 @@ static void test_start_services(void)
         CloseServiceHandle(service);
         CloseServiceHandle(scm);
     }
+
+    delete_test_files();
+    DeleteFileA(msifile);
 }
 
 static void test_delete_services(void)
@@ -6869,7 +6893,7 @@ START_TEST(action)
     test_write_registry_values();
     test_envvar();
     test_create_remove_folder();
-    test_start_services();
+    test_start_stop_services();
     test_delete_services();
     test_install_services();
     test_self_registration();




More information about the wine-cvs mailing list