test: raisexcp.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# raisexcp.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1990  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     raisexcp.c
    00008
    00009 Abstract:
    00010
    00011     This module implements the internal kernel code to continue execution
    00012     and raise a exception.
    00013
    00014 Author:
    00015
    00016     David N. Cutler (davec) 8-Aug-1990
    00017
    00018 Environment:
    00019
    00020     Kernel mode only.
    00021
    00022 Revision History:
    00023
    00024 18-Oct-1997                     Neillc
    00025
    00026 Fix for bug #98981. KiRaiseException referenced the users exception record before probeing.
    00027 It also had a range check that was incorrect for the number of exception parameters because
    00028 it used a signed temp to make a later calculation of the size work. The exception record
    00029 was also subject to changes to the number of parameters after validation. This might cause
    00030 lower levels to fail.
    00031
    00032 --*/
    00033
    00034 #include "ki.h"
    00035
    00036 VOID
    00037 KiContinuePreviousModeUser(
    00038     IN PCONTEXT ContextRecord,
    00039     IN PKEXCEPTION_FRAME ExceptionFrame,
    00040     IN PKTRAP_FRAME TrapFrame,
    00041     IN KPROCESSOR_MODE PreviousMode
    00042     )
    00043
    00044 /*++
    00045
    00046 Routine Description:
    00047
    00048     This function is called from KiContinue if PreviousMode is
    00049     not KernelMode.   In this case a kernel mode copy of the
    00050     ContextRecord is made before calling KeContextToKframes.
    00051     This is done in a seperate routine to save stack space for
    00052     the common case which is PreviousMode == Kernel.
    00053
    00054     N.B. This routine is called from within a try/except block
    00055     that will be used to handle errors like invalid context.
    00056
    00057 Arguments:
    00058
    00059
    00060     ContextRecord - Supplies a pointer to a context record.
    00061
    00062     ExceptionFrame - Supplies a pointer to an exception frame.
    00063
    00064     TrapFrame - Supplies a pointer to a trap frame.
    00065
    00066     PreviousMode - Not KernelMode.
    00067
    00068 Return Value:
    00069
    00070     None.
    00071
    00072 --*/
    00073
    00074 {
    00075     CONTEXT ContextRecord2;
    00076
    00077     //
    00078     // Copy the context record to kernel mode space.
    00079     //
    00080
    00081     ProbeForRead(ContextRecord, sizeof(CONTEXT), CONTEXT_ALIGN);
    00082     RtlMoveMemory(&ContextRecord2, ContextRecord, sizeof(CONTEXT));
    00083     ContextRecord = &ContextRecord2;
    00084
    00085     //
    00086     // Move information from the context record to the exception
    00087     // and trap frames.
    00088     //
    00089
    00090     KeContextToKframes(TrapFrame,
    00091                        ExceptionFrame,
    00092                        &ContextRecord2,
    00093                        ContextRecord2.ContextFlags,
    00094                        PreviousMode);
    00095 }
    00096
    00097
    00098 NTSTATUS
    00099 KiContinue (
    00100     IN PCONTEXT ContextRecord,
    00101     IN PKEXCEPTION_FRAME ExceptionFrame,
    00102     IN PKTRAP_FRAME TrapFrame
    00103     )
    00104
    00105 /*++
    00106
    00107 Routine Description:
    00108
    00109     This function is called to copy the specified context frame to the
    00110     specified exception and trap frames for the continue system service.
    00111
    00112 Arguments:
    00113
    00114     ContextRecord - Supplies a pointer to a context record.
    00115
    00116     ExceptionFrame - Supplies a pointer to an exception frame.
    00117
    00118     TrapFrame - Supplies a pointer to a trap frame.
    00119
    00120 Return Value:
    00121
    00122     STATUS_ACCESS_VIOLATION is returned if the context record is not readable
    00123         from user mode.
    00124
    00125     STATUS_DATATYPE_MISALIGNMENT is returned if the context record is not
    00126         properly aligned.
    00127
    00128     STATUS_SUCCESS is returned if the context frame is copied successfully
    00129         to the specified exception and trap frames.
    00130
    00131 --*/
    00132
    00133 {
    00134     KPROCESSOR_MODE PreviousMode;
    00135     NTSTATUS Status;
    00136     KIRQL OldIrql;
    00137     BOOLEAN IrqlChanged = FALSE;
    00138
    00139     //
    00140     // Synchronize with other context operations.
    00141     //
    00142
    00143     Status = STATUS_SUCCESS;
    00144     if (KeGetCurrentIrql() < APC_LEVEL) {
    00145
    00146         //
    00147         // To support try-except and ExRaiseStatus in device driver code we
    00148         // need to check if we are already at raised level.
    00149         //
    00150
    00151         IrqlChanged = TRUE;
    00152         KeRaiseIrql(APC_LEVEL, &OldIrql);
    00153     }
    00154
    00155     //
    00156     // Establish an exception handler and probe and capture the specified
    00157     // context record if the previous mode is user. If the probe or copy
    00158     // fails, then return the exception code as the function value. Else
    00159     // copy the context record to the specified exception and trap frames,
    00160     // and return success as the function value.
    00161     //
    00162
    00163     try {
    00164
    00165         //
    00166         // Get the previous processor mode. If the previous processor mode is
    00167         // user, then probe and copy the specified context record.
    00168         //
    00169
    00170         PreviousMode = KeGetPreviousMode();
    00171         if (PreviousMode != KernelMode) {
    00172             KiContinuePreviousModeUser(ContextRecord,
    00173                                        ExceptionFrame,
    00174                                        TrapFrame,
    00175                                        PreviousMode);
    00176         } else {
    00177
    00178             //
    00179             // Move information from the context record to the exception
    00180             // and trap frames.
    00181             //
    00182
    00183             KeContextToKframes(TrapFrame,
    00184                                ExceptionFrame,
    00185                                ContextRecord,
    00186                                ContextRecord->ContextFlags,
    00187                                PreviousMode);
    00188         }
    00189
    00190     //
    00191     // If an exception occurs during the probe or copy of the context
    00192     // record, then always handle the exception and return the exception
    00193     // code as the status value.
    00194     //
    00195
    00196     } except(EXCEPTION_EXECUTE_HANDLER) {
    00197         Status = GetExceptionCode();
    00198     }
    00199
    00200     if (IrqlChanged) {
    00201         KeLowerIrql (OldIrql);
    00202     }
    00203
    00204     return Status;
    00205 }
    00206
    00207 NTSTATUS
    00208 KiRaiseException (
    00209     IN PEXCEPTION_RECORD ExceptionRecord,
    00210     IN PCONTEXT ContextRecord,
    00211     IN PKEXCEPTION_FRAME ExceptionFrame,
    00212     IN PKTRAP_FRAME TrapFrame,
    00213     IN BOOLEAN FirstChance
    00214     )
    00215
    00216 /*++
    00217
    00218 Routine Description:
    00219
    00220     This function is called to raise an exception. The exception can be
    00221     raised as a first or second chance exception.
    00222
    00223 Arguments:
    00224
    00225     ExceptionRecord - Supplies a pointer to an exception record.
    00226
    00227     ContextRecord - Supplies a pointer to a context record.
    00228
    00229     ExceptionFrame - Supplies a pointer to an exception frame.
    00230
    00231     TrapFrame - Supplies a pointer to a trap frame.
    00232
    00233     FirstChance - Supplies a boolean value that specifies whether this is
    00234         the first (TRUE) or second (FALSE) chance for the exception.
    00235
    00236 Return Value:
    00237
    00238     STATUS_ACCESS_VIOLATION is returned if either the exception or the context
    00239         record is not readable from user mode.
    00240
    00241     STATUS_DATATYPE_MISALIGNMENT is returned if the exception record or the
    00242         context record are not properly aligned.
    00243
    00244     STATUS_INVALID_PARAMETER is returned if the number of exception parameters
    00245         is greater than the maximum allowable number of exception parameters.
    00246
    00247     STATUS_SUCCESS is returned if the exception is dispatched and handled.
    00248
    00249 --*/
    00250
    00251 {
    00252
    00253     CONTEXT ContextRecord2;
    00254     EXCEPTION_RECORD ExceptionRecord2;
    00255     ULONG Length;
    00256     ULONG Params;
    00257     KPROCESSOR_MODE PreviousMode;
    00258
    00259     //
    00260     // Establish an exception handler and probe the specified exception and
    00261     // context records for read accessibility. If the probe fails, then
    00262     // return the exception code as the service status. Else call the exception
    00263     // dispatcher to dispatch the exception.
    00264     //
    00265
    00266     try {
    00267
    00268         //
    00269         // Get the previous processor mode. If the previous processor mode
    00270         // is user, then probe and copy the specified exception and context
    00271         // records.
    00272         //
    00273
    00274         PreviousMode = KeGetPreviousMode();
    00275         if (PreviousMode != KernelMode) {
    00276             ProbeForRead(ContextRecord, sizeof(CONTEXT), CONTEXT_ALIGN);
    00277             ProbeForRead(ExceptionRecord,
    00278                          FIELD_OFFSET (EXCEPTION_RECORD, NumberParameters) +
    00279                          sizeof (ExceptionRecord->NumberParameters), sizeof(ULONG));
    00280             Params = ExceptionRecord->NumberParameters;
    00281             if (Params > EXCEPTION_MAXIMUM_PARAMETERS) {
    00282                 return STATUS_INVALID_PARAMETER;
    00283             }
    00284
    00285             //
    00286             // The exception record structure is defined unlike others with trailing
    00287             // information as being its maximum size rather than just a single trailing
    00288             // element.
    00289             //
    00290             Length = (sizeof(EXCEPTION_RECORD) -
    00291                      ((EXCEPTION_MAXIMUM_PARAMETERS - Params) *
    00292                      sizeof(ExceptionRecord->ExceptionInformation[0])));
    00293
    00294             //
    00295             // The structure is currently less that 64k so we don't really need this probe.
    00296             //
    00297             ProbeForRead(ExceptionRecord, Length, sizeof(ULONG));
    00298
    00299             //
    00300             // Copy the exception and context record to local storage so an
    00301             // access violation cannot occur during exception dispatching.
    00302             //
    00303
    00304             RtlMoveMemory(&ContextRecord2, ContextRecord, sizeof(CONTEXT));
    00305             RtlMoveMemory(&ExceptionRecord2, ExceptionRecord, Length);
    00306             ContextRecord = &ContextRecord2;
    00307             ExceptionRecord = &ExceptionRecord2;
    00308             //
    00309             // The number of parameters might have changed after we validated but before we
    00310             // copied the structure. Fix this up as lower levels might not like this.
    00311             //
    00312             ExceptionRecord->NumberParameters = Params;
    00313         }
    00314
    00315     //
    00316     // If an exception occurs during the probe of the exception or context
    00317     // record, then always handle the exception and return the exception code
    00318     // as the status value.
    00319     //
    00320
    00321     } except(EXCEPTION_EXECUTE_HANDLER) {
    00322         return GetExceptionCode();
    00323     }
    00324
    00325     //
    00326     // Move information from the context record to the exception and
    00327     // trap frames.
    00328     //
    00329
    00330     KeContextToKframes(TrapFrame,
    00331                        ExceptionFrame,
    00332                        ContextRecord,
    00333                        ContextRecord->ContextFlags,
    00334                        PreviousMode);
    00335
    00336     //
    00337     // Make sure the reserved bit is clear in the exception code and
    00338     // perform exception dispatching.
    00339     //
    00340     // N.B. The reserved bit is used to differentiate internally gerarated
    00341     //      codes from codes generated by application programs.
    00342     //
    00343
    00344     ExceptionRecord->ExceptionCode &= 0xefffffff;
    00345     KiDispatchException(ExceptionRecord,
    00346                         ExceptionFrame,
    00347                         TrapFrame,
    00348                         PreviousMode,
    00349                         FirstChance);
    00350
    00351     return STATUS_SUCCESS;
    00352 }