317 lines
7.6 KiB
C
317 lines
7.6 KiB
C
/*++
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
NtExcept.c
|
||
|
||
Abstract:
|
||
|
||
This module declares the exception handlers for the NTwrapper.
|
||
|
||
Author:
|
||
|
||
JoeLinn [JoeLinn] 1-Dec-94
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "precomp.h"
|
||
#pragma hdrstop
|
||
#include "stdarg.h"
|
||
#include "stdio.h"
|
||
#include "string.h"
|
||
#include "prefix.h"
|
||
|
||
//
|
||
// The Bug check file id for this module
|
||
//
|
||
|
||
#define BugCheckFileId (RDBSS_BUG_CHECK_NTEXCEPT)
|
||
|
||
//
|
||
// The debug trace level
|
||
//
|
||
|
||
#define Dbg (DEBUG_TRACE_CATCH_EXCEPTIONS)
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(PAGE, RxProcessException)
|
||
#pragma alloc_text(PAGE, RxPopUpFileCorrupt)
|
||
#endif
|
||
|
||
PCONTEXT RxExpCXR;
|
||
PEXCEPTION_RECORD RxExpEXR;
|
||
PVOID RxExpAddr;
|
||
NTSTATUS RxExpCode;
|
||
|
||
|
||
LONG
|
||
RxExceptionFilter (
|
||
IN PRX_CONTEXT RxContext,
|
||
IN PEXCEPTION_POINTERS ExceptionPointer
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is used to decide if we should or should not handle
|
||
an exception status that is being raised. It first determines the true exception
|
||
code by examining the exception record. If there is an Irp Context, then it inserts the status
|
||
into the RxContext. Finally, it determines whether to handle the exception or bugcheck
|
||
according to whether the except is one of the expected ones. in actuality, all exceptions are expected
|
||
except for some lowlevel machine errors (see fsrtl\filter.c)
|
||
|
||
Arguments:
|
||
|
||
RxContext - the irp context of current operation for storing away the code.
|
||
|
||
ExceptionPointer - Supplies the exception context.
|
||
|
||
Return Value:
|
||
|
||
ULONG - returns EXCEPTION_EXECUTE_HANDLER or bugchecks
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS ExceptionCode;
|
||
|
||
//save these values in statics so i can see 'em on the debugger............
|
||
ExceptionCode = RxExpCode = ExceptionPointer->ExceptionRecord->ExceptionCode;
|
||
RxExpAddr = ExceptionPointer->ExceptionRecord->ExceptionAddress;
|
||
RxExpEXR = ExceptionPointer->ExceptionRecord;
|
||
RxExpCXR = ExceptionPointer->ContextRecord;
|
||
|
||
RxLog(("!!! %lx %lx %lx %lx\n", RxExpCode, RxExpAddr, RxExpEXR, RxExpCXR));
|
||
RxWmiLog(LOG,
|
||
RxExceptionFilter_1,
|
||
LOGULONG(RxExpCode)
|
||
LOGPTR(RxExpAddr)
|
||
LOGPTR(RxExpEXR)
|
||
LOGPTR(RxExpCXR));
|
||
|
||
RxDbgTrace(0, (DEBUG_TRACE_UNWIND), ("RxExceptionFilter %X at %X\n", RxExpCode, RxExpAddr));
|
||
RxDbgTrace(0, (DEBUG_TRACE_UNWIND), ("RxExceptionFilter EXR=%X, CXR=%X\n", RxExpEXR, RxExpCXR));
|
||
|
||
if (RxContext == NULL) {
|
||
//we cannot do anything even moderately sane
|
||
return EXCEPTION_EXECUTE_HANDLER;
|
||
}
|
||
|
||
IF_DEBUG {
|
||
if (!FlagOn(RxContext->Flags,RX_CONTEXT_FLAG_NO_EXCEPTION_BREAKPOINT)) {
|
||
//DbgBreakPoint();
|
||
}
|
||
}
|
||
|
||
//
|
||
// If the exception is RxStatus(IN_PAGE_ERROR), get the I/O error code
|
||
// from the exception record.
|
||
//
|
||
|
||
if (ExceptionCode == STATUS_IN_PAGE_ERROR) {
|
||
RxLog(("InPageError...."));
|
||
RxWmiLog(LOG,
|
||
RxExceptionFilter_2,
|
||
LOGPTR(RxContext));
|
||
if (ExceptionPointer->ExceptionRecord->NumberParameters >= 3) {
|
||
ExceptionCode = (NTSTATUS)ExceptionPointer->ExceptionRecord->ExceptionInformation[2];
|
||
}
|
||
}
|
||
|
||
#if 0
|
||
this code was used back when we thought we could do something sane w/o a context........as it stands now
|
||
we cannot call RxProcessException without a context so we might as well punt right now.......... actually,
|
||
the punting code is earlier......
|
||
//
|
||
// If there is not an irp context, we must have had insufficient resources.
|
||
//
|
||
|
||
// if ( !ARGUMENT_PRESENT( RxContext )
|
||
// || ( RxContext->MajorFunction == IRP_MJ_CLOSE ) ) {
|
||
if ( RxContext==NULL ) {
|
||
|
||
ASSERT(ExceptionCode==STATUS_INSUFFICIENT_RESOURCES);
|
||
|
||
if (!FsRtlIsNtstatusExpected( ExceptionCode )) {
|
||
|
||
RxBugCheck( (ULONG)ExceptionPointer->ExceptionRecord,
|
||
(ULONG)ExceptionPointer->ContextRecord,
|
||
(ULONG)ExceptionPointer->ExceptionRecord->ExceptionAddress );
|
||
}
|
||
|
||
return EXCEPTION_EXECUTE_HANDLER;
|
||
}
|
||
#endif
|
||
|
||
if ( RxContext->StoredStatus == 0 ) {
|
||
|
||
if (FsRtlIsNtstatusExpected( ExceptionCode )) {
|
||
|
||
RxContext->StoredStatus = ExceptionCode;
|
||
|
||
return EXCEPTION_EXECUTE_HANDLER;
|
||
|
||
} else {
|
||
|
||
RxBugCheck( (ULONG_PTR)ExceptionPointer->ExceptionRecord,
|
||
(ULONG_PTR)ExceptionPointer->ContextRecord,
|
||
(ULONG_PTR)ExceptionPointer->ExceptionRecord->ExceptionAddress );
|
||
}
|
||
|
||
} else {
|
||
|
||
//
|
||
// We raised this code explicitly ourselves, so it had better be
|
||
// expected.
|
||
//
|
||
|
||
ASSERT( FsRtlIsNtstatusExpected( ExceptionCode ) );
|
||
}
|
||
|
||
return EXCEPTION_EXECUTE_HANDLER;
|
||
}
|
||
|
||
NTSTATUS
|
||
RxProcessException (
|
||
IN PRX_CONTEXT RxContext,
|
||
IN NTSTATUS ExceptionCode
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine processes an exception. It either completes the request
|
||
with the saved exception status or it bugchecks
|
||
|
||
|
||
Arguments:
|
||
|
||
RxContext - Context of the current operation
|
||
|
||
ExceptionCode - Supplies the normalized exception status being handled
|
||
|
||
Return Value:
|
||
|
||
RXSTATUS - Returns the results of either posting the Irp or the
|
||
saved completion status.
|
||
|
||
--*/
|
||
|
||
{
|
||
PAGED_CODE();
|
||
|
||
RxDbgTrace(0, Dbg, ("RxProcessException\n", 0));
|
||
|
||
if ( RxContext == NULL ) {
|
||
|
||
// we cannot do anything even moderately sane without a context..........sigh
|
||
|
||
//DbgBreakPoint();
|
||
RxBugCheck( 0,0,0 ); //this shouldn't happen.
|
||
}
|
||
|
||
//
|
||
// Get the exception status from RxContext->StoredStatus as stored there by
|
||
// the exception filter., and
|
||
// reset it. Also copy it to the Irp in case it isn't already there
|
||
//
|
||
|
||
ExceptionCode = RxContext->StoredStatus;
|
||
|
||
if (!FsRtlIsNtstatusExpected( ExceptionCode )) {
|
||
|
||
RxBugCheck( 0,0,0 ); //this shouldn't happen. we should have BC'd in the filter
|
||
}
|
||
|
||
if (RxContext->MajorFunction == IRP_MJ_CREATE) {
|
||
RxpPrepareCreateContextForReuse(RxContext);
|
||
}
|
||
|
||
{
|
||
RxCaptureFcb;
|
||
|
||
PAGED_CODE();
|
||
|
||
if (capFcb != NULL) {
|
||
|
||
if (RxContext->FcbResourceAcquired) {
|
||
|
||
RxDbgTrace( 0, Dbg,("RxCommonWrite ReleasingFcb\n"));
|
||
__RxReleaseFcb(RxContext, (PMRX_FCB)(capFcb)
|
||
#ifdef RDBSS_TRACKER
|
||
,__LINE__,__FILE__,0
|
||
#endif
|
||
);
|
||
RxContext->FcbResourceAcquired = FALSE;
|
||
}
|
||
|
||
if (RxContext->FcbPagingIoResourceAcquired) {
|
||
RxDbgTrace( 0, Dbg,("RxCommonWrite ReleasingPaginIo\n"));
|
||
RxReleasePagingIoResource(capFcb,RxContext);
|
||
}
|
||
}
|
||
}
|
||
|
||
RxCompleteContextAndReturn( ExceptionCode );
|
||
}
|
||
|
||
VOID
|
||
RxPopUpFileCorrupt (
|
||
IN PRX_CONTEXT RxContext,
|
||
IN PFCB Fcb
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
The Following routine makes an informational popup that the file
|
||
is corrupt.
|
||
|
||
Arguments:
|
||
|
||
Fcb - The file that is corrupt.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PKTHREAD Thread;
|
||
RxCaptureRequestPacket;
|
||
|
||
PAGED_CODE();
|
||
|
||
//if (Fcb->FullFileName.Buffer == NULL) {
|
||
//
|
||
// RxSetFullFileNameInFcb( RxContext, Fcb );
|
||
//}
|
||
|
||
//
|
||
// We never want to block a system thread waiting for the user to
|
||
// press OK.
|
||
//
|
||
|
||
if (IoIsSystemThread(capReqPacket->Tail.Overlay.Thread)) {
|
||
|
||
Thread = NULL;
|
||
|
||
} else {
|
||
|
||
Thread = capReqPacket->Tail.Overlay.Thread;
|
||
}
|
||
|
||
IoRaiseInformationalHardError( STATUS_FILE_CORRUPT_ERROR,
|
||
&Fcb->FcbTableEntry.Path, //&Fcb->FullFileName,
|
||
Thread);
|
||
}
|
||
|
||
|