Major refactoring of the exception handling code + misc fixes:

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

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

View file

@ -144,6 +144,10 @@
#define CONTEXT_FLAGS 0x0 #define CONTEXT_FLAGS 0x0
#define CONTEXT_DR6 0x14 #define CONTEXT_DR6 0x14
#define CONTEXT_FLOAT_SAVE 0x1C #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_EDI 0x9C
#define CONTEXT_ESI 0xA0 #define CONTEXT_ESI 0xA0
#define CONTEXT_EBX 0xA4 #define CONTEXT_EBX 0xA4
@ -152,21 +156,37 @@
#define CONTEXT_EAX 0xB0 #define CONTEXT_EAX 0xB0
#define CONTEXT_EBP 0xB4 #define CONTEXT_EBP 0xB4
#define CONTEXT_EIP 0xB8 #define CONTEXT_EIP 0xB8
#define CONTEXT_SEGCS 0xBC
#define CONTEXT_EFLAGS 0xC0
#define CONTEXT_ESP 0xC4 #define CONTEXT_ESP 0xC4
#define CONTEXT_SEGSS 0xC8
#define CONTEXT_FLOAT_SAVE_CONTROL_WORD CONTEXT_FLOAT_SAVE + FN_CONTROL_WORD #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_STATUS_WORD CONTEXT_FLOAT_SAVE + FN_STATUS_WORD
#define CONTEXT_FLOAT_SAVE_TAG_WORD CONTEXT_FLOAT_SAVE + FN_TAG_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 */ /* TEB CONSTANTS */
#define TEB_EXCEPTION_LIST 0x0 #define TEB_EXCEPTION_LIST 0x0
#define TEB_STACK_BASE 0x4 #define TEB_STACK_BASE 0x4
#define TEB_STACK_LIMIT 0x8 #define TEB_STACK_LIMIT 0x8
#define TEB_FIBER_DATA 0x10 #define TEB_FIBER_DATA 0x10
#define TEB_PEB 0x30
#define TEB_EXCEPTION_CODE 0x1A4
#define TEB_ACTIVATION_CONTEXT_STACK_POINTER 0x1A8 #define TEB_ACTIVATION_CONTEXT_STACK_POINTER 0x1A8
#define TEB_DEALLOCATION_STACK 0xE0C #define TEB_DEALLOCATION_STACK 0xE0C
#define TEB_GUARANTEED_STACK_BYTES 0xF78 #define TEB_GUARANTEED_STACK_BYTES 0xF78
#define TEB_FLS_DATA 0xFB4 #define TEB_FLS_DATA 0xFB4
/* PEB CONSTANTS */
#define PEB_KERNEL_CALLBACK_TABLE 0x2C
/* FIBER CONSTANTS */ /* FIBER CONSTANTS */
#define FIBER_PARAMETER 0x0 #define FIBER_PARAMETER 0x0
#define FIBER_EXCEPTION_LIST 0x4 #define FIBER_EXCEPTION_LIST 0x4

View file

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

View file

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

View file

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

View file

