1 /* 2 * COPYRIGHT: See COPYRIGHT.TXT 3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP 4 * FILE: except.c 5 * PROGRAMMER: Matt Wu <mattwu@163.com> 6 * HOMEPAGE: http://www.ext2fsd.com 7 * UPDATE HISTORY: 8 */ 9 10 /* INCLUDES *****************************************************************/ 11 12 #include "ext2fs.h" 13 14 /* GLOBALS ***************************************************************/ 15 16 extern PEXT2_GLOBAL Ext2Global; 17 18 /* DEFINITIONS *************************************************************/ 19 20 NTSTATUS 21 Ext2ExceptionFilter ( 22 IN PEXT2_IRP_CONTEXT IrpContext, 23 IN PEXCEPTION_POINTERS ExceptionPointer 24 ) 25 { 26 NTSTATUS Status = EXCEPTION_EXECUTE_HANDLER; 27 NTSTATUS ExceptionCode; 28 PEXCEPTION_RECORD ExceptRecord; 29 30 ExceptRecord = ExceptionPointer->ExceptionRecord; 31 ExceptionCode = ExceptRecord->ExceptionCode; 32 33 DbgPrint("-------------------------------------------------------------\n"); 34 DbgPrint("Exception happends in Ext2Fsd (code %xh):\n", ExceptionCode); 35 DbgPrint(".exr %p;.cxr %p;\n", ExceptionPointer->ExceptionRecord, 36 ExceptionPointer->ContextRecord); 37 DbgPrint("-------------------------------------------------------------\n"); 38 39 DbgBreak(); 40 41 // 42 // Check IrpContext is valid or not 43 // 44 45 if (IrpContext) { 46 if ((IrpContext->Identifier.Type != EXT2ICX) || 47 (IrpContext->Identifier.Size != sizeof(EXT2_IRP_CONTEXT))) { 48 DbgBreak(); 49 IrpContext = NULL; 50 } else if (IrpContext->DeviceObject) { 51 PEXT2_VCB Vcb = NULL; 52 Vcb = (PEXT2_VCB) IrpContext->DeviceObject->DeviceExtension; 53 if (NULL == Vcb) { 54 Status = EXCEPTION_EXECUTE_HANDLER; 55 } else { 56 if (Vcb->Identifier.Type == EXT2VCB && !IsMounted(Vcb)) { 57 Status = EXCEPTION_EXECUTE_HANDLER; 58 } 59 } 60 } 61 } else { 62 if (FsRtlIsNtstatusExpected(ExceptionCode)) { 63 return EXCEPTION_EXECUTE_HANDLER; 64 } else { 65 Ext2BugCheck( EXT2_BUGCHK_EXCEPT, (ULONG_PTR)ExceptRecord, 66 (ULONG_PTR)ExceptionPointer->ContextRecord, 67 (ULONG_PTR)ExceptRecord->ExceptionAddress ); 68 } 69 } 70 71 if (IrpContext) { 72 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); 73 } 74 75 if ( Status == EXCEPTION_EXECUTE_HANDLER || 76 FsRtlIsNtstatusExpected(ExceptionCode)) { 77 // 78 // If the exception is expected execute our handler 79 // 80 81 DEBUG(DL_ERR, ( "Ext2ExceptionFilter: Catching exception %xh\n", 82 ExceptionCode)); 83 84 Status = EXCEPTION_EXECUTE_HANDLER; 85 86 if (IrpContext) { 87 IrpContext->ExceptionInProgress = TRUE; 88 IrpContext->ExceptionCode = ExceptionCode; 89 } 90 91 } else { 92 93 // 94 // Continue search for an higher level exception handler 95 // 96 97 DEBUG(DL_ERR, ( "Ext2ExceptionFilter: Passing on exception %#x\n", 98 ExceptionCode)); 99 100 Status = EXCEPTION_CONTINUE_SEARCH; 101 102 if (IrpContext) { 103 Ext2FreeIrpContext(IrpContext); 104 } 105 } 106 107 return Status; 108 } 109 110 111 NTSTATUS 112 Ext2ExceptionHandler (IN PEXT2_IRP_CONTEXT IrpContext) 113 { 114 NTSTATUS Status; 115 116 if (IrpContext) { 117 118 if ( (IrpContext->Identifier.Type != EXT2ICX) || 119 (IrpContext->Identifier.Size != sizeof(EXT2_IRP_CONTEXT))) { 120 DbgBreak(); 121 return STATUS_UNSUCCESSFUL; 122 } 123 124 Status = IrpContext->ExceptionCode; 125 126 if (IrpContext->Irp) { 127 128 // 129 // Check if this error is a result of user actions 130 // 131 132 PEXT2_VCB Vcb = NULL; 133 PIRP Irp = IrpContext->Irp; 134 PIO_STACK_LOCATION IrpSp; 135 136 IrpSp = IoGetCurrentIrpStackLocation(Irp); 137 Vcb = (PEXT2_VCB) IrpContext->DeviceObject->DeviceExtension; 138 139 if (NULL == Vcb) { 140 Status = STATUS_INVALID_PARAMETER; 141 } else if (Vcb->Identifier.Type != EXT2VCB) { 142 Status = STATUS_INVALID_PARAMETER; 143 } else if (!IsMounted(Vcb)) { 144 if (IsFlagOn(Vcb->Flags, VCB_DEVICE_REMOVED)) { 145 Status = STATUS_NO_SUCH_DEVICE; 146 } else { 147 Status = STATUS_VOLUME_DISMOUNTED; 148 } 149 } else { 150 151 /* queue it again if our request is at top level */ 152 if (IrpContext->IsTopLevel && 153 ((Status == STATUS_CANT_WAIT) || 154 ((Status == STATUS_VERIFY_REQUIRED) && 155 (KeGetCurrentIrql() >= APC_LEVEL)))) { 156 157 Status = Ext2QueueRequest(IrpContext); 158 } 159 } 160 161 if (Status == STATUS_PENDING) { 162 goto errorout; 163 } 164 165 Irp->IoStatus.Status = Status; 166 167 if (IoIsErrorUserInduced(Status)) { 168 169 // 170 // Now we will generate a pop-up to user 171 // 172 173 PDEVICE_OBJECT RealDevice; 174 PVPB Vpb = NULL; 175 PETHREAD Thread; 176 177 if (IrpSp->FileObject != NULL) { 178 Vpb = IrpSp->FileObject->Vpb; 179 } 180 181 // 182 // Get the initial thread 183 // 184 185 Thread = Irp->Tail.Overlay.Thread; 186 RealDevice = IoGetDeviceToVerify( Thread ); 187 188 if (RealDevice == NULL) { 189 // 190 // Get current thread 191 // 192 193 Thread = PsGetCurrentThread(); 194 RealDevice = IoGetDeviceToVerify( Thread ); 195 196 ASSERT( RealDevice != NULL ); 197 } 198 199 Status = IrpContext->ExceptionCode; 200 201 if (RealDevice != NULL) { 202 203 if (IrpContext->ExceptionCode == STATUS_VERIFY_REQUIRED) { 204 205 Status = IoVerifyVolume (RealDevice, FALSE); 206 207 ExAcquireResourceSharedLite(&Vcb->MainResource, TRUE); 208 if (NT_SUCCESS(Status) && (!IsMounted(Vcb) || 209 IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))) { 210 Status = STATUS_WRONG_VOLUME; 211 } 212 ExReleaseResourceLite(&Vcb->MainResource); 213 214 if (Ext2CheckDismount(IrpContext, Vcb, FALSE)) { 215 Ext2CompleteIrpContext( IrpContext, STATUS_VOLUME_DISMOUNTED); 216 Status = STATUS_VOLUME_DISMOUNTED; 217 Irp = NULL; 218 goto errorout; 219 } 220 221 if ( (IrpContext->MajorFunction == IRP_MJ_CREATE) && 222 (IrpContext->FileObject->RelatedFileObject == NULL) && 223 ((Status == STATUS_SUCCESS) || (Status == STATUS_WRONG_VOLUME))) { 224 225 Irp->IoStatus.Information = IO_REMOUNT; 226 227 Ext2CompleteIrpContext( IrpContext, STATUS_REPARSE); 228 Status = STATUS_REPARSE; 229 Irp = NULL; 230 } 231 232 if (Irp) { 233 234 if (!NT_SUCCESS(Status)) { 235 IoSetHardErrorOrVerifyDevice(Irp, RealDevice); 236 ASSERT (STATUS_VERIFY_REQUIRED != Status); 237 Ext2NormalizeAndRaiseStatus(IrpContext, Status); 238 } 239 240 Status = Ext2QueueRequest(IrpContext); 241 } 242 243 goto errorout; 244 245 } else { 246 247 Status = STATUS_PENDING; 248 249 IoMarkIrpPending( Irp ); 250 IoRaiseHardError( Irp, Vpb, RealDevice ); 251 IoSetDeviceToVerify( Thread, NULL ); 252 goto release_context; 253 } 254 } 255 } 256 257 Ext2CompleteRequest(Irp, FALSE, IO_NO_INCREMENT); 258 } 259 260 release_context: 261 262 Ext2FreeIrpContext(IrpContext); 263 264 } else { 265 266 Status = STATUS_INVALID_PARAMETER; 267 } 268 269 errorout: 270 271 return Status; 272 } 273 274