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.
 
 
 
 
 
 

499 lines
14 KiB

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
dllsig16.c
Abstract:
This module implements 32 equivalents of OS/2 V1.21 Signal
API Calls. These are called from 16->32 thunks (i386\doscalls.asm).
Author:
Yaron Shamir (YaronS) 30-May-1991
Revision History:
--*/
#define INCL_OS2V20_MEMORY
#define INCL_OS2V20_FILESYS
#define INCL_OS2V20_ERRORS
#include "os2dll.h"
#include "os2dll16.h"
extern OD2_SIG_HANDLER_REC SigHandlerRec;
extern POD2_VEC_HANDLER_REC pVecHandlerRec;
extern PVOID __cdecl Od2JumpTo16SignalDispatch(ULONG address, ULONG regs,
ULONG usFlagNum, ULONG usFlagArg);
extern BOOLEAN LDRIsLDTValid(SEL sel);
extern APIRET DosFreeSeg(SEL sel);
VOID
Od2PrepareEnterToSignalHandler(
PCONTEXT pContext,
POD2_CONTEXT_SAVE_AREA pSaveArea
);
VOID
Od2MakeSignalHandlerContext(
POS2_REGISTER16_SIGNAL pContext16
);
VOID
Od2ExitFromSignalHandler(
PCONTEXT Context,
POD2_CONTEXT_SAVE_AREA pSaveArea
);
APIRET
DosFlagProcess(
ULONG pid,
ULONG fScope,
ULONG usFlagNum,
ULONG usFlagArg,
ULONG pstack
)
{
OS2_API_MSG m;
POS2_DISPATCH16_SIGNAL a = &m.u.Dispatch16Signal;
if (usFlagNum > 2) {
return(ERROR_INVALID_FLAG_NUMBER);
}
if (pid == 0 || pid == 0xffff) {
return(ERROR_INVALID_FUNCTION);
}
if (fScope != FLGP_SUBTREE && fScope != FLGP_PID) {
return(ERROR_INVALID_FUNCTION);
}
if ((ULONG) Od2Process->Pib.ProcessId == pid
&& Od2CurrentThreadId() == 1) {
Od2JumpTo16SignalDispatch(SigHandlerRec.sighandler[usFlagNum +
SIG_PFLG_A - 1],
pstack,
usFlagNum + SIG_PFLG_A,
usFlagArg);
return(NO_ERROR);
}
a->usFlagNum = (USHORT) (usFlagNum + SIG_PFLG_A);
a->usFlagArg = (USHORT) usFlagArg;
a->fscope = fScope;
a->pidProcess = (ULONG) pid;
a->routine = (ULONG) _Od2ProcessSignal16;
a->sighandleraddr = (ULONG) &SigHandlerRec;
if (Od2CallSubsystem( &m,
NULL,
Os2Dispatch16Signal,
sizeof( *a )
)) {
return( m.ReturnedErrorValue );
}
return(NO_ERROR);
}
APIRET
DosHoldSignal(
ULONG fDisable,
ULONG pstack
)
{
OS2_API_MSG m;
POS2_DISPATCH16_SIGNAL a = &m.u.Dispatch16Signal;
ULONG i;
UNREFERENCED_PARAMETER(pstack);
if (fDisable == HLDSIG_DISABLE) {
SigHandlerRec.fholdenable++;
return NO_ERROR;
}
if (fDisable == HLDSIG_ENABLE && SigHandlerRec.fholdenable > 0) {
SigHandlerRec.fholdenable--;
if (SigHandlerRec.fholdenable == 0) {
for (i = 0; i < 7; ++i) {
if (SigHandlerRec.outstandingsig[i].sighandleraddr != 0) {
a->usFlagNum = HOLD_SIGNAL_CLEARED;
a->usFlagArg = (USHORT) (i + 1);
a->fscope = 0;
a->pidProcess = (ULONG) Od2Process->Pib.ProcessId;
a->routine = (ULONG) _Od2ProcessSignal16;
a->sighandleraddr = (ULONG) &SigHandlerRec;
Od2CallSubsystem( &m,
NULL,
Os2Dispatch16Signal,
sizeof( *a ));
}
}
}
return NO_ERROR;
}
else {
return ERROR_INVALID_FUNCTION;
}
}
APIRET
DosSendSignal(
ULONG idProcess,
ULONG usSigNumber,
ULONG pstack
)
{
OS2_API_MSG m;
POS2_DISPATCH16_SIGNAL a = &m.u.Dispatch16Signal;
UNREFERENCED_PARAMETER(pstack);
if (usSigNumber != SIG_CTRLC && usSigNumber != SIG_CTRLBREAK)
return(ERROR_INVALID_FLAG_NUMBER);
a->usFlagNum = (USHORT) usSigNumber;
a->usFlagArg = 0;
a->fscope = 0;
a->pidProcess = (ULONG) idProcess;
a->routine = (ULONG) _Od2ProcessSignal16;
a->sighandleraddr = (ULONG) &SigHandlerRec;
if (Od2CallSubsystem( &m,
NULL,
Os2Dispatch16Signal,
sizeof( *a )
)) {
return( m.ReturnedErrorValue );
}
return (NO_ERROR);
}
APIRET
DosSetSigHandler( PFNSIGHANDLER pfnSigHandler,
PFNSIGHANDLER *pfnPrev,
PUSHORT pfAction,
ULONG fAction,
ULONG usSigNum
)
{
OS2_API_MSG m;
ULONG address;
POS2_REGISTER_HANDLER b = &m.u.DosRegisterCtrlHandler;
POS2_DISPATCH16_SIGNAL a = &m.u.Dispatch16Signal;
if (usSigNum < SIG_CTRLC || usSigNum >= SIG_CSIGNALS) {
return ERROR_INVALID_SIGNAL_NUMBER;
}
if (usSigNum == SIG_BROKENPIPE && fAction != SIGA_ACKNOWLEDGE) {
return ERROR_INVALID_SIGNAL_NUMBER;
}
if (fAction > SIGA_ACKNOWLEDGE || usSigNum >= SIG_CSIGNALS) {
return ERROR_INVALID_SIGNAL_NUMBER;
}
// if (!LDRIsLDTValid(((FLATTOSEL((ULONG) pfnSigHandler) | 4 | 3)))) {
// return ERROR_INVALID_STARTING_RING;
// }
//
// Check if signal outstanding if so the next command from the user
// has to be an acknowledge
//
if (SigHandlerRec.action[usSigNum - 1] == SIGA_ACKNOWLEDGE &&
fAction != SIGA_ACKNOWLEDGE) {
return ERROR_SIGNAL_PENDING;
}
//
// If signal is acknowledge check to see if a signal is pending,
// process the pending signal then set to clear pending. This must be
// done while signal is being processed to permit the signal to be
// used again.
//
if (fAction == SIGA_ACKNOWLEDGE) {
if (SigHandlerRec.outstandingsig[usSigNum - 1].sighandleraddr != 0) {
SigHandlerRec.action[usSigNum - 1] = SIGA_ACKNOWLEDGE_AND_ACCEPT;
a->usFlagNum = HOLD_SIGNAL_CLEARED;
a->usFlagArg = (USHORT) usSigNum;
a->fscope = 0;
a->pidProcess = (ULONG) Od2Process->Pib.ProcessId;
a->routine = (ULONG) _Od2ProcessSignal16;
a->sighandleraddr = (ULONG) &SigHandlerRec;
Od2CallSubsystem( &m,
NULL,
Os2Dispatch16Signal,
sizeof( *a ));
return NO_ERROR;
}
SigHandlerRec.action[usSigNum - 1] = SIGA_ACCEPT;
return NO_ERROR;
}
if (pfnSigHandler == 0 && fAction != SIGA_IGNORE) {
//
// means set default handling
//
fAction = SIGA_KILL;
}
//
// Check to see if we should remove the signal
//
if (fAction == SIGA_KILL) {
//
// Reinstall default handler, same as done in \loader\loader.c
//
address = SigHandlerRec.doscallssel;
switch (usSigNum) {
case SIG_CTRLC:
SigHandlerRec.sighandler[SIG_CTRLC - 1] = (ULONG)
(address | ThunkOffsetExitProcessStub);
SigHandlerRec.action[SIG_CTRLC - 1] = SIGA_ACCEPT;
break;
case SIG_BROKENPIPE:
SigHandlerRec.sighandler[SIG_BROKENPIPE - 1] = (ULONG)
(address | ThunkOffsetDosReturn);
SigHandlerRec.action[SIG_BROKENPIPE - 1] = SIGA_IGNORE;
break;
case SIG_KILLPROCESS:
SigHandlerRec.sighandler[SIG_KILLPROCESS - 1] = (ULONG)
(address | ThunkOffsetExitProcessStub);
SigHandlerRec.action[SIG_KILLPROCESS - 1] = SIGA_ACCEPT;
break;
case SIG_CTRLBREAK:
SigHandlerRec.sighandler[SIG_CTRLBREAK - 1] = (ULONG)
(address | ThunkOffsetExitProcessStub);
SigHandlerRec.action[SIG_CTRLBREAK - 1] = SIGA_ACCEPT;
break;
case SIG_PFLG_A:
SigHandlerRec.sighandler[SIG_PFLG_A - 1] = (ULONG)
(address | ThunkOffsetDosReturn);
SigHandlerRec.action[SIG_PFLG_A - 1] = SIGA_ACCEPT;
break;
case SIG_PFLG_B:
SigHandlerRec.sighandler[SIG_PFLG_B - 1] = (ULONG)
(address | ThunkOffsetDosReturn);
SigHandlerRec.action[SIG_PFLG_B - 1] = SIGA_ACCEPT;
break;
case SIG_PFLG_C:
SigHandlerRec.sighandler[SIG_PFLG_C - 1] = (ULONG)
(address | ThunkOffsetDosReturn);
SigHandlerRec.action[SIG_PFLG_C - 1] = SIGA_ACCEPT;
break;
}
if (usSigNum == SIG_CTRLC || usSigNum == SIG_KILLPROCESS ||
usSigNum == SIG_CTRLBREAK) {
b->usFlagNum = usSigNum;
b->fAction = SIGA_KILL;
Od2CallSubsystem(&m,
NULL,
Os2RegisterCtrlHandler,
sizeof( *b ));
}
return NO_ERROR;
}
try {
if (pfnPrev != NULL) {
*pfnPrev = (PFNSIGHANDLER) SigHandlerRec.sighandler[usSigNum - 1];
}
if (pfAction != NULL) {
*pfAction = SigHandlerRec.action[usSigNum - 1];
}
}
except( EXCEPTION_EXECUTE_HANDLER ) {
return ERROR_INVALID_FUNCTION;
}
if (pfnSigHandler) {
//
// fAction is SIGA_IGNORE
//
SigHandlerRec.sighandler[usSigNum - 1] = (ULONG)(FLATTOFARPTR((ULONG)pfnSigHandler));
}
SigHandlerRec.action[usSigNum - 1] = (USHORT) fAction;
if (usSigNum == SIG_CTRLC || usSigNum == SIG_KILLPROCESS ||
usSigNum == SIG_CTRLBREAK) {
b->usFlagNum = usSigNum;
if (fAction == SIGA_IGNORE)
b->fAction = SIGA_IGNORE;
else
b->fAction = SIGA_ACCEPT;
Od2CallSubsystem(&m,
NULL,
Os2RegisterCtrlHandler,
sizeof( *b ));
}
return NO_ERROR;
}
VOID
Od2ProcessSignal16 (
IN ULONG rEax, // The value of EAX during interrupt. It will be useful
// if this is the return code of any wait. The value of
// EAX was set after that the context was read.
IN POS2_REGISTER16_SIGNAL pa
)
{
CONTEXT Context;
PCONTEXT pContext;
ULONG size;
ULONG address;
ULONG signum;
NTSTATUS Status;
OD2_CONTEXT_SAVE_AREA SaveArea;
pContext = (PCONTEXT) ((PCHAR) pa + sizeof(OS2_REGISTER16_SIGNAL));
Od2PrepareEnterToSignalHandler(pContext, &SaveArea);
Od2Process->Pib.SignalWasntDelivered = FALSE;
signum = pa->usFlagNum;
//
// Since the signal handler routine can not run on stack of the
// process which called DosFlagProcess get stack from process
// context and run on that. But check to see where the program
// was excuting, if the CS is = 0x1b "Flat CS" then it was in the client
// or server. So restore registers from pointer to 16-bit stack
// saved at thunk entry.
//
pContext->Eax = rEax; // Set the right value of EAX to the saved context
//
// Copy context of process we stopped on to stack so we can free the
// memory later which was allocated in the other process to pass the
// context
//
RtlMoveMemory(&Context, pContext, sizeof(Context));
if (SigHandlerRec.signature == 0xdead) {
Od2MakeSignalHandlerContext(pa);
if (SigHandlerRec.sighandler[signum - 1] != 0 ) {
Od2JumpTo16SignalDispatch(SigHandlerRec.sighandler[signum - 1],
(ULONG) pa,
signum,
(ULONG) pa->usFlagArg);
}
}
size = 0;
address = (ULONG) pa;
Status = NtFreeVirtualMemory(NtCurrentProcess(),
(PVOID *) &address,
&size,
MEM_RELEASE);
ASSERT(NT_SUCCESS(Status));
Od2ExitFromSignalHandler(&Context, &SaveArea);
}
APIRET
DosSetVec(
ULONG usVecNum,
PFN pfnFun,
PFN* ppfnPrev
)
{
ULONG index;
PFN fn;
try {
fn = *ppfnPrev;
fn = pfnFun;
}
except( EXCEPTION_EXECUTE_HANDLER ) {
Od2ExitGP();
}
switch (usVecNum) {
case VECTOR_DIVIDE_BY_ZERO:
index = 0;
break;
case VECTOR_OVERFLOW:
index = 1;
break;
case VECTOR_OUTOFBOUNDS:
index = 2;
break;
case VECTOR_INVALIDOPCODE:
index = 3;
break;
case VECTOR_NO_EXTENSION:
index = 4;
break;
case VECTOR_EXTENSION_ERROR:
index = 5;
break;
default:
return ERROR_INVALID_FUNCTION;
}
if (fn == 0) {
if (pVecHandlerRec->VecHandler[index] ==
(ULONG) (pVecHandlerRec->doscallssel | ThunkOffsetDosReturn)) {
*ppfnPrev = 0;
}
else {
*ppfnPrev = (PFN) pVecHandlerRec->VecHandler[index];
}
pVecHandlerRec->VecHandler[index] =
(ULONG) (pVecHandlerRec->doscallssel | ThunkOffsetDosReturn);
}
else {
if (pVecHandlerRec->VecHandler[index] ==
(ULONG) (pVecHandlerRec->doscallssel | ThunkOffsetDosReturn)) {
*ppfnPrev = 0;
}
else {
*ppfnPrev = (PFN) pVecHandlerRec->VecHandler[index];
}
pVecHandlerRec->VecHandler[index] = (ULONG)(FLATTOFARPTR((ULONG)(pfnFun)));
}
return NO_ERROR;
}
VOID
Od2EnableCtrlHandling()
{
OS2_API_MSG m;
POS2_REGISTER_HANDLER b = &m.u.DosRegisterCtrlHandler;
b->usFlagNum = 0;
b->fAction = SIGA_ENABLE_HANDLING;
Od2CallSubsystem(&m,
NULL,
Os2RegisterCtrlHandler,
sizeof( *b ));
}