Piotr Caban : advapi32: Send shutdown notification to services.

Alexandre Julliard julliard at winehq.org
Wed Nov 30 14:19:21 CST 2011


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

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Wed Nov 30 15:29:15 2011 +0100

advapi32: Send shutdown notification to services.

---

 dlls/advapi32/service.c |   41 ++++++++++++++++++++++++++++++++++++++---
 1 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c
index 7c45f94..bdebc91 100644
--- a/dlls/advapi32/service.c
+++ b/dlls/advapi32/service.c
@@ -61,6 +61,7 @@ typedef struct service_data_t
     LPVOID context;
     HANDLE thread;
     SC_HANDLE handle;
+    SC_HANDLE full_access_handle;
     BOOL unicode : 1;
     union {
         LPSERVICE_MAIN_FUNCTIONA a;
@@ -425,7 +426,8 @@ static DWORD WINAPI service_control_dispatcher(LPVOID arg)
         case WINESERV_STARTINFO:
             if (!service->handle)
             {
-                if (!(service->handle = OpenServiceW( manager, data, SERVICE_SET_STATUS )))
+                if (!(service->handle = OpenServiceW( manager, data, SERVICE_SET_STATUS )) ||
+                    !(service->full_access_handle = OpenServiceW( manager, data, GENERIC_READ|GENERIC_WRITE )))
                     FIXME( "failed to open service %s\n", debugstr_w(data) );
             }
             result = service_handle_start(service, data + info.name_size,
@@ -484,8 +486,41 @@ static BOOL service_run_main_thread(void)
         ret = WaitForMultipleObjects( n, wait_handles, FALSE, INFINITE );
         if (!ret)  /* system process event */
         {
-            TRACE( "last user process exited, shutting down\n" );
-            /* FIXME: we should maybe send a shutdown control to running services */
+            SERVICE_STATUS st;
+            SERVICE_PRESHUTDOWN_INFO spi;
+            DWORD timeout = 5000;
+            BOOL res;
+
+            EnterCriticalSection( &service_cs );
+            n = 0;
+            for (i = 0; i < nb_services && n < MAXIMUM_WAIT_OBJECTS; i++)
+            {
+                if (!services[i]->thread) continue;
+
+                res = QueryServiceStatus(services[i]->full_access_handle, &st);
+                ret = ERROR_SUCCESS;
+                if (res && (st.dwControlsAccepted & SERVICE_ACCEPT_PRESHUTDOWN))
+                {
+                    res = QueryServiceConfig2W( services[i]->full_access_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
+                            (LPBYTE)&spi, sizeof(spi), &i );
+                    if (res)
+                    {
+                        FIXME("service should be able to delay shutdown\n");
+                        timeout += spi.dwPreshutdownTimeout;
+                        ret = service_handle_control( services[i], SERVICE_CONTROL_PRESHUTDOWN );
+                        wait_handles[n++] = services[i]->thread;
+                    }
+                }
+                else if (res && (st.dwControlsAccepted & SERVICE_ACCEPT_SHUTDOWN))
+                {
+                    ret = service_handle_control( services[i], SERVICE_CONTROL_SHUTDOWN );
+                    wait_handles[n++] = services[i]->thread;
+                }
+            }
+            LeaveCriticalSection( &service_cs );
+
+            TRACE("last user process exited, shutting down (timeout: %d)\n", timeout);
+            WaitForMultipleObjects( n, wait_handles, TRUE, timeout );
             ExitProcess(0);
         }
         else if (ret == 1)




More information about the wine-cvs mailing list