From 4bef6f59138941e0766c3a4b3d24d70d4a60e432 Mon Sep 17 00:00:00 2001 From: Giannis Adamopoulos Date: Thu, 3 Jan 2019 14:26:57 +0200 Subject: [PATCH] [WINSRV] consrv: Implement terminating console processes on shutdown Also stub handling non-console, non-gui processes. --- win32ss/user/winsrv/consrv/console.c | 2 +- win32ss/user/winsrv/consrv/console.h | 5 ++ win32ss/user/winsrv/consrv/shutdown.c | 73 +++++++++++++++++++++++---- 3 files changed, 70 insertions(+), 10 deletions(-) diff --git a/win32ss/user/winsrv/consrv/console.c b/win32ss/user/winsrv/consrv/console.c index a6e687b3a3a..e28c8a2a52d 100644 --- a/win32ss/user/winsrv/consrv/console.c +++ b/win32ss/user/winsrv/consrv/console.c @@ -805,7 +805,7 @@ ConSrvDeleteConsole(PCONSRV_CONSOLE Console) -static NTSTATUS +NTSTATUS ConSrvConsoleCtrlEventTimeout(IN ULONG CtrlEvent, IN PCONSOLE_PROCESS_DATA ProcessData, IN ULONG Timeout) diff --git a/win32ss/user/winsrv/consrv/console.h b/win32ss/user/winsrv/consrv/console.h index 07741638c2b..cac1eab36d5 100644 --- a/win32ss/user/winsrv/consrv/console.h +++ b/win32ss/user/winsrv/consrv/console.h @@ -47,3 +47,8 @@ ConSrvValidateConsole(OUT struct _CONSRV_CONSOLE** /* PCONSRV_CONSOLE* */ Consol IN HANDLE ConsoleHandle, IN CONSOLE_STATE ExpectedState, IN BOOLEAN LockConsole); + +NTSTATUS +ConSrvConsoleCtrlEventTimeout(IN ULONG CtrlEvent, + IN PCONSOLE_PROCESS_DATA ProcessData, + IN ULONG Timeout); diff --git a/win32ss/user/winsrv/consrv/shutdown.c b/win32ss/user/winsrv/consrv/shutdown.c index bbe25daf7cb..4bfa41d4506 100644 --- a/win32ss/user/winsrv/consrv/shutdown.c +++ b/win32ss/user/winsrv/consrv/shutdown.c @@ -9,12 +9,64 @@ /* INCLUDES *******************************************************************/ #include "consrv.h" +#include #define NDEBUG #include /* FUNCTIONS ******************************************************************/ +static void +NotifyConsoleProcessForShutdown(IN PCSR_PROCESS CsrProcess, + IN PCONSOLE_PROCESS_DATA ProcessData, + IN ULONG Flags) +{ + DPRINT1("ConsoleClientShutdown(0x%p, 0x%x) - Console process [0x%x, 0x%x]\n", + CsrProcess, Flags, CsrProcess->ClientId.UniqueProcess, CsrProcess->ClientId.UniqueThread); + + /* Send a log-off event. In reality this should be way more complex */ + ConSrvConsoleCtrlEventTimeout(CTRL_LOGOFF_EVENT, ProcessData, + ShutdownSettings.WaitToKillAppTimeout); +} + +static BOOL +NotifyGenericProcessForShutdown(IN PCSR_PROCESS CsrProcess, + IN ULONG Flags) +{ + /* FIXME: Implement the generic process shutdown handler */ + UNIMPLEMENTED_ONCE; + + return TRUE; +} + +ULONG +NTAPI +NonConsoleProcessShutdown(IN PCSR_PROCESS Process, + IN ULONG Flags) +{ + if (NotifyGenericProcessForShutdown(Process, Flags)) + { + /* Terminate this process */ +#if DBG + WCHAR buffer[MAX_PATH]; + if (!GetProcessImageFileNameW(Process->ProcessHandle, buffer, MAX_PATH)) + { + DPRINT1("Terminating process %x\n", Process->ClientId.UniqueProcess); + } + else + { + DPRINT1("Terminating process %x (%S)\n", Process->ClientId.UniqueProcess, buffer); + } +#endif + + NtTerminateProcess(Process->ProcessHandle, 0); + WaitForSingleObject(Process->ProcessHandle, ShutdownSettings.ProcessTerminateTimeout); + } + + CsrDereferenceProcess(Process); + return CsrShutdownCsrProcess; +} + // NOTE: See http://blogs.msdn.com/b/ntdebugging/archive/2007/06/09/how-windows-shuts-down.aspx ULONG NTAPI @@ -24,14 +76,19 @@ ConsoleClientShutdown(IN PCSR_PROCESS CsrProcess, { PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess); - //FIXME: UNIMPLEMENTED! + /* Do not kill system processes when a user is logging off */ + if ((Flags & EWX_SHUTDOWN) == EWX_LOGOFF && + (CsrProcess->ShutdownFlags & (CsrShutdownSystem | CsrShutdownOther))) + { + DPRINT("Do not kill a system process in a logoff request!\n"); + return CsrShutdownNonCsrProcess; + } + /* Is it a console process? */ if ( ProcessData->ConsoleHandle != NULL || ProcessData->HandleTable != NULL ) { - DPRINT("ConsoleClientShutdown(0x%p, 0x%x, %s) - Console process [0x%x, 0x%x]\n", - CsrProcess, Flags, FirstPhase ? "FirstPhase" : "LastPhase", - CsrProcess->ClientId.UniqueProcess, CsrProcess->ClientId.UniqueThread); + NotifyConsoleProcessForShutdown(CsrProcess, ProcessData, Flags); /* We are done with the process itself */ CsrDereferenceProcess(CsrProcess); @@ -43,13 +100,11 @@ ConsoleClientShutdown(IN PCSR_PROCESS CsrProcess, CsrProcess, Flags, FirstPhase ? "FirstPhase" : "LastPhase", CsrProcess->ClientId.UniqueProcess, CsrProcess->ClientId.UniqueThread); - /* On first pass, ignore the process since the GUI server should take it... */ + /* On first pass, let the gui server terminate all the processes that it owns */ if (FirstPhase) return CsrShutdownNonCsrProcess; - /* ... otherwise, call the generic handler */ - // FIXME: Should call a generic shutdown handler!! - CsrDereferenceProcess(CsrProcess); - return CsrShutdownCsrProcess; + /* Use the generic handler since this isn't a gui process */ + return NonConsoleProcessShutdown(CsrProcess, Flags); } return CsrShutdownNonCsrProcess;