1 /* 2 * COPYRIGHT: See COPYRIGHT.TXT 3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP 4 * FILE: read.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 Ext2ReadComplete (IN PEXT2_IRP_CONTEXT IrpContext); 22 23 NTSTATUS 24 Ext2ReadFile (IN PEXT2_IRP_CONTEXT IrpContext); 25 26 NTSTATUS 27 Ext2ReadVolume (IN PEXT2_IRP_CONTEXT IrpContext); 28 29 /* FUNCTIONS *************************************************************/ 30 31 NTSTATUS 32 Ext2CompleteIrpContext ( 33 IN PEXT2_IRP_CONTEXT IrpContext, 34 IN NTSTATUS Status ) 35 { 36 PIRP Irp = NULL; 37 BOOLEAN bPrint; 38 39 Irp = IrpContext->Irp; 40 41 if (Irp != NULL) { 42 43 if (NT_ERROR(Status)) { 44 Irp->IoStatus.Information = 0; 45 } 46 47 Irp->IoStatus.Status = Status; 48 bPrint = !IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED); 49 50 Ext2CompleteRequest( 51 Irp, bPrint, (CCHAR)(NT_SUCCESS(Status)? 52 IO_DISK_INCREMENT : IO_NO_INCREMENT) ); 53 54 IrpContext->Irp = NULL; 55 } 56 57 Ext2FreeIrpContext(IrpContext); 58 59 return Status; 60 } 61 62 63 NTSTATUS 64 Ext2ReadVolume (IN PEXT2_IRP_CONTEXT IrpContext) 65 { 66 NTSTATUS Status = STATUS_UNSUCCESSFUL; 67 68 PEXT2_VCB Vcb = NULL; 69 PEXT2_CCB Ccb = NULL; 70 PEXT2_FCBVCB FcbOrVcb = NULL; 71 PFILE_OBJECT FileObject = NULL; 72 73 PDEVICE_OBJECT DeviceObject = NULL; 74 75 PIRP Irp = NULL; 76 PIO_STACK_LOCATION IoStackLocation = NULL; 77 78 ULONG Length; 79 LARGE_INTEGER ByteOffset; 80 81 BOOLEAN PagingIo; 82 BOOLEAN Nocache; 83 BOOLEAN SynchronousIo; 84 BOOLEAN MainResourceAcquired = FALSE; 85 86 PUCHAR Buffer = NULL; 87 EXT2_EXTENT BlockArray; 88 89 _SEH2_TRY { 90 91 ASSERT(IrpContext); 92 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 93 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 94 95 DeviceObject = IrpContext->DeviceObject; 96 Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; 97 ASSERT(Vcb != NULL); 98 ASSERT((Vcb->Identifier.Type == EXT2VCB) && 99 (Vcb->Identifier.Size == sizeof(EXT2_VCB))); 100 101 FileObject = IrpContext->FileObject; 102 FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext; 103 ASSERT(FcbOrVcb); 104 105 if (!(FcbOrVcb->Identifier.Type == EXT2VCB && (PVOID)FcbOrVcb == (PVOID)Vcb)) { 106 107 Status = STATUS_INVALID_DEVICE_REQUEST; 108 _SEH2_LEAVE; 109 } 110 111 Ccb = (PEXT2_CCB) FileObject->FsContext2; 112 Irp = IrpContext->Irp; 113 Irp->IoStatus.Information = 0; 114 IoStackLocation = IoGetCurrentIrpStackLocation(Irp); 115 116 Length = IoStackLocation->Parameters.Read.Length; 117 ByteOffset = IoStackLocation->Parameters.Read.ByteOffset; 118 119 PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO); 120 Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE) || (Ccb != NULL); 121 SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO); 122 123 if (PagingIo) { 124 ASSERT(Nocache); 125 } 126 127 if (Length == 0) { 128 Irp->IoStatus.Information = 0; 129 Status = STATUS_SUCCESS; 130 _SEH2_LEAVE; 131 } 132 133 if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) { 134 ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); 135 Status = STATUS_PENDING; 136 _SEH2_LEAVE; 137 } 138 139 if (ByteOffset.QuadPart >= 140 Vcb->PartitionInformation.PartitionLength.QuadPart ) { 141 Irp->IoStatus.Information = 0; 142 Status = STATUS_END_OF_FILE; 143 _SEH2_LEAVE; 144 } 145 146 if (ByteOffset.QuadPart + Length > Vcb->Header.FileSize.QuadPart) { 147 Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart); 148 } 149 150 /* 151 * User direct volume access 152 */ 153 154 if (Ccb != NULL && !PagingIo) { 155 156 if (!ExAcquireResourceExclusiveLite( 157 &Vcb->MainResource, 158 IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { 159 Status = STATUS_PENDING; 160 _SEH2_LEAVE; 161 } 162 MainResourceAcquired = TRUE; 163 164 if (!FlagOn(Ccb->Flags, CCB_VOLUME_DASD_PURGE)) { 165 166 if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) { 167 Ext2FlushVolume(IrpContext, Vcb, FALSE); 168 } 169 170 SetFlag(Ccb->Flags, CCB_VOLUME_DASD_PURGE); 171 } 172 173 ExReleaseResourceLite(&Vcb->MainResource); 174 MainResourceAcquired = FALSE; 175 176 /* will do Nocache i/o */ 177 } 178 179 /* 180 * I/O to volume StreamObject 181 */ 182 183 if (!Nocache) { 184 185 if (IsFlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) { 186 187 CcMdlRead( 188 Vcb->Volume, 189 &ByteOffset, 190 Length, 191 &Irp->MdlAddress, 192 &Irp->IoStatus ); 193 194 Status = Irp->IoStatus.Status; 195 196 } else { 197 198 Buffer = Ext2GetUserBuffer(Irp); 199 if (Buffer == NULL) { 200 DbgBreak(); 201 Status = STATUS_INVALID_USER_BUFFER; 202 _SEH2_LEAVE; 203 } 204 205 if (!CcCopyRead( 206 Vcb->Volume, 207 &ByteOffset, 208 Length, 209 Ext2CanIWait(), 210 Buffer, 211 &Irp->IoStatus )) { 212 Status = STATUS_PENDING; 213 _SEH2_LEAVE; 214 } 215 216 Status = Irp->IoStatus.Status; 217 } 218 219 } else { 220 221 Length &= ~((ULONG)SECTOR_SIZE - 1); 222 Status = Ext2LockUserBuffer( 223 IrpContext->Irp, 224 Length, 225 IoWriteAccess ); 226 227 if (!NT_SUCCESS(Status)) { 228 _SEH2_LEAVE; 229 } 230 231 BlockArray.Irp = NULL; 232 BlockArray.Lba = ByteOffset.QuadPart; 233 BlockArray.Offset = 0; 234 BlockArray.Length = Length; 235 BlockArray.Next = NULL; 236 237 Status = Ext2ReadWriteBlocks(IrpContext, 238 Vcb, 239 &BlockArray, 240 Length ); 241 242 Irp = IrpContext->Irp; 243 if (!Irp) { 244 _SEH2_LEAVE; 245 } 246 } 247 248 } _SEH2_FINALLY { 249 250 if (MainResourceAcquired) { 251 ExReleaseResourceLite(&Vcb->MainResource); 252 } 253 254 if (!IrpContext->ExceptionInProgress) { 255 256 if (Irp) { 257 258 if (Status == STATUS_PENDING && 259 !IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED)) { 260 261 Status = Ext2LockUserBuffer( 262 IrpContext->Irp, 263 Length, 264 IoWriteAccess ); 265 266 if (NT_SUCCESS(Status)) { 267 Status = Ext2QueueRequest(IrpContext); 268 } else { 269 Ext2CompleteIrpContext(IrpContext, Status); 270 } 271 272 } else { 273 274 if (NT_SUCCESS(Status)) { 275 276 if (!PagingIo) { 277 278 if (SynchronousIo) { 279 280 FileObject->CurrentByteOffset.QuadPart = 281 ByteOffset.QuadPart + Irp->IoStatus.Information; 282 } 283 284 FileObject->Flags |= FO_FILE_FAST_IO_READ; 285 } 286 } 287 288 Ext2CompleteIrpContext(IrpContext, Status);; 289 } 290 291 } else { 292 Ext2FreeIrpContext(IrpContext); 293 } 294 } 295 } _SEH2_END; 296 297 return Status; 298 } 299 300 301 #define SafeZeroMemory(AT,BYTE_COUNT) { \ 302 _SEH2_TRY { \ 303 if (AT) \ 304 RtlZeroMemory((AT), (BYTE_COUNT)); \ 305 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { \ 306 Ext2RaiseStatus( IrpContext, STATUS_INVALID_USER_BUFFER ); \ 307 } _SEH2_END; \ 308 } 309 310 NTSTATUS 311 Ext2ReadInode ( 312 IN PEXT2_IRP_CONTEXT IrpContext, 313 IN PEXT2_VCB Vcb, 314 IN PEXT2_MCB Mcb, 315 IN ULONGLONG Offset, 316 IN PVOID Buffer, 317 IN ULONG Size, 318 IN BOOLEAN bDirectIo, 319 OUT PULONG BytesRead 320 ) 321 { 322 PEXT2_EXTENT Chain = NULL; 323 PEXT2_EXTENT Extent = NULL, Prev = NULL; 324 325 IO_STATUS_BLOCK IoStatus; 326 NTSTATUS Status = STATUS_UNSUCCESSFUL; 327 ULONG RealSize ; 328 329 if (BytesRead) { 330 *BytesRead = 0; 331 } 332 333 _SEH2_TRY { 334 335 Ext2ReferMcb(Mcb); 336 337 ASSERT((Mcb->Identifier.Type == EXT2MCB) && 338 (Mcb->Identifier.Size == sizeof(EXT2_MCB))); 339 340 if ((Mcb->Identifier.Type != EXT2MCB) || 341 (Mcb->Identifier.Size != sizeof(EXT2_MCB))) { 342 _SEH2_LEAVE; 343 } 344 345 if (Buffer == NULL && IrpContext != NULL) 346 Buffer = Ext2GetUserBuffer(IrpContext->Irp); 347 348 349 /* handle fast symlinks */ 350 if (S_ISLNK(Mcb->Inode.i_mode) && 0 == Mcb->Inode.i_blocks) { 351 352 PUCHAR Data = (PUCHAR) (&Mcb->Inode.i_block[0]); 353 if (!Buffer) { 354 Status = STATUS_INSUFFICIENT_RESOURCES; 355 _SEH2_LEAVE; 356 } 357 358 if (Offset < EXT2_LINKLEN_IN_INODE) { 359 if ((ULONG)Offset + Size >= EXT2_LINKLEN_IN_INODE) 360 Size = EXT2_LINKLEN_IN_INODE - (ULONG)Offset - 1; 361 RtlCopyMemory(Buffer, Data + (ULONG)Offset, Size); 362 Status = STATUS_SUCCESS; 363 } else { 364 Status = STATUS_END_OF_FILE; 365 } 366 _SEH2_LEAVE; 367 } 368 369 // 370 // Build the scatterred block ranges to be read 371 // 372 373 if (bDirectIo) { 374 RealSize = CEILING_ALIGNED(ULONG, Size, SECTOR_SIZE - 1); 375 } else { 376 RealSize = Size; 377 } 378 379 Status = Ext2BuildExtents( 380 IrpContext, 381 Vcb, 382 Mcb, 383 Offset, 384 RealSize, 385 FALSE, 386 &Chain 387 ); 388 389 if (!NT_SUCCESS(Status)) { 390 _SEH2_LEAVE; 391 } 392 393 if (Chain == NULL) { 394 SafeZeroMemory((PCHAR)Buffer, Size); 395 Status = STATUS_SUCCESS; 396 _SEH2_LEAVE; 397 } 398 399 /* for sparse file, we need zero the gaps */ 400 for (Extent = Chain; Buffer != NULL && Extent != NULL; Extent = Extent->Next) { 401 if (NULL == Prev) { 402 ASSERT(Extent == Chain); 403 if (Extent->Offset) { 404 SafeZeroMemory((PCHAR)Buffer, Extent->Offset); 405 } 406 } else if (Extent->Offset > (Prev->Offset + Prev->Length)) { 407 SafeZeroMemory((PCHAR)Buffer + Prev->Offset + Prev->Length, 408 Extent->Offset - Prev->Offset - Prev->Length); 409 } 410 if (NULL == Extent->Next) { 411 if (Extent->Offset + Extent->Length < Size) { 412 SafeZeroMemory((PCHAR)Buffer + Extent->Offset + Extent->Length, 413 Size - Extent->Offset - Extent->Length); 414 } 415 } 416 Prev = Extent; 417 } 418 419 if (bDirectIo) { 420 421 ASSERT(IrpContext != NULL); 422 423 // Offset should be SECTOR_SIZE aligned ... 424 Status = Ext2ReadWriteBlocks( 425 IrpContext, 426 Vcb, 427 Chain, 428 Size 429 ); 430 } else { 431 432 for (Extent = Chain; Extent != NULL; Extent = Extent->Next) { 433 434 if (!CcCopyRead( 435 Vcb->Volume, 436 (PLARGE_INTEGER)(&(Extent->Lba)), 437 Extent->Length, 438 PIN_WAIT, 439 (PVOID)((PUCHAR)Buffer + Extent->Offset), 440 &IoStatus 441 )) { 442 Status = STATUS_CANT_WAIT; 443 } else { 444 Status = IoStatus.Status; 445 } 446 447 if (!NT_SUCCESS(Status)) { 448 break; 449 } 450 } 451 } 452 453 } _SEH2_FINALLY { 454 455 if (Chain) { 456 Ext2DestroyExtentChain(Chain); 457 } 458 459 Ext2DerefMcb(Mcb); 460 } _SEH2_END; 461 462 if (NT_SUCCESS(Status)) { 463 if (BytesRead) 464 *BytesRead = Size; 465 } 466 467 return Status; 468 } 469 470 NTSTATUS 471 Ext2ReadFile(IN PEXT2_IRP_CONTEXT IrpContext) 472 { 473 NTSTATUS Status = STATUS_UNSUCCESSFUL; 474 475 PEXT2_VCB Vcb = NULL; 476 PEXT2_FCB Fcb = NULL; 477 PEXT2_CCB Ccb = NULL; 478 PFILE_OBJECT FileObject = NULL; 479 480 PDEVICE_OBJECT DeviceObject = NULL; 481 482 PIRP Irp = NULL; 483 PIO_STACK_LOCATION IoStackLocation = NULL; 484 485 ULONG Length; 486 ULONG ReturnedLength = 0; 487 LARGE_INTEGER ByteOffset; 488 489 BOOLEAN OpPostIrp = FALSE; 490 BOOLEAN PagingIo; 491 BOOLEAN Nocache; 492 BOOLEAN SynchronousIo; 493 BOOLEAN MainResourceAcquired = FALSE; 494 BOOLEAN PagingIoResourceAcquired = FALSE; 495 496 PUCHAR Buffer; 497 498 _SEH2_TRY { 499 500 ASSERT(IrpContext); 501 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 502 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 503 504 DeviceObject = IrpContext->DeviceObject; 505 Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; 506 ASSERT(Vcb != NULL); 507 ASSERT((Vcb->Identifier.Type == EXT2VCB) && 508 (Vcb->Identifier.Size == sizeof(EXT2_VCB))); 509 510 FileObject = IrpContext->FileObject; 511 Fcb = (PEXT2_FCB) FileObject->FsContext; 512 ASSERT(Fcb); 513 ASSERT((Fcb->Identifier.Type == EXT2FCB) && 514 (Fcb->Identifier.Size == sizeof(EXT2_FCB))); 515 516 Ccb = (PEXT2_CCB) FileObject->FsContext2; 517 518 Irp = IrpContext->Irp; 519 IoStackLocation = IoGetCurrentIrpStackLocation(Irp); 520 521 Length = IoStackLocation->Parameters.Read.Length; 522 ByteOffset = IoStackLocation->Parameters.Read.ByteOffset; 523 524 PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO); 525 Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE); 526 SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO); 527 528 if (PagingIo) { 529 ASSERT(Nocache); 530 } 531 532 DEBUG(DL_INF, ("Ext2ReadFile: reading %wZ Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n", 533 &Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache)); 534 535 if (IsSpecialFile(Fcb) || IsInodeSymLink(Fcb->Inode) ) { 536 Status = STATUS_INVALID_DEVICE_REQUEST; 537 _SEH2_LEAVE; 538 } 539 540 if ((IsSymLink(Fcb) && IsFileDeleted(Fcb->Mcb->Target)) || 541 IsFileDeleted(Fcb->Mcb)) { 542 Status = STATUS_FILE_DELETED; 543 _SEH2_LEAVE; 544 } 545 546 if (Length == 0) { 547 Irp->IoStatus.Information = 0; 548 Status = STATUS_SUCCESS; 549 _SEH2_LEAVE; 550 } 551 552 if (ByteOffset.LowPart == FILE_USE_FILE_POINTER_POSITION && 553 ByteOffset.HighPart == -1) { 554 ByteOffset = FileObject->CurrentByteOffset; 555 } 556 557 if (Nocache && (ByteOffset.LowPart & (SECTOR_SIZE - 1) || 558 Length & (SECTOR_SIZE - 1))) { 559 Status = STATUS_INVALID_PARAMETER; 560 DbgBreak(); 561 _SEH2_LEAVE; 562 } 563 564 if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) { 565 ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); 566 Status = STATUS_PENDING; 567 DbgBreak(); 568 _SEH2_LEAVE; 569 } 570 571 ReturnedLength = Length; 572 573 if (PagingIo) { 574 575 if (!ExAcquireResourceSharedLite( 576 &Fcb->PagingIoResource, 577 IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { 578 Status = STATUS_PENDING; 579 _SEH2_LEAVE; 580 } 581 PagingIoResourceAcquired = TRUE; 582 583 } else { 584 585 if (Nocache && Ccb != NULL && Fcb->SectionObject.DataSectionObject) { 586 587 if (!ExAcquireResourceExclusiveLite( 588 &Fcb->MainResource, 589 IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { 590 Status = STATUS_PENDING; 591 _SEH2_LEAVE; 592 } 593 MainResourceAcquired = TRUE; 594 595 CcFlushCache(&Fcb->SectionObject, 596 &ByteOffset, 597 Length, 598 &Irp->IoStatus ); 599 if (!NT_SUCCESS(Irp->IoStatus.Status)) 600 _SEH2_LEAVE; 601 ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED); 602 603 if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) { 604 ExReleaseResourceLite(&(Fcb->PagingIoResource)); 605 } 606 CcPurgeCacheSection( &Fcb->SectionObject, 607 NULL, 608 0, 609 FALSE ); 610 611 ExConvertExclusiveToShared(&Fcb->MainResource); 612 613 } else { 614 615 if (!ExAcquireResourceSharedLite( 616 &Fcb->MainResource, 617 IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { 618 Status = STATUS_PENDING; 619 _SEH2_LEAVE; 620 } 621 MainResourceAcquired = TRUE; 622 } 623 624 if (!FsRtlCheckLockForReadAccess( 625 &Fcb->FileLockAnchor, 626 Irp )) { 627 Status = STATUS_FILE_LOCK_CONFLICT; 628 _SEH2_LEAVE; 629 } 630 } 631 632 if ((ByteOffset.QuadPart + (LONGLONG)Length) > Fcb->Header.FileSize.QuadPart) { 633 if (ByteOffset.QuadPart >= Fcb->Header.FileSize.QuadPart) { 634 Irp->IoStatus.Information = 0; 635 Status = STATUS_END_OF_FILE; 636 _SEH2_LEAVE; 637 } 638 ReturnedLength = (ULONG)(Fcb->Header.FileSize.QuadPart - ByteOffset.QuadPart); 639 } 640 641 642 if (!IsDirectory(Fcb) && Ccb != NULL) { 643 Status = FsRtlCheckOplock( &Fcb->Oplock, 644 Irp, 645 IrpContext, 646 Ext2OplockComplete, 647 Ext2LockIrp ); 648 649 if (Status != STATUS_SUCCESS) { 650 OpPostIrp = TRUE; 651 _SEH2_LEAVE; 652 } 653 654 // 655 // Set the flag indicating if Fast I/O is possible 656 // 657 658 Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); 659 } 660 661 if (!Nocache) { 662 663 if (IsDirectory(Fcb)) { 664 _SEH2_LEAVE; 665 } 666 667 if (FileObject->PrivateCacheMap == NULL) { 668 CcInitializeCacheMap( 669 FileObject, 670 (PCC_FILE_SIZES)(&Fcb->Header.AllocationSize), 671 FALSE, 672 &Ext2Global->CacheManagerCallbacks, 673 Fcb ); 674 CcSetReadAheadGranularity( 675 FileObject, 676 READ_AHEAD_GRANULARITY ); 677 } 678 679 if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) { 680 CcMdlRead( 681 FileObject, 682 (&ByteOffset), 683 ReturnedLength, 684 &Irp->MdlAddress, 685 &Irp->IoStatus ); 686 687 Status = Irp->IoStatus.Status; 688 689 } else { 690 691 Buffer = Ext2GetUserBuffer(Irp); 692 if (Buffer == NULL) { 693 Status = STATUS_INVALID_USER_BUFFER; 694 DbgBreak(); 695 _SEH2_LEAVE; 696 } 697 698 if (!CcCopyRead(FileObject, &ByteOffset, ReturnedLength, 699 Ext2CanIWait(), Buffer, &Irp->IoStatus)) { 700 701 if (Ext2CanIWait() || !CcCopyRead(FileObject, &ByteOffset, 702 ReturnedLength, TRUE, 703 Buffer, &Irp->IoStatus)) { 704 Status = STATUS_PENDING; 705 DbgBreak(); 706 _SEH2_LEAVE; 707 } 708 } 709 Status = Irp->IoStatus.Status; 710 } 711 712 } else { 713 714 ULONG BytesRead = ReturnedLength; 715 PUCHAR SystemVA = Ext2GetUserBuffer(IrpContext->Irp); 716 717 if (ByteOffset.QuadPart + BytesRead > Fcb->Header.ValidDataLength.QuadPart) { 718 719 if (ByteOffset.QuadPart >= Fcb->Header.ValidDataLength.QuadPart) { 720 if (SystemVA) { 721 SafeZeroMemory(SystemVA, Length); 722 } 723 Irp->IoStatus.Information = ReturnedLength; 724 Status = STATUS_SUCCESS; 725 _SEH2_LEAVE; 726 } else { 727 BytesRead = (ULONG)(Fcb->Header.ValidDataLength.QuadPart - ByteOffset.QuadPart); 728 if (SystemVA) { 729 SafeZeroMemory(SystemVA + BytesRead, Length - BytesRead); 730 } 731 } 732 } 733 734 Status = Ext2LockUserBuffer( 735 IrpContext->Irp, 736 BytesRead, 737 IoReadAccess ); 738 739 if (!NT_SUCCESS(Status)) { 740 _SEH2_LEAVE; 741 } 742 743 Status = Ext2ReadInode( 744 IrpContext, 745 Vcb, 746 Fcb->Mcb, 747 ByteOffset.QuadPart, 748 NULL, 749 BytesRead, 750 TRUE, 751 NULL ); 752 753 /* we need re-queue this request in case STATUS_CANT_WAIT 754 and fail it in other failure cases */ 755 if (!NT_SUCCESS(Status)) { 756 _SEH2_LEAVE; 757 } 758 759 /* pended by low level device */ 760 if (Status == STATUS_PENDING) { 761 IrpContext->Irp = Irp = NULL; 762 _SEH2_LEAVE; 763 } 764 765 Irp = IrpContext->Irp; 766 ASSERT(Irp); 767 Status = Irp->IoStatus.Status; 768 769 if (!NT_SUCCESS(Status)) { 770 Ext2NormalizeAndRaiseStatus(IrpContext, Status); 771 } 772 } 773 774 Irp->IoStatus.Information = ReturnedLength; 775 776 } _SEH2_FINALLY { 777 778 if (Irp) { 779 if (PagingIoResourceAcquired) { 780 ExReleaseResourceLite(&Fcb->PagingIoResource); 781 } 782 783 if (MainResourceAcquired) { 784 ExReleaseResourceLite(&Fcb->MainResource); 785 } 786 } 787 788 if (!OpPostIrp && !IrpContext->ExceptionInProgress) { 789 790 if (Irp) { 791 if ( Status == STATUS_PENDING || 792 Status == STATUS_CANT_WAIT) { 793 794 Status = Ext2LockUserBuffer( 795 IrpContext->Irp, 796 Length, 797 IoWriteAccess ); 798 799 if (NT_SUCCESS(Status)) { 800 Status = Ext2QueueRequest(IrpContext); 801 } else { 802 Ext2CompleteIrpContext(IrpContext, Status); 803 } 804 } else { 805 if (NT_SUCCESS(Status)) { 806 if (!PagingIo) { 807 if (SynchronousIo) { 808 FileObject->CurrentByteOffset.QuadPart = 809 ByteOffset.QuadPart + Irp->IoStatus.Information; 810 } 811 FileObject->Flags |= FO_FILE_FAST_IO_READ; 812 } 813 } 814 815 Ext2CompleteIrpContext(IrpContext, Status); 816 } 817 818 } else { 819 820 Ext2FreeIrpContext(IrpContext); 821 } 822 } 823 } _SEH2_END; 824 825 DEBUG(DL_IO, ("Ext2ReadFile: %wZ fetch at Off=%I64xh Len=%xh Paging=%xh Nocache=%xh Returned=%xh Status=%xh\n", 826 &Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache, ReturnedLength, Status)); 827 return Status; 828 829 } 830 831 NTSTATUS 832 Ext2ReadComplete (IN PEXT2_IRP_CONTEXT IrpContext) 833 { 834 NTSTATUS Status = STATUS_UNSUCCESSFUL; 835 PFILE_OBJECT FileObject; 836 PIRP Irp; 837 838 _SEH2_TRY { 839 840 ASSERT(IrpContext); 841 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 842 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 843 844 FileObject = IrpContext->FileObject; 845 Irp = IrpContext->Irp; 846 847 CcMdlReadComplete(FileObject, Irp->MdlAddress); 848 Irp->MdlAddress = NULL; 849 Status = STATUS_SUCCESS; 850 851 } _SEH2_FINALLY { 852 853 if (!IrpContext->ExceptionInProgress) { 854 Ext2CompleteIrpContext(IrpContext, Status); 855 } 856 } _SEH2_END; 857 858 return Status; 859 } 860 861 862 NTSTATUS 863 Ext2Read (IN PEXT2_IRP_CONTEXT IrpContext) 864 { 865 NTSTATUS Status; 866 PEXT2_VCB Vcb; 867 PEXT2_FCBVCB FcbOrVcb; 868 PDEVICE_OBJECT DeviceObject; 869 PFILE_OBJECT FileObject; 870 BOOLEAN bCompleteRequest; 871 872 ASSERT(IrpContext); 873 874 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 875 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 876 877 _SEH2_TRY { 878 879 if (FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE)) { 880 881 Status = Ext2ReadComplete(IrpContext); 882 bCompleteRequest = FALSE; 883 884 } else { 885 886 DeviceObject = IrpContext->DeviceObject; 887 888 if (IsExt2FsDevice(DeviceObject)) { 889 Status = STATUS_INVALID_DEVICE_REQUEST; 890 bCompleteRequest = TRUE; 891 _SEH2_LEAVE; 892 } 893 894 Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; 895 if (Vcb->Identifier.Type != EXT2VCB || 896 Vcb->Identifier.Size != sizeof(EXT2_VCB) ) { 897 Status = STATUS_INVALID_DEVICE_REQUEST; 898 bCompleteRequest = TRUE; 899 900 _SEH2_LEAVE; 901 } 902 903 FileObject = IrpContext->FileObject; 904 905 if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) && 906 Vcb->LockFile != FileObject ) { 907 Status = STATUS_ACCESS_DENIED; 908 _SEH2_LEAVE; 909 } 910 911 FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext; 912 913 if (FcbOrVcb->Identifier.Type == EXT2VCB) { 914 915 Status = Ext2ReadVolume(IrpContext); 916 bCompleteRequest = FALSE; 917 918 } else if (FcbOrVcb->Identifier.Type == EXT2FCB) { 919 920 if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) { 921 Status = STATUS_TOO_LATE; 922 bCompleteRequest = TRUE; 923 _SEH2_LEAVE; 924 } 925 926 Status = Ext2ReadFile(IrpContext); 927 bCompleteRequest = FALSE; 928 } else { 929 DEBUG(DL_ERR, ( "Ext2Read: Inavlid FileObject (Vcb or Fcb corrupted)\n")); 930 DbgBreak(); 931 932 Status = STATUS_INVALID_PARAMETER; 933 bCompleteRequest = TRUE; 934 } 935 } 936 937 } _SEH2_FINALLY { 938 if (bCompleteRequest) { 939 Ext2CompleteIrpContext(IrpContext, Status); 940 } 941 } _SEH2_END; 942 943 return Status; 944 } 945