@ -63,6 +63,12 @@
* -- AJ * -- 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. /* 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 * This is only useful when compiling to a native Windows binary, as the built-in
* compiler exceptions will most certainly not work under Winelib. * compiler exceptions will most certainly not work under Winelib.

View file

@ -1,11 +1,15 @@
#include "precomp.h" #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 * @implemented
*/ */
void __cdecl void __cdecl
_global_unwind2(PEXCEPTION_REGISTRATION RegistrationFrame) _global_unwind2(PEXCEPTION_REGISTRATION_RECORD RegistrationFrame)
{ {
#ifdef __GNUC__ #ifdef __GNUC__
RtlUnwind(RegistrationFrame, &&__ret_label, NULL, 0); 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 */ /* VC++ extensions to Win32 SEH */
typedef struct _SCOPETABLE typedef struct _SCOPETABLE
{ {
@ -35,8 +31,8 @@ typedef struct _SCOPETABLE
typedef struct _MSVCRT_EXCEPTION_FRAME typedef struct _MSVCRT_EXCEPTION_FRAME
{ {
EXCEPTION_FRAME *prev; PEXCEPTION_REGISTRATION_RECORD *prev;
void (*handler)(PEXCEPTION_RECORD, PEXCEPTION_FRAME, void (*handler)(PEXCEPTION_RECORD, PEXCEPTION_REGISTRATION_RECORD,
PCONTEXT, PEXCEPTION_RECORD); PCONTEXT, PEXCEPTION_RECORD);
PSCOPETABLE scopetable; PSCOPETABLE scopetable;
int trylevel; int trylevel;

View file

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

View file

@ -31,7 +31,6 @@
#include "winreg.h" #include "winreg.h"
#include "ntstatus.h" #include "ntstatus.h"
#include "thread.h" /* FIXME: must be included before winternl.h */ #include "thread.h" /* FIXME: must be included before winternl.h */
#include "winternl.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "stackframe.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 /* cur_switch holds address of curr_stack's field in TEB in debuggee
* address space * address space
*/ */
/*
if (NtQueryInformationThread(hThread, ThreadBasicInformation, &info, if (NtQueryInformationThread(hThread, ThreadBasicInformation, &info,
sizeof(info), NULL) != STATUS_SUCCESS) sizeof(info), NULL) != STATUS_SUCCESS)
goto done_err; 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, if (!f_read_mem(hProcess, (void*)curr_switch, &next_switch,
sizeof(next_switch), NULL)) sizeof(next_switch), NULL))
{ {

View file

@ -23,7 +23,10 @@
#include <string.h> #include <string.h>
#include <winnt.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 SELECTOROF(ptr) (HIWORD(ptr))
#define OFFSETOF(ptr) (LOWORD(ptr)) #define OFFSETOF(ptr) (LOWORD(ptr))
@ -77,23 +80,5 @@ return -1;
#define CURRENT_STACK16 ((STACK16FRAME*)MapSL(NtCurrentTeb()->cur_stack)) #define CURRENT_STACK16 ((STACK16FRAME*)MapSL(NtCurrentTeb()->cur_stack))
#define CURRENT_DS (CURRENT_STACK16->ds) #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 */ #endif /* __WINE_STACKFRAME_H */

View file

@ -26,7 +26,6 @@
#include <winbase.h> #include <winbase.h>
#include <winreg.h> #include <winreg.h>
#define WINE_NO_TEB #define WINE_NO_TEB
#include <winternl.h>
#include <wine/windef16.h> #include <wine/windef16.h>
struct _SECURITY_ATTRIBUTES; struct _SECURITY_ATTRIBUTES;
@ -42,114 +41,4 @@ struct debug_info
char output[1024]; /* current output line */ 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 */ #endif /* __WINE_THREAD_H */

View file

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

View file

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

View file

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

View file

@ -1,8 +1,9 @@
/* COPYRIGHT: See COPYING in the top level directory /* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries * PROJECT: ReactOS NT Library
* PURPOSE: User-mode APC support
* FILE: lib/ntdll/main/dispatch.c * 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 *****************************************************************/ /* INCLUDES *****************************************************************/
@ -11,77 +12,41 @@
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
typedef NTSTATUS (STDCALL *KERNEL_CALLBACK_FUNCTION)(PVOID Argument, typedef NTSTATUS (STDCALL *USER_CALL)(PVOID Argument, ULONG ArgumentLength);
ULONG ArgumentLength);
EXCEPTION_DISPOSITION
RtlpExecuteVectoredExceptionHandlers(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context);
ULONG
RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context);
/* FUNCTIONS ****************************************************************/ /* 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 * @implemented
*/ */
VOID VOID
STDCALL STDCALL
KiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord, KiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord,
PCONTEXT Context) PCONTEXT Context)
{ {
EXCEPTION_RECORD NestedExceptionRecord; EXCEPTION_RECORD NestedExceptionRecord;
NTSTATUS Status; NTSTATUS Status;
if(RtlpExecuteVectoredExceptionHandlers(ExceptionRecord, /* Dispatch the exception and check the result */
Context) != ExceptionContinueExecution) if(RtlDispatchException(ExceptionRecord, Context))
{ {
Status = NtContinue(Context, FALSE); /* Continue executing */
Status = NtContinue(Context, FALSE);
} }
else else
{ {
if(RtlpDispatchException(ExceptionRecord, Context) != ExceptionContinueExecution) /* Raise an exception */
{ Status = NtRaiseException(ExceptionRecord, Context, FALSE);
Status = NtContinue(Context, FALSE);
}
else
{
Status = NtRaiseException(ExceptionRecord, Context, FALSE);
}
} }
NestedExceptionRecord.ExceptionCode = Status; /* Setup the Exception record */
NestedExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE; NestedExceptionRecord.ExceptionCode = Status;
NestedExceptionRecord.ExceptionRecord = ExceptionRecord; NestedExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
NestedExceptionRecord.NumberParameters = Status; NestedExceptionRecord.ExceptionRecord = ExceptionRecord;
NestedExceptionRecord.NumberParameters = Status;
RtlRaiseException(&NestedExceptionRecord); /* Raise the exception */
RtlRaiseException(&NestedExceptionRecord);
} }
/* /*
@ -91,14 +56,16 @@ VOID
STDCALL STDCALL
KiRaiseUserExceptionDispatcher(VOID) KiRaiseUserExceptionDispatcher(VOID)
{ {
EXCEPTION_RECORD ExceptionRecord; EXCEPTION_RECORD ExceptionRecord;
ExceptionRecord.ExceptionCode = ((PTEB)NtCurrentTeb())->ExceptionCode; /* Setup the exception record */
ExceptionRecord.ExceptionFlags = 0; ExceptionRecord.ExceptionCode = ((PTEB)NtCurrentTeb())->ExceptionCode;
ExceptionRecord.ExceptionRecord = NULL; ExceptionRecord.ExceptionFlags = 0;
ExceptionRecord.NumberParameters = 0; ExceptionRecord.ExceptionRecord = NULL;
ExceptionRecord.NumberParameters = 0;
RtlRaiseException(&ExceptionRecord); /* Raise the exception */
RtlRaiseException(&ExceptionRecord);
} }
/* /*
@ -106,16 +73,13 @@ KiRaiseUserExceptionDispatcher(VOID)
*/ */
VOID VOID
STDCALL STDCALL
KiUserCallbackDispatcher(ULONG RoutineIndex, KiUserCallbackDispatcher(ULONG Index,
PVOID Argument, PVOID Argument,
ULONG ArgumentLength) ULONG ArgumentLength)
{ {
PPEB Peb; /* Return with the result of the callback function */
NTSTATUS Status; ZwCallbackReturn(NULL,
KERNEL_CALLBACK_FUNCTION Callback; 0,
((USER_CALL)(NtCurrentPeb()->KernelCallbackTable[Index]))
Peb = NtCurrentPeb(); (Argument, ArgumentLength));
Callback = (KERNEL_CALLBACK_FUNCTION)Peb->KernelCallbackTable[RoutineIndex];
Status = Callback(Argument, ArgumentLength);
ZwCallbackReturn(NULL, 0, Status);
} }

View file

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

View file

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

View file

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

View file

@ -1,9 +1,10 @@
/* /*
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS NT User-Mode DLL
* FILE: lib/ntdll/rtl/libsup.c * FILE: lib/ntdll/rtl/libsup.c
* PURPOSE: Rtl library support routines * PURPOSE: RTL Support Routines
* PROGRAMMER: Gunnar Dalsnes * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
* Gunnar Dalsnes
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
@ -14,6 +15,13 @@
/* FUNCTIONS ***************************************************************/ /* FUNCTIONS ***************************************************************/
BOOLEAN
NTAPI
RtlpCheckForActiveDebugger(VOID)
{
return (NtCurrentPeb()->BeingDebugged);
}
KPROCESSOR_MODE KPROCESSOR_MODE
STDCALL STDCALL
RtlpGetMode() RtlpGetMode()
@ -28,7 +36,6 @@ RtlpCurrentPeb(VOID)
return NtCurrentPeb(); return NtCurrentPeb();
} }
/* /*
* @implemented * @implemented
*/ */
@ -39,7 +46,6 @@ RtlAcquirePebLock(VOID)
Peb->FastPebLockRoutine (Peb->FastPebLock); Peb->FastPebLockRoutine (Peb->FastPebLock);
} }
/* /*
* @implemented * @implemented
*/ */
@ -57,8 +63,8 @@ ULONG
STDCALL STDCALL
RtlGetNtGlobalFlags(VOID) RtlGetNtGlobalFlags(VOID)
{ {
PPEB pPeb = NtCurrentPeb(); PPEB pPeb = NtCurrentPeb();
return pPeb->NtGlobalFlag; return pPeb->NtGlobalFlag;
} }
NTSTATUS NTSTATUS
@ -82,7 +88,7 @@ STDCALL
RtlInitializeHeapLock( RtlInitializeHeapLock(
PRTL_CRITICAL_SECTION CriticalSection) PRTL_CRITICAL_SECTION CriticalSection)
{ {
return RtlInitializeCriticalSection(CriticalSection ); return RtlInitializeCriticalSection(CriticalSection);
} }
NTSTATUS NTSTATUS
@ -127,6 +133,27 @@ CHECK_PAGED_CODE_RTL(char *file, int line)
} }
#endif #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 ************************************************************/ /* RTL Atom Tables ************************************************************/
typedef struct _RTL_ATOM_HANDLE typedef struct _RTL_ATOM_HANDLE

View file

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

View file

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

View file

@ -1,10 +1,10 @@
/* $Id$ /*
*
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS Run-Time Library
* PURPOSE: User-mode exception support for IA-32 * PURPOSE: User-mode exception support for IA-32
* FILE: lib/ntdll/rtl/i386/exception.c * FILE: lib/rtl/i386/exception.c
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) * PROGRAMERS: Alex Ionescu (alex@relsoft.net)
* Casper S. Hornstrup (chorns@users.sourceforge.net)
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
@ -14,383 +14,340 @@
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
/* FUNCTIONS ***************************************************************/ /* PRIVATE FUNCTIONS *********************************************************/
/* Implemented in except.s */
VOID VOID
RtlpCaptureContext(PCONTEXT pContext); STDCALL
RtlpGetStackLimits(PULONG_PTR StackBase,
PULONG_PTR StackLimit);
#define SehpGetStackLimits(StackBase, StackLimit) \ PEXCEPTION_REGISTRATION_RECORD
{ \ STDCALL
(*(StackBase)) = NtCurrentTeb()->Tib->StackBase; \ RtlpGetExceptionList(VOID);
(*(StackLimit)) = NtCurrentTeb()->Tib->StackLimit; \
}
#define SehpGetExceptionList() \ VOID
(PEXCEPTION_REGISTRATION)(NtCurrentTeb()->Tib.ExceptionList) STDCALL
RtlpSetExceptionList(PEXCEPTION_REGISTRATION_RECORD NewExceptionList);
#define SehpSetExceptionList(NewExceptionList) \ /* PUBLIC FUNCTIONS **********************************************************/
NtCurrentTeb()->Tib.ExceptionList = (PVOID)(NewExceptionList)
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 * @implemented
*/ */
VOID STDCALL BOOLEAN
RtlUnwind(PEXCEPTION_REGISTRATION RegistrationFrame, STDCALL
PVOID ReturnAddress, RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT Context)
DWORD EaxValue)
{ {
PEXCEPTION_REGISTRATION ERHead; PEXCEPTION_REGISTRATION_RECORD RegistrationFrame, NestedFrame = NULL;
PEXCEPTION_RECORD pExceptRec; PEXCEPTION_REGISTRATION_RECORD DispatcherContext;
EXCEPTION_RECORD TempER; EXCEPTION_RECORD ExceptionRecord2;
CONTEXT Context; EXCEPTION_DISPOSITION ReturnValue;
ULONG_PTR StackLow, StackHigh;
ULONG_PTR RegistrationFrameEnd;
DPRINT1("RtlDispatchException(): %p, %p \n", ExceptionRecord, Context);
DPRINT("RtlUnwind(). RegistrationFrame 0x%X\n", RegistrationFrame); /* Get the current stack limits and registration frame */
RtlpGetStackLimits(&StackLow, &StackHigh);
RegistrationFrame = RtlpGetExceptionList();
DPRINT1("RegistrationFrame is 0x%X\n", RegistrationFrame);
#ifndef NDEBUG /* Now loop every frame */
RtlpDumpExceptionRegistrations(); while (RegistrationFrame != EXCEPTION_CHAIN_END)
#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"); /* Find out where it ends */
RegistrationFrameEnd = (ULONG_PTR)RegistrationFrame +
sizeof(*RegistrationFrame);
// Generate an exception to bail out /* Make sure the registration frame is located within the stack */
er2.ExceptionRecord = pExceptRec; if ((RegistrationFrameEnd > StackHigh) ||
er2.NumberParameters = 0; ((ULONG_PTR)RegistrationFrame < StackLow) ||
er2.ExceptionCode = STATUS_INVALID_UNWIND_TARGET; ((ULONG_PTR)RegistrationFrame & 0x3))
er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
RtlRaiseException(&er2);
}
#if 0
Stack = ERHead + sizeof(EXCEPTION_REGISTRATION);
if ( (Teb->Tib.StackBase <= (PVOID)ERHead ) // Make sure that ERHead
&& (Teb->Tib.->StackLimit >= (PVOID)Stack ) // is in range, and a multiple
&& (0 == ((ULONG_PTR)ERHead & 3)) ) // of 4 (i.e., sane)
#else
if (1)
#endif
{
PEXCEPTION_REGISTRATION NewERHead;
PEXCEPTION_REGISTRATION pCurrExceptReg;
EXCEPTION_DISPOSITION ReturnValue;
DPRINT("Executing handler at 0x%X for unwind\n", ERHead->handler);
ReturnValue = RtlpExecuteHandlerForUnwind(
pExceptRec,
ERHead,
&Context,
&NewERHead,
ERHead->handler);
DPRINT("Handler at 0x%X returned 0x%X\n", ERHead->handler, ReturnValue);
if (ReturnValue != ExceptionContinueSearch)
{
if (ReturnValue != ExceptionCollidedUnwind)
{ {
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; /* Set invalid stack and return false */
er2.NumberParameters = 0; ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
er2.ExceptionCode = STATUS_INVALID_DISPOSITION; DPRINT1("Invalid exception frame\n");
er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; return FALSE;
}
RtlRaiseException(&er2); /* Check if logging is enabled */
DPRINT1("Checking for logging\n");
RtlpCheckLogException(ExceptionRecord,
Context,
RegistrationFrame,
sizeof(*RegistrationFrame));
/* Call the handler */
DPRINT1("Executing handler: %p\n", RegistrationFrame->Handler);
ReturnValue = RtlpExecuteHandlerForException(ExceptionRecord,
RegistrationFrame,
Context,
&DispatcherContext,
RegistrationFrame->Handler);
DPRINT1("Handler returned: %lx\n", ReturnValue);
/* Check if this is a nested frame */
if (RegistrationFrame == NestedFrame)
{
/* Mask out the flag and the nested frame */
ExceptionRecord->ExceptionFlags &= ~EXCEPTION_NESTED_CALL;
NestedFrame = NULL;
}
/* Handle the dispositions */
if (ReturnValue == ExceptionContinueExecution)
{
/* Check if it was non-continuable */
if (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
{
/* Set up the exception record */
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
ExceptionRecord2.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION;
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
ExceptionRecord2.NumberParameters = 0;
/* Raise the exception */
DPRINT1("Non-continuable\n");
RtlRaiseException(&ExceptionRecord2);
}
else
{
/* Return to caller */
return TRUE;
}
}
else if (ReturnValue == ExceptionNestedException)
{
/* Turn the nested flag on */
ExceptionRecord->ExceptionFlags |= EXCEPTION_NESTED_CALL;
/* Update the current nested frame */
if (NestedFrame < DispatcherContext) NestedFrame = DispatcherContext;
}
else if (ReturnValue == ExceptionContinueSearch)
{
} }
else else
{ {
ERHead = NewERHead; /* Set up the exception record */
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION;
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
ExceptionRecord2.NumberParameters = 0;
/* Raise the exception */
RtlRaiseException(&ExceptionRecord2);
} }
}
pCurrExceptReg = ERHead; /* Go to the next frame */
ERHead = ERHead->prev; RegistrationFrame = RegistrationFrame->Next;
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
/* Unhandled, return false */
DPRINT1("FALSE:(\n");
return FALSE;
}
/*
* @implemented
*/
VOID
STDCALL
RtlUnwind(PVOID RegistrationFrame OPTIONAL,
PVOID ReturnAddress OPTIONAL,
PEXCEPTION_RECORD ExceptionRecord OPTIONAL,
PVOID EaxValue)
{
PEXCEPTION_REGISTRATION_RECORD RegistrationFrame2, OldFrame;
PEXCEPTION_REGISTRATION_RECORD DispatcherContext;
EXCEPTION_RECORD ExceptionRecord2, ExceptionRecord3;
EXCEPTION_DISPOSITION ReturnValue;
ULONG_PTR StackLow, StackHigh;
ULONG_PTR RegistrationFrameEnd;
CONTEXT LocalContext;
PCONTEXT Context;
DPRINT1("RtlUnwind(). RegistrationFrame 0x%X\n", RegistrationFrame);
/* Get the current stack limits */
RtlpGetStackLimits(&StackLow, &StackHigh);
/* Check if we don't have an exception record */
if (!ExceptionRecord)
{ {
DPRINT("Bad stack\n"); /* Overwrite the argument */
ExceptionRecord = &ExceptionRecord3;
er2.ExceptionRecord = pExceptRec; /* Setup a local one */
er2.NumberParameters = 0; ExceptionRecord3.ExceptionFlags = 0;
er2.ExceptionCode = STATUS_BAD_STACK; ExceptionRecord3.ExceptionCode = STATUS_UNWIND;
er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; ExceptionRecord3.ExceptionRecord = NULL;
ExceptionRecord3.ExceptionAddress = RtlpGetExceptionAddress();
RtlRaiseException(&er2); ExceptionRecord3.NumberParameters = 0;
}
/* Check if we have a frame */
if (RegistrationFrame)
{
/* Set it as unwinding */
ExceptionRecord->ExceptionFlags |= EXCEPTION_UNWINDING;
}
else
{
/* Set the Exit Unwind flag as well */
ExceptionRecord->ExceptionFlags |= (EXCEPTION_UNWINDING |
EXCEPTION_EXIT_UNWIND);
}
/* Now capture the context */
Context = &LocalContext;
LocalContext.ContextFlags = CONTEXT_INTEGER |
CONTEXT_CONTROL |
CONTEXT_SEGMENTS;
RtlpCaptureContext(Context);
/* Pop the current arguments off */
LocalContext.Esp += sizeof(RegistrationFrame) +
sizeof(ReturnAddress) +
sizeof(ExceptionRecord) +
sizeof(ReturnValue);
/* Set the new value for EAX */
LocalContext.Eax = (ULONG)EaxValue;
/* Get the current frame */
RegistrationFrame2 = RtlpGetExceptionList();
/* Now loop every frame */
while (RegistrationFrame2 != EXCEPTION_CHAIN_END)
{
DPRINT1("RegistrationFrame is 0x%X\n", RegistrationFrame2);
/* If this is the target */
if (RegistrationFrame2 == RegistrationFrame)
{
/* Continue execution */
ZwContinue(Context, FALSE);
}
/* Check if the frame is too low */
if ((RegistrationFrame) && ((ULONG_PTR)RegistrationFrame <
(ULONG_PTR)RegistrationFrame2))
{
/* Create an invalid unwind exception */
ExceptionRecord2.ExceptionCode = STATUS_INVALID_UNWIND_TARGET;
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
ExceptionRecord2.NumberParameters = 0;
/* Raise the exception */
DPRINT1("Frame is invalid\n");
RtlRaiseException(&ExceptionRecord2);
}
/* Find out where it ends */
RegistrationFrameEnd = (ULONG_PTR)RegistrationFrame2 +
sizeof(*RegistrationFrame2);
/* Make sure the registration frame is located within the stack */
if ((RegistrationFrameEnd > StackHigh) ||
((ULONG_PTR)RegistrationFrame < StackLow) ||
((ULONG_PTR)RegistrationFrame & 0x3))
{
/* Check if this happened in the DPC Stack */
if (RtlpHandleDpcStackException(RegistrationFrame,
RegistrationFrameEnd,
&StackLow,
&StackHigh))
{
/* Use DPC Stack Limits and restart */
continue;
}
/* Create an invalid stack exception */
ExceptionRecord2.ExceptionCode = STATUS_BAD_STACK;
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
ExceptionRecord2.NumberParameters = 0;
/* Raise the exception */
DPRINT1("Frame has bad stack\n");
RtlRaiseException(&ExceptionRecord2);
}
else
{
/* Call the handler */
DPRINT1("Executing unwind handler: %p\n", RegistrationFrame2->Handler);
ReturnValue = RtlpExecuteHandlerForUnwind(ExceptionRecord,
RegistrationFrame2,
Context,
&DispatcherContext,
RegistrationFrame2->Handler);
DPRINT1("Handler returned: %lx\n", ReturnValue);
/* Handle the dispositions */
if (ReturnValue == ExceptionContinueSearch)
{
/* Get out of here */
break;
}
else if (ReturnValue == ExceptionCollidedUnwind)
{
/* Get the previous frame */
RegistrationFrame2 = DispatcherContext;
}
else
{
/* Set up the exception record */
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION;
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
ExceptionRecord2.NumberParameters = 0;
/* Raise the exception */
RtlRaiseException(&ExceptionRecord2);
}
/* Go to the next frame */
OldFrame = RegistrationFrame2;
RegistrationFrame2 = RegistrationFrame2->Next;
/* Remove this handler */
RtlpSetExceptionList(OldFrame);
}
}
/* Check if we reached the end */
if (RegistrationFrame == EXCEPTION_CHAIN_END)
{
/* Unwind completed, so we don't exit */
ZwContinue(Context, FALSE);
}
else
{
/* This is an exit_unwind or the frame wasn't present in the list */
ZwRaiseException(ExceptionRecord, Context, FALSE);
} }
}
} }
/* EOF */ /* EOF */

View file

@ -23,27 +23,7 @@
/* Helper Header */ /* Helper Header */
#include <reactos/helper.h> #include <reactos/helper.h>
/* FIXME: Move this somewhere else, maybe */ /* Internal RTL header */
#ifdef DBG #include "rtlp.h"
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')
/* EOF */ /* EOF */

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

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

View file

@ -29,7 +29,7 @@ STDCALL
ExRaiseAccessViolation(VOID) ExRaiseAccessViolation(VOID)
{ {
/* Raise the Right Status */ /* Raise the Right Status */
ExRaiseStatus (STATUS_ACCESS_VIOLATION); RtlRaiseStatus(STATUS_ACCESS_VIOLATION);
} }
/* /*
@ -40,39 +40,7 @@ STDCALL
ExRaiseDatatypeMisalignment (VOID) ExRaiseDatatypeMisalignment (VOID)
{ {
/* Raise the Right Status */ /* Raise the Right Status */
ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT); RtlRaiseStatus(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);
} }
/* /*

View file

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

View file

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

View file

@ -75,33 +75,90 @@ RtlpCreateUnicodeString(
IN OUT PUNICODE_STRING UniDest, IN OUT PUNICODE_STRING UniDest,
IN PCWSTR Source, IN PCWSTR Source,
IN POOL_TYPE PoolType); 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 VOID
RtlReleaseCapturedUnicodeString( NTAPI
IN PUNICODE_STRING CapturedString, RtlpLogException(IN PEXCEPTION_RECORD ExceptionRecord,
IN KPROCESSOR_MODE CurrentMode, IN PCONTEXT ContextRecord,
IN BOOLEAN CaptureIfKernel IN PVOID ContextData,
); IN ULONG Size);
#define ExRaiseStatus RtlRaiseStatus
/* /*
* Inlined Probing Macros * 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! * NOTE: Alignment of the pointers is not verified!
*/ */
#define ProbeForWriteGenericType(Ptr, Type) \ #define ProbeForWriteGenericType(Ptr, Type) \
do { \ do { \
if ((ULONG_PTR)(Ptr) + sizeof(Type) - 1 < (ULONG_PTR)(Ptr) || \ if ((ULONG_PTR)(Ptr) + sizeof(Type) - 1 < (ULONG_PTR)(Ptr) || \
(ULONG_PTR)(Ptr) + sizeof(Type) - 1 >= (ULONG_PTR)MmUserProbeAddress) { \ (ULONG_PTR)(Ptr) + sizeof(Type) - 1 >= (ULONG_PTR)MmUserProbeAddress) { \
ExRaiseStatus (STATUS_ACCESS_VIOLATION); \ RtlRaiseStatus (STATUS_ACCESS_VIOLATION); \
} \ } \
*(volatile Type *)(Ptr) = *(volatile Type *)(Ptr); \ *(volatile Type *)(Ptr) = *(volatile Type *)(Ptr); \
} while (0) } while (0)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -15,6 +15,16 @@
#define NDEBUG #define NDEBUG
#include <internal/debug.h> #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 *****************************************************************/ /* GLOBALS *****************************************************************/
#define FLAG_IF (1<<9) #define FLAG_IF (1<<9)
@ -172,7 +182,7 @@ KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
/* FIXME: Which exceptions are noncontinuable? */ /* FIXME: Which exceptions are noncontinuable? */
Er.ExceptionFlags = 0; Er.ExceptionFlags = 0;
KiDispatchException(&Er, 0, Tf, KernelMode, TRUE); KiDispatchException(&Er, NULL, Tf, KernelMode, TRUE);
return(0); return(0);
} }
@ -559,6 +569,7 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
BOOLEAN BOOLEAN
STDCALL STDCALL
KeContextToTrapFrame(PCONTEXT Context, KeContextToTrapFrame(PCONTEXT Context,
PKEXCEPTION_FRAME ExceptionFrame,
PKTRAP_FRAME TrapFrame) PKTRAP_FRAME TrapFrame)
{ {
/* Start with the basic Registers */ /* Start with the basic Registers */
@ -907,6 +918,158 @@ KeInitExceptions(VOID)
set_system_call_gate(0x2e,(int)KiSystemService); 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 * @implemented
*/ */
@ -927,32 +1090,3 @@ KeRaiseUserException(IN NTSTATUS ExceptionCode)
return((NTSTATUS)OldEip); return((NTSTATUS)OldEip);
} }
/*
* @implemented
*/
NTSTATUS
STDCALL
NtRaiseException (
IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context,
IN BOOLEAN SearchFrames)
{
PKTHREAD Thread = KeGetCurrentThread();
PKTRAP_FRAME TrapFrame = Thread->TrapFrame;
PKTRAP_FRAME PrevTrapFrame = (PKTRAP_FRAME)TrapFrame->Edx;
KeGetCurrentKPCR()->Tib.ExceptionList = TrapFrame->ExceptionList;
KiDispatchException(ExceptionRecord,
Context,
TrapFrame,
KeGetPreviousMode(),
SearchFrames);
/* Restore the user context */
Thread->TrapFrame = PrevTrapFrame;
__asm__("mov %%ebx, %%esp;\n" "jmp _KiServiceExit": : "b" (TrapFrame));
/* We never get here */
return(STATUS_SUCCESS);
}

View file

@ -569,7 +569,7 @@ KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr)
/* Dispatch exception */ /* Dispatch exception */
DPRINT("Dispatching exception (ExceptionCode = 0x%08x)\n", Er.ExceptionCode); 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"); DPRINT("Math-fault handled!\n");
return STATUS_SUCCESS; return STATUS_SUCCESS;

View file

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

View file

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

View file

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

View file

@ -352,5 +352,26 @@ _KiTrapUnknown:
movl $255, %esi movl $255, %esi
jmp _KiTrapProlog 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 */ /* EOF */

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,11 +1,10 @@
/* $Id$ /*
*
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: ntoskrnl/rtl/libsupp.c * FILE: ntoskrnl/rtl/libsupp.c
* PURPOSE: Rtl library support routines * PURPOSE: RTL Support Routines
* * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
* PROGRAMMERS: No programmer listed. * Gunnar Dalsnes
*/ */
/* INCLUDES ******************************************************************/ /* INCLUDES ******************************************************************/
@ -14,8 +13,17 @@
#define NDEBUG #define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
extern ULONG NtGlobalFlag;
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
BOOLEAN
NTAPI
RtlpCheckForActiveDebugger(VOID)
{
/* This check is meaningless in kernel-mode */
return TRUE;
}
KPROCESSOR_MODE KPROCESSOR_MODE
STDCALL STDCALL
@ -124,6 +132,53 @@ CHECK_PAGED_CODE_RTL(char *file, int line)
} }
#endif #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 ************************************************************/ /* RTL Atom Tables ************************************************************/
NTSTATUS NTSTATUS

View file

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

View file

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