1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Console Server DLL 4 * FILE: win32ss/user/winsrv/consrv/shutdown.c 5 * PURPOSE: Processes Shutdown 6 * PROGRAMMERS: Alex Ionescu 7 */ 8 9 /* INCLUDES *******************************************************************/ 10 11 #include "consrv.h" 12 #include <psapi.h> 13 14 #define NDEBUG 15 #include <debug.h> 16 17 /* FUNCTIONS ******************************************************************/ 18 19 static void 20 NotifyConsoleProcessForShutdown(IN PCSR_PROCESS CsrProcess, 21 IN PCONSOLE_PROCESS_DATA ProcessData, 22 IN ULONG Flags) 23 { 24 DPRINT1("ConsoleClientShutdown(0x%p, 0x%x) - Console process [0x%x, 0x%x]\n", 25 CsrProcess, Flags, CsrProcess->ClientId.UniqueProcess, CsrProcess->ClientId.UniqueThread); 26 27 /* Send a log-off event. In reality this should be way more complex */ 28 ConSrvConsoleCtrlEventTimeout(CTRL_LOGOFF_EVENT, ProcessData, 29 ShutdownSettings.WaitToKillAppTimeout); 30 } 31 32 static BOOL 33 NotifyGenericProcessForShutdown(IN PCSR_PROCESS CsrProcess, 34 IN ULONG Flags) 35 { 36 /* FIXME: Implement the generic process shutdown handler */ 37 UNIMPLEMENTED_ONCE; 38 39 return TRUE; 40 } 41 42 ULONG 43 NTAPI 44 NonConsoleProcessShutdown(IN PCSR_PROCESS Process, 45 IN ULONG Flags) 46 { 47 if (NotifyGenericProcessForShutdown(Process, Flags)) 48 { 49 /* Terminate this process */ 50 #if DBG 51 WCHAR buffer[MAX_PATH]; 52 if (!GetProcessImageFileNameW(Process->ProcessHandle, buffer, MAX_PATH)) 53 { 54 DPRINT1("Terminating process %x\n", Process->ClientId.UniqueProcess); 55 } 56 else 57 { 58 DPRINT1("Terminating process %x (%S)\n", Process->ClientId.UniqueProcess, buffer); 59 } 60 #endif 61 62 NtTerminateProcess(Process->ProcessHandle, 0); 63 WaitForSingleObject(Process->ProcessHandle, ShutdownSettings.ProcessTerminateTimeout); 64 } 65 66 CsrDereferenceProcess(Process); 67 return CsrShutdownCsrProcess; 68 } 69 70 // NOTE: See http://blogs.msdn.com/b/ntdebugging/archive/2007/06/09/how-windows-shuts-down.aspx 71 ULONG 72 NTAPI 73 ConsoleClientShutdown(IN PCSR_PROCESS CsrProcess, 74 IN ULONG Flags, 75 IN BOOLEAN FirstPhase) 76 { 77 PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess); 78 79 /* Do not kill system processes when a user is logging off */ 80 if ((Flags & EWX_SHUTDOWN) == EWX_LOGOFF && 81 (CsrProcess->ShutdownFlags & (CsrShutdownSystem | CsrShutdownOther))) 82 { 83 DPRINT("Do not kill a system process in a logoff request!\n"); 84 return CsrShutdownNonCsrProcess; 85 } 86 87 /* Is it a console process? */ 88 if ( ProcessData->ConsoleHandle != NULL || 89 ProcessData->HandleTable != NULL ) 90 { 91 NotifyConsoleProcessForShutdown(CsrProcess, ProcessData, Flags); 92 93 /* We are done with the process itself */ 94 CsrDereferenceProcess(CsrProcess); 95 return CsrShutdownCsrProcess; 96 } 97 else 98 { 99 DPRINT("ConsoleClientShutdown(0x%p, 0x%x, %s) - Non-console process [0x%x, 0x%x]\n", 100 CsrProcess, Flags, FirstPhase ? "FirstPhase" : "LastPhase", 101 CsrProcess->ClientId.UniqueProcess, CsrProcess->ClientId.UniqueThread); 102 103 /* On first pass, let the gui server terminate all the processes that it owns */ 104 if (FirstPhase) return CsrShutdownNonCsrProcess; 105 106 /* Use the generic handler since this isn't a gui process */ 107 return NonConsoleProcessShutdown(CsrProcess, Flags); 108 } 109 110 return CsrShutdownNonCsrProcess; 111 } 112 113 /* EOF */ 114