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);
|
|||
|
}
|
|||
|
|
|||
|
|