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;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* 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
|
||||
*
|
||||
|
@ -1041,6 +896,7 @@ static DWORD WINAPI CONSOLE_SendEventThread(void* pmt)
|
|||
*/
|
||||
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 )
|
||||
|
@ -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.@)
|
||||
*/
|
||||
|
@ -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.@)
|
||||
*/
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue