Author: sir_richard Date: Tue Mar 9 21:13:19 2010 New Revision: 46041
URL: http://svn.reactos.org/svn/reactos?rev=46041&view=rev Log: [KERNEL32]: Bug fix CTRL-C handler registration/deregistration/notification, needed for correct console shutdown behavior.
Modified: trunk/reactos/dll/win32/kernel32/misc/console.c trunk/reactos/dll/win32/kernel32/misc/dllmain.c
Modified: trunk/reactos/dll/win32/kernel32/misc/console.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/misc/con... ============================================================================== --- trunk/reactos/dll/win32/kernel32/misc/console.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/kernel32/misc/console.c [iso-8859-1] Tue Mar 9 21:13:19 2010 @@ -19,16 +19,17 @@ #define NDEBUG #include <debug.h>
-extern BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event); -extern __declspec(noreturn) VOID CALLBACK ConsoleControlDispatcher(DWORD CodeAndFlag); extern RTL_CRITICAL_SECTION ConsoleLock; extern BOOL ConsoleInitialized; extern BOOL WINAPI IsDebuggerPresent(VOID);
/* GLOBALS *******************************************************************/
-static PHANDLER_ROUTINE* CtrlHandlers = NULL; -static ULONG NrCtrlHandlers = 0; +PHANDLER_ROUTINE InitialHandler[1]; +PHANDLER_ROUTINE* CtrlHandlers; +ULONG NrCtrlHandlers; +ULONG NrAllocatedHandlers; + #define INPUTEXENAME_BUFLEN 256 static WCHAR InputExeName[INPUTEXENAME_BUFLEN] = L"";
@@ -49,7 +50,7 @@ break;
case CTRL_SHUTDOWN_EVENT: - DPRINT("Ctrl Shutdown Event\n"); + DPRINT1("Ctrl Shutdown Event\n"); break;
case CTRL_CLOSE_EVENT: @@ -57,14 +58,13 @@ break;
case CTRL_LOGOFF_EVENT: - DPRINT("Ctrl Logoff Event\n"); + DPRINT1("Ctrl Logoff Event\n"); break; }
- ExitProcess(0); + ExitProcess(CONTROL_C_EXIT); return TRUE; } -
__declspec(noreturn) VOID @@ -74,7 +74,8 @@ DWORD nExitCode = 0; DWORD nCode = CodeAndFlag & MAXLONG; UINT i; - + EXCEPTION_RECORD erException; + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
switch(nCode) @@ -82,51 +83,77 @@ case CTRL_C_EVENT: case CTRL_BREAK_EVENT: { - if(IsDebuggerPresent()) + if (IsDebuggerPresent()) { - EXCEPTION_RECORD erException; - erException.ExceptionCode = - (nCode == CTRL_C_EVENT ? DBG_CONTROL_C : DBG_CONTROL_BREAK); + erException.ExceptionCode = (nCode == CTRL_C_EVENT ? + DBG_CONTROL_C : DBG_CONTROL_BREAK); erException.ExceptionFlags = 0; erException.ExceptionRecord = NULL; - erException.ExceptionAddress = &DefaultConsoleCtrlHandler; + erException.ExceptionAddress = DefaultConsoleCtrlHandler; erException.NumberParameters = 0; - RtlRaiseException(&erException); + + _SEH2_TRY + { + RtlRaiseException(&erException); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + RtlEnterCriticalSection(&ConsoleLock); + + if ((nCode != CTRL_C_EVENT) || + (NtCurrentPeb()->ProcessParameters->ConsoleFlags != 1)) + { + for (i = NrCtrlHandlers; i > 0; i--) + { + if (CtrlHandlers[i - 1](nCode)) break; + } + } + + RtlLeaveCriticalSection(&ConsoleLock); + } + _SEH2_END; + + ExitThread(0); } - - if (!ConsoleInitialized) ExitThread(0); - RtlEnterCriticalSection(&ConsoleLock); - - if (!(nCode == CTRL_C_EVENT && - NtCurrentPeb()->ProcessParameters->ConsoleFlags & 1)) - { - for(i = NrCtrlHandlers; i > 0; -- i) - if(CtrlHandlers[i - 1](nCode)) break; - } - RtlLeaveCriticalSection(&ConsoleLock); - ExitThread(0); + + break; }
case CTRL_CLOSE_EVENT: case CTRL_LOGOFF_EVENT: case CTRL_SHUTDOWN_EVENT: break; - - default: ExitThread(0); - } - - if (!ConsoleInitialized) ExitThread(0); + + case 3: + + ExitThread(0); + break; + + case 4: + + ExitProcess(CONTROL_C_EXIT); + break; + + default: + + ASSERT(FALSE); + break; + } + + ASSERT(ConsoleInitialized); + RtlEnterCriticalSection(&ConsoleLock); - - if (!(nCode == CTRL_C_EVENT && - NtCurrentPeb()->ProcessParameters->ConsoleFlags & 1)) - { - i = NrCtrlHandlers; - while (i > 0) + nExitCode = 0; + if ((nCode != CTRL_C_EVENT) || (NtCurrentPeb()->ProcessParameters->ConsoleFlags != 1)) + { + for (i = NrCtrlHandlers; i > 0; i--) { - if (i == 1 && (CodeAndFlag & MINLONG) && - (nCode == CTRL_LOGOFF_EVENT || nCode == CTRL_SHUTDOWN_EVENT)) + if ((i == 1) && + (CodeAndFlag & MINLONG) && + ((nCode == CTRL_LOGOFF_EVENT) || (nCode == CTRL_SHUTDOWN_EVENT))) + { break; + }
if (CtrlHandlers[i - 1](nCode)) { @@ -135,14 +162,17 @@ case CTRL_CLOSE_EVENT: case CTRL_LOGOFF_EVENT: case CTRL_SHUTDOWN_EVENT: + case 3: nExitCode = CodeAndFlag; + break; } break; } - --i; } } + RtlLeaveCriticalSection(&ConsoleLock); + ExitThread(nExitCode); }
@@ -3235,74 +3265,70 @@ BOOL AddConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine) { + PHANDLER_ROUTINE* NewCtrlHandlers = NULL; + if (HandlerRoutine == NULL) { NtCurrentPeb()->ProcessParameters->ConsoleFlags = TRUE; - return(TRUE); - } - else - { - NrCtrlHandlers++; - if (CtrlHandlers == NULL) + return TRUE; + } + + if (NrCtrlHandlers == NrAllocatedHandlers) + { + NewCtrlHandlers = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + (NrCtrlHandlers + 4) * sizeof(PHANDLER_ROUTINE)); + if (NewCtrlHandlers == NULL) { - CtrlHandlers = RtlAllocateHeap(RtlGetProcessHeap(), - HEAP_ZERO_MEMORY, - NrCtrlHandlers * sizeof(PHANDLER_ROUTINE)); - } - else - { - CtrlHandlers = RtlReAllocateHeap(RtlGetProcessHeap(), - HEAP_ZERO_MEMORY, - (PVOID)CtrlHandlers, - NrCtrlHandlers * sizeof(PHANDLER_ROUTINE)); - } - - if (CtrlHandlers == NULL) - { - NrCtrlHandlers = 0; SetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } - - CtrlHandlers[NrCtrlHandlers - 1] = HandlerRoutine; + + memmove(NewCtrlHandlers, CtrlHandlers, sizeof(PHANDLER_ROUTINE) * NrCtrlHandlers); + + if (NrAllocatedHandlers > 1) RtlFreeHeap(RtlGetProcessHeap(), 0, CtrlHandlers); + + CtrlHandlers = NewCtrlHandlers; + NrAllocatedHandlers += 4; + } + + ASSERT(NrCtrlHandlers < NrAllocatedHandlers); + + CtrlHandlers[NrCtrlHandlers++] = HandlerRoutine; + return TRUE; +} + + +static +BOOL +RemoveConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine) +{ + ULONG i; + + if (HandlerRoutine == NULL) + { + NtCurrentPeb()->ProcessParameters->ConsoleFlags = FALSE; return TRUE; } -} - - -static -BOOL -RemoveConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine) -{ - ULONG i; - - if (HandlerRoutine == NULL) - { - NtCurrentPeb()->ProcessParameters->ConsoleFlags = FALSE; - return(TRUE); - } - else - { - for (i = 0; i < NrCtrlHandlers; i++) + + for (i = 0; i < NrCtrlHandlers; i++) + { + if (CtrlHandlers[i] == HandlerRoutine) { - if ( ((void*)(CtrlHandlers[i])) == (void*)HandlerRoutine) + if (i < (NrCtrlHandlers - 1)) { - NrCtrlHandlers--; - memmove(CtrlHandlers + i, - CtrlHandlers + i + 1, - (NrCtrlHandlers - i) * sizeof(PHANDLER_ROUTINE)); - - CtrlHandlers = RtlReAllocateHeap(RtlGetProcessHeap(), - HEAP_ZERO_MEMORY, - (PVOID)CtrlHandlers, - NrCtrlHandlers * sizeof(PHANDLER_ROUTINE)); - return(TRUE); + memmove(&CtrlHandlers[i], + &CtrlHandlers[i+1], + (NrCtrlHandlers - i + 1) * sizeof(PHANDLER_ROUTINE)); } + + NrCtrlHandlers--; + return TRUE; } }
SetLastError(ERROR_INVALID_PARAMETER); - return(FALSE); + return FALSE; }
Modified: trunk/reactos/dll/win32/kernel32/misc/dllmain.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/misc/dll... ============================================================================== --- trunk/reactos/dll/win32/kernel32/misc/dllmain.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/kernel32/misc/dllmain.c [iso-8859-1] Tue Mar 9 21:13:19 2010 @@ -41,7 +41,10 @@
extern BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event); extern __declspec(noreturn) VOID CALLBACK ConsoleControlDispatcher(DWORD CodeAndFlag); - +extern PHANDLER_ROUTINE InitialHandler[1]; +extern PHANDLER_ROUTINE* CtrlHandlers; +extern ULONG NrCtrlHandlers; +extern ULONG NrAllocatedHandlers; extern BOOL FASTCALL NlsInit(VOID); extern VOID FASTCALL NlsUninit(VOID); BOOLEAN InWindows = FALSE; @@ -178,7 +181,10 @@ /* Initialize Console Ctrl Handler */ ConsoleInitialized = TRUE; RtlInitializeCriticalSection(&ConsoleLock); - SetConsoleCtrlHandler(DefaultConsoleCtrlHandler, TRUE); + NrAllocatedHandlers = 1; + NrCtrlHandlers = 1; + CtrlHandlers = InitialHandler; + CtrlHandlers[0] = DefaultConsoleCtrlHandler;
/* Now use the proper console handle */ Request.Data.AllocConsoleRequest.Console = Parameters->ConsoleHandle;