mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 20:53:02 +00:00
[KERNEL32]: Bug fix CTRL-C handler registration/deregistration/notification, needed for correct console shutdown behavior.
svn path=/trunk/; revision=46041
This commit is contained in:
parent
9c91a4dc46
commit
e2d31e88e4
2 changed files with 111 additions and 79 deletions
|
@ -19,16 +19,17 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
extern BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event);
|
|
||||||
extern __declspec(noreturn) VOID CALLBACK ConsoleControlDispatcher(DWORD CodeAndFlag);
|
|
||||||
extern RTL_CRITICAL_SECTION ConsoleLock;
|
extern RTL_CRITICAL_SECTION ConsoleLock;
|
||||||
extern BOOL ConsoleInitialized;
|
extern BOOL ConsoleInitialized;
|
||||||
extern BOOL WINAPI IsDebuggerPresent(VOID);
|
extern BOOL WINAPI IsDebuggerPresent(VOID);
|
||||||
|
|
||||||
/* GLOBALS *******************************************************************/
|
/* GLOBALS *******************************************************************/
|
||||||
|
|
||||||
static PHANDLER_ROUTINE* CtrlHandlers = NULL;
|
PHANDLER_ROUTINE InitialHandler[1];
|
||||||
static ULONG NrCtrlHandlers = 0;
|
PHANDLER_ROUTINE* CtrlHandlers;
|
||||||
|
ULONG NrCtrlHandlers;
|
||||||
|
ULONG NrAllocatedHandlers;
|
||||||
|
|
||||||
#define INPUTEXENAME_BUFLEN 256
|
#define INPUTEXENAME_BUFLEN 256
|
||||||
static WCHAR InputExeName[INPUTEXENAME_BUFLEN] = L"";
|
static WCHAR InputExeName[INPUTEXENAME_BUFLEN] = L"";
|
||||||
|
|
||||||
|
@ -49,7 +50,7 @@ DefaultConsoleCtrlHandler(DWORD Event)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CTRL_SHUTDOWN_EVENT:
|
case CTRL_SHUTDOWN_EVENT:
|
||||||
DPRINT("Ctrl Shutdown Event\n");
|
DPRINT1("Ctrl Shutdown Event\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CTRL_CLOSE_EVENT:
|
case CTRL_CLOSE_EVENT:
|
||||||
|
@ -57,15 +58,14 @@ DefaultConsoleCtrlHandler(DWORD Event)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CTRL_LOGOFF_EVENT:
|
case CTRL_LOGOFF_EVENT:
|
||||||
DPRINT("Ctrl Logoff Event\n");
|
DPRINT1("Ctrl Logoff Event\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExitProcess(0);
|
ExitProcess(CONTROL_C_EXIT);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
__declspec(noreturn)
|
__declspec(noreturn)
|
||||||
VOID
|
VOID
|
||||||
CALLBACK
|
CALLBACK
|
||||||
|
@ -74,6 +74,7 @@ ConsoleControlDispatcher(DWORD CodeAndFlag)
|
||||||
DWORD nExitCode = 0;
|
DWORD nExitCode = 0;
|
||||||
DWORD nCode = CodeAndFlag & MAXLONG;
|
DWORD nCode = CodeAndFlag & MAXLONG;
|
||||||
UINT i;
|
UINT i;
|
||||||
|
EXCEPTION_RECORD erException;
|
||||||
|
|
||||||
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
|
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
|
||||||
|
|
||||||
|
@ -84,49 +85,75 @@ ConsoleControlDispatcher(DWORD CodeAndFlag)
|
||||||
{
|
{
|
||||||
if (IsDebuggerPresent())
|
if (IsDebuggerPresent())
|
||||||
{
|
{
|
||||||
EXCEPTION_RECORD erException;
|
erException.ExceptionCode = (nCode == CTRL_C_EVENT ?
|
||||||
erException.ExceptionCode =
|
DBG_CONTROL_C : DBG_CONTROL_BREAK);
|
||||||
(nCode == CTRL_C_EVENT ? DBG_CONTROL_C : DBG_CONTROL_BREAK);
|
|
||||||
erException.ExceptionFlags = 0;
|
erException.ExceptionFlags = 0;
|
||||||
erException.ExceptionRecord = NULL;
|
erException.ExceptionRecord = NULL;
|
||||||
erException.ExceptionAddress = &DefaultConsoleCtrlHandler;
|
erException.ExceptionAddress = DefaultConsoleCtrlHandler;
|
||||||
erException.NumberParameters = 0;
|
erException.NumberParameters = 0;
|
||||||
|
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
RtlRaiseException(&erException);
|
RtlRaiseException(&erException);
|
||||||
}
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
if (!ConsoleInitialized) ExitThread(0);
|
{
|
||||||
RtlEnterCriticalSection(&ConsoleLock);
|
RtlEnterCriticalSection(&ConsoleLock);
|
||||||
|
|
||||||
if (!(nCode == CTRL_C_EVENT &&
|
if ((nCode != CTRL_C_EVENT) ||
|
||||||
NtCurrentPeb()->ProcessParameters->ConsoleFlags & 1))
|
(NtCurrentPeb()->ProcessParameters->ConsoleFlags != 1))
|
||||||
|
{
|
||||||
|
for (i = NrCtrlHandlers; i > 0; i--)
|
||||||
{
|
{
|
||||||
for(i = NrCtrlHandlers; i > 0; -- i)
|
|
||||||
if (CtrlHandlers[i - 1](nCode)) break;
|
if (CtrlHandlers[i - 1](nCode)) break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RtlLeaveCriticalSection(&ConsoleLock);
|
RtlLeaveCriticalSection(&ConsoleLock);
|
||||||
|
}
|
||||||
|
_SEH2_END;
|
||||||
|
|
||||||
ExitThread(0);
|
ExitThread(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case CTRL_CLOSE_EVENT:
|
case CTRL_CLOSE_EVENT:
|
||||||
case CTRL_LOGOFF_EVENT:
|
case CTRL_LOGOFF_EVENT:
|
||||||
case CTRL_SHUTDOWN_EVENT:
|
case CTRL_SHUTDOWN_EVENT:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: ExitThread(0);
|
case 3:
|
||||||
|
|
||||||
|
ExitThread(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
|
||||||
|
ExitProcess(CONTROL_C_EXIT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
ASSERT(FALSE);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ConsoleInitialized) ExitThread(0);
|
ASSERT(ConsoleInitialized);
|
||||||
RtlEnterCriticalSection(&ConsoleLock);
|
|
||||||
|
|
||||||
if (!(nCode == CTRL_C_EVENT &&
|
RtlEnterCriticalSection(&ConsoleLock);
|
||||||
NtCurrentPeb()->ProcessParameters->ConsoleFlags & 1))
|
nExitCode = 0;
|
||||||
|
if ((nCode != CTRL_C_EVENT) || (NtCurrentPeb()->ProcessParameters->ConsoleFlags != 1))
|
||||||
{
|
{
|
||||||
i = NrCtrlHandlers;
|
for (i = NrCtrlHandlers; i > 0; i--)
|
||||||
while (i > 0)
|
{
|
||||||
|
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;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (CtrlHandlers[i - 1](nCode))
|
if (CtrlHandlers[i - 1](nCode))
|
||||||
{
|
{
|
||||||
|
@ -135,14 +162,17 @@ ConsoleControlDispatcher(DWORD CodeAndFlag)
|
||||||
case CTRL_CLOSE_EVENT:
|
case CTRL_CLOSE_EVENT:
|
||||||
case CTRL_LOGOFF_EVENT:
|
case CTRL_LOGOFF_EVENT:
|
||||||
case CTRL_SHUTDOWN_EVENT:
|
case CTRL_SHUTDOWN_EVENT:
|
||||||
|
case 3:
|
||||||
nExitCode = CodeAndFlag;
|
nExitCode = CodeAndFlag;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
--i;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RtlLeaveCriticalSection(&ConsoleLock);
|
RtlLeaveCriticalSection(&ConsoleLock);
|
||||||
|
|
||||||
ExitThread(nExitCode);
|
ExitThread(nExitCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3235,38 +3265,37 @@ static
|
||||||
BOOL
|
BOOL
|
||||||
AddConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
|
AddConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
|
||||||
{
|
{
|
||||||
|
PHANDLER_ROUTINE* NewCtrlHandlers = NULL;
|
||||||
|
|
||||||
if (HandlerRoutine == NULL)
|
if (HandlerRoutine == NULL)
|
||||||
{
|
{
|
||||||
NtCurrentPeb()->ProcessParameters->ConsoleFlags = TRUE;
|
NtCurrentPeb()->ProcessParameters->ConsoleFlags = TRUE;
|
||||||
return(TRUE);
|
return TRUE;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NrCtrlHandlers++;
|
|
||||||
if (CtrlHandlers == 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)
|
if (NrCtrlHandlers == NrAllocatedHandlers)
|
||||||
|
{
|
||||||
|
NewCtrlHandlers = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||||
|
0,
|
||||||
|
(NrCtrlHandlers + 4) * sizeof(PHANDLER_ROUTINE));
|
||||||
|
if (NewCtrlHandlers == NULL)
|
||||||
{
|
{
|
||||||
NrCtrlHandlers = 0;
|
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
CtrlHandlers[NrCtrlHandlers - 1] = HandlerRoutine;
|
memmove(NewCtrlHandlers, CtrlHandlers, sizeof(PHANDLER_ROUTINE) * NrCtrlHandlers);
|
||||||
return TRUE;
|
|
||||||
|
if (NrAllocatedHandlers > 1) RtlFreeHeap(RtlGetProcessHeap(), 0, CtrlHandlers);
|
||||||
|
|
||||||
|
CtrlHandlers = NewCtrlHandlers;
|
||||||
|
NrAllocatedHandlers += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASSERT(NrCtrlHandlers < NrAllocatedHandlers);
|
||||||
|
|
||||||
|
CtrlHandlers[NrCtrlHandlers++] = HandlerRoutine;
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3279,30 +3308,27 @@ RemoveConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
|
||||||
if (HandlerRoutine == NULL)
|
if (HandlerRoutine == NULL)
|
||||||
{
|
{
|
||||||
NtCurrentPeb()->ProcessParameters->ConsoleFlags = FALSE;
|
NtCurrentPeb()->ProcessParameters->ConsoleFlags = FALSE;
|
||||||
return(TRUE);
|
return TRUE;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
for (i = 0; i < NrCtrlHandlers; i++)
|
for (i = 0; i < NrCtrlHandlers; i++)
|
||||||
{
|
{
|
||||||
if ( ((void*)(CtrlHandlers[i])) == (void*)HandlerRoutine)
|
if (CtrlHandlers[i] == HandlerRoutine)
|
||||||
{
|
{
|
||||||
NrCtrlHandlers--;
|
if (i < (NrCtrlHandlers - 1))
|
||||||
memmove(CtrlHandlers + i,
|
{
|
||||||
CtrlHandlers + i + 1,
|
memmove(&CtrlHandlers[i],
|
||||||
(NrCtrlHandlers - i) * sizeof(PHANDLER_ROUTINE));
|
&CtrlHandlers[i+1],
|
||||||
|
(NrCtrlHandlers - i + 1) * sizeof(PHANDLER_ROUTINE));
|
||||||
CtrlHandlers = RtlReAllocateHeap(RtlGetProcessHeap(),
|
|
||||||
HEAP_ZERO_MEMORY,
|
|
||||||
(PVOID)CtrlHandlers,
|
|
||||||
NrCtrlHandlers * sizeof(PHANDLER_ROUTINE));
|
|
||||||
return(TRUE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NrCtrlHandlers--;
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
return(FALSE);
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,10 @@ RTL_CRITICAL_SECTION ConsoleLock;
|
||||||
|
|
||||||
extern BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event);
|
extern BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event);
|
||||||
extern __declspec(noreturn) VOID CALLBACK ConsoleControlDispatcher(DWORD CodeAndFlag);
|
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 BOOL FASTCALL NlsInit(VOID);
|
||||||
extern VOID FASTCALL NlsUninit(VOID);
|
extern VOID FASTCALL NlsUninit(VOID);
|
||||||
BOOLEAN InWindows = FALSE;
|
BOOLEAN InWindows = FALSE;
|
||||||
|
@ -178,7 +181,10 @@ BasepInitConsole(VOID)
|
||||||
/* Initialize Console Ctrl Handler */
|
/* Initialize Console Ctrl Handler */
|
||||||
ConsoleInitialized = TRUE;
|
ConsoleInitialized = TRUE;
|
||||||
RtlInitializeCriticalSection(&ConsoleLock);
|
RtlInitializeCriticalSection(&ConsoleLock);
|
||||||
SetConsoleCtrlHandler(DefaultConsoleCtrlHandler, TRUE);
|
NrAllocatedHandlers = 1;
|
||||||
|
NrCtrlHandlers = 1;
|
||||||
|
CtrlHandlers = InitialHandler;
|
||||||
|
CtrlHandlers[0] = DefaultConsoleCtrlHandler;
|
||||||
|
|
||||||
/* Now use the proper console handle */
|
/* Now use the proper console handle */
|
||||||
Request.Data.AllocConsoleRequest.Console = Parameters->ConsoleHandle;
|
Request.Data.AllocConsoleRequest.Console = Parameters->ConsoleHandle;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue