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.
 
 
 
 
 
 

282 lines
5.6 KiB

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
winexcpt.cxx
Abstract:
Provides RPC exception handling support for Windows 3.x
Author:
Steven Zeck (stevez) 4/16/92
--*/
#include "sysinc.h"
#include "rpc.h"
#undef NULL
#include "windows.h"
#include "rpcwin.h"
// For windows, the DLL data segment is shared amoung all processes
// we must maintain an exception record for each task that is using
// this DLL. Each active exception context has an owner. When an
// exception context is needed it is located by an associated search
// of the exception table.
typedef struct {
HTASK Task;
pExceptionBuff CurrentContext;
} EXCEPTION, *PEXCEPTION;
PEXCEPTION ExceptTable;
int TableSize;
// This should be small to keep down the linear search times.
#define TABLE_INCREMENT 2
int
InitializeWinExceptions (
)
/*++
Routine Description:
Initializes the exception table.
Returns:
0 for success, 1 for failure due to out of memory.
--*/
{
TableSize += TABLE_INCREMENT;
if (!(ExceptTable = (PEXCEPTION)
LocalAlloc(LMEM_FIXED, sizeof(EXCEPTION) * TableSize)))
return(1);
memset(ExceptTable, 0, sizeof(EXCEPTION) * TableSize);
return(0);
}
static void
SearchForContext(
IN HTASK TaskSelf
)
/*++
Routine Description:
Do an associative search for an exception and bring it to the front
of the exception table.
Arguments:
TaskSelf - task that we are looking for
--*/
{
pExceptionBuff oldExcept;
int i;
// Scan the exception table for one owned by this task.
for (i = 0; i < TableSize && ExceptTable[i].Task != TaskSelf; i++) ;
// If there wasn't a prior exception record in the table,
// terminate the process.
if (i == TableSize)
{
MessageBox(0, "Application encountered unhandled exception.\n Application will be terminated.",
"Remote Procedure Call", MB_TASKMODAL | MB_OK | MB_ICONSTOP);
// Hammer the process dead, without all the windows cleanup.
_asm
{
mov ax, 4c01h
int 21h
};
}
// Now that we have table slot, swap it with the
// first slot so it is at the front of the list.
ExceptTable[i].Task = ExceptTable[0].Task;
ExceptTable[0].Task = TaskSelf;
oldExcept = ExceptTable[0].CurrentContext;
ExceptTable[0].CurrentContext = ExceptTable[i].CurrentContext;
ExceptTable[i].CurrentContext = oldExcept;
}
void CALLBACK
ExceptionCleanup(HTASK TaskSelf)
/*++
Routine Description:
Clean-up the exception record for the current task (if it's still
there). Called at task-exit time.
--*/
{
int i;
// Scan the exception table for one owned by this task.
for (i = 0; i < TableSize && ExceptTable[i].Task != TaskSelf; i++) ;
if (i < TableSize)
ExceptTable[i].Task = 0;
}
void PAPI * RPC_ENTRY
RpcSetExceptionHandler (
IN pExceptionBuff newhandler
)
/*++
Routine Description:
This function sets the exception context to a given value. Each
process has its own exception context which must be maintained.
New contexts are created on demand for processes.
Arguments:
newhandler - new context value to association with this process
Returns:
The old handler.
--*/
{
HTASK TaskSelf = GetCurrentTask();
pExceptionBuff oldExcept;
if (ExceptTable->Task != TaskSelf)
{
int i, iFree;
// Scan the exception table for one owned by this task.
for (i = 0, iFree = -1;
i < TableSize && ExceptTable[i].Task != TaskSelf; i++)
{
// Keep track of a free slot to make allocation faster
if (ExceptTable[i].Task == 0 && iFree == -1)
iFree = i;
}
// If there wasn't a prior exception record in the table,
// allocate a new one.
if (i == TableSize)
{
if ((i = iFree) == -1)
{
// We are out of table entries, grow the table
// to be bigger.
PEXCEPTION LastExceptTable = ExceptTable;
if (InitializeWinExceptions())
// Can't allocate memory - get a context that will fail.
SearchForContext((HTASK) -1);
memcpy(ExceptTable, LastExceptTable,
sizeof(EXCEPTION) * (TableSize-TABLE_INCREMENT));
LocalFree((HLOCAL) LastExceptTable);
i = TableSize-TABLE_INCREMENT;
}
// Register an exit-time handler for this task
WinDLLAtExit(ExceptionCleanup);
}
// Now that we have table slot, swap it with the
// first slot so it is at the front of the list.
ExceptTable[i].Task = ExceptTable[0].Task;
ExceptTable[0].Task = TaskSelf;
oldExcept = ExceptTable[0].CurrentContext;
ExceptTable[0].CurrentContext = ExceptTable[i].CurrentContext;
ExceptTable[i].CurrentContext = oldExcept;
}
oldExcept = ExceptTable->CurrentContext;
ExceptTable->CurrentContext = newhandler;
return (oldExcept);
}
void PAPI * RPC_ENTRY
RpcGetExceptionHandler (
)
/*++
Routine Description:
Get the current exception context for the current task.
Returns:
The exception record.
--*/
{
HTASK TaskSelf = GetCurrentTask();
if (ExceptTable->Task != TaskSelf)
SearchForContext(TaskSelf);
return(ExceptTable->CurrentContext);
}
void RPC_ENTRY
RpcLeaveException (
)
/*++
Routine Description:
Pop the exception stack one level. The back pointer to the previous
exception records becomes the current.
--*/
{
HTASK TaskSelf = GetCurrentTask();
if (ExceptTable->Task != TaskSelf)
SearchForContext(TaskSelf);
ExceptTable->CurrentContext = ExceptTable->CurrentContext->pExceptNext;
}