Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenexcept.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: BSD - See COPYING.ARM in the top level directory 00004 * FILE: ntoskrnl/ke/except.c 00005 * PURPOSE: Platform independent exception handling 00006 * PROGRAMMERS: ReactOS Portable Systems Group 00007 * Alex Ionescu (alex.ionescu@reactos.org) 00008 */ 00009 00010 /* INCLUDES ******************************************************************/ 00011 00012 #include <ntoskrnl.h> 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 /* FUNCTIONS *****************************************************************/ 00017 00018 VOID 00019 NTAPI 00020 KiContinuePreviousModeUser(IN PCONTEXT Context, 00021 IN PKEXCEPTION_FRAME ExceptionFrame, 00022 IN PKTRAP_FRAME TrapFrame) 00023 { 00024 CONTEXT LocalContext; 00025 00026 /* We'll have to make a copy and probe it */ 00027 ProbeForRead(Context, sizeof(CONTEXT), sizeof(ULONG)); 00028 RtlCopyMemory(&LocalContext, Context, sizeof(CONTEXT)); 00029 Context = &LocalContext; 00030 00031 /* Convert the context into Exception/Trap Frames */ 00032 KeContextToTrapFrame(&LocalContext, 00033 ExceptionFrame, 00034 TrapFrame, 00035 LocalContext.ContextFlags, 00036 UserMode); 00037 } 00038 00039 NTSTATUS 00040 NTAPI 00041 KiContinue(IN PCONTEXT Context, 00042 IN PKEXCEPTION_FRAME ExceptionFrame, 00043 IN PKTRAP_FRAME TrapFrame) 00044 { 00045 NTSTATUS Status = STATUS_SUCCESS; 00046 KIRQL OldIrql = APC_LEVEL; 00047 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 00048 00049 /* Raise to APC_LEVEL, only if needed */ 00050 if (KeGetCurrentIrql() < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql); 00051 00052 /* Set up SEH to validate the context */ 00053 _SEH2_TRY 00054 { 00055 /* Check the previous mode */ 00056 if (PreviousMode != KernelMode) 00057 { 00058 /* Validate from user-mode */ 00059 KiContinuePreviousModeUser(Context, 00060 ExceptionFrame, 00061 TrapFrame); 00062 } 00063 else 00064 { 00065 /* Convert the context into Exception/Trap Frames */ 00066 KeContextToTrapFrame(Context, 00067 ExceptionFrame, 00068 TrapFrame, 00069 Context->ContextFlags, 00070 KernelMode); 00071 } 00072 } 00073 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00074 { 00075 /* Save the exception code */ 00076 Status = _SEH2_GetExceptionCode(); 00077 } 00078 _SEH2_END; 00079 00080 /* Lower the IRQL if needed */ 00081 if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql); 00082 00083 /* Return status */ 00084 return Status; 00085 } 00086 00087 NTSTATUS 00088 NTAPI 00089 KiRaiseException(IN PEXCEPTION_RECORD ExceptionRecord, 00090 IN PCONTEXT Context, 00091 IN PKEXCEPTION_FRAME ExceptionFrame, 00092 IN PKTRAP_FRAME TrapFrame, 00093 IN BOOLEAN SearchFrames) 00094 { 00095 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 00096 CONTEXT LocalContext; 00097 EXCEPTION_RECORD LocalExceptionRecord; 00098 ULONG ParameterCount, Size; 00099 00100 /* Check if we need to probe */ 00101 if (PreviousMode != KernelMode) 00102 { 00103 /* Set up SEH */ 00104 _SEH2_TRY 00105 { 00106 /* Probe the context */ 00107 ProbeForRead(Context, sizeof(CONTEXT), sizeof(ULONG)); 00108 00109 /* Probe the Exception Record */ 00110 ProbeForRead(ExceptionRecord, 00111 FIELD_OFFSET(EXCEPTION_RECORD, NumberParameters) + 00112 sizeof(ULONG), 00113 sizeof(ULONG)); 00114 00115 /* Validate the maximum parameters */ 00116 if ((ParameterCount = ExceptionRecord->NumberParameters) > 00117 EXCEPTION_MAXIMUM_PARAMETERS) 00118 { 00119 /* Too large */ 00120 _SEH2_YIELD(return STATUS_INVALID_PARAMETER); 00121 } 00122 00123 /* Probe the entire parameters now*/ 00124 Size = (sizeof(EXCEPTION_RECORD) - 00125 ((EXCEPTION_MAXIMUM_PARAMETERS - ParameterCount) * sizeof(ULONG))); 00126 ProbeForRead(ExceptionRecord, Size, sizeof(ULONG)); 00127 00128 /* Now make copies in the stack */ 00129 RtlCopyMemory(&LocalContext, Context, sizeof(CONTEXT)); 00130 RtlCopyMemory(&LocalExceptionRecord, ExceptionRecord, Size); 00131 Context = &LocalContext; 00132 ExceptionRecord = &LocalExceptionRecord; 00133 00134 /* Update the parameter count */ 00135 ExceptionRecord->NumberParameters = ParameterCount; 00136 } 00137 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00138 { 00139 /* Don't fail silently */ 00140 DPRINT1("KiRaiseException: Failed to Probe\n"); 00141 DbgBreakPoint(); 00142 00143 /* Return the exception code */ 00144 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00145 } 00146 _SEH2_END; 00147 } 00148 00149 /* Convert the context record */ 00150 KeContextToTrapFrame(Context, 00151 ExceptionFrame, 00152 TrapFrame, 00153 Context->ContextFlags, 00154 PreviousMode); 00155 00156 /* Dispatch the exception */ 00157 ExceptionRecord->ExceptionCode &= ~KI_EXCEPTION_INTERNAL; 00158 KiDispatchException(ExceptionRecord, 00159 ExceptionFrame, 00160 TrapFrame, 00161 PreviousMode, 00162 SearchFrames); 00163 00164 /* We are done */ 00165 return STATUS_SUCCESS; 00166 } 00167 00168 /* SYSTEM CALLS ***************************************************************/ 00169 00170 NTSTATUS 00171 NTAPI 00172 NtRaiseException(IN PEXCEPTION_RECORD ExceptionRecord, 00173 IN PCONTEXT Context, 00174 IN BOOLEAN FirstChance) 00175 { 00176 NTSTATUS Status; 00177 PKTHREAD Thread; 00178 PKTRAP_FRAME TrapFrame; 00179 00180 /* Get trap frame and link previous one*/ 00181 Thread = KeGetCurrentThread(); 00182 TrapFrame = Thread->TrapFrame; 00183 Thread->TrapFrame = KiGetLinkedTrapFrame(TrapFrame); 00184 00185 /* Set exception list */ 00186 #ifdef _M_IX86 00187 KeGetPcr()->NtTib.ExceptionList = TrapFrame->ExceptionList; 00188 #endif 00189 00190 /* Raise the exception */ 00191 Status = KiRaiseException(ExceptionRecord, 00192 Context, 00193 NULL, 00194 TrapFrame, 00195 FirstChance); 00196 if (NT_SUCCESS(Status)) 00197 { 00198 /* It was handled, so exit restoring all state */ 00199 KiServiceExit2(TrapFrame); 00200 } 00201 else 00202 { 00203 /* Exit with error */ 00204 KiServiceExit(TrapFrame, Status); 00205 } 00206 00207 /* We don't actually make it here */ 00208 return Status; 00209 } 00210 00211 NTSTATUS 00212 NTAPI 00213 NtContinue(IN PCONTEXT Context, 00214 IN BOOLEAN TestAlert) 00215 { 00216 PKTHREAD Thread; 00217 NTSTATUS Status; 00218 PKTRAP_FRAME TrapFrame; 00219 00220 /* Get trap frame and link previous one*/ 00221 Thread = KeGetCurrentThread(); 00222 TrapFrame = Thread->TrapFrame; 00223 Thread->TrapFrame = KiGetLinkedTrapFrame(TrapFrame); 00224 00225 /* Continue from this point on */ 00226 Status = KiContinue(Context, NULL, TrapFrame); 00227 if (NT_SUCCESS(Status)) 00228 { 00229 /* Check if alert was requested */ 00230 if (TestAlert) KeTestAlertThread(Thread->PreviousMode); 00231 00232 /* Exit to new trap frame */ 00233 KiServiceExit2(TrapFrame); 00234 } 00235 else 00236 { 00237 /* Exit with an error */ 00238 KiServiceExit(TrapFrame, Status); 00239 } 00240 00241 /* We don't actually make it here */ 00242 return Status; 00243 } 00244 00245 /* EOF */ Generated on Sun May 27 2012 04:24:25 for ReactOS by
1.7.6.1
|