NTSTATUS Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext) { NTSTATUS Status = STATUS_SUCCESS; PIRP Irp = NULL; PIO_STACK_LOCATION IrpSp = NULL; PEXT2_VCB Vcb = NULL; PEXT2_FCB Fcb = NULL; PEXT2_FCBVCB FcbOrVcb = NULL; PEXT2_CCB Ccb = NULL; PFILE_OBJECT FileObject = NULL; PDEVICE_OBJECT DeviceObject = NULL; BOOLEAN MainResourceAcquired = FALSE; __try { ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; // // This request is not allowed on the main device object // if (IsExt2FsDevice(DeviceObject)) { Status = STATUS_INVALID_DEVICE_REQUEST; __leave; } Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == EXT2VCB) && (Vcb->Identifier.Size == sizeof(EXT2_VCB))); ASSERT(IsMounted(Vcb)); if ( IsFlagOn(Vcb->Flags, VCB_READ_ONLY) || IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) { Status = STATUS_SUCCESS; __leave; } Irp = IrpContext->Irp; IrpSp = IoGetCurrentIrpStackLocation(Irp); FileObject = IrpContext->FileObject; FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext; ASSERT(FcbOrVcb != NULL); Ccb = (PEXT2_CCB) FileObject->FsContext2; if (Ccb == NULL) { Status = STATUS_SUCCESS; __leave; } MainResourceAcquired = ExAcquireResourceExclusiveLite(&FcbOrVcb->MainResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)); ASSERT(MainResourceAcquired); DEBUG(DL_INF, ("Ext2Flush-pre: total mcb records=%u\n", FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents))); if (FcbOrVcb->Identifier.Type == EXT2VCB) { Ext2VerifyVcb(IrpContext, Vcb); Status = Ext2FlushFiles(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE); if (NT_SUCCESS(Status)) { __leave; } Status = Ext2FlushVolume(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE); if (NT_SUCCESS(Status) && IsFlagOn(Vcb->Volume->Flags, FO_FILE_MODIFIED)) { ClearFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED); } } else if (FcbOrVcb->Identifier.Type == EXT2FCB) { Fcb = (PEXT2_FCB)(FcbOrVcb); Status = Ext2FlushFile(IrpContext, Fcb, Ccb); if (NT_SUCCESS(Status)) { if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) { Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE; ClearFlag(FileObject->Flags, FO_FILE_MODIFIED); } } } DEBUG(DL_INF, ("Ext2Flush-post: total mcb records=%u\n", FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents))); } __finally { if (MainResourceAcquired) { ExReleaseResourceLite(&FcbOrVcb->MainResource); } if (!IrpContext->ExceptionInProgress) { if (Vcb && Irp && IrpSp && (!IsFlagOn(Vcb->Flags, VCB_READ_ONLY))) { // Call the disk driver to flush the physial media. NTSTATUS DriverStatus; PIO_STACK_LOCATION NextIrpSp; NextIrpSp = IoGetNextIrpStackLocation(Irp); *NextIrpSp = *IrpSp; IoSetCompletionRoutine( Irp, Ext2FlushCompletionRoutine, NULL, TRUE, TRUE, TRUE ); DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, Irp); Status = (DriverStatus == STATUS_INVALID_DEVICE_REQUEST) ? Status : DriverStatus; IrpContext->Irp = Irp = NULL; } Ext2CompleteIrpContext(IrpContext, Status); } } return Status; }
NTSTATUS Ext2ShutDown (IN PEXT2_IRP_CONTEXT IrpContext) { NTSTATUS Status; PIRP Irp; PIO_STACK_LOCATION IrpSp; PEXT2_VCB Vcb; PLIST_ENTRY ListEntry; BOOLEAN GlobalResourceAcquired = FALSE; __try { Status = STATUS_SUCCESS; ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); Irp = IrpContext->Irp; IrpSp = IoGetCurrentIrpStackLocation(Irp); if (!ExAcquireResourceExclusiveLite( &Ext2Global->Resource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { Status = STATUS_PENDING; __leave; } GlobalResourceAcquired = TRUE; for (ListEntry = Ext2Global->VcbList.Flink; ListEntry != &(Ext2Global->VcbList); ListEntry = ListEntry->Flink ) { Vcb = CONTAINING_RECORD(ListEntry, EXT2_VCB, Next); if (ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE )) { if (IsMounted(Vcb)) { /* update mount count */ Vcb->SuperBlock->s_mnt_count++; if (Vcb->SuperBlock->s_mnt_count > Vcb->SuperBlock->s_max_mnt_count ) { Vcb->SuperBlock->s_mnt_count = Vcb->SuperBlock->s_max_mnt_count; } Ext2SaveSuper(IrpContext, Vcb); /* flush dirty cache for all files */ Status = Ext2FlushFiles(IrpContext, Vcb, TRUE); if (!NT_SUCCESS(Status)) { DbgBreak(); } /* flush volume stream's cache to disk */ Status = Ext2FlushVolume(IrpContext, Vcb, TRUE); if (!NT_SUCCESS(Status) && Status != STATUS_MEDIA_WRITE_PROTECTED) { DbgBreak(); } /* send shutdown request to underlying disk */ Ext2DiskShutDown(Vcb); } ExReleaseResourceLite(&Vcb->MainResource); } } /* IoUnregisterFileSystem(Ext2Global->DiskdevObject); IoUnregisterFileSystem(Ext2Global->CdromdevObject); */ } __finally { if (GlobalResourceAcquired) { ExReleaseResourceLite(&Ext2Global->Resource); } if (!IrpContext->ExceptionInProgress) { if (Status == STATUS_PENDING) { Ext2QueueRequest(IrpContext); } else { Ext2CompleteIrpContext(IrpContext, Status); } } } return Status; }
NTSTATUS Ext2ReadVolume (IN PEXT2_IRP_CONTEXT IrpContext) { NTSTATUS Status = STATUS_UNSUCCESSFUL; PEXT2_VCB Vcb = NULL; PEXT2_CCB Ccb = NULL; PEXT2_FCBVCB FcbOrVcb = NULL; PFILE_OBJECT FileObject = NULL; PDEVICE_OBJECT DeviceObject = NULL; PIRP Irp = NULL; PIO_STACK_LOCATION IoStackLocation = NULL; ULONG Length; LARGE_INTEGER ByteOffset; BOOLEAN PagingIo; BOOLEAN Nocache; BOOLEAN SynchronousIo; BOOLEAN MainResourceAcquired = FALSE; PUCHAR Buffer = NULL; EXT2_EXTENT BlockArray; __try { ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == EXT2VCB) && (Vcb->Identifier.Size == sizeof(EXT2_VCB))); FileObject = IrpContext->FileObject; FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext; ASSERT(FcbOrVcb); if (!(FcbOrVcb->Identifier.Type == EXT2VCB && (PVOID)FcbOrVcb == (PVOID)Vcb)) { Status = STATUS_INVALID_DEVICE_REQUEST; __leave; } Ccb = (PEXT2_CCB) FileObject->FsContext2; Irp = IrpContext->Irp; Irp->IoStatus.Information = 0; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); Length = IoStackLocation->Parameters.Read.Length; ByteOffset = IoStackLocation->Parameters.Read.ByteOffset; PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO); Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE) || (Ccb != NULL); SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO); if (PagingIo) { ASSERT(Nocache); } if (Length == 0) { Irp->IoStatus.Information = 0; Status = STATUS_SUCCESS; __leave; } if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) { ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); Status = STATUS_PENDING; __leave; } if (ByteOffset.QuadPart >= Vcb->PartitionInformation.PartitionLength.QuadPart ) { Irp->IoStatus.Information = 0; Status = STATUS_END_OF_FILE; __leave; } if (ByteOffset.QuadPart + Length > Vcb->Header.FileSize.QuadPart) { Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart); } /* * User direct volume access */ if (Ccb != NULL && !PagingIo) { if (!ExAcquireResourceExclusiveLite( &Vcb->MainResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { Status = STATUS_PENDING; __leave; } MainResourceAcquired = TRUE; if (!FlagOn(Ccb->Flags, CCB_VOLUME_DASD_PURGE)) { if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) { Ext2FlushVolume(IrpContext, Vcb, FALSE); } SetFlag(Ccb->Flags, CCB_VOLUME_DASD_PURGE); } ExReleaseResourceLite(&Vcb->MainResource); MainResourceAcquired = FALSE; /* will do Nocache i/o */ } /* * I/O to volume StreamObject */ if (!Nocache) { if (IsFlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) { CcMdlRead( Vcb->Volume, &ByteOffset, Length, &Irp->MdlAddress, &Irp->IoStatus ); Status = Irp->IoStatus.Status; } else { Buffer = Ext2GetUserBuffer(Irp); if (Buffer == NULL) { DbgBreak(); Status = STATUS_INVALID_USER_BUFFER; __leave; } if (!CcCopyRead( Vcb->Volume, &ByteOffset, Length, Ext2CanIWait(), Buffer, &Irp->IoStatus )) { Status = STATUS_PENDING; __leave; } Status = Irp->IoStatus.Status; } } else { Length &= ~((ULONG)SECTOR_SIZE - 1); Status = Ext2LockUserBuffer( IrpContext->Irp, Length, IoWriteAccess ); if (!NT_SUCCESS(Status)) { __leave; } BlockArray.Irp = NULL; BlockArray.Lba = ByteOffset.QuadPart; BlockArray.Offset = 0; BlockArray.Length = Length; BlockArray.Next = NULL; Status = Ext2ReadWriteBlocks(IrpContext, Vcb, &BlockArray, Length ); Irp = IrpContext->Irp; if (!Irp) { __leave; } } } __finally { if (MainResourceAcquired) { ExReleaseResourceLite(&Vcb->MainResource); } if (!IrpContext->ExceptionInProgress) { if (Irp) { if (Status == STATUS_PENDING && !IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED)) { Status = Ext2LockUserBuffer( IrpContext->Irp, Length, IoWriteAccess ); if (NT_SUCCESS(Status)) { Status = Ext2QueueRequest(IrpContext); } else { Ext2CompleteIrpContext(IrpContext, Status); } } else { if (NT_SUCCESS(Status)) { if (!PagingIo) { if (SynchronousIo) { FileObject->CurrentByteOffset.QuadPart = ByteOffset.QuadPart + Irp->IoStatus.Information; } FileObject->Flags |= FO_FILE_FAST_IO_READ; } } Ext2CompleteIrpContext(IrpContext, Status);; } } else { Ext2FreeIrpContext(IrpContext); } } } return Status; }
NTSTATUS Ext2ProcessVolumeProperty( IN PEXT2_VCB Vcb, IN PEXT2_VOLUME_PROPERTY3 Property3, IN ULONG Length ) { struct nls_table * PageTable = NULL; PEXT2_VOLUME_PROPERTY2 Property2 = (PVOID)Property3; PEXT2_VOLUME_PROPERTY Property = (PVOID)Property3; NTSTATUS Status = STATUS_SUCCESS; BOOLEAN VcbResourceAcquired = FALSE; __try { ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); VcbResourceAcquired = TRUE; if (Property->Command == APP_CMD_SET_PROPERTY || Property->Command == APP_CMD_QUERY_PROPERTY) { if (Length < sizeof(EXT2_VOLUME_PROPERTY)) { Status = STATUS_INVALID_PARAMETER; __leave; } } else if (Property->Command == APP_CMD_SET_PROPERTY2 || Property->Command == APP_CMD_QUERY_PROPERTY2) { if (Length < sizeof(EXT2_VOLUME_PROPERTY2)) { Status = STATUS_INVALID_PARAMETER; __leave; } } else if (Property->Command == APP_CMD_SET_PROPERTY3 || Property->Command == APP_CMD_QUERY_PROPERTY3) { if (Length < sizeof(EXT2_VOLUME_PROPERTY3)) { Status = STATUS_INVALID_PARAMETER; __leave; } } switch (Property->Command) { case APP_CMD_SET_PROPERTY3: if (Property3->Flags2 & EXT2_VPROP3_AUTOMOUNT) { if (Property3->AutoMount) SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); else ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); } if (Property3->Flags2 & EXT2_VPROP3_USERIDS) { SetFlag(Vcb->Flags, VCB_USER_IDS); Vcb->uid = Property3->uid; Vcb->gid = Property3->gid; if (Property3->EIDS) { Vcb->euid = Property3->euid; Vcb->egid = Property3->egid; SetFlag(Vcb->Flags, VCB_USER_EIDS); } else { Vcb->euid = Vcb->egid = 0; ClearFlag(Vcb->Flags, VCB_USER_EIDS); } } else { ClearFlag(Vcb->Flags, VCB_USER_IDS); ClearFlag(Vcb->Flags, VCB_USER_EIDS); Vcb->uid = Vcb->gid = 0; Vcb->euid = Vcb->egid = 0; } case APP_CMD_SET_PROPERTY2: RtlZeroMemory(Vcb->sHidingPrefix, HIDINGPAT_LEN); if (Vcb->bHidingPrefix = Property2->bHidingPrefix) { RtlCopyMemory( Vcb->sHidingPrefix, Property2->sHidingPrefix, HIDINGPAT_LEN - 1); } RtlZeroMemory(Vcb->sHidingSuffix, HIDINGPAT_LEN); if (Vcb->bHidingSuffix = Property2->bHidingSuffix) { RtlCopyMemory( Vcb->sHidingSuffix, Property2->sHidingSuffix, HIDINGPAT_LEN - 1); } Vcb->DrvLetter = Property2->DrvLetter; case APP_CMD_SET_PROPERTY: if (Property->bReadonly) { if (IsFlagOn(Vcb->Flags, VCB_INITIALIZED)) { Ext2FlushFiles(NULL, Vcb, FALSE); Ext2FlushVolume(NULL, Vcb, FALSE); } SetLongFlag(Vcb->Flags, VCB_READ_ONLY); } else { if (Property->bExt3Writable) { SetLongFlag(Vcb->Flags, VCB_FORCE_WRITING); } if (!Vcb->IsExt3fs) { ClearLongFlag(Vcb->Flags, VCB_READ_ONLY); } else if (!Property->bExt3Writable) { SetLongFlag(Vcb->Flags, VCB_READ_ONLY); } else if (IsFlagOn(Vcb->Flags, VCB_JOURNAL_RECOVER)) { ClearLongFlag(Vcb->Flags, VCB_READ_ONLY); Ext2RecoverJournal(NULL, Vcb); if (IsFlagOn(Vcb->Flags, VCB_JOURNAL_RECOVER)) { SetLongFlag(Vcb->Flags, VCB_READ_ONLY); } else { ClearLongFlag(Vcb->Flags, VCB_READ_ONLY); } } else { ClearLongFlag(Vcb->Flags, VCB_READ_ONLY); } } PageTable = load_nls(Property->Codepage); memcpy(Vcb->Codepage.AnsiName, Property->Codepage, CODEPAGE_MAXLEN); Vcb->Codepage.PageTable = PageTable; if (Vcb->Codepage.PageTable) { Ext2InitializeLabel(Vcb, Vcb->SuperBlock); } break; case APP_CMD_QUERY_PROPERTY3: if (IsFlagOn(Ext2Global->Flags, EXT2_AUTO_MOUNT)) { SetFlag(Property3->Flags2, EXT2_VPROP3_AUTOMOUNT); Property3->AutoMount = TRUE; } else { ClearFlag(Property3->Flags2, EXT2_VPROP3_AUTOMOUNT); Property3->AutoMount = FALSE; } if (IsFlagOn(Vcb->Flags, VCB_USER_IDS)) { SetFlag(Property3->Flags2, EXT2_VPROP3_USERIDS); Property3->uid = Vcb->uid; Property3->gid = Vcb->gid; if (IsFlagOn(Vcb->Flags, VCB_USER_EIDS)) { Property3->EIDS = TRUE; Property3->euid = Vcb->euid; Property3->egid = Vcb->egid; } else { Property3->EIDS = FALSE; } } else { ClearFlag(Property3->Flags2, EXT2_VPROP3_USERIDS); } case APP_CMD_QUERY_PROPERTY2: RtlCopyMemory(Property2->UUID, Vcb->SuperBlock->s_uuid, 16); Property2->DrvLetter = Vcb->DrvLetter; if (Property2->bHidingPrefix = Vcb->bHidingPrefix) { RtlCopyMemory( Property2->sHidingPrefix, Vcb->sHidingPrefix, HIDINGPAT_LEN); } else { RtlZeroMemory( Property2->sHidingPrefix, HIDINGPAT_LEN); } if (Property2->bHidingSuffix = Vcb->bHidingSuffix) { RtlCopyMemory( Property2->sHidingSuffix, Vcb->sHidingSuffix, HIDINGPAT_LEN); } else { RtlZeroMemory( Property2->sHidingSuffix, HIDINGPAT_LEN); } case APP_CMD_QUERY_PROPERTY: Property->bExt2 = TRUE; Property->bExt3 = Vcb->IsExt3fs; Property->bReadonly = IsFlagOn(Vcb->Flags, VCB_READ_ONLY); if (!Property->bReadonly && Vcb->IsExt3fs) { Property->bExt3Writable = TRUE; } else { Property->bExt3Writable = FALSE; } RtlZeroMemory(Property->Codepage, CODEPAGE_MAXLEN); if (Vcb->Codepage.PageTable) { strncpy(Property->Codepage, Vcb->Codepage.PageTable->charset, CODEPAGE_MAXLEN); } else { strncpy(Property->Codepage, "default", CODEPAGE_MAXLEN); } break; default: Status = STATUS_INVALID_PARAMETER; break; } } __finally { if (VcbResourceAcquired) { ExReleaseResourceLite(&Vcb->MainResource); } } return Status; }