Commit 11217ee6 authored by Alexandre Julliard's avatar Alexandre Julliard

kernel32: Move SetConsoleCtrlHandler() implementation to kernelbase.

parent 48020f48
......@@ -890,157 +890,13 @@ BOOL WINAPI GetNumberOfConsoleMouseButtons(LPDWORD nrofbuttons)
}
/******************************************************************
* CONSOLE_DefaultHandler
*
* Final control event handler
*/
static BOOL WINAPI CONSOLE_DefaultHandler(DWORD dwCtrlType)
{
FIXME("Terminating process %x on event %x\n", GetCurrentProcessId(), dwCtrlType);
ExitProcess(0);
/* should never go here */
return TRUE;
}
/******************************************************************************
* SetConsoleCtrlHandler [KERNEL32.@] Adds function to calling process list
*
* PARAMS
* func [I] Address of handler function
* add [I] Handler to add or remove
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
struct ConsoleHandler
{
PHANDLER_ROUTINE handler;
struct ConsoleHandler* next;
};
static struct ConsoleHandler CONSOLE_DefaultConsoleHandler = {CONSOLE_DefaultHandler, NULL};
static struct ConsoleHandler* CONSOLE_Handlers = &CONSOLE_DefaultConsoleHandler;
/*****************************************************************************/
/******************************************************************
* SetConsoleCtrlHandler (KERNEL32.@)
*/
BOOL WINAPI SetConsoleCtrlHandler(PHANDLER_ROUTINE func, BOOL add)
{
BOOL ret = TRUE;
TRACE("(%p,%i)\n", func, add);
if (!func)
{
RtlEnterCriticalSection(&CONSOLE_CritSect);
if (add)
NtCurrentTeb()->Peb->ProcessParameters->ConsoleFlags |= 1;
else
NtCurrentTeb()->Peb->ProcessParameters->ConsoleFlags &= ~1;
RtlLeaveCriticalSection(&CONSOLE_CritSect);
}
else if (add)
{
struct ConsoleHandler* ch = HeapAlloc(GetProcessHeap(), 0, sizeof(struct ConsoleHandler));
if (!ch) return FALSE;
ch->handler = func;
RtlEnterCriticalSection(&CONSOLE_CritSect);
ch->next = CONSOLE_Handlers;
CONSOLE_Handlers = ch;
RtlLeaveCriticalSection(&CONSOLE_CritSect);
}
else
{
struct ConsoleHandler** ch;
RtlEnterCriticalSection(&CONSOLE_CritSect);
for (ch = &CONSOLE_Handlers; *ch; ch = &(*ch)->next)
{
if ((*ch)->handler == func) break;
}
if (*ch)
{
struct ConsoleHandler* rch = *ch;
/* sanity check */
if (rch == &CONSOLE_DefaultConsoleHandler)
{
ERR("Who's trying to remove default handler???\n");
SetLastError(ERROR_INVALID_PARAMETER);
ret = FALSE;
}
else
{
*ch = rch->next;
HeapFree(GetProcessHeap(), 0, rch);
}
}
else
{
WARN("Attempt to remove non-installed CtrlHandler %p\n", func);
SetLastError(ERROR_INVALID_PARAMETER);
ret = FALSE;
}
RtlLeaveCriticalSection(&CONSOLE_CritSect);
}
return ret;
}
static LONG WINAPI CONSOLE_CtrlEventHandler(EXCEPTION_POINTERS *eptr)
{
TRACE("(%x)\n", eptr->ExceptionRecord->ExceptionCode);
return EXCEPTION_EXECUTE_HANDLER;
}
/******************************************************************
* CONSOLE_SendEventThread
*
* Internal helper to pass an event to the list on installed handlers
*/
static DWORD WINAPI CONSOLE_SendEventThread(void* pmt)
{
DWORD_PTR event = (DWORD_PTR)pmt;
struct ConsoleHandler* ch;
if (event == CTRL_C_EVENT)
{
BOOL caught_by_dbg = TRUE;
/* First, try to pass the ctrl-C event to the debugger (if any)
* If it continues, there's nothing more to do
* Otherwise, we need to send the ctrl-C event to the handlers
*/
__TRY
{
RaiseException( DBG_CONTROL_C, 0, 0, NULL );
}
__EXCEPT(CONSOLE_CtrlEventHandler)
{
caught_by_dbg = FALSE;
}
__ENDTRY;
if (caught_by_dbg) return 0;
/* the debugger didn't continue... so, pass to ctrl handlers */
}
RtlEnterCriticalSection(&CONSOLE_CritSect);
for (ch = CONSOLE_Handlers; ch; ch = ch->next)
{
if (ch->handler(event)) break;
}
RtlLeaveCriticalSection(&CONSOLE_CritSect);
return 1;
}
/******************************************************************
* CONSOLE_HandleCtrlC
*
* Check whether the shall manipulate CtrlC events
*/
int CONSOLE_HandleCtrlC(unsigned sig)
{
extern DWORD WINAPI CtrlRoutine( void *arg );
HANDLE thread;
/* FIXME: better test whether a console is attached to this process ??? */
......@@ -1059,7 +915,7 @@ int CONSOLE_HandleCtrlC(unsigned sig)
* console critical section, we need another execution environment where
* we can wait on this critical section
*/
thread = CreateThread(NULL, 0, CONSOLE_SendEventThread, (void*)CTRL_C_EVENT, 0, NULL);
thread = CreateThread(NULL, 0, CtrlRoutine, (void*)CTRL_C_EVENT, 0, NULL);
if (thread == NULL)
return 0;
......
......@@ -345,7 +345,7 @@
@ stdcall CreateWaitableTimerExA(ptr str long long)
@ stdcall -import CreateWaitableTimerExW(ptr wstr long long)
@ stdcall -import CreateWaitableTimerW(ptr long wstr)
# @ stub CtrlRoutine
@ stdcall CtrlRoutine(ptr) kernelbase.CtrlRoutine
@ stdcall -import DeactivateActCtx(long long)
@ stdcall -import DebugActiveProcess(long)
@ stdcall -import DebugActiveProcessStop(long)
......@@ -1349,7 +1349,7 @@
@ stdcall -import SetConsoleCP(long)
# @ stub SetConsoleHistoryInfo
@ stub SetConsoleCommandHistoryMode
@ stdcall SetConsoleCtrlHandler(ptr long)
@ stdcall -import SetConsoleCtrlHandler(ptr long)
@ stub SetConsoleCursor
@ stdcall -import SetConsoleCursorInfo(long ptr)
@ stub SetConsoleCursorMode
......
......@@ -55,6 +55,21 @@ static CRITICAL_SECTION console_section = { &critsect_debug, -1, 0, 0, 0, 0 };
static WCHAR input_exe[MAX_PATH + 1];
struct ctrl_handler
{
PHANDLER_ROUTINE func;
struct ctrl_handler *next;
};
static BOOL WINAPI default_ctrl_handler( DWORD type )
{
FIXME( "Terminating process %x on event %x\n", GetCurrentProcessId(), type );
RtlExitUserProcess( 0 );
return TRUE;
}
static struct ctrl_handler default_handler = { default_ctrl_handler, NULL };
static struct ctrl_handler *ctrl_handlers = &default_handler;
/* map a kernel32 console handle onto a real wineserver handle */
static inline obj_handle_t console_handle_unmap( HANDLE h )
......@@ -240,6 +255,45 @@ HANDLE WINAPI DECLSPEC_HOTPATCH CreateConsoleScreenBuffer( DWORD access, DWORD s
/******************************************************************************
* CtrlRoutine (kernelbase.@)
*/
DWORD WINAPI CtrlRoutine( void *arg )
{
DWORD_PTR event = (DWORD_PTR)arg;
struct ctrl_handler *handler;
if (event == CTRL_C_EVENT)
{
BOOL caught_by_dbg = TRUE;
/* First, try to pass the ctrl-C event to the debugger (if any)
* If it continues, there's nothing more to do
* Otherwise, we need to send the ctrl-C event to the handlers
*/
__TRY
{
RaiseException( DBG_CONTROL_C, 0, 0, NULL );
}
__EXCEPT_ALL
{
caught_by_dbg = FALSE;
}
__ENDTRY
if (caught_by_dbg) return 0;
}
if (NtCurrentTeb()->Peb->ProcessParameters->ConsoleFlags & 1) return 0;
RtlEnterCriticalSection( &console_section );
for (handler = ctrl_handlers; handler; handler = handler->next)
{
if (handler->func( event )) break;
}
RtlLeaveCriticalSection( &console_section );
return 1;
}
/******************************************************************************
* FillConsoleOutputAttribute (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH FillConsoleOutputAttribute( HANDLE handle, WORD attr, DWORD length,
......@@ -986,6 +1040,57 @@ BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleCP( UINT cp )
/******************************************************************************
* SetConsoleCtrlHandler (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleCtrlHandler( PHANDLER_ROUTINE func, BOOL add )
{
struct ctrl_handler *handler;
BOOL ret = FALSE;
TRACE( "(%p,%d)\n", func, add );
RtlEnterCriticalSection( &console_section );
if (!func)
{
if (add) NtCurrentTeb()->Peb->ProcessParameters->ConsoleFlags |= 1;
else NtCurrentTeb()->Peb->ProcessParameters->ConsoleFlags &= ~1;
ret = TRUE;
}
else if (add)
{
if ((handler = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*handler) )))
{
handler->func = func;
handler->next = ctrl_handlers;
ctrl_handlers = handler;
ret = TRUE;
}
}
else
{
struct ctrl_handler **p_handler;
for (p_handler = &ctrl_handlers; *p_handler; p_handler = &(*p_handler)->next)
{
if ((*p_handler)->func == func) break;
}
if (*p_handler && *p_handler != &default_handler)
{
handler = *p_handler;
*p_handler = handler->next;
RtlFreeHeap( GetProcessHeap(), 0, handler );
ret = TRUE;
}
else SetLastError( ERROR_INVALID_PARAMETER );
}
RtlLeaveCriticalSection( &console_section );
return ret;
}
/******************************************************************************
* SetConsoleCursorInfo (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleCursorInfo( HANDLE handle, CONSOLE_CURSOR_INFO *info )
......
......@@ -234,7 +234,7 @@
@ stdcall CreateWaitableTimerExW(ptr wstr long long)
@ stdcall CreateWaitableTimerW(ptr long wstr)
@ stdcall CreateWellKnownSid(long ptr ptr ptr)
# @ stub CtrlRoutine
@ stdcall CtrlRoutine(ptr)
# @ stub CveEventWrite
@ stdcall DeactivateActCtx(long long)
@ stdcall DebugActiveProcess(long)
......@@ -1404,7 +1404,7 @@
@ stdcall SetComputerNameW(wstr)
@ stdcall SetConsoleActiveScreenBuffer(long)
@ stdcall SetConsoleCP(long)
@ stdcall SetConsoleCtrlHandler(ptr long) kernel32.SetConsoleCtrlHandler
@ stdcall SetConsoleCtrlHandler(ptr long)
@ stdcall SetConsoleCursorInfo(long ptr)
@ stdcall SetConsoleCursorPosition(long long)
@ stdcall SetConsoleInputExeNameA(str)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment