Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

348 lines
8.9 KiB

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
consignl.c
Abstract:
This module contains the handler for signals received from OS2SES.
Author:
Avi Nathan (avin) 17-Jul-1991
Revision History:
--*/
#define INCL_OS2V20_TASKING
#define INCL_OS2V20_ERRORS
#define INCL_OS2V20_EXCEPTIONS
#include "os2srv.h"
#include "os2win.h"
#define NTOS2_ONLY
#define XCPT_REPLACE_CMD 12
#include "sesport.h"
VOID
Os2PrepareCmdSignals(POS2_PROCESS Process)
{
/*++
This routine installs a dummy signal handler, to mimique the signal
behavior of OS/2 CMD.EXE, in cases where we shortcut cmd /c for performance
--*/
POS2_SESSION Session;
POS2_REGISTER_HANDLER_REC pRec;
POS2_REGISTER_HANDLER_REC pPRec;
Session = Process->Session;
pPRec = (POS2_REGISTER_HANDLER_REC)
RtlAllocateHeap(Os2Heap, 0,
sizeof(OS2_REGISTER_HANDLER_REC));
if ((PVOID)pPRec == NULL) {
#if DBG
DbgPrint("Os2PrepareCmdSingals, no memory for heap, return with no action\n");
#endif
return;
}
pPRec->Signal = XCPT_REPLACE_CMD;
pPRec->fAction = XCPT_REPLACE_CMD;
pPRec->Process = Process;
if (Session->RegisterCtrlHandler == NULL) {
Session->RegisterCtrlHandler = pPRec;
pPRec->Link = NULL;
}
else {
pRec = Session->RegisterCtrlHandler;
Session->RegisterCtrlHandler = pPRec;
pPRec->Link = pRec;
}
}
VOID
Os2SigKillProcess(
POS2_PROCESS Process)
{
POS2_THREAD Thread = NULL;
PLIST_ENTRY ListHead, ListNext;
OS2_API_MSG m;
POS2_TERMINATEPROCESS_MSG a = &m.u.TerminateProcess;
PORT_MSG_DATA_LENGTH(m) = sizeof(m) - sizeof(PORT_MESSAGE);
PORT_MSG_TOTAL_LENGTH(m) = sizeof(m);
PORT_MSG_ZERO_INIT(m) = 0L;
//
// Kill the process by issuing an Os2DosExit on it's behalf, then
// resume it to terminate gracefully
//
#if DBG
IF_OS2_DEBUG(SIG) {
DbgPrint("Os2SigKillProcess, Process %x\n", Process);
}
#endif
ListHead = &Process->ThreadList;
ListNext = ListHead->Flink;
Thread = NULL;
while (ListNext != ListHead) {
Thread = CONTAINING_RECORD(ListNext, OS2_THREAD, Link);
if (Thread->Flags & OS2_THREAD_THREAD1) {
break;
}
else {
ListNext = ListNext->Flink;
}
}
if (Thread != NULL) {
a->ExitReason = TC_EXIT;
a->ExitResult = ERROR_INTERRUPT;
((POS2_DOSEXIT_MSG)a)->ExitAction = EXIT_PROCESS;
if (Process->CtrlHandlerFlag) {
if (Process->ResultCodes.ExitReason != TC_TRAP) {
ULONG killed = TRUE;
NTSTATUS Status;
Status = NtWriteVirtualMemory( Process->ProcessHandle,
&Process->ClientPib->Killed,
&killed,
sizeof( Process->ClientPib->Killed ),
NULL
);
#if DBG
if (!(NT_SUCCESS(Status))) {
KdPrint(( "Os2SigKillProcess, failed to write to client, Status %lx\n", Status));
}
#endif // DBG
}
//
// set flag to create a separate thread for Os2DosExit
//
m.ApiNumber = Os2MaxApiNumber;
Os2DosExit (Thread, &m);
#if DBG
IF_OS2_DEBUG(SIG) {
DbgPrint("now resuming thread1\n");
}
#endif
// NtResumeThread(Thread->ThreadHandle, NULL);
// There is no need to alert thread here. It will be executed later
// by Os2TerminationThread.
//
//#if DBG
// DbgPrint("[%d,%d]: Os2SigKillProcess NtAlertThread(%x)\n",
// Thread->Process->ProcessId,
// Thread->ThreadId,
// Thread->ThreadHandle);
//#endif
// NtAlertThread(Thread->ThreadHandle);
}
else {
#if DBG
IF_OS2_DEBUG(SIG) {
DbgPrint("OS2SRV: Handling a signal before loading completed\n");
}
#endif
Process->ExitStatus |= OS2_EXIT_IN_PROGRESS;
Os2InternalTerminateProcess(Thread, &m);
}
}
}
VOID
Os2SigKillProcessTree(
IN POS2_PROCESS RootProcess,
IN BOOLEAN IncludeRoot
)
/*++
Routine Description:
This routine recursively kills each subtree inside it
Arguments:
RootProcess - root process of tree to issue Signal to
Return Value:
none
--*/
{
PLIST_ENTRY ListHead, ListNext;
if (IncludeRoot){
#if DBG
IF_OS2_DEBUG(SIG) {
DbgPrint("SigKillProcessTree, killing parent\n");
}
#endif
Os2SigKillProcess(RootProcess);
}
ListHead = &RootProcess->ChildrenList;
ListNext = ListHead->Flink;
while (ListNext != ListHead) {
#if DBG
IF_OS2_DEBUG(SIG) {
DbgPrint("SigKillProcessTree, getting into recursion\n");
}
#endif
Os2SigKillProcessTree( CONTAINING_RECORD( ListNext,OS2_PROCESS,SiblingLink),
TRUE
);
ListNext = ListNext->Flink;
}
}
NTSTATUS
Os2CtrlSignalHandler(
IN OUT PVOID RequestMsg,
IN POS2_PROCESS RecievingProcess
)
{
POS2_PROCESS Process, Parent = NULL;
POS2_THREAD Thread = NULL;
PLIST_ENTRY ListHead, ListNext;
int Signal = ((POS2SESREQUESTMSG)RequestMsg)->d.Signal.Type;
POS2_SESSION Session = (POS2_SESSION)(((POS2SESREQUESTMSG)RequestMsg)->Session);
POS2_REGISTER_HANDLER_REC pRec;
#if DBG
IF_OS2_DEBUG(SIG) {
DbgPrint("Os2CtrlSignalHandler: Signal %x for Session %p\n", Signal, Session);
}
#endif
if (Session == NULL) {
#if DBG
DbgPrint("Os2CtrlSignalHandler: NULL Session Passed\n");
#endif
return STATUS_INVALID_HANDLE;
}
if ((Signal != XCPT_SIGNAL_INTR ) &&
(Signal != XCPT_SIGNAL_KILLPROC ) &&
(Signal != XCPT_SIGNAL_BREAK )){
#if DBG
DbgPrint("Os2CtrlSignalHandler: Unknown Signal %x\n", Signal);
#endif
return (0L);
}
if (Session->InTermination)
{
#if DBG
IF_OS2_DEBUG(SIG) {
DbgPrint("Os2CtrlSignalHandler: session in termination already\n");
}
#endif
return (0L);
}
//
// If a process in this session has registered a handler for Ctrl-c,
// Kill process or Ctrl-break dispatch only to this one otherwise
// send a signal to each process
//
if ((pRec = Session->RegisterCtrlHandler) != NULL) {
while (pRec != NULL) {
if (pRec->Signal == (ULONG) Signal) {
//
// Since we receive a debug message for each process
// in the session, no need to forward except for
// the process who actually handles the Signal
//
if ((pRec->Process == RecievingProcess) || (RecievingProcess == NULL)) {
if (pRec->fAction != SIGA_IGNORE){
Os2IssueSignal(pRec->Process, Signal);
}
}
return(0L);
}
else if (pRec->Signal == XCPT_REPLACE_CMD) {
//
// We replaced (performance) exec of cmd /c with direct
// exec of it's children, and none of them registered
// A handler for this signal - kill the subtree
//
Os2SigKillProcessTree(pRec->Process, TRUE);
return(0L);
}
pRec = pRec->Link;
}
}
//
// We need to send a signal to each process in this session. First
// suspend each process in this session.
//
for (
ListHead = &Os2RootProcess->ListLink,
ListNext = ListHead->Flink;
ListNext != ListHead ;
ListNext = ListNext->Flink
) {
Process = CONTAINING_RECORD( ListNext, OS2_PROCESS, ListLink );
if ( Process->Session == Session ) {
Os2SuspendProcess(Process);
}
}
//
// After each process has been suspended kill each one
//
ListHead = &Os2RootProcess->ListLink;
ListNext = ListHead->Flink;
while (ListNext != ListHead) {
Process = CONTAINING_RECORD(ListNext, OS2_PROCESS, ListLink);
ListNext = ListNext->Flink;
if ( Process->Session == Session ) {
Os2SigKillProcess(Process);
}
}
//
// This Session should not respond to any more signals until it terminates
//
try {
Session->InTermination = TRUE;
if (Session->ReferenceCount != -1L)
{
((POS2_SES_GROUP_PARMS)Session->SesGrpAddress)->InTermination |= 1;
}
} except( EXCEPTION_EXECUTE_HANDLER ) {
#if DBG
IF_OS2_DEBUG(SIG) {
DbgPrint("OS2SRV: Os2CtrlSignalHandler Got an Exception, recovery ok\n");
}
#endif
;
}
return(0L);
}