kernel32: Move SetConsoleCtrlHandler() implementation to kernelbase.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
48020f4846
commit
11217ee628
|
@ -889,151 +889,6 @@ BOOL WINAPI GetNumberOfConsoleMouseButtons(LPDWORD nrofbuttons)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************
|
|
||||||
* 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
|
* CONSOLE_HandleCtrlC
|
||||||
*
|
*
|
||||||
|
@ -1041,6 +896,7 @@ static DWORD WINAPI CONSOLE_SendEventThread(void* pmt)
|
||||||
*/
|
*/
|
||||||
int CONSOLE_HandleCtrlC(unsigned sig)
|
int CONSOLE_HandleCtrlC(unsigned sig)
|
||||||
{
|
{
|
||||||
|
extern DWORD WINAPI CtrlRoutine( void *arg );
|
||||||
HANDLE thread;
|
HANDLE thread;
|
||||||
|
|
||||||
/* FIXME: better test whether a console is attached to this process ??? */
|
/* 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
|
* console critical section, we need another execution environment where
|
||||||
* we can wait on this critical section
|
* 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)
|
if (thread == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -345,7 +345,7 @@
|
||||||
@ stdcall CreateWaitableTimerExA(ptr str long long)
|
@ stdcall CreateWaitableTimerExA(ptr str long long)
|
||||||
@ stdcall -import CreateWaitableTimerExW(ptr wstr long long)
|
@ stdcall -import CreateWaitableTimerExW(ptr wstr long long)
|
||||||
@ stdcall -import CreateWaitableTimerW(ptr long wstr)
|
@ stdcall -import CreateWaitableTimerW(ptr long wstr)
|
||||||
# @ stub CtrlRoutine
|
@ stdcall CtrlRoutine(ptr) kernelbase.CtrlRoutine
|
||||||
@ stdcall -import DeactivateActCtx(long long)
|
@ stdcall -import DeactivateActCtx(long long)
|
||||||
@ stdcall -import DebugActiveProcess(long)
|
@ stdcall -import DebugActiveProcess(long)
|
||||||
@ stdcall -import DebugActiveProcessStop(long)
|
@ stdcall -import DebugActiveProcessStop(long)
|
||||||
|
@ -1349,7 +1349,7 @@
|
||||||
@ stdcall -import SetConsoleCP(long)
|
@ stdcall -import SetConsoleCP(long)
|
||||||
# @ stub SetConsoleHistoryInfo
|
# @ stub SetConsoleHistoryInfo
|
||||||
@ stub SetConsoleCommandHistoryMode
|
@ stub SetConsoleCommandHistoryMode
|
||||||
@ stdcall SetConsoleCtrlHandler(ptr long)
|
@ stdcall -import SetConsoleCtrlHandler(ptr long)
|
||||||
@ stub SetConsoleCursor
|
@ stub SetConsoleCursor
|
||||||
@ stdcall -import SetConsoleCursorInfo(long ptr)
|
@ stdcall -import SetConsoleCursorInfo(long ptr)
|
||||||
@ stub SetConsoleCursorMode
|
@ 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];
|
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 */
|
/* map a kernel32 console handle onto a real wineserver handle */
|
||||||
static inline obj_handle_t console_handle_unmap( HANDLE h )
|
static inline obj_handle_t console_handle_unmap( HANDLE h )
|
||||||
|
@ -239,6 +254,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.@)
|
* FillConsoleOutputAttribute (kernelbase.@)
|
||||||
*/
|
*/
|
||||||
|
@ -985,6 +1039,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.@)
|
* SetConsoleCursorInfo (kernelbase.@)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -234,7 +234,7 @@
|
||||||
@ stdcall CreateWaitableTimerExW(ptr wstr long long)
|
@ stdcall CreateWaitableTimerExW(ptr wstr long long)
|
||||||
@ stdcall CreateWaitableTimerW(ptr long wstr)
|
@ stdcall CreateWaitableTimerW(ptr long wstr)
|
||||||
@ stdcall CreateWellKnownSid(long ptr ptr ptr)
|
@ stdcall CreateWellKnownSid(long ptr ptr ptr)
|
||||||
# @ stub CtrlRoutine
|
@ stdcall CtrlRoutine(ptr)
|
||||||
# @ stub CveEventWrite
|
# @ stub CveEventWrite
|
||||||
@ stdcall DeactivateActCtx(long long)
|
@ stdcall DeactivateActCtx(long long)
|
||||||
@ stdcall DebugActiveProcess(long)
|
@ stdcall DebugActiveProcess(long)
|
||||||
|
@ -1404,7 +1404,7 @@
|
||||||
@ stdcall SetComputerNameW(wstr)
|
@ stdcall SetComputerNameW(wstr)
|
||||||
@ stdcall SetConsoleActiveScreenBuffer(long)
|
@ stdcall SetConsoleActiveScreenBuffer(long)
|
||||||
@ stdcall SetConsoleCP(long)
|
@ stdcall SetConsoleCP(long)
|
||||||
@ stdcall SetConsoleCtrlHandler(ptr long) kernel32.SetConsoleCtrlHandler
|
@ stdcall SetConsoleCtrlHandler(ptr long)
|
||||||
@ stdcall SetConsoleCursorInfo(long ptr)
|
@ stdcall SetConsoleCursorInfo(long ptr)
|
||||||
@ stdcall SetConsoleCursorPosition(long long)
|
@ stdcall SetConsoleCursorPosition(long long)
|
||||||
@ stdcall SetConsoleInputExeNameA(str)
|
@ stdcall SetConsoleInputExeNameA(str)
|
||||||
|
|
Loading…
Reference in New Issue