mirror of https://github.com/lianthony/NT4.0
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.
508 lines
11 KiB
508 lines
11 KiB
/*++
|
|
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
dllxcpt.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the OS/2 V2.0 exception handling API calls
|
|
|
|
Author:
|
|
|
|
Therese Stowell (thereses) 10-June-1990
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#define INCL_OS2V20_MEMORY
|
|
#define INCL_OS2V20_ERRORS
|
|
#define INCL_OS2V20_TASKING
|
|
#define INCL_OS2V20_EXCEPTIONS
|
|
|
|
#include "os2dll.h"
|
|
#include "os2dll16.h"
|
|
#ifdef MIPS
|
|
#define CONDITION_HANDLING 0
|
|
#endif
|
|
|
|
extern OD2_SIG_HANDLER_REC SigHandlerRec;
|
|
extern ULONG Od2Saved16Stack;
|
|
extern PVOID __cdecl Od2JumpTo16SignalDispatch(ULONG address, ULONG regs,
|
|
ULONG usFlagNum, ULONG usFlagArg);
|
|
|
|
VOID
|
|
Od2PrepareEnterToSignalHandler(
|
|
PCONTEXT Context,
|
|
POD2_CONTEXT_SAVE_AREA pSaveArea
|
|
);
|
|
VOID
|
|
Od2ExitFromSignalHandler(
|
|
PCONTEXT Context,
|
|
POD2_CONTEXT_SAVE_AREA pSaveArea
|
|
);
|
|
|
|
VOID
|
|
Od2MakeSignalHandlerContext(
|
|
POS2_REGISTER16_SIGNAL pContext16
|
|
);
|
|
|
|
APIRET
|
|
DosSetSigHandler( PFNSIGHANDLER pfnSigHandler,
|
|
PFNSIGHANDLER *pfnPrev,
|
|
PUSHORT pfAction,
|
|
ULONG fAction,
|
|
ULONG usSigNum
|
|
);
|
|
|
|
APIRET
|
|
DosEnterMustComplete(
|
|
OUT PULONG NestingLevel
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine implements the DosEnterMustComplete API.
|
|
|
|
Arguments:
|
|
|
|
NestingLevel - the number of times DosEnterMustComplete has been
|
|
called minus the number of times DosExitMustComplete has been called.
|
|
|
|
Return Value:
|
|
|
|
ERROR_INVALID_PARAMETER - a parameter contains an invalid pointer.
|
|
|
|
--*/
|
|
|
|
{
|
|
OS2_API_MSG m;
|
|
POS2_DOSENTERMUSTCOMPLETE_MSG a = &m.u.DosEnterMustComplete;
|
|
|
|
try {
|
|
*NestingLevel = 0;
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
Od2CallSubsystem( &m, NULL, Os2EnterMustComplete, sizeof( *a ) );
|
|
if (m.ReturnedErrorValue != NO_ERROR) {
|
|
return m.ReturnedErrorValue;
|
|
}
|
|
*NestingLevel = a->NestingLevel;
|
|
return NO_ERROR;
|
|
}
|
|
|
|
APIRET
|
|
DosExitMustComplete(
|
|
OUT PULONG NestingLevel
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine implements the DosExitMustComplete API.
|
|
|
|
Arguments:
|
|
|
|
NestingLevel - the number of times DosEnterMustComplete has been
|
|
called minus the number of times DosExitMustComplete has been called.
|
|
|
|
Return Value:
|
|
|
|
ERROR_INVALID_PARAMETER - a parameter contains an invalid pointer.
|
|
|
|
--*/
|
|
|
|
{
|
|
OS2_API_MSG m;
|
|
POS2_DOSEXITMUSTCOMPLETE_MSG a = &m.u.DosExitMustComplete;
|
|
|
|
try {
|
|
*NestingLevel = 0;
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
Od2CallSubsystem( &m, NULL, Os2ExitMustComplete, sizeof( *a ) );
|
|
if (m.ReturnedErrorValue != NO_ERROR) {
|
|
return m.ReturnedErrorValue;
|
|
}
|
|
*NestingLevel = a->NestingLevel;
|
|
return NO_ERROR;
|
|
}
|
|
|
|
APIRET
|
|
DosRaiseException(
|
|
IN PEXCEPTIONREPORTRECORD ExceptionReportRecord
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine implements the DosRaiseException API.
|
|
|
|
Arguments:
|
|
|
|
ExceptionReportRecord - the exception to generate
|
|
|
|
Return Value:
|
|
|
|
ERROR_INVALID_PARAMETER - a parameter contains an invalid pointer.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// probe exception record
|
|
//
|
|
|
|
try {
|
|
Od2ProbeForRead(ExceptionReportRecord,
|
|
FIELD_OFFSET(EXCEPTIONREPORTRECORD,ExceptionInfo) +
|
|
(ExceptionReportRecord->cParameters * sizeof(ULONG)),
|
|
4);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
//
|
|
// raise exception
|
|
//
|
|
|
|
#if CONDITION_HANDLING
|
|
RtlRaiseException((PEXCEPTION_RECORD) ExceptionReportRecord);
|
|
#endif
|
|
return NO_ERROR;
|
|
}
|
|
|
|
APIRET
|
|
DosUnwindException(
|
|
IN PEXCEPTIONREGISTRATIONRECORD ExceptionHandler,
|
|
IN PVOID TargetIP,
|
|
IN PEXCEPTIONREPORTRECORD ExceptionReportRecord
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine implements the DosUnwindException API.
|
|
|
|
Arguments:
|
|
|
|
ExceptionHandler - call frame that is target of the unwind
|
|
|
|
TargetIP - continuation address
|
|
|
|
ExceptionReportRecord - the exception record to pass to handlers during
|
|
unwind.
|
|
|
|
Return Value:
|
|
|
|
ERROR_INVALID_PARAMETER - a parameter contains an invalid pointer.
|
|
|
|
--*/
|
|
|
|
{
|
|
#if DBG
|
|
IF_OD2_DEBUG( EXCEPTIONS ) {
|
|
DbgPrint("entering DosUnwindException\n");
|
|
}
|
|
#endif
|
|
//
|
|
// probe exception record
|
|
//
|
|
|
|
try {
|
|
Od2ProbeForRead(ExceptionReportRecord,
|
|
FIELD_OFFSET(EXCEPTIONREPORTRECORD,ExceptionInfo) +
|
|
(ExceptionReportRecord->cParameters * sizeof(ULONG)),
|
|
4);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
//
|
|
// raise exception
|
|
//
|
|
|
|
#if CONDITION_HANDLING
|
|
|
|
RtlUnwind(ExceptionHandler,
|
|
TargetIP,
|
|
(PEXCEPTION_RECORD) ExceptionReportRecord, 0);
|
|
|
|
#endif
|
|
|
|
#if DBG
|
|
IF_OD2_DEBUG( EXCEPTIONS ) {
|
|
DbgPrint("leaving DosUnwindException\n");
|
|
}
|
|
#endif
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
APIRET
|
|
Od2AcknowledgeSignalException(
|
|
IN ULONG SignalNumber
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine calls the server to acknowledge a signal exception.
|
|
|
|
Arguments:
|
|
|
|
SignalNumber - number of signal to acknowledge
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
OS2_API_MSG m;
|
|
POS2_DOSACKNOWLEDGESIGNALEXCEPTION_MSG a = &m.u.DosAcknowledgeSignalException;
|
|
a->SignalNumber = SignalNumber;
|
|
Od2CallSubsystem( &m, NULL, Os2AcknowledgeSignalException, sizeof( *a ) );
|
|
return m.ReturnedErrorValue;
|
|
}
|
|
|
|
APIRET
|
|
DosAcknowledgeSignalException(
|
|
IN ULONG SignalNumber
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine acknowledges a signal exception.
|
|
|
|
Arguments:
|
|
|
|
SignalNumber - number of signal to acknowledge
|
|
|
|
Return Value:
|
|
|
|
ERROR_INVALID_SIGNAL_NUMBER - an invalid signal number was specified
|
|
|
|
--*/
|
|
|
|
{
|
|
switch (SignalNumber) {
|
|
case XCPT_SIGNAL_INTR:
|
|
case XCPT_SIGNAL_KILLPROC:
|
|
case XCPT_SIGNAL_BREAK:
|
|
return Od2AcknowledgeSignalException(SignalNumber);
|
|
break;
|
|
|
|
default:
|
|
return(ERROR_INVALID_SIGNAL_NUMBER);
|
|
}
|
|
}
|
|
|
|
APIRET
|
|
DosSetSignalExceptionFocus(
|
|
IN BOOL32 Flag,
|
|
OUT PULONG NestingLevel
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine specifies that a particular process should or should not
|
|
receive signals.
|
|
|
|
Arguments:
|
|
|
|
Flag - whet
|
|
|
|
NestingLevel - the number of times this API has been called with
|
|
Flag == set
|
|
called minus the number of times DosExitMustComplete has been called.
|
|
|
|
Return Value:
|
|
|
|
ERROR_INVALID_SIGNAL_NUMBER - an invalid signal number was specified
|
|
|
|
--*/
|
|
|
|
{
|
|
OS2_API_MSG m;
|
|
POS2_DOSSETSIGNALEXCEPTIONFOCUS_MSG a = &m.u.DosSetSignalExceptionFocus;
|
|
|
|
try {
|
|
*NestingLevel = 0;
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
if (Flag > SIG_SETFOCUS) {
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
a->Flag = Flag;
|
|
Od2CallSubsystem( &m, NULL, Os2SetSignalExceptionFocus, sizeof( *a ) );
|
|
if (m.ReturnedErrorValue != NO_ERROR) {
|
|
return m.ReturnedErrorValue;
|
|
}
|
|
*NestingLevel = a->NestingLevel;
|
|
return(NO_ERROR);
|
|
|
|
}
|
|
|
|
APIRET
|
|
DosSendSignalException(
|
|
IN PID ProcessId,
|
|
IN ULONG Exception
|
|
)
|
|
{
|
|
OS2_API_MSG m;
|
|
POS2_DOSSENDSIGNALEXCEPTION_MSG a = &m.u.DosSendSignalException;
|
|
|
|
switch (Exception) {
|
|
case XCPT_SIGNAL_INTR:
|
|
case XCPT_SIGNAL_BREAK:
|
|
|
|
a->Exception = Exception;
|
|
a->ProcessId = ProcessId;
|
|
Od2CallSubsystem( &m, NULL, Os2SendSignalException, sizeof( *a ) );
|
|
return m.ReturnedErrorValue;
|
|
break;
|
|
|
|
default:
|
|
return(ERROR_INVALID_FUNCTION);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
Od2RaiseStackException( VOID )
|
|
{
|
|
EXCEPTION_RECORD ExceptionRecord;
|
|
|
|
ExceptionRecord.ExceptionFlags = 0;
|
|
ExceptionRecord.ExceptionCode = XCPT_UNABLE_TO_GROW_STACK;
|
|
ExceptionRecord.ExceptionRecord = (PEXCEPTION_RECORD) NULL;
|
|
ExceptionRecord.NumberParameters = 0;
|
|
#if CONDITION_HANDLING
|
|
RtlRaiseException(&ExceptionRecord);
|
|
#endif
|
|
}
|
|
|
|
VOID
|
|
Od2SignalDeliverer (
|
|
IN PCONTEXT pContext,
|
|
IN int Signal
|
|
)
|
|
{
|
|
OS2_REGISTER16_SIGNAL stack;
|
|
ULONG sig;
|
|
NTSTATUS Status;
|
|
OD2_CONTEXT_SAVE_AREA SaveArea;
|
|
|
|
Od2PrepareEnterToSignalHandler(pContext, &SaveArea);
|
|
|
|
#if DBG
|
|
IF_OD2_DEBUG( EXCEPTIONS ) {
|
|
DbgPrint("[%d]entering Od2SignalDeliverer with Signal %ld\n",
|
|
Od2Process->Pib.ProcessId,
|
|
Signal);
|
|
}
|
|
#endif
|
|
|
|
switch (Signal) {
|
|
|
|
case XCPT_SIGNAL_INTR:
|
|
sig = SIG_CTRLC;
|
|
break;
|
|
case XCPT_SIGNAL_KILLPROC:
|
|
sig = SIG_KILLPROCESS;
|
|
break;
|
|
case XCPT_SIGNAL_BREAK:
|
|
sig = SIG_CTRLBREAK;
|
|
break;
|
|
default:
|
|
#if DBG
|
|
DbgPrint("OS2: Od2SignalDeliverer() received unexpected signal %d\n", Signal);
|
|
ASSERT(FALSE);
|
|
#endif // DBG
|
|
Od2Process->Pib.SignalWasntDelivered = FALSE;
|
|
Od2ExitFromSignalHandler(pContext, &SaveArea);
|
|
}
|
|
|
|
if (SigHandlerRec.sighandler[sig - 1] !=
|
|
(SigHandlerRec.doscallssel | ThunkOffsetExitProcessStub)) {
|
|
//
|
|
// If previous signal has not been acknowledged
|
|
// Or if the flag to hold signals to this process is enabled
|
|
//
|
|
//
|
|
// Since we can not return error back to caller don't hold
|
|
// unacknowledged signals
|
|
//
|
|
if (SigHandlerRec.signature != 0xdead) {
|
|
//
|
|
// Not ready yet for signal handling, let the loader complete
|
|
// loading
|
|
//
|
|
DosExit(0, 0);
|
|
}
|
|
}
|
|
|
|
if (SigHandlerRec.action[sig - 1] == SIGA_ACKNOWLEDGE ||
|
|
SigHandlerRec.fholdenable) {
|
|
//
|
|
// See if we already are holding an unacknowleged signal or a hold
|
|
// signal
|
|
//
|
|
if (SigHandlerRec.outstandingsig[sig - 1].sighandleraddr != 0) {
|
|
Od2Process->Pib.SignalWasntDelivered = FALSE;
|
|
Od2ExitFromSignalHandler(pContext, &SaveArea);
|
|
}
|
|
//
|
|
// Save this signal till other is processed
|
|
//
|
|
SigHandlerRec.outstandingsig[sig - 1].usFlagNum = (USHORT) sig;
|
|
SigHandlerRec.outstandingsig[sig - 1].usFlagArg = 0;
|
|
SigHandlerRec.outstandingsig[sig - 1].pidProcess =
|
|
(ULONG) Od2Process->Pib.ProcessId;
|
|
SigHandlerRec.outstandingsig[sig - 1].routine =
|
|
(ULONG) _Od2ProcessSignal16;
|
|
SigHandlerRec.outstandingsig[sig - 1].sighandleraddr =
|
|
(ULONG) &SigHandlerRec;
|
|
Od2Process->Pib.SignalWasntDelivered = FALSE;
|
|
Od2ExitFromSignalHandler(pContext, &SaveArea);
|
|
}
|
|
|
|
//
|
|
// Disable this signal till we get a SIGA_ACKNOWLEDGE
|
|
//
|
|
SigHandlerRec.action[sig - 1] = SIGA_ACKNOWLEDGE;
|
|
|
|
Od2Process->Pib.SignalWasntDelivered = FALSE;
|
|
Od2MakeSignalHandlerContext(&stack);
|
|
|
|
stack.usFlagNum = (USHORT)sig;
|
|
stack.usFlagArg = 0;
|
|
|
|
Od2JumpTo16SignalDispatch(SigHandlerRec.sighandler[sig - 1],
|
|
(ULONG) &stack,
|
|
sig,
|
|
0);
|
|
#if DBG
|
|
DbgPrint("Os2: after execution of 16bit signal\n");
|
|
#endif
|
|
Od2ExitFromSignalHandler(pContext, &SaveArea);
|
|
ASSERT(FALSE);
|
|
}
|