ReactOS  0.4.13-dev-257-gfabbd7c
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,
124  LARGE_INTEGER ReadOffset,
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,
336  LARGE_INTEGER WriteOffset)
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 IrpContext)
877 {
878  PVFATFCB Fcb;
881  LARGE_INTEGER OldFileSize;
883  ULONG Length = 0;
884  PVOID Buffer;
885  ULONG BytesPerSector;
886  BOOLEAN PagingIo, CanWait, IsVolume, IsFAT, NoCache;
887 
888  ASSERT(IrpContext);
889 
890  DPRINT("VfatWrite(IrpContext %p)\n", IrpContext);
891 
892  ASSERT(IrpContext->DeviceObject);
893 
894  PagingIo = BooleanFlagOn(IrpContext->Irp->Flags, IRP_PAGING_IO);
895  CanWait = BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT);
896  NoCache = BooleanFlagOn(IrpContext->Irp->Flags, IRP_NOCACHE);
897 
898  // This request is not allowed on the main device object
899  if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
900  {
901  DPRINT("VfatWrite is called with the main device object.\n");
903  goto ByeBye;
904  }
905 
906  ASSERT(IrpContext->DeviceExt);
907  ASSERT(IrpContext->FileObject);
908  Fcb = IrpContext->FileObject->FsContext;
909  ASSERT(Fcb);
910 
911  IsVolume = BooleanFlagOn(Fcb->Flags, FCB_IS_VOLUME);
912  IsFAT = BooleanFlagOn(Fcb->Flags, FCB_IS_FAT);
913 
915  {
916  PFATINFO FatInfo = &IrpContext->DeviceExt->FatInfo;
917  IrpContext->Stack->Parameters.Write.ByteOffset.QuadPart += FatInfo->dataStart * FatInfo->BytesPerSector;
918  IoSkipCurrentIrpStackLocation(IrpContext->Irp);
919  IrpContext->Flags &= ~IRPCONTEXT_COMPLETE;
920  DPRINT("Write to page file, disk offset %I64x\n", IrpContext->Stack->Parameters.Write.ByteOffset.QuadPart);
921  Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, IrpContext->Irp);
922  return Status;
923  }
924 
925  DPRINT("<%wZ>\n", &Fcb->PathNameU);
926 
927  /* fail if file is a directory and no paged read */
928  if (vfatFCBIsDirectory(Fcb) && !PagingIo)
929  {
931  goto ByeBye;
932  }
933 
934  ByteOffset = IrpContext->Stack->Parameters.Write.ByteOffset;
935  if (ByteOffset.u.LowPart == FILE_WRITE_TO_END_OF_FILE &&
936  ByteOffset.u.HighPart == -1)
937  {
938  ByteOffset.QuadPart = Fcb->RFCB.FileSize.QuadPart;
939  }
940  Length = IrpContext->Stack->Parameters.Write.Length;
941  BytesPerSector = IrpContext->DeviceExt->FatInfo.BytesPerSector;
942 
943  if (ByteOffset.u.HighPart && !IsVolume)
944  {
946  goto ByeBye;
947  }
948 
949  if (IsFAT || IsVolume ||
950  vfatDirEntryGetFirstCluster(IrpContext->DeviceExt, &Fcb->entry) == 1)
951  {
952  if (ByteOffset.QuadPart + Length > Fcb->RFCB.FileSize.QuadPart)
953  {
954  // we can't extend the FAT, the volume or the root on FAT12/FAT16
956  goto ByeBye;
957  }
958  }
959 
960  if (PagingIo || NoCache || IsVolume)
961  {
962  if (ByteOffset.u.LowPart % BytesPerSector != 0 || Length % BytesPerSector != 0)
963  {
964  // non cached write must be sector aligned
966  goto ByeBye;
967  }
968  }
969 
970  OldFileSize = Fcb->RFCB.FileSize;
971 
972  if (Length == 0)
973  {
974  /* Update last write time */
975  IrpContext->Irp->IoStatus.Information = 0;
977  goto Metadata;
978  }
979 
980  if (PagingIo)
981  {
982  if (ByteOffset.u.LowPart + Length > Fcb->RFCB.AllocationSize.u.LowPart)
983  {
985  goto ByeBye;
986  }
987 
988  if (ByteOffset.u.LowPart + Length > ROUND_UP(Fcb->RFCB.AllocationSize.u.LowPart, BytesPerSector))
989  {
990  Length = ROUND_UP(Fcb->RFCB.FileSize.u.LowPart, BytesPerSector) - ByteOffset.u.LowPart;
991  }
992  }
993 
994  if (!NoCache && !CcCanIWrite(IrpContext->FileObject, Length, CanWait,
996  {
997  BOOLEAN Retrying;
998 
999  Retrying = BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_DEFERRED_WRITE);
1000  SetFlag(IrpContext->Flags, IRPCONTEXT_DEFERRED_WRITE);
1001 
1004  IrpContext, NULL, Length, Retrying);
1005 
1006  DPRINT1("Dererring write!\n");
1007 
1008  goto ByeBye;
1009  }
1010 
1011  if (IsVolume)
1012  {
1013  Resource = &IrpContext->DeviceExt->DirResource;
1014  }
1015  else if (PagingIo)
1016  {
1018  }
1019  else
1020  {
1022  }
1023 
1024  if (PagingIo)
1025  {
1026  if (!ExAcquireResourceSharedLite(Resource, CanWait))
1027  {
1028  Resource = NULL;
1030  goto ByeBye;
1031  }
1032  }
1033  else
1034  {
1036  {
1037  Resource = NULL;
1039  goto ByeBye;
1040  }
1041  }
1042 
1043  if (!PagingIo &&
1045  {
1046  if (!FsRtlCheckLockForWriteAccess(&Fcb->FileLock, IrpContext->Irp))
1047  {
1049  goto ByeBye;
1050  }
1051  }
1052 
1053  if (!CanWait && !IsVolume)
1054  {
1055  if (ByteOffset.u.LowPart + Length > Fcb->RFCB.AllocationSize.u.LowPart)
1056  {
1058  goto ByeBye;
1059  }
1060  }
1061 
1062  Buffer = VfatGetUserBuffer(IrpContext->Irp, PagingIo);
1063 
1064  if (!IsFAT && !IsVolume && !PagingIo &&
1065  ByteOffset.u.LowPart + Length > Fcb->RFCB.FileSize.u.LowPart)
1066  {
1068 
1069  if (!ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource, CanWait))
1070  {
1072  goto ByeBye;
1073  }
1074 
1075  AllocationSize.QuadPart = ByteOffset.u.LowPart + Length;
1077  IrpContext->DeviceExt, &AllocationSize);
1078 
1079  ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource);
1080 
1081  if (!NT_SUCCESS (Status))
1082  {
1083  goto ByeBye;
1084  }
1085  }
1086 
1087  if (!NoCache && !PagingIo && !IsVolume)
1088  {
1089  // cached write
1090 
1091  vfatAddToStat(IrpContext->DeviceExt, Base.UserFileWrites, 1);
1092  vfatAddToStat(IrpContext->DeviceExt, Base.UserFileWriteBytes, Length);
1093 
1094  _SEH2_TRY
1095  {
1096  if (IrpContext->FileObject->PrivateCacheMap == NULL)
1097  {
1098  CcInitializeCacheMap(IrpContext->FileObject,
1100  FALSE,
1102  Fcb);
1103  }
1104 
1105  if (ByteOffset.QuadPart > OldFileSize.QuadPart)
1106  {
1107  CcZeroData(IrpContext->FileObject, &OldFileSize, &ByteOffset, TRUE);
1108  }
1109 
1110  if (CcCopyWrite(IrpContext->FileObject,
1111  &ByteOffset,
1112  Length,
1113  TRUE /*CanWait*/,
1114  Buffer))
1115  {
1116  IrpContext->Irp->IoStatus.Information = Length;
1118  }
1119  else
1120  {
1121  ASSERT(FALSE );
1123  }
1124  }
1126  {
1128  }
1129  _SEH2_END;
1130  }
1131  else
1132  {
1133  // non cached write
1134  Status = VfatLockUserBuffer(IrpContext->Irp, Length, IoReadAccess);
1135  if (!NT_SUCCESS(Status))
1136  {
1138  goto ByeBye;
1139  }
1140 
1141  if (ByteOffset.QuadPart > OldFileSize.QuadPart)
1142  {
1143  CcZeroData(IrpContext->FileObject, &OldFileSize, &ByteOffset, TRUE);
1144  }
1145 
1146  if (!IsVolume)
1147  {
1148  vfatAddToStat(IrpContext->DeviceExt, Fat.NonCachedWrites, 1);
1149  vfatAddToStat(IrpContext->DeviceExt, Fat.NonCachedWriteBytes, Length);
1150  }
1151  else
1152  {
1153  vfatAddToStat(IrpContext->DeviceExt, Base.MetaDataWrites, 1);
1154  vfatAddToStat(IrpContext->DeviceExt, Base.MetaDataWriteBytes, Length);
1155  }
1156 
1157  Status = VfatWriteFileData(IrpContext, Length, ByteOffset);
1158  if (NT_SUCCESS(Status))
1159  {
1160  IrpContext->Irp->IoStatus.Information = Length;
1161  }
1162  }
1163 
1164 Metadata:
1165  if (!PagingIo && !IsFAT && !IsVolume)
1166  {
1167  if(!vfatFCBIsDirectory(Fcb))
1168  {
1169  LARGE_INTEGER SystemTime;
1170  ULONG Filter;
1171 
1172  // set dates and times
1173  KeQuerySystemTime (&SystemTime);
1174  if (vfatVolumeIsFatX(IrpContext->DeviceExt))
1175  {
1177  &SystemTime, &Fcb->entry.FatX.UpdateDate,
1178  &Fcb->entry.FatX.UpdateTime);
1179  Fcb->entry.FatX.AccessDate = Fcb->entry.FatX.UpdateDate;
1180  Fcb->entry.FatX.AccessTime = Fcb->entry.FatX.UpdateTime;
1181  }
1182  else
1183  {
1185  &SystemTime, &Fcb->entry.Fat.UpdateDate,
1186  &Fcb->entry.Fat.UpdateTime);
1187  Fcb->entry.Fat.AccessDate = Fcb->entry.Fat.UpdateDate;
1188  }
1189  /* set date and times to dirty */
1190  Fcb->Flags |= FCB_IS_DIRTY;
1191 
1192  /* Time to notify the OS */
1194  if (ByteOffset.QuadPart != OldFileSize.QuadPart) Filter |= FILE_NOTIFY_CHANGE_SIZE;
1195 
1197  }
1198  }
1199 
1200 ByeBye:
1201  if (Resource)
1202  {
1204  }
1205 
1206  if (Status == STATUS_PENDING)
1207  {
1208  Status = VfatLockUserBuffer(IrpContext->Irp, Length, IoReadAccess);
1209  if (NT_SUCCESS(Status))
1210  {
1211  Status = VfatMarkIrpContextForQueue(IrpContext);
1212  }
1213  }
1214  else
1215  {
1216  IrpContext->Irp->IoStatus.Status = Status;
1217  if (BooleanFlagOn(IrpContext->FileObject->Flags, FO_SYNCHRONOUS_IO) &&
1218  !PagingIo && NT_SUCCESS(Status))
1219  {
1220  IrpContext->FileObject->CurrentByteOffset.QuadPart =
1221  ByteOffset.QuadPart + IrpContext->Irp->IoStatus.Information;
1222  }
1223 
1224  if (NT_SUCCESS(Status))
1225  IrpContext->PriorityBoost = IO_DISK_INCREMENT;
1226  }
1227  DPRINT("%x\n", Status);
1228  return Status;
1229 }
#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:1207
FILE_LOCK FileLock
Definition: fatstruc.h:1067
#define IN
Definition: typedefs.h:38
NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, PULONG CurrentCluster, BOOLEAN Extend)
Definition: rw.c:40
#define TRUE
Definition: types.h:120
VOID NTAPI Extend(VOID)
Definition: extend.c:14
#define IRPCONTEXT_DEFERRED_WRITE
Definition: vfat.h:573
#define ROUND_UP(n, align)
Definition: eventvwr.h:31
#define FCB_IS_DIRTY
Definition: vfat.h:432
Definition: vfat.h:441
#define DbgPrint
Definition: loader.c:25
#define IRPCONTEXT_COMPLETE
Definition: vfat.h:570
PDEVICE_EXTENSION DeviceExt
Definition: vfat.h:579
ULONG vfatDirEntryGetFirstCluster(PDEVICE_EXTENSION pDeviceExt, PDIR_ENTRY pFatDirEntry)
Definition: direntry.c:19
#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
NTSTATUS VfatWrite(PVFAT_IRP_CONTEXT IrpContext)
Definition: rw.c:875
LONG NTSTATUS
Definition: precomp.h:26
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2327
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:631
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
#define FILE_NOTIFY_CHANGE_SIZE
#define FILE_NOTIFY_CHANGE_LAST_WRITE
#define vfatAddToStat(Vcb, Stat, Inc)
Definition: vfat.h:665
PFILE_OBJECT FileObject
Definition: vfat.h:585
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:4250
ULONG RefCount
Definition: vfat.h:586
#define STATUS_END_OF_FILE
Definition: shellext.h:62
#define FO_SYNCHRONOUS_IO
Definition: iotypes.h:1732
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
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
CCHAR PriorityBoost
Definition: vfat.h:588
ERESOURCE * PERESOURCE
Definition: env_spec_w32.h:595
#define IO_DISK_INCREMENT
Definition: iotypes.h:567
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:848
BOOLEAN NTAPI CcZeroData(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER StartOffset, IN PLARGE_INTEGER EndOffset, IN BOOLEAN Wait)
Definition: fssup.c:412
VOID VfatPostRead(PVFAT_IRP_CONTEXT IrpContext, PERESOURCE Lock, BOOLEAN PagingIo)
Definition: rw.c:684
_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
_In_ PVOID _In_ ULONG Event
Definition: iotypes.h:434
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 EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define OVERFLOW_READ_THRESHHOLD
Definition: rw.c:31
KEVENT Event
Definition: vfat.h:587
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define IRPCONTEXT_CANWAIT
Definition: vfat.h:569
void DPRINT(...)
Definition: polytest.cpp:61
VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1465
Definition: bufpool.h:45
PVOID VfatGetUserBuffer(IN PIRP Irp, IN BOOLEAN Paging)
Definition: misc.c:365
#define FsRtlAreThereCurrentFileLocks(FL)
Definition: fsrtlfuncs.h:1584
FSRTL_COMMON_FCB_HEADER RFCB
Definition: ntfs.h:501
#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
FORCEINLINE BOOLEAN vfatVolumeIsFatX(PDEVICE_EXTENSION DeviceExt)
Definition: vfat.h:645
PDEVICE_OBJECT DeviceObject
Definition: vfat.h:406
NTSTATUS GetNextClusterExtend(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:771
#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:193
#define FCB_IS_PAGE_FILE
Definition: vfat.h:430
BOOLEAN NTAPI FsRtlCheckLockForReadAccess(IN PFILE_LOCK FileLock, IN PIRP Irp)
Definition: filelock.c:676
FORCEINLINE NTSTATUS VfatMarkIrpContextForQueue(PVFAT_IRP_CONTEXT IrpContext)
Definition: vfat.h:619
VOID NTAPI FsRtlPostStackOverflow(IN PVOID Context, IN PKEVENT Event, IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine)
Definition: stackovf.c:232
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
ULONG Flags
Definition: ntfs.h:520
#define FCB_IS_FAT
Definition: vfat.h:429
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
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG IN OUT PLONG IN LONG Increment IN PNDIS_RW_LOCK Lock
Definition: CrNtStubs.h:75
ERESOURCE MainResource
Definition: ntfs.h:512
NTSTATUS VfatCommonRead(PVFAT_IRP_CONTEXT IrpContext)
Definition: rw.c:547
Status
Definition: gdiplustypes.h:24
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:310
PVFAT_GLOBAL_DATA VfatGlobalData
Definition: iface.c:40
CACHE_MANAGER_CALLBACKS CacheMgrCallbacks
Definition: vfat.h:416
#define FCB_IS_VOLUME
Definition: vfat.h:431
#define ROUND_DOWN(n, align)
Definition: eventvwr.h:30
NTSTATUS GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:742
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
_SEH2_END
Definition: create.c:4424
#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:652
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:151
#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:578
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:306
struct _LARGE_INTEGER::@2192 u
VOID NTAPI VfatHandleDeferredWrite(IN PVOID IrpContext, IN PVOID Unused)
Definition: misc.c:218
struct tagContext Context
Definition: acpixf.h:1012
unsigned int ULONG
Definition: retypes.h:1
ERESOURCE PagingIoResource
Definition: ntfs.h:511
ULONG Flags
Definition: vfat.h:580
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2771
_In_ PFCB Fcb
Definition: cdprocs.h:151
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
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:582
return STATUS_SUCCESS
Definition: btrfs.c:2745
NTSTATUS VfatLockUserBuffer(IN PIRP Irp, IN ULONG Length, IN LOCK_OPERATION Operation)
Definition: misc.c:382
signed int * PLONG
Definition: retypes.h:5
ULONGLONG ClusterToSector(PDEVICE_EXTENSION DeviceExt, ULONG Cluster)
Definition: fat.c:729
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:112
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:716
NTSTATUS OffsetToCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, ULONG FileOffset, PULONG Cluster, BOOLEAN Extend)
Definition: rw.c:61