mirror of
https://github.com/reactos/reactos.git
synced 2025-06-27 19:19:43 +00:00
274 lines
8.3 KiB
C
274 lines
8.3 KiB
C
![]() |
/*
|
||
|
* COPYRIGHT: See COPYRIGHT.TXT
|
||
|
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
||
|
* FILE: except.c
|
||
|
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||
|
* HOMEPAGE: http://www.ext2fsd.com
|
||
|
* UPDATE HISTORY:
|
||
|
*/
|
||
|
|
||
|
/* INCLUDES *****************************************************************/
|
||
|
|
||
|
#include "ext2fs.h"
|
||
|
|
||
|
/* GLOBALS ***************************************************************/
|
||
|
|
||
|
extern PEXT2_GLOBAL Ext2Global;
|
||
|
|
||
|
/* DEFINITIONS *************************************************************/
|
||
|
|
||
|
NTSTATUS
|
||
|
Ext2ExceptionFilter (
|
||
|
IN PEXT2_IRP_CONTEXT IrpContext,
|
||
|
IN PEXCEPTION_POINTERS ExceptionPointer
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS Status = EXCEPTION_EXECUTE_HANDLER;
|
||
|
NTSTATUS ExceptionCode;
|
||
|
PEXCEPTION_RECORD ExceptRecord;
|
||
|
|
||
|
ExceptRecord = ExceptionPointer->ExceptionRecord;
|
||
|
ExceptionCode = ExceptRecord->ExceptionCode;
|
||
|
|
||
|
DbgPrint("-------------------------------------------------------------\n");
|
||
|
DbgPrint("Exception happends in Ext2Fsd (code %xh):\n", ExceptionCode);
|
||
|
DbgPrint(".exr %p;.cxr %p;\n", ExceptionPointer->ExceptionRecord,
|
||
|
ExceptionPointer->ContextRecord);
|
||
|
DbgPrint("-------------------------------------------------------------\n");
|
||
|
|
||
|
DbgBreak();
|
||
|
|
||
|
//
|
||
|
// Check IrpContext is valid or not
|
||
|
//
|
||
|
|
||
|
if (IrpContext) {
|
||
|
if ((IrpContext->Identifier.Type != EXT2ICX) ||
|
||
|
(IrpContext->Identifier.Size != sizeof(EXT2_IRP_CONTEXT))) {
|
||
|
DbgBreak();
|
||
|
IrpContext = NULL;
|
||
|
} else if (IrpContext->DeviceObject) {
|
||
|
PEXT2_VCB Vcb = NULL;
|
||
|
Vcb = (PEXT2_VCB) IrpContext->DeviceObject->DeviceExtension;
|
||
|
if (NULL == Vcb) {
|
||
|
Status = EXCEPTION_EXECUTE_HANDLER;
|
||
|
} else {
|
||
|
if (Vcb->Identifier.Type == EXT2VCB && !IsMounted(Vcb)) {
|
||
|
Status = EXCEPTION_EXECUTE_HANDLER;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
if (FsRtlIsNtstatusExpected(ExceptionCode)) {
|
||
|
return EXCEPTION_EXECUTE_HANDLER;
|
||
|
} else {
|
||
|
Ext2BugCheck( EXT2_BUGCHK_EXCEPT, (ULONG_PTR)ExceptRecord,
|
||
|
(ULONG_PTR)ExceptionPointer->ContextRecord,
|
||
|
(ULONG_PTR)ExceptRecord->ExceptionAddress );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (IrpContext) {
|
||
|
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
|
||
|
}
|
||
|
|
||
|
if ( Status == EXCEPTION_EXECUTE_HANDLER ||
|
||
|
FsRtlIsNtstatusExpected(ExceptionCode)) {
|
||
|
//
|
||
|
// If the exception is expected execute our handler
|
||
|
//
|
||
|
|
||
|
DEBUG(DL_ERR, ( "Ext2ExceptionFilter: Catching exception %xh\n",
|
||
|
ExceptionCode));
|
||
|
|
||
|
Status = EXCEPTION_EXECUTE_HANDLER;
|
||
|
|
||
|
if (IrpContext) {
|
||
|
IrpContext->ExceptionInProgress = TRUE;
|
||
|
IrpContext->ExceptionCode = ExceptionCode;
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
|
||
|
//
|
||
|
// Continue search for an higher level exception handler
|
||
|
//
|
||
|
|
||
|
DEBUG(DL_ERR, ( "Ext2ExceptionFilter: Passing on exception %#x\n",
|
||
|
ExceptionCode));
|
||
|
|
||
|
Status = EXCEPTION_CONTINUE_SEARCH;
|
||
|
|
||
|
if (IrpContext) {
|
||
|
Ext2FreeIrpContext(IrpContext);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
Ext2ExceptionHandler (IN PEXT2_IRP_CONTEXT IrpContext)
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
if (IrpContext) {
|
||
|
|
||
|
if ( (IrpContext->Identifier.Type != EXT2ICX) ||
|
||
|
(IrpContext->Identifier.Size != sizeof(EXT2_IRP_CONTEXT))) {
|
||
|
DbgBreak();
|
||
|
return STATUS_UNSUCCESSFUL;
|
||
|
}
|
||
|
|
||
|
Status = IrpContext->ExceptionCode;
|
||
|
|
||
|
if (IrpContext->Irp) {
|
||
|
|
||
|
//
|
||
|
// Check if this error is a result of user actions
|
||
|
//
|
||
|
|
||
|
PEXT2_VCB Vcb = NULL;
|
||
|
PIRP Irp = IrpContext->Irp;
|
||
|
PIO_STACK_LOCATION IrpSp;
|
||
|
|
||
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||
|
Vcb = (PEXT2_VCB) IrpContext->DeviceObject->DeviceExtension;
|
||
|
|
||
|
if (NULL == Vcb) {
|
||
|
Status = STATUS_INVALID_PARAMETER;
|
||
|
} else if (Vcb->Identifier.Type != EXT2VCB) {
|
||
|
Status = STATUS_INVALID_PARAMETER;
|
||
|
} else if (!IsMounted(Vcb)) {
|
||
|
if (IsFlagOn(Vcb->Flags, VCB_DEVICE_REMOVED)) {
|
||
|
Status = STATUS_NO_SUCH_DEVICE;
|
||
|
} else {
|
||
|
Status = STATUS_VOLUME_DISMOUNTED;
|
||
|
}
|
||
|
} else {
|
||
|
|
||
|
/* queue it again if our request is at top level */
|
||
|
if (IrpContext->IsTopLevel &&
|
||
|
((Status == STATUS_CANT_WAIT) ||
|
||
|
((Status == STATUS_VERIFY_REQUIRED) &&
|
||
|
(KeGetCurrentIrql() >= APC_LEVEL)))) {
|
||
|
|
||
|
Status = Ext2QueueRequest(IrpContext);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Status == STATUS_PENDING) {
|
||
|
goto errorout;
|
||
|
}
|
||
|
|
||
|
Irp->IoStatus.Status = Status;
|
||
|
|
||
|
if (IoIsErrorUserInduced(Status)) {
|
||
|
|
||
|
//
|
||
|
// Now we will generate a pop-up to user
|
||
|
//
|
||
|
|
||
|
PDEVICE_OBJECT RealDevice;
|
||
|
PVPB Vpb = NULL;
|
||
|
PETHREAD Thread;
|
||
|
|
||
|
if (IrpSp->FileObject != NULL) {
|
||
|
Vpb = IrpSp->FileObject->Vpb;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get the initial thread
|
||
|
//
|
||
|
|
||
|
Thread = Irp->Tail.Overlay.Thread;
|
||
|
RealDevice = IoGetDeviceToVerify( Thread );
|
||
|
|
||
|
if (RealDevice == NULL) {
|
||
|
//
|
||
|
// Get current thread
|
||
|
//
|
||
|
|
||
|
Thread = PsGetCurrentThread();
|
||
|
RealDevice = IoGetDeviceToVerify( Thread );
|
||
|
|
||
|
ASSERT( RealDevice != NULL );
|
||
|
}
|
||
|
|
||
|
Status = IrpContext->ExceptionCode;
|
||
|
|
||
|
if (RealDevice != NULL) {
|
||
|
|
||
|
if (IrpContext->ExceptionCode == STATUS_VERIFY_REQUIRED) {
|
||
|
|
||
|
Status = IoVerifyVolume (RealDevice, FALSE);
|
||
|
|
||
|
ExAcquireResourceSharedLite(&Vcb->MainResource, TRUE);
|
||
|
if (NT_SUCCESS(Status) && (!IsMounted(Vcb) ||
|
||
|
IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))) {
|
||
|
Status = STATUS_WRONG_VOLUME;
|
||
|
}
|
||
|
ExReleaseResourceLite(&Vcb->MainResource);
|
||
|
|
||
|
if (Ext2CheckDismount(IrpContext, Vcb, FALSE)) {
|
||
|
Ext2CompleteIrpContext( IrpContext, STATUS_VOLUME_DISMOUNTED);
|
||
|
Status = STATUS_VOLUME_DISMOUNTED;
|
||
|
Irp = NULL;
|
||
|
goto errorout;
|
||
|
}
|
||
|
|
||
|
if ( (IrpContext->MajorFunction == IRP_MJ_CREATE) &&
|
||
|
(IrpContext->FileObject->RelatedFileObject == NULL) &&
|
||
|
((Status == STATUS_SUCCESS) || (Status == STATUS_WRONG_VOLUME))) {
|
||
|
|
||
|
Irp->IoStatus.Information = IO_REMOUNT;
|
||
|
|
||
|
Ext2CompleteIrpContext( IrpContext, STATUS_REPARSE);
|
||
|
Status = STATUS_REPARSE;
|
||
|
Irp = NULL;
|
||
|
}
|
||
|
|
||
|
if (Irp) {
|
||
|
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
IoSetHardErrorOrVerifyDevice(Irp, RealDevice);
|
||
|
ASSERT (STATUS_VERIFY_REQUIRED != Status);
|
||
|
Ext2NormalizeAndRaiseStatus(IrpContext, Status);
|
||
|
}
|
||
|
|
||
|
Status = Ext2QueueRequest(IrpContext);
|
||
|
}
|
||
|
|
||
|
goto errorout;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
Status = STATUS_PENDING;
|
||
|
|
||
|
IoMarkIrpPending( Irp );
|
||
|
IoRaiseHardError( Irp, Vpb, RealDevice );
|
||
|
IoSetDeviceToVerify( Thread, NULL );
|
||
|
goto release_context;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Ext2CompleteRequest(Irp, FALSE, IO_NO_INCREMENT);
|
||
|
}
|
||
|
|
||
|
release_context:
|
||
|
|
||
|
Ext2FreeIrpContext(IrpContext);
|
||
|
|
||
|
} else {
|
||
|
|
||
|
Status = STATUS_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
errorout:
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|