/*++ 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); }