ReactOS  0.4.15-dev-2991-g632fa1c
rw.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS kernel
4  * FILE: drivers/filesystems/fastfat/rw.c
5  * PURPOSE: VFAT Filesystem
6  * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
7  * Pierre Schweitzer (pierre@reactos.org)
8  *
9  */
10 
11 /* INCLUDES *****************************************************************/
12 
13 #include "vfat.h"
14 
15 #define NDEBUG
16 #include <debug.h>
17 
18 /*
19  * Uncomment to enable strict verification of cluster/offset pair
20  * caching. If this option is enabled you lose all the benefits of
21  * the caching and the read/write operations will actually be
22  * slower. It's meant only for debugging!!!
23  * - Filip Navara, 26/07/2004
24  */
25 /* #define DEBUG_VERIFY_OFFSET_CACHING */
26 
27 /* Arbitrary, taken from MS FastFAT, should be
28  * refined given what we experience in common
29  * out of stack operations
30  */
31 #define OVERFLOW_READ_THRESHHOLD 0xE00
32 
33 /* FUNCTIONS *****************************************************************/
34 
35 /*
36  * Return the next cluster in a FAT chain, possibly extending the chain if
37  * necessary
38  */
41  PDEVICE_EXTENSION DeviceExt,
42  ULONG FirstCluster,
43  PULONG CurrentCluster,
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 }
59 
62  PDEVICE_EXTENSION DeviceExt,
63  ULONG FirstCluster,
65  PULONG Cluster,
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 }
115 
116 /*
117  * FUNCTION: Reads data from a file
118  */
119 static
120 NTSTATUS
122  PVFAT_IRP_CONTEXT IrpContext,
123  ULONG Length,
125  PULONG LengthRead)
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 }
330 
331 static
332 NTSTATUS
334  PVFAT_IRP_CONTEXT IrpContext,
335  ULONG Length,
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 }
545 
546 NTSTATUS
548  PVFAT_IRP_CONTEXT IrpContext)
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 }
663 
664 VOID
665 NTAPI
667  PVOID Context,
668  IN PKEVENT Event)
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 }
682 
683 VOID
685  PVFAT_IRP_CONTEXT IrpContext,
687  BOOLEAN PagingIo)
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 }
708 
709 NTSTATUS
711  PVFAT_IRP_CONTEXT IrpContext)
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 }
873 
874 NTSTATUS
876  PVFAT_IRP_CONTEXT *pIrpContext)
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:1071
#define IN
Definition: typedefs.h:39
NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, PULONG CurrentCluster, BOOLEAN Extend)
Definition: rw.c:40
VOID NTAPI Extend(VOID)
Definition: extend.c:14
_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 DbgPrint
Definition: loader.c:25
#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
_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
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2386
VOID NTAPI FsRtlPostPagingFileStackOverflow(IN PVOID Context, IN PKEVENT Event, IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine)
Definition: stackovf.c:206
#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
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
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
static NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext, ULONG Length, LARGE_INTEGER WriteOffset)
Definition: rw.c:333
VOID NTAPI VfatStackOverflowRead(PVOID Context, IN PKEVENT Event)
Definition: rw.c:666
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
_SEH2_TRY
Definition: create.c:4226
ULONG RefCount
Definition: vfat.h:592
#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
WCHAR First[]
Definition: FormatMessage.c:11
#define ROUND_UP_64(n, align)
Definition: vfat.h:34
CCHAR PriorityBoost
Definition: vfat.h:594
ERESOURCE * PERESOURCE
Definition: env_spec_w32.h:595
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
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
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1427
VOID VfatPostRead(PVFAT_IRP_CONTEXT IrpContext, PERESOURCE Lock, BOOLEAN PagingIo)
Definition: rw.c:684
_Must_inspect_result_ _In_ WDFUSBPIPE _In_ WDFREQUEST _In_opt_ WDFMEMORY _In_opt_ PWDFMEMORY_OFFSET ReadOffset
Definition: wdfusb.h:1996
_Must_inspect_result_ _In_opt_ PFLT_FILTER Filter
Definition: fltkernel.h:1801
#define FILE_ACTION_MODIFIED
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
_In_ PVOID _In_ ULONG Event
Definition: iotypes.h:467
NTSTATUS VfatWriteDiskPartial(IN PVFAT_IRP_CONTEXT IrpContext, IN PLARGE_INTEGER WriteOffset, IN ULONG WriteLength, IN ULONG BufferOffset, IN BOOLEAN Wait)
Definition: blockdev.c:336
#define OVERFLOW_READ_THRESHHOLD
Definition: rw.c:31
KEVENT Event
Definition: vfat.h:593
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
static NTSTATUS VfatReadFileData(PVFAT_IRP_CONTEXT IrpContext, ULONG Length, LARGE_INTEGER ReadOffset, PULONG LengthRead)
Definition: rw.c:121
Status
Definition: gdiplustypes.h:24
FORCEINLINE BOOLEAN vfatVolumeIsFatX(PDEVICE_EXTENSION DeviceExt)
Definition: vfat.h:651
int Count
Definition: noreturn.cpp:7
PDEVICE_OBJECT DeviceObject
Definition: vfat.h:412
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
#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
BOOLEAN NTAPI FsRtlCheckLockForReadAccess(IN PFILE_LOCK FileLock, IN PIRP Irp)
Definition: filelock.c:676
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
FORCEINLINE NTSTATUS VfatMarkIrpContextForQueue(PVFAT_IRP_CONTEXT IrpContext)
Definition: vfat.h:625
VOID NTAPI FsRtlPostStackOverflow(IN PVOID Context, IN PKEVENT Event, IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine)
Definition: stackovf.c:232
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
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
#define InterlockedDecrement
Definition: armddk.h:52
ULONG dataStart
Definition: vfat.h:258
_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
ERESOURCE MainResource
Definition: ntfs.h:524
NTSTATUS VfatCommonRead(PVFAT_IRP_CONTEXT IrpContext)
Definition: rw.c:547
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 ROUND_DOWN(n, align)
Definition: eventvwr.h:30
NTSTATUS GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:746
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
_SEH2_END
Definition: create.c:4400
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
FORCEINLINE VOID vfatReportChange(IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB Fcb, IN ULONG FilterMatch, IN ULONG Action)
Definition: vfat.h:658
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
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
NTSTATUS VfatRead(PVFAT_IRP_CONTEXT IrpContext)
Definition: rw.c:710
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:159
#define FILE_NOTIFY_CHANGE_ATTRIBUTES
unsigned int * PULONG
Definition: retypes.h:1
#define min(a, b)
Definition: monoChain.cc:55
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
struct tagContext Context
Definition: acpixf.h:1034
VOID NTAPI VfatHandleDeferredWrite(IN PVOID IrpContext, IN PVOID Unused)
Definition: misc.c:221
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:124
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
NTSTATUS VfatReadDiskPartial(IN PVFAT_IRP_CONTEXT IrpContext, IN PLARGE_INTEGER ReadOffset, IN ULONG ReadLength, ULONG BufferOffset, IN BOOLEAN Wait)
Definition: blockdev.c:153
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)
signed int * PLONG
Definition: retypes.h:5
NTSTATUS VfatWrite(PVFAT_IRP_CONTEXT *pIrpContext)
Definition: rw.c:875
ULONGLONG ClusterToSector(PDEVICE_EXTENSION DeviceExt, ULONG Cluster)
Definition: fat.c:733
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
struct _LARGE_INTEGER::@2252 u
NTSTATUS OffsetToCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, ULONG FileOffset, PULONG Cluster, BOOLEAN Extend)
Definition: rw.c:61