__drv_mustHoldCriticalRegion NTSTATUS FFSDirectoryControl( IN PFFS_IRP_CONTEXT IrpContext) { NTSTATUS Status; PAGED_CODE(); ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); switch (IrpContext->MinorFunction) { case IRP_MN_QUERY_DIRECTORY: Status = FFSQueryDirectory(IrpContext); break; case IRP_MN_NOTIFY_CHANGE_DIRECTORY: Status = FFSNotifyChangeDirectory(IrpContext); break; default: Status = STATUS_INVALID_DEVICE_REQUEST; FFSCompleteIrpContext(IrpContext, Status); } return Status; }
__drv_mustHoldCriticalRegion NTSTATUS FFSSelectBSDPartition( IN PFFS_IRP_CONTEXT IrpContext) { PIRP Irp; NTSTATUS Status; PFFS_BSD_PARTITION BSDPartition; _SEH2_TRY { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); Irp = IrpContext->Irp; BSDPartition = (PFFS_BSD_PARTITION)Irp->AssociatedIrp.SystemBuffer; FFSGlobal->PartitionNumber = BSDPartition->Number; Status = STATUS_SUCCESS; } _SEH2_FINALLY { if (!IrpContext->ExceptionInProgress) { FFSCompleteIrpContext(IrpContext, Status); } } _SEH2_END; return Status; }
NTSTATUS FFSWriteComplete( IN PFFS_IRP_CONTEXT IrpContext) { NTSTATUS Status = STATUS_UNSUCCESSFUL; PFILE_OBJECT FileObject; PIRP Irp; PIO_STACK_LOCATION IrpSp; __try { ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); FileObject = IrpContext->FileObject; Irp = IrpContext->Irp; IrpSp = IoGetCurrentIrpStackLocation(Irp); CcMdlWriteComplete(FileObject, &(IrpSp->Parameters.Write.ByteOffset), Irp->MdlAddress); Irp->MdlAddress = NULL; Status = STATUS_SUCCESS; } __finally { if (!IrpContext->ExceptionInProgress) { FFSCompleteIrpContext(IrpContext, Status); } } return Status; }
__drv_mustHoldCriticalRegion NTSTATUS FFSFileSystemControl( IN PFFS_IRP_CONTEXT IrpContext) { NTSTATUS Status; PAGED_CODE(); ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); switch (IrpContext->MinorFunction) { case IRP_MN_USER_FS_REQUEST: Status = FFSUserFsRequest(IrpContext); break; case IRP_MN_MOUNT_VOLUME: Status = FFSMountVolume(IrpContext); break; case IRP_MN_VERIFY_VOLUME: Status = FFSVerifyVolume(IrpContext); break; default: FFSPrint((DBG_ERROR, "FFSFilsSystemControl: Invalid Device Request.\n")); Status = STATUS_INVALID_DEVICE_REQUEST; FFSCompleteIrpContext(IrpContext, Status); } return Status; }
__drv_mustHoldCriticalRegion NTSTATUS FFSAllowExtendedDasdIo( IN PFFS_IRP_CONTEXT IrpContext) { PIO_STACK_LOCATION IrpSp; PFFS_VCB Vcb; PFFS_CCB Ccb; PAGED_CODE(); IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp); Vcb = (PFFS_VCB)IrpSp->FileObject->FsContext; Ccb = (PFFS_CCB)IrpSp->FileObject->FsContext2; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == FFSVCB) && (Vcb->Identifier.Size == sizeof(FFS_VCB))); ASSERT(IsMounted(Vcb)); if (Ccb) { SetFlag(Ccb->Flags, CCB_ALLOW_EXTENDED_DASD_IO); FFSCompleteIrpContext(IrpContext, STATUS_SUCCESS); return STATUS_SUCCESS; } else { return STATUS_INVALID_PARAMETER; } }
NTSTATUS FFSDispatchRequest( IN PFFS_IRP_CONTEXT IrpContext) { ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); switch (IrpContext->MajorFunction) { case IRP_MJ_CREATE: return FFSCreate(IrpContext); case IRP_MJ_CLOSE: return FFSClose(IrpContext); case IRP_MJ_READ: return FFSRead(IrpContext); case IRP_MJ_WRITE: return FFSWrite(IrpContext); case IRP_MJ_FLUSH_BUFFERS: return FFSFlush(IrpContext); case IRP_MJ_QUERY_INFORMATION: return FFSQueryInformation(IrpContext); case IRP_MJ_SET_INFORMATION: return FFSSetInformation(IrpContext); case IRP_MJ_QUERY_VOLUME_INFORMATION: return FFSQueryVolumeInformation(IrpContext); case IRP_MJ_SET_VOLUME_INFORMATION: return FFSSetVolumeInformation(IrpContext); case IRP_MJ_DIRECTORY_CONTROL: return FFSDirectoryControl(IrpContext); case IRP_MJ_FILE_SYSTEM_CONTROL: return FFSFileSystemControl(IrpContext); case IRP_MJ_DEVICE_CONTROL: return FFSDeviceControl(IrpContext); case IRP_MJ_LOCK_CONTROL: return FFSLockControl(IrpContext); case IRP_MJ_CLEANUP: return FFSCleanup(IrpContext); case IRP_MJ_SHUTDOWN: return FFSShutDown(IrpContext); #if (_WIN32_WINNT >= 0x0500) case IRP_MJ_PNP: return FFSPnp(IrpContext); #endif //(_WIN32_WINNT >= 0x0500) default: FFSPrint((DBG_ERROR, "FFSDispatchRequest: Unexpected major function: %xh\n", IrpContext->MajorFunction)); FFSCompleteIrpContext(IrpContext, STATUS_DRIVER_INTERNAL_ERROR); return STATUS_DRIVER_INTERNAL_ERROR; } }
__drv_mustHoldCriticalRegion NTSTATUS FFSNotifyChangeDirectory( IN PFFS_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; BOOLEAN CompleteRequest; NTSTATUS Status = STATUS_UNSUCCESSFUL; PFFS_VCB Vcb; PFILE_OBJECT FileObject; PFFS_FCB Fcb = 0; PIRP Irp; PIO_STACK_LOCATION IrpSp; ULONG CompletionFilter; BOOLEAN WatchTree; BOOLEAN bFcbAcquired = FALSE; PUNICODE_STRING FullName; PAGED_CODE(); _SEH2_TRY { ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); // // Always set the wait flag in the Irp context for the original request. // SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); DeviceObject = IrpContext->DeviceObject; if (DeviceObject == FFSGlobal->DeviceObject) { CompleteRequest = TRUE; Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; } Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == FFSVCB) && (Vcb->Identifier.Size == sizeof(FFS_VCB))); ASSERT(IsMounted(Vcb)); FileObject = IrpContext->FileObject; Fcb = (PFFS_FCB)FileObject->FsContext; ASSERT(Fcb); if (Fcb->Identifier.Type == FFSVCB) { FFSBreakPoint(); CompleteRequest = TRUE; Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; } ASSERT((Fcb->Identifier.Type == FFSFCB) && (Fcb->Identifier.Size == sizeof(FFS_FCB))); if (!IsDirectory(Fcb)) { FFSBreakPoint(); CompleteRequest = TRUE; Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; } if (ExAcquireResourceExclusiveLite( &Fcb->MainResource, TRUE)) { bFcbAcquired = TRUE; } else { Status = STATUS_PENDING; _SEH2_LEAVE; } Irp = IrpContext->Irp; IrpSp = IoGetCurrentIrpStackLocation(Irp); #if !defined(_GNU_NTIFS_) || defined(__REACTOS__) CompletionFilter = IrpSp->Parameters.NotifyDirectory.CompletionFilter; #else // _GNU_NTIFS_ CompletionFilter = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.NotifyDirectory.CompletionFilter; #endif // _GNU_NTIFS_ WatchTree = IsFlagOn(IrpSp->Flags, SL_WATCH_TREE); if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { Status = STATUS_DELETE_PENDING; _SEH2_LEAVE; } FullName = &Fcb->LongName; if (FullName->Buffer == NULL) { if (!FFSGetFullFileName(Fcb->FFSMcb, FullName)) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; } } FsRtlNotifyFullChangeDirectory(Vcb->NotifySync, &Vcb->NotifyList, FileObject->FsContext2, (PSTRING)FullName, WatchTree, FALSE, CompletionFilter, Irp, NULL, NULL); CompleteRequest = FALSE; Status = STATUS_PENDING; /* Currently the driver is read-only but here is an example on how to use the FsRtl-functions to report a change: ANSI_STRING TestString; USHORT FileNamePartLength; RtlInitAnsiString(&TestString, "\\ntifs.h"); FileNamePartLength = 7; FsRtlNotifyReportChange( Vcb->NotifySync, // PNOTIFY_SYNC NotifySync &Vcb->NotifyList, // PLIST_ENTRY NotifyList &TestString, // PSTRING FullTargetName &FileNamePartLength, // PUSHORT FileNamePartLength FILE_NOTIFY_CHANGE_NAME // ULONG FilterMatch ); or ANSI_STRING TestString; RtlInitAnsiString(&TestString, "\\ntifs.h"); FsRtlNotifyFullReportChange( Vcb->NotifySync, // PNOTIFY_SYNC NotifySync &Vcb->NotifyList, // PLIST_ENTRY NotifyList &TestString, // PSTRING FullTargetName 1, // USHORT TargetNameOffset NULL, // PSTRING StreamName OPTIONAL NULL, // PSTRING NormalizedParentName OPTIONAL FILE_NOTIFY_CHANGE_NAME, // ULONG FilterMatch 0, // ULONG Action NULL // PVOID TargetContext ); */ } _SEH2_FINALLY { if (bFcbAcquired) { ExReleaseResourceForThreadLite( &Fcb->MainResource, ExGetCurrentResourceThread()); } if (!IrpContext->ExceptionInProgress) { if (!CompleteRequest) { IrpContext->Irp = NULL; } FFSCompleteIrpContext(IrpContext, Status); } } _SEH2_END; return Status; }
__drv_mustHoldCriticalRegion NTSTATUS FFSQueryDirectory( IN PFFS_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_UNSUCCESSFUL; PFFS_VCB Vcb = 0; PFILE_OBJECT FileObject; PFFS_FCB Fcb = 0; PFFS_CCB Ccb; PIRP Irp; PIO_STACK_LOCATION IoStackLocation; FILE_INFORMATION_CLASS FileInformationClass; ULONG Length; PUNICODE_STRING FileName; ULONG FileIndex; BOOLEAN RestartScan; BOOLEAN ReturnSingleEntry; BOOLEAN IndexSpecified; PUCHAR Buffer; BOOLEAN FirstQuery; PFFSv1_INODE dinode1 = NULL; PFFSv2_INODE dinode2 = NULL; BOOLEAN FcbResourceAcquired = FALSE; ULONG UsedLength = 0; USHORT InodeFileNameLength; UNICODE_STRING InodeFileName; PFFS_DIR_ENTRY pDir = NULL; ULONG dwBytes; ULONG dwTemp = 0; ULONG dwSize = 0; ULONG dwReturn = 0; BOOLEAN bRun = TRUE; ULONG ByteOffset; PAGED_CODE(); InodeFileName.Buffer = NULL; _SEH2_TRY { ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; // // This request is not allowed on the main device object // if (DeviceObject == FFSGlobal->DeviceObject) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; } Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == FFSVCB) && (Vcb->Identifier.Size == sizeof(FFS_VCB))); ASSERT(IsMounted(Vcb)); FileObject = IrpContext->FileObject; Fcb = (PFFS_FCB)FileObject->FsContext; ASSERT(Fcb); // // This request is not allowed on volumes // if (Fcb->Identifier.Type == FFSVCB) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; } ASSERT((Fcb->Identifier.Type == FFSFCB) && (Fcb->Identifier.Size == sizeof(FFS_FCB))); if (!IsDirectory(Fcb)) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; } Ccb = (PFFS_CCB)FileObject->FsContext2; ASSERT(Ccb); ASSERT((Ccb->Identifier.Type == FFSCCB) && (Ccb->Identifier.Size == sizeof(FFS_CCB))); Irp = IrpContext->Irp; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); #if !defined(_GNU_NTIFS_) || defined(__REACTOS__) FileInformationClass = IoStackLocation->Parameters.QueryDirectory.FileInformationClass; Length = IoStackLocation->Parameters.QueryDirectory.Length; FileName = IoStackLocation->Parameters.QueryDirectory.FileName; FileIndex = IoStackLocation->Parameters.QueryDirectory.FileIndex; #else // _GNU_NTIFS_ FileInformationClass = ((PEXTENDED_IO_STACK_LOCATION) IoStackLocation)->Parameters.QueryDirectory.FileInformationClass; Length = ((PEXTENDED_IO_STACK_LOCATION) IoStackLocation)->Parameters.QueryDirectory.Length; FileName = ((PEXTENDED_IO_STACK_LOCATION) IoStackLocation)->Parameters.QueryDirectory.FileName; FileIndex = ((PEXTENDED_IO_STACK_LOCATION) IoStackLocation)->Parameters.QueryDirectory.FileIndex; #endif // _GNU_NTIFS_ RestartScan = FlagOn(IoStackLocation->Flags, SL_RESTART_SCAN); ReturnSingleEntry = FlagOn(IoStackLocation->Flags, SL_RETURN_SINGLE_ENTRY); IndexSpecified = FlagOn(IoStackLocation->Flags, SL_INDEX_SPECIFIED); /* if (!Irp->MdlAddress && Irp->UserBuffer) { ProbeForWrite(Irp->UserBuffer, Length, 1); } */ Buffer = FFSGetUserBuffer(Irp); if (Buffer == NULL) { FFSBreakPoint(); Status = STATUS_INVALID_USER_BUFFER; _SEH2_LEAVE; } if (!IrpContext->IsSynchronous) { Status = STATUS_PENDING; _SEH2_LEAVE; } if (!ExAcquireResourceSharedLite( &Fcb->MainResource, IrpContext->IsSynchronous)) { Status = STATUS_PENDING; _SEH2_LEAVE; } FcbResourceAcquired = TRUE; if (FileName != NULL) { if (Ccb->DirectorySearchPattern.Buffer != NULL) { FirstQuery = FALSE; } else { FirstQuery = TRUE; Ccb->DirectorySearchPattern.Length = Ccb->DirectorySearchPattern.MaximumLength = FileName->Length; Ccb->DirectorySearchPattern.Buffer = ExAllocatePoolWithTag(PagedPool, FileName->Length, FFS_POOL_TAG); if (Ccb->DirectorySearchPattern.Buffer == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; } Status = RtlUpcaseUnicodeString( &(Ccb->DirectorySearchPattern), FileName, FALSE); if (!NT_SUCCESS(Status)) _SEH2_LEAVE; } } else if (Ccb->DirectorySearchPattern.Buffer != NULL) { FirstQuery = FALSE; FileName = &Ccb->DirectorySearchPattern; } else { FirstQuery = TRUE; Ccb->DirectorySearchPattern.Length = Ccb->DirectorySearchPattern.MaximumLength = 2; Ccb->DirectorySearchPattern.Buffer = ExAllocatePoolWithTag(PagedPool, 2, FFS_POOL_TAG); if (Ccb->DirectorySearchPattern.Buffer == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; } RtlCopyMemory( Ccb->DirectorySearchPattern.Buffer, L"*\0", 2); } if (!IndexSpecified) { if (RestartScan || FirstQuery) { FileIndex = Fcb->FFSMcb->DeOffset = 0; } else { FileIndex = Ccb->CurrentByteOffset; } } if (FS_VERSION == 1) { dinode1 = (PFFSv1_INODE)ExAllocatePoolWithTag( PagedPool, DINODE1_SIZE, FFS_POOL_TAG); if (dinode1 == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; } RtlZeroMemory(Buffer, Length); if (Fcb->dinode1->di_size <= FileIndex) { Status = STATUS_NO_MORE_FILES; _SEH2_LEAVE; } } else { dinode2 = (PFFSv2_INODE)ExAllocatePoolWithTag( PagedPool, DINODE2_SIZE, FFS_POOL_TAG); if (dinode2 == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; } RtlZeroMemory(Buffer, Length); if (Fcb->dinode2->di_size <= FileIndex) { Status = STATUS_NO_MORE_FILES; _SEH2_LEAVE; } } pDir = ExAllocatePoolWithTag(PagedPool, sizeof(FFS_DIR_ENTRY), FFS_POOL_TAG); if (!pDir) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; } if (FS_VERSION == 1) { dwBytes = 0; dwSize = (ULONG)Fcb->dinode1->di_size - FileIndex - (sizeof(FFS_DIR_ENTRY) - FFS_NAME_LEN + 1); ByteOffset = FileIndex; dwTemp = 0; while (bRun && UsedLength < Length && dwBytes < dwSize) { OEM_STRING OemName; RtlZeroMemory(pDir, sizeof(FFS_DIR_ENTRY)); Status = FFSv1ReadInode( NULL, Vcb, Fcb->dinode1, ByteOffset, (PVOID)pDir, sizeof(FFS_DIR_ENTRY), &dwReturn); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } if (!pDir->d_ino) { if (pDir->d_reclen == 0) { FFSBreakPoint(); _SEH2_LEAVE; } goto ProcessNextEntryv1; } OemName.Buffer = pDir->d_name; OemName.Length = (pDir->d_namlen & 0xff); OemName.MaximumLength = OemName.Length; #if 0 /* // // We could not filter the files: "." and ".." // if ((OemName.Length >) 1 && OemName.Buffer[0] == '.') { if ( OemName.Length == 2 && OemName.Buffer[1] == '.') { } else { goto ProcessNextEntry1; } } */ #endif InodeFileNameLength = (USHORT) RtlOemStringToUnicodeSize(&OemName); InodeFileName.Length = 0; InodeFileName.MaximumLength = InodeFileNameLength + 2; if (InodeFileNameLength <= 0) { break; } InodeFileName.Buffer = ExAllocatePoolWithTag( PagedPool, InodeFileNameLength + 2, FFS_POOL_TAG); if (!InodeFileName.Buffer) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; } RtlZeroMemory( InodeFileName.Buffer, InodeFileNameLength + 2); Status = FFSOEMToUnicode(&InodeFileName, &OemName); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } if (FsRtlDoesNameContainWildCards( &(Ccb->DirectorySearchPattern)) ? FsRtlIsNameInExpression( &(Ccb->DirectorySearchPattern), &InodeFileName, TRUE, NULL) : !RtlCompareUnicodeString( &(Ccb->DirectorySearchPattern), &InodeFileName, TRUE)) { dwReturn = FFSProcessDirEntry( Vcb, FileInformationClass, pDir->d_ino, Buffer, UsedLength, Length - UsedLength, (FileIndex + dwBytes), &InodeFileName, ReturnSingleEntry); if (dwReturn <= 0) { bRun = FALSE; } else { dwTemp = UsedLength; UsedLength += dwReturn; } } if (InodeFileName.Buffer != NULL) { ExFreePool(InodeFileName.Buffer); InodeFileName.Buffer = NULL; } ProcessNextEntryv1: if (bRun) { dwBytes +=pDir->d_reclen; Ccb->CurrentByteOffset = FileIndex + dwBytes; } if (UsedLength && ReturnSingleEntry) { Status = STATUS_SUCCESS; _SEH2_LEAVE; } ByteOffset = FileIndex + dwBytes; } } else { dwBytes = 0; dwSize = (ULONG)Fcb->dinode2->di_size - FileIndex - (sizeof(FFS_DIR_ENTRY) - FFS_NAME_LEN + 1); ByteOffset = FileIndex; dwTemp = 0; while (bRun && UsedLength < Length && dwBytes < dwSize) { OEM_STRING OemName; RtlZeroMemory(pDir, sizeof(FFS_DIR_ENTRY)); Status = FFSv2ReadInode( NULL, Vcb, Fcb->dinode2, ByteOffset, (PVOID)pDir, sizeof(FFS_DIR_ENTRY), &dwReturn); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } if (!pDir->d_ino) { if (pDir->d_reclen == 0) { FFSBreakPoint(); _SEH2_LEAVE; } goto ProcessNextEntryv2; } OemName.Buffer = pDir->d_name; OemName.Length = (pDir->d_namlen & 0xff); OemName.MaximumLength = OemName.Length; #if 0 /* // // We could not filter the files: "." and ".." // if ((OemName.Length >) 1 && OemName.Buffer[0] == '.') { if ( OemName.Length == 2 && OemName.Buffer[1] == '.') { } else { goto ProcessNextEntry2; } } */ #endif InodeFileNameLength = (USHORT) RtlOemStringToUnicodeSize(&OemName); InodeFileName.Length = 0; InodeFileName.MaximumLength = InodeFileNameLength + 2; if (InodeFileNameLength <= 0) { break; } InodeFileName.Buffer = ExAllocatePoolWithTag( PagedPool, InodeFileNameLength + 2, FFS_POOL_TAG); if (!InodeFileName.Buffer) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; } RtlZeroMemory( InodeFileName.Buffer, InodeFileNameLength + 2); Status = FFSOEMToUnicode(&InodeFileName, &OemName); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } if (FsRtlDoesNameContainWildCards( &(Ccb->DirectorySearchPattern)) ? FsRtlIsNameInExpression( &(Ccb->DirectorySearchPattern), &InodeFileName, TRUE, NULL) : !RtlCompareUnicodeString( &(Ccb->DirectorySearchPattern), &InodeFileName, TRUE)) { dwReturn = FFSProcessDirEntry( Vcb, FileInformationClass, pDir->d_ino, Buffer, UsedLength, Length - UsedLength, (FileIndex + dwBytes), &InodeFileName, ReturnSingleEntry); if (dwReturn <= 0) { bRun = FALSE; } else { dwTemp = UsedLength; UsedLength += dwReturn; } } if (InodeFileName.Buffer != NULL) { ExFreePool(InodeFileName.Buffer); InodeFileName.Buffer = NULL; } ProcessNextEntryv2: if (bRun) { dwBytes +=pDir->d_reclen; Ccb->CurrentByteOffset = FileIndex + dwBytes; } if (UsedLength && ReturnSingleEntry) { Status = STATUS_SUCCESS; _SEH2_LEAVE; } ByteOffset = FileIndex + dwBytes; } } FileIndex += dwBytes; ((PULONG)((PUCHAR)Buffer + dwTemp)) [0] = 0; if (!UsedLength) { if (FirstQuery) { Status = STATUS_NO_SUCH_FILE; } else { Status = STATUS_NO_MORE_FILES; } } else { Status = STATUS_SUCCESS; } } _SEH2_FINALLY { if (FcbResourceAcquired) { ExReleaseResourceForThreadLite( &Fcb->MainResource, ExGetCurrentResourceThread()); } if (FS_VERSION == 1) { if (dinode1 != NULL) { ExFreePool(dinode1); } } else { if (dinode2 != NULL) { ExFreePool(dinode2); } } if (pDir != NULL) { ExFreePool(pDir); pDir = NULL; } if (InodeFileName.Buffer != NULL) { ExFreePool(InodeFileName.Buffer); } if (!IrpContext->ExceptionInProgress) { if (Status == STATUS_PENDING) { Status = FFSLockUserBuffer( IrpContext->Irp, Length, IoWriteAccess); if (NT_SUCCESS(Status)) { Status = FFSQueueRequest(IrpContext); } else { FFSCompleteIrpContext(IrpContext, Status); } } else { IrpContext->Irp->IoStatus.Information = UsedLength; FFSCompleteIrpContext(IrpContext, Status); } } } _SEH2_END; return Status; }
__drv_mustHoldCriticalRegion NTSTATUS FFSMountVolume( IN PFFS_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT MainDeviceObject; BOOLEAN GlobalDataResourceAcquired = FALSE; PIRP Irp; PIO_STACK_LOCATION IoStackLocation; PDEVICE_OBJECT TargetDeviceObject; NTSTATUS Status = STATUS_UNRECOGNIZED_VOLUME; PDEVICE_OBJECT VolumeDeviceObject = NULL; PFFS_VCB Vcb; PFFS_SUPER_BLOCK FFSSb = NULL; ULONG dwBytes; DISK_GEOMETRY DiskGeometry; PAGED_CODE(); _SEH2_TRY { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); MainDeviceObject = IrpContext->DeviceObject; // // Make sure we can wait. // SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); // // This request is only allowed on the main device object // if (MainDeviceObject != FFSGlobal->DeviceObject) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; } ExAcquireResourceExclusiveLite( &(FFSGlobal->Resource), TRUE); GlobalDataResourceAcquired = TRUE; if (FlagOn(FFSGlobal->Flags, FFS_UNLOAD_PENDING)) { Status = STATUS_UNRECOGNIZED_VOLUME; _SEH2_LEAVE; } Irp = IrpContext->Irp; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); TargetDeviceObject = IoStackLocation->Parameters.MountVolume.DeviceObject; dwBytes = sizeof(DISK_GEOMETRY); Status = FFSDiskIoControl( TargetDeviceObject, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &DiskGeometry, &dwBytes); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } Status = IoCreateDevice( MainDeviceObject->DriverObject, sizeof(FFS_VCB), NULL, FILE_DEVICE_DISK_FILE_SYSTEM, 0, FALSE, &VolumeDeviceObject); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } VolumeDeviceObject->StackSize = (CCHAR)(TargetDeviceObject->StackSize + 1); if (TargetDeviceObject->AlignmentRequirement > VolumeDeviceObject->AlignmentRequirement) { VolumeDeviceObject->AlignmentRequirement = TargetDeviceObject->AlignmentRequirement; } (IoStackLocation->Parameters.MountVolume.Vpb)->DeviceObject = VolumeDeviceObject; Vcb = (PFFS_VCB)VolumeDeviceObject->DeviceExtension; RtlZeroMemory(Vcb, sizeof(FFS_VCB)); Vcb->Identifier.Type = FFSVCB; Vcb->Identifier.Size = sizeof(FFS_VCB); Vcb->TargetDeviceObject = TargetDeviceObject; Vcb->DiskGeometry = DiskGeometry; Status = FFSLoadDiskLabel(TargetDeviceObject, Vcb); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } FFSSb = Vcb->ffs_super_block; Vcb->BlockSize = FFSSb->fs_bsize; Vcb->SectorBits = FFSLog2(SECTOR_SIZE); Status = FFSInitializeVcb(IrpContext, Vcb, FFSSb, TargetDeviceObject, VolumeDeviceObject, IoStackLocation->Parameters.MountVolume.Vpb); if (NT_SUCCESS(Status)) { if (FFSIsMediaWriteProtected(IrpContext, TargetDeviceObject)) { SetFlag(Vcb->Flags, VCB_WRITE_PROTECTED); } else { ClearFlag(Vcb->Flags, VCB_WRITE_PROTECTED); } SetFlag(Vcb->Flags, VCB_MOUNTED); FFSInsertVcb(Vcb); ClearFlag(VolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING); } } _SEH2_FINALLY { if (GlobalDataResourceAcquired) { ExReleaseResourceForThreadLite( &FFSGlobal->Resource, ExGetCurrentResourceThread()); } if (!NT_SUCCESS(Status)) { if (FFSSb) { ExFreePool(FFSSb); } if (VolumeDeviceObject) { IoDeleteDevice(VolumeDeviceObject); } } if (!IrpContext->ExceptionInProgress) { if (NT_SUCCESS(Status)) { ClearFlag(VolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING); } FFSCompleteIrpContext(IrpContext, Status); } } _SEH2_END; return Status; }
__drv_mustHoldCriticalRegion NTSTATUS FFSCleanup( IN PFFS_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_SUCCESS; PFFS_VCB Vcb = 0; BOOLEAN VcbResourceAcquired = FALSE; PFILE_OBJECT FileObject; PFFS_FCB Fcb = 0; BOOLEAN FcbResourceAcquired = FALSE; BOOLEAN FcbPagingIoAcquired = FALSE; PFFS_CCB Ccb; PIRP Irp; PAGED_CODE(); _SEH2_TRY { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; if (DeviceObject == FFSGlobal->DeviceObject) { Status = STATUS_SUCCESS; _SEH2_LEAVE; } Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == FFSVCB) && (Vcb->Identifier.Size == sizeof(FFS_VCB))); if (!IsFlagOn(Vcb->Flags, VCB_INITIALIZED)) { Status = STATUS_SUCCESS; _SEH2_LEAVE; } #ifdef _MSC_VER #pragma prefast( suppress: 28137, "by design" ) #endif if (!ExAcquireResourceExclusiveLite( &Vcb->MainResource, IrpContext->IsSynchronous)) { Status = STATUS_PENDING; _SEH2_LEAVE; } VcbResourceAcquired = TRUE; FileObject = IrpContext->FileObject; Fcb = (PFFS_FCB)FileObject->FsContext; if (!Fcb) { Status = STATUS_SUCCESS; _SEH2_LEAVE; } if (Fcb->Identifier.Type == FFSVCB) { if (IsFlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) && (Vcb->LockFile == FileObject)) { ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED); Vcb->LockFile = NULL; FFSClearVpbFlag(Vcb->Vpb, VPB_LOCKED); } Vcb->OpenHandleCount--; if (!Vcb->OpenHandleCount) { IoRemoveShareAccess(FileObject, &Vcb->ShareAccess); } Status = STATUS_SUCCESS; _SEH2_LEAVE; } ASSERT((Fcb->Identifier.Type == FFSFCB) && (Fcb->Identifier.Size == sizeof(FFS_FCB))); /* if (!IsFlagOn(Vcb->Flags, VCB_READ_ONLY) && !IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)) */ { #ifdef _MSC_VER #pragma prefast( suppress: 28137, "by design" ) #endif if (!ExAcquireResourceExclusiveLite( &Fcb->MainResource, IrpContext->IsSynchronous)) { Status = STATUS_PENDING; _SEH2_LEAVE; } FcbResourceAcquired = TRUE; } Ccb = (PFFS_CCB)FileObject->FsContext2; if (!Ccb) { Status = STATUS_SUCCESS; _SEH2_LEAVE; } if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) { if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) && IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK) && !IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) { Status = FFSFlushFile(Fcb); } _SEH2_LEAVE; } ASSERT((Ccb->Identifier.Type == FFSCCB) && (Ccb->Identifier.Size == sizeof(FFS_CCB))); Irp = IrpContext->Irp; Fcb->OpenHandleCount--; if (!IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED)) { Fcb->NonCachedOpenCount--; } Vcb->OpenFileHandleCount--; if (IsFlagOn(Fcb->Flags, FCB_DELETE_ON_CLOSE)) { SetFlag(Fcb->Flags, FCB_DELETE_PENDING); if (IsDirectory(Fcb)) { FsRtlNotifyFullChangeDirectory( Vcb->NotifySync, &Vcb->NotifyList, Fcb, NULL, FALSE, FALSE, 0, NULL, NULL, NULL); } } if (IsDirectory(Fcb)) { FsRtlNotifyCleanup( Vcb->NotifySync, &Vcb->NotifyList, Ccb); } else { // // Drop any byte range locks this process may have on the file. // FsRtlFastUnlockAll( &Fcb->FileLockAnchor, FileObject, IoGetRequestorProcess(Irp), NULL); // // If there are no byte range locks owned by other processes on the // file the fast I/O read/write functions doesn't have to check for // locks so we set IsFastIoPossible to FastIoIsPossible again. // if (!FsRtlGetNextFileLock(&Fcb->FileLockAnchor, TRUE)) { if (Fcb->Header.IsFastIoPossible != FastIoIsPossible) { FFSPrint(( DBG_INFO, ": %-16.16s %-31s %s\n", FFSGetCurrentProcessName(), "FastIoIsPossible", Fcb->AnsiFileName.Buffer)); Fcb->Header.IsFastIoPossible = FastIoIsPossible; } } } if (IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) && (Fcb->NonCachedOpenCount != 0) && (Fcb->NonCachedOpenCount == Fcb->ReferenceCount) && (Fcb->SectionObject.DataSectionObject != NULL)) { if(!IsFlagOn(Vcb->Flags, VCB_READ_ONLY) && !IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) { CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL); } ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE); ExReleaseResourceLite(&(Fcb->PagingIoResource)); CcPurgeCacheSection(&Fcb->SectionObject, NULL, 0, FALSE); } #if !FFS_READ_ONLY if (Fcb->OpenHandleCount == 0) { if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { BOOLEAN bDeleted = FALSE; // // Have to delete this file... // #ifdef _MSC_VER #pragma prefast( suppress: 28137, "by design" ) #endif if (!ExAcquireResourceExclusiveLite( &Fcb->PagingIoResource, IrpContext->IsSynchronous)) { Status = STATUS_PENDING; _SEH2_LEAVE; } FcbPagingIoAcquired = TRUE; bDeleted = FFSDeleteFile(IrpContext, Vcb, Fcb); if (bDeleted) { if (IsDirectory(Fcb)) { FFSNotifyReportChange(IrpContext, Vcb, Fcb, FILE_NOTIFY_CHANGE_DIR_NAME, FILE_ACTION_REMOVED); } else { FFSNotifyReportChange(IrpContext, Vcb, Fcb, FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_REMOVED); } } if (FcbPagingIoAcquired) { ExReleaseResourceForThreadLite( &Fcb->PagingIoResource, ExGetCurrentResourceThread()); FcbPagingIoAcquired = FALSE; } /* if (bDeleted) { FFSPurgeFile(Fcb, FALSE); } */ } } #endif // !FFS_READ_ONLY if (!IsDirectory(Fcb) && FileObject->PrivateCacheMap) { FFSPrint((DBG_INFO, "FFSCleanup: CcUninitializeCacheMap is called for %s.\n", Fcb->AnsiFileName.Buffer)); CcUninitializeCacheMap( FileObject, (PLARGE_INTEGER)(&(Fcb->Header.FileSize)), NULL); } if (!Fcb->OpenHandleCount) { IoRemoveShareAccess(FileObject, &Fcb->ShareAccess); } FFSPrint((DBG_INFO, "FFSCleanup: OpenCount: %u ReferCount: %u %s\n", Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->AnsiFileName.Buffer)); Status = STATUS_SUCCESS; if (FileObject) { SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE); } } _SEH2_FINALLY { if (FcbPagingIoAcquired) { ExReleaseResourceForThreadLite( &Fcb->PagingIoResource, ExGetCurrentResourceThread()); } if (FcbResourceAcquired) { ExReleaseResourceForThreadLite( &Fcb->MainResource, ExGetCurrentResourceThread()); } if (VcbResourceAcquired) { ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread()); } if (!IrpContext->ExceptionInProgress) { if (Status == STATUS_PENDING) { FFSQueueRequest(IrpContext); } else { IrpContext->Irp->IoStatus.Status = Status; FFSCompleteIrpContext(IrpContext, Status); } } } _SEH2_END; return Status; }
NTSTATUS FFSWriteVolume( IN PFFS_IRP_CONTEXT IrpContext) { NTSTATUS Status = STATUS_UNSUCCESSFUL; PFFS_VCB Vcb = NULL; PFFS_CCB Ccb = NULL; PFFS_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; BOOLEAN PagingIoResourceAcquired = FALSE; BOOLEAN bDeferred = FALSE; PUCHAR Buffer = NULL; __try { ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == FFSVCB) && (Vcb->Identifier.Size == sizeof(FFS_VCB))); FileObject = IrpContext->FileObject; FcbOrVcb = (PFFS_FCBVCB)FileObject->FsContext; ASSERT(FcbOrVcb); if (!(FcbOrVcb->Identifier.Type == FFSVCB && (PVOID)FcbOrVcb == (PVOID)Vcb)) { Status = STATUS_INVALID_DEVICE_REQUEST; __leave; } Ccb = (PFFS_CCB)FileObject->FsContext2; Irp = IrpContext->Irp; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); Length = IoStackLocation->Parameters.Write.Length; ByteOffset = IoStackLocation->Parameters.Write.ByteOffset; PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE); Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE); SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE); FFSPrint((DBG_INFO, "FFSWriteVolume: Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n", ByteOffset.QuadPart, Length, PagingIo, Nocache)); if (Length == 0) { Irp->IoStatus.Information = 0; Status = STATUS_SUCCESS; __leave; } // For the case of "Direct Access Storage Device", we // need flush/purge the cache if (Ccb != NULL) { ExAcquireResourceExclusive(&Vcb->MainResource, TRUE); MainResourceAcquired = TRUE; Status = FFSPurgeVolume(Vcb, TRUE); ExReleaseResource(&Vcb->MainResource); MainResourceAcquired = FALSE; if(!IsFlagOn(Ccb->Flags, CCB_ALLOW_EXTENDED_DASD_IO)) { if (ByteOffset.QuadPart + Length > Vcb->Header.FileSize.QuadPart) { Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart); } } { FFS_BDL BlockArray; if ((ByteOffset.LowPart & (SECTOR_SIZE - 1)) || (Length & (SECTOR_SIZE - 1))) { Status = STATUS_INVALID_PARAMETER; __leave; } Status = FFSLockUserBuffer( IrpContext->Irp, Length, IoReadAccess); if (!NT_SUCCESS(Status)) { __leave; } BlockArray.Irp = NULL; BlockArray.Lba = ByteOffset.QuadPart;; BlockArray.Offset = 0; BlockArray.Length = Length; Status = FFSReadWriteBlocks(IrpContext, Vcb, &BlockArray, Length, 1, FALSE); Irp = IrpContext->Irp; __leave; } } if (Nocache && (ByteOffset.LowPart & (SECTOR_SIZE - 1) || Length & (SECTOR_SIZE - 1))) { Status = STATUS_INVALID_PARAMETER; __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 FALSE if (!Nocache) { BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED); BOOLEAN bWait = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED); if (!CcCanIWrite( FileObject, Length, (bWait && bQueue), bAgain)) { SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED); CcDeferWrite(FileObject, (PCC_POST_DEFERRED_WRITE)FFSDeferWrite, IrpContext, Irp, Length, bAgain); bDeferred = TRUE; FFSBreakPoint(); Status = STATUS_PENDING; __leave; } } #endif if (Nocache && !PagingIo && (Vcb->SectionObject.DataSectionObject != NULL)) { ExAcquireResourceExclusive(&Vcb->MainResource, TRUE); MainResourceAcquired = TRUE; ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE); ExReleaseResource(&Vcb->PagingIoResource); CcFlushCache(&(Vcb->SectionObject), &ByteOffset, Length, &(Irp->IoStatus)); if (!NT_SUCCESS(Irp->IoStatus.Status)) { Status = Irp->IoStatus.Status; __leave; } ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE); ExReleaseResource(&Vcb->PagingIoResource); CcPurgeCacheSection(&(Vcb->SectionObject), (PLARGE_INTEGER)&(ByteOffset), Length, FALSE); ExReleaseResource(&Vcb->MainResource); MainResourceAcquired = FALSE; } if (!PagingIo) { if (!ExAcquireResourceExclusiveLite( &Vcb->MainResource, IrpContext->IsSynchronous)) { Status = STATUS_PENDING; __leave; } MainResourceAcquired = TRUE; } else { /* ULONG ResShCnt, ResExCnt; ResShCnt = ExIsResourceAcquiredSharedLite(&Vcb->PagingIoResource); ResExCnt = ExIsResourceAcquiredExclusiveLite(&Vcb->PagingIoResource); FFSPrint((DBG_USER, "PagingIoRes: %xh:%xh Synchronous=%xh\n", ResShCnt, ResExCnt, IrpContext->IsSynchronous)); */ if (Ccb) { if (!ExAcquireResourceSharedLite( &Vcb->PagingIoResource, IrpContext->IsSynchronous)) { Status = STATUS_PENDING; __leave; } PagingIoResourceAcquired = TRUE; } } if (!Nocache) { if ((ByteOffset.QuadPart + Length) > Vcb->PartitionInformation.PartitionLength.QuadPart ) { Length = (ULONG) ( Vcb->PartitionInformation.PartitionLength.QuadPart - ByteOffset.QuadPart); Length &= ~((ULONG)SECTOR_SIZE - 1); } if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) { CcPrepareMdlWrite( Vcb->StreamObj, &ByteOffset, Length, &Irp->MdlAddress, &Irp->IoStatus); Status = Irp->IoStatus.Status; } else { Buffer = FFSGetUserBuffer(Irp); if (Buffer == NULL) { FFSBreakPoint(); Status = STATUS_INVALID_USER_BUFFER; __leave; } if (!CcCopyWrite(Vcb->StreamObj, (PLARGE_INTEGER)(&ByteOffset), Length, TRUE, Buffer)) { Status = STATUS_PENDING; __leave; } Status = Irp->IoStatus.Status; FFSAddMcbEntry(Vcb, ByteOffset.QuadPart, (LONGLONG)Length); } if (NT_SUCCESS(Status)) { Irp->IoStatus.Information = Length; } } else { PFFS_BDL ffs_bdl = NULL; ULONG Blocks = 0; LONGLONG DirtyStart; LONGLONG DirtyLba; LONGLONG DirtyLength; LONGLONG RemainLength; if ((ByteOffset.QuadPart + Length) > Vcb->PartitionInformation.PartitionLength.QuadPart) { Length = (ULONG)( Vcb->PartitionInformation.PartitionLength.QuadPart - ByteOffset.QuadPart); Length &= ~((ULONG)SECTOR_SIZE - 1); } Status = FFSLockUserBuffer( IrpContext->Irp, Length, IoReadAccess); if (!NT_SUCCESS(Status)) { __leave; } ffs_bdl = ExAllocatePool(PagedPool, (Length / Vcb->BlockSize) * sizeof(FFS_BDL)); if (!ffs_bdl) { Status = STATUS_INSUFFICIENT_RESOURCES; __leave; } DirtyLba = ByteOffset.QuadPart; RemainLength = (LONGLONG)Length; while (RemainLength > 0) { DirtyStart = DirtyLba; if (FFSLookupMcbEntry(Vcb, DirtyStart, &DirtyLba, &DirtyLength, (PLONGLONG)NULL, (PLONGLONG)NULL, (PULONG)NULL)) { if (DirtyLba == -1) { DirtyLba = DirtyStart + DirtyLength; RemainLength = ByteOffset.QuadPart + (LONGLONG)Length - DirtyLba; continue; } ffs_bdl[Blocks].Irp = NULL; ffs_bdl[Blocks].Lba = DirtyLba; ffs_bdl[Blocks].Offset = (ULONG)((LONGLONG)Length + DirtyStart - RemainLength - DirtyLba); if (DirtyLba + DirtyLength > DirtyStart + RemainLength) { ffs_bdl[Blocks].Length = (ULONG)(DirtyStart + RemainLength - DirtyLba); RemainLength = 0; } else { ffs_bdl[Blocks].Length = (ULONG)DirtyLength; RemainLength = (DirtyStart + RemainLength) - (DirtyLba + DirtyLength); } DirtyLba = DirtyStart + DirtyLength; Blocks++; } else { if (Blocks == 0) { if (ffs_bdl) ExFreePool(ffs_bdl); // // Lookup fails at the first time, ie. // no dirty blocks in the run // FFSBreakPoint(); if (RemainLength == (LONGLONG)Length) Status = STATUS_SUCCESS; else Status = STATUS_UNSUCCESSFUL; __leave; } else { break; } } } if (Blocks > 0) { Status = FFSReadWriteBlocks(IrpContext, Vcb, ffs_bdl, Length, Blocks, FALSE); Irp = IrpContext->Irp; if (NT_SUCCESS(Status)) { ULONG i; for (i = 0; i < Blocks; i++) { FFSRemoveMcbEntry(Vcb, ffs_bdl[i].Lba, ffs_bdl[i].Length); } } if (ffs_bdl) ExFreePool(ffs_bdl); if (!Irp) __leave; } else { if (ffs_bdl) ExFreePool(ffs_bdl); Irp->IoStatus.Information = Length; Status = STATUS_SUCCESS; __leave; } } } __finally { if (PagingIoResourceAcquired) { ExReleaseResourceForThreadLite( &Vcb->PagingIoResource, ExGetCurrentResourceThread()); } if (MainResourceAcquired) { ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread()); } if (!IrpContext->ExceptionInProgress) { if (Irp) { if (Status == STATUS_PENDING) { if(!bDeferred) { Status = FFSLockUserBuffer( IrpContext->Irp, Length, IoReadAccess); if (NT_SUCCESS(Status)) { Status = FFSQueueRequest(IrpContext); } else { FFSCompleteIrpContext(IrpContext, Status); } } } else { if (NT_SUCCESS(Status)) { if (SynchronousIo && !PagingIo) { FileObject->CurrentByteOffset.QuadPart = ByteOffset.QuadPart + Irp->IoStatus.Information; } if (!PagingIo) { SetFlag(FileObject->Flags, FO_FILE_MODIFIED); } } FFSCompleteIrpContext(IrpContext, Status); } } else { FFSFreeIrpContext(IrpContext); } } } return Status; }
__drv_mustHoldCriticalRegion NTSTATUS FFSInvalidateVolumes( IN PFFS_IRP_CONTEXT IrpContext) { NTSTATUS Status; PIRP Irp; PIO_STACK_LOCATION IrpSp; HANDLE Handle; PLIST_ENTRY ListEntry; PFILE_OBJECT FileObject; PDEVICE_OBJECT DeviceObject; BOOLEAN GlobalResourceAcquired = FALSE; LUID Privilege = {SE_TCB_PRIVILEGE, 0}; _SEH2_TRY { Irp = IrpContext->Irp; IrpSp = IoGetCurrentIrpStackLocation(Irp); if (!SeSinglePrivilegeCheck(Privilege, Irp->RequestorMode)) { Status = STATUS_PRIVILEGE_NOT_HELD; _SEH2_LEAVE; } if ( #if !defined(_GNU_NTIFS_) || defined(__REACTOS__) IrpSp->Parameters.FileSystemControl.InputBufferLength #else ((PEXTENDED_IO_STACK_LOCATION)(IrpSp))-> Parameters.FileSystemControl.InputBufferLength #endif != sizeof(HANDLE)) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; } Handle = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer; Status = ObReferenceObjectByHandle(Handle, 0, *IoFileObjectType, KernelMode, (void **)&FileObject, NULL); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } else { ObDereferenceObject(FileObject); DeviceObject = FileObject->DeviceObject; } FFSPrint((DBG_INFO, "FFSInvalidateVolumes: FileObject=%xh ...\n", FileObject)); ExAcquireResourceExclusiveLite( &FFSGlobal->Resource, TRUE); GlobalResourceAcquired = TRUE; ListEntry = FFSGlobal->VcbList.Flink; while (ListEntry != &FFSGlobal->VcbList) { PFFS_VCB Vcb; Vcb = CONTAINING_RECORD(ListEntry, FFS_VCB, Next); ListEntry = ListEntry->Flink; FFSPrint((DBG_INFO, "FFSInvalidateVolumes: Vcb=%xh Vcb->Vpb=%xh...\n", Vcb, Vcb->Vpb)); if (Vcb->Vpb && (Vcb->Vpb->RealDevice == DeviceObject)) { ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); FFSPrint((DBG_INFO, "FFSInvalidateVolumes: FFSPurgeVolume...\n")); FFSPurgeVolume(Vcb, FALSE); ClearFlag(Vcb->Flags, VCB_MOUNTED); ExReleaseResourceLite(&Vcb->MainResource); // // Vcb is still attached on the list ...... // if (ListEntry->Blink == &Vcb->Next) { FFSPrint((DBG_INFO, "FFSInvalidateVolumes: FFSCheckDismount...\n")); FFSCheckDismount(IrpContext, Vcb, FALSE); } } } } _SEH2_FINALLY { if (GlobalResourceAcquired) { ExReleaseResourceForThreadLite( &FFSGlobal->Resource, ExGetCurrentResourceThread()); } FFSCompleteIrpContext(IrpContext, Status); } _SEH2_END; return Status; }
__drv_mustHoldCriticalRegion NTSTATUS FFSUnlockVolume( IN PFFS_IRP_CONTEXT IrpContext) { PIO_STACK_LOCATION IrpSp; PDEVICE_OBJECT DeviceObject; NTSTATUS Status; PFFS_VCB Vcb = 0; BOOLEAN VcbResourceAcquired = FALSE; PAGED_CODE(); _SEH2_TRY { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; // // This request is not allowed on the main device object // if (DeviceObject == FFSGlobal->DeviceObject) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; } Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == FFSVCB) && (Vcb->Identifier.Size == sizeof(FFS_VCB))); ASSERT(IsMounted(Vcb)); IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp); ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE); VcbResourceAcquired = TRUE; Status = FFSUnlockVcb(Vcb, IrpSp->FileObject); } _SEH2_FINALLY { if (VcbResourceAcquired) { ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread()); } if (!IrpContext->ExceptionInProgress) { FFSCompleteIrpContext(IrpContext, Status); } } _SEH2_END; return Status; }
__drv_mustHoldCriticalRegion NTSTATUS FFSDismountVolume( IN PFFS_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_UNSUCCESSFUL; PFFS_VCB Vcb = 0; BOOLEAN VcbResourceAcquired = FALSE; PAGED_CODE(); _SEH2_TRY { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; // // This request is not allowed on the main device object // if (DeviceObject == FFSGlobal->DeviceObject) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; } Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == FFSVCB) && (Vcb->Identifier.Size == sizeof(FFS_VCB))); ASSERT(IsMounted(Vcb)); ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE); VcbResourceAcquired = TRUE; if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) { Status = STATUS_VOLUME_DISMOUNTED; _SEH2_LEAVE; } /* if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) { FFSPrint((DBG_ERROR, "FFSDismount: Volume is not locked.\n")); Status = STATUS_ACCESS_DENIED; _SEH2_LEAVE; } */ FFSFlushFiles(Vcb, FALSE); FFSFlushVolume(Vcb, FALSE); FFSPurgeVolume(Vcb, TRUE); ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread()); VcbResourceAcquired = FALSE; FFSCheckDismount(IrpContext, Vcb, TRUE); FFSPrint((DBG_INFO, "FFSDismount: Volume dismount pending.\n")); Status = STATUS_SUCCESS; } _SEH2_FINALLY { if (VcbResourceAcquired) { ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread()); } if (!IrpContext->ExceptionInProgress) { FFSCompleteIrpContext(IrpContext, Status); } } _SEH2_END; return Status; }
__drv_mustHoldCriticalRegion NTSTATUS FFSVerifyVolume( IN PFFS_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_UNSUCCESSFUL; PFFS_SUPER_BLOCK FFSSb = NULL; PFFS_VCB Vcb = 0; BOOLEAN VcbResourceAcquired = FALSE; BOOLEAN GlobalResourceAcquired = FALSE; PIRP Irp; PIO_STACK_LOCATION IoStackLocation; ULONG ChangeCount; ULONG dwReturn; PAGED_CODE(); _SEH2_TRY { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; // // This request is not allowed on the main device object // if (DeviceObject == FFSGlobal->DeviceObject) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; } ExAcquireResourceExclusiveLite( &FFSGlobal->Resource, TRUE); GlobalResourceAcquired = TRUE; Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == FFSVCB) && (Vcb->Identifier.Size == sizeof(FFS_VCB))); ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE); VcbResourceAcquired = TRUE; if (!FlagOn(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME)) { Status = STATUS_SUCCESS; _SEH2_LEAVE; } if (!IsMounted(Vcb)) { Status = STATUS_WRONG_VOLUME; _SEH2_LEAVE; } dwReturn = sizeof(ULONG); Status = FFSDiskIoControl( Vcb->TargetDeviceObject, IOCTL_DISK_CHECK_VERIFY, NULL, 0, &ChangeCount, &dwReturn); if (ChangeCount != Vcb->ChangeCount) { Status = STATUS_WRONG_VOLUME; _SEH2_LEAVE; } Irp = IrpContext->Irp; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); if (((((FFSSb = FFSLoadSuper(Vcb, TRUE, SBLOCK_UFS1)) != NULL) && (FFSSb->fs_magic == FS_UFS1_MAGIC)) || (((FFSSb = FFSLoadSuper(Vcb, TRUE, SBLOCK_UFS2)) != NULL) && (FFSSb->fs_magic == FS_UFS2_MAGIC))) && (memcmp(FFSSb->fs_id, SUPER_BLOCK->fs_id, 8) == 0) && (memcmp(FFSSb->fs_volname, SUPER_BLOCK->fs_volname, 16) == 0)) { ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME); if (FFSIsMediaWriteProtected(IrpContext, Vcb->TargetDeviceObject)) { SetFlag(Vcb->Flags, VCB_WRITE_PROTECTED); } else { ClearFlag(Vcb->Flags, VCB_WRITE_PROTECTED); } FFSPrint((DBG_INFO, "FFSVerifyVolume: Volume verify succeeded.\n")); Status = STATUS_SUCCESS; } else { Status = STATUS_WRONG_VOLUME; FFSPurgeVolume(Vcb, FALSE); SetFlag(Vcb->Flags, VCB_DISMOUNT_PENDING); ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME); FFSPrint((DBG_INFO, "FFSVerifyVolume: Volume verify failed.\n")); } } _SEH2_FINALLY { if (FFSSb) ExFreePool(FFSSb); if (VcbResourceAcquired) { ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread()); } if (GlobalResourceAcquired) { ExReleaseResourceForThreadLite( &FFSGlobal->Resource, ExGetCurrentResourceThread()); } if (!IrpContext->ExceptionInProgress) { FFSCompleteIrpContext(IrpContext, Status); } } _SEH2_END; return Status; }
NTSTATUS FFSWrite( IN PFFS_IRP_CONTEXT IrpContext) { NTSTATUS Status; PFFS_FCBVCB FcbOrVcb; PDEVICE_OBJECT DeviceObject; PFILE_OBJECT FileObject; PFFS_VCB Vcb; BOOLEAN bCompleteRequest = TRUE; ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); __try { if (FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE)) { Status = FFSWriteComplete(IrpContext); bCompleteRequest = FALSE; } else { DeviceObject = IrpContext->DeviceObject; if (DeviceObject == FFSGlobal->DeviceObject) { Status = STATUS_INVALID_DEVICE_REQUEST; __leave; } Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; if (Vcb->Identifier.Type != FFSVCB || Vcb->Identifier.Size != sizeof(FFS_VCB)) { Status = STATUS_INVALID_PARAMETER; __leave; } ASSERT(IsMounted(Vcb)); if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) { Status = STATUS_TOO_LATE; __leave; } if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) { Status = STATUS_MEDIA_WRITE_PROTECTED; __leave; } FileObject = IrpContext->FileObject; FcbOrVcb = (PFFS_FCBVCB)FileObject->FsContext; if (FcbOrVcb->Identifier.Type == FFSVCB) { Status = FFSWriteVolume(IrpContext); if (!NT_SUCCESS(Status)) { FFSBreakPoint(); } bCompleteRequest = FALSE; } else if (FcbOrVcb->Identifier.Type == FFSFCB) { Status = FFSWriteFile(IrpContext); if (!NT_SUCCESS(Status)) { FFSBreakPoint(); } bCompleteRequest = FALSE; } else { Status = STATUS_INVALID_PARAMETER; } } } __finally { if (bCompleteRequest) { FFSCompleteIrpContext(IrpContext, Status); } } return Status; }
__drv_mustHoldCriticalRegion NTSTATUS FFSUserFsRequest( IN PFFS_IRP_CONTEXT IrpContext) { PIRP Irp; PIO_STACK_LOCATION IoStackLocation; ULONG FsControlCode; NTSTATUS Status; PAGED_CODE(); ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); Irp = IrpContext->Irp; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); #if !defined(_GNU_NTIFS_) || defined(__REACTOS__) FsControlCode = IoStackLocation->Parameters.FileSystemControl.FsControlCode; #else FsControlCode = ((PEXTENDED_IO_STACK_LOCATION) IoStackLocation)->Parameters.FileSystemControl.FsControlCode; #endif switch (FsControlCode) { case FSCTL_LOCK_VOLUME: Status = FFSLockVolume(IrpContext); break; case FSCTL_UNLOCK_VOLUME: Status = FFSUnlockVolume(IrpContext); break; case FSCTL_DISMOUNT_VOLUME: Status = FFSDismountVolume(IrpContext); break; case FSCTL_IS_VOLUME_MOUNTED: Status = FFSIsVolumeMounted(IrpContext); break; case FSCTL_INVALIDATE_VOLUMES: Status = FFSInvalidateVolumes(IrpContext); break; #if (_WIN32_WINNT >= 0x0500) case FSCTL_ALLOW_EXTENDED_DASD_IO: Status = FFSAllowExtendedDasdIo(IrpContext); break; #endif //(_WIN32_WINNT >= 0x0500) default: FFSPrint((DBG_ERROR, "FFSUserFsRequest: Invalid User Request: %xh.\n", FsControlCode)); Status = STATUS_INVALID_DEVICE_REQUEST; FFSCompleteIrpContext(IrpContext, Status); } return Status; }
NTSTATUS FFSWriteFile( IN PFFS_IRP_CONTEXT IrpContext) { NTSTATUS Status = STATUS_UNSUCCESSFUL; PFFS_VCB Vcb = NULL; PFFS_FCB Fcb = NULL; PFFS_CCB Ccb = NULL; PFILE_OBJECT FileObject = NULL; PFILE_OBJECT CacheObject; PDEVICE_OBJECT DeviceObject = NULL; PIRP Irp = NULL; PIO_STACK_LOCATION IoStackLocation = NULL; ULONG Length; ULONG ReturnedLength = 0; LARGE_INTEGER ByteOffset; BOOLEAN PagingIo; BOOLEAN Nocache; BOOLEAN SynchronousIo; BOOLEAN MainResourceAcquired = FALSE; BOOLEAN PagingIoResourceAcquired = FALSE; BOOLEAN bNeedExtending = FALSE; BOOLEAN bAppendFile = FALSE; BOOLEAN bDeferred = FALSE; PUCHAR Buffer = NULL; __try { ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == FFSVCB) && (Vcb->Identifier.Size == sizeof(FFS_VCB))); FileObject = IrpContext->FileObject; Fcb = (PFFS_FCB)FileObject->FsContext; ASSERT(Fcb); ASSERT((Fcb->Identifier.Type == FFSFCB) && (Fcb->Identifier.Size == sizeof(FFS_FCB))); Ccb = (PFFS_CCB)FileObject->FsContext2; Irp = IrpContext->Irp; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); Length = IoStackLocation->Parameters.Write.Length; ByteOffset = IoStackLocation->Parameters.Write.ByteOffset; PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE); Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE); SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE); FFSPrint((DBG_INFO, "FFSWriteFile: Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n", ByteOffset.QuadPart, Length, PagingIo, Nocache)); /* if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED)) { Status = STATUS_FILE_DELETED; __leave; } if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { Status = STATUS_DELETE_PENDING; __leave; } */ if (Length == 0) { Irp->IoStatus.Information = 0; Status = STATUS_SUCCESS; __leave; } if (Nocache && (ByteOffset.LowPart & (SECTOR_SIZE - 1) || Length & (SECTOR_SIZE - 1))) { Status = STATUS_INVALID_PARAMETER; __leave; } if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) { ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); Status = STATUS_PENDING; __leave; } #if FALSE if (!Nocache) { BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED); BOOLEAN bWait = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED); if (!CcCanIWrite( FileObject, Length, (bWait && bQueue), bAgain)) { SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED); CcDeferWrite(FileObject, (PCC_POST_DEFERRED_WRITE)FFSDeferWrite, IrpContext, Irp, Length, bAgain); bDeferred = TRUE; FFSBreakPoint(); Status = STATUS_PENDING; __leave; } } #endif if (IsEndOfFile(ByteOffset)) { bAppendFile = TRUE; ByteOffset.QuadPart = Fcb->Header.FileSize.QuadPart; } if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) && !PagingIo) { Status = STATUS_INVALID_DEVICE_REQUEST; __leave; } // // Do flushing for such cases // if (Nocache && !PagingIo && (Fcb->SectionObject.DataSectionObject != NULL)) { ExAcquireResourceExclusive(&Fcb->MainResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)); MainResourceAcquired = TRUE; ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE); ExReleaseResource(&Fcb->PagingIoResource); CcFlushCache(&(Fcb->SectionObject), &ByteOffset, Length, &(Irp->IoStatus)); ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED); if (!NT_SUCCESS(Irp->IoStatus.Status)) { Status = Irp->IoStatus.Status; __leave; } ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE); ExReleaseResource(&Fcb->PagingIoResource); CcPurgeCacheSection(&(Fcb->SectionObject), (PLARGE_INTEGER)&(ByteOffset), Length, FALSE); ExReleaseResource(&Fcb->MainResource); MainResourceAcquired = FALSE; } if (!PagingIo) { if (!ExAcquireResourceExclusiveLite( &Fcb->MainResource, IrpContext->IsSynchronous)) { Status = STATUS_PENDING; __leave; } MainResourceAcquired = TRUE; } else { /* ULONG ResShCnt, ResExCnt; ResShCnt = ExIsResourceAcquiredSharedLite(&Fcb->PagingIoResource); ResExCnt = ExIsResourceAcquiredExclusiveLite(&Fcb->PagingIoResource); FFSPrint((DBG_USER, "FFSWriteFile: Inode=%xh %S PagingIo: %xh:%xh Synchronous=%xh\n", Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer, ResShCnt, ResExCnt, IrpContext->IsSynchronous)); */ if (!ExAcquireResourceSharedLite( &Fcb->PagingIoResource, IrpContext->IsSynchronous)) { Status = STATUS_PENDING; __leave; } PagingIoResourceAcquired = TRUE; } if (!PagingIo) { if (!FsRtlCheckLockForWriteAccess( &Fcb->FileLockAnchor, Irp)) { Status = STATUS_FILE_LOCK_CONFLICT; __leave; } } if (Nocache) { if ((ByteOffset.QuadPart + Length) > Fcb->Header.AllocationSize.QuadPart) { if (ByteOffset.QuadPart >= Fcb->Header.AllocationSize.QuadPart) { Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; __leave; } else { if (Length > (ULONG)(Fcb->Header.AllocationSize.QuadPart - ByteOffset.QuadPart)) { Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart - ByteOffset.QuadPart); } } } } if (!Nocache) { if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) { __leave; } if (FileObject->PrivateCacheMap == NULL) { CcInitializeCacheMap( FileObject, (PCC_FILE_SIZES)(&Fcb->Header.AllocationSize), FALSE, &FFSGlobal->CacheManagerCallbacks, Fcb); CcSetReadAheadGranularity( FileObject, READ_AHEAD_GRANULARITY); CcSetFileSizes( FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); } CacheObject = FileObject; // // Need extending the size of inode ? // if ((bAppendFile) || ((ULONG)(ByteOffset.QuadPart + Length) > (ULONG)(Fcb->Header.FileSize.QuadPart))) { LARGE_INTEGER ExtendSize; LARGE_INTEGER FileSize; bNeedExtending = TRUE; FileSize = Fcb->Header.FileSize; ExtendSize.QuadPart = (LONGLONG)(ByteOffset.QuadPart + Length); if (ExtendSize.QuadPart > Fcb->Header.AllocationSize.QuadPart) { if (!FFSExpandFile(IrpContext, Vcb, Fcb, &ExtendSize)) { Status = STATUS_INSUFFICIENT_RESOURCES; __leave; } } { Fcb->Header.FileSize.QuadPart = ExtendSize.QuadPart; Fcb->dinode1->di_size = (ULONG)ExtendSize.QuadPart; } if (FileObject->PrivateCacheMap) { CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); if (ByteOffset.QuadPart > FileSize.QuadPart) { FFSZeroHoles(IrpContext, Vcb, FileObject, FileSize.QuadPart, ByteOffset.QuadPart - FileSize.QuadPart); } if (Fcb->Header.AllocationSize.QuadPart > ExtendSize.QuadPart) { FFSZeroHoles(IrpContext, Vcb, FileObject, ExtendSize.QuadPart, Fcb->Header.AllocationSize.QuadPart - ExtendSize.QuadPart); } } if (FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, Fcb->dinode1)) { Status = STATUS_SUCCESS; } FFSNotifyReportChange( IrpContext, Vcb, Fcb, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED); } if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) { CcPrepareMdlWrite( CacheObject, (&ByteOffset), Length, &Irp->MdlAddress, &Irp->IoStatus); Status = Irp->IoStatus.Status; } else { Buffer = FFSGetUserBuffer(Irp); if (Buffer == NULL) { FFSBreakPoint(); Status = STATUS_INVALID_USER_BUFFER; __leave; } if (!CcCopyWrite( CacheObject, (PLARGE_INTEGER)&ByteOffset, Length, IrpContext->IsSynchronous, Buffer)) { Status = STATUS_PENDING; __leave; } Status = Irp->IoStatus.Status; } if (NT_SUCCESS(Status)) { Irp->IoStatus.Information = Length; if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) { FFSPrint((DBG_USER, "FFSWriteFile is starting FlushingDpc...\n")); FFSStartFloppyFlushDpc(Vcb, Fcb, FileObject); } } } else { ReturnedLength = Length; Status = FFSLockUserBuffer( IrpContext->Irp, Length, IoReadAccess); if (!NT_SUCCESS(Status)) { __leave; } Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = Length; Status = FFSv1WriteInode( IrpContext, Vcb, Fcb->dinode1, (ULONGLONG)(ByteOffset.QuadPart), NULL, Length, TRUE, &ReturnedLength); Irp = IrpContext->Irp; } } __finally { if (PagingIoResourceAcquired) { ExReleaseResourceForThreadLite( &Fcb->PagingIoResource, ExGetCurrentResourceThread()); } if (MainResourceAcquired) { ExReleaseResourceForThreadLite( &Fcb->MainResource, ExGetCurrentResourceThread()); } if (!IrpContext->ExceptionInProgress) { if (Irp) { if (Status == STATUS_PENDING) { if (!bDeferred) { Status = FFSLockUserBuffer( IrpContext->Irp, Length, IoReadAccess); if (NT_SUCCESS(Status)) { Status = FFSQueueRequest(IrpContext); } else { FFSCompleteIrpContext(IrpContext, Status); } } } else { if (NT_SUCCESS(Status)) { if (SynchronousIo && !PagingIo) { FileObject->CurrentByteOffset.QuadPart = ByteOffset.QuadPart + Irp->IoStatus.Information; } if (!PagingIo) { SetFlag(FileObject->Flags, FO_FILE_MODIFIED); SetFlag(Fcb->Flags, FCB_FILE_MODIFIED); } } FFSCompleteIrpContext(IrpContext, Status); } } else { FFSFreeIrpContext(IrpContext); } } } return Status; }
__drv_mustHoldCriticalRegion NTSTATUS FFSClose( IN PFFS_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_SUCCESS; PFFS_VCB Vcb = 0; BOOLEAN VcbResourceAcquired = FALSE; PFILE_OBJECT FileObject; PFFS_FCB Fcb = 0; BOOLEAN FcbResourceAcquired = FALSE; PFFS_CCB Ccb; BOOLEAN FreeVcb = FALSE; PAGED_CODE(); _SEH2_TRY { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; if (DeviceObject == FFSGlobal->DeviceObject) { Status = STATUS_SUCCESS; _SEH2_LEAVE; } Vcb = (PFFS_VCB) DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == FFSVCB) && (Vcb->Identifier.Size == sizeof(FFS_VCB))); ASSERT(IsMounted(Vcb)); if (!ExAcquireResourceExclusiveLite( &Vcb->MainResource, IrpContext->IsSynchronous)) { FFSPrint((DBG_INFO, "FFSClose: PENDING ... Vcb: %xh/%xh\n", Vcb->OpenFileHandleCount, Vcb->ReferenceCount)); Status = STATUS_PENDING; _SEH2_LEAVE; } VcbResourceAcquired = TRUE; FileObject = IrpContext->FileObject; if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) { Fcb = IrpContext->Fcb; Ccb = IrpContext->Ccb; } else { Fcb = (PFFS_FCB)FileObject->FsContext; if (!Fcb) { Status = STATUS_SUCCESS; _SEH2_LEAVE; } ASSERT(Fcb != NULL); Ccb = (PFFS_CCB)FileObject->FsContext2; } if (Fcb->Identifier.Type == FFSVCB) { Vcb->ReferenceCount--; if (!Vcb->ReferenceCount && FlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) { FreeVcb = TRUE; } if (Ccb) { FFSFreeCcb(Ccb); if (FileObject) { FileObject->FsContext2 = Ccb = NULL; } } Status = STATUS_SUCCESS; _SEH2_LEAVE; } if (Fcb->Identifier.Type != FFSFCB || Fcb->Identifier.Size != sizeof(FFS_FCB)) { #if DBG FFSPrint((DBG_ERROR, "FFSClose: Strange IRP_MJ_CLOSE by system!\n")); ExAcquireResourceExclusiveLite( &FFSGlobal->CountResource, TRUE); FFSGlobal->IRPCloseCount++; ExReleaseResourceForThreadLite( &FFSGlobal->CountResource, ExGetCurrentResourceThread()); #endif _SEH2_LEAVE; } ASSERT((Fcb->Identifier.Type == FFSFCB) && (Fcb->Identifier.Size == sizeof(FFS_FCB))); /* if ((!IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) && (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE))) */ { if (!ExAcquireResourceExclusiveLite( &Fcb->MainResource, IrpContext->IsSynchronous)) { Status = STATUS_PENDING; _SEH2_LEAVE; } FcbResourceAcquired = TRUE; } if (!Ccb) { Status = STATUS_SUCCESS; _SEH2_LEAVE; } ASSERT((Ccb->Identifier.Type == FFSCCB) && (Ccb->Identifier.Size == sizeof(FFS_CCB))); Fcb->ReferenceCount--; Vcb->ReferenceCount--; if (!Vcb->ReferenceCount && IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) { FreeVcb = TRUE; } FFSPrint((DBG_INFO, "FFSClose: OpenHandleCount: %u ReferenceCount: %u %s\n", Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->AnsiFileName.Buffer)); if (Ccb) { FFSFreeCcb(Ccb); if (FileObject) { FileObject->FsContext2 = Ccb = NULL; } } if (!Fcb->ReferenceCount) { // // Remove Fcb from Vcb->FcbList ... // RemoveEntryList(&Fcb->Next); FFSFreeFcb(Fcb); FcbResourceAcquired = FALSE; } Status = STATUS_SUCCESS; } _SEH2_FINALLY { if (FcbResourceAcquired) { ExReleaseResourceForThreadLite( &Fcb->MainResource, ExGetCurrentResourceThread()); } if (VcbResourceAcquired) { ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread()); } if (!IrpContext->ExceptionInProgress) { if (Status == STATUS_PENDING) { FFSQueueCloseRequest(IrpContext); #if 0 /* Status = STATUS_SUCCESS; if (IrpContext->Irp != NULL) { IrpContext->Irp->IoStatus.Status = Status; FFSCompleteRequest( IrpContext->Irp, (BOOLEAN)!IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED), (CCHAR) (NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT)); IrpContext->Irp = NULL; } */ #endif } else { FFSCompleteIrpContext(IrpContext, Status); if (FreeVcb) { ExAcquireResourceExclusiveLite( &FFSGlobal->Resource, TRUE); FFSClearVpbFlag(Vcb->Vpb, VPB_MOUNTED); FFSRemoveVcb(Vcb); ExReleaseResourceForThreadLite( &FFSGlobal->Resource, ExGetCurrentResourceThread()); FFSFreeVcb(Vcb); } } } } _SEH2_END; return Status; }