ReactOS  0.4.15-dev-2738-gbe65a85
rw.c File Reference
#include "vfat.h"
#include <debug.h>
Include dependency graph for rw.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define OVERFLOW_READ_THRESHHOLD   0xE00
 

Functions

NTSTATUS NextCluster (PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, PULONG CurrentCluster, BOOLEAN Extend)
 
NTSTATUS OffsetToCluster (PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, ULONG FileOffset, PULONG Cluster, BOOLEAN Extend)
 
static NTSTATUS VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext, ULONG Length, LARGE_INTEGER ReadOffset, PULONG LengthRead)
 
static NTSTATUS VfatWriteFileData (PVFAT_IRP_CONTEXT IrpContext, ULONG Length, LARGE_INTEGER WriteOffset)
 
NTSTATUS VfatCommonRead (PVFAT_IRP_CONTEXT IrpContext)
 
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)
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 15 of file rw.c.

◆ OVERFLOW_READ_THRESHHOLD

#define OVERFLOW_READ_THRESHHOLD   0xE00

Definition at line 31 of file rw.c.

Function Documentation

◆ NextCluster()

NTSTATUS NextCluster ( PDEVICE_EXTENSION  DeviceExt,
ULONG  FirstCluster,
PULONG  CurrentCluster,
BOOLEAN  Extend 
)

Definition at line 40 of file rw.c.

45 {
46  if (FirstCluster == 1)
47  {
48  (*CurrentCluster) += DeviceExt->FatInfo.SectorsPerCluster;
49  return STATUS_SUCCESS;
50  }
51  else
52  {
53  if (Extend)
54  return GetNextClusterExtend(DeviceExt, (*CurrentCluster), CurrentCluster);
55  else
56  return GetNextCluster(DeviceExt, (*CurrentCluster), CurrentCluster);
57  }
58 }
VOID NTAPI Extend(VOID)
Definition: extend.c:14
NTSTATUS GetNextClusterExtend(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:775
NTSTATUS GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:746
#define STATUS_SUCCESS
Definition: shellext.h:65

Referenced by FAT12GetNextCluster(), FAT16GetNextCluster(), FAT32GetNextCluster(), FATAddEntry(), FATDelEntry(), FATXDelEntry(), GetNextCluster(), GetNextClusterExtend(), VfatGetRetrievalPointers(), vfatInitFCBFromDirEntry(), vfatMakeRootFCB(), VfatReadFileData(), VfatSetAllocationSizeInformation(), and VfatWriteFileData().

◆ OffsetToCluster()

NTSTATUS OffsetToCluster ( PDEVICE_EXTENSION  DeviceExt,
ULONG  FirstCluster,
ULONG  FileOffset,
PULONG  Cluster,
BOOLEAN  Extend 
)

Definition at line 61 of file rw.c.

67 {
68  ULONG CurrentCluster;
69  ULONG i;
71 /*
72  DPRINT("OffsetToCluster(DeviceExt %x, Fcb %x, FirstCluster %x,"
73  " FileOffset %x, Cluster %x, Extend %d)\n", DeviceExt,
74  Fcb, FirstCluster, FileOffset, Cluster, Extend);
75 */
76  if (FirstCluster == 0)
77  {
78  DbgPrint("OffsetToCluster is called with FirstCluster = 0!\n");
79  ASSERT(FALSE);
80  }
81 
82  if (FirstCluster == 1)
83  {
84  /* root of FAT16 or FAT12 */
85  *Cluster = DeviceExt->FatInfo.rootStart + FileOffset
86  / (DeviceExt->FatInfo.BytesPerCluster) * DeviceExt->FatInfo.SectorsPerCluster;
87  return STATUS_SUCCESS;
88  }
89  else
90  {
91  CurrentCluster = FirstCluster;
92  if (Extend)
93  {
94  for (i = 0; i < FileOffset / DeviceExt->FatInfo.BytesPerCluster; i++)
95  {
96  Status = GetNextClusterExtend (DeviceExt, CurrentCluster, &CurrentCluster);
97  if (!NT_SUCCESS(Status))
98  return Status;
99  }
100  *Cluster = CurrentCluster;
101  }
102  else
103  {
104  for (i = 0; i < FileOffset / DeviceExt->FatInfo.BytesPerCluster; i++)
105  {
106  Status = GetNextCluster (DeviceExt, CurrentCluster, &CurrentCluster);
107  if (!NT_SUCCESS(Status))
108  return Status;
109  }
110  *Cluster = CurrentCluster;
111  }
112  return STATUS_SUCCESS;
113  }
114 }
VOID NTAPI Extend(VOID)
Definition: extend.c:14
#define DbgPrint
Definition: loader.c:25
LONG NTSTATUS
Definition: precomp.h:26
#define FALSE
Definition: types.h:117
Status
Definition: gdiplustypes.h:24
NTSTATUS GetNextClusterExtend(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:775
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
NTSTATUS GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:746
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
Definition: glfuncs.h:248
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:159
unsigned int ULONG
Definition: retypes.h:1
#define STATUS_SUCCESS
Definition: shellext.h:65

Referenced by VfatGetRetrievalPointers(), VfatReadFileData(), VfatSetAllocationSizeInformation(), and VfatWriteFileData().

◆ VfatCommonRead()

NTSTATUS VfatCommonRead ( PVFAT_IRP_CONTEXT  IrpContext)

Definition at line 547 of file rw.c.

549 {
550  PVFATFCB Fcb;
551  PVOID Buffer;
553  ULONG Length = 0;
554  ULONG BytesPerSector;
556  ULONG ReturnedLength = 0;
557  BOOLEAN PagingIo, CanWait, IsVolume, NoCache;
558 
559  PagingIo = BooleanFlagOn(IrpContext->Irp->Flags, IRP_PAGING_IO);
560  CanWait = BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT);
561  NoCache = BooleanFlagOn(IrpContext->Irp->Flags, IRP_NOCACHE);
562  Fcb = IrpContext->FileObject->FsContext;
563  IsVolume = BooleanFlagOn(Fcb->Flags, FCB_IS_VOLUME);
564 
565  ByteOffset = IrpContext->Stack->Parameters.Read.ByteOffset;
566  Length = IrpContext->Stack->Parameters.Read.Length;
567  BytesPerSector = IrpContext->DeviceExt->FatInfo.BytesPerSector;
568 
569  if (!PagingIo &&
571  {
572  if (!FsRtlCheckLockForReadAccess(&Fcb->FileLock, IrpContext->Irp))
573  {
575  }
576  }
577 
578  Buffer = VfatGetUserBuffer(IrpContext->Irp, PagingIo);
579 
580  if (!PagingIo && !NoCache && !IsVolume)
581  {
582  // cached read
584  if (ByteOffset.u.LowPart + Length > Fcb->RFCB.FileSize.u.LowPart)
585  {
586  Length = Fcb->RFCB.FileSize.u.LowPart - ByteOffset.u.LowPart;
587  Status = /*STATUS_END_OF_FILE*/STATUS_SUCCESS;
588  }
589 
590  vfatAddToStat(IrpContext->DeviceExt, Base.UserFileReads, 1);
591  vfatAddToStat(IrpContext->DeviceExt, Base.UserFileReadBytes, Length);
592 
593  _SEH2_TRY
594  {
595  if (IrpContext->FileObject->PrivateCacheMap == NULL)
596  {
597  CcInitializeCacheMap(IrpContext->FileObject,
599  FALSE,
601  Fcb);
602  }
603 
604  if (!CcCopyRead(IrpContext->FileObject,
605  &ByteOffset,
606  Length,
607  CanWait,
608  Buffer,
609  &IrpContext->Irp->IoStatus))
610  {
611  ASSERT(!CanWait);
613  goto ByeBye;
614  }
615  }
617  {
619  goto ByeBye;
620  }
621  _SEH2_END;
622 
623  if (!NT_SUCCESS(IrpContext->Irp->IoStatus.Status))
624  {
625  Status = IrpContext->Irp->IoStatus.Status;
626  }
627  }
628  else
629  {
630  // non cached read
632  if (!NT_SUCCESS(Status))
633  {
634  goto ByeBye;
635  }
636 
637  if (ByteOffset.QuadPart + Length > ROUND_UP_64(Fcb->RFCB.FileSize.QuadPart, BytesPerSector))
638  {
639  Length = (ULONG)(ROUND_UP_64(Fcb->RFCB.FileSize.QuadPart, BytesPerSector) - ByteOffset.QuadPart);
640  }
641 
642  if (!IsVolume)
643  {
644  vfatAddToStat(IrpContext->DeviceExt, Fat.NonCachedReads, 1);
645  vfatAddToStat(IrpContext->DeviceExt, Fat.NonCachedReadBytes, Length);
646  }
647  else
648  {
649  vfatAddToStat(IrpContext->DeviceExt, Base.MetaDataReads, 1);
650  vfatAddToStat(IrpContext->DeviceExt, Base.MetaDataReadBytes, Length);
651  }
652 
654  if (NT_SUCCESS(Status))
655  {
656  IrpContext->Irp->IoStatus.Information = ReturnedLength;
657  }
658  }
659 
660 ByeBye:
661  return Status;
662 }
FILE_LOCK FileLock
Definition: fatstruc.h:1070
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
Definition: vfat.h:447
PDEVICE_EXTENSION DeviceExt
Definition: vfat.h:585
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
LONG NTSTATUS
Definition: precomp.h:26
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2386
#define IRP_NOCACHE
#define vfatAddToStat(Vcb, Stat, Inc)
Definition: vfat.h:671
IO_STATUS_BLOCK IoStatus
PFILE_OBJECT FileObject
Definition: vfat.h:591
_SEH2_TRY
Definition: create.c:4226
#define ROUND_UP_64(n, align)
Definition: vfat.h:34
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
#define IRPCONTEXT_CANWAIT
Definition: vfat.h:575
Definition: bufpool.h:45
PVOID VfatGetUserBuffer(IN PIRP Irp, IN BOOLEAN Paging)
Definition: misc.c:444
#define FsRtlAreThereCurrentFileLocks(FL)
Definition: fsrtlfuncs.h:1584
FSRTL_COMMON_FCB_HEADER RFCB
Definition: ntfs.h:513
static NTSTATUS VfatReadFileData(PVFAT_IRP_CONTEXT IrpContext, ULONG Length, LARGE_INTEGER ReadOffset, PULONG LengthRead)
Definition: rw.c:121
Status
Definition: gdiplustypes.h:24
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
VOID NTAPI CcInitializeCacheMap(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes, IN BOOLEAN PinAccess, IN PCACHE_MANAGER_CALLBACKS Callbacks, IN PVOID LazyWriteContext)
Definition: fssup.c:195
BOOLEAN NTAPI FsRtlCheckLockForReadAccess(IN PFILE_LOCK FileLock, IN PIRP Irp)
Definition: filelock.c:676
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
ULONG Flags
Definition: ntfs.h:532
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)
Definition: copysup.c:43
_In_ ULONG _In_ BATTERY_QUERY_INFORMATION_LEVEL _In_ LONG _In_ ULONG _Out_ PULONG ReturnedLength
Definition: batclass.h:187
LARGE_INTEGER AllocationSize
Definition: env_spec_w32.h:755
struct _LARGE_INTEGER::@2276 u
PVFAT_GLOBAL_DATA VfatGlobalData
Definition: iface.c:36
CACHE_MANAGER_CALLBACKS CacheMgrCallbacks
Definition: vfat.h:422
#define FCB_IS_VOLUME
Definition: vfat.h:437
_SEH2_END
Definition: create.c:4400
#define NULL
Definition: types.h:112
#define IRP_PAGING_IO
#define STATUS_FILE_LOCK_CONFLICT
Definition: ntstatus.h:320
unsigned int ULONG
Definition: retypes.h:1
ULONG Flags
Definition: vfat.h:586
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define STATUS_SUCCESS
Definition: shellext.h:65
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
_In_ PFCB Fcb
Definition: cdprocs.h:159
PIO_STACK_LOCATION Stack
Definition: vfat.h:588
NTSTATUS VfatLockUserBuffer(IN PIRP Irp, IN ULONG Length, IN LOCK_OPERATION Operation)
Definition: misc.c:461
LONGLONG QuadPart
Definition: typedefs.h:114
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:725

Referenced by VfatRead(), and VfatStackOverflowRead().

◆ VfatPostRead()

VOID VfatPostRead ( PVFAT_IRP_CONTEXT  IrpContext,
PERESOURCE  Lock,
BOOLEAN  PagingIo 
)

Definition at line 684 of file rw.c.

688 {
689  KEVENT Event;
690 
692 
694 
695  /* If paging IO, call the non failing but blocking routine */
696  if (PagingIo)
697  {
699  }
700  else
701  {
703  }
704 
705  /* Wait till it's done */
707 }
#define TRUE
Definition: types.h:120
VOID NTAPI FsRtlPostPagingFileStackOverflow(IN PVOID Context, IN PKEVENT Event, IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine)
Definition: stackovf.c:206
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
VOID NTAPI VfatStackOverflowRead(PVOID Context, IN PKEVENT Event)
Definition: rw.c:666
#define FALSE
Definition: types.h:117
_In_ PVOID _In_ ULONG Event
Definition: iotypes.h:467
VOID NTAPI FsRtlPostStackOverflow(IN PVOID Context, IN PKEVENT Event, IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine)
Definition: stackovf.c:232
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define NULL
Definition: types.h:112
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:124

Referenced by VfatRead().

◆ VfatRead()

NTSTATUS VfatRead ( PVFAT_IRP_CONTEXT  IrpContext)

Definition at line 710 of file rw.c.

712 {
714  PVFATFCB Fcb;
715  ULONG Length = 0;
718  ULONG BytesPerSector;
719  BOOLEAN PagingIo, CanWait, IsVolume, NoCache;
720 
721  ASSERT(IrpContext);
722 
723  DPRINT("VfatRead(IrpContext %p)\n", IrpContext);
724 
725  ASSERT(IrpContext->DeviceObject);
726 
727  PagingIo = BooleanFlagOn(IrpContext->Irp->Flags, IRP_PAGING_IO);
728  CanWait = BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT);
729  NoCache = BooleanFlagOn(IrpContext->Irp->Flags, IRP_NOCACHE);
730 
731  // This request is not allowed on the main device object
732  if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
733  {
734  DPRINT("VfatRead is called with the main device object.\n");
736  goto ByeBye;
737  }
738 
739  ASSERT(IrpContext->DeviceExt);
740  ASSERT(IrpContext->FileObject);
741  Fcb = IrpContext->FileObject->FsContext;
742  ASSERT(Fcb);
743 
744  IsVolume = BooleanFlagOn(Fcb->Flags, FCB_IS_VOLUME);
745 
747  {
748  PFATINFO FatInfo = &IrpContext->DeviceExt->FatInfo;
749  IrpContext->Stack->Parameters.Read.ByteOffset.QuadPart += FatInfo->dataStart * FatInfo->BytesPerSector;
750  IoSkipCurrentIrpStackLocation(IrpContext->Irp);
751  IrpContext->Flags &= ~IRPCONTEXT_COMPLETE;
752  DPRINT("Read from page file, disk offset %I64x\n", IrpContext->Stack->Parameters.Read.ByteOffset.QuadPart);
753  Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, IrpContext->Irp);
754  return Status;
755  }
756 
757  DPRINT("<%wZ>\n", &Fcb->PathNameU);
758 
759  ByteOffset = IrpContext->Stack->Parameters.Read.ByteOffset;
760  Length = IrpContext->Stack->Parameters.Read.Length;
761  BytesPerSector = IrpContext->DeviceExt->FatInfo.BytesPerSector;
762 
763  /* fail if file is a directory and no paged read */
764  if (vfatFCBIsDirectory(Fcb) && !PagingIo)
765  {
767  goto ByeBye;
768  }
769 
770  DPRINT("'%wZ', Offset: %u, Length %u\n", &Fcb->PathNameU, ByteOffset.u.LowPart, Length);
771 
772  if (ByteOffset.u.HighPart && !IsVolume)
773  {
775  goto ByeBye;
776  }
777 
778  if (Length == 0)
779  {
780  IrpContext->Irp->IoStatus.Information = 0;
782  goto ByeBye;
783  }
784 
785  if (ByteOffset.QuadPart >= Fcb->RFCB.FileSize.QuadPart)
786  {
787  IrpContext->Irp->IoStatus.Information = 0;
789  goto ByeBye;
790  }
791 
792  if (NoCache || PagingIo || IsVolume)
793  {
794  if (ByteOffset.u.LowPart % BytesPerSector != 0 || Length % BytesPerSector != 0)
795  {
796  DPRINT("%u %u\n", ByteOffset.u.LowPart, Length);
797  // non cached read must be sector aligned
799  goto ByeBye;
800  }
801  }
802 
803  if (IsVolume)
804  {
805  Resource = &IrpContext->DeviceExt->DirResource;
806  }
807  else if (PagingIo)
808  {
810  }
811  else
812  {
814  }
815 
816  /* Are we out of stack for the rest of the operation? */
817  if (IoGetRemainingStackSize() < OVERFLOW_READ_THRESHHOLD)
818  {
819  /* Lock the buffer */
821  if (!NT_SUCCESS(Status))
822  {
823  return Status;
824  }
825 
826  /* And post the read to the overflow thread */
827  VfatPostRead(IrpContext, Resource, PagingIo);
828 
829  /* Return the appropriate status */
830  return IrpContext->Irp->IoStatus.Status;
831  }
832 
833  if (!ExAcquireResourceSharedLite(Resource, CanWait))
834  {
835  Resource = NULL;
837  goto ByeBye;
838  }
839 
840  Status = VfatCommonRead(IrpContext);
841 
842 ByeBye:
843  if (Resource)
844  {
846  }
847 
848  if (Status == STATUS_PENDING)
849  {
851  if (NT_SUCCESS(Status))
852  {
853  Status = VfatMarkIrpContextForQueue(IrpContext);
854  }
855  }
856  else
857  {
858  IrpContext->Irp->IoStatus.Status = Status;
859  if (BooleanFlagOn(IrpContext->FileObject->Flags, FO_SYNCHRONOUS_IO) &&
860  !PagingIo &&
862  {
863  IrpContext->FileObject->CurrentByteOffset.QuadPart =
864  ByteOffset.QuadPart + IrpContext->Irp->IoStatus.Information;
865  }
866 
867  if (NT_SUCCESS(Status))
868  IrpContext->PriorityBoost = IO_DISK_INCREMENT;
869  }
870  DPRINT("%x\n", Status);
871  return Status;
872 }
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
Definition: vfat.h:447
#define IRPCONTEXT_COMPLETE
Definition: vfat.h:576
PDEVICE_EXTENSION DeviceExt
Definition: vfat.h:585
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
LONG NTSTATUS
Definition: precomp.h:26
#define IRP_NOCACHE
FORCEINLINE BOOLEAN vfatFCBIsDirectory(PVFATFCB FCB)
Definition: vfat.h:637
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
IO_STATUS_BLOCK IoStatus
PFILE_OBJECT FileObject
Definition: vfat.h:591
#define STATUS_END_OF_FILE
Definition: shellext.h:67
#define FO_SYNCHRONOUS_IO
Definition: iotypes.h:1776
CCHAR PriorityBoost
Definition: vfat.h:594
ERESOURCE * PERESOURCE
Definition: env_spec_w32.h:595
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
_Acquires_exclusive_lock_ Resource _Acquires_shared_lock_ Resource _Inout_ PERESOURCE Resource
Definition: cdprocs.h:843
VOID VfatPostRead(PVFAT_IRP_CONTEXT IrpContext, PERESOURCE Lock, BOOLEAN PagingIo)
Definition: rw.c:684
#define OVERFLOW_READ_THRESHHOLD
Definition: rw.c:31
unsigned char BOOLEAN
#define IRPCONTEXT_CANWAIT
Definition: vfat.h:575
FSRTL_COMMON_FCB_HEADER RFCB
Definition: ntfs.h:513
Status
Definition: gdiplustypes.h:24
PDEVICE_OBJECT DeviceObject
Definition: vfat.h:412
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define FCB_IS_PAGE_FILE
Definition: vfat.h:436
FORCEINLINE NTSTATUS VfatMarkIrpContextForQueue(PVFAT_IRP_CONTEXT IrpContext)
Definition: vfat.h:625
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
ULONG Flags
Definition: ntfs.h:532
ULONG BytesPerSector
Definition: vfat.h:261
ULONG dataStart
Definition: vfat.h:258
ERESOURCE MainResource
Definition: ntfs.h:524
NTSTATUS VfatCommonRead(PVFAT_IRP_CONTEXT IrpContext)
Definition: rw.c:547
Definition: vfat.h:249
PVFAT_GLOBAL_DATA VfatGlobalData
Definition: iface.c:36
#define FCB_IS_VOLUME
Definition: vfat.h:437
PDEVICE_OBJECT DeviceObject
Definition: vfat.h:584
#define NULL
Definition: types.h:112
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
#define IRP_PAGING_IO
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
unsigned int ULONG
Definition: retypes.h:1
ERESOURCE PagingIoResource
Definition: ntfs.h:523
ULONG Flags
Definition: vfat.h:586
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
_In_ PFCB Fcb
Definition: cdprocs.h:159
PIO_STACK_LOCATION Stack
Definition: vfat.h:588
NTSTATUS VfatLockUserBuffer(IN PIRP Irp, IN ULONG Length, IN LOCK_OPERATION Operation)
Definition: misc.c:461
LONGLONG QuadPart
Definition: typedefs.h:114
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:725

Referenced by VfatDispatchRequest().

◆ VfatReadFileData()

static NTSTATUS VfatReadFileData ( PVFAT_IRP_CONTEXT  IrpContext,
ULONG  Length,
LARGE_INTEGER  ReadOffset,
PULONG  LengthRead 
)
static

Definition at line 121 of file rw.c.

126 {
127  ULONG CurrentCluster;
128  ULONG FirstCluster;
129  ULONG StartCluster;
130  ULONG ClusterCount;
131  LARGE_INTEGER StartOffset;
132  PDEVICE_EXTENSION DeviceExt;
133  BOOLEAN First = TRUE;
134  PVFATFCB Fcb;
136  ULONG BytesDone;
137  ULONG BytesPerSector;
138  ULONG BytesPerCluster;
139  ULONG LastCluster;
140  ULONG LastOffset;
141 
142  /* PRECONDITION */
143  ASSERT(IrpContext);
144  DeviceExt = IrpContext->DeviceExt;
145  ASSERT(DeviceExt);
146  ASSERT(DeviceExt->FatInfo.BytesPerCluster);
147  ASSERT(IrpContext->FileObject);
148  ASSERT(IrpContext->FileObject->FsContext2 != NULL);
149 
150  DPRINT("VfatReadFileData(DeviceExt %p, FileObject %p, "
151  "Length %u, ReadOffset 0x%I64x)\n", DeviceExt,
152  IrpContext->FileObject, Length, ReadOffset.QuadPart);
153 
154  *LengthRead = 0;
155 
156  Fcb = IrpContext->FileObject->FsContext;
157  BytesPerSector = DeviceExt->FatInfo.BytesPerSector;
158  BytesPerCluster = DeviceExt->FatInfo.BytesPerCluster;
159 
160  ASSERT(ReadOffset.QuadPart + Length <= ROUND_UP_64(Fcb->RFCB.FileSize.QuadPart, BytesPerSector));
161  ASSERT(ReadOffset.u.LowPart % BytesPerSector == 0);
162  ASSERT(Length % BytesPerSector == 0);
163 
164  /* Is this a read of the FAT? */
166  {
167  ReadOffset.QuadPart += DeviceExt->FatInfo.FATStart * BytesPerSector;
168  Status = VfatReadDiskPartial(IrpContext, &ReadOffset, Length, 0, TRUE);
169 
170  if (NT_SUCCESS(Status))
171  {
172  *LengthRead = Length;
173  }
174  else
175  {
176  DPRINT1("FAT reading failed, Status %x\n", Status);
177  }
178  return Status;
179  }
180 
181  /* Is this a read of the Volume ? */
183  {
184  Status = VfatReadDiskPartial(IrpContext, &ReadOffset, Length, 0, TRUE);
185  if (NT_SUCCESS(Status))
186  {
187  *LengthRead = Length;
188  }
189  else
190  {
191  DPRINT1("Volume reading failed, Status %x\n", Status);
192  }
193  return Status;
194  }
195 
196  /* Find the first cluster */
197  FirstCluster =
198  CurrentCluster = vfatDirEntryGetFirstCluster (DeviceExt, &Fcb->entry);
199 
200  if (FirstCluster == 1)
201  {
202  /* Directory of FAT12/16 needs a special handling */
203  if (ReadOffset.u.LowPart + Length > DeviceExt->FatInfo.rootDirectorySectors * BytesPerSector)
204  {
205  Length = DeviceExt->FatInfo.rootDirectorySectors * BytesPerSector - ReadOffset.u.LowPart;
206  }
207  ReadOffset.u.LowPart += DeviceExt->FatInfo.rootStart * BytesPerSector;
208 
209  /* Fire up the read command */
210  Status = VfatReadDiskPartial (IrpContext, &ReadOffset, Length, 0, TRUE);
211  if (NT_SUCCESS(Status))
212  {
213  *LengthRead = Length;
214  }
215  return Status;
216  }
217 
218  ExAcquireFastMutex(&Fcb->LastMutex);
219  LastCluster = Fcb->LastCluster;
220  LastOffset = Fcb->LastOffset;
221  ExReleaseFastMutex(&Fcb->LastMutex);
222 
223  /* Find the cluster to start the read from */
224  if (LastCluster > 0 && ReadOffset.u.LowPart >= LastOffset)
225  {
226  Status = OffsetToCluster(DeviceExt, LastCluster,
227  ROUND_DOWN(ReadOffset.u.LowPart, BytesPerCluster) -
228  LastOffset,
229  &CurrentCluster, FALSE);
230 #ifdef DEBUG_VERIFY_OFFSET_CACHING
231  /* DEBUG VERIFICATION */
232  {
233  ULONG CorrectCluster;
234  OffsetToCluster(DeviceExt, FirstCluster,
235  ROUND_DOWN(ReadOffset.u.LowPart, BytesPerCluster),
236  &CorrectCluster, FALSE);
237  if (CorrectCluster != CurrentCluster)
238  KeBugCheck(FAT_FILE_SYSTEM);
239  }
240 #endif
241  }
242  else
243  {
244  Status = OffsetToCluster(DeviceExt, FirstCluster,
245  ROUND_DOWN(ReadOffset.u.LowPart, BytesPerCluster),
246  &CurrentCluster, FALSE);
247  }
248 
249  if (!NT_SUCCESS(Status))
250  {
251  return Status;
252  }
253 
254  ExAcquireFastMutex(&Fcb->LastMutex);
255  Fcb->LastCluster = CurrentCluster;
256  Fcb->LastOffset = ROUND_DOWN (ReadOffset.u.LowPart, BytesPerCluster);
257  ExReleaseFastMutex(&Fcb->LastMutex);
258 
260  IrpContext->RefCount = 1;
261 
262  while (Length > 0 && CurrentCluster != 0xffffffff)
263  {
264  StartCluster = CurrentCluster;
265  StartOffset.QuadPart = ClusterToSector(DeviceExt, StartCluster) * BytesPerSector;
266  BytesDone = 0;
267  ClusterCount = 0;
268 
269  do
270  {
271  ClusterCount++;
272  if (First)
273  {
274  BytesDone = min (Length, BytesPerCluster - (ReadOffset.u.LowPart % BytesPerCluster));
275  StartOffset.QuadPart += ReadOffset.u.LowPart % BytesPerCluster;
276  First = FALSE;
277  }
278  else
279  {
280  if (Length - BytesDone > BytesPerCluster)
281  {
282  BytesDone += BytesPerCluster;
283  }
284  else
285  {
286  BytesDone = Length;
287  }
288  }
289  Status = NextCluster(DeviceExt, FirstCluster, &CurrentCluster, FALSE);
290  }
291  while (StartCluster + ClusterCount == CurrentCluster && NT_SUCCESS(Status) && Length > BytesDone);
292  DPRINT("start %08x, next %08x, count %u\n",
293  StartCluster, CurrentCluster, ClusterCount);
294 
295  ExAcquireFastMutex(&Fcb->LastMutex);
296  Fcb->LastCluster = StartCluster + (ClusterCount - 1);
297  Fcb->LastOffset = ROUND_DOWN(ReadOffset.u.LowPart, BytesPerCluster) + (ClusterCount - 1) * BytesPerCluster;
298  ExReleaseFastMutex(&Fcb->LastMutex);
299 
300  /* Fire up the read command */
301  Status = VfatReadDiskPartial (IrpContext, &StartOffset, BytesDone, *LengthRead, FALSE);
303  {
304  break;
305  }
306  *LengthRead += BytesDone;
307  Length -= BytesDone;
308  ReadOffset.u.LowPart += BytesDone;
309  }
310 
311  if (InterlockedDecrement((PLONG)&IrpContext->RefCount) != 0)
312  {
314  }
315 
317  {
318  if (Length > 0)
319  {
321  }
322  else
323  {
324  Status = IrpContext->Irp->IoStatus.Status;
325  }
326  }
327 
328  return Status;
329 }
NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, PULONG CurrentCluster, BOOLEAN Extend)
Definition: rw.c:40
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
Definition: vfat.h:447
PDEVICE_EXTENSION DeviceExt
Definition: vfat.h:585
ULONG vfatDirEntryGetFirstCluster(PDEVICE_EXTENSION pDeviceExt, PDIR_ENTRY pFatDirEntry)
Definition: direntry.c:19
#define TRUE
Definition: types.h:120
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
LONG NTSTATUS
Definition: precomp.h:26
IO_STATUS_BLOCK IoStatus
PFILE_OBJECT FileObject
Definition: vfat.h:591
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
ULONG RefCount
Definition: vfat.h:592
WCHAR First[]
Definition: FormatMessage.c:11
#define ROUND_UP_64(n, align)
Definition: vfat.h:34
#define FALSE
Definition: types.h:117
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1427
_Must_inspect_result_ _In_ WDFUSBPIPE _In_ WDFREQUEST _In_opt_ WDFMEMORY _In_opt_ PWDFMEMORY_OFFSET ReadOffset
Definition: wdfusb.h:1996
KEVENT Event
Definition: vfat.h:593
unsigned char BOOLEAN
FSRTL_COMMON_FCB_HEADER RFCB
Definition: ntfs.h:513
Status
Definition: gdiplustypes.h:24
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
ULONG Flags
Definition: ntfs.h:532
#define FCB_IS_FAT
Definition: vfat.h:435
#define InterlockedDecrement
Definition: armddk.h:52
#define FCB_IS_VOLUME
Definition: vfat.h:437
#define ROUND_DOWN(n, align)
Definition: eventvwr.h:30
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
#define min(a, b)
Definition: monoChain.cc:55
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
unsigned int ULONG
Definition: retypes.h:1
#define DPRINT
Definition: sndvol32.h:71
_In_ PFCB Fcb
Definition: cdprocs.h:159
NTSTATUS VfatReadDiskPartial(IN PVFAT_IRP_CONTEXT IrpContext, IN PLARGE_INTEGER ReadOffset, IN ULONG ReadLength, ULONG BufferOffset, IN BOOLEAN Wait)
Definition: blockdev.c:153
signed int * PLONG
Definition: retypes.h:5
ULONGLONG ClusterToSector(PDEVICE_EXTENSION DeviceExt, ULONG Cluster)
Definition: fat.c:733
LONGLONG QuadPart
Definition: typedefs.h:114
NTSTATUS OffsetToCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, ULONG FileOffset, PULONG Cluster, BOOLEAN Extend)
Definition: rw.c:61

Referenced by VfatCommonRead().

◆ VfatStackOverflowRead()

VOID NTAPI VfatStackOverflowRead ( PVOID  Context,
IN PKEVENT  Event 
)

Definition at line 666 of file rw.c.

669 {
670  PVFAT_IRP_CONTEXT IrpContext;
671 
672  IrpContext = Context;
673  /* In a separate thread, we can wait and resources got locked */
674  SetFlag(IrpContext->Flags, IRPCONTEXT_CANWAIT);
675 
676  /* Perform the read operation */
677  DPRINT1("Performing posted read\n");
678  VfatCommonRead(IrpContext);
679 
680  KeSetEvent(Event, 0, FALSE);
681 }
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
#define FALSE
Definition: types.h:117
#define IRPCONTEXT_CANWAIT
Definition: vfat.h:575
NTSTATUS VfatCommonRead(PVFAT_IRP_CONTEXT IrpContext)
Definition: rw.c:547
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define DPRINT1
Definition: precomp.h:8
struct tagContext Context
Definition: acpixf.h:1034
ULONG Flags
Definition: vfat.h:586

Referenced by VfatPostRead().

◆ VfatWrite()

NTSTATUS VfatWrite ( PVFAT_IRP_CONTEXT pIrpContext)

CanWait

Definition at line 875 of file rw.c.

877 {
878  PVFAT_IRP_CONTEXT IrpContext = *pIrpContext;
879  PVFATFCB Fcb;
882  LARGE_INTEGER OldFileSize;
884  ULONG Length = 0;
885  PVOID Buffer;
886  ULONG BytesPerSector;
887  BOOLEAN PagingIo, CanWait, IsVolume, IsFAT, NoCache;
888 
889  ASSERT(IrpContext);
890 
891  DPRINT("VfatWrite(IrpContext %p)\n", IrpContext);
892 
893  ASSERT(IrpContext->DeviceObject);
894 
895  PagingIo = BooleanFlagOn(IrpContext->Irp->Flags, IRP_PAGING_IO);
896  CanWait = BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT);
897  NoCache = BooleanFlagOn(IrpContext->Irp->Flags, IRP_NOCACHE);
898 
899  // This request is not allowed on the main device object
900  if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
901  {
902  DPRINT("VfatWrite is called with the main device object.\n");
904  goto ByeBye;
905  }
906 
907  ASSERT(IrpContext->DeviceExt);
908  ASSERT(IrpContext->FileObject);
909  Fcb = IrpContext->FileObject->FsContext;
910  ASSERT(Fcb);
911 
912  IsVolume = BooleanFlagOn(Fcb->Flags, FCB_IS_VOLUME);
913  IsFAT = BooleanFlagOn(Fcb->Flags, FCB_IS_FAT);
914 
916  {
917  PFATINFO FatInfo = &IrpContext->DeviceExt->FatInfo;
918  IrpContext->Stack->Parameters.Write.ByteOffset.QuadPart += FatInfo->dataStart * FatInfo->BytesPerSector;
919  IoSkipCurrentIrpStackLocation(IrpContext->Irp);
920  IrpContext->Flags &= ~IRPCONTEXT_COMPLETE;
921  DPRINT("Write to page file, disk offset %I64x\n", IrpContext->Stack->Parameters.Write.ByteOffset.QuadPart);
922  Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, IrpContext->Irp);
923  return Status;
924  }
925 
926  DPRINT("<%wZ>\n", &Fcb->PathNameU);
927 
928  /* fail if file is a directory and no paged read */
929  if (vfatFCBIsDirectory(Fcb) && !PagingIo)
930  {
932  goto ByeBye;
933  }
934 
935  ByteOffset = IrpContext->Stack->Parameters.Write.ByteOffset;
936  if (ByteOffset.u.LowPart == FILE_WRITE_TO_END_OF_FILE &&
937  ByteOffset.u.HighPart == -1)
938  {
939  ByteOffset.QuadPart = Fcb->RFCB.FileSize.QuadPart;
940  }
941  Length = IrpContext->Stack->Parameters.Write.Length;
942  BytesPerSector = IrpContext->DeviceExt->FatInfo.BytesPerSector;
943 
944  if (ByteOffset.u.HighPart && !IsVolume)
945  {
947  goto ByeBye;
948  }
949 
950  if (IsFAT || IsVolume ||
951  vfatDirEntryGetFirstCluster(IrpContext->DeviceExt, &Fcb->entry) == 1)
952  {
953  if (ByteOffset.QuadPart + Length > Fcb->RFCB.FileSize.QuadPart)
954  {
955  // we can't extend the FAT, the volume or the root on FAT12/FAT16
957  goto ByeBye;
958  }
959  }
960 
961  if (PagingIo || NoCache || IsVolume)
962  {
963  if (ByteOffset.u.LowPart % BytesPerSector != 0 || Length % BytesPerSector != 0)
964  {
965  // non cached write must be sector aligned
967  goto ByeBye;
968  }
969  }
970 
971  OldFileSize = Fcb->RFCB.FileSize;
972 
973  if (Length == 0)
974  {
975  /* Update last write time */
976  IrpContext->Irp->IoStatus.Information = 0;
978  goto Metadata;
979  }
980 
981  if (PagingIo)
982  {
983  if (ByteOffset.u.LowPart + Length > Fcb->RFCB.AllocationSize.u.LowPart)
984  {
986  goto ByeBye;
987  }
988 
989  if (ByteOffset.u.LowPart + Length > ROUND_UP(Fcb->RFCB.AllocationSize.u.LowPart, BytesPerSector))
990  {
991  Length = ROUND_UP(Fcb->RFCB.FileSize.u.LowPart, BytesPerSector) - ByteOffset.u.LowPart;
992  }
993  }
994 
995  if (!NoCache && !CcCanIWrite(IrpContext->FileObject, Length, CanWait,
997  {
998  BOOLEAN Retrying;
999 
1000  Retrying = BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_DEFERRED_WRITE);
1001  SetFlag(IrpContext->Flags, IRPCONTEXT_DEFERRED_WRITE);
1002 
1003  IoMarkIrpPending(IrpContext->Irp);
1005 
1006  DPRINT1("Deferring write for Irp %p, context %p!\n", IrpContext->Irp, IrpContext);
1008  IrpContext, NULL, Length, Retrying);
1009  *pIrpContext = NULL;
1010 
1011  return Status;
1012  }
1013 
1014  if (IsVolume)
1015  {
1016  Resource = &IrpContext->DeviceExt->DirResource;
1017  }
1018  else if (PagingIo)
1019  {
1021  }
1022  else
1023  {
1025  }
1026 
1027  if (PagingIo)
1028  {
1029  if (!ExAcquireResourceSharedLite(Resource, CanWait))
1030  {
1031  Resource = NULL;
1033  goto ByeBye;
1034  }
1035  }
1036  else
1037  {
1039  {
1040  Resource = NULL;
1042  goto ByeBye;
1043  }
1044  }
1045 
1046  if (!PagingIo &&
1048  {
1049  if (!FsRtlCheckLockForWriteAccess(&Fcb->FileLock, IrpContext->Irp))
1050  {
1052  goto ByeBye;
1053  }
1054  }
1055 
1056  if (!CanWait && !IsVolume)
1057  {
1058  if (ByteOffset.u.LowPart + Length > Fcb->RFCB.AllocationSize.u.LowPart)
1059  {
1061  goto ByeBye;
1062  }
1063  }
1064 
1065  Buffer = VfatGetUserBuffer(IrpContext->Irp, PagingIo);
1066 
1067  if (!IsFAT && !IsVolume && !PagingIo &&
1068  ByteOffset.u.LowPart + Length > Fcb->RFCB.FileSize.u.LowPart)
1069  {
1071 
1072  if (!ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource, CanWait))
1073  {
1075  goto ByeBye;
1076  }
1077 
1078  AllocationSize.QuadPart = ByteOffset.u.LowPart + Length;
1080  IrpContext->DeviceExt, &AllocationSize);
1081 
1082  ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource);
1083 
1084  if (!NT_SUCCESS (Status))
1085  {
1086  goto ByeBye;
1087  }
1088  }
1089 
1090  if (!NoCache && !PagingIo && !IsVolume)
1091  {
1092  // cached write
1093 
1094  vfatAddToStat(IrpContext->DeviceExt, Base.UserFileWrites, 1);
1095  vfatAddToStat(IrpContext->DeviceExt, Base.UserFileWriteBytes, Length);
1096 
1097  _SEH2_TRY
1098  {
1099  if (IrpContext->FileObject->PrivateCacheMap == NULL)
1100  {
1101  CcInitializeCacheMap(IrpContext->FileObject,
1103  FALSE,
1105  Fcb);
1106  }
1107 
1108  if (ByteOffset.QuadPart > OldFileSize.QuadPart)
1109  {
1110  CcZeroData(IrpContext->FileObject, &OldFileSize, &ByteOffset, TRUE);
1111  }
1112 
1113  if (CcCopyWrite(IrpContext->FileObject,
1114  &ByteOffset,
1115  Length,
1116  TRUE /*CanWait*/,
1117  Buffer))
1118  {
1119  IrpContext->Irp->IoStatus.Information = Length;
1121  }
1122  else
1123  {
1124  ASSERT(FALSE );
1126  }
1127  }
1129  {
1131  }
1132  _SEH2_END;
1133  }
1134  else
1135  {
1136  // non cached write
1137  Status = VfatLockUserBuffer(IrpContext->Irp, Length, IoReadAccess);
1138  if (!NT_SUCCESS(Status))
1139  {
1141  goto ByeBye;
1142  }
1143 
1144  if (ByteOffset.QuadPart > OldFileSize.QuadPart)
1145  {
1146  CcZeroData(IrpContext->FileObject, &OldFileSize, &ByteOffset, TRUE);
1147  }
1148 
1149  if (!IsVolume)
1150  {
1151  vfatAddToStat(IrpContext->DeviceExt, Fat.NonCachedWrites, 1);
1152  vfatAddToStat(IrpContext->DeviceExt, Fat.NonCachedWriteBytes, Length);
1153  }
1154  else
1155  {
1156  vfatAddToStat(IrpContext->DeviceExt, Base.MetaDataWrites, 1);
1157  vfatAddToStat(IrpContext->DeviceExt, Base.MetaDataWriteBytes, Length);
1158  }
1159 
1160  Status = VfatWriteFileData(IrpContext, Length, ByteOffset);
1161  if (NT_SUCCESS(Status))
1162  {
1163  IrpContext->Irp->IoStatus.Information = Length;
1164  }
1165  }
1166 
1167 Metadata:
1168  if (!PagingIo && !IsFAT && !IsVolume)
1169  {
1170  if(!vfatFCBIsDirectory(Fcb))
1171  {
1172  LARGE_INTEGER SystemTime;
1173  ULONG Filter;
1174 
1175  // set dates and times
1176  KeQuerySystemTime (&SystemTime);
1177  if (vfatVolumeIsFatX(IrpContext->DeviceExt))
1178  {
1180  &SystemTime, &Fcb->entry.FatX.UpdateDate,
1181  &Fcb->entry.FatX.UpdateTime);
1182  Fcb->entry.FatX.AccessDate = Fcb->entry.FatX.UpdateDate;
1183  Fcb->entry.FatX.AccessTime = Fcb->entry.FatX.UpdateTime;
1184  }
1185  else
1186  {
1188  &SystemTime, &Fcb->entry.Fat.UpdateDate,
1189  &Fcb->entry.Fat.UpdateTime);
1190  Fcb->entry.Fat.AccessDate = Fcb->entry.Fat.UpdateDate;
1191  }
1192  /* set date and times to dirty */
1193  Fcb->Flags |= FCB_IS_DIRTY;
1194 
1195  /* Time to notify the OS */
1197  if (ByteOffset.QuadPart != OldFileSize.QuadPart) Filter |= FILE_NOTIFY_CHANGE_SIZE;
1198 
1200  }
1201  }
1202 
1203 ByeBye:
1204  if (Resource)
1205  {
1207  }
1208 
1209  if (Status == STATUS_PENDING)
1210  {
1211  Status = VfatLockUserBuffer(IrpContext->Irp, Length, IoReadAccess);
1212  if (NT_SUCCESS(Status))
1213  {
1214  Status = VfatMarkIrpContextForQueue(IrpContext);
1215  }
1216  }
1217  else
1218  {
1219  IrpContext->Irp->IoStatus.Status = Status;
1220  if (BooleanFlagOn(IrpContext->FileObject->Flags, FO_SYNCHRONOUS_IO) &&
1221  !PagingIo && NT_SUCCESS(Status))
1222  {
1223  IrpContext->FileObject->CurrentByteOffset.QuadPart =
1224  ByteOffset.QuadPart + IrpContext->Irp->IoStatus.Information;
1225  }
1226 
1227  if (NT_SUCCESS(Status))
1228  IrpContext->PriorityBoost = IO_DISK_INCREMENT;
1229  }
1230  DPRINT("%x\n", Status);
1231  return Status;
1232 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
NTSTATUS VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject, PVFATFCB Fcb, PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER AllocationSize)
Definition: finfo.c:1213
FILE_LOCK FileLock
Definition: fatstruc.h:1070
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define IRPCONTEXT_DEFERRED_WRITE
Definition: vfat.h:579
#define ROUND_UP(n, align)
Definition: eventvwr.h:31
#define FCB_IS_DIRTY
Definition: vfat.h:438
Definition: vfat.h:447
#define IRPCONTEXT_COMPLETE
Definition: vfat.h:576
PDEVICE_EXTENSION DeviceExt
Definition: vfat.h:585
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
ULONG vfatDirEntryGetFirstCluster(PDEVICE_EXTENSION pDeviceExt, PDIR_ENTRY pFatDirEntry)
Definition: direntry.c:19
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
BOOLEAN NTAPI FsRtlCheckLockForWriteAccess(IN PFILE_LOCK FileLock, IN PIRP Irp)
Definition: filelock.c:714
LONG NTSTATUS
Definition: precomp.h:26
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2386
#define IRP_NOCACHE
FORCEINLINE BOOLEAN vfatFCBIsDirectory(PVFATFCB FCB)
Definition: vfat.h:637
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define FILE_NOTIFY_CHANGE_SIZE
#define FILE_NOTIFY_CHANGE_LAST_WRITE
#define vfatAddToStat(Vcb, Stat, Inc)
Definition: vfat.h:671
IO_STATUS_BLOCK IoStatus
PFILE_OBJECT FileObject
Definition: vfat.h:591
static NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext, ULONG Length, LARGE_INTEGER WriteOffset)
Definition: rw.c:333
_SEH2_TRY
Definition: create.c:4226
#define STATUS_END_OF_FILE
Definition: shellext.h:67
#define FO_SYNCHRONOUS_IO
Definition: iotypes.h:1776
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
CCHAR PriorityBoost
Definition: vfat.h:594
ERESOURCE * PERESOURCE
Definition: env_spec_w32.h:595
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
BOOLEAN FsdSystemTimeToDosDateTime(PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER SystemTime, PUSHORT pDosDate, PUSHORT pDosTime)
Definition: dir.c:53
_Acquires_exclusive_lock_ Resource _Acquires_shared_lock_ Resource _Inout_ PERESOURCE Resource
Definition: cdprocs.h:843
#define FALSE
Definition: types.h:117
BOOLEAN NTAPI CcZeroData(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER StartOffset, IN PLARGE_INTEGER EndOffset, IN BOOLEAN Wait)
Definition: fssup.c:414
_Must_inspect_result_ _In_opt_ PFLT_FILTER Filter
Definition: fltkernel.h:1802
#define FILE_ACTION_MODIFIED
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
unsigned char BOOLEAN
#define IRPCONTEXT_CANWAIT
Definition: vfat.h:575
Definition: bufpool.h:45
PVOID VfatGetUserBuffer(IN PIRP Irp, IN BOOLEAN Paging)
Definition: misc.c:444
#define FsRtlAreThereCurrentFileLocks(FL)
Definition: fsrtlfuncs.h:1584
FSRTL_COMMON_FCB_HEADER RFCB
Definition: ntfs.h:513
#define FILE_WRITE_TO_END_OF_FILE
Definition: ext2fs.h:273
Status
Definition: gdiplustypes.h:24
FORCEINLINE BOOLEAN vfatVolumeIsFatX(PDEVICE_EXTENSION DeviceExt)
Definition: vfat.h:651
PDEVICE_OBJECT DeviceObject
Definition: vfat.h:412
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
BOOLEAN NTAPI CcCanIWrite(IN PFILE_OBJECT FileObject, IN ULONG BytesToWrite, IN BOOLEAN Wait, IN UCHAR Retrying)
Definition: copysup.c:214
VOID NTAPI CcInitializeCacheMap(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes, IN BOOLEAN PinAccess, IN PCACHE_MANAGER_CALLBACKS Callbacks, IN PVOID LazyWriteContext)
Definition: fssup.c:195
#define FCB_IS_PAGE_FILE
Definition: vfat.h:436
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
FORCEINLINE NTSTATUS VfatMarkIrpContextForQueue(PVFAT_IRP_CONTEXT IrpContext)
Definition: vfat.h:625
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
ULONG Flags
Definition: ntfs.h:532
#define FCB_IS_FAT
Definition: vfat.h:435
ULONG BytesPerSector
Definition: vfat.h:261
ULONG dataStart
Definition: vfat.h:258
LARGE_INTEGER AllocationSize
Definition: env_spec_w32.h:755
ERESOURCE MainResource
Definition: ntfs.h:524
struct _LARGE_INTEGER::@2276 u
BOOLEAN NTAPI CcCopyWrite(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN PVOID Buffer)
Definition: copysup.c:129
Definition: vfat.h:249
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:319
PVFAT_GLOBAL_DATA VfatGlobalData
Definition: iface.c:36
CACHE_MANAGER_CALLBACKS CacheMgrCallbacks
Definition: vfat.h:422
#define FCB_IS_VOLUME
Definition: vfat.h:437
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
_SEH2_END
Definition: create.c:4400
FORCEINLINE VOID vfatReportChange(IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB Fcb, IN ULONG FilterMatch, IN ULONG Action)
Definition: vfat.h:658
#define FILE_NOTIFY_CHANGE_ATTRIBUTES
PDEVICE_OBJECT DeviceObject
Definition: vfat.h:584
#define NULL
Definition: types.h:112
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
#define IRP_PAGING_IO
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
#define DPRINT1
Definition: precomp.h:8
#define STATUS_FILE_LOCK_CONFLICT
Definition: ntstatus.h:320
VOID NTAPI VfatHandleDeferredWrite(IN PVOID IrpContext, IN PVOID Unused)
Definition: misc.c:221
unsigned int ULONG
Definition: retypes.h:1
ERESOURCE PagingIoResource
Definition: ntfs.h:523
ULONG Flags
Definition: vfat.h:586
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define STATUS_SUCCESS
Definition: shellext.h:65
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define DPRINT
Definition: sndvol32.h:71
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
_In_ PFCB Fcb
Definition: cdprocs.h:159
PIO_STACK_LOCATION Stack
Definition: vfat.h:588
NTSTATUS VfatLockUserBuffer(IN PIRP Irp, IN ULONG Length, IN LOCK_OPERATION Operation)
Definition: misc.c:461
IoMarkIrpPending(Irp)
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)
Definition: copysup.c:225
LONGLONG QuadPart
Definition: typedefs.h:114
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:725

Referenced by VfatDispatchRequest().

◆ VfatWriteFileData()

static NTSTATUS VfatWriteFileData ( PVFAT_IRP_CONTEXT  IrpContext,
ULONG  Length,
LARGE_INTEGER  WriteOffset 
)
static

Definition at line 333 of file rw.c.

337 {
338  PDEVICE_EXTENSION DeviceExt;
339  PVFATFCB Fcb;
340  ULONG Count;
341  ULONG FirstCluster;
342  ULONG CurrentCluster;
343  ULONG BytesDone;
344  ULONG StartCluster;
345  ULONG ClusterCount;
347  BOOLEAN First = TRUE;
348  ULONG BytesPerSector;
349  ULONG BytesPerCluster;
350  LARGE_INTEGER StartOffset;
351  ULONG BufferOffset;
352  ULONG LastCluster;
353  ULONG LastOffset;
354 
355  /* PRECONDITION */
356  ASSERT(IrpContext);
357  DeviceExt = IrpContext->DeviceExt;
358  ASSERT(DeviceExt);
359  ASSERT(DeviceExt->FatInfo.BytesPerCluster);
360  ASSERT(IrpContext->FileObject);
361  ASSERT(IrpContext->FileObject->FsContext2 != NULL);
362 
363  Fcb = IrpContext->FileObject->FsContext;
364  BytesPerCluster = DeviceExt->FatInfo.BytesPerCluster;
365  BytesPerSector = DeviceExt->FatInfo.BytesPerSector;
366 
367  DPRINT("VfatWriteFileData(DeviceExt %p, FileObject %p, "
368  "Length %u, WriteOffset 0x%I64x), '%wZ'\n", DeviceExt,
369  IrpContext->FileObject, Length, WriteOffset.QuadPart,
370  &Fcb->PathNameU);
371 
372  ASSERT(WriteOffset.QuadPart + Length <= Fcb->RFCB.AllocationSize.QuadPart);
373  ASSERT(WriteOffset.u.LowPart % BytesPerSector == 0);
374  ASSERT(Length % BytesPerSector == 0);
375 
376  /* Is this a write of the volume? */
378  {
379  Status = VfatWriteDiskPartial(IrpContext, &WriteOffset, Length, 0, TRUE);
380  if (!NT_SUCCESS(Status))
381  {
382  DPRINT1("Volume writing failed, Status %x\n", Status);
383  }
384  return Status;
385  }
386 
387  /* Is this a write to the FAT? */
389  {
390  WriteOffset.u.LowPart += DeviceExt->FatInfo.FATStart * BytesPerSector;
391  IrpContext->RefCount = 1;
392  for (Count = 0; Count < DeviceExt->FatInfo.FATCount; Count++)
393  {
394  Status = VfatWriteDiskPartial(IrpContext, &WriteOffset, Length, 0, FALSE);
396  {
397  DPRINT1("FAT writing failed, Status %x\n", Status);
398  break;
399  }
400  WriteOffset.u.LowPart += Fcb->RFCB.FileSize.u.LowPart;
401  }
402 
403  if (InterlockedDecrement((PLONG)&IrpContext->RefCount) != 0)
404  {
406  }
407 
409  {
410  Status = IrpContext->Irp->IoStatus.Status;
411  }
412  return Status;
413  }
414 
415  /*
416  * Find the first cluster
417  */
418  FirstCluster =
419  CurrentCluster = vfatDirEntryGetFirstCluster (DeviceExt, &Fcb->entry);
420 
421  if (FirstCluster == 1)
422  {
423  ASSERT(WriteOffset.u.LowPart + Length <= DeviceExt->FatInfo.rootDirectorySectors * BytesPerSector);
424  // Directory of FAT12/16 needs a special handling
425  WriteOffset.u.LowPart += DeviceExt->FatInfo.rootStart * BytesPerSector;
426  // Fire up the write command
427  Status = VfatWriteDiskPartial (IrpContext, &WriteOffset, Length, 0, TRUE);
428  return Status;
429  }
430 
431  ExAcquireFastMutex(&Fcb->LastMutex);
432  LastCluster = Fcb->LastCluster;
433  LastOffset = Fcb->LastOffset;
434  ExReleaseFastMutex(&Fcb->LastMutex);
435 
436  /*
437  * Find the cluster to start the write from
438  */
439  if (LastCluster > 0 && WriteOffset.u.LowPart >= LastOffset)
440  {
441  Status = OffsetToCluster(DeviceExt, LastCluster,
442  ROUND_DOWN(WriteOffset.u.LowPart, BytesPerCluster) -
443  LastOffset,
444  &CurrentCluster, FALSE);
445 #ifdef DEBUG_VERIFY_OFFSET_CACHING
446  /* DEBUG VERIFICATION */
447  {
448  ULONG CorrectCluster;
449  OffsetToCluster(DeviceExt, FirstCluster,
450  ROUND_DOWN(WriteOffset.u.LowPart, BytesPerCluster),
451  &CorrectCluster, FALSE);
452  if (CorrectCluster != CurrentCluster)
453  KeBugCheck(FAT_FILE_SYSTEM);
454  }
455 #endif
456  }
457  else
458  {
459  Status = OffsetToCluster(DeviceExt, FirstCluster,
460  ROUND_DOWN(WriteOffset.u.LowPart, BytesPerCluster),
461  &CurrentCluster, FALSE);
462  }
463 
464  if (!NT_SUCCESS(Status))
465  {
466  return Status;
467  }
468 
469  ExAcquireFastMutex(&Fcb->LastMutex);
470  Fcb->LastCluster = CurrentCluster;
471  Fcb->LastOffset = ROUND_DOWN (WriteOffset.u.LowPart, BytesPerCluster);
472  ExReleaseFastMutex(&Fcb->LastMutex);
473 
474  IrpContext->RefCount = 1;
475  BufferOffset = 0;
476 
477  while (Length > 0 && CurrentCluster != 0xffffffff)
478  {
479  StartCluster = CurrentCluster;
480  StartOffset.QuadPart = ClusterToSector(DeviceExt, StartCluster) * BytesPerSector;
481  BytesDone = 0;
482  ClusterCount = 0;
483 
484  do
485  {
486  ClusterCount++;
487  if (First)
488  {
489  BytesDone = min (Length, BytesPerCluster - (WriteOffset.u.LowPart % BytesPerCluster));
490  StartOffset.QuadPart += WriteOffset.u.LowPart % BytesPerCluster;
491  First = FALSE;
492  }
493  else
494  {
495  if (Length - BytesDone > BytesPerCluster)
496  {
497  BytesDone += BytesPerCluster;
498  }
499  else
500  {
501  BytesDone = Length;
502  }
503  }
504  Status = NextCluster(DeviceExt, FirstCluster, &CurrentCluster, FALSE);
505  }
506  while (StartCluster + ClusterCount == CurrentCluster && NT_SUCCESS(Status) && Length > BytesDone);
507  DPRINT("start %08x, next %08x, count %u\n",
508  StartCluster, CurrentCluster, ClusterCount);
509 
510  ExAcquireFastMutex(&Fcb->LastMutex);
511  Fcb->LastCluster = StartCluster + (ClusterCount - 1);
512  Fcb->LastOffset = ROUND_DOWN(WriteOffset.u.LowPart, BytesPerCluster) + (ClusterCount - 1) * BytesPerCluster;
513  ExReleaseFastMutex(&Fcb->LastMutex);
514 
515  // Fire up the write command
516  Status = VfatWriteDiskPartial (IrpContext, &StartOffset, BytesDone, BufferOffset, FALSE);
518  {
519  break;
520  }
521  BufferOffset += BytesDone;
522  Length -= BytesDone;
523  WriteOffset.u.LowPart += BytesDone;
524  }
525 
526  if (InterlockedDecrement((PLONG)&IrpContext->RefCount) != 0)
527  {
529  }
530 
532  {
533  if (Length > 0)
534  {
536  }
537  else
538  {
539  Status = IrpContext->Irp->IoStatus.Status;
540  }
541  }
542 
543  return Status;
544 }
NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, PULONG CurrentCluster, BOOLEAN Extend)
Definition: rw.c:40
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
Definition: vfat.h:447
PDEVICE_EXTENSION DeviceExt
Definition: vfat.h:585
ULONG vfatDirEntryGetFirstCluster(PDEVICE_EXTENSION pDeviceExt, PDIR_ENTRY pFatDirEntry)
Definition: direntry.c:19
#define TRUE
Definition: types.h:120
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
_Must_inspect_result_ _In_ WDFUSBPIPE _In_ WDFREQUEST _In_opt_ WDFMEMORY _In_opt_ PWDFMEMORY_OFFSET WriteOffset
Definition: wdfusb.h:1914
LONG NTSTATUS
Definition: precomp.h:26
IO_STATUS_BLOCK IoStatus
PFILE_OBJECT FileObject
Definition: vfat.h:591
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
ULONG RefCount
Definition: vfat.h:592
WCHAR First[]
Definition: FormatMessage.c:11
#define FALSE
Definition: types.h:117
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1427
NTSTATUS VfatWriteDiskPartial(IN PVFAT_IRP_CONTEXT IrpContext, IN PLARGE_INTEGER WriteOffset, IN ULONG WriteLength, IN ULONG BufferOffset, IN BOOLEAN Wait)
Definition: blockdev.c:336
KEVENT Event
Definition: vfat.h:593
unsigned char BOOLEAN
FSRTL_COMMON_FCB_HEADER RFCB
Definition: ntfs.h:513
Status
Definition: gdiplustypes.h:24
int Count
Definition: noreturn.cpp:7
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
ULONG Flags
Definition: ntfs.h:532
#define FCB_IS_FAT
Definition: vfat.h:435
#define InterlockedDecrement
Definition: armddk.h:52
struct _LARGE_INTEGER::@2276 u
#define FCB_IS_VOLUME
Definition: vfat.h:437
#define ROUND_DOWN(n, align)
Definition: eventvwr.h:30
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
#define min(a, b)
Definition: monoChain.cc:55
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
unsigned int ULONG
Definition: retypes.h:1
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
_In_ PFCB Fcb
Definition: cdprocs.h:159
signed int * PLONG
Definition: retypes.h:5
ULONGLONG ClusterToSector(PDEVICE_EXTENSION DeviceExt, ULONG Cluster)
Definition: fat.c:733
LONGLONG QuadPart
Definition: typedefs.h:114
NTSTATUS OffsetToCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, ULONG FileOffset, PULONG Cluster, BOOLEAN Extend)
Definition: rw.c:61

Referenced by VfatWrite().