NTSTATUS Ext2FlushFiles( IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN BOOLEAN bShutDown ) { IO_STATUS_BLOCK IoStatus; PEXT2_FCB Fcb; PLIST_ENTRY ListEntry; if (IsVcbReadOnly(Vcb)) { return STATUS_SUCCESS; } IoStatus.Status = STATUS_SUCCESS; DEBUG(DL_INF, ( "Flushing Files ...\n")); // Flush all Fcbs in Vcb list queue. for (ListEntry = Vcb->FcbList.Flink; ListEntry != &Vcb->FcbList; ListEntry = ListEntry->Flink ) { Fcb = CONTAINING_RECORD(ListEntry, EXT2_FCB, Next); ExAcquireResourceExclusiveLite( &Fcb->MainResource, TRUE); IoStatus.Status = Ext2FlushFile(IrpContext, Fcb, NULL); ExReleaseResourceLite(&Fcb->MainResource); } return IoStatus.Status; }
FAST_IO_POSSIBLE Ext2IsFastIoPossible( IN PEXT2_FCB Fcb ) { FAST_IO_POSSIBLE IsPossible = FastIoIsNotPossible; if (!Fcb || !FsRtlOplockIsFastIoPossible(&Fcb->Oplock)) return IsPossible; IsPossible = FastIoIsQuestionable; if (!FsRtlAreThereCurrentFileLocks(&Fcb->FileLockAnchor)) { if (!IsVcbReadOnly(Fcb->Vcb) && !FlagOn(Fcb->Vcb->Flags, VCB_VOLUME_LOCKED)) { IsPossible = FastIoIsPossible; } } return IsPossible; }
INT Ext2CheckJournal( PEXT2_VCB Vcb, PULONG jNo ) { struct ext3_super_block* esb = NULL; /* check ext3 super block */ esb = (struct ext3_super_block *)Vcb->SuperBlock; if (IsFlagOn(esb->s_feature_incompat, EXT3_FEATURE_INCOMPAT_RECOVER)) { SetLongFlag(Vcb->Flags, VCB_JOURNAL_RECOVER); } /* must stop here if volume is read-only */ if (IsVcbReadOnly(Vcb)) { goto errorout; } /* journal is external ? */ if (esb->s_journal_inum == 0) { goto errorout; } /* oops: volume is corrupted */ if (esb->s_journal_dev) { goto errorout; } /* return the journal inode number */ *jNo = esb->s_journal_inum; return TRUE; errorout: return FALSE; }
NTSTATUS Ext2Write (IN PEXT2_IRP_CONTEXT IrpContext) { NTSTATUS Status; PEXT2_FCBVCB FcbOrVcb; PDEVICE_OBJECT DeviceObject; PFILE_OBJECT FileObject; PEXT2_VCB Vcb; BOOLEAN bCompleteRequest = TRUE; ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); __try { if (IsFlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE)) { Status = Ext2WriteComplete(IrpContext); bCompleteRequest = FALSE; } else { DeviceObject = IrpContext->DeviceObject; if (IsExt2FsDevice(DeviceObject)) { Status = STATUS_INVALID_DEVICE_REQUEST; __leave; } FileObject = IrpContext->FileObject; Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; if (Vcb->Identifier.Type != EXT2VCB || Vcb->Identifier.Size != sizeof(EXT2_VCB) ) { Status = STATUS_INVALID_PARAMETER; __leave; } if (IsVcbReadOnly(Vcb)) { Status = STATUS_MEDIA_WRITE_PROTECTED; __leave; } if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) && Vcb->LockFile != FileObject ) { Status = STATUS_ACCESS_DENIED; __leave; } FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext; if (FcbOrVcb->Identifier.Type == EXT2VCB) { Status = Ext2WriteVolume(IrpContext); if (!NT_SUCCESS(Status)) { DbgBreak(); } bCompleteRequest = FALSE; } else if (FcbOrVcb->Identifier.Type == EXT2FCB) { if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) { Status = STATUS_TOO_LATE; __leave; } Status = Ext2WriteFile(IrpContext); if (!NT_SUCCESS(Status)) { DbgBreak(); } bCompleteRequest = FALSE; } else { Status = STATUS_INVALID_PARAMETER; } } } __finally { if (bCompleteRequest) { Ext2CompleteIrpContext(IrpContext, Status); } } return Status; }
BOOLEAN Ext2FastIoCheckIfPossible ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN ULONG LockKey, IN BOOLEAN CheckForReadOperation, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ) { BOOLEAN bPossible = FastIoIsNotPossible; PEXT2_FCB Fcb; PEXT2_CCB Ccb; LARGE_INTEGER lLength; lLength.QuadPart = Length; __try { FsRtlEnterFileSystem(); __try { if (IsExt2FsDevice(DeviceObject)) { __leave; } Fcb = (PEXT2_FCB) FileObject->FsContext; if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { __leave; } ASSERT((Fcb->Identifier.Type == EXT2FCB) && (Fcb->Identifier.Size == sizeof(EXT2_FCB))); if (IsDirectory(Fcb)) { __leave; } Ccb = (PEXT2_CCB) FileObject->FsContext2; if (Ccb == NULL) { __leave; } if (CheckForReadOperation) { bPossible = FsRtlFastCheckLockForRead( &Fcb->FileLockAnchor, FileOffset, &lLength, LockKey, FileObject, PsGetCurrentProcess()); } else { if (!IsVcbReadOnly(Fcb->Vcb)) { bPossible = FsRtlFastCheckLockForWrite( &Fcb->FileLockAnchor, FileOffset, &lLength, LockKey, FileObject, PsGetCurrentProcess()); } } #if EXT2_DEBUG DEBUG(DL_INF, ("Ext2FastIIOCheckPossible: %s %s %wZ\n", Ext2GetCurrentProcessName(), "FASTIO_CHECK_IF_POSSIBLE", &Fcb->Mcb->FullName )); DEBUG(DL_INF, ( "Ext2FastIIOCheckPossible: Offset: %I64xg Length: %xh Key: %u %s %s\n", FileOffset->QuadPart, Length, LockKey, (CheckForReadOperation ? "CheckForReadOperation:" : "CheckForWriteOperation:"), (bPossible ? "Succeeded" : "Failed"))); #endif } __except (EXCEPTION_EXECUTE_HANDLER) { bPossible = FastIoIsNotPossible; } } __finally { FsRtlExitFileSystem(); } return bPossible; }
BOOLEAN Ext2FastIoWrite ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN ULONG LockKey, OUT PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject) { PEXT2_FCB Fcb = NULL; BOOLEAN Status = FALSE; BOOLEAN Locked = FALSE; Fcb = (PEXT2_FCB) FileObject->FsContext; if (Fcb == NULL) return FALSE; __try { FsRtlEnterFileSystem(); ASSERT((Fcb->Identifier.Type == EXT2FCB) && (Fcb->Identifier.Size == sizeof(EXT2_FCB))); if (IsVcbReadOnly(Fcb->Vcb)) { __leave; } if (!ExAcquireResourceSharedLite(Fcb->Header.Resource, Wait)) { __leave; } Locked = TRUE; if (IsWritingToEof(*FileOffset) || Fcb->Header.ValidDataLength.QuadPart < FileOffset->QuadPart + Length || Fcb->Header.FileSize.QuadPart < FileOffset->QuadPart + Length ) { Status = FALSE; __leave; } if (Locked) { ExReleaseResourceLite(Fcb->Header.Resource); Locked = FALSE; } Status = FsRtlCopyWrite(FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject); if (Status) { if (IoStatus) Length = (ULONG)IoStatus->Information; } } __finally { if (Locked) { ExReleaseResourceLite(Fcb->Header.Resource); } FsRtlExitFileSystem(); } DEBUG(DL_IO, ("Ext2FastIoWrite: %wZ Offset: %I64xh Length: %xh Key: %xh Status=%d\n", &Fcb->Mcb->ShortName, FileOffset->QuadPart, Length, LockKey, Status)); return Status; }
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; _SEH2_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; _SEH2_LEAVE; } Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == EXT2VCB) && (Vcb->Identifier.Size == sizeof(EXT2_VCB))); ASSERT(IsMounted(Vcb)); if (IsVcbReadOnly(Vcb)) { Status = STATUS_SUCCESS; _SEH2_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; _SEH2_LEAVE; } MainResourceAcquired = ExAcquireResourceExclusiveLite(&FcbOrVcb->MainResource, TRUE); 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)) { _SEH2_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))); } _SEH2_FINALLY { if (MainResourceAcquired) { ExReleaseResourceLite(&FcbOrVcb->MainResource); } if (!IrpContext->ExceptionInProgress) { if (Vcb && Irp && IrpSp && !IsVcbReadOnly(Vcb)) { // 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); } } _SEH2_END; return Status; }
NTSTATUS Ext2SetVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_UNSUCCESSFUL; PEXT2_VCB Vcb = NULL; PIRP Irp; PIO_STACK_LOCATION IoStackLocation; FS_INFORMATION_CLASS FsInformationClass; BOOLEAN VcbResourceAcquired = FALSE; __try { ASSERT(IrpContext != NULL); 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 (IsVcbReadOnly(Vcb)) { Status = STATUS_MEDIA_WRITE_PROTECTED; __leave; } if (!ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE)) { Status = STATUS_PENDING; __leave; } VcbResourceAcquired = TRUE; Ext2VerifyVcb(IrpContext, Vcb); Irp = IrpContext->Irp; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); //Notes: SetVolume is not defined in ntddk.h of win2k ddk, // But it's same to QueryVolume .... FsInformationClass = IoStackLocation->Parameters./*SetVolume*/QueryVolume.FsInformationClass; switch (FsInformationClass) { case FileFsLabelInformation: { PFILE_FS_LABEL_INFORMATION VolLabelInfo = NULL; ULONG VolLabelLen; UNICODE_STRING LabelName ; OEM_STRING OemName; VolLabelInfo = (PFILE_FS_LABEL_INFORMATION) Irp->AssociatedIrp.SystemBuffer; VolLabelLen = VolLabelInfo->VolumeLabelLength; if (VolLabelLen > (16 * sizeof(WCHAR))) { Status = STATUS_INVALID_VOLUME_LABEL; __leave; } RtlCopyMemory( Vcb->Vpb->VolumeLabel, VolLabelInfo->VolumeLabel, VolLabelLen ); RtlZeroMemory(Vcb->SuperBlock->s_volume_name, 16); LabelName.Buffer = VolLabelInfo->VolumeLabel; LabelName.MaximumLength = (USHORT)16 * sizeof(WCHAR); LabelName.Length = (USHORT)VolLabelLen; OemName.Buffer = SUPER_BLOCK->s_volume_name; OemName.Length = 0; OemName.MaximumLength = 16; Ext2UnicodeToOEM(Vcb, &OemName, &LabelName); Vcb->Vpb->VolumeLabelLength = (USHORT) VolLabelLen; if (Ext2SaveSuper(IrpContext, Vcb)) { Status = STATUS_SUCCESS; } Irp->IoStatus.Information = 0; } break; default: Status = STATUS_INVALID_INFO_CLASS; } } __finally { if (VcbResourceAcquired) { ExReleaseResourceLite(&Vcb->MainResource); } if (!IrpContext->ExceptionInProgress) { if (Status == STATUS_PENDING) { Ext2QueueRequest(IrpContext); } else { Ext2CompleteIrpContext(IrpContext, Status); } } } return Status; }
NTSTATUS Ext2QueryVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; PEXT2_VCB Vcb = NULL; PIRP Irp = NULL; PIO_STACK_LOCATION IoStackLocation = NULL; PVOID Buffer; ULONG Length; NTSTATUS Status = STATUS_UNSUCCESSFUL; FS_INFORMATION_CLASS FsInformationClass; BOOLEAN VcbResourceAcquired = FALSE; __try { ASSERT(IrpContext != NULL); 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))); if (!IsMounted(Vcb)) { Status = STATUS_VOLUME_DISMOUNTED; __leave; } if (!ExAcquireResourceSharedLite( &Vcb->MainResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { Status = STATUS_PENDING; __leave; } VcbResourceAcquired = TRUE; Irp = IrpContext->Irp; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); FsInformationClass = IoStackLocation->Parameters.QueryVolume.FsInformationClass; Length = IoStackLocation->Parameters.QueryVolume.Length; Buffer = Irp->AssociatedIrp.SystemBuffer; RtlZeroMemory(Buffer, Length); switch (FsInformationClass) { case FileFsVolumeInformation: { PFILE_FS_VOLUME_INFORMATION FsVolInfo; ULONG VolumeLabelLength; ULONG RequiredLength; if (Length < sizeof(FILE_FS_VOLUME_INFORMATION)) { Status = STATUS_BUFFER_OVERFLOW; __leave; } FsVolInfo = (PFILE_FS_VOLUME_INFORMATION) Buffer; FsVolInfo->VolumeCreationTime.QuadPart = 0; FsVolInfo->VolumeSerialNumber = Vcb->Vpb->SerialNumber; VolumeLabelLength = Vcb->Vpb->VolumeLabelLength; FsVolInfo->VolumeLabelLength = VolumeLabelLength; /* We don't support ObjectId */ FsVolInfo->SupportsObjects = FALSE; RequiredLength = sizeof(FILE_FS_VOLUME_INFORMATION) + VolumeLabelLength - sizeof(WCHAR); if (Length < RequiredLength) { Irp->IoStatus.Information = sizeof(FILE_FS_VOLUME_INFORMATION); Status = STATUS_BUFFER_OVERFLOW; __leave; } RtlCopyMemory(FsVolInfo->VolumeLabel, Vcb->Vpb->VolumeLabel, Vcb->Vpb->VolumeLabelLength); Irp->IoStatus.Information = RequiredLength; Status = STATUS_SUCCESS; } break; case FileFsSizeInformation: { PFILE_FS_SIZE_INFORMATION FsSizeInfo; if (Length < sizeof(FILE_FS_SIZE_INFORMATION)) { Status = STATUS_BUFFER_OVERFLOW; __leave; } FsSizeInfo = (PFILE_FS_SIZE_INFORMATION) Buffer; FsSizeInfo->TotalAllocationUnits.QuadPart = ext3_blocks_count(SUPER_BLOCK); FsSizeInfo->AvailableAllocationUnits.QuadPart = ext3_free_blocks_count(SUPER_BLOCK); FsSizeInfo->SectorsPerAllocationUnit = Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector; FsSizeInfo->BytesPerSector = Vcb->DiskGeometry.BytesPerSector; Irp->IoStatus.Information = sizeof(FILE_FS_SIZE_INFORMATION); Status = STATUS_SUCCESS; } break; case FileFsDeviceInformation: { PFILE_FS_DEVICE_INFORMATION FsDevInfo; if (Length < sizeof(FILE_FS_DEVICE_INFORMATION)) { Status = STATUS_BUFFER_OVERFLOW; __leave; } FsDevInfo = (PFILE_FS_DEVICE_INFORMATION) Buffer; FsDevInfo->DeviceType = Vcb->TargetDeviceObject->DeviceType; if (FsDevInfo->DeviceType != FILE_DEVICE_DISK) { DbgBreak(); } FsDevInfo->Characteristics = Vcb->TargetDeviceObject->Characteristics; if (IsVcbReadOnly(Vcb)) { SetFlag( FsDevInfo->Characteristics, FILE_READ_ONLY_DEVICE ); } Irp->IoStatus.Information = sizeof(FILE_FS_DEVICE_INFORMATION); Status = STATUS_SUCCESS; } break; case FileFsAttributeInformation: { PFILE_FS_ATTRIBUTE_INFORMATION FsAttrInfo; ULONG RequiredLength; if (Length < sizeof(FILE_FS_ATTRIBUTE_INFORMATION)) { Status = STATUS_BUFFER_OVERFLOW; __leave; } FsAttrInfo = (PFILE_FS_ATTRIBUTE_INFORMATION) Buffer; FsAttrInfo->FileSystemAttributes = FILE_SUPPORTS_HARD_LINKS | FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES | FILE_SUPPORTS_REPARSE_POINTS; if (IsVcbReadOnly(Vcb)) { FsAttrInfo->FileSystemAttributes |= FILE_READ_ONLY_VOLUME; } FsAttrInfo->MaximumComponentNameLength = EXT2_NAME_LEN; FsAttrInfo->FileSystemNameLength = 8; RequiredLength = sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8 - sizeof(WCHAR); if (Length < RequiredLength) { Irp->IoStatus.Information = sizeof(FILE_FS_ATTRIBUTE_INFORMATION); Status = STATUS_BUFFER_OVERFLOW; __leave; } if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, EXT4_FEATURE_INCOMPAT_EXTENTS)) { RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT4\0", 10); } else if (Vcb->IsExt3fs) { RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT3\0", 10); } else { RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT2\0", 10); } Irp->IoStatus.Information = RequiredLength; Status = STATUS_SUCCESS; } break; #if (_WIN32_WINNT >= 0x0500) case FileFsFullSizeInformation: { PFILE_FS_FULL_SIZE_INFORMATION PFFFSI; if (Length < sizeof(FILE_FS_FULL_SIZE_INFORMATION)) { Status = STATUS_BUFFER_OVERFLOW; __leave; } PFFFSI = (PFILE_FS_FULL_SIZE_INFORMATION) Buffer; /* typedef struct _FILE_FS_FULL_SIZE_INFORMATION { LARGE_INTEGER TotalAllocationUnits; LARGE_INTEGER CallerAvailableAllocationUnits; LARGE_INTEGER ActualAvailableAllocationUnits; ULONG SectorsPerAllocationUnit; ULONG BytesPerSector; } FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION; */ { PFFFSI->TotalAllocationUnits.QuadPart = ext3_blocks_count(SUPER_BLOCK); PFFFSI->CallerAvailableAllocationUnits.QuadPart = ext3_free_blocks_count(SUPER_BLOCK); /* - Vcb->SuperBlock->s_r_blocks_count; */ PFFFSI->ActualAvailableAllocationUnits.QuadPart = ext3_free_blocks_count(SUPER_BLOCK); } PFFFSI->SectorsPerAllocationUnit = Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector; PFFFSI->BytesPerSector = Vcb->DiskGeometry.BytesPerSector; Irp->IoStatus.Information = sizeof(FILE_FS_FULL_SIZE_INFORMATION); Status = STATUS_SUCCESS; } break; #endif // (_WIN32_WINNT >= 0x0500) default: Status = STATUS_INVALID_INFO_CLASS; break; } } __finally { if (VcbResourceAcquired) { ExReleaseResourceLite(&Vcb->MainResource); } if (!IrpContext->ExceptionInProgress) { if (Status == STATUS_PENDING) { Ext2QueueRequest(IrpContext); } else { Ext2CompleteIrpContext(IrpContext, Status); } } } return Status; }