29#define OVERFLOW_READ_THRESHHOLD 0xE00
44 if (FirstCluster == 1)
46 (*CurrentCluster) += DeviceExt->FatInfo.SectorsPerCluster;
54 return GetNextCluster(DeviceExt, (*CurrentCluster), CurrentCluster);
74 if (FirstCluster == 0)
76 DbgPrint(
"OffsetToCluster is called with FirstCluster = 0!\n");
80 if (FirstCluster == 1)
83 *Cluster = DeviceExt->FatInfo.rootStart +
FileOffset
84 / (DeviceExt->FatInfo.BytesPerCluster) * DeviceExt->FatInfo.SectorsPerCluster;
89 CurrentCluster = FirstCluster;
92 for (
i = 0;
i <
FileOffset / DeviceExt->FatInfo.BytesPerCluster;
i++)
98 *Cluster = CurrentCluster;
102 for (
i = 0;
i <
FileOffset / DeviceExt->FatInfo.BytesPerCluster;
i++)
108 *Cluster = CurrentCluster;
125 ULONG CurrentCluster;
135 ULONG BytesPerSector;
136 ULONG BytesPerCluster;
144 ASSERT(DeviceExt->FatInfo.BytesPerCluster);
148 DPRINT(
"VfatReadFileData(DeviceExt %p, FileObject %p, "
149 "Length %u, ReadOffset 0x%I64x)\n", DeviceExt,
155 BytesPerSector = DeviceExt->FatInfo.BytesPerSector;
156 BytesPerCluster = DeviceExt->FatInfo.BytesPerCluster;
165 ReadOffset.QuadPart += DeviceExt->FatInfo.FATStart * BytesPerSector;
198 if (FirstCluster == 1)
201 if (
ReadOffset.u.LowPart +
Length > DeviceExt->FatInfo.rootDirectorySectors * BytesPerSector)
203 Length = DeviceExt->FatInfo.rootDirectorySectors * BytesPerSector -
ReadOffset.u.LowPart;
205 ReadOffset.u.LowPart += DeviceExt->FatInfo.rootStart * BytesPerSector;
217 LastCluster =
Fcb->LastCluster;
218 LastOffset =
Fcb->LastOffset;
222 if (LastCluster > 0 &&
ReadOffset.u.LowPart >= LastOffset)
227 &CurrentCluster,
FALSE);
228#ifdef DEBUG_VERIFY_OFFSET_CACHING
231 ULONG CorrectCluster;
234 &CorrectCluster,
FALSE);
235 if (CorrectCluster != CurrentCluster)
244 &CurrentCluster,
FALSE);
253 Fcb->LastCluster = CurrentCluster;
260 while (
Length > 0 && CurrentCluster != 0xffffffff)
262 StartCluster = CurrentCluster;
278 if (
Length - BytesDone > BytesPerCluster)
280 BytesDone += BytesPerCluster;
290 DPRINT(
"start %08x, next %08x, count %u\n",
291 StartCluster, CurrentCluster, ClusterCount);
294 Fcb->LastCluster = StartCluster + (ClusterCount - 1);
304 *LengthRead += BytesDone;
340 ULONG CurrentCluster;
346 ULONG BytesPerSector;
347 ULONG BytesPerCluster;
357 ASSERT(DeviceExt->FatInfo.BytesPerCluster);
362 BytesPerCluster = DeviceExt->FatInfo.BytesPerCluster;
363 BytesPerSector = DeviceExt->FatInfo.BytesPerSector;
365 DPRINT(
"VfatWriteFileData(DeviceExt %p, FileObject %p, "
366 "Length %u, WriteOffset 0x%I64x), '%wZ'\n", DeviceExt,
388 WriteOffset.u.LowPart += DeviceExt->FatInfo.FATStart * BytesPerSector;
419 if (FirstCluster == 1)
421 ASSERT(
WriteOffset.u.LowPart + Length <= DeviceExt->FatInfo.rootDirectorySectors * BytesPerSector);
423 WriteOffset.u.LowPart += DeviceExt->FatInfo.rootStart * BytesPerSector;
430 LastCluster =
Fcb->LastCluster;
431 LastOffset =
Fcb->LastOffset;
437 if (LastCluster > 0 &&
WriteOffset.u.LowPart >= LastOffset)
442 &CurrentCluster,
FALSE);
443#ifdef DEBUG_VERIFY_OFFSET_CACHING
446 ULONG CorrectCluster;
449 &CorrectCluster,
FALSE);
450 if (CorrectCluster != CurrentCluster)
459 &CurrentCluster,
FALSE);
468 Fcb->LastCluster = CurrentCluster;
475 while (
Length > 0 && CurrentCluster != 0xffffffff)
477 StartCluster = CurrentCluster;
493 if (
Length - BytesDone > BytesPerCluster)
495 BytesDone += BytesPerCluster;
505 DPRINT(
"start %08x, next %08x, count %u\n",
506 StartCluster, CurrentCluster, ClusterCount);
509 Fcb->LastCluster = StartCluster + (ClusterCount - 1);
519 BufferOffset += BytesDone;
552 ULONG BytesPerSector;
555 BOOLEAN PagingIo, CanWait, IsVolume, NoCache;
578 if (!PagingIo && !NoCache && !IsVolume)
675 DPRINT1(
"Performing posted read\n");
716 ULONG BytesPerSector;
717 BOOLEAN PagingIo, CanWait, IsVolume, NoCache;
721 DPRINT(
"VfatRead(IrpContext %p)\n", IrpContext);
732 DPRINT(
"VfatRead is called with the main device object.\n");
749 IrpContext->
Flags &= ~IRPCONTEXT_COMPLETE;
790 if (NoCache || PagingIo || IsVolume)
792 if (
ByteOffset.u.LowPart % BytesPerSector != 0 ||
Length % BytesPerSector != 0)
861 IrpContext->
FileObject->CurrentByteOffset.QuadPart =
884 ULONG BytesPerSector;
885 BOOLEAN PagingIo, CanWait, IsVolume, IsFAT, NoCache;
889 DPRINT(
"VfatWrite(IrpContext %p)\n", IrpContext);
900 DPRINT(
"VfatWrite is called with the main device object.\n");
918 IrpContext->
Flags &= ~IRPCONTEXT_COMPLETE;
948 if (IsFAT || IsVolume ||
959 if (PagingIo || NoCache || IsVolume)
961 if (
ByteOffset.u.LowPart % BytesPerSector != 0 ||
Length % BytesPerSector != 0)
1004 DPRINT1(
"Deferring write for Irp %p, context %p!\n", IrpContext->
Irp, IrpContext);
1007 *pIrpContext =
NULL;
1054 if (!CanWait && !IsVolume)
1065 if (!IsFAT && !IsVolume && !PagingIo &&
1088 if (!NoCache && !PagingIo && !IsVolume)
1166 if (!PagingIo && !IsFAT && !IsVolume)
1178 &SystemTime, &
Fcb->entry.FatX.UpdateDate,
1179 &
Fcb->entry.FatX.UpdateTime);
1180 Fcb->entry.FatX.AccessDate =
Fcb->entry.FatX.UpdateDate;
1181 Fcb->entry.FatX.AccessTime =
Fcb->entry.FatX.UpdateTime;
1186 &SystemTime, &
Fcb->entry.Fat.UpdateDate,
1187 &
Fcb->entry.Fat.UpdateTime);
1188 Fcb->entry.Fat.AccessDate =
Fcb->entry.Fat.UpdateDate;
1221 IrpContext->
FileObject->CurrentByteOffset.QuadPart =
#define InterlockedDecrement
_In_ ULONG _In_ BATTERY_QUERY_INFORMATION_LEVEL _In_ LONG _In_ ULONG _Out_ PULONG ReturnedLength
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
_In_ PFCB _In_ LONGLONG FileOffset
_Acquires_exclusive_lock_ Resource _Acquires_shared_lock_ Resource _Inout_ PERESOURCE Resource
ULONG vfatDirEntryGetFirstCluster(PDEVICE_EXTENSION pDeviceExt, PDIR_ENTRY pFatDirEntry)
#define NT_SUCCESS(StatCode)
#define IRPCONTEXT_CANWAIT
BOOLEAN FsdSystemTimeToDosDateTime(PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER SystemTime, PUSHORT pDosDate, PUSHORT pDosTime)
NTSTATUS GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
NTSTATUS GetNextClusterExtend(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
ULONGLONG ClusterToSector(PDEVICE_EXTENSION DeviceExt, ULONG Cluster)
NTSTATUS VfatLockUserBuffer(IN PIRP Irp, IN ULONG Length, IN LOCK_OPERATION Operation)
VOID NTAPI VfatHandleDeferredWrite(IN PVOID IrpContext, IN PVOID Unused)
PVOID VfatGetUserBuffer(IN PIRP Irp, IN BOOLEAN Paging)
VOID NTAPI VfatStackOverflowRead(PVOID Context, IN PKEVENT Event)
VOID VfatPostRead(PVFAT_IRP_CONTEXT IrpContext, PERESOURCE Lock, BOOLEAN PagingIo)
NTSTATUS VfatRead(PVFAT_IRP_CONTEXT IrpContext)
NTSTATUS VfatWrite(PVFAT_IRP_CONTEXT *pIrpContext)
NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, PULONG CurrentCluster, BOOLEAN Extend)
static NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext, ULONG Length, LARGE_INTEGER WriteOffset)
#define OVERFLOW_READ_THRESHHOLD
static NTSTATUS VfatReadFileData(PVFAT_IRP_CONTEXT IrpContext, ULONG Length, LARGE_INTEGER ReadOffset, PULONG LengthRead)
NTSTATUS VfatCommonRead(PVFAT_IRP_CONTEXT IrpContext)
NTSTATUS OffsetToCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, ULONG FileOffset, PULONG Cluster, BOOLEAN Extend)
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
#define KeInitializeEvent(pEvt, foo, foo2)
#define KeSetEvent(pEvt, foo, foo2)
#define KeQuerySystemTime(t)
#define ExAcquireResourceExclusiveLite(res, wait)
#define ExAcquireResourceSharedLite(res, wait)
#define ROUND_UP(n, align)
#define ROUND_DOWN(n, align)
#define FILE_WRITE_TO_END_OF_FILE
#define BooleanFlagOn(F, SF)
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
BOOLEAN NTAPI FsRtlCheckLockForWriteAccess(IN PFILE_LOCK FileLock, IN PIRP Irp)
BOOLEAN NTAPI FsRtlCheckLockForReadAccess(IN PFILE_LOCK FileLock, IN PIRP Irp)
PVFAT_GLOBAL_DATA VfatGlobalData
_Must_inspect_result_ _In_opt_ PFLT_FILTER Filter
#define FsRtlAreThereCurrentFileLocks(FL)
VOID NTAPI CcInitializeCacheMap(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes, IN BOOLEAN PinAccess, IN PCACHE_MANAGER_CALLBACKS Callbacks, IN PVOID LazyWriteContext)
BOOLEAN NTAPI CcZeroData(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER StartOffset, IN PLARGE_INTEGER EndOffset, IN BOOLEAN Wait)
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
#define EXCEPTION_EXECUTE_HANDLER
_In_ ULONG _In_ ULONG _In_ ULONG Length
#define IoSkipCurrentIrpStackLocation(Irp)
BOOLEAN NTAPI CcCopyWrite(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN PVOID Buffer)
BOOLEAN NTAPI CcCanIWrite(IN PFILE_OBJECT FileObject, IN ULONG BytesToWrite, IN BOOLEAN Wait, IN UCHAR Retrying)
BOOLEAN NTAPI CcCopyRead(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, OUT PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatus)
VOID NTAPI CcDeferWrite(IN PFILE_OBJECT FileObject, IN PCC_POST_DEFERRED_WRITE PostRoutine, IN PVOID Context1, IN PVOID Context2, IN ULONG BytesToWrite, IN BOOLEAN Retrying)
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
#define STATUS_FILE_LOCK_CONFLICT
#define _SEH2_GetExceptionCode()
#define _SEH2_EXCEPT(...)
#define STATUS_END_OF_FILE
VOID NTAPI FsRtlPostStackOverflow(IN PVOID Context, IN PKEVENT Event, IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine)
VOID NTAPI FsRtlPostPagingFileStackOverflow(IN PVOID Context, IN PKEVENT Event, IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine)
PDEVICE_OBJECT StorageDevice
CACHE_MANAGER_CALLBACKS CacheMgrCallbacks
PDEVICE_OBJECT DeviceObject
PDEVICE_OBJECT DeviceObject
PDEVICE_EXTENSION DeviceExt
FSRTL_COMMON_FCB_HEADER RFCB
ERESOURCE PagingIoResource
struct _IO_STACK_LOCATION::@3974::@3979 Write
struct _IO_STACK_LOCATION::@3974::@3978 Read
union _IO_STACK_LOCATION::@1575 Parameters
#define STATUS_INVALID_DEVICE_REQUEST
#define STATUS_INVALID_PARAMETER
#define STATUS_UNSUCCESSFUL
#define STATUS_INVALID_USER_BUFFER
struct _LARGE_INTEGER::@2299 u
#define IRPCONTEXT_DEFERRED_WRITE
#define vfatAddToStat(Vcb, Stat, Inc)
#define ROUND_UP_64(n, align)
FORCEINLINE BOOLEAN vfatFCBIsDirectory(PVFATFCB FCB)
FORCEINLINE BOOLEAN vfatVolumeIsFatX(PDEVICE_EXTENSION DeviceExt)
FORCEINLINE NTSTATUS VfatMarkIrpContextForQueue(PVFAT_IRP_CONTEXT IrpContext)
FORCEINLINE VOID vfatReportChange(IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB Fcb, IN ULONG FilterMatch, IN ULONG Action)
NTSTATUS VfatReadDiskPartial(IN PVFAT_IRP_CONTEXT IrpContext, IN PLARGE_INTEGER ReadOffset, IN ULONG ReadLength, ULONG BufferOffset, IN BOOLEAN Wait)
NTSTATUS VfatWriteDiskPartial(IN PVFAT_IRP_CONTEXT IrpContext, IN PLARGE_INTEGER WriteOffset, IN ULONG WriteLength, IN ULONG BufferOffset, IN BOOLEAN Wait)
NTSTATUS VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject, PVFATFCB Fcb, PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER AllocationSize)
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
_Must_inspect_result_ _In_ WDFUSBPIPE _In_ WDFREQUEST _In_opt_ WDFMEMORY _In_opt_ PWDFMEMORY_OFFSET ReadOffset
_Must_inspect_result_ _In_ WDFUSBPIPE _In_ WDFREQUEST _In_opt_ WDFMEMORY _In_opt_ PWDFMEMORY_OFFSET WriteOffset
#define FILE_NOTIFY_CHANGE_SIZE
#define FILE_ACTION_MODIFIED
#define FILE_NOTIFY_CHANGE_ATTRIBUTES
#define IO_DISK_INCREMENT
#define FO_SYNCHRONOUS_IO
#define FILE_NOTIFY_CHANGE_LAST_WRITE