1 /* 2 * COPYRIGHT: See COPYRIGHT.TXT 3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP 4 * FILE: write.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 #define DL_FLP DL_DBG 19 20 /* DEFINITIONS *************************************************************/ 21 22 #define EXT2_FLPFLUSH_MAGIC 'FF2E' 23 24 typedef struct _EXT2_FLPFLUSH_CONTEXT { 25 26 PEXT2_VCB Vcb; 27 PEXT2_FCB Fcb; 28 PFILE_OBJECT FileObject; 29 30 KDPC Dpc; 31 KTIMER Timer; 32 WORK_QUEUE_ITEM Item; 33 34 } EXT2_FLPFLUSH_CONTEXT, *PEXT2_FLPFLUSH_CONTEXT; 35 36 #ifdef __REACTOS__ 37 VOID NTAPI 38 #else 39 VOID 40 #endif 41 Ext2FloppyFlush(IN PVOID Parameter); 42 43 #ifdef __REACTOS__ 44 VOID NTAPI 45 #else 46 VOID 47 #endif 48 Ext2FloppyFlushDpc ( 49 IN PKDPC Dpc, 50 IN PVOID DeferredContext, 51 IN PVOID SystemArgument1, 52 IN PVOID SystemArgument2); 53 54 55 NTSTATUS 56 Ext2WriteComplete (IN PEXT2_IRP_CONTEXT IrpContext); 57 58 NTSTATUS 59 Ext2WriteFile (IN PEXT2_IRP_CONTEXT IrpContext); 60 61 NTSTATUS 62 Ext2WriteVolume (IN PEXT2_IRP_CONTEXT IrpContext); 63 64 VOID 65 Ext2DeferWrite(IN PEXT2_IRP_CONTEXT, PIRP Irp); 66 67 68 /* FUNCTIONS *************************************************************/ 69 70 #ifdef __REACTOS__ 71 VOID NTAPI 72 #else 73 VOID 74 #endif 75 Ext2FloppyFlush(IN PVOID Parameter) 76 { 77 PEXT2_FLPFLUSH_CONTEXT Context; 78 PFILE_OBJECT FileObject; 79 PEXT2_FCB Fcb; 80 PEXT2_VCB Vcb; 81 82 Context = (PEXT2_FLPFLUSH_CONTEXT) Parameter; 83 FileObject = Context->FileObject; 84 Fcb = Context->Fcb; 85 Vcb = Context->Vcb; 86 87 DEBUG(DL_FLP, ("Ext2FloppyFlushing ...\n")); 88 89 IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP); 90 91 if (FileObject) { 92 ASSERT(Fcb == (PEXT2_FCB)FileObject->FsContext); 93 ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE); 94 ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE); 95 ExReleaseResourceLite(&Fcb->PagingIoResource); 96 97 CcFlushCache(&(Fcb->SectionObject), NULL, 0, NULL); 98 ExReleaseResourceLite(&Fcb->MainResource); 99 100 ObDereferenceObject(FileObject); 101 } 102 103 if (Vcb) { 104 ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); 105 106 ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE); 107 ExReleaseResourceLite(&Vcb->PagingIoResource); 108 109 Ext2FlushVcb(Vcb); 110 ExReleaseResourceLite(&Vcb->MainResource); 111 } 112 113 IoSetTopLevelIrp(NULL); 114 Ext2FreePool(Parameter, EXT2_FLPFLUSH_MAGIC); 115 } 116 117 #ifdef __REACTOS__ 118 VOID NTAPI 119 #else 120 VOID 121 #endif 122 Ext2FloppyFlushDpc ( 123 IN PKDPC Dpc, 124 IN PVOID DeferredContext, 125 IN PVOID SystemArgument1, 126 IN PVOID SystemArgument2 127 ) 128 { 129 PEXT2_FLPFLUSH_CONTEXT Context; 130 131 Context = (PEXT2_FLPFLUSH_CONTEXT) DeferredContext; 132 133 DEBUG(DL_FLP, ("Ext2FloppyFlushDpc is to be started...\n")); 134 135 ExQueueWorkItem(&Context->Item, CriticalWorkQueue); 136 } 137 138 VOID 139 Ext2StartFloppyFlushDpc ( 140 PEXT2_VCB Vcb, 141 PEXT2_FCB Fcb, 142 PFILE_OBJECT FileObject ) 143 { 144 LARGE_INTEGER OneSecond; 145 PEXT2_FLPFLUSH_CONTEXT Context; 146 147 ASSERT(IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)); 148 149 Context = Ext2AllocatePool( 150 NonPagedPool, 151 sizeof(EXT2_FLPFLUSH_CONTEXT), 152 EXT2_FLPFLUSH_MAGIC 153 ); 154 155 if (!Context) { 156 DEBUG(DL_ERR, ( "Ex2StartFloppy...: failed to allocate Context\n")); 157 DbgBreak(); 158 return; 159 } 160 161 KeInitializeTimer(&Context->Timer); 162 163 KeInitializeDpc( &Context->Dpc, 164 Ext2FloppyFlushDpc, 165 Context ); 166 167 ExInitializeWorkItem( &Context->Item, 168 Ext2FloppyFlush, 169 Context ); 170 171 Context->Vcb = Vcb; 172 Context->Fcb = Fcb; 173 Context->FileObject = FileObject; 174 175 if (FileObject) { 176 ObReferenceObject(FileObject); 177 } 178 179 OneSecond.QuadPart = (LONGLONG)-1*1000*1000*10; 180 KeSetTimer( &Context->Timer, 181 OneSecond, 182 &Context->Dpc ); 183 } 184 185 BOOLEAN 186 Ext2ZeroData ( 187 IN PEXT2_IRP_CONTEXT IrpContext, 188 IN PEXT2_VCB Vcb, 189 IN PFILE_OBJECT FileObject, 190 IN PLARGE_INTEGER Start, 191 IN PLARGE_INTEGER End 192 ) 193 { 194 PEXT2_FCB Fcb; 195 PBCB Bcb; 196 PVOID Ptr; 197 ULONG Size; 198 BOOLEAN rc = TRUE; 199 200 ASSERT (End && Start && End->QuadPart > Start->QuadPart); 201 Fcb = (PEXT2_FCB) FileObject->FsContext; 202 203 /* skip data zero if we've already tracked unwritten part */ 204 if (0 == ( End->LowPart & (BLOCK_SIZE -1)) && 205 0 == (Start->LowPart & (BLOCK_SIZE -1))) { 206 207 if (INODE_HAS_EXTENT(Fcb->Inode)) { 208 return TRUE; 209 } else { 210 #if !EXT2_PRE_ALLOCATION_SUPPORT 211 return TRUE; 212 #endif 213 } 214 } 215 216 /* clear data in range [Start, End) */ 217 _SEH2_TRY { 218 rc = CcZeroData(FileObject, Start, End, Ext2CanIWait()); 219 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { 220 DbgBreak(); 221 } _SEH2_END; 222 223 return rc; 224 } 225 226 VOID 227 Ext2DeferWrite(IN PEXT2_IRP_CONTEXT IrpContext, PIRP Irp) 228 { 229 ASSERT(IrpContext->Irp == Irp); 230 231 Ext2QueueRequest(IrpContext); 232 } 233 234 235 NTSTATUS 236 Ext2WriteVolume (IN PEXT2_IRP_CONTEXT IrpContext) 237 { 238 NTSTATUS Status = STATUS_UNSUCCESSFUL; 239 240 PEXT2_VCB Vcb = NULL; 241 PEXT2_CCB Ccb = NULL; 242 PEXT2_FCBVCB FcbOrVcb = NULL; 243 PFILE_OBJECT FileObject = NULL; 244 245 PDEVICE_OBJECT DeviceObject = NULL; 246 247 PIRP Irp = NULL; 248 PIO_STACK_LOCATION IoStackLocation = NULL; 249 250 ULONG Length; 251 LARGE_INTEGER ByteOffset; 252 253 BOOLEAN PagingIo = FALSE; 254 BOOLEAN Nocache = FALSE; 255 BOOLEAN SynchronousIo = FALSE; 256 BOOLEAN MainResourceAcquired = FALSE; 257 258 BOOLEAN bDeferred = FALSE; 259 260 PUCHAR Buffer = NULL; 261 PEXT2_EXTENT Chain = NULL; 262 EXT2_EXTENT BlockArray; 263 264 _SEH2_TRY { 265 266 ASSERT(IrpContext); 267 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 268 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 269 270 DeviceObject = IrpContext->DeviceObject; 271 Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; 272 ASSERT(Vcb != NULL); 273 ASSERT((Vcb->Identifier.Type == EXT2VCB) && 274 (Vcb->Identifier.Size == sizeof(EXT2_VCB))); 275 276 FileObject = IrpContext->FileObject; 277 FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext; 278 ASSERT(FcbOrVcb); 279 280 if (!(FcbOrVcb->Identifier.Type == EXT2VCB && (PVOID)FcbOrVcb == (PVOID)Vcb)) { 281 Status = STATUS_INVALID_DEVICE_REQUEST; 282 _SEH2_LEAVE; 283 } 284 285 Ccb = (PEXT2_CCB) FileObject->FsContext2; 286 Irp = IrpContext->Irp; 287 IoStackLocation = IoGetCurrentIrpStackLocation(Irp); 288 289 Length = IoStackLocation->Parameters.Write.Length; 290 ByteOffset = IoStackLocation->Parameters.Write.ByteOffset; 291 292 PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO); 293 Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE) || (Ccb != NULL); 294 SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO); 295 296 if (PagingIo) { 297 ASSERT(Nocache); 298 } 299 300 DEBUG(DL_INF, ("Ext2WriteVolume: Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n", 301 ByteOffset.QuadPart, Length, PagingIo, Nocache)); 302 303 if (Length == 0) { 304 Irp->IoStatus.Information = 0; 305 Status = STATUS_SUCCESS; 306 _SEH2_LEAVE; 307 } 308 309 if (Nocache && 310 (ByteOffset.LowPart & (SECTOR_SIZE - 1) || 311 Length & (SECTOR_SIZE - 1))) { 312 Status = STATUS_INVALID_PARAMETER; 313 _SEH2_LEAVE; 314 } 315 316 if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) { 317 ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); 318 Status = STATUS_PENDING; 319 _SEH2_LEAVE; 320 } 321 322 if (ByteOffset.QuadPart >= 323 Vcb->PartitionInformation.PartitionLength.QuadPart ) { 324 Irp->IoStatus.Information = 0; 325 Status = STATUS_END_OF_FILE; 326 _SEH2_LEAVE; 327 } 328 329 if (!Nocache) { 330 331 BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED); 332 BOOLEAN bWait = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); 333 BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED); 334 335 if ( !CcCanIWrite( 336 FileObject, 337 Length, 338 (bWait && bQueue), 339 bAgain ) ) { 340 341 Status = Ext2LockUserBuffer( 342 IrpContext->Irp, 343 Length, 344 IoReadAccess); 345 if (NT_SUCCESS(Status)) { 346 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED); 347 CcDeferWrite( FileObject, 348 (PCC_POST_DEFERRED_WRITE)Ext2DeferWrite, 349 IrpContext, 350 Irp, 351 Length, 352 bAgain ); 353 354 bDeferred = TRUE; 355 Status = STATUS_PENDING; 356 357 _SEH2_LEAVE; 358 } 359 } 360 } 361 362 /* 363 * User direct volume access 364 */ 365 366 if (Ccb != NULL && !PagingIo) { 367 368 if (!FlagOn(Ccb->Flags, CCB_VOLUME_DASD_PURGE)) { 369 370 if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) { 371 Status = Ext2PurgeVolume( Vcb, TRUE); 372 } 373 374 SetFlag(Ccb->Flags, CCB_VOLUME_DASD_PURGE); 375 } 376 377 if (!IsFlagOn(Ccb->Flags, CCB_ALLOW_EXTENDED_DASD_IO)) { 378 if (ByteOffset.QuadPart + Length > Vcb->Header.FileSize.QuadPart) { 379 Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart); 380 } 381 } 382 383 } else if (Nocache && !PagingIo && (Vcb->SectionObject.DataSectionObject != NULL)) { 384 385 ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); 386 MainResourceAcquired = TRUE; 387 388 ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE); 389 ExReleaseResourceLite(&Vcb->PagingIoResource); 390 391 CcFlushCache( &(Vcb->SectionObject), 392 &ByteOffset, 393 Length, 394 &(Irp->IoStatus)); 395 396 if (!NT_SUCCESS(Irp->IoStatus.Status)) { 397 Status = Irp->IoStatus.Status; 398 _SEH2_LEAVE; 399 } 400 401 ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE); 402 ExReleaseResourceLite(&Vcb->PagingIoResource); 403 404 CcPurgeCacheSection( &(Vcb->SectionObject), 405 (PLARGE_INTEGER)&(ByteOffset), 406 Length, 407 FALSE ); 408 409 ExReleaseResourceLite(&Vcb->MainResource); 410 MainResourceAcquired = FALSE; 411 } 412 413 if ( (ByteOffset.QuadPart + Length) > Vcb->Header.FileSize.QuadPart) { 414 Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart); 415 } 416 417 if (!Nocache) { 418 419 if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) { 420 421 CcPrepareMdlWrite ( 422 Vcb->Volume, 423 &ByteOffset, 424 Length, 425 &Irp->MdlAddress, 426 &Irp->IoStatus ); 427 428 Status = Irp->IoStatus.Status; 429 430 } else { 431 432 Buffer = Ext2GetUserBuffer(Irp); 433 if (Buffer == NULL) { 434 DbgBreak(); 435 436 Status = STATUS_INVALID_USER_BUFFER; 437 _SEH2_LEAVE; 438 } 439 440 if (!CcCopyWrite( Vcb->Volume, 441 (PLARGE_INTEGER)(&ByteOffset), 442 Length, 443 TRUE, 444 Buffer )) { 445 Status = STATUS_PENDING; 446 _SEH2_LEAVE; 447 } 448 449 Status = Irp->IoStatus.Status; 450 Ext2AddVcbExtent(Vcb, ByteOffset.QuadPart, (LONGLONG)Length); 451 } 452 453 if (NT_SUCCESS(Status)) { 454 Irp->IoStatus.Information = Length; 455 } 456 457 } else if (PagingIo) { 458 459 LONGLONG DirtyStart; 460 LONGLONG DirtyLba; 461 LONGLONG DirtyLength; 462 LONGLONG RemainLength; 463 464 PEXT2_EXTENT Extent = NULL; 465 PEXT2_EXTENT List = NULL; 466 467 Length &= ~((ULONG)SECTOR_SIZE - 1); 468 469 Status = Ext2LockUserBuffer(IrpContext->Irp, Length, IoReadAccess); 470 if (!NT_SUCCESS(Status)) { 471 _SEH2_LEAVE; 472 } 473 474 DirtyLba = ByteOffset.QuadPart; 475 RemainLength = (LONGLONG) Length; 476 477 ASSERT(Length >= SECTOR_SIZE); 478 479 while (RemainLength > 0) { 480 481 DirtyStart = DirtyLba; 482 ASSERT(DirtyStart >= ByteOffset.QuadPart); 483 ASSERT(DirtyStart <= ByteOffset.QuadPart + Length); 484 485 if (Ext2LookupVcbExtent(Vcb, DirtyStart, &DirtyLba, &DirtyLength)) { 486 487 if (DirtyLba == -1) { 488 489 DirtyLba = DirtyStart + DirtyLength; 490 if (ByteOffset.QuadPart + Length > DirtyLba) { 491 RemainLength = ByteOffset.QuadPart + Length - DirtyLba; 492 ASSERT(DirtyStart >= ByteOffset.QuadPart); 493 ASSERT(DirtyStart <= ByteOffset.QuadPart + Length); 494 } else { 495 RemainLength = 0; 496 } 497 continue; 498 } 499 500 ASSERT(DirtyLba <= DirtyStart); 501 Extent = Ext2AllocateExtent(); 502 503 if (!Extent) { 504 DEBUG(DL_ERR, ( "Ex2WriteVolume: failed to allocate Extent\n")); 505 Status = STATUS_INSUFFICIENT_RESOURCES; 506 _SEH2_LEAVE; 507 } 508 509 Extent->Irp = NULL; 510 Extent->Lba = DirtyStart; 511 Extent->Offset = (ULONG)( DirtyStart + Length - 512 RemainLength - DirtyLba ); 513 ASSERT(Extent->Offset <= Length); 514 515 if (DirtyLba + DirtyLength >= DirtyStart + RemainLength) { 516 Extent->Length = (ULONG)( DirtyLba + 517 RemainLength - 518 DirtyStart ); 519 ASSERT(Extent->Length <= Length); 520 RemainLength = 0; 521 } else { 522 Extent->Length = (ULONG)(DirtyLength + DirtyLba - DirtyStart); 523 RemainLength = RemainLength - Extent->Length; 524 /* 525 RemainLength = (DirtyStart + RemainLength) - 526 (DirtyLba + DirtyLength); 527 */ 528 ASSERT(RemainLength <= (LONGLONG)Length); 529 ASSERT(Extent->Length <= Length); 530 } 531 532 ASSERT(Extent->Length >= SECTOR_SIZE); 533 DirtyLba = DirtyStart + Extent->Length; 534 535 if (List) { 536 List->Next = Extent; 537 List = Extent; 538 } else { 539 Chain = List = Extent; 540 } 541 542 } else { 543 544 if (RemainLength > SECTOR_SIZE) { 545 DirtyLba = DirtyStart + SECTOR_SIZE; 546 RemainLength -= SECTOR_SIZE; 547 } else { 548 RemainLength = 0; 549 } 550 } 551 } 552 553 if (Chain) { 554 Status = Ext2ReadWriteBlocks(IrpContext, 555 Vcb, 556 Chain, 557 Length ); 558 Irp = IrpContext->Irp; 559 560 if (NT_SUCCESS(Status)) { 561 for (Extent = Chain; Extent != NULL; Extent = Extent->Next) { 562 Ext2RemoveVcbExtent(Vcb, Extent->Lba, Extent->Length); 563 } 564 } 565 566 if (!Irp) { 567 _SEH2_LEAVE; 568 } 569 570 } else { 571 572 Irp->IoStatus.Information = Length; 573 Status = STATUS_SUCCESS; 574 _SEH2_LEAVE; 575 } 576 577 } else { 578 579 Length &= ~((ULONG)SECTOR_SIZE - 1); 580 581 Status = Ext2LockUserBuffer( 582 IrpContext->Irp, 583 Length, 584 IoWriteAccess ); 585 586 if (!NT_SUCCESS(Status)) { 587 _SEH2_LEAVE; 588 } 589 590 BlockArray.Irp = NULL; 591 BlockArray.Lba = ByteOffset.QuadPart; 592 BlockArray.Offset = 0; 593 BlockArray.Length = Length; 594 BlockArray.Next = NULL; 595 596 Status = Ext2ReadWriteBlocks(IrpContext, 597 Vcb, 598 &BlockArray, 599 Length ); 600 601 if (NT_SUCCESS(Status)) { 602 Irp->IoStatus.Information = Length; 603 } 604 605 Irp = IrpContext->Irp; 606 if (!Irp) { 607 _SEH2_LEAVE; 608 } 609 } 610 611 } _SEH2_FINALLY { 612 613 if (MainResourceAcquired) { 614 ExReleaseResourceLite(&Vcb->MainResource); 615 } 616 617 if (!IrpContext->ExceptionInProgress) { 618 619 if (Irp) { 620 621 if (Status == STATUS_PENDING) { 622 623 if (!bDeferred) { 624 Status = Ext2LockUserBuffer( 625 IrpContext->Irp, 626 Length, 627 IoReadAccess ); 628 629 if (NT_SUCCESS(Status)) { 630 Status = Ext2QueueRequest(IrpContext); 631 } else { 632 Ext2CompleteIrpContext(IrpContext, Status); 633 } 634 } 635 636 } else { 637 638 if (NT_SUCCESS(Status)) { 639 640 if (SynchronousIo && !PagingIo) { 641 FileObject->CurrentByteOffset.QuadPart = 642 ByteOffset.QuadPart + Irp->IoStatus.Information; 643 } 644 645 if (!PagingIo) { 646 SetFlag(FileObject->Flags, FO_FILE_MODIFIED); 647 } 648 } 649 650 Ext2CompleteIrpContext(IrpContext, Status); 651 } 652 653 } else { 654 655 Ext2FreeIrpContext(IrpContext); 656 } 657 } 658 659 if (Chain) { 660 Ext2DestroyExtentChain(Chain); 661 } 662 } _SEH2_END; 663 664 return Status; 665 } 666 667 NTSTATUS 668 Ext2WriteInode ( 669 IN PEXT2_IRP_CONTEXT IrpContext, 670 IN PEXT2_VCB Vcb, 671 IN PEXT2_MCB Mcb, 672 IN ULONGLONG Offset, 673 IN PVOID Buffer, 674 IN ULONG Size, 675 IN BOOLEAN bDirectIo, 676 OUT PULONG BytesWritten 677 ) 678 { 679 PEXT2_EXTENT Chain = NULL; 680 NTSTATUS Status = STATUS_UNSUCCESSFUL; 681 682 _SEH2_TRY { 683 684 if (BytesWritten) { 685 *BytesWritten = 0; 686 } 687 688 Status = Ext2BuildExtents ( 689 IrpContext, 690 Vcb, 691 Mcb, 692 Offset, 693 Size, 694 S_ISDIR(Mcb->Inode.i_mode) ? FALSE : TRUE, 695 &Chain 696 ); 697 698 if (!NT_SUCCESS(Status)) { 699 _SEH2_LEAVE; 700 } 701 702 if (Chain == NULL) { 703 Status = STATUS_SUCCESS; 704 _SEH2_LEAVE; 705 } 706 707 if (bDirectIo) { 708 709 ASSERT(IrpContext != NULL); 710 711 // 712 // We assume the offset is aligned. 713 // 714 715 Status = Ext2ReadWriteBlocks( 716 IrpContext, 717 Vcb, 718 Chain, 719 Size 720 ); 721 722 } else { 723 724 PEXT2_EXTENT Extent; 725 for (Extent = Chain; Extent != NULL; Extent = Extent->Next) { 726 727 if ( !Ext2SaveBuffer( 728 IrpContext, 729 Vcb, 730 Extent->Lba, 731 Extent->Length, 732 (PVOID)((PUCHAR)Buffer + Extent->Offset) 733 )) { 734 _SEH2_LEAVE; 735 } 736 } 737 738 if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) { 739 740 DEBUG(DL_FLP, ("Ext2WriteInode is starting FlushingDpc...\n")); 741 Ext2StartFloppyFlushDpc(Vcb, NULL, NULL); 742 } 743 744 Status = STATUS_SUCCESS; 745 } 746 747 } _SEH2_FINALLY { 748 749 if (Chain) { 750 Ext2DestroyExtentChain(Chain); 751 } 752 753 if (NT_SUCCESS(Status) && BytesWritten) { 754 *BytesWritten = Size; 755 } 756 } _SEH2_END; 757 758 return Status; 759 } 760 761 762 NTSTATUS 763 Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext) 764 { 765 PEXT2_VCB Vcb = NULL; 766 PEXT2_FCB Fcb = NULL; 767 PEXT2_CCB Ccb = NULL; 768 PFILE_OBJECT FileObject = NULL; 769 770 PDEVICE_OBJECT DeviceObject = NULL; 771 772 PIRP Irp = NULL; 773 PIO_STACK_LOCATION IoStackLocation = NULL; 774 PUCHAR Buffer = NULL; 775 776 LARGE_INTEGER ByteOffset; 777 ULONG ReturnedLength = 0; 778 ULONG Length; 779 780 NTSTATUS Status = STATUS_UNSUCCESSFUL; 781 782 BOOLEAN OpPostIrp = FALSE; 783 BOOLEAN PagingIo = FALSE; 784 BOOLEAN Nocache = FALSE; 785 BOOLEAN SynchronousIo = FALSE; 786 787 BOOLEAN RecursiveWriteThrough = FALSE; 788 BOOLEAN MainResourceAcquired = FALSE; 789 BOOLEAN PagingIoResourceAcquired = FALSE; 790 791 BOOLEAN bDeferred = FALSE; 792 #ifndef __REACTOS__ 793 BOOLEAN UpdateFileValidSize = FALSE; 794 #endif 795 BOOLEAN FileSizesChanged = FALSE; 796 BOOLEAN rc; 797 798 799 _SEH2_TRY { 800 801 ASSERT(IrpContext); 802 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 803 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 804 805 DeviceObject = IrpContext->DeviceObject; 806 Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; 807 ASSERT(Vcb != NULL); 808 ASSERT((Vcb->Identifier.Type == EXT2VCB) && 809 (Vcb->Identifier.Size == sizeof(EXT2_VCB))); 810 811 FileObject = IrpContext->FileObject; 812 Fcb = (PEXT2_FCB) FileObject->FsContext; 813 Ccb = (PEXT2_CCB) FileObject->FsContext2; 814 ASSERT(Fcb); 815 ASSERT((Fcb->Identifier.Type == EXT2FCB) && 816 (Fcb->Identifier.Size == sizeof(EXT2_FCB))); 817 818 Irp = IrpContext->Irp; 819 IoStackLocation = IoGetCurrentIrpStackLocation(Irp); 820 821 Length = IoStackLocation->Parameters.Write.Length; 822 ByteOffset = IoStackLocation->Parameters.Write.ByteOffset; 823 824 PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO); 825 Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE); 826 SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO); 827 828 if (PagingIo) { 829 ASSERT(Nocache); 830 } 831 832 DEBUG(DL_INF, ("Ext2WriteFile: %wZ Offset=%I64xh Length=%xh Paging=%xh Nocache=%xh\n", 833 &Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache)); 834 835 if (IsSpecialFile(Fcb) || IsInodeSymLink(Fcb->Inode) ) { 836 Status = STATUS_INVALID_DEVICE_REQUEST; 837 _SEH2_LEAVE; 838 } 839 840 if (IsFileDeleted(Fcb->Mcb) || 841 (IsSymLink(Fcb) && IsFileDeleted(Fcb->Mcb->Target)) ) { 842 Status = STATUS_FILE_DELETED; 843 _SEH2_LEAVE; 844 } 845 846 if (Length == 0) { 847 Irp->IoStatus.Information = 0; 848 Status = STATUS_SUCCESS; 849 _SEH2_LEAVE; 850 } 851 852 if (ByteOffset.LowPart == FILE_USE_FILE_POINTER_POSITION && 853 ByteOffset.HighPart == -1) { 854 ByteOffset = FileObject->CurrentByteOffset; 855 } else if (IsWritingToEof(ByteOffset)) { 856 ByteOffset.QuadPart = Fcb->Header.FileSize.QuadPart; 857 } 858 859 if (Nocache && !PagingIo && 860 ( (ByteOffset.LowPart & (SECTOR_SIZE - 1)) || 861 (Length & (SECTOR_SIZE - 1))) ) { 862 Status = STATUS_INVALID_PARAMETER; 863 _SEH2_LEAVE; 864 } 865 866 if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) { 867 ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); 868 Status = STATUS_PENDING; 869 _SEH2_LEAVE; 870 } 871 872 if (!Nocache) { 873 874 BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED); 875 BOOLEAN bWait = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); 876 BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED); 877 878 if ( !CcCanIWrite( 879 FileObject, 880 Length, 881 (bWait && bQueue), 882 bAgain ) ) { 883 884 Status = Ext2LockUserBuffer( 885 IrpContext->Irp, 886 Length, 887 IoReadAccess); 888 889 if (NT_SUCCESS(Status)) { 890 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED); 891 CcDeferWrite( FileObject, 892 (PCC_POST_DEFERRED_WRITE)Ext2DeferWrite, 893 IrpContext, 894 Irp, 895 Length, 896 bAgain ); 897 bDeferred = TRUE; 898 Status = STATUS_PENDING; 899 _SEH2_LEAVE; 900 } 901 } 902 } 903 904 if (IsDirectory(Fcb) && !PagingIo) { 905 Status = STATUS_INVALID_DEVICE_REQUEST; 906 _SEH2_LEAVE; 907 } 908 909 if (IsFlagOn(Irp->Flags, IRP_SYNCHRONOUS_PAGING_IO) && !IrpContext->IsTopLevel) { 910 911 PIRP TopIrp; 912 913 TopIrp = IoGetTopLevelIrp(); 914 915 if ( (ULONG_PTR)TopIrp > FSRTL_MAX_TOP_LEVEL_IRP_FLAG && 916 NodeType(TopIrp) == IO_TYPE_IRP) { 917 918 PIO_STACK_LOCATION IrpStack; 919 920 IrpStack = IoGetCurrentIrpStackLocation(TopIrp); 921 922 if ((IrpStack->MajorFunction == IRP_MJ_WRITE) && 923 (IrpStack->FileObject->FsContext == FileObject->FsContext) && 924 !FlagOn(TopIrp->Flags, IRP_NOCACHE) ) { 925 926 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH); 927 RecursiveWriteThrough = TRUE; 928 } 929 } 930 } 931 932 if (PagingIo) { 933 934 if (!ExAcquireResourceSharedLite(&Fcb->PagingIoResource, TRUE)) { 935 Status = STATUS_PENDING; 936 _SEH2_LEAVE; 937 } 938 PagingIoResourceAcquired = TRUE; 939 940 if ( (ByteOffset.QuadPart + Length) > Fcb->Header.FileSize.QuadPart) { 941 942 if (ByteOffset.QuadPart >= Fcb->Header.AllocationSize.QuadPart) { 943 944 Status = STATUS_SUCCESS; 945 Irp->IoStatus.Information = 0; 946 _SEH2_LEAVE; 947 948 } else { 949 950 ReturnedLength = (ULONG)(Fcb->Header.FileSize.QuadPart - ByteOffset.QuadPart); 951 if (ByteOffset.QuadPart + Length > Fcb->Header.AllocationSize.QuadPart) 952 Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart - ByteOffset.QuadPart); 953 } 954 955 } else { 956 957 ReturnedLength = Length; 958 } 959 960 } else { 961 962 if (!Ext2CheckFileAccess(Vcb, Fcb->Mcb, Ext2FileCanWrite)) { 963 Status = STATUS_ACCESS_DENIED; 964 _SEH2_LEAVE; 965 } 966 967 if (IsDirectory(Fcb)) { 968 _SEH2_LEAVE; 969 } 970 971 if (!ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE)) { 972 Status = STATUS_PENDING; 973 _SEH2_LEAVE; 974 } 975 MainResourceAcquired = TRUE; 976 977 // 978 // Do flushing for such cases 979 // 980 if (Nocache && Ccb != NULL && Fcb->SectionObject.DataSectionObject != NULL) { 981 982 ExAcquireSharedStarveExclusive( &Fcb->PagingIoResource, TRUE); 983 ExReleaseResourceLite(&Fcb->PagingIoResource); 984 985 CcFlushCache( &(Fcb->SectionObject), 986 &ByteOffset, 987 CEILING_ALIGNED(ULONG, Length, BLOCK_SIZE), 988 &(Irp->IoStatus)); 989 ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED); 990 991 if (!NT_SUCCESS(Irp->IoStatus.Status)) { 992 Status = Irp->IoStatus.Status; 993 _SEH2_LEAVE; 994 } 995 996 ExAcquireSharedStarveExclusive( &Fcb->PagingIoResource, TRUE); 997 ExReleaseResourceLite(&Fcb->PagingIoResource); 998 999 CcPurgeCacheSection( &(Fcb->SectionObject), 1000 &(ByteOffset), 1001 CEILING_ALIGNED(ULONG, Length, BLOCK_SIZE), 1002 FALSE ); 1003 } 1004 1005 if (!FsRtlCheckLockForWriteAccess(&Fcb->FileLockAnchor, Irp)) { 1006 Status = STATUS_FILE_LOCK_CONFLICT; 1007 _SEH2_LEAVE; 1008 } 1009 1010 if (Ccb != NULL) { 1011 Status = FsRtlCheckOplock( &Fcb->Oplock, 1012 Irp, 1013 IrpContext, 1014 Ext2OplockComplete, 1015 Ext2LockIrp ); 1016 1017 if (Status != STATUS_SUCCESS) { 1018 OpPostIrp = TRUE; 1019 _SEH2_LEAVE; 1020 } 1021 1022 // 1023 // Set the flag indicating if Fast I/O is possible 1024 // 1025 1026 Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); 1027 } 1028 1029 // 1030 // Extend the inode size when the i/o is beyond the file end ? 1031 // 1032 1033 if ((ByteOffset.QuadPart + Length) > Fcb->Header.FileSize.QuadPart) { 1034 1035 LARGE_INTEGER AllocationSize, Last; 1036 1037 if (!ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE)) { 1038 Status = STATUS_PENDING; 1039 _SEH2_LEAVE; 1040 } 1041 PagingIoResourceAcquired = TRUE; 1042 1043 /* let this irp wait, since it has to be synchronous */ 1044 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); 1045 1046 Last.QuadPart = Fcb->Header.AllocationSize.QuadPart; 1047 AllocationSize.QuadPart = (LONGLONG)(ByteOffset.QuadPart + Length); 1048 AllocationSize.QuadPart = CEILING_ALIGNED(ULONGLONG, 1049 (ULONGLONG)AllocationSize.QuadPart, 1050 (ULONGLONG)BLOCK_SIZE); 1051 1052 /* tell Ext2ExpandFile to allocate unwritten extent or NULL blocks 1053 for indirect files, otherwise we might get gabage data in holes */ 1054 IrpContext->MajorFunction += IRP_MJ_MAXIMUM_FUNCTION; 1055 Status = Ext2ExpandFile(IrpContext, Vcb, Fcb->Mcb, &AllocationSize); 1056 IrpContext->MajorFunction -= IRP_MJ_MAXIMUM_FUNCTION; 1057 if (AllocationSize.QuadPart > Last.QuadPart) { 1058 Fcb->Header.AllocationSize.QuadPart = AllocationSize.QuadPart; 1059 SetLongFlag(Fcb->Flags, FCB_ALLOC_IN_WRITE); 1060 } 1061 ExReleaseResourceLite(&Fcb->PagingIoResource); 1062 PagingIoResourceAcquired = FALSE; 1063 1064 if (ByteOffset.QuadPart >= Fcb->Header.AllocationSize.QuadPart) { 1065 if (NT_SUCCESS(Status)) { 1066 DbgBreak(); 1067 Status = STATUS_UNSUCCESSFUL; 1068 } 1069 _SEH2_LEAVE; 1070 } 1071 1072 if (ByteOffset.QuadPart + Length > Fcb->Header.AllocationSize.QuadPart) { 1073 Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart - ByteOffset.QuadPart); 1074 } 1075 1076 Fcb->Header.FileSize.QuadPart = Fcb->Inode->i_size = ByteOffset.QuadPart + Length; 1077 Ext2SaveInode(IrpContext, Vcb, Fcb->Inode); 1078 1079 if (CcIsFileCached(FileObject)) { 1080 CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); 1081 } 1082 1083 FileObject->Flags |= FO_FILE_SIZE_CHANGED | FO_FILE_MODIFIED; 1084 FileSizesChanged = TRUE; 1085 1086 if (Fcb->Header.FileSize.QuadPart >= 0x80000000 && 1087 !IsFlagOn(SUPER_BLOCK->s_feature_ro_compat, EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) { 1088 SetFlag(SUPER_BLOCK->s_feature_ro_compat, EXT2_FEATURE_RO_COMPAT_LARGE_FILE); 1089 Ext2SaveSuper(IrpContext, Vcb); 1090 } 1091 1092 DEBUG(DL_IO, ("Ext2WriteFile: expanding %wZ to FS: %I64xh FA: %I64xh\n", 1093 &Fcb->Mcb->ShortName, Fcb->Header.FileSize.QuadPart, 1094 Fcb->Header.AllocationSize.QuadPart)); 1095 } 1096 1097 ReturnedLength = Length; 1098 } 1099 1100 if (!Nocache) { 1101 1102 if (FileObject->PrivateCacheMap == NULL) { 1103 CcInitializeCacheMap( 1104 FileObject, 1105 (PCC_FILE_SIZES)(&Fcb->Header.AllocationSize), 1106 FALSE, 1107 &Ext2Global->CacheManagerCallbacks, 1108 Fcb ); 1109 1110 CcSetReadAheadGranularity( 1111 FileObject, 1112 READ_AHEAD_GRANULARITY ); 1113 } 1114 1115 if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) { 1116 1117 CcPrepareMdlWrite( 1118 FileObject, 1119 &ByteOffset, 1120 Length, 1121 &Irp->MdlAddress, 1122 &Irp->IoStatus ); 1123 1124 Status = Irp->IoStatus.Status; 1125 1126 } else { 1127 1128 Buffer = Ext2GetUserBuffer(Irp); 1129 if (Buffer == NULL) { 1130 DbgBreak(); 1131 Status = STATUS_INVALID_USER_BUFFER; 1132 _SEH2_LEAVE; 1133 } 1134 1135 if (ByteOffset.QuadPart > Fcb->Header.ValidDataLength.QuadPart) { 1136 1137 /* let this irp wait, since it has to be synchronous */ 1138 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); 1139 1140 rc = Ext2ZeroData(IrpContext, Vcb, FileObject, 1141 &Fcb->Header.ValidDataLength, &ByteOffset); 1142 if (!rc) { 1143 Status = STATUS_PENDING; 1144 DbgBreak(); 1145 _SEH2_LEAVE; 1146 } 1147 } 1148 1149 if (!CcCopyWrite(FileObject, &ByteOffset, Length, Ext2CanIWait(), Buffer)) { 1150 if (Ext2CanIWait() || 1151 !CcCopyWrite(FileObject, &ByteOffset, Length, TRUE, Buffer)) { 1152 Status = STATUS_PENDING; 1153 DbgBreak(); 1154 _SEH2_LEAVE; 1155 } 1156 } 1157 1158 if (ByteOffset.QuadPart + Length > Fcb->Header.ValidDataLength.QuadPart ) { 1159 1160 if (Fcb->Header.FileSize.QuadPart < ByteOffset.QuadPart + Length) { 1161 Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart; 1162 } else { 1163 if (Fcb->Header.ValidDataLength.QuadPart < ByteOffset.QuadPart + Length) 1164 Fcb->Header.ValidDataLength.QuadPart = ByteOffset.QuadPart + Length; 1165 } 1166 1167 CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); 1168 FileSizesChanged = TRUE; 1169 } 1170 1171 Status = STATUS_SUCCESS; 1172 } 1173 1174 if (NT_SUCCESS(Status)) { 1175 Irp->IoStatus.Information = Length; 1176 if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) { 1177 DEBUG(DL_FLP, ("Ext2WriteFile is starting FlushingDpc...\n")); 1178 Ext2StartFloppyFlushDpc(Vcb, Fcb, FileObject); 1179 } 1180 } 1181 1182 } else { 1183 1184 if (!PagingIo && !RecursiveWriteThrough && !IsLazyWriter(Fcb)) { 1185 if (ByteOffset.QuadPart > Fcb->Header.ValidDataLength.QuadPart) { 1186 1187 /* let this irp wait, since it has to be synchronous */ 1188 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); 1189 rc = Ext2ZeroData(IrpContext, Vcb, FileObject, 1190 &Fcb->Header.ValidDataLength, 1191 &ByteOffset); 1192 if (!rc) { 1193 Status = STATUS_PENDING; 1194 DbgBreak(); 1195 _SEH2_LEAVE; 1196 } 1197 } 1198 } 1199 1200 Status = Ext2LockUserBuffer( 1201 IrpContext->Irp, 1202 Length, 1203 IoReadAccess ); 1204 1205 if (!NT_SUCCESS(Status)) { 1206 _SEH2_LEAVE; 1207 } 1208 1209 Irp->IoStatus.Status = STATUS_SUCCESS; 1210 Irp->IoStatus.Information = ReturnedLength; 1211 1212 Status = Ext2WriteInode( 1213 IrpContext, 1214 Vcb, 1215 Fcb->Mcb, 1216 (ULONGLONG)(ByteOffset.QuadPart), 1217 NULL, 1218 ReturnedLength, 1219 TRUE, 1220 &Length 1221 ); 1222 1223 Irp = IrpContext->Irp; 1224 1225 if (NT_SUCCESS(Status) && !RecursiveWriteThrough && !IsLazyWriter(Fcb)) { 1226 1227 if (ByteOffset.QuadPart + Length > Fcb->Header.ValidDataLength.QuadPart ) { 1228 1229 FileSizesChanged = TRUE; 1230 1231 if (Fcb->Header.FileSize.QuadPart < ByteOffset.QuadPart + Length) { 1232 if (!PagingIo) 1233 Fcb->Header.FileSize.QuadPart = ByteOffset.QuadPart + Length; 1234 Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart; 1235 } else { 1236 if (Fcb->Header.ValidDataLength.QuadPart < ByteOffset.QuadPart + Length) 1237 Fcb->Header.ValidDataLength.QuadPart = ByteOffset.QuadPart + Length; 1238 } 1239 1240 if (!PagingIo && CcIsFileCached(FileObject)) { 1241 CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); 1242 } 1243 1244 DEBUG(DL_IO, ("Ext2WriteFile: %wZ written FS: %I64xh FA: %I64xh BO: %I64xh LEN: %u\n", 1245 &Fcb->Mcb->ShortName, Fcb->Header.FileSize.QuadPart, 1246 Fcb->Header.AllocationSize.QuadPart, ByteOffset.QuadPart, Length)); 1247 } 1248 } 1249 } 1250 1251 if (FileSizesChanged) { 1252 FileObject->Flags |= FO_FILE_SIZE_CHANGED | FO_FILE_MODIFIED; 1253 Ext2NotifyReportChange( IrpContext, Vcb, Fcb->Mcb, 1254 FILE_NOTIFY_CHANGE_SIZE, 1255 FILE_ACTION_MODIFIED ); 1256 } 1257 1258 } _SEH2_FINALLY { 1259 1260 /* 1261 * in case we got excpetions, we need revert MajorFunction 1262 * back to IRP_MJ_WRITE. The reason we do this, is to tell 1263 * Ext2ExpandFile to allocate unwritten extent or don't add 1264 * new blocks for indirect files. 1265 */ 1266 if (IrpContext->MajorFunction > IRP_MJ_MAXIMUM_FUNCTION) 1267 IrpContext->MajorFunction -= IRP_MJ_MAXIMUM_FUNCTION; 1268 1269 if (Irp) { 1270 if (PagingIoResourceAcquired) { 1271 ExReleaseResourceLite(&Fcb->PagingIoResource); 1272 } 1273 1274 if (MainResourceAcquired) { 1275 ExReleaseResourceLite(&Fcb->MainResource); 1276 } 1277 } 1278 1279 if (!OpPostIrp && !IrpContext->ExceptionInProgress) { 1280 1281 if (Irp) { 1282 1283 if (Status == STATUS_PENDING || 1284 Status == STATUS_CANT_WAIT ) { 1285 1286 if (!bDeferred) { 1287 Status = Ext2QueueRequest(IrpContext); 1288 } 1289 1290 } else { 1291 1292 if (NT_SUCCESS(Status) && !PagingIo) { 1293 1294 if (SynchronousIo) { 1295 FileObject->CurrentByteOffset.QuadPart = 1296 ByteOffset.QuadPart + Irp->IoStatus.Information; 1297 } 1298 1299 SetFlag(FileObject->Flags, FO_FILE_MODIFIED); 1300 SetLongFlag(Fcb->Flags, FCB_FILE_MODIFIED); 1301 } 1302 1303 Ext2CompleteIrpContext(IrpContext, Status); 1304 } 1305 } else { 1306 Ext2FreeIrpContext(IrpContext); 1307 } 1308 } 1309 } _SEH2_END; 1310 1311 DEBUG(DL_IO, ("Ext2WriteFile: %wZ written at Offset=%I64xh Length=%xh PagingIo=%d Nocache=%d " 1312 "RetLen=%xh VDL=%I64xh FileSize=%I64xh i_size=%I64xh Status=%xh\n", 1313 &Fcb->Mcb->ShortName, ByteOffset, Length, PagingIo, Nocache, ReturnedLength, 1314 Fcb->Header.ValidDataLength.QuadPart,Fcb->Header.FileSize.QuadPart, 1315 Fcb->Inode->i_size, Status)); 1316 1317 return Status; 1318 } 1319 1320 NTSTATUS 1321 Ext2WriteComplete (IN PEXT2_IRP_CONTEXT IrpContext) 1322 { 1323 NTSTATUS Status = STATUS_UNSUCCESSFUL; 1324 PFILE_OBJECT FileObject; 1325 PIRP Irp; 1326 PIO_STACK_LOCATION IrpSp; 1327 1328 _SEH2_TRY { 1329 1330 ASSERT(IrpContext); 1331 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 1332 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 1333 1334 FileObject = IrpContext->FileObject; 1335 1336 Irp = IrpContext->Irp; 1337 IrpSp = IoGetCurrentIrpStackLocation(Irp); 1338 1339 CcMdlWriteComplete(FileObject, &(IrpSp->Parameters.Write.ByteOffset), Irp->MdlAddress); 1340 Irp->MdlAddress = NULL; 1341 Status = STATUS_SUCCESS; 1342 1343 } _SEH2_FINALLY { 1344 1345 if (!IrpContext->ExceptionInProgress) { 1346 Ext2CompleteIrpContext(IrpContext, Status); 1347 } 1348 } _SEH2_END; 1349 1350 return Status; 1351 } 1352 1353 1354 NTSTATUS 1355 Ext2Write (IN PEXT2_IRP_CONTEXT IrpContext) 1356 { 1357 NTSTATUS Status; 1358 PEXT2_FCBVCB FcbOrVcb; 1359 PDEVICE_OBJECT DeviceObject; 1360 PFILE_OBJECT FileObject; 1361 PEXT2_VCB Vcb; 1362 BOOLEAN bCompleteRequest = TRUE; 1363 1364 ASSERT(IrpContext); 1365 1366 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 1367 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 1368 1369 _SEH2_TRY { 1370 1371 if (IsFlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE)) { 1372 1373 Status = Ext2WriteComplete(IrpContext); 1374 bCompleteRequest = FALSE; 1375 1376 } else { 1377 1378 DeviceObject = IrpContext->DeviceObject; 1379 if (IsExt2FsDevice(DeviceObject)) { 1380 Status = STATUS_INVALID_DEVICE_REQUEST; 1381 _SEH2_LEAVE; 1382 } 1383 FileObject = IrpContext->FileObject; 1384 1385 Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; 1386 1387 if (Vcb->Identifier.Type != EXT2VCB || 1388 Vcb->Identifier.Size != sizeof(EXT2_VCB) ) { 1389 Status = STATUS_INVALID_PARAMETER; 1390 _SEH2_LEAVE; 1391 } 1392 1393 if (IsVcbReadOnly(Vcb)) { 1394 Status = STATUS_MEDIA_WRITE_PROTECTED; 1395 _SEH2_LEAVE; 1396 } 1397 1398 if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) && 1399 Vcb->LockFile != FileObject ) { 1400 Status = STATUS_ACCESS_DENIED; 1401 _SEH2_LEAVE; 1402 } 1403 1404 FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext; 1405 1406 if (FcbOrVcb->Identifier.Type == EXT2VCB) { 1407 1408 Status = Ext2WriteVolume(IrpContext); 1409 if (!NT_SUCCESS(Status)) { 1410 DbgBreak(); 1411 } 1412 bCompleteRequest = FALSE; 1413 1414 } else if (FcbOrVcb->Identifier.Type == EXT2FCB) { 1415 1416 if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) { 1417 Status = STATUS_TOO_LATE; 1418 _SEH2_LEAVE; 1419 } 1420 1421 Status = Ext2WriteFile(IrpContext); 1422 if (!NT_SUCCESS(Status)) { 1423 DbgBreak(); 1424 } 1425 1426 bCompleteRequest = FALSE; 1427 } else { 1428 Status = STATUS_INVALID_PARAMETER; 1429 } 1430 } 1431 1432 } _SEH2_FINALLY { 1433 1434 if (bCompleteRequest) { 1435 Ext2CompleteIrpContext(IrpContext, Status); 1436 } 1437 } _SEH2_END; 1438 1439 return Status; 1440 } 1441