Major refactoring of the exception handling code + misc fixes:

- Fix/add prototypes for RtlCaptureContext, RtlDispatchException and RtlUnwind
	- Fix EXCEPTION_REGISTRATION_RECORD structure and PEXCEPTION_ROUTINE
	- Add w32api excpt.h (based on mingw) with PSDK compatibility fixes
	- Fix seriously broken User-Mode Ldr thunk and APC Callback prototypes
	- Fix KiUserExceptionDispatcher
	- Remove useless NTDLL entrypoint
	- Implement NTDLL Ki* callbacks in ASM
	- Implement RtlCaptureContext
	- Fix RtlRaiseException to handle cases when a user-mode debugger is present
	- Fix RtlRaiseStatus as above, plus set the exception address and capture context
	- Little cleanup of RTL headers
	- Implement RtlpGetStackLimits, RtlpGetExceptionList, RtlpSetExceptionList, RtlpGetExceptionAddress in ASM
	- Fix RtlDispatchException, add cases for exceptions in the DPC stack and validate the validity of the 
exception frames. Add support for exception logging by the global flag. Use TRAP_FRAME/EXCPETION_FRAME instead of 
Context.
	- Fix RtlUnwind logic, support cases where it's called with custom arguments instead of NULL.
	- Reimplement RtlpCaptureContext to work properly, convert exception handler calling functions to INTEL syntax 
and fix some bugs (like checking for the right unwind flag, clearing volatile register values, etc. Also use some 
optimizations to increase speed.
	- Modify some kernel functions (like KeContextToTrapFrame, KiDispatchException, KiInitializeUserApc, etc.) to 
support a PKEXCEPTION_FRAME for future PPC compatibility.
	- Reimplement RtlCaptureUnicodeString/FreeUnicodeString as inlined probe macros and optimize them.
	- Export ExRaiseStatus/Exception as Rtl*
	- Reimplement NtContinue to have more platform-independent code, and to protect and validate user-mode context 
and parameters with SEH.
	- Implement KiRaiseException, add SEH to all user-mode parameters and when copying data to the user-mode stack.
	- Fix KiInitializeUserApc to use KeTrapFrameToContext, to save the debug registers, not to deliver APCs during 
v86 mode, and to protect user-mode stack operations in SEH and probing. Also make it generate the proper stack for the 
user-mode callback. 
	- Implement KiUnexpectedInterrupt and KiCoprocessorError
	- Reimplement NtRaiseException in ASM to take advantage of optimizations due to the trap frame being in the 
stack when called through System call interface.
	- Fix Ntcontinue to respect AlertThread paramter
	- Fix some functiosn to return with KiServiceExit2 instead of KiServiceExit when required/needed
	- Fix KiDispatchException's logic, fix hacks when calling KeUserExceptionDispatcher, use correct context 
flags,...
	- Make NTDLL Ki* callbacks have SEH to protect them and return to kernel-mode with notification of any 
exceptions (the kernel-mode code to handle this isn't written yet though)

svn path=/trunk/; revision=17811
This commit is contained in:
Alex Ionescu 2005-09-11 22:32:20 +00:00
parent 801ad7223f
commit b9020b11dd
48 changed files with 1839 additions and 1345 deletions

View file

@ -144,6 +144,10 @@
#define CONTEXT_FLAGS 0x0
#define CONTEXT_DR6 0x14
#define CONTEXT_FLOAT_SAVE 0x1C
#define CONTEXT_SEGGS 0x8C
#define CONTEXT_SEGFS 0x90
#define CONTEXT_SEGES 0x94
#define CONTEXT_SEGDS 0x98
#define CONTEXT_EDI 0x9C
#define CONTEXT_ESI 0xA0
#define CONTEXT_EBX 0xA4
@ -152,21 +156,37 @@
#define CONTEXT_EAX 0xB0
#define CONTEXT_EBP 0xB4
#define CONTEXT_EIP 0xB8
#define CONTEXT_SEGCS 0xBC
#define CONTEXT_EFLAGS 0xC0
#define CONTEXT_ESP 0xC4
#define CONTEXT_SEGSS 0xC8
#define CONTEXT_FLOAT_SAVE_CONTROL_WORD CONTEXT_FLOAT_SAVE + FN_CONTROL_WORD
#define CONTEXT_FLOAT_SAVE_STATUS_WORD CONTEXT_FLOAT_SAVE + FN_STATUS_WORD
#define CONTEXT_FLOAT_SAVE_TAG_WORD CONTEXT_FLOAT_SAVE + FN_TAG_WORD
/* EXCEPTION_RECORD Constants */
#define EXCEPTION_RECORD_EXCEPTION_CODE 0x0
#define EXCEPTION_RECORD_EXCEPTION_FLAGS 0x4
#define EXCEPTION_RECORD_EXCEPTION_RECORD 0x8
#define EXCEPTION_RECORD_EXCEPTION_ADDRESS 0xC
#define EXCEPTION_RECORD_NUMBER_PARAMETERS 0x10
#define SIZEOF_EXCEPTION_RECORD 0x14
/* TEB CONSTANTS */
#define TEB_EXCEPTION_LIST 0x0
#define TEB_STACK_BASE 0x4
#define TEB_STACK_LIMIT 0x8
#define TEB_FIBER_DATA 0x10
#define TEB_PEB 0x30
#define TEB_EXCEPTION_CODE 0x1A4
#define TEB_ACTIVATION_CONTEXT_STACK_POINTER 0x1A8
#define TEB_DEALLOCATION_STACK 0xE0C
#define TEB_GUARANTEED_STACK_BYTES 0xF78
#define TEB_FLS_DATA 0xFB4
/* PEB CONSTANTS */
#define PEB_KERNEL_CALLBACK_TABLE 0x2C
/* FIBER CONSTANTS */
#define FIBER_PARAMETER 0x0
#define FIBER_EXCEPTION_LIST 0x4

View file

@ -11,7 +11,6 @@
/* C Standard Headers */
#include <stdarg.h>
#include <excpt.h>
/* Helper Header */
#include <helper.h>

View file

@ -37,6 +37,11 @@ RtlAssert(
PCHAR Message
);
NTSYSAPI
VOID
NTAPI
RtlCaptureContext(OUT PCONTEXT ContextRecord);
NTSYSAPI
PVOID
NTAPI
@ -47,6 +52,14 @@ PVOID
NTAPI
RtlDecodePointer(IN PVOID Pointer);
NTSYSAPI
BOOLEAN
NTAPI
RtlDispatchException(
IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context
);
NTSYSAPI
ULONG
NTAPI
@ -71,10 +84,10 @@ NTSYSAPI
VOID
NTAPI
RtlUnwind(
PEXCEPTION_REGISTRATION RegistrationFrame,
PVOID ReturnAddress,
PEXCEPTION_RECORD ExceptionRecord,
ULONG EaxValue
IN PVOID TargetFrame OPTIONAL,
IN PVOID TargetIp OPTIONAL,
IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL,
IN PVOID ReturnValue
);
/*

View file

@ -10,7 +10,6 @@
#define _RTLTYPES_H
/* DEPENDENCIES **************************************************************/
#include "excpt.h"
/* CONSTANTS *****************************************************************/
#define MAXIMUM_LEADBYTES 12
@ -27,6 +26,7 @@
#define PEB_BASE (0x7FFDF000)
#define EXCEPTION_CHAIN_END ((PEXCEPTION_REGISTRATION_RECORD)-1)
#define EXCEPTION_CONTINUE_SEARCH 0
#define EXCEPTION_EXECUTE_HANDLER 1
@ -292,11 +292,11 @@ typedef NTSTATUS
);
typedef EXCEPTION_DISPOSITION
(*PEXCEPTION_HANDLER)(
struct _EXCEPTION_RECORD*,
PVOID,
struct _CONTEXT*,
PVOID
(NTAPI *PEXCEPTION_ROUTINE)(
IN struct _EXCEPTION_RECORD *ExceptionRecord,
IN PVOID EstablisherFrame,
IN OUT struct _CONTEXT *ContextRecord,
IN OUT PVOID DispatcherContext
);
typedef LONG (NTAPI *PVECTORED_EXCEPTION_HANDLER)(
@ -634,16 +634,11 @@ typedef struct _MODULE_INFORMATION
} MODULE_INFORMATION, *PMODULE_INFORMATION;
/* END REVIEW AREA */
#ifdef _INC_EXCPT
typedef struct _EXCEPTION_REGISTRATION
typedef struct _EXCEPTION_REGISTRATION_RECORD
{
struct _EXCEPTION_REGISTRATION *prev;
PEXCEPTION_HANDLER handler;
} EXCEPTION_REGISTRATION, *PEXCEPTION_REGISTRATION;
#endif
typedef EXCEPTION_REGISTRATION EXCEPTION_REGISTRATION_RECORD;
typedef PEXCEPTION_REGISTRATION PEXCEPTION_REGISTRATION_RECORD;
struct _EXCEPTION_REGISTRATION_RECORD *Next;
PEXCEPTION_HANDLER Handler;
} EXCEPTION_REGISTRATION_RECORD, *PEXCEPTION_REGISTRATION_RECORD;
typedef struct _CURDIR
{

View file

@ -63,6 +63,12 @@
* -- AJ
*/
typedef struct _EXCEPTION_REGISTRATION_RECORD
{
struct _EXCEPTION_REGISTRATION_RECORD *prev;
PEXCEPTION_HANDLER handler;
} EXCEPTION_REGISTRATION_RECORD, *PEXCEPTION_REGISTRATION_RECORD;
/* Define this if you want to use your compiler built-in __try/__except support.
* This is only useful when compiling to a native Windows binary, as the built-in
* compiler exceptions will most certainly not work under Winelib.

View file

@ -1,11 +1,15 @@
#include "precomp.h"
#include <winternl.h>
#include <windows.h>
#define NTOS_MODE_USER
#include <ndk/umtypes.h>
#include <ndk/extypes.h>
#include <ndk/rtlfuncs.h>
/*
* @implemented
*/
void __cdecl
_global_unwind2(PEXCEPTION_REGISTRATION RegistrationFrame)
_global_unwind2(PEXCEPTION_REGISTRATION_RECORD RegistrationFrame)
{
#ifdef __GNUC__
RtlUnwind(RegistrationFrame, &&__ret_label, NULL, 0);
@ -17,14 +21,6 @@ __ret_label:
}
// This is dragged over from WINE:
typedef struct __EXCEPTION_FRAME
{
struct __EXCEPTION_FRAME *Prev;
PEXCEPTION_HANDLER Handler;
} EXCEPTION_FRAME, *PEXCEPTION_FRAME;
/* VC++ extensions to Win32 SEH */
typedef struct _SCOPETABLE
{
@ -35,8 +31,8 @@ typedef struct _SCOPETABLE
typedef struct _MSVCRT_EXCEPTION_FRAME
{
EXCEPTION_FRAME *prev;
void (*handler)(PEXCEPTION_RECORD, PEXCEPTION_FRAME,
PEXCEPTION_REGISTRATION_RECORD *prev;
void (*handler)(PEXCEPTION_RECORD, PEXCEPTION_REGISTRATION_RECORD,
PCONTEXT, PEXCEPTION_RECORD);
PSCOPETABLE scopetable;
int trylevel;

View file

@ -41,8 +41,11 @@
#include <ctype.h>
#include <internal/file.h>
#include <windows.h>
#define NTOS_MODE_USER
#include <ndk/ntndk.h>
#include <ndk/umtypes.h>
#include <ndk/extypes.h>
#include <ndk/rtlfuncs.h>
#define NDEBUG
#include <internal/debug.h>

View file

@ -31,7 +31,6 @@
#include "winreg.h"
#include "ntstatus.h"
#include "thread.h" /* FIXME: must be included before winternl.h */
#include "winternl.h"
#include "wine/debug.h"
#include "stackframe.h"
@ -127,10 +126,11 @@ BOOL WINAPI StackWalk(DWORD MachineType, HANDLE hProcess, HANDLE hThread,
/* cur_switch holds address of curr_stack's field in TEB in debuggee
* address space
*/
/*
if (NtQueryInformationThread(hThread, ThreadBasicInformation, &info,
sizeof(info), NULL) != STATUS_SUCCESS)
goto done_err;
curr_switch = (unsigned long)info.TebBaseAddress + FIELD_OFFSET(TEB, cur_stack);
curr_switch = (unsigned long)info.TebBaseAddress + FIELD_OFFSET(TEB, cur_stack); */
if (!f_read_mem(hProcess, (void*)curr_switch, &next_switch,
sizeof(next_switch), NULL))
{

View file

@ -23,7 +23,10 @@
#include <string.h>
#include <winnt.h>
#include <excpt.h>
#define NTOS_MODE_USER
#include <ndk/umtypes.h>
#include <ndk/extypes.h>
#include <ndk/rtlfuncs.h>
#define SELECTOROF(ptr) (HIWORD(ptr))
#define OFFSETOF(ptr) (LOWORD(ptr))
@ -77,23 +80,5 @@ return -1;
#define CURRENT_STACK16 ((STACK16FRAME*)MapSL(NtCurrentTeb()->cur_stack))
#define CURRENT_DS (CURRENT_STACK16->ds)
/* Push bytes on the 16-bit stack of a thread;
* return a segptr to the first pushed byte
*/
static inline SEGPTR stack16_push( int size )
{
STACK16FRAME *frame = CURRENT_STACK16;
memmove( (char*)frame - size, frame, sizeof(*frame) );
NtCurrentTeb()->cur_stack -= size;
return (SEGPTR)(NtCurrentTeb()->cur_stack + sizeof(*frame));
}
/* Pop bytes from the 16-bit stack of a thread */
static inline void stack16_pop( int size )
{
STACK16FRAME *frame = CURRENT_STACK16;
memmove( (char*)frame + size, frame, sizeof(*frame) );
NtCurrentTeb()->cur_stack += size;
}
#endif /* __WINE_STACKFRAME_H */

View file

@ -26,7 +26,6 @@
#include <winbase.h>
#include <winreg.h>
#define WINE_NO_TEB
#include <winternl.h>
#include <wine/windef16.h>
struct _SECURITY_ATTRIBUTES;
@ -42,114 +41,4 @@ struct debug_info
char output[1024]; /* current output line */
};
/* Thread exception block
flags in the comment:
1-- win95 field
d-- win95 debug version
-2- nt field
--3 wine special
--n wine unused
!-- or -!- likely or observed collision
more problems (collected from mailing list):
psapi.dll 0x10/0x30 (expects nt fields)
ie4 0x40
PESHiELD 0x23/0x30 (win95)
*/
#ifndef WINE_TEB_DEFINED
#define WINE_TEB_DEFINED
typedef struct _TEB
{
NT_TIB Tib; /* 12- 00 Thread information block */
PVOID EnvironmentPointer; /* 12- 1c EnvironmentPointer (win95: tib flags + win16 mutex count) */
CLIENT_ID ClientId; /* -2- 20 Process and thread id (win95: debug context) */
HQUEUE16 queue; /* 1!- 28 Message queue (NT: DWORD ActiveRpcHandle)*/
WORD pad1; /* --n 2a */
PVOID ThreadLocalStoragePointer; /* 1-- 2c Pointer to TLS array */
PEB *Peb; /* 12- 30 owning process PEB */
DWORD LastErrorValue; /* -2- 34 Last error code */
DWORD exit_code; /* 1-- 38 Termination status */
WORD teb_sel; /* 1-- 3c Selector to TEB */
WORD emu_sel; /* 1-n 3e 80387 emulator selector */
DWORD unknown1; /* --n 40 */
DWORD unknown2; /* --n 44 */
DWORD unknown3; /* --n 48 */
int thread_errno; /* --3 4c Per-thread errno (was: ring0_thread) */
int thread_h_errno; /* --3 50 Per-thread h_errno (was: ptr to tdbx structure) */
void *stack_base; /* 1-n 54 Stack base (unused) */
void *exit_stack; /* 1-n 58 Exit stack */
void *emu_data; /* --n 5c Related to 80387 emulation */
DWORD last_error; /* 1-- 60 Last error code */
HANDLE debug_cb; /* 1-n 64 Debugger context block */
DWORD debug_thread; /* 1-n 68 Thread debugging this one (?) */
void *pcontext; /* 1-n 6c Thread register context */
DWORD cur_stack; /* --3 70 Current stack (was: unknown) */
DWORD ThunkConnect; /* 1-n 74 */
DWORD NegStackBase; /* 1-n 78 */
WORD current_ss; /* 1-n 7c Another 16-bit stack selector */
WORD pad2; /* --n 7e */
void *ss_table; /* --n 80 Pointer to info about 16-bit stack */
WORD stack_sel; /* --3 84 16-bit stack selector */
HTASK16 htask16; /* --3 86 Win16 task handle */
DWORD pad4[15]; /* --n 88 */
ULONG CurrentLocale; /* -2- C4 */
DWORD pad5[48]; /* --n C8 */
DWORD delta_priority; /* 1-n 188 Priority delta */
DWORD unknown4[7]; /* d-n 18c Unknown */
void *create_data; /* d-n 1a8 Pointer to creation structure */
DWORD suspend_count; /* d-n 1ac SuspendThread() counter */
DWORD unknown5[6]; /* --n 1b0 Unknown */
DWORD sys_count[4]; /* --3 1c8 Syslevel mutex entry counters */
struct tagSYSLEVEL *sys_mutex[4]; /* --3 1d8 Syslevel mutex pointers */
DWORD unknown6[5]; /* --n 1e8 Unknown */
/* The following are Wine-specific fields (NT: GDI stuff) */
UINT code_page; /* --3 1fc Thread code page */
DWORD unused[2]; /* --3 200 Was server buffer */
DWORD gs_sel; /* --3 208 %gs selector for this thread */
int request_fd; /* --3 20c fd for sending server requests */
int reply_fd; /* --3 210 fd for receiving server replies */
int wait_fd[2]; /* --3 214 fd for sleeping server requests */
struct debug_info *debug_info; /* --3 21c Info for debugstr functions */
void *pthread_data; /* --3 220 Data for pthread emulation */
struct async_private *pending_list; /* --3 224 list of pending async operations */
void *driver_data; /* --3 228 Graphics driver private data */
DWORD dpmi_vif; /* --3 22c Protected mode virtual interrupt flag */
DWORD vm86_pending; /* --3 230 Data for vm86 mode */
void *vm86_ptr; /* --3 234 Data for vm86 mode */
/* here is plenty space for wine specific fields (don't forget to change pad6!!) */
/* the following are nt specific fields */
DWORD pad6[624]; /* --n 238 */
UNICODE_STRING StaticUnicodeString; /* -2- bf8 used by advapi32 */
WCHAR StaticUnicodeBuffer[261]; /* -2- c00 used by advapi32 */
PVOID DeallocationStack; /* -2- e0c Base of the stack */
LPVOID TlsSlots[64]; /* -2- e10 Thread local storage */
LIST_ENTRY TlsLinks; /* -2- f10 */
DWORD pad8[1]; /* --n f18 */
PVOID ReservedForNtRpc; /* -2- f1c used by rpcrt4 */
DWORD pad9[24]; /* --n f20 */
PVOID ReservedForOle; /* -2- f80 used by ole32 (IErrorInfo*) */
PVOID pad10[4]; /* --n f84 */
PVOID TlsExpansionSlots; /* -2- f94 */
} TEB;
#endif /* WINE_TEB_DEFINED */
/* The thread information for 16-bit threads */
/* NtCurrentTeb()->SubSystemTib points to this */
typedef struct
{
void *unknown; /* 00 unknown */
UNICODE_STRING *exe_name; /* 04 exe module name */
/* the following fields do not exist under Windows */
UNICODE_STRING exe_str; /* exe name string pointed to by exe_name */
CURDIR curdir; /* current directory */
WCHAR curdir_buffer[MAX_PATH];
} WIN16_SUBSYSTEM_TIB;
/* scheduler/thread.c */
extern TEB *THREAD_InitStack( TEB *teb, DWORD stack_size );
#endif /* __WINE_THREAD_H */

View file

@ -33,7 +33,7 @@ DbgUiRemoteBreakin@0
DbgUiWaitStateChange@8
DbgUserBreakPoint@0
KiRaiseUserExceptionDispatcher@0
KiUserApcDispatcher@20
KiUserApcDispatcher@16
KiUserCallbackDispatcher@12
KiUserExceptionDispatcher@8
LdrAccessResource@16

View file

@ -1,18 +0,0 @@
#include <roscfg.h>
.extern ___true_LdrInitializeThunk@16
.globl _LdrInitializeThunk@16
_LdrInitializeThunk@16:
#if defined(_M_IX86)
nop /* breakin overwrites this with "int 3" */
jmp ___true_LdrInitializeThunk@16
#elif defined(_M_ALPHA)
nop /* breakin overwrites this with "call_pal bpt" */
br ___true_LdrInitializeThunk@16
#elif defined(_M_MIPS)
nop /* breakin overwrites this with "break" */
j ___true_LdrInitializeThunk@16
#else
#error Unsupported architecture.
#endif

View file

@ -239,11 +239,11 @@ finish:
/* FUNCTIONS *****************************************************************/
VOID STDCALL
__true_LdrInitializeThunk (ULONG Unknown1,
ULONG Unknown2,
ULONG Unknown3,
ULONG Unknown4)
VOID
STDCALL
LdrpInit(PCONTEXT Context,
PVOID SystemArgument1,
PVOID SystemArgument2)
{
PIMAGE_NT_HEADERS NTHeaders;
PEPFUNC EntryPoint;
@ -256,7 +256,7 @@ __true_LdrInitializeThunk (ULONG Unknown1,
SYSTEM_BASIC_INFORMATION SystemInformation;
NTSTATUS Status;
DPRINT("LdrInitializeThunk()\n");
DPRINT("LdrpInit()\n");
if (NtCurrentPeb()->Ldr == NULL || NtCurrentPeb()->Ldr->Initialized == FALSE)
{
Peb = (PPEB)(PEB_BASE);

View file

@ -1,8 +1,9 @@
/* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* PURPOSE: User-mode APC support
* PROJECT: ReactOS NT Library
* FILE: lib/ntdll/main/dispatch.c
* PROGRAMER: David Welch <welch@cwcom.net>
* PURPOSE: User-Mode NT Dispatchers
* PROGRAMERS: Alex Ionescu (alex@relsoft.net)
* David Welch <welch@cwcom.net>
*/
/* INCLUDES *****************************************************************/
@ -11,77 +12,41 @@
#define NDEBUG
#include <debug.h>
typedef NTSTATUS (STDCALL *KERNEL_CALLBACK_FUNCTION)(PVOID Argument,
ULONG ArgumentLength);
typedef NTSTATUS (STDCALL *USER_CALL)(PVOID Argument, ULONG ArgumentLength);
EXCEPTION_DISPOSITION
RtlpExecuteVectoredExceptionHandlers(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context);
ULONG
RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context);
/* FUNCTIONS ****************************************************************/
/*
* @implemented
*/
VOID
STDCALL
KiUserApcDispatcher(PIO_APC_ROUTINE ApcRoutine,
PVOID ApcContext,
PIO_STATUS_BLOCK Iosb,
ULONG Reserved,
PCONTEXT Context)
{
/*
* Call the APC
*/
//DPRINT1("ITS ME\n");
ApcRoutine(ApcContext,
Iosb,
Reserved);
/*
* Switch back to the interrupted context
*/
//DPRINT1("switch back\n");
NtContinue(Context, 1);
}
/*
* @implemented
*/
VOID
STDCALL
KiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord,
PCONTEXT Context)
PCONTEXT Context)
{
EXCEPTION_RECORD NestedExceptionRecord;
NTSTATUS Status;
EXCEPTION_RECORD NestedExceptionRecord;
NTSTATUS Status;
if(RtlpExecuteVectoredExceptionHandlers(ExceptionRecord,
Context) != ExceptionContinueExecution)
/* Dispatch the exception and check the result */
if(RtlDispatchException(ExceptionRecord, Context))
{
Status = NtContinue(Context, FALSE);
/* Continue executing */
Status = NtContinue(Context, FALSE);
}
else
else
{
if(RtlpDispatchException(ExceptionRecord, Context) != ExceptionContinueExecution)
{
Status = NtContinue(Context, FALSE);
}
else
{
Status = NtRaiseException(ExceptionRecord, Context, FALSE);
}
/* Raise an exception */
Status = NtRaiseException(ExceptionRecord, Context, FALSE);
}
NestedExceptionRecord.ExceptionCode = Status;
NestedExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
NestedExceptionRecord.ExceptionRecord = ExceptionRecord;
NestedExceptionRecord.NumberParameters = Status;
/* Setup the Exception record */
NestedExceptionRecord.ExceptionCode = Status;
NestedExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
NestedExceptionRecord.ExceptionRecord = ExceptionRecord;
NestedExceptionRecord.NumberParameters = Status;
RtlRaiseException(&NestedExceptionRecord);
/* Raise the exception */
RtlRaiseException(&NestedExceptionRecord);
}
/*
@ -91,14 +56,16 @@ VOID
STDCALL
KiRaiseUserExceptionDispatcher(VOID)
{
EXCEPTION_RECORD ExceptionRecord;
EXCEPTION_RECORD ExceptionRecord;
ExceptionRecord.ExceptionCode = ((PTEB)NtCurrentTeb())->ExceptionCode;
ExceptionRecord.ExceptionFlags = 0;
ExceptionRecord.ExceptionRecord = NULL;
ExceptionRecord.NumberParameters = 0;
/* Setup the exception record */
ExceptionRecord.ExceptionCode = ((PTEB)NtCurrentTeb())->ExceptionCode;
ExceptionRecord.ExceptionFlags = 0;
ExceptionRecord.ExceptionRecord = NULL;
ExceptionRecord.NumberParameters = 0;
RtlRaiseException(&ExceptionRecord);
/* Raise the exception */
RtlRaiseException(&ExceptionRecord);
}
/*
@ -106,16 +73,13 @@ KiRaiseUserExceptionDispatcher(VOID)
*/
VOID
STDCALL
KiUserCallbackDispatcher(ULONG RoutineIndex,
PVOID Argument,
ULONG ArgumentLength)
KiUserCallbackDispatcher(ULONG Index,
PVOID Argument,
ULONG ArgumentLength)
{
PPEB Peb;
NTSTATUS Status;
KERNEL_CALLBACK_FUNCTION Callback;
Peb = NtCurrentPeb();
Callback = (KERNEL_CALLBACK_FUNCTION)Peb->KernelCallbackTable[RoutineIndex];
Status = Callback(Argument, ArgumentLength);
ZwCallbackReturn(NULL, 0, Status);
/* Return with the result of the callback function */
ZwCallbackReturn(NULL,
0,
((USER_CALL)(NtCurrentPeb()->KernelCallbackTable[Index]))
(Argument, ArgumentLength));
}

View file

@ -1,21 +0,0 @@
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/ntdll/main/dllmain.c
* PURPOSE:
* PROGRAMMER:
*/
#include <ntdll.h>
#define NDEBUG
#include <debug.h>
BOOL WINAPI DllMainCRTStartup(HINSTANCE hinstDll,
DWORD fdwReason,
LPVOID fImpLoad)
{
return TRUE;
}
/* EOF */

View file

@ -0,0 +1,186 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS NT Library
* FILE: lib/ntdll/main/i386/dispatch.S
* PURPOSE: User-Mode NT Dispatchers
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
*/
/* INCLUDES ******************************************************************/
#include <ndk/asm.h>
#include <ndk/i386/segment.h>
.intel_syntax noprefix
#define EXCEPTION_NONCONTINUABLE 1
#define EXCEPTION_UNWINDING 2
#define EXCEPTION_EXIT_UNWIND 4
#define EXCEPTION_UNWIND (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND)
#define STATUS_CALLBACK_POP_STACK 0xC0000423
#define ExceptionContinueSearch 1
/* FUNCTIONS ****************************************************************/
.globl _LdrInitializeThunk@16
_LdrInitializeThunk@16:
/* Get the APC Context */
lea eax, [esp+16]
/* Send it as the first parameter */
mov [esp+4], eax
/* Terminate the frame list */
xor ebp, ebp
/* Jump into the C initialization routine */
jmp _LdrpInit@12
.globl _KiUserExceptionApcHandler@16
_KiUserApcExceptionHandler@16:
/* Put the exception record in ECX and check the Flags */
mov ecx, [esp+4]
test dword ptr [ecx+EXCEPTION_RECORD_EXCEPTION_FLAGS], EXCEPTION_UNWIND
jz .return
/* Test alert the thread */
call _NtTestAlert@0
.return:
/* We'll continue */
mov eax, ExceptionContinueSearch
ret 16
.globl _KiUserApcDispatcher@16
_KiUserApcDispatcher@16:
/* Put the Context in EDI */
lea edi, [esp+16]
/* Get the ApcRoutine and call it */
pop eax
call eax
/* Switch back to the context */
push 1
push edi
call _ZwContinue@8
.globl _KiUserCallbackExceptionHandler@16
_KiUserCallbackExceptionHandler@16:
/* Put the exception record in ECX and check the Flags */
mov ecx, [esp+4]
test dword ptr [ecx+EXCEPTION_RECORD_EXCEPTION_FLAGS], EXCEPTION_UNWIND
jz return
/* Tell the kernel to invalidate the stack */
push STATUS_CALLBACK_POP_STACK
push 0
push 0
call _ZwCallbackReturn@12
return:
/* We'll continue */
mov eax, ExceptionContinueSearch
ret 16
.globl _KiUserCallbackDispatcher@12
_KiUserCallbackDispatcher@12:
/* Get the callback Index */
add esp, 4
pop edx
/* Get the callback table */
mov eax, [fs:TEB_PEB]
mov eax, [eax+PEB_KERNEL_CALLBACK_TABLE]
/* Call the routine */
call [eax+edx*4]
/* Return from callback */
push eax
push 0
push 0
call _ZwCallbackReturn@12
.globl _KiRaiseUserExceptionDispatcher@0
_KiRaiseUserExceptionDispatcher@0:
/* Setup stack for EXCEPTION_RECORD */
push ebp
mov ebp, esp
sub esp, SIZEOF_EXCEPTION_RECORD
/* Fill out the record */
mov eax, [fs:TEB_SELECTOR]
mov eax, [eax+TEB_EXCEPTION_CODE]
mov [esp+EXCEPTION_RECORD_EXCEPTION_CODE], eax
mov dword ptr [esp+EXCEPTION_RECORD_EXCEPTION_FLAGS], 0
mov dword ptr [esp+EXCEPTION_RECORD_EXCEPTION_RECORD], 0
mov dword ptr [esp+EXCEPTION_RECORD_NUMBER_PARAMETERS], 0
/* Raise the exception */
push esp
call _RtlRaiseException@4
/* Return exception code */
mov eax, [esp+EXCEPTION_RECORD_EXCEPTION_CODE]
mov esp, ebp
pop ebp
ret
.globl _KiUserExceptionDispatcher@8
_KiUserExceptionDispatcher@8:
/* Save the Context and Exception Records */
mov ecx, [esp+4]
mov ebx, [esp]
/* Dispatch the exception */
push ecx
push ebx
call _RtlDispatchException@8
/* Check for success */
or al, al
jz RaiseException
/* We're fine, continue execution */
push 0
push ecx
call _ZwContinue@8
/* Exit */
jmp Exit
RaiseException:
/* Pop off the records */
pop ebx
pop ecx
/* Raise the exception */
push 0
push ecx
push ebx
call _ZwRaiseException@12
Exit:
/* Allocate space for the nested exception record */
add esp, -SIZEOF_EXCEPTION_RECORD
/* Set it up */
mov [esp+EXCEPTION_RECORD_EXCEPTION_CODE], eax
mov dword ptr [esp+EXCEPTION_RECORD_EXCEPTION_FLAGS], EXCEPTION_NONCONTINUABLE
mov [esp+EXCEPTION_RECORD_EXCEPTION_RECORD], ebx
mov dword ptr [esp+EXCEPTION_RECORD_NUMBER_PARAMETERS], 0
/* Raise the exception */
push esp
call _RtlRaiseException@4
ret 8

View file

@ -24,14 +24,19 @@
<file>print.c</file>
</directory>
<directory name="ldr">
<file>entry.S</file>
<file>res.c</file>
<file>startup.c</file>
<file>utils.c</file>
</directory>
<directory name="main">
<file>dispatch.c</file>
<file>dllmain.c</file>
<if property="ARCH" value="i386">
<directory name="i386">
<file>dispatch.S</file>
</directory>
</if>
<ifnot property="ARCH" value="i386">
<file>dispatch.c</file>
</ifnot>
</directory>
<directory name="rtl">
<file>libsupp.c</file>

View file

@ -1,9 +1,10 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PROJECT: ReactOS NT User-Mode DLL
* FILE: lib/ntdll/rtl/libsup.c
* PURPOSE: Rtl library support routines
* PROGRAMMER: Gunnar Dalsnes
* PURPOSE: RTL Support Routines
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
* Gunnar Dalsnes
*/
/* INCLUDES *****************************************************************/
@ -14,6 +15,13 @@
/* FUNCTIONS ***************************************************************/
BOOLEAN
NTAPI
RtlpCheckForActiveDebugger(VOID)
{
return (NtCurrentPeb()->BeingDebugged);
}
KPROCESSOR_MODE
STDCALL
RtlpGetMode()
@ -28,7 +36,6 @@ RtlpCurrentPeb(VOID)
return NtCurrentPeb();
}
/*
* @implemented
*/
@ -39,7 +46,6 @@ RtlAcquirePebLock(VOID)
Peb->FastPebLockRoutine (Peb->FastPebLock);
}
/*
* @implemented
*/
@ -57,8 +63,8 @@ ULONG
STDCALL
RtlGetNtGlobalFlags(VOID)
{
PPEB pPeb = NtCurrentPeb();
return pPeb->NtGlobalFlag;
PPEB pPeb = NtCurrentPeb();
return pPeb->NtGlobalFlag;
}
NTSTATUS
@ -82,7 +88,7 @@ STDCALL
RtlInitializeHeapLock(
PRTL_CRITICAL_SECTION CriticalSection)
{
return RtlInitializeCriticalSection(CriticalSection );
return RtlInitializeCriticalSection(CriticalSection);
}
NTSTATUS
@ -127,6 +133,27 @@ CHECK_PAGED_CODE_RTL(char *file, int line)
}
#endif
BOOLEAN
NTAPI
RtlpHandleDpcStackException(IN PEXCEPTION_REGISTRATION_RECORD RegistrationFrame,
IN ULONG_PTR RegistrationFrameEnd,
IN OUT PULONG_PTR StackLow,
IN OUT PULONG_PTR StackHigh)
{
/* There's no such thing as a DPC stack in user-mode */
return FALSE;
}
VOID
NTAPI
RtlpCheckLogException(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT ContextRecord,
IN PVOID ContextData,
IN ULONG Size)
{
/* Exception logging is not done in user-mode */
}
/* RTL Atom Tables ************************************************************/
typedef struct _RTL_ATOM_HANDLE

View file

@ -1,8 +1,9 @@
/* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* PURPOSE: User-mode exception support
* PROJECT: ReactOS Runtime Library
* PURPOSE: User-Mode Exception Support
* FILE: lib/rtl/exception.c
* PROGRAMERS: David Welch <welch@cwcom.net>
* PROGRAMERS: Alex Ionescu (alex@relsoft.net)
* David Welch <welch@cwcom.net>
* Skywing <skywing@valhallalegends.com>
* KJK::Hyperion <noog@libero.it>
*/
@ -16,72 +17,110 @@
/* FUNCTIONS ***************************************************************/
/* implemented in except.s */
VOID
RtlpCaptureContext(PCONTEXT Context);
/*
* @unimplemented
*/
NTSTATUS
STDCALL
RtlDispatchException(
PEXCEPTION_RECORD pExcptRec,
CONTEXT * pContext
)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/*
* @unimplemented
*/
VOID
STDCALL
RtlGetCallersAddress(
OUT PVOID *CallersAddress,
OUT PVOID *CallersCaller
)
{
UNIMPLEMENTED;
}
/*
* @implemented
*/
VOID STDCALL
VOID
STDCALL
RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord)
{
CONTEXT Context;
NTSTATUS Status;
CONTEXT Context;
NTSTATUS Status;
DPRINT1("RtlRaiseException(Status %p)\n", ExceptionRecord);
RtlpCaptureContext(&Context);
/* Capture the context */
RtlCaptureContext(&Context);
ExceptionRecord->ExceptionAddress = (PVOID)(*(((PULONG)Context.Ebp)+1));
Context.ContextFlags = CONTEXT_FULL;
/* Save the exception address */
ExceptionRecord->ExceptionAddress = RtlpGetExceptionAddress();
DPRINT1("ExceptionAddress %p\n", ExceptionRecord->ExceptionAddress);
Status = NtRaiseException(ExceptionRecord, &Context, TRUE);
RtlRaiseException(ExceptionRecord);
RtlRaiseStatus(Status);
/* Write the context flag */
Context.ContextFlags = CONTEXT_FULL;
/* Check if we're being debugged (user-mode only) */
if (!RtlpCheckForActiveDebugger())
{
/* Raise an exception immediately */
ZwRaiseException(ExceptionRecord, &Context, TRUE);
}
else
{
/* Dispatch the exception and check if we should continue */
if (RtlDispatchException(ExceptionRecord, &Context))
{
/* Raise the exception */
Status = ZwRaiseException(ExceptionRecord, &Context, FALSE);
}
else
{
/* Continue, go back to previous context */
ZwContinue(&Context, FALSE);
}
}
/* If we returned, raise a status */
RtlRaiseStatus(Status);
}
/*
* @implemented
*/
VOID STDCALL
VOID
STDCALL
RtlRaiseStatus(NTSTATUS Status)
{
EXCEPTION_RECORD ExceptionRecord;
EXCEPTION_RECORD ExceptionRecord;
CONTEXT Context;
DPRINT1("RtlRaiseStatus(Status 0x%.08x)\n", Status);
DPRINT("RtlRaiseStatus(Status 0x%.08x)\n", Status);
/* Capture the context */
RtlCaptureContext(&Context);
ExceptionRecord.ExceptionCode = Status;
ExceptionRecord.ExceptionRecord = NULL;
ExceptionRecord.NumberParameters = 0;
ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
RtlRaiseException (& ExceptionRecord);
/* Add one argument to ESP */
Context.Esp += sizeof(PVOID);
/* Create an exception record */
ExceptionRecord.ExceptionAddress = RtlpGetExceptionAddress();
ExceptionRecord.ExceptionCode = Status;
ExceptionRecord.ExceptionRecord = NULL;
ExceptionRecord.NumberParameters = 0;
ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
/* Write the context flag */
Context.ContextFlags = CONTEXT_FULL;
/* Check if we're being debugged (user-mode only) */
if (!RtlpCheckForActiveDebugger())
{
/* Raise an exception immediately */
ZwRaiseException(&ExceptionRecord, &Context, TRUE);
}
else
{
/* Dispatch the exception */
RtlDispatchException(&ExceptionRecord, &Context);
/* Raise exception if we got here */
Status = ZwRaiseException(&ExceptionRecord, &Context, FALSE);
}
/* If we returned, raise a status */
RtlRaiseStatus(Status);
}
/*
* @unimplemented
*/
USHORT
STDCALL
RtlCaptureStackBackTrace(IN ULONG FramesToSkip,
IN ULONG FramesToCapture,
OUT PVOID *BackTrace,
OUT PULONG BackTraceHash OPTIONAL)
{
UNIMPLEMENTED;
return 0;
}
/*
@ -89,15 +128,12 @@ RtlRaiseStatus(NTSTATUS Status)
*/
ULONG
STDCALL
RtlWalkFrameChain (
OUT PVOID *Callers,
IN ULONG Count,
IN ULONG Flags
)
RtlWalkFrameChain(OUT PVOID *Callers,
IN ULONG Count,
IN ULONG Flags)
{
UNIMPLEMENTED;
return 0;
UNIMPLEMENTED;
return 0;
}
/* EOF */

View file

@ -1,293 +1,266 @@
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: User-mode exception support for IA-32
* FILE: lib/ntdll/rtl/i386/except.s
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* NOTES: This file is shared with ntoskrnl/rtl/i386/except.s.
* Please keep them in sync.
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS NT Library
* FILE: lib/rtl/i386/except.S
* PURPOSE: User-mode exception support for IA-32
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
* Casper S. Hornstrup (chorns@users.sourceforge.net)
*/
#define EXCEPTION_UNWINDING 0x02
/* INCLUDES ******************************************************************/
#define EREC_FLAGS 0x04
#include <ndk/asm.h>
#include <ndk/i386/segment.h>
.intel_syntax noprefix
#define ExceptionContinueExecution 0
#define ExceptionContinueSearch 1
#define ExceptionNestedException 2
#define ExceptionCollidedUnwind 3
#define EXCEPTION_UNWINDING 2
#define EXCEPTION_EXIT_UNWIND 4
#define EXCEPTION_UNWIND (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND)
.globl _RtlpExecuteHandlerForException
.globl _RtlpExecuteHandlerForUnwind
#define ExceptionContinueExecution 0
#define ExceptionContinueSearch 1
#define ExceptionNestedException 2
#define ExceptionCollidedUnwind 3
#define CONTEXT_FLAGS 0x00
#define CONTEXT_SEGGS 0x8C
#define CONTEXT_SEGFS 0x90
#define CONTEXT_SEGES 0x94
#define CONTEXT_SEGDS 0x98
#define CONTEXT_EDI 0x9C
#define CONTEXT_ESI 0xA0
#define CONTEXT_EBX 0xA4
#define CONTEXT_EDX 0xA8
#define CONTEXT_ECX 0xAC
#define CONTEXT_EAX 0xB0
#define CONTEXT_EBP 0xB4
#define CONTEXT_EIP 0xB8
#define CONTEXT_SEGCS 0xBC
#define CONTEXT_EFLAGS 0xC0
#define CONTEXT_ESP 0xC4
#define CONTEXT_SEGSS 0xC8
/* FUNCTIONS ****************************************************************/
.globl _RtlpGetStackLimits@8
_RtlpGetStackLimits@8:
#define RCC_CONTEXT 0x08
/* Get the stack limits */
mov eax, [fs:TEB_STACK_LIMIT]
mov ecx, [fs:TEB_STACK_BASE]
// EAX = value to print
_do_debug:
pushal
pushl %eax
call _AsmDebug@4
popal
ret
/* Return them */
mov edx, [esp+4]
mov [edx], eax
mov edx, [esp+8]
mov [edx], ecx
#ifndef __NTOSKRNL__
/* return */
ret 8
//
// VOID
// RtlpCaptureContext(PCONTEXT pContext);
//
// Parameters:
// [ESP+08h] - PCONTEXT_X86 pContext
// Registers:
// None
// Returns:
// Nothing
// Notes:
// Grabs the current CPU context.
.globl _RtlpCaptureContext
_RtlpCaptureContext:
pushl %ebp
movl %esp, %ebp
pushl %ebx
movl RCC_CONTEXT(%ebp), %edx // EDX = Address of context structure
.globl _RtlpGetExceptionList@0
_RtlpGetExceptionList@0:
cld
pushf
pop %eax
movl %eax, CONTEXT_EFLAGS(%edx)
xorl %eax, %eax
movl %eax, CONTEXT_EAX(%edx)
movl %eax, CONTEXT_EBX(%edx)
movl %eax, CONTEXT_ECX(%edx)
movl %eax, CONTEXT_EDX(%edx)
movl %eax, CONTEXT_ESI(%edx)
movl %eax, CONTEXT_EDI(%edx)
movl %cs, %eax
movl %eax, CONTEXT_SEGCS(%edx)
movl %ds, %eax
movl %eax, CONTEXT_SEGDS(%edx)
movl %es, %eax
movl %eax, CONTEXT_SEGES(%edx)
movl %fs, %eax
movl %eax, CONTEXT_SEGFS(%edx)
movl %gs, %eax
movl %eax, CONTEXT_SEGGS(%edx)
movl %ss, %eax
movl %eax, CONTEXT_SEGSS(%edx)
//
// STACK LAYOUT: - (ESP to put in context structure)
// - RETURN ADDRESS OF CALLER OF CALLER
// - EBP OF CALLER OF CALLER
// ...
// - RETURN ADDRESS OF CALLER
// - EBP OF CALLER
// ...
//
// Get return address of the caller of the caller of this function
movl %ebp, %ebx
//movl 4(%ebx), %eax // EAX = return address of caller
movl (%ebx), %ebx // EBX = EBP of caller
movl 4(%ebx), %eax // EAX = return address of caller of caller
movl (%ebx), %ebx // EBX = EBP of caller of caller
movl %eax, CONTEXT_EIP(%edx) // EIP = return address of caller of caller
movl %ebx, CONTEXT_EBP(%edx) // EBP = EBP of caller of caller
addl $8, %ebx
movl %ebx, CONTEXT_ESP(%edx) // ESP = EBP of caller of caller + 8
popl %ebx
movl %ebp, %esp
popl %ebp
/* Return the exception list */
mov eax, [fs:TEB_EXCEPTION_LIST]
ret
#endif /* !__NTOSKRNL__ */
.globl _RtlpSetExceptionList@4
_RtlpSetExceptionList@4:
#define REH_ERECORD 0x08
#define REH_RFRAME 0x0C
#define REH_CONTEXT 0x10
#define REH_DCONTEXT 0x14
#define REH_EROUTINE 0x18
/* Get the new list */
mov ecx, [esp+4]
mov ecx, [ecx]
// Parameters:
// None
// Registers:
// [EBP+08h] - PEXCEPTION_RECORD ExceptionRecord
// [EBP+0Ch] - PEXCEPTION_REGISTRATION RegistrationFrame
// [EBP+10h] - PVOID Context
// [EBP+14h] - PVOID DispatcherContext
// [EBP+18h] - PEXCEPTION_HANDLER ExceptionRoutine
// EDX - Address of protecting exception handler
// Returns:
// EXCEPTION_DISPOSITION
// Notes:
// Setup the protecting exception handler and call the exception
// handler in the right context.
_RtlpExecuteHandler:
pushl %ebp
movl %esp, %ebp
pushl REH_RFRAME(%ebp)
/* Write it */
mov [fs:TEB_EXCEPTION_LIST], ecx
pushl %edx
pushl %fs:0x0
movl %esp, %fs:0x0
/* Return */
ret 4
// Prepare to call the exception handler
pushl REH_DCONTEXT(%ebp)
pushl REH_CONTEXT(%ebp)
pushl REH_RFRAME(%ebp)
pushl REH_ERECORD(%ebp)
.globl _RtlpGetExceptionAddress@0
_RtlpGetExceptionAddress@0:
// Now call the exception handler
movl REH_EROUTINE(%ebp), %eax
call *%eax
/* Return the address from the stack */
mov eax, [ebp+4]
cmpl $-1, %fs:0x0
jne .reh_stack_looks_ok
// This should not happen
pushl 0
pushl 0
pushl 0
pushl 0
call _RtlAssert@16
.reh_loop:
jmp .reh_loop
.reh_stack_looks_ok:
movl %fs:0x0, %esp
// Return to the 'front-end' for this function
popl %fs:0x0
movl %ebp, %esp
popl %ebp
/* Return */
ret
.globl _RtlCaptureContext@4
_RtlCaptureContext@4:
#define REP_ERECORD 0x04
#define REP_RFRAME 0x08
#define REP_CONTEXT 0x0C
#define REP_DCONTEXT 0x10
/* Preserve EBX and put the context in it */
push ebx
mov ebx, [esp+8]
/* Save the basic register context */
mov [ebx+CONTEXT_EAX], eax
mov [ebx+CONTEXT_ECX], ecx
mov [ebx+CONTEXT_EDX], edx
mov eax, [esp] /* We pushed EBX, remember? ;) */
mov [ebx+CONTEXT_EBX], eax
mov [ebx+CONTEXT_ESI], esi
mov [ebx+CONTEXT_EDI], edi
/* Capture the other regs */
jmp CaptureRest
.globl _RtlpCaptureContext@4
_RtlpCaptureContext@4:
/* Preserve EBX and put the context in it */
push ebx
mov ebx, [esp+8]
/* Clear the basic register context */
mov dword ptr [ebx+CONTEXT_EAX], 0
mov dword ptr [ebx+CONTEXT_ECX], 0
mov dword ptr [ebx+CONTEXT_EDX], 0
mov dword ptr [ebx+CONTEXT_EBX], 0
mov dword ptr [ebx+CONTEXT_ESI], 0
mov dword ptr [ebx+CONTEXT_EDI], 0
CaptureRest:
/* Capture the segment registers */
mov [ebx+CONTEXT_SEGCS], cs
mov [ebx+CONTEXT_SEGDS], ds
mov [ebx+CONTEXT_SEGES], es
mov [ebx+CONTEXT_SEGFS], fs
mov [ebx+CONTEXT_SEGGS], gs
mov [ebx+CONTEXT_SEGSS], ss
/* Capture flags */
pushfd
pop [ebx+CONTEXT_EFLAGS]
/* The return address should be in [ebp+4] */
mov eax, [ebp+4]
mov [ebx+CONTEXT_EIP], eax
/* Get EBP */
mov eax, [esp]
mov [ebx+CONTEXT_EBP], eax
/* And get ESP */
mov eax, [ebp+8]
mov [ebx+CONTEXT_ESP], eax
/* Return to the caller */
pop ebx
ret 4
.globl _RtlpExecuteHandlerForException@20
_RtlpExecuteHandlerForException@20:
/* Copy the routine in EDX */
mov edx, offset _RtlpExceptionProtector
/* Jump to common routine */
jmp _RtlpExecuteHandler@20
.globl _RtlpExecuteHandlerForUnwind@20
_RtlpExecuteHandlerForUnwind@20:
/* Copy the routine in EDX */
mov edx, offset _RtlpExceptionProtector
/* Run the common routine */
_RtlpExecuteHandler@20:
/* Save non-volatile */
push ebx
push esi
push edi
/* Clear registers */
xor eax, eax
xor ebx, ebx
xor esi, esi
xor edi, edi
/* Call the 2nd-stage executer */
push [esp+0x20]
push [esp+0x20]
push [esp+0x20]
push [esp+0x20]
push [esp+0x20]
call _RtlpExecuteHandler2@20
/* Restore non-volatile */
pop edi
pop esi
pop ebx
ret 0x14
.globl _RtlpExecuteHandler2@20
_RtlpExecuteHandler2@20:
/* Set up stack frame */
push ebp
mov ebp, esp
/* Save the Frame */
push [ebp+0xC]
/* Push handler address */
push edx
/* Push the exception list */
push [fs:TEB_EXCEPTION_LIST]
/* Link us to it */
mov [fs:TEB_EXCEPTION_LIST], esp
/* Call the handler */
push [ebp+0x14]
push [ebp+0x10]
push [ebp+0xC]
push [ebp+8]
mov ecx, [ebp+0x18]
call ecx
/* Unlink us */
mov esp, [fs:TEB_EXCEPTION_LIST]
/* Restore it */
pop [fs:TEB_EXCEPTION_LIST]
/* Undo stack frame and return */
mov esp, ebp
pop ebp
ret 0x14
// Parameters:
// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord
// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
// [ESP+0Ch] - PCONTEXT Context
// [ESP+10h] - PVOID DispatcherContext
// Registers:
// None
// Returns:
// EXCEPTION_DISPOSITION
// Notes:
// This exception handler protects the exception handling
// mechanism by detecting nested exceptions.
_RtlpExceptionProtector:
movl $ExceptionContinueSearch, %eax
movl REP_ERECORD(%esp), %ecx
testl $EXCEPTION_UNWINDING, EREC_FLAGS(%ecx)
jnz .rep_end
// Unwinding is not taking place, so return ExceptionNestedException
/* Assume we'll continue */
mov eax, ExceptionContinueSearch
// Set DispatcherContext field to the exception registration for the
// exception handler that executed when a nested exception occurred
movl REP_DCONTEXT(%esp), %ecx
movl REP_RFRAME(%esp), %eax
movl %eax, (%ecx)
movl $ExceptionNestedException, %eax
/* Put the exception record in ECX and check the Flags */
mov ecx, [esp+4]
test dword ptr [ecx+EXCEPTION_RECORD_EXCEPTION_FLAGS], EXCEPTION_UNWIND
jnz return
.rep_end:
ret
/* Save the frame in ECX and Context in EDX */
mov ecx, [esp+8]
mov edx, [esp+16]
/* Get the nested frame */
mov eax, [ecx+8]
// Parameters:
// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord
// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
// [ESP+0Ch] - PCONTEXT Context
// [ESP+10h] - PVOID DispatcherContext
// [ESP+14h] - PEXCEPTION_HANDLER ExceptionHandler
// Registers:
// None
// Returns:
// EXCEPTION_DISPOSITION
// Notes:
// Front-end
_RtlpExecuteHandlerForException:
movl $_RtlpExceptionProtector, %edx
jmp _RtlpExecuteHandler
/* Set it as the dispatcher context */
mov [edx], eax
/* Return nested exception */
mov eax, ExceptionNestedException
#define RUP_ERECORD 0x04
#define RUP_RFRAME 0x08
#define RUP_CONTEXT 0x0C
#define RUP_DCONTEXT 0x10
return:
ret 16
// Parameters:
// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord
// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
// [ESP+0Ch] - PCONTEXT Context
// [ESP+10h] - PVOID DispatcherContext
// Registers:
// None
// Returns:
// EXCEPTION_DISPOSITION
// Notes:
// This exception handler protects the exception handling
// mechanism by detecting collided unwinds.
_RtlpUnwindProtector:
movl $ExceptionContinueSearch, %eax
movl %ecx, RUP_ERECORD(%esp)
testl $EXCEPTION_UNWINDING, EREC_FLAGS(%ecx)
jz .rup_end
/* Assume we'll continue */
mov eax, ExceptionContinueSearch
// Unwinding is taking place, so return ExceptionCollidedUnwind
/* Put the exception record in ECX and check the Flags */
mov ecx, [esp+4]
test dword ptr [ecx+EXCEPTION_RECORD_EXCEPTION_FLAGS], EXCEPTION_UNWIND
jnz .return
movl RUP_RFRAME(%esp), %ecx
movl RUP_DCONTEXT(%esp), %edx
/* Save the frame in ECX and Context in EDX */
mov ecx, [esp+8]
mov edx, [esp+16]
// Set DispatcherContext field to the exception registration for the
// exception handler that executed when a collision occurred
movl RUP_RFRAME(%ecx), %eax
movl %eax, (%edx)
movl $ExceptionCollidedUnwind, %eax
/* Get the nested frame */
mov eax, [ecx+8]
.rup_end:
ret
/* Set it as the dispatcher context */
mov [edx], eax
/* Return collided unwind */
mov eax, ExceptionCollidedUnwind
.return:
ret 16
// Parameters:
// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord
// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
// [ESP+0Ch] - PCONTEXT Context
// [ESP+10h] - PVOID DispatcherContext
// [ESP+14h] - PEXCEPTION_HANDLER ExceptionHandler
// Registers:
// None
// Returns:
// EXCEPTION_DISPOSITION
_RtlpExecuteHandlerForUnwind:
movl $_RtlpUnwindProtector, %edx
jmp _RtlpExecuteHandler

View file

@ -1,10 +1,10 @@
/* $Id$
*
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PROJECT: ReactOS Run-Time Library
* PURPOSE: User-mode exception support for IA-32
* FILE: lib/ntdll/rtl/i386/exception.c
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* FILE: lib/rtl/i386/exception.c
* PROGRAMERS: Alex Ionescu (alex@relsoft.net)
* Casper S. Hornstrup (chorns@users.sourceforge.net)
*/
/* INCLUDES *****************************************************************/
@ -14,383 +14,340 @@
#define NDEBUG
#include <debug.h>
/* FUNCTIONS ***************************************************************/
/* Implemented in except.s */
/* PRIVATE FUNCTIONS *********************************************************/
VOID
RtlpCaptureContext(PCONTEXT pContext);
STDCALL
RtlpGetStackLimits(PULONG_PTR StackBase,
PULONG_PTR StackLimit);
#define SehpGetStackLimits(StackBase, StackLimit) \
{ \
(*(StackBase)) = NtCurrentTeb()->Tib->StackBase; \
(*(StackLimit)) = NtCurrentTeb()->Tib->StackLimit; \
}
PEXCEPTION_REGISTRATION_RECORD
STDCALL
RtlpGetExceptionList(VOID);
#define SehpGetExceptionList() \
(PEXCEPTION_REGISTRATION)(NtCurrentTeb()->Tib.ExceptionList)
VOID
STDCALL
RtlpSetExceptionList(PEXCEPTION_REGISTRATION_RECORD NewExceptionList);
#define SehpSetExceptionList(NewExceptionList) \
NtCurrentTeb()->Tib.ExceptionList = (PVOID)(NewExceptionList)
/* PUBLIC FUNCTIONS **********************************************************/
VOID STDCALL
AsmDebug(ULONG Value)
/*
* @unimplemented
*/
VOID
STDCALL
RtlGetCallersAddress(OUT PVOID *CallersAddress,
OUT PVOID *CallersCaller)
{
DbgPrint("Value 0x%.08x\n", Value);
UNIMPLEMENTED;
}
/* Declare a few prototypes for the functions in except.s */
EXCEPTION_DISPOSITION
RtlpExecuteHandlerForException(
PEXCEPTION_RECORD ExceptionRecord,
PEXCEPTION_REGISTRATION RegistrationFrame,
PCONTEXT Context,
PVOID DispatcherContext,
PEXCEPTION_HANDLER ExceptionHandler);
EXCEPTION_DISPOSITION
RtlpExecuteHandlerForUnwind(
PEXCEPTION_RECORD ExceptionRecord,
PEXCEPTION_REGISTRATION RegistrationFrame,
PCONTEXT Context,
PVOID DispatcherContext,
PEXCEPTION_HANDLER ExceptionHandler);
#ifndef NDEBUG
VOID RtlpDumpExceptionRegistrations(VOID)
{
PEXCEPTION_REGISTRATION Current;
DbgPrint("Dumping exception registrations:\n");
Current = SehpGetExceptionList();
if ((ULONG_PTR)Current != -1)
{
while ((ULONG_PTR)Current != -1)
{
DbgPrint(" (0x%08X) HANDLER (0x%08X)\n", Current, Current->handler);
Current = Current->prev;
}
DbgPrint(" End-Of-List\n");
} else {
DbgPrint(" No exception registrations exists.\n");
}
}
#endif /* NDEBUG */
ULONG
RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context)
{
PEXCEPTION_REGISTRATION RegistrationFrame, NestedFrame = NULL, DispatcherContext;
DWORD ReturnValue;
DPRINT("RtlpDispatchException()\n");
#ifndef NDEBUG
RtlpDumpExceptionRegistrations();
#endif /* NDEBUG */
RegistrationFrame = SehpGetExceptionList();
DPRINT("RegistrationFrame is 0x%X\n", RegistrationFrame);
while ((ULONG_PTR)RegistrationFrame != (ULONG_PTR)-1)
{
EXCEPTION_RECORD ExceptionRecord2;
//PVOID RegistrationFrameEnd = (PVOID)RegistrationFrame + 8;
// Make sure the registration frame is located within the stack
DPRINT("Error checking\n");
#if 0
if (Teb->Tib.StackBase > RegistrationFrameEnd)
{
DPRINT("Teb->Tib.StackBase (0x%.08x) > RegistrationFrameEnd (0x%.08x)\n",
Teb->Tib.StackBase, RegistrationFrameEnd);
ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
return ExceptionContinueExecution;
}
// FIXME: Stack top, correct?
if (Teb->Tib.StackLimit < RegistrationFrameEnd)
{
DPRINT("Teb->Tib.StackLimit (0x%.08x) > RegistrationFrameEnd (0x%.08x)\n",
Teb->Tib.StackLimit, RegistrationFrameEnd);
ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
return ExceptionContinueExecution;
}
// Make sure stack is DWORD aligned
if ((ULONG_PTR)RegistrationFrame & 3)
{
DPRINT("RegistrationFrameEnd (0x%.08x) is not DWORD aligned.\n",
RegistrationFrameEnd);
ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
return ExceptionContinueExecution;
}
#endif
#if 0
/* FIXME: */
if (someFlag)
RtlpLogLastExceptionDisposition( hLog, retValue );
#endif
DPRINT("Calling handler at 0x%X\n", RegistrationFrame->handler);
DPRINT("ExceptionRecord 0x%X\n", ExceptionRecord);
DPRINT("RegistrationFrame 0x%X\n", RegistrationFrame);
DPRINT("Context 0x%X\n", Context);
DPRINT("&DispatcherContext 0x%X\n", &DispatcherContext);
ReturnValue = RtlpExecuteHandlerForException(
ExceptionRecord,
RegistrationFrame,
Context,
&DispatcherContext,
RegistrationFrame->handler);
#ifdef DEBUG
DPRINT("Exception handler said 0x%X\n", ReturnValue);
DPRINT("RegistrationFrame == 0x%.08x\n", RegistrationFrame);
{
PULONG sp = (PULONG)((PVOID)RegistrationFrame - 0x08);
DPRINT("StandardESP == 0x%.08x\n", sp[0]);
DPRINT("Exception Pointers == 0x%.08x\n", sp[1]);
DPRINT("PrevFrame == 0x%.08x\n", sp[2]);
DPRINT("Handler == 0x%.08x\n", sp[3]);
DPRINT("ScopeTable == 0x%.08x\n", sp[4]);
DPRINT("TryLevel == 0x%.08x\n", sp[5]);
DPRINT("EBP == 0x%.08x\n", sp[6]);
}
#endif
if (RegistrationFrame == NestedFrame)
{
ExceptionRecord->ExceptionFlags &= ~EXCEPTION_NESTED_CALL; // Turn off flag
NestedFrame = NULL;
}
if (ReturnValue == ExceptionContinueExecution)
{
DPRINT("ReturnValue == ExceptionContinueExecution\n");
if (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
{
DPRINT("(ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) == TRUE\n");
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
ExceptionRecord2.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION;
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
ExceptionRecord2.NumberParameters = 0;
RtlRaiseException(&ExceptionRecord2);
}
else
{
/* Copy the (possibly changed) context back to the trap frame and return */
ZwContinue(Context, FALSE);
return ExceptionContinueExecution;
}
}
else if (ReturnValue == ExceptionContinueSearch)
{
DPRINT("ReturnValue == ExceptionContinueSearch\n");
/* Nothing to do here */
}
else if (ReturnValue == ExceptionNestedException)
{
DPRINT("ReturnValue == ExceptionNestedException\n");
ExceptionRecord->ExceptionFlags |= EXCEPTION_NESTED_CALL;
if (NestedFrame < DispatcherContext)
{
NestedFrame = DispatcherContext;
}
}
else /* if (ReturnValue == ExceptionCollidedUnwind) */
{
DPRINT("ReturnValue == ExceptionCollidedUnwind or unknown\n");
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION;
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
ExceptionRecord2.NumberParameters = 0;
RtlRaiseException(&ExceptionRecord2);
}
RegistrationFrame = RegistrationFrame->prev; // Go to previous frame
}
/* No exception handler will handle this exception */
DPRINT("RtlpDispatchException(): Return ExceptionContinueExecution\n");
ExceptionRecord->ExceptionFlags = EXCEPTION_NONCONTINUABLE;
return ExceptionContinueExecution;
}
/*
* @implemented
*/
VOID STDCALL
RtlUnwind(PEXCEPTION_REGISTRATION RegistrationFrame,
PVOID ReturnAddress,
PEXCEPTION_RECORD ExceptionRecord,
DWORD EaxValue)
BOOLEAN
STDCALL
RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context)
{
PEXCEPTION_REGISTRATION ERHead;
PEXCEPTION_RECORD pExceptRec;
EXCEPTION_RECORD TempER;
CONTEXT Context;
PEXCEPTION_REGISTRATION_RECORD RegistrationFrame, NestedFrame = NULL;
PEXCEPTION_REGISTRATION_RECORD DispatcherContext;
EXCEPTION_RECORD ExceptionRecord2;
EXCEPTION_DISPOSITION ReturnValue;
ULONG_PTR StackLow, StackHigh;
ULONG_PTR RegistrationFrameEnd;
DPRINT1("RtlDispatchException(): %p, %p \n", ExceptionRecord, Context);
DPRINT("RtlUnwind(). RegistrationFrame 0x%X\n", RegistrationFrame);
/* Get the current stack limits and registration frame */
RtlpGetStackLimits(&StackLow, &StackHigh);
RegistrationFrame = RtlpGetExceptionList();
DPRINT1("RegistrationFrame is 0x%X\n", RegistrationFrame);
#ifndef NDEBUG
RtlpDumpExceptionRegistrations();
#endif /* NDEBUG */
ERHead = SehpGetExceptionList();
DPRINT("ERHead is 0x%X\n", ERHead);
if (ExceptionRecord == NULL) // The normal case
{
DPRINT("ExceptionRecord == NULL (normal)\n");
pExceptRec = &TempER;
pExceptRec->ExceptionFlags = 0;
pExceptRec->ExceptionCode = STATUS_UNWIND;
pExceptRec->ExceptionRecord = NULL;
pExceptRec->ExceptionAddress = ReturnAddress;
pExceptRec->ExceptionInformation[0] = 0;
}
else
{
pExceptRec = ExceptionRecord;
}
if (RegistrationFrame)
pExceptRec->ExceptionFlags |= EXCEPTION_UNWINDING;
else
pExceptRec->ExceptionFlags |= (EXCEPTION_UNWINDING|EXCEPTION_EXIT_UNWIND);
#ifndef NDEBUG
DPRINT("ExceptionFlags == 0x%x:\n", pExceptRec->ExceptionFlags);
if (pExceptRec->ExceptionFlags & EXCEPTION_UNWINDING)
{
DPRINT(" * EXCEPTION_UNWINDING (0x%x)\n", EXCEPTION_UNWINDING);
}
if (pExceptRec->ExceptionFlags & EXCEPTION_EXIT_UNWIND)
{
DPRINT(" * EXCEPTION_EXIT_UNWIND (0x%x)\n", EXCEPTION_EXIT_UNWIND);
}
#endif /* NDEBUG */
Context.ContextFlags =
(CONTEXT_i386 | CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS);
RtlpCaptureContext(&Context);
DPRINT("Context.Eip = 0x%.08x\n", Context.Eip);
DPRINT("Context.Ebp = 0x%.08x\n", Context.Ebp);
DPRINT("Context.Esp = 0x%.08x\n", Context.Esp);
Context.Esp += 0x10;
Context.Eax = EaxValue;
// Begin traversing the list of EXCEPTION_REGISTRATION
while ((ULONG_PTR)ERHead != (ULONG_PTR)-1 && ERHead != RegistrationFrame)
{
EXCEPTION_RECORD er2;
DPRINT("ERHead 0x%X\n", ERHead);
// If there's an exception frame, but it's lower on the stack
// than the head of the exception list, something's wrong!
if (RegistrationFrame && (RegistrationFrame <= ERHead))
/* Now loop every frame */
while (RegistrationFrame != EXCEPTION_CHAIN_END)
{
DPRINT("The exception frame is bad\n");
/* Find out where it ends */
RegistrationFrameEnd = (ULONG_PTR)RegistrationFrame +
sizeof(*RegistrationFrame);
// Generate an exception to bail out
er2.ExceptionRecord = pExceptRec;
er2.NumberParameters = 0;
er2.ExceptionCode = STATUS_INVALID_UNWIND_TARGET;
er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
RtlRaiseException(&er2);
}
#if 0
Stack = ERHead + sizeof(EXCEPTION_REGISTRATION);
if ( (Teb->Tib.StackBase <= (PVOID)ERHead ) // Make sure that ERHead
&& (Teb->Tib.->StackLimit >= (PVOID)Stack ) // is in range, and a multiple
&& (0 == ((ULONG_PTR)ERHead & 3)) ) // of 4 (i.e., sane)
#else
if (1)
#endif
{
PEXCEPTION_REGISTRATION NewERHead;
PEXCEPTION_REGISTRATION pCurrExceptReg;
EXCEPTION_DISPOSITION ReturnValue;
DPRINT("Executing handler at 0x%X for unwind\n", ERHead->handler);
ReturnValue = RtlpExecuteHandlerForUnwind(
pExceptRec,
ERHead,
&Context,
&NewERHead,
ERHead->handler);
DPRINT("Handler at 0x%X returned 0x%X\n", ERHead->handler, ReturnValue);
if (ReturnValue != ExceptionContinueSearch)
{
if (ReturnValue != ExceptionCollidedUnwind)
/* Make sure the registration frame is located within the stack */
if ((RegistrationFrameEnd > StackHigh) ||
((ULONG_PTR)RegistrationFrame < StackLow) ||
((ULONG_PTR)RegistrationFrame & 0x3))
{
DPRINT("Bad return value\n");
/* Check if this happened in the DPC Stack */
if (RtlpHandleDpcStackException(RegistrationFrame,
RegistrationFrameEnd,
&StackLow,
&StackHigh))
{
/* Use DPC Stack Limits and restart */
continue;
}
er2.ExceptionRecord = pExceptRec;
er2.NumberParameters = 0;
er2.ExceptionCode = STATUS_INVALID_DISPOSITION;
er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
/* Set invalid stack and return false */
ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
DPRINT1("Invalid exception frame\n");
return FALSE;
}
RtlRaiseException(&er2);
/* Check if logging is enabled */
DPRINT1("Checking for logging\n");
RtlpCheckLogException(ExceptionRecord,
Context,
RegistrationFrame,
sizeof(*RegistrationFrame));
/* Call the handler */
DPRINT1("Executing handler: %p\n", RegistrationFrame->Handler);
ReturnValue = RtlpExecuteHandlerForException(ExceptionRecord,
RegistrationFrame,
Context,
&DispatcherContext,
RegistrationFrame->Handler);
DPRINT1("Handler returned: %lx\n", ReturnValue);
/* Check if this is a nested frame */
if (RegistrationFrame == NestedFrame)
{
/* Mask out the flag and the nested frame */
ExceptionRecord->ExceptionFlags &= ~EXCEPTION_NESTED_CALL;
NestedFrame = NULL;
}
/* Handle the dispositions */
if (ReturnValue == ExceptionContinueExecution)
{
/* Check if it was non-continuable */
if (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
{
/* Set up the exception record */
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
ExceptionRecord2.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION;
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
ExceptionRecord2.NumberParameters = 0;
/* Raise the exception */
DPRINT1("Non-continuable\n");
RtlRaiseException(&ExceptionRecord2);
}
else
{
/* Return to caller */
return TRUE;
}
}
else if (ReturnValue == ExceptionNestedException)
{
/* Turn the nested flag on */
ExceptionRecord->ExceptionFlags |= EXCEPTION_NESTED_CALL;
/* Update the current nested frame */
if (NestedFrame < DispatcherContext) NestedFrame = DispatcherContext;
}
else if (ReturnValue == ExceptionContinueSearch)
{
}
else
{
ERHead = NewERHead;
/* Set up the exception record */
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION;
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
ExceptionRecord2.NumberParameters = 0;
/* Raise the exception */
RtlRaiseException(&ExceptionRecord2);
}
}
pCurrExceptReg = ERHead;
ERHead = ERHead->prev;
DPRINT("New ERHead is 0x%X\n", ERHead);
DPRINT("Setting exception registration at 0x%X as current\n",
/*RegistrationFrame->prev*/ pCurrExceptReg->prev);
// Unlink the exception handler
SehpSetExceptionList(pCurrExceptReg->prev);
/* Go to the next frame */
RegistrationFrame = RegistrationFrame->Next;
}
else // The stack looks goofy! Raise an exception to bail out
/* Unhandled, return false */
DPRINT1("FALSE:(\n");
return FALSE;
}
/*
* @implemented
*/
VOID
STDCALL
RtlUnwind(PVOID RegistrationFrame OPTIONAL,
PVOID ReturnAddress OPTIONAL,
PEXCEPTION_RECORD ExceptionRecord OPTIONAL,
PVOID EaxValue)
{
PEXCEPTION_REGISTRATION_RECORD RegistrationFrame2, OldFrame;
PEXCEPTION_REGISTRATION_RECORD DispatcherContext;
EXCEPTION_RECORD ExceptionRecord2, ExceptionRecord3;
EXCEPTION_DISPOSITION ReturnValue;
ULONG_PTR StackLow, StackHigh;
ULONG_PTR RegistrationFrameEnd;
CONTEXT LocalContext;
PCONTEXT Context;
DPRINT1("RtlUnwind(). RegistrationFrame 0x%X\n", RegistrationFrame);
/* Get the current stack limits */
RtlpGetStackLimits(&StackLow, &StackHigh);
/* Check if we don't have an exception record */
if (!ExceptionRecord)
{
DPRINT("Bad stack\n");
/* Overwrite the argument */
ExceptionRecord = &ExceptionRecord3;
er2.ExceptionRecord = pExceptRec;
er2.NumberParameters = 0;
er2.ExceptionCode = STATUS_BAD_STACK;
er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
RtlRaiseException(&er2);
/* Setup a local one */
ExceptionRecord3.ExceptionFlags = 0;
ExceptionRecord3.ExceptionCode = STATUS_UNWIND;
ExceptionRecord3.ExceptionRecord = NULL;
ExceptionRecord3.ExceptionAddress = RtlpGetExceptionAddress();
ExceptionRecord3.NumberParameters = 0;
}
/* Check if we have a frame */
if (RegistrationFrame)
{
/* Set it as unwinding */
ExceptionRecord->ExceptionFlags |= EXCEPTION_UNWINDING;
}
else
{
/* Set the Exit Unwind flag as well */
ExceptionRecord->ExceptionFlags |= (EXCEPTION_UNWINDING |
EXCEPTION_EXIT_UNWIND);
}
/* Now capture the context */
Context = &LocalContext;
LocalContext.ContextFlags = CONTEXT_INTEGER |
CONTEXT_CONTROL |
CONTEXT_SEGMENTS;
RtlpCaptureContext(Context);
/* Pop the current arguments off */
LocalContext.Esp += sizeof(RegistrationFrame) +
sizeof(ReturnAddress) +
sizeof(ExceptionRecord) +
sizeof(ReturnValue);
/* Set the new value for EAX */
LocalContext.Eax = (ULONG)EaxValue;
/* Get the current frame */
RegistrationFrame2 = RtlpGetExceptionList();
/* Now loop every frame */
while (RegistrationFrame2 != EXCEPTION_CHAIN_END)
{
DPRINT1("RegistrationFrame is 0x%X\n", RegistrationFrame2);
/* If this is the target */
if (RegistrationFrame2 == RegistrationFrame)
{
/* Continue execution */
ZwContinue(Context, FALSE);
}
/* Check if the frame is too low */
if ((RegistrationFrame) && ((ULONG_PTR)RegistrationFrame <
(ULONG_PTR)RegistrationFrame2))
{
/* Create an invalid unwind exception */
ExceptionRecord2.ExceptionCode = STATUS_INVALID_UNWIND_TARGET;
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
ExceptionRecord2.NumberParameters = 0;
/* Raise the exception */
DPRINT1("Frame is invalid\n");
RtlRaiseException(&ExceptionRecord2);
}
/* Find out where it ends */
RegistrationFrameEnd = (ULONG_PTR)RegistrationFrame2 +
sizeof(*RegistrationFrame2);
/* Make sure the registration frame is located within the stack */
if ((RegistrationFrameEnd > StackHigh) ||
((ULONG_PTR)RegistrationFrame < StackLow) ||
((ULONG_PTR)RegistrationFrame & 0x3))
{
/* Check if this happened in the DPC Stack */
if (RtlpHandleDpcStackException(RegistrationFrame,
RegistrationFrameEnd,
&StackLow,
&StackHigh))
{
/* Use DPC Stack Limits and restart */
continue;
}
/* Create an invalid stack exception */
ExceptionRecord2.ExceptionCode = STATUS_BAD_STACK;
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
ExceptionRecord2.NumberParameters = 0;
/* Raise the exception */
DPRINT1("Frame has bad stack\n");
RtlRaiseException(&ExceptionRecord2);
}
else
{
/* Call the handler */
DPRINT1("Executing unwind handler: %p\n", RegistrationFrame2->Handler);
ReturnValue = RtlpExecuteHandlerForUnwind(ExceptionRecord,
RegistrationFrame2,
Context,
&DispatcherContext,
RegistrationFrame2->Handler);
DPRINT1("Handler returned: %lx\n", ReturnValue);
/* Handle the dispositions */
if (ReturnValue == ExceptionContinueSearch)
{
/* Get out of here */
break;
}
else if (ReturnValue == ExceptionCollidedUnwind)
{
/* Get the previous frame */
RegistrationFrame2 = DispatcherContext;
}
else
{
/* Set up the exception record */
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION;
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
ExceptionRecord2.NumberParameters = 0;
/* Raise the exception */
RtlRaiseException(&ExceptionRecord2);
}
/* Go to the next frame */
OldFrame = RegistrationFrame2;
RegistrationFrame2 = RegistrationFrame2->Next;
/* Remove this handler */
RtlpSetExceptionList(OldFrame);
}
}
/* Check if we reached the end */
if (RegistrationFrame == EXCEPTION_CHAIN_END)
{
/* Unwind completed, so we don't exit */
ZwContinue(Context, FALSE);
}
else
{
/* This is an exit_unwind or the frame wasn't present in the list */
ZwRaiseException(ExceptionRecord, Context, FALSE);
}
}
}
/* EOF */

View file

@ -23,27 +23,7 @@
/* Helper Header */
#include <reactos/helper.h>
/* FIXME: Move this somewhere else, maybe */
#ifdef DBG
extern VOID FASTCALL CHECK_PAGED_CODE_RTL(char *file, int line);
#define PAGED_CODE_RTL() CHECK_PAGED_CODE_RTL(__FILE__, __LINE__)
#else
#define PAGED_CODE_RTL()
#endif
PVOID STDCALL RtlpAllocateMemory(UINT Bytes, ULONG Tag);
VOID STDCALL RtlpFreeMemory(PVOID Mem, ULONG Tag);
KPROCESSOR_MODE STDCALL RtlpGetMode();
NTSTATUS STDCALL RtlDeleteHeapLock(PRTL_CRITICAL_SECTION CriticalSection);
NTSTATUS STDCALL RtlEnterHeapLock(PRTL_CRITICAL_SECTION CriticalSection);
NTSTATUS STDCALL RtlInitializeHeapLock(PRTL_CRITICAL_SECTION CriticalSection);
NTSTATUS STDCALL RtlLeaveHeapLock(PRTL_CRITICAL_SECTION CriticalSection);
#define RtlpAllocateStringMemory RtlpAllocateMemory
#define RtlpFreeStringMemory RtlpFreeMemory
#define TAG_USTR TAG('U', 'S', 'T', 'R')
#define TAG_ASTR TAG('A', 'S', 'T', 'R')
#define TAG_OSTR TAG('O', 'S', 'T', 'R')
/* Internal RTL header */
#include "rtlp.h"
/* EOF */

104
reactos/lib/rtl/rtlp.h Normal file
View file

@ -0,0 +1,104 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS System Libraries
* FILE: lib/rtl/rtlp.h
* PURPOSE: Run-Time Libary Internal Header
* PROGRAMMER: Alex Ionescu
*/
/* INCLUDES ******************************************************************/
/* PAGED_CODE equivalent for user-mode RTL */
#ifdef DBG
extern VOID FASTCALL CHECK_PAGED_CODE_RTL(char *file, int line);
#define PAGED_CODE_RTL() CHECK_PAGED_CODE_RTL(__FILE__, __LINE__)
#else
#define PAGED_CODE_RTL()
#endif
/* These provide support for sharing code between User and Kernel RTL */
PVOID
STDCALL
RtlpAllocateMemory(
ULONG Bytes,
ULONG Tag);
VOID
STDCALL
RtlpFreeMemory(
PVOID Mem,
ULONG Tag);
KPROCESSOR_MODE
STDCALL
RtlpGetMode(VOID);
NTSTATUS
STDCALL
RtlDeleteHeapLock(PRTL_CRITICAL_SECTION CriticalSection);
NTSTATUS
STDCALL
RtlEnterHeapLock(PRTL_CRITICAL_SECTION CriticalSection);
NTSTATUS
STDCALL
RtlInitializeHeapLock(PRTL_CRITICAL_SECTION CriticalSection);
NTSTATUS
STDCALL
RtlLeaveHeapLock(PRTL_CRITICAL_SECTION CriticalSection);
BOOLEAN
NTAPI
RtlpCheckForActiveDebugger(VOID);
BOOLEAN
NTAPI
RtlpHandleDpcStackException(IN PEXCEPTION_REGISTRATION_RECORD RegistrationFrame,
IN ULONG_PTR RegistrationFrameEnd,
IN OUT PULONG_PTR StackLow,
IN OUT PULONG_PTR StackHigh);
#define RtlpAllocateStringMemory RtlpAllocateMemory
#define RtlpFreeStringMemory RtlpFreeMemory
/* i386/except.S */
EXCEPTION_DISPOSITION
STDCALL
RtlpExecuteHandlerForException(PEXCEPTION_RECORD ExceptionRecord,
PEXCEPTION_REGISTRATION_RECORD RegistrationFrame,
PCONTEXT Context,
PVOID DispatcherContext,
PEXCEPTION_HANDLER ExceptionHandler);
EXCEPTION_DISPOSITION
STDCALL
RtlpExecuteHandlerForUnwind(PEXCEPTION_RECORD ExceptionRecord,
PEXCEPTION_REGISTRATION_RECORD RegistrationFrame,
PCONTEXT Context,
PVOID DispatcherContext,
PEXCEPTION_HANDLER ExceptionHandler);
VOID
NTAPI
RtlpCheckLogException(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT ContextRecord,
IN PVOID ContextData,
IN ULONG Size);
PVOID
NTAPI
RtlpGetExceptionAddress(VOID);
VOID
NTAPI
RtlpCaptureContext(OUT PCONTEXT ContextRecord);
/* Tags for the String Allocators */
#define TAG_USTR TAG('U', 'S', 'T', 'R')
#define TAG_ASTR TAG('A', 'S', 'T', 'R')
#define TAG_OSTR TAG('O', 'S', 'T', 'R')
/* EOF */

View file

@ -29,7 +29,7 @@ STDCALL
ExRaiseAccessViolation(VOID)
{
/* Raise the Right Status */
ExRaiseStatus (STATUS_ACCESS_VIOLATION);
RtlRaiseStatus(STATUS_ACCESS_VIOLATION);
}
/*
@ -40,39 +40,7 @@ STDCALL
ExRaiseDatatypeMisalignment (VOID)
{
/* Raise the Right Status */
ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
}
/*
* @implemented
*/
VOID
STDCALL
ExRaiseStatus(IN NTSTATUS Status)
{
EXCEPTION_RECORD ExceptionRecord;
DPRINT("ExRaiseStatus(%x)\n", Status);
/* Set up an Exception Record */
ExceptionRecord.ExceptionRecord = NULL;
ExceptionRecord.NumberParameters = 0;
ExceptionRecord.ExceptionCode = Status;
ExceptionRecord.ExceptionFlags = 0;
/* Call the Rtl Function */
RtlRaiseException(&ExceptionRecord);
}
/*
* @implemented
*/
VOID
STDCALL
ExRaiseException (PEXCEPTION_RECORD ExceptionRecord)
{
/* Call the Rtl function */
RtlRaiseException(ExceptionRecord);
RtlRaiseStatus(STATUS_DATATYPE_MISALIGNMENT);
}
/*

View file

@ -155,11 +155,9 @@ NtQuerySystemEnvironmentValue (IN PUNICODE_STRING VariableName,
/*
* Copy the name to kernel space if necessary and convert it to ANSI.
*/
Status = RtlCaptureUnicodeString(&WName,
PreviousMode,
NonPagedPool,
FALSE,
VariableName);
Status = ProbeAndCaptureUnicodeString(&WName,
PreviousMode,
VariableName);
if(NT_SUCCESS(Status))
{
/*
@ -168,9 +166,8 @@ NtQuerySystemEnvironmentValue (IN PUNICODE_STRING VariableName,
if(!SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege,
PreviousMode))
{
RtlReleaseCapturedUnicodeString(&WName,
PreviousMode,
FALSE);
ReleaseCapturedUnicodeString(&WName,
PreviousMode);
DPRINT1("NtQuerySystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
return STATUS_PRIVILEGE_NOT_HELD;
}
@ -179,9 +176,8 @@ NtQuerySystemEnvironmentValue (IN PUNICODE_STRING VariableName,
* convert the value name to ansi
*/
Status = RtlUnicodeStringToAnsiString(&AName, &WName, TRUE);
RtlReleaseCapturedUnicodeString(&WName,
PreviousMode,
FALSE);
ReleaseCapturedUnicodeString(&WName,
PreviousMode);
if(!NT_SUCCESS(Status))
{
return Status;
@ -273,18 +269,14 @@ NtSetSystemEnvironmentValue (IN PUNICODE_STRING VariableName,
/*
* Copy the strings to kernel space if necessary
*/
Status = RtlCaptureUnicodeString(&CapturedName,
PreviousMode,
NonPagedPool,
FALSE,
VariableName);
Status = ProbeAndCaptureUnicodeString(&CapturedName,
PreviousMode,
VariableName);
if(NT_SUCCESS(Status))
{
Status = RtlCaptureUnicodeString(&CapturedValue,
PreviousMode,
NonPagedPool,
FALSE,
Value);
Status = ProbeAndCaptureUnicodeString(&CapturedValue,
PreviousMode,
Value);
if(NT_SUCCESS(Status))
{
/*
@ -319,14 +311,12 @@ NtSetSystemEnvironmentValue (IN PUNICODE_STRING VariableName,
Status = STATUS_PRIVILEGE_NOT_HELD;
}
RtlReleaseCapturedUnicodeString(&CapturedValue,
PreviousMode,
FALSE);
ReleaseCapturedUnicodeString(&CapturedValue,
PreviousMode);
}
RtlReleaseCapturedUnicodeString(&CapturedName,
PreviousMode,
FALSE);
ReleaseCapturedUnicodeString(&CapturedName,
PreviousMode);
}
return Status;

View file

@ -287,7 +287,7 @@ VOID inline FASTCALL KiSatisifyMultipleObjectWaits(PKWAIT_BLOCK WaitBlock);
VOID FASTCALL KiWaitTest(PDISPATCHER_HEADER Object, KPRIORITY Increment);
PULONG KeGetStackTopThread(struct _ETHREAD* Thread);
BOOLEAN STDCALL KeContextToTrapFrame(PCONTEXT Context, PKTRAP_FRAME TrapFrame);
BOOLEAN STDCALL KeContextToTrapFrame(PCONTEXT Context, PKEXCEPTION_FRAME ExeptionFrame, PKTRAP_FRAME TrapFrame);
VOID STDCALL KiDeliverApc(KPROCESSOR_MODE PreviousMode,
PVOID Reserved,
PKTRAP_FRAME TrapFrame);
@ -308,7 +308,7 @@ KeSetProcess(struct _KPROCESS* Process,
VOID STDCALL KeInitializeEventPair(PKEVENT_PAIR EventPair);
VOID STDCALL KiInitializeUserApc(IN PVOID Reserved,
VOID STDCALL KiInitializeUserApc(IN PKEXCEPTION_FRAME Reserved,
IN PKTRAP_FRAME TrapFrame,
IN PKNORMAL_ROUTINE NormalRoutine,
IN PVOID NormalContext,
@ -362,9 +362,10 @@ KiMoveApcState (PKAPC_STATE OldState,
VOID
KiAddProfileEvent(KPROFILE_SOURCE Source, ULONG Pc);
VOID
NTAPI
KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
PCONTEXT Context,
PKTRAP_FRAME Tf,
PKEXCEPTION_FRAME ExceptionFrame,
PKTRAP_FRAME Tf,
KPROCESSOR_MODE PreviousMode,
BOOLEAN SearchFrames);
VOID KeTrapFrameToContext(PKTRAP_FRAME TrapFrame,

View file

@ -75,33 +75,90 @@ RtlpCreateUnicodeString(
IN OUT PUNICODE_STRING UniDest,
IN PCWSTR Source,
IN POOL_TYPE PoolType);
NTSTATUS
RtlCaptureUnicodeString(
OUT PUNICODE_STRING Dest,
IN KPROCESSOR_MODE CurrentMode,
IN POOL_TYPE PoolType,
IN BOOLEAN CaptureIfKernel,
IN PUNICODE_STRING UnsafeSrc
);
VOID
RtlReleaseCapturedUnicodeString(
IN PUNICODE_STRING CapturedString,
IN KPROCESSOR_MODE CurrentMode,
IN BOOLEAN CaptureIfKernel
);
NTAPI
RtlpLogException(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT ContextRecord,
IN PVOID ContextData,
IN ULONG Size);
#define ExRaiseStatus RtlRaiseStatus
/*
* Inlined Probing Macros
*
*/
static __inline
NTSTATUS
NTAPI
ProbeAndCaptureUnicodeString(OUT PUNICODE_STRING Dest,
KPROCESSOR_MODE CurrentMode,
IN PUNICODE_STRING UnsafeSrc)
{
NTSTATUS Status = STATUS_SUCCESS;
PVOID Buffer;
ASSERT(Dest != NULL);
/* Probe the structure and buffer*/
if(CurrentMode != KernelMode)
{
_SEH_TRY
{
ProbeForRead(UnsafeSrc,
sizeof(UNICODE_STRING),
sizeof(ULONG));
*Dest = *UnsafeSrc;
if(Dest->Length > 0)
{
ProbeForRead(Dest->Buffer,
Dest->Length,
sizeof(WCHAR));
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if (!NT_SUCCESS(Status)) return Status;
}
else
{
/* Just copy it directly */
*Dest = *UnsafeSrc;
}
/* Allocate space for the buffer */
Buffer = ExAllocatePool(PagedPool, Dest->MaximumLength);
/* Copy it */
RtlCopyMemory(Buffer, Dest->Buffer, Dest->MaximumLength);
/* Set it as the buffer */
Dest->Buffer = Buffer;
/* Return */
return Status;
}
static __inline
VOID
NTAPI
ReleaseCapturedUnicodeString(IN PUNICODE_STRING CapturedString,
KPROCESSOR_MODE CurrentMode)
{
if(CurrentMode != KernelMode) ExFreePool(CapturedString->Buffer);
}
/*
* NOTE: Alignment of the pointers is not verified!
*/
#define ProbeForWriteGenericType(Ptr, Type) \
do { \
if ((ULONG_PTR)(Ptr) + sizeof(Type) - 1 < (ULONG_PTR)(Ptr) || \
(ULONG_PTR)(Ptr) + sizeof(Type) - 1 >= (ULONG_PTR)MmUserProbeAddress) { \
ExRaiseStatus (STATUS_ACCESS_VIOLATION); \
RtlRaiseStatus (STATUS_ACCESS_VIOLATION); \
} \
*(volatile Type *)(Ptr) = *(volatile Type *)(Ptr); \
} while (0)

View file

@ -21,7 +21,7 @@
#include <ndk/asm.h>
/* FIXME: Temporary until CC Ros is gone */
#include <ccros.h>
#include <ccros.h>
/* ReactOS Headers */
#include <reactos/version.h>

View file

@ -1878,11 +1878,9 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
}
#endif
Status = RtlCaptureUnicodeString(&CapturedDriverServiceName,
PreviousMode,
PagedPool,
FALSE,
DriverServiceName);
Status = ProbeAndCaptureUnicodeString(&CapturedDriverServiceName,
PreviousMode,
DriverServiceName);
if (!NT_SUCCESS(Status))
{
return Status;
@ -2021,9 +2019,8 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
Status = IopStartDevice(DeviceNode);
ReleaseCapturedString:
RtlReleaseCapturedUnicodeString(&CapturedDriverServiceName,
PreviousMode,
FALSE);
ReleaseCapturedUnicodeString(&CapturedDriverServiceName,
PreviousMode);
return Status;
}

View file

@ -1321,7 +1321,7 @@ KdpGdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
#error Unknown compiler for inline assembler
#endif
KeContextToTrapFrame(Context, TrapFrame);
KeContextToTrapFrame(Context, NULL, TrapFrame);
return ((SigVal == 5) ? (kdContinue) : (kdHandleException));
break;
}
@ -1434,7 +1434,7 @@ GspBreakIn(PKINTERRUPT Interrupt,
KdpGdbEnterDebuggerException (NULL, &Context, TrapFrame);
KeContextToTrapFrame (&Context, TrapFrame);
KeContextToTrapFrame (&Context, NULL, TrapFrame);
KeLowerIrql (OldIrql);

View file

@ -793,57 +793,55 @@ KiFreeApcRoutine(PKAPC Apc,
*--*/
VOID
STDCALL
KiInitializeUserApc(IN PVOID Reserved,
KiInitializeUserApc(IN PKEXCEPTION_FRAME ExceptionFrame,
IN PKTRAP_FRAME TrapFrame,
IN PKNORMAL_ROUTINE NormalRoutine,
IN PVOID NormalContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2)
{
PCONTEXT Context;
PULONG Esp;
CONTEXT Context;
ULONG_PTR Stack;
ULONG Size;
DPRINT("KiInitializeUserApc(TrapFrame %x/%x)\n", TrapFrame, KeGetCurrentThread()->TrapFrame);
DPRINT("KiInitializeUserApc(TrapFrame %x/%x)\n", TrapFrame,
KeGetCurrentThread()->TrapFrame);
/*
* Save the thread's current context (in other words the registers
* that will be restored when it returns to user mode) so the
* APC dispatcher can restore them later
*/
Context = (PCONTEXT)(((PUCHAR)TrapFrame->Esp) - sizeof(CONTEXT));
RtlZeroMemory(Context, sizeof(CONTEXT));
Context->ContextFlags = CONTEXT_FULL;
Context->SegGs = TrapFrame->Gs;
Context->SegFs = TrapFrame->Fs;
Context->SegEs = TrapFrame->Es;
Context->SegDs = TrapFrame->Ds;
Context->Edi = TrapFrame->Edi;
Context->Esi = TrapFrame->Esi;
Context->Ebx = TrapFrame->Ebx;
Context->Edx = TrapFrame->Edx;
Context->Ecx = TrapFrame->Ecx;
Context->Eax = TrapFrame->Eax;
Context->Ebp = TrapFrame->Ebp;
Context->Eip = TrapFrame->Eip;
Context->SegCs = TrapFrame->Cs;
Context->EFlags = TrapFrame->Eflags;
Context->Esp = TrapFrame->Esp;
Context->SegSs = TrapFrame->Ss;
/* Don't deliver APCs in V86 mode */
if (TrapFrame->Eflags & 2) return;
/*
* Setup the trap frame so the thread will start executing at the
* APC Dispatcher when it returns to user-mode
*/
Esp = (PULONG)(((PUCHAR)TrapFrame->Esp) - (sizeof(CONTEXT) + (6 * sizeof(ULONG))));
Esp[0] = 0xdeadbeef;
Esp[1] = (ULONG)NormalRoutine;
Esp[2] = (ULONG)NormalContext;
Esp[3] = (ULONG)SystemArgument1;
Esp[4] = (ULONG)SystemArgument2;
Esp[5] = (ULONG)Context;
TrapFrame->Eip = (ULONG)KeUserApcDispatcher;
DPRINT("TrapFrame->Eip: %x\n", TrapFrame->Eip);
TrapFrame->Esp = (ULONG)Esp;
/* Save the full context */
Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
KeTrapFrameToContext(TrapFrame, &Context);
/* Protect with SEH */
_SEH_TRY
{
/* Get the aligned size */
Size = ((sizeof(CONTEXT) + 3) & ~3) + 4 * sizeof(ULONG_PTR);
Stack = (Context.Esp & ~3) - Size;
/* Probe and copy */
ProbeForWrite((PVOID)Stack, Size, 4);
RtlMoveMemory((PVOID)(Stack + 4 * sizeof(ULONG_PTR)),
&Context,
sizeof(CONTEXT));
/* Run at APC dispatcher */
TrapFrame->Eip = (ULONG)KeUserApcDispatcher;
TrapFrame->Esp = Stack;
/* Setup the stack */
*(PULONG_PTR)(Stack + 0 * sizeof(ULONG_PTR)) = (ULONG_PTR)NormalRoutine;
*(PULONG_PTR)(Stack + 1 * sizeof(ULONG_PTR)) = (ULONG_PTR)NormalContext;
*(PULONG_PTR)(Stack + 2 * sizeof(ULONG_PTR)) = (ULONG_PTR)SystemArgument1;
*(PULONG_PTR)(Stack + 3 * sizeof(ULONG_PTR)) = (ULONG_PTR)SystemArgument2;
}
_SEH_HANDLE
{
/* FIXME: Get the record and raise an exception */
}
_SEH_END;
}
/*++

View file

@ -0,0 +1,157 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel
* FILE: ntoskrnl/ke/exception.c
* PURPOSE: Platform independent exception handling
* PROGRAMMER: Alex Ionescu (alex@relsoft.net)
*/
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
/* FUNCTIONS ****************************************************************/
VOID
NTAPI
KiContinuePreviousModeUser(IN PCONTEXT Context,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN PKTRAP_FRAME TrapFrame)
{
CONTEXT LocalContext;
/* We'll have to make a copy and probe it */
ProbeForRead(Context, sizeof(CONTEXT), sizeof(ULONG));
RtlMoveMemory(&LocalContext, Context, sizeof(CONTEXT));
Context = &LocalContext;
/* Convert the context into Exception/Trap Frames */
KeContextToTrapFrame(&LocalContext, ExceptionFrame, TrapFrame);
}
NTSTATUS
NTAPI
KiContinue(IN PCONTEXT Context,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN PKTRAP_FRAME TrapFrame)
{
NTSTATUS Status = STATUS_SUCCESS;
KIRQL OldIrql = APC_LEVEL;
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
/* Raise to APC_LEVEL, only if needed */
if (KeGetCurrentIrql() < APC_LEVEL)
{
/* Raise to APC_LEVEL */
KeRaiseIrql(APC_LEVEL, &OldIrql);
}
/* Set up SEH to validate the context */
_SEH_TRY
{
/* Check the previous mode */
if (PreviousMode != KernelMode)
{
/* Validate from user-mode */
KiContinuePreviousModeUser(Context,
ExceptionFrame,
TrapFrame);
}
else
{
/* Convert the context into Exception/Trap Frames */
KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame);
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
/* Lower the IRQL if needed */
if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql);
/* Return status */
return Status;
}
NTSTATUS
NTAPI
KiRaiseException(PEXCEPTION_RECORD ExceptionRecord,
PCONTEXT Context,
PKEXCEPTION_FRAME ExceptionFrame,
PKTRAP_FRAME TrapFrame,
BOOLEAN SearchFrames)
{
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
CONTEXT LocalContext;
EXCEPTION_RECORD LocalExceptionRecord;
ULONG ParameterCount, Size;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT1("KiRaiseException\n");
/* Set up SEH */
_SEH_TRY
{
/* Check the previous mode */
if (PreviousMode != KernelMode)
{
/* Probe the context */
ProbeForRead(Context, sizeof(CONTEXT), sizeof(ULONG));
/* Probe the Exception Record */
ProbeForRead(ExceptionRecord,
FIELD_OFFSET(EXCEPTION_RECORD, NumberParameters) +
sizeof(ULONG),
sizeof(ULONG));
/* Validate the maximum parameters */
if ((ParameterCount = ExceptionRecord->NumberParameters) >
EXCEPTION_MAXIMUM_PARAMETERS)
{
/* Too large */
return STATUS_INVALID_PARAMETER;
}
/* Probe the entire parameters now*/
Size = (sizeof(EXCEPTION_RECORD) -
((EXCEPTION_MAXIMUM_PARAMETERS - ParameterCount) * sizeof(ULONG)));
ProbeForRead(ExceptionRecord, Size, sizeof(ULONG));
/* Now make copies in the stack */
RtlMoveMemory(&LocalContext, Context, sizeof(CONTEXT));
RtlMoveMemory(&LocalExceptionRecord, ExceptionRecord, Size);
Context = &LocalContext;
ExceptionRecord = &LocalExceptionRecord;
/* Update the parameter count */
ExceptionRecord->NumberParameters = ParameterCount;
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if (NT_SUCCESS(Status))
{
/* Convert the context record */
KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame);
/* Dispatch the exception */
KiDispatchException(ExceptionRecord,
ExceptionFrame,
TrapFrame,
PreviousMode,
SearchFrames);
}
/* Return the status */
return Status;
}
/* EOF */

View file

@ -15,6 +15,16 @@
#define NDEBUG
#include <internal/debug.h>
/*
* FIXMES:
* - Clean up file.
* - Add more exception frame support for non-i386 compatibility.
* - Add PSEH handler when an exception occurs in an exception (KiCopyExceptionRecord).
* - Implement official stack trace functions (exported) and remove stuff here.
* - Forward exceptions to user-mode debugger.
* - Wrap Ki NTDLL callbacks in SEH.
*/
/* GLOBALS *****************************************************************/
#define FLAG_IF (1<<9)
@ -172,7 +182,7 @@ KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
/* FIXME: Which exceptions are noncontinuable? */
Er.ExceptionFlags = 0;
KiDispatchException(&Er, 0, Tf, KernelMode, TRUE);
KiDispatchException(&Er, NULL, Tf, KernelMode, TRUE);
return(0);
}
@ -559,6 +569,7 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
BOOLEAN
STDCALL
KeContextToTrapFrame(PCONTEXT Context,
PKEXCEPTION_FRAME ExceptionFrame,
PKTRAP_FRAME TrapFrame)
{
/* Start with the basic Registers */
@ -907,6 +918,158 @@ KeInitExceptions(VOID)
set_system_call_gate(0x2e,(int)KiSystemService);
}
VOID
NTAPI
KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
PKEXCEPTION_FRAME ExceptionFrame,
PKTRAP_FRAME TrapFrame,
KPROCESSOR_MODE PreviousMode,
BOOLEAN FirstChance)
{
CONTEXT Context;
KD_CONTINUE_TYPE Action;
ULONG_PTR Stack, NewStack;
ULONG Size;
DPRINT1("KiDispatchException() called\n");
/* Increase number of Exception Dispatches */
KeGetCurrentPrcb()->KeExceptionDispatchCount++;
/* Set the context flags */
Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
/* Check if User Mode */
if (PreviousMode == UserMode)
{
/* Add the FPU Flag */
Context.ContextFlags |= CONTEXT_FLOATING_POINT;
}
/* Get a Context */
KeTrapFrameToContext(TrapFrame, &Context);
/* Handle kernel-mode first, it's simpler */
if (PreviousMode == KernelMode)
{
/* Check if this is a first-chance exception */
if (FirstChance == TRUE)
{
/* Break into the debugger for the first time */
Action = KdpEnterDebuggerException(ExceptionRecord,
PreviousMode,
&Context,
TrapFrame,
TRUE,
TRUE);
/* If the debugger said continue, then continue */
if (Action == kdContinue) goto Handled;
/* If the Debugger couldn't handle it, dispatch the exception */
if (RtlDispatchException(ExceptionRecord, &Context))
{
/* It was handled by an exception handler, continue */
goto Handled;
}
}
/* This is a second-chance exception, only for the debugger */
Action = KdpEnterDebuggerException(ExceptionRecord,
PreviousMode,
&Context,
TrapFrame,
FALSE,
FALSE);
/* If the debugger said continue, then continue */
if (Action == kdContinue) goto Handled;
/* Third strike; you're out */
KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED,
ExceptionRecord->ExceptionCode,
(ULONG_PTR)ExceptionRecord->ExceptionAddress,
ExceptionRecord->ExceptionInformation[0],
ExceptionRecord->ExceptionInformation[1],
TrapFrame);
}
else
{
/* User mode exception, was it first-chance? */
if (FirstChance)
{
/* Enter Debugger if available */
Action = KdpEnterDebuggerException(ExceptionRecord,
PreviousMode,
&Context,
TrapFrame,
TRUE,
FALSE);
/* Exit if we're continuing */
if (Action == kdContinue) goto Handled;
/* FIXME: Forward exception to user mode debugger */
/* Set up the user-stack */
_SEH_TRY
{
/* Align context size and get stack pointer */
Size = (sizeof(CONTEXT) + 3) & ~3;
Stack = (Context.Esp & ~3) - Size;
/* Probe stack and copy Context */
ProbeForWrite((PVOID)Stack, Size, sizeof(ULONG));
RtlMoveMemory((PVOID)Stack, &Context, sizeof(CONTEXT));
/* Align exception record size and get stack pointer */
Size = (sizeof(EXCEPTION_RECORD) -
(EXCEPTION_MAXIMUM_PARAMETERS - ExceptionRecord->NumberParameters) *
sizeof(ULONG) + 3) & ~3;
NewStack = Stack - Size;
/* Probe stack and copy exception record. Don't forget to add the two params */
ProbeForWrite((PVOID)(NewStack - 2 * sizeof(ULONG_PTR)),
Size + 2 * sizeof(ULONG_PTR),
sizeof(ULONG));
RtlMoveMemory((PVOID)NewStack, ExceptionRecord, Size);
/* Now write the two params for the user-mode dispatcher */
*(PULONG_PTR)(NewStack - 1 * sizeof(ULONG_PTR)) = Stack;
*(PULONG_PTR)(NewStack - 2 * sizeof(ULONG_PTR)) = NewStack;
/* Set new Stack Pointer */
TrapFrame->Esp = NewStack - 2 * sizeof(ULONG_PTR);
/* Set EIP to the User-mode Dispathcer */
TrapFrame->Eip = (ULONG)KeUserExceptionDispatcher;
return;
}
_SEH_HANDLE
{
/* Do second-chance */
}
_SEH_END;
}
/* FIXME: Forward the exception to the debugger for 2nd chance */
/* 3rd strike, kill the thread */
DPRINT1("Unhandled UserMode exception, terminating thread\n");
ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED,
ExceptionRecord->ExceptionCode,
(ULONG_PTR)ExceptionRecord->ExceptionAddress,
ExceptionRecord->ExceptionInformation[0],
ExceptionRecord->ExceptionInformation[1],
TrapFrame);
}
Handled:
/* Convert the context back into Trap/Exception Frames */
KeContextToTrapFrame(&Context, NULL, TrapFrame);
return;
}
/*
* @implemented
*/
@ -927,32 +1090,3 @@ KeRaiseUserException(IN NTSTATUS ExceptionCode)
return((NTSTATUS)OldEip);
}
/*
* @implemented
*/
NTSTATUS
STDCALL
NtRaiseException (
IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context,
IN BOOLEAN SearchFrames)
{
PKTHREAD Thread = KeGetCurrentThread();
PKTRAP_FRAME TrapFrame = Thread->TrapFrame;
PKTRAP_FRAME PrevTrapFrame = (PKTRAP_FRAME)TrapFrame->Edx;
KeGetCurrentKPCR()->Tib.ExceptionList = TrapFrame->ExceptionList;
KiDispatchException(ExceptionRecord,
Context,
TrapFrame,
KeGetPreviousMode(),
SearchFrames);
/* Restore the user context */
Thread->TrapFrame = PrevTrapFrame;
__asm__("mov %%ebx, %%esp;\n" "jmp _KiServiceExit": : "b" (TrapFrame));
/* We never get here */
return(STATUS_SUCCESS);
}

View file

@ -569,7 +569,7 @@ KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr)
/* Dispatch exception */
DPRINT("Dispatching exception (ExceptionCode = 0x%08x)\n", Er.ExceptionCode);
KiDispatchException(&Er, Context, Tf, PreviousMode, TRUE);
KiDispatchException(&Er, NULL, Tf, PreviousMode, TRUE);
DPRINT("Math-fault handled!\n");
return STATUS_SUCCESS;

View file

@ -489,3 +489,12 @@ _irq_handler_15:
iret
#endif /* CONFIG_SMP */
.intel_syntax noprefix
.globl _KiUnexpectedInterrupt@0
_KiUnexpectedInterrupt@0:
/* Bugcheck with invalid interrupt code */
push 0x12
call _KeBugCheck@4

View file

@ -458,3 +458,92 @@ _KiDebugService:
/* Exit through common routine */
jmp _KiServiceExit2
.globl _NtRaiseException@12
_NtRaiseException@12:
/* NOTE: We -must- be called by Zw* to have the right frame! */
/* Push the stack frame */
push ebp
/* Get the current thread and restore its trap frame */
mov ebx, [fs:KPCR_CURRENT_THREAD]
mov edx, [ebp+KTRAP_FRAME_EDX]
mov [ebx+KTHREAD_TRAP_FRAME], edx
/* Set up stack frame */
mov ebp, esp
/* Get the Trap Frame in EBX */
mov ebx, [ebp+0]
/* Get the exception list and restore */
mov eax, [ebx+KTRAP_FRAME_EXCEPTION_LIST]
mov [fs:KPCR_EXCEPTION_LIST], eax
/* Get the parameters */
mov edx, [ebp+16] /* Search frames */
mov ecx, [ebp+12] /* Context */
mov eax, [ebp+8] /* Exception Record */
/* Raise the exception */
push edx
push ebx
push 0
push ecx
push eax
call _KiRaiseException@20
/* Restore trap frame in EBP */
pop ebp
mov esp, ebp
.globl _NtContinue@8
_NtContinue@8:
/* NOTE: We -must- be called by Zw* to have the right frame! */
/* Push the stack frame */
push ebp
/* Get the current thread and restore its trap frame */
mov ebx, [fs:KPCR_CURRENT_THREAD]
mov edx, [ebp+KTRAP_FRAME_EDX]
mov [ebx+KTHREAD_TRAP_FRAME], edx
/* Set up stack frame */
mov ebp, esp
/* Save the parameters */
mov eax, [ebp+0]
mov ecx, [ebp+8]
/* Call KiContinue */
push eax
push 0
push ecx
call _KiContinue@12
/* Check if we failed (bad context record) */
or eax, eax
jnz Error
/* Check if test alert was requested */
cmp dword ptr [ebp+12], 0
je DontTest
/* Test alert for the thread */
mov al, [ebx+KTHREAD_PREVIOUS_MODE]
push eax
call _KeTestAlertThread@4
DontTest:
/* Return to previous context */
pop ebp
mov esp, ebp
jmp _KiServiceExit2
Error:
pop ebp
mov esp, ebp
jmp _KiServiceExit

View file

@ -85,7 +85,7 @@ Ke386InitThreadWithContext(PKTHREAD Thread,
TrapFrame = &InitFrame->TrapFrame;
/* Set up a trap frame from the context. */
if (KeContextToTrapFrame(Context, TrapFrame))
if (KeContextToTrapFrame(Context, NULL, TrapFrame))
{
Thread->NpxState = NPX_STATE_VALID;
}

View file

@ -352,5 +352,26 @@ _KiTrapUnknown:
movl $255, %esi
jmp _KiTrapProlog
.intel_syntax noprefix
.globl _KiCoprocessorError@0
_KiCoprocessorError@0:
/* Get the NPX Thread's Initial stack */
mov eax, [fs:KPCR_NPX_THREAD]
mov eax, [eax+KTHREAD_INITIAL_STACK]
/* Make space for the FPU Save area */
sub eax, SIZEOF_FX_SAVE_AREA
/* Set the CR0 State */
mov dword ptr [eax+FN_CR0_NPX_STATE], 8
/* Update it */
mov eax, cr0
or eax, 8
mov cr0, eax
/* Return to caller */
ret
/* EOF */

View file

@ -792,11 +792,9 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName,
PreviousMode = ExGetPreviousMode();
Status = RtlCaptureUnicodeString(&CapturedFileName,
PreviousMode,
PagedPool,
FALSE,
FileName);
Status = ProbeAndCaptureUnicodeString(&CapturedFileName,
PreviousMode,
FileName);
if (!NT_SUCCESS(Status))
{
return(Status);
@ -816,9 +814,8 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName,
if (!NT_SUCCESS(Status))
{
RtlReleaseCapturedUnicodeString(&CapturedFileName,
PreviousMode,
FALSE);
ReleaseCapturedUnicodeString(&CapturedFileName,
PreviousMode);
return Status;
}
}
@ -849,9 +846,8 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName,
NULL,
SL_OPEN_PAGING_FILE | IO_NO_PARAMETER_CHECKING);
RtlReleaseCapturedUnicodeString(&CapturedFileName,
PreviousMode,
FALSE);
ReleaseCapturedUnicodeString(&CapturedFileName,
PreviousMode);
if (!NT_SUCCESS(Status))
{
return(Status);

View file

@ -127,9 +127,9 @@ ExQueryPoolBlockSize@8
ExQueueWorkItem@8
ExRaiseAccessViolation@0
ExRaiseDatatypeMisalignment@0
ExRaiseException@4
ExRaiseException@4=RtlRaiseException@4
ExRaiseHardError@24
ExRaiseStatus@4
ExRaiseStatus@4=RtlRaiseStatus@4
ExRegisterCallback@12
ExReinitializeResourceLite@4
@ExReInitializeRundownProtection@4

View file

@ -50,11 +50,11 @@
</if>
<file>apc.c</file>
<file>bug.c</file>
<file>catch.c</file>
<file>clock.c</file>
<file>device.c</file>
<file>dpc.c</file>
<file>event.c</file>
<file>exception.c</file>
<file>gate.c</file>
<file>gmutex.c</file>
<file>ipi.c</file>
@ -285,11 +285,6 @@
<file>power.c</file>
</directory>
<directory name="ps">
<if property="ARCH" value="i386">
<directory name="i386">
<file>continue.c</file>
</directory>
</if>
<file>debug.c</file>
<file>idle.c</file>
<file>job.c</file>
@ -313,7 +308,6 @@
</directory>
</if>
<file>atom.c</file>
<file>capture.c</file>
<file>debug.c</file>
<file>libsupp.c</file>
<file>misc.c</file>

View file

@ -200,11 +200,9 @@ NtCreateSymbolicLinkObject(OUT PHANDLE LinkHandle,
}
}
Status = RtlCaptureUnicodeString(&CapturedLinkTarget,
PreviousMode,
PagedPool,
FALSE,
LinkTarget);
Status = ProbeAndCaptureUnicodeString(&CapturedLinkTarget,
PreviousMode,
LinkTarget);
if(!NT_SUCCESS(Status))
{
DPRINT1("NtCreateSymbolicLinkObject: Capturing the target link failed!\n");
@ -263,9 +261,8 @@ NtCreateSymbolicLinkObject(OUT PHANDLE LinkHandle,
ObDereferenceObject(SymbolicLink);
}
RtlReleaseCapturedUnicodeString(&CapturedLinkTarget,
PreviousMode,
FALSE);
ReleaseCapturedUnicodeString(&CapturedLinkTarget,
PreviousMode);
return Status;
}

View file

@ -57,7 +57,7 @@ PspGetOrSetContextKernelRoutine(PKAPC Apc,
} else {
/* Set the Context */
KeContextToTrapFrame(Context, KeGetCurrentThread()->TrapFrame);
KeContextToTrapFrame(Context, NULL, KeGetCurrentThread()->TrapFrame);
}
/* Notify the Native API that we are done */
@ -221,7 +221,7 @@ NtSetContextThread(IN HANDLE ThreadHandle,
* I don't know if trying to get your own context makes much
* sense but we can handle it more efficently.
*/
KeContextToTrapFrame(&GetSetContext.Context, Thread->Tcb.TrapFrame);
KeContextToTrapFrame(&GetSetContext.Context, NULL, Thread->Tcb.TrapFrame);
} else {

View file

@ -1,159 +0,0 @@
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/rtl/capture.c
* PURPOSE: Helper routines for system calls.
*
* PROGRAMMERS: David Welch (welch@cwcom.net)
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
/* FUNCTIONS *****************************************************************/
NTSTATUS
RtlCaptureUnicodeString(OUT PUNICODE_STRING Dest,
IN KPROCESSOR_MODE CurrentMode,
IN POOL_TYPE PoolType,
IN BOOLEAN CaptureIfKernel,
IN PUNICODE_STRING UnsafeSrc)
{
UNICODE_STRING Src;
NTSTATUS Status = STATUS_SUCCESS;
ASSERT(Dest != NULL);
/*
* Copy the source string structure to kernel space.
*/
if(CurrentMode != KernelMode)
{
RtlZeroMemory(&Src, sizeof(Src));
_SEH_TRY
{
ProbeForRead(UnsafeSrc,
sizeof(UNICODE_STRING),
sizeof(ULONG));
Src = *UnsafeSrc;
if(Src.Length > 0)
{
ProbeForRead(Src.Buffer,
Src.Length,
sizeof(WCHAR));
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
else if(!CaptureIfKernel)
{
/* just copy the UNICODE_STRING structure, the pointers are considered valid */
*Dest = *UnsafeSrc;
return STATUS_SUCCESS;
}
else
{
/* capture the string even though it is considered to be valid */
Src = *UnsafeSrc;
}
/*
* Initialize the destination string.
*/
Dest->Length = Src.Length;
if(Src.Length > 0)
{
Dest->MaximumLength = Src.Length + sizeof(WCHAR);
Dest->Buffer = ExAllocatePool(PoolType, Dest->MaximumLength);
if (Dest->Buffer == NULL)
{
Dest->Length = Dest->MaximumLength = 0;
Dest->Buffer = NULL;
return STATUS_INSUFFICIENT_RESOURCES;
}
/*
* Copy the source string to kernel space.
*/
_SEH_TRY
{
RtlCopyMemory(Dest->Buffer, Src.Buffer, Src.Length);
Dest->Buffer[Src.Length / sizeof(WCHAR)] = L'\0';
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
ExFreePool(Dest->Buffer);
Dest->Buffer = NULL;
Dest->Length = Dest->MaximumLength = 0;
}
}
else
{
Dest->MaximumLength = 0;
Dest->Buffer = NULL;
}
return Status;
}
VOID
RtlReleaseCapturedUnicodeString(IN PUNICODE_STRING CapturedString,
IN KPROCESSOR_MODE CurrentMode,
IN BOOLEAN CaptureIfKernel)
{
if(CurrentMode != KernelMode || CaptureIfKernel )
{
ExFreePool(CapturedString->Buffer);
}
}
/*
* @unimplemented
*/
VOID
STDCALL
RtlCaptureContext (
OUT PCONTEXT ContextRecord
)
{
UNIMPLEMENTED;
}
/*
* @unimplemented
*/
USHORT
STDCALL
RtlCaptureStackBackTrace (
IN ULONG FramesToSkip,
IN ULONG FramesToCapture,
OUT PVOID *BackTrace,
OUT PULONG BackTraceHash OPTIONAL
)
{
UNIMPLEMENTED;
return 0;
}
/* EOF */

View file

@ -62,7 +62,7 @@ _except_handler2(
* @implemented
*/
void __cdecl
_global_unwind2(PEXCEPTION_REGISTRATION RegistrationFrame)
_global_unwind2(PEXCEPTION_REGISTRATION_RECORD RegistrationFrame)
{
RtlUnwind(RegistrationFrame, &&__ret_label, NULL, 0);
__ret_label:

View file

@ -1,11 +1,10 @@
/* $Id$
*
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/rtl/libsupp.c
* PURPOSE: Rtl library support routines
*
* PROGRAMMERS: No programmer listed.
* PURPOSE: RTL Support Routines
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
* Gunnar Dalsnes
*/
/* INCLUDES ******************************************************************/
@ -14,8 +13,17 @@
#define NDEBUG
#include <internal/debug.h>
extern ULONG NtGlobalFlag;
/* FUNCTIONS *****************************************************************/
BOOLEAN
NTAPI
RtlpCheckForActiveDebugger(VOID)
{
/* This check is meaningless in kernel-mode */
return TRUE;
}
KPROCESSOR_MODE
STDCALL
@ -124,6 +132,53 @@ CHECK_PAGED_CODE_RTL(char *file, int line)
}
#endif
VOID
NTAPI
RtlpCheckLogException(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT ContextRecord,
IN PVOID ContextData,
IN ULONG Size)
{
/* Check the global flag */
if (NtGlobalFlag & FLG_ENABLE_EXCEPTION_LOGGING)
{
/* FIXME: Log this exception */
}
}
BOOLEAN
NTAPI
RtlpHandleDpcStackException(IN PEXCEPTION_REGISTRATION_RECORD RegistrationFrame,
IN ULONG_PTR RegistrationFrameEnd,
IN OUT PULONG_PTR StackLow,
IN OUT PULONG_PTR StackHigh)
{
PKPRCB Prcb;
ULONG_PTR DpcStack;
/* Check if we are at DISPATCH or higher */
if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
{
/* Get the PRCB and DPC Stack */
Prcb = KeGetCurrentPrcb();
DpcStack = (ULONG_PTR)Prcb->DpcStack;
/* Check if we are in a DPC and the stack matches */
if ((Prcb->DpcRoutineActive) &&
(RegistrationFrameEnd <= DpcStack) &&
((ULONG_PTR)RegistrationFrame >= DpcStack - 4096))
{
/* Update the limits to the DPC Stack's */
*StackHigh = DpcStack;
*StackLow = DpcStack - 4096;
return TRUE;
}
}
/* Not in DPC stack */
return FALSE;
}
/* RTL Atom Tables ************************************************************/
NTSTATUS

View file

@ -33,6 +33,7 @@
#include <stdarg.h>
#include <windef.h>
#include <excpt.h>
#include <ntdef.h>
#include <basetyps.h>

View file

@ -0,0 +1,90 @@
/*
* excpt.h
* This file has no copyright assigned and is placed in the Public Domain.
* This file is a part of the mingw-runtime package.
* No warranty is given; refer to the file DISCLAIMER within the package.
*
* Support for operating system level structured exception handling.
*
* NOTE: This is very preliminary stuff. I am also pretty sure it is
* completely Intel specific.
*
*/
#ifndef _EXCPT_H_
#define _EXCPT_H_
/* All the headers include this file. */
#include <_mingw.h>
#include <windef.h>
/*
* NOTE: The constants structs and typedefs below should be defined in the
* Win32 API headers.
*/
#define EH_NONCONTINUABLE 0x01
#define EH_UNWINDING 0x02
#define EH_EXIT_UNWIND 0x04
#define EH_STACK_INVALID 0x08
#define EH_NESTED_CALL 0x10
#ifndef RC_INVOKED
typedef enum {
ExceptionContinueExecution,
ExceptionContinueSearch,
ExceptionNestedException,
ExceptionCollidedUnwind
} EXCEPTION_DISPOSITION;
/*
* End of stuff that should be in the Win32 API files.
*/
#ifdef __cplusplus
extern "C" {
#endif
/*
* The type of function that is expected as an exception handler to be
* installed with _try1.
*/
typedef EXCEPTION_DISPOSITION (*PEXCEPTION_HANDLER)
(struct _EXCEPTION_RECORD*, void*, struct _CONTEXT*, void*);
/*
* A macro which installs the supplied exception handler.
* Push the pointer to the new handler onto the stack,
* then push the pointer to the old registration structure (at fs:0)
* onto the stack, then put a pointer to the new registration
* structure (i.e. the current stack pointer) at fs:0.
*/
#define __try1(pHandler) \
__asm__ ("pushl %0;pushl %%fs:0;movl %%esp,%%fs:0;" : : "g" (pHandler));
/*
* A macro which (despite its name) *removes* an installed
* exception handler. Should be used only in conjunction with the above
* install routine __try1.
* Move the pointer to the old reg. struct (at the current stack
* position) to fs:0, replacing the pointer we installed above,
* then add 8 to the stack pointer to get rid of the space we
* used when we pushed on our new reg. struct above. Notice that
* the stack must be in the exact state at this point that it was
* after we did _try1 or this will smash things.
*/
#define __except1 \
__asm__ ("movl (%%esp),%%eax;movl %%eax,%%fs:0;addl $8,%%esp;" \
: : : "%eax");
#ifdef __cplusplus
}
#endif
#endif /* Not RC_INVOKED */
#endif /* _EXCPT_H_ not defined */