mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
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:
parent
801ad7223f
commit
b9020b11dd
48 changed files with 1839 additions and 1345 deletions
|
@ -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
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
|
||||
/* C Standard Headers */
|
||||
#include <stdarg.h>
|
||||
#include <excpt.h>
|
||||
|
||||
/* Helper Header */
|
||||
#include <helper.h>
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -33,7 +33,7 @@ DbgUiRemoteBreakin@0
|
|||
DbgUiWaitStateChange@8
|
||||
DbgUserBreakPoint@0
|
||||
KiRaiseUserExceptionDispatcher@0
|
||||
KiUserApcDispatcher@20
|
||||
KiUserApcDispatcher@16
|
||||
KiUserCallbackDispatcher@12
|
||||
KiUserExceptionDispatcher@8
|
||||
LdrAccessResource@16
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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,43 +12,10 @@
|
|||
#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
|
||||
*/
|
||||
|
@ -59,28 +27,25 @@ KiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord,
|
|||
EXCEPTION_RECORD NestedExceptionRecord;
|
||||
NTSTATUS Status;
|
||||
|
||||
if(RtlpExecuteVectoredExceptionHandlers(ExceptionRecord,
|
||||
Context) != ExceptionContinueExecution)
|
||||
{
|
||||
Status = NtContinue(Context, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(RtlpDispatchException(ExceptionRecord, Context) != ExceptionContinueExecution)
|
||||
/* Dispatch the exception and check the result */
|
||||
if(RtlDispatchException(ExceptionRecord, Context))
|
||||
{
|
||||
/* Continue executing */
|
||||
Status = NtContinue(Context, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Raise an exception */
|
||||
Status = NtRaiseException(ExceptionRecord, Context, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup the Exception record */
|
||||
NestedExceptionRecord.ExceptionCode = Status;
|
||||
NestedExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
|
||||
NestedExceptionRecord.ExceptionRecord = ExceptionRecord;
|
||||
NestedExceptionRecord.NumberParameters = Status;
|
||||
|
||||
/* Raise the exception */
|
||||
RtlRaiseException(&NestedExceptionRecord);
|
||||
}
|
||||
|
||||
|
@ -93,11 +58,13 @@ KiRaiseUserExceptionDispatcher(VOID)
|
|||
{
|
||||
EXCEPTION_RECORD ExceptionRecord;
|
||||
|
||||
/* Setup the exception record */
|
||||
ExceptionRecord.ExceptionCode = ((PTEB)NtCurrentTeb())->ExceptionCode;
|
||||
ExceptionRecord.ExceptionFlags = 0;
|
||||
ExceptionRecord.ExceptionRecord = NULL;
|
||||
ExceptionRecord.NumberParameters = 0;
|
||||
|
||||
/* Raise the exception */
|
||||
RtlRaiseException(&ExceptionRecord);
|
||||
}
|
||||
|
||||
|
@ -106,16 +73,13 @@ KiRaiseUserExceptionDispatcher(VOID)
|
|||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
KiUserCallbackDispatcher(ULONG RoutineIndex,
|
||||
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));
|
||||
}
|
||||
|
|
|
@ -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 */
|
186
reactos/lib/ntdll/main/i386/dispatch.S
Normal file
186
reactos/lib/ntdll/main/i386/dispatch.S
Normal 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
|
||||
|
|
@ -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">
|
||||
<if property="ARCH" value="i386">
|
||||
<directory name="i386">
|
||||
<file>dispatch.S</file>
|
||||
</directory>
|
||||
</if>
|
||||
<ifnot property="ARCH" value="i386">
|
||||
<file>dispatch.c</file>
|
||||
<file>dllmain.c</file>
|
||||
</ifnot>
|
||||
</directory>
|
||||
<directory name="rtl">
|
||||
<file>libsupp.c</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
|
||||
*/
|
||||
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
DPRINT1("RtlRaiseException(Status %p)\n", ExceptionRecord);
|
||||
|
||||
RtlpCaptureContext(&Context);
|
||||
/* Capture the context */
|
||||
RtlCaptureContext(&Context);
|
||||
|
||||
ExceptionRecord->ExceptionAddress = (PVOID)(*(((PULONG)Context.Ebp)+1));
|
||||
/* Save the exception address */
|
||||
ExceptionRecord->ExceptionAddress = RtlpGetExceptionAddress();
|
||||
DPRINT1("ExceptionAddress %p\n", ExceptionRecord->ExceptionAddress);
|
||||
|
||||
/* Write the context flag */
|
||||
Context.ContextFlags = CONTEXT_FULL;
|
||||
|
||||
Status = NtRaiseException(ExceptionRecord, &Context, TRUE);
|
||||
RtlRaiseException(ExceptionRecord);
|
||||
RtlRaiseStatus(Status);
|
||||
/* 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;
|
||||
CONTEXT Context;
|
||||
DPRINT1("RtlRaiseStatus(Status 0x%.08x)\n", Status);
|
||||
|
||||
DPRINT("RtlRaiseStatus(Status 0x%.08x)\n", Status);
|
||||
/* Capture the context */
|
||||
RtlCaptureContext(&Context);
|
||||
|
||||
/* 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;
|
||||
RtlRaiseException (& ExceptionRecord);
|
||||
|
||||
/* 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,
|
||||
RtlWalkFrameChain(OUT PVOID *Callers,
|
||||
IN ULONG Count,
|
||||
IN ULONG Flags
|
||||
)
|
||||
IN ULONG Flags)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -1,293 +1,266 @@
|
|||
/* $Id$
|
||||
*
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* PROJECT: ReactOS NT Library
|
||||
* FILE: lib/rtl/i386/except.S
|
||||
* 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.
|
||||
* 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 EXCEPTION_UNWINDING 2
|
||||
#define EXCEPTION_EXIT_UNWIND 4
|
||||
#define EXCEPTION_UNWIND (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND)
|
||||
|
||||
#define ExceptionContinueExecution 0
|
||||
#define ExceptionContinueSearch 1
|
||||
#define ExceptionNestedException 2
|
||||
#define ExceptionCollidedUnwind 3
|
||||
|
||||
.globl _RtlpExecuteHandlerForException
|
||||
.globl _RtlpExecuteHandlerForUnwind
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
#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
|
||||
.globl _RtlpGetStackLimits@8
|
||||
_RtlpGetStackLimits@8:
|
||||
|
||||
/* Get the stack limits */
|
||||
mov eax, [fs:TEB_STACK_LIMIT]
|
||||
mov ecx, [fs:TEB_STACK_BASE]
|
||||
|
||||
#define RCC_CONTEXT 0x08
|
||||
/* Return them */
|
||||
mov edx, [esp+4]
|
||||
mov [edx], eax
|
||||
mov edx, [esp+8]
|
||||
mov [edx], ecx
|
||||
|
||||
// EAX = value to print
|
||||
_do_debug:
|
||||
pushal
|
||||
pushl %eax
|
||||
call _AsmDebug@4
|
||||
popal
|
||||
/* return */
|
||||
ret 8
|
||||
|
||||
.globl _RtlpGetExceptionList@0
|
||||
_RtlpGetExceptionList@0:
|
||||
|
||||
/* Return the exception list */
|
||||
mov eax, [fs:TEB_EXCEPTION_LIST]
|
||||
ret
|
||||
|
||||
#ifndef __NTOSKRNL__
|
||||
.globl _RtlpSetExceptionList@4
|
||||
_RtlpSetExceptionList@4:
|
||||
|
||||
//
|
||||
// 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
|
||||
/* Get the new list */
|
||||
mov ecx, [esp+4]
|
||||
mov ecx, [ecx]
|
||||
|
||||
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)
|
||||
/* Write it */
|
||||
mov [fs:TEB_EXCEPTION_LIST], ecx
|
||||
|
||||
//
|
||||
// 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
|
||||
// ...
|
||||
//
|
||||
/* Return */
|
||||
ret 4
|
||||
|
||||
// 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
|
||||
.globl _RtlpGetExceptionAddress@0
|
||||
_RtlpGetExceptionAddress@0:
|
||||
|
||||
movl 4(%ebx), %eax // EAX = return address of caller of caller
|
||||
movl (%ebx), %ebx // EBX = EBP of caller of caller
|
||||
/* Return the address from the stack */
|
||||
mov eax, [ebp+4]
|
||||
|
||||
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 */
|
||||
ret
|
||||
|
||||
#endif /* !__NTOSKRNL__ */
|
||||
.globl _RtlCaptureContext@4
|
||||
_RtlCaptureContext@4:
|
||||
|
||||
#define REH_ERECORD 0x08
|
||||
#define REH_RFRAME 0x0C
|
||||
#define REH_CONTEXT 0x10
|
||||
#define REH_DCONTEXT 0x14
|
||||
#define REH_EROUTINE 0x18
|
||||
/* Preserve EBX and put the context in it */
|
||||
push ebx
|
||||
mov ebx, [esp+8]
|
||||
|
||||
// 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)
|
||||
/* 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
|
||||
|
||||
pushl %edx
|
||||
pushl %fs:0x0
|
||||
movl %esp, %fs:0x0
|
||||
/* Capture the other regs */
|
||||
jmp CaptureRest
|
||||
|
||||
// Prepare to call the exception handler
|
||||
pushl REH_DCONTEXT(%ebp)
|
||||
pushl REH_CONTEXT(%ebp)
|
||||
pushl REH_RFRAME(%ebp)
|
||||
pushl REH_ERECORD(%ebp)
|
||||
.globl _RtlpCaptureContext@4
|
||||
_RtlpCaptureContext@4:
|
||||
|
||||
// Now call the exception handler
|
||||
movl REH_EROUTINE(%ebp), %eax
|
||||
call *%eax
|
||||
/* Preserve EBX and put the context in it */
|
||||
push ebx
|
||||
mov ebx, [esp+8]
|
||||
|
||||
cmpl $-1, %fs:0x0
|
||||
jne .reh_stack_looks_ok
|
||||
/* 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
|
||||
|
||||
// This should not happen
|
||||
pushl 0
|
||||
pushl 0
|
||||
pushl 0
|
||||
pushl 0
|
||||
call _RtlAssert@16
|
||||
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
|
||||
|
||||
.reh_loop:
|
||||
jmp .reh_loop
|
||||
/* Capture flags */
|
||||
pushfd
|
||||
pop [ebx+CONTEXT_EFLAGS]
|
||||
|
||||
.reh_stack_looks_ok:
|
||||
movl %fs:0x0, %esp
|
||||
/* The return address should be in [ebp+4] */
|
||||
mov eax, [ebp+4]
|
||||
mov [ebx+CONTEXT_EIP], eax
|
||||
|
||||
// Return to the 'front-end' for this function
|
||||
popl %fs:0x0
|
||||
movl %ebp, %esp
|
||||
popl %ebp
|
||||
ret
|
||||
/* Get EBP */
|
||||
mov eax, [esp]
|
||||
mov [ebx+CONTEXT_EBP], eax
|
||||
|
||||
/* And get ESP */
|
||||
mov eax, [ebp+8]
|
||||
mov [ebx+CONTEXT_ESP], eax
|
||||
|
||||
#define REP_ERECORD 0x04
|
||||
#define REP_RFRAME 0x08
|
||||
#define REP_CONTEXT 0x0C
|
||||
#define REP_DCONTEXT 0x10
|
||||
/* 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
|
||||
|
|
|
@ -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,382 +14,339 @@
|
|||
#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;
|
||||
|
||||
DPRINT("RtlUnwind(). RegistrationFrame 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))
|
||||
{
|
||||
DPRINT("The exception frame is bad\n");
|
||||
|
||||
// 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;
|
||||
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("Executing handler at 0x%X for unwind\n", ERHead->handler);
|
||||
/* Get the current stack limits and registration frame */
|
||||
RtlpGetStackLimits(&StackLow, &StackHigh);
|
||||
RegistrationFrame = RtlpGetExceptionList();
|
||||
DPRINT1("RegistrationFrame is 0x%X\n", RegistrationFrame);
|
||||
|
||||
ReturnValue = RtlpExecuteHandlerForUnwind(
|
||||
pExceptRec,
|
||||
ERHead,
|
||||
&Context,
|
||||
&NewERHead,
|
||||
ERHead->handler);
|
||||
|
||||
DPRINT("Handler at 0x%X returned 0x%X\n", ERHead->handler, ReturnValue);
|
||||
|
||||
if (ReturnValue != ExceptionContinueSearch)
|
||||
/* Now loop every frame */
|
||||
while (RegistrationFrame != EXCEPTION_CHAIN_END)
|
||||
{
|
||||
if (ReturnValue != ExceptionCollidedUnwind)
|
||||
/* Find out where it ends */
|
||||
RegistrationFrameEnd = (ULONG_PTR)RegistrationFrame +
|
||||
sizeof(*RegistrationFrame);
|
||||
|
||||
/* 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
|
||||
{
|
||||
ERHead = NewERHead;
|
||||
/* Return to caller */
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
else // The stack looks goofy! Raise an exception to bail out
|
||||
else if (ReturnValue == ExceptionNestedException)
|
||||
{
|
||||
DPRINT("Bad stack\n");
|
||||
/* Turn the nested flag on */
|
||||
ExceptionRecord->ExceptionFlags |= EXCEPTION_NESTED_CALL;
|
||||
|
||||
er2.ExceptionRecord = pExceptRec;
|
||||
er2.NumberParameters = 0;
|
||||
er2.ExceptionCode = STATUS_BAD_STACK;
|
||||
er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
|
||||
|
||||
RtlRaiseException(&er2);
|
||||
/* Update the current nested frame */
|
||||
if (NestedFrame < DispatcherContext) NestedFrame = DispatcherContext;
|
||||
}
|
||||
else if (ReturnValue == ExceptionContinueSearch)
|
||||
{
|
||||
}
|
||||
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 */
|
||||
RegistrationFrame = RegistrationFrame->Next;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
/* Overwrite the argument */
|
||||
ExceptionRecord = &ExceptionRecord3;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
104
reactos/lib/rtl/rtlp.h
Normal 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 */
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -155,10 +155,8 @@ NtQuerySystemEnvironmentValue (IN PUNICODE_STRING VariableName,
|
|||
/*
|
||||
* Copy the name to kernel space if necessary and convert it to ANSI.
|
||||
*/
|
||||
Status = RtlCaptureUnicodeString(&WName,
|
||||
Status = ProbeAndCaptureUnicodeString(&WName,
|
||||
PreviousMode,
|
||||
NonPagedPool,
|
||||
FALSE,
|
||||
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,17 +269,13 @@ NtSetSystemEnvironmentValue (IN PUNICODE_STRING VariableName,
|
|||
/*
|
||||
* Copy the strings to kernel space if necessary
|
||||
*/
|
||||
Status = RtlCaptureUnicodeString(&CapturedName,
|
||||
Status = ProbeAndCaptureUnicodeString(&CapturedName,
|
||||
PreviousMode,
|
||||
NonPagedPool,
|
||||
FALSE,
|
||||
VariableName);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
Status = RtlCaptureUnicodeString(&CapturedValue,
|
||||
Status = ProbeAndCaptureUnicodeString(&CapturedValue,
|
||||
PreviousMode,
|
||||
NonPagedPool,
|
||||
FALSE,
|
||||
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;
|
||||
|
|
|
@ -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,8 +362,9 @@ KiMoveApcState (PKAPC_STATE OldState,
|
|||
VOID
|
||||
KiAddProfileEvent(KPROFILE_SOURCE Source, ULONG Pc);
|
||||
VOID
|
||||
NTAPI
|
||||
KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
|
||||
PCONTEXT Context,
|
||||
PKEXCEPTION_FRAME ExceptionFrame,
|
||||
PKTRAP_FRAME Tf,
|
||||
KPROCESSOR_MODE PreviousMode,
|
||||
BOOLEAN SearchFrames);
|
||||
|
|
|
@ -76,32 +76,89 @@ RtlpCreateUnicodeString(
|
|||
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)
|
||||
|
|
|
@ -1878,10 +1878,8 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
|
|||
}
|
||||
#endif
|
||||
|
||||
Status = RtlCaptureUnicodeString(&CapturedDriverServiceName,
|
||||
Status = ProbeAndCaptureUnicodeString(&CapturedDriverServiceName,
|
||||
PreviousMode,
|
||||
PagedPool,
|
||||
FALSE,
|
||||
DriverServiceName);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
|
@ -2021,9 +2019,8 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
|
|||
Status = IopStartDevice(DeviceNode);
|
||||
|
||||
ReleaseCapturedString:
|
||||
RtlReleaseCapturedUnicodeString(&CapturedDriverServiceName,
|
||||
PreviousMode,
|
||||
FALSE);
|
||||
ReleaseCapturedUnicodeString(&CapturedDriverServiceName,
|
||||
PreviousMode);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
/* 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;
|
||||
DPRINT("TrapFrame->Eip: %x\n", TrapFrame->Eip);
|
||||
TrapFrame->Esp = (ULONG)Esp;
|
||||
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;
|
||||
}
|
||||
|
||||
/*++
|
||||
|
|
157
reactos/ntoskrnl/ke/exception.c
Normal file
157
reactos/ntoskrnl/ke/exception.c
Normal 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 */
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -792,10 +792,8 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName,
|
|||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
Status = RtlCaptureUnicodeString(&CapturedFileName,
|
||||
Status = ProbeAndCaptureUnicodeString(&CapturedFileName,
|
||||
PreviousMode,
|
||||
PagedPool,
|
||||
FALSE,
|
||||
FileName);
|
||||
if (!NT_SUCCESS(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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -200,10 +200,8 @@ NtCreateSymbolicLinkObject(OUT PHANDLE LinkHandle,
|
|||
}
|
||||
}
|
||||
|
||||
Status = RtlCaptureUnicodeString(&CapturedLinkTarget,
|
||||
Status = ProbeAndCaptureUnicodeString(&CapturedLinkTarget,
|
||||
PreviousMode,
|
||||
PagedPool,
|
||||
FALSE,
|
||||
LinkTarget);
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
|
@ -263,9 +261,8 @@ NtCreateSymbolicLinkObject(OUT PHANDLE LinkHandle,
|
|||
ObDereferenceObject(SymbolicLink);
|
||||
}
|
||||
|
||||
RtlReleaseCapturedUnicodeString(&CapturedLinkTarget,
|
||||
PreviousMode,
|
||||
FALSE);
|
||||
ReleaseCapturedUnicodeString(&CapturedLinkTarget,
|
||||
PreviousMode);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include <stdarg.h>
|
||||
#include <windef.h>
|
||||
#include <excpt.h>
|
||||
#include <ntdef.h>
|
||||
#include <basetyps.h>
|
||||
|
||||
|
|
90
reactos/w32api/include/excpt.h
Normal file
90
reactos/w32api/include/excpt.h
Normal 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 */
|
Loading…
Reference in a new issue