ReactOS  0.4.15-dev-5455-g015cd25
rw.c
Go to the documentation of this file.
1 /*
2  * PROJECT: VFAT Filesystem
3  * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE: Reading and writing routines
5  * COPYRIGHT: Copyright 1998 Jason Filby <jasonfilby@yahoo.com>
6  * Copyright 2008-2018 Pierre Schweitzer <pierre@reactos.org>
7  */
8 
9 /* INCLUDES *****************************************************************/
10 
11 #include "vfat.h"
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 /*
17  * Uncomment to enable strict verification of cluster/offset pair
18  * caching. If this option is enabled you lose all the benefits of
19  * the caching and the read/write operations will actually be
20  * slower. It's meant only for debugging!!!
21  * - Filip Navara, 26/07/2004
22  */
23 /* #define DEBUG_VERIFY_OFFSET_CACHING */
24 
25 /* Arbitrary, taken from MS FastFAT, should be
26  * refined given what we experience in common
27  * out of stack operations
28  */
29 #define OVERFLOW_READ_THRESHHOLD 0xE00
30 
31 /* FUNCTIONS *****************************************************************/
32 
33 /*
34  * Return the next cluster in a FAT chain, possibly extending the chain if
35  * necessary
36  */
39  PDEVICE_EXTENSION DeviceExt,
40  ULONG FirstCluster,
41  PULONG CurrentCluster,
43 {
44  if (FirstCluster == 1)
45  {
46  (*CurrentCluster) += DeviceExt->FatInfo.SectorsPerCluster;
47  return STATUS_SUCCESS;
48  }
49  else
50  {
51  if (Extend)
52  return GetNextClusterExtend(DeviceExt, (*CurrentCluster), CurrentCluster);
53  else
54  return GetNextCluster(DeviceExt, (*CurrentCluster), CurrentCluster);
55  }
56 }
57 
60  PDEVICE_EXTENSION DeviceExt,
61  ULONG FirstCluster,
63  PULONG Cluster,
65 {
66  ULONG CurrentCluster;
67  ULONG i;
69 /*
70  DPRINT("OffsetToCluster(DeviceExt %x, Fcb %x, FirstCluster %x,"
71  " FileOffset %x, Cluster %x, Extend %d)\n", DeviceExt,
72  Fcb, FirstCluster, FileOffset, Cluster, Extend);
73 */
74  if (FirstCluster == 0)
75  {
76  DbgPrint("OffsetToCluster is called with FirstCluster = 0!\n");
77  ASSERT(FALSE);
78  }
79 
80  if (FirstCluster == 1)
81  {
82  /* root of FAT16 or FAT12 */
83  *Cluster = DeviceExt->FatInfo.rootStart + FileOffset
84  / (DeviceExt->FatInfo.BytesPerCluster) * DeviceExt->FatInfo.SectorsPerCluster;
85  return STATUS_SUCCESS;
86  }
87  else
88  {
89  CurrentCluster = FirstCluster;
90  if (Extend)
91  {
92  for (i = 0; i < FileOffset / DeviceExt->FatInfo.BytesPerCluster; i++)
93  {
94  Status = GetNextClusterExtend (DeviceExt, CurrentCluster, &CurrentCluster);
95  if (!NT_SUCCESS(Status))
96  return Status;
97  }
98  *Cluster = CurrentCluster;
99  }
100  else
101  {
102  for (i = 0; i < FileOffset / DeviceExt->FatInfo.BytesPerCluster; i++)
103  {
104  Status = GetNextCluster (DeviceExt, CurrentCluster, &CurrentCluster);
105  if (!NT_SUCCESS(Status))
106  return Status;
107  }
108  *Cluster = CurrentCluster;
109  }
110  return STATUS_SUCCESS;
111  }
112 }
113 
114 /*
115  * FUNCTION: Reads data from a file
116  */
117 static
118 NTSTATUS
120  PVFAT_IRP_CONTEXT IrpContext,
121  ULONG Length,
123  PULONG LengthRead)
124 {
125  ULONG CurrentCluster;
126  ULONG FirstCluster;
127  ULONG StartCluster;
128  ULONG ClusterCount;
129  LARGE_INTEGER StartOffset;
130  PDEVICE_EXTENSION DeviceExt;
131  BOOLEAN First = TRUE;
132  PVFATFCB Fcb;
134  ULONG BytesDone;
135  ULONG BytesPerSector;
136  ULONG BytesPerCluster;
137  ULONG LastCluster;
138  ULONG LastOffset;
139 
140  /* PRECONDITION */
141  ASSERT(IrpContext);
142  DeviceExt = IrpContext->DeviceExt;
143  ASSERT(DeviceExt);
144  ASSERT(DeviceExt->FatInfo.BytesPerCluster);
145  ASSERT(IrpContext->FileObject);
146  ASSERT(IrpContext->FileObject->FsContext2 != NULL);
147 
148  DPRINT("VfatReadFileData(DeviceExt %p, FileObject %p, "
149  "Length %u, ReadOffset 0x%I64x)\n", DeviceExt,
150  IrpContext->FileObject, Length, ReadOffset.QuadPart);
151 
152  *LengthRead = 0;
153 
154  Fcb = IrpContext->FileObject->FsContext;
155  BytesPerSector = DeviceExt->FatInfo.BytesPerSector;
156  BytesPerCluster = DeviceExt->FatInfo.BytesPerCluster;
157 
158  ASSERT(ReadOffset.QuadPart + Length <= ROUND_UP_64(Fcb->RFCB.FileSize.QuadPart, BytesPerSector));
159  ASSERT(ReadOffset.u.LowPart % BytesPerSector == 0);
160  ASSERT(Length % BytesPerSector == 0);
161 
162  /* Is this a read of the FAT? */
164  {
165  ReadOffset.QuadPart += DeviceExt->FatInfo.FATStart * BytesPerSector;
166  Status = VfatReadDiskPartial(IrpContext, &ReadOffset, Length, 0, TRUE);
167 
168  if (NT_SUCCESS(Status))
169  {
170  *LengthRead = Length;
171  }
172  else
173  {
174  DPRINT1("FAT reading failed, Status %x\n", Status);
175  }
176  return Status;
177  }
178 
179  /* Is this a read of the Volume ? */
181  {
182  Status = VfatReadDiskPartial(IrpContext, &ReadOffset, Length, 0, TRUE);
183  if (NT_SUCCESS(Status))
184  {
185  *LengthRead = Length;
186  }
187  else
188  {
189  DPRINT1("Volume reading failed, Status %x\n", Status);
190  }
191  return Status;
192  }
193 
194  /* Find the first cluster */
195  FirstCluster =
196  CurrentCluster = vfatDirEntryGetFirstCluster (DeviceExt, &Fcb->entry);
197 
198  if (FirstCluster == 1)
199  {
200  /* Directory of FAT12/16 needs a special handling */
201  if (ReadOffset.u.LowPart + Length > DeviceExt->FatInfo.rootDirectorySectors * BytesPerSector)
202  {
203  Length = DeviceExt->FatInfo.rootDirectorySectors * BytesPerSector - ReadOffset.u.LowPart;
204  }
205  ReadOffset.u.LowPart += DeviceExt->FatInfo.rootStart * BytesPerSector;
206 
207  /* Fire up the read command */
208  Status = VfatReadDiskPartial (IrpContext, &ReadOffset, Length, 0, TRUE);
209  if (NT_SUCCESS(Status))
210  {
211  *LengthRead = Length;
212  }
213  return Status;
214  }
215 
216  ExAcquireFastMutex(&Fcb->LastMutex);
217  LastCluster = Fcb->LastCluster;
218  LastOffset = Fcb->LastOffset;
219  ExReleaseFastMutex(&Fcb->LastMutex);
220 
221  /* Find the cluster to start the read from */
222  if (LastCluster > 0 && ReadOffset.u.LowPart >= LastOffset)
223  {
224  Status = OffsetToCluster(DeviceExt, LastCluster,
225  ROUND_DOWN(ReadOffset.u.LowPart, BytesPerCluster) -
226  LastOffset,
227  &CurrentCluster, FALSE);
228 #ifdef DEBUG_VERIFY_OFFSET_CACHING
229  /* DEBUG VERIFICATION */
230  {
231  ULONG CorrectCluster;
232  OffsetToCluster(DeviceExt, FirstCluster,
233  ROUND_DOWN(ReadOffset.u.LowPart, BytesPerCluster),
234  &CorrectCluster, FALSE);
235  if (CorrectCluster != CurrentCluster)
236  KeBugCheck(FAT_FILE_SYSTEM);
237  }
238 #endif
239  }
240  else
241  {
242  Status = OffsetToCluster(DeviceExt, FirstCluster,
243  ROUND_DOWN(ReadOffset.u.LowPart, BytesPerCluster),
244  &CurrentCluster, FALSE);
245  }
246 
247  if (!NT_SUCCESS(Status))
248  {
249  return Status;
250  }
251 
252  ExAcquireFastMutex(&Fcb->LastMutex);
253  Fcb->LastCluster = CurrentCluster;
254  Fcb->LastOffset = ROUND_DOWN (ReadOffset.u.LowPart, BytesPerCluster);
255  ExReleaseFastMutex(&Fcb->LastMutex);
256 
258  IrpContext->RefCount = 1;
259 
260  while (Length > 0 && CurrentCluster != 0xffffffff)
261  {
262  StartCluster = CurrentCluster;
263  StartOffset.QuadPart = ClusterToSector(DeviceExt, StartCluster) * BytesPerSector;
264  BytesDone = 0;
265  ClusterCount = 0;
266 
267  do
268  {
269  ClusterCount++;
270  if (First)
271  {
272  BytesDone = min (Length, BytesPerCluster - (ReadOffset.u.LowPart % BytesPerCluster));
273  StartOffset.QuadPart += ReadOffset.u.LowPart % BytesPerCluster;
274  First = FALSE;
275  }
276  else
277  {
278  if (Length - BytesDone > BytesPerCluster)
279  {
280  BytesDone += BytesPerCluster;
281  }
282  else
283  {
284  BytesDone = Length;
285  }
286  }
287  Status = NextCluster(DeviceExt, FirstCluster, &CurrentCluster, FALSE);
288  }
289  while (StartCluster + ClusterCount == CurrentCluster && NT_SUCCESS(Status) && Length > BytesDone);
290  DPRINT("start %08x, next %08x, count %u\n",
291  StartCluster, CurrentCluster, ClusterCount);
292 
293  ExAcquireFastMutex(&Fcb->LastMutex);
294  Fcb->LastCluster = StartCluster + (ClusterCount - 1);
295  Fcb->LastOffset = ROUND_DOWN(ReadOffset.u.LowPart, BytesPerCluster) + (ClusterCount - 1) * BytesPerCluster;
296  ExReleaseFastMutex(&Fcb->LastMutex);
297 
298  /* Fire up the read command */
299  Status = VfatReadDiskPartial (IrpContext, &StartOffset, BytesDone, *LengthRead, FALSE);
301  {
302  break;
303  }
304  *LengthRead += BytesDone;
305  Length -= BytesDone;
306  ReadOffset.u.LowPart += BytesDone;
307  }
308 
309  if (InterlockedDecrement((PLONG)&IrpContext->RefCount) != 0)
310  {
312  }
313 
315  {
316  if (Length > 0)
317  {
319  }
320  else
321  {
322  Status = IrpContext->Irp->IoStatus.Status;
323  }
324  }
325 
326  return Status;
327 }
328 
329 static
330 NTSTATUS
332  PVFAT_IRP_CONTEXT IrpContext,
333  ULONG Length,
335 {
336  PDEVICE_EXTENSION DeviceExt;
337  PVFATFCB Fcb;
338  ULONG Count;
339  ULONG FirstCluster;
340  ULONG CurrentCluster;
341  ULONG BytesDone;
342  ULONG StartCluster;
343  ULONG ClusterCount;
345  BOOLEAN First = TRUE;
346  ULONG BytesPerSector;
347  ULONG BytesPerCluster;
348  LARGE_INTEGER StartOffset;
349  ULONG BufferOffset;
350  ULONG LastCluster;
351  ULONG LastOffset;
352 
353  /* PRECONDITION */
354  ASSERT(IrpContext);
355  DeviceExt = IrpContext->DeviceExt;
356  ASSERT(DeviceExt);
357  ASSERT(DeviceExt->FatInfo.BytesPerCluster);
358  ASSERT(IrpContext->FileObject);
359  ASSERT(IrpContext->FileObject->FsContext2 != NULL);
360 
361  Fcb = IrpContext->FileObject->FsContext;
362  BytesPerCluster = DeviceExt->FatInfo.BytesPerCluster;
363  BytesPerSector = DeviceExt->FatInfo.BytesPerSector;
364 
365  DPRINT("VfatWriteFileData(DeviceExt %p, FileObject %p, "
366  "Length %u, WriteOffset 0x%I64x), '%wZ'\n", DeviceExt,
367  IrpContext->FileObject, Length, WriteOffset.QuadPart,
368  &Fcb->PathNameU);
369 
370  ASSERT(WriteOffset.QuadPart + Length <= Fcb->RFCB.AllocationSize.QuadPart);
371  ASSERT(WriteOffset.u.LowPart % BytesPerSector == 0);
372  ASSERT(Length % BytesPerSector == 0);
373 
374  /* Is this a write of the volume? */
376  {
377  Status = VfatWriteDiskPartial(IrpContext, &WriteOffset, Length, 0, TRUE);
378  if (!NT_SUCCESS(Status))
379  {
380  DPRINT1("Volume writing failed, Status %x\n", Status);
381  }
382  return Status;
383  }
384 
385  /* Is this a write to the FAT? */
387  {
388  WriteOffset.u.LowPart += DeviceExt->FatInfo.FATStart * BytesPerSector;
389  IrpContext->RefCount = 1;
390  for (Count = 0; Count < DeviceExt->FatInfo.FATCount; Count++)
391  {
392  Status = VfatWriteDiskPartial(IrpContext, &WriteOffset, Length, 0, FALSE);
394  {
395  DPRINT1("FAT writing failed, Status %x\n", Status);
396  break;
397  }
398  WriteOffset.u.LowPart += Fcb->RFCB.FileSize.u.LowPart;
399  }
400 
401  if (InterlockedDecrement((PLONG)&IrpContext->RefCount) != 0)
402  {
404  }
405 
407  {
408  Status = IrpContext->Irp->IoStatus.Status;
409  }
410  return Status;
411  }
412 
413  /*
414  * Find the first cluster
415  */
416  FirstCluster =
417  CurrentCluster = vfatDirEntryGetFirstCluster (DeviceExt, &Fcb->entry);
418 
419  if (FirstCluster == 1)
420  {
421  ASSERT(WriteOffset.u.LowPart + Length <= DeviceExt->FatInfo.rootDirectorySectors * BytesPerSector);
422  // Directory of FAT12/16 needs a special handling
423  WriteOffset.u.LowPart += DeviceExt->FatInfo.rootStart * BytesPerSector;
424  // Fire up the write command
425  Status = VfatWriteDiskPartial (IrpContext, &WriteOffset, Length, 0, TRUE);
426  return Status;
427  }
428 
429  ExAcquireFastMutex(&Fcb->LastMutex);
430  LastCluster = Fcb->LastCluster;
431  LastOffset = Fcb->LastOffset;
432  ExReleaseFastMutex(&Fcb->LastMutex);
433 
434  /*
435  * Find the cluster to start the write from
436  */
437  if (LastCluster > 0 && WriteOffset.u.LowPart >= LastOffset)
438  {
439  Status = OffsetToCluster(DeviceExt, LastCluster,
440  ROUND_DOWN(WriteOffset.u.LowPart, BytesPerCluster) -
441  LastOffset,
442  &CurrentCluster, FALSE);
443 #ifdef DEBUG_VERIFY_OFFSET_CACHING
444  /* DEBUG VERIFICATION */
445  {
446  ULONG CorrectCluster;
447  OffsetToCluster(DeviceExt, FirstCluster,
448  ROUND_DOWN(WriteOffset.u.LowPart, BytesPerCluster),
449  &CorrectCluster, FALSE);
450  if (CorrectCluster != CurrentCluster)
451  KeBugCheck(FAT_FILE_SYSTEM);
452  }
453 #endif
454  }
455  else
456  {
457  Status = OffsetToCluster(DeviceExt, FirstCluster,
458  ROUND_DOWN(WriteOffset.u.LowPart, BytesPerCluster),
459  &CurrentCluster, FALSE);
460  }
461 
462  if (!NT_SUCCESS(Status))
463  {
464  return Status;
465  }
466 
467  ExAcquireFastMutex(&Fcb->LastMutex);
468  Fcb->LastCluster = CurrentCluster;
469  Fcb->LastOffset = ROUND_DOWN (WriteOffset.u.LowPart, BytesPerCluster);
470  ExReleaseFastMutex(&Fcb->LastMutex);
471 
472  IrpContext->RefCount = 1;
473  BufferOffset = 0;
474 
475  while (Length > 0 && CurrentCluster != 0xffffffff)
476  {
477  StartCluster = CurrentCluster;
478  StartOffset.QuadPart = ClusterToSector(DeviceExt, StartCluster) * BytesPerSector;
479  BytesDone = 0;
480  ClusterCount = 0;
481 
482  do
483  {
484  ClusterCount++;
485  if (First)
486  {
487  BytesDone = min (Length, BytesPerCluster - (WriteOffset.u.LowPart % BytesPerCluster));
488  StartOffset.QuadPart += WriteOffset.u.LowPart % BytesPerCluster;
489  First = FALSE;
490  }
491  else
492  {
493  if (Length - BytesDone > BytesPerCluster)
494  {
495  BytesDone += BytesPerCluster;
496  }
497  else
498  {
499  BytesDone = Length;
500  }
501  }
502  Status = NextCluster(DeviceExt, FirstCluster, &CurrentCluster, FALSE);
503  }
504  while (StartCluster + ClusterCount == CurrentCluster && NT_SUCCESS(Status) && Length > BytesDone);
505  DPRINT("start %08x, next %08x, count %u\n",
506  StartCluster, CurrentCluster, ClusterCount);
507 
508  ExAcquireFastMutex(&Fcb->LastMutex);
509  Fcb->LastCluster = StartCluster + (ClusterCount - 1);
510  Fcb->LastOffset = ROUND_DOWN(WriteOffset.u.LowPart, BytesPerCluster) + (ClusterCount - 1) * BytesPerCluster;
511  ExReleaseFastMutex(&Fcb->LastMutex);
512 
513  // Fire up the write command
514  Status = VfatWriteDiskPartial (IrpContext, &StartOffset, BytesDone, BufferOffset, FALSE);
516  {
517  break;
518  }
519  BufferOffset += BytesDone;
520  Length -= BytesDone;
521  WriteOffset.u.LowPart += BytesDone;
522  }
523 
524  if (InterlockedDecrement((PLONG)&IrpContext->RefCount) != 0)
525  {
527  }
528 
530  {
531  if (Length > 0)
532  {
534  }
535  else
536  {
537  Status = IrpContext->Irp->IoStatus.Status;
538  }
539  }
540 
541  return Status;
542 }
543 
544 NTSTATUS
546  PVFAT_IRP_CONTEXT IrpContext)
547 {
548  PVFATFCB Fcb;
549  PVOID Buffer;
551  ULONG Length = 0;
552  ULONG BytesPerSector;
554  ULONG ReturnedLength = 0;
555  BOOLEAN PagingIo, CanWait, IsVolume, NoCache;
556 
557  PagingIo = BooleanFlagOn(IrpContext->Irp->Flags, IRP_PAGING_IO);
558  CanWait = BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT);
559  NoCache = BooleanFlagOn(IrpContext->Irp->Flags, IRP_NOCACHE);
560  Fcb = IrpContext->FileObject->FsContext;
561  IsVolume = BooleanFlagOn(Fcb->Flags, FCB_IS_VOLUME);
562 
563  ByteOffset = IrpContext->Stack->Parameters.Read.ByteOffset;
564  Length = IrpContext->Stack->Parameters.Read.Length;
565  BytesPerSector = IrpContext->DeviceExt->FatInfo.BytesPerSector;
566 
567  if (!PagingIo &&
569  {
570  if (!FsRtlCheckLockForReadAccess(&Fcb->FileLock, IrpContext->Irp))
571  {
573  }
574  }
575 
576  Buffer = VfatGetUserBuffer(IrpContext->Irp, PagingIo);
577 
578  if (!PagingIo && !NoCache && !IsVolume)
579  {
580  // cached read
582  if (ByteOffset.u.LowPart + Length > Fcb->RFCB.FileSize.u.LowPart)
583  {
584  Length = Fcb->RFCB.FileSize.u.LowPart - ByteOffset.u.LowPart;
585  Status = /*STATUS_END_OF_FILE*/STATUS_SUCCESS;
586  }
587 
588  vfatAddToStat(IrpContext->DeviceExt, Base.UserFileReads, 1);
589  vfatAddToStat(IrpContext->DeviceExt, Base.UserFileReadBytes, Length);
590 
591  _SEH2_TRY
592  {
593  if (IrpContext->FileObject->PrivateCacheMap == NULL)
594  {
595  CcInitializeCacheMap(IrpContext->FileObject,
597  FALSE,
599  Fcb);
600  }
601 
602  if (!CcCopyRead(IrpContext->FileObject,
603  &ByteOffset,
604  Length,
605  CanWait,
606  Buffer,
607  &IrpContext->Irp->IoStatus))
608  {
609  ASSERT(!CanWait);
611  goto ByeBye;
612  }
613  }
615  {
617  goto ByeBye;
618  }
619  _SEH2_END;
620 
621  if (!NT_SUCCESS(IrpContext->Irp->IoStatus.Status))
622  {
623  Status = IrpContext->Irp->IoStatus.Status;
624  }
625  }
626  else
627  {
628  // non cached read
630  if (!NT_SUCCESS(Status))
631  {
632  goto ByeBye;
633  }
634 
635  if (ByteOffset.QuadPart + Length > ROUND_UP_64(Fcb->RFCB.FileSize.QuadPart, BytesPerSector))
636  {
637  Length = (ULONG)(ROUND_UP_64(Fcb->RFCB.FileSize.QuadPart, BytesPerSector) - ByteOffset.QuadPart);
638  }
639 
640  if (!IsVolume)
641  {
642  vfatAddToStat(IrpContext->DeviceExt, Fat.NonCachedReads, 1);
643  vfatAddToStat(IrpContext->DeviceExt, Fat.NonCachedReadBytes, Length);
644  }
645  else
646  {
647  vfatAddToStat(IrpContext->DeviceExt, Base.MetaDataReads, 1);
648  vfatAddToStat(IrpContext->DeviceExt, Base.MetaDataReadBytes, Length);
649  }
650 
652  if (NT_SUCCESS(Status))
653  {
654  IrpContext->Irp->IoStatus.Information = ReturnedLength;
655  }
656  }
657 
658 ByeBye:
659  return Status;
660 }
661 
662 VOID
663 NTAPI
665  PVOID Context,
666  IN PKEVENT Event)
667 {
668  PVFAT_IRP_CONTEXT IrpContext;
669 
670  IrpContext = Context;
671  /* In a separate thread, we can wait and resources got locked */
672  SetFlag(IrpContext->Flags, IRPCONTEXT_CANWAIT);
673 
674  /* Perform the read operation */
675  DPRINT1("Performing posted read\n");
676  VfatCommonRead(IrpContext);
677 
678  KeSetEvent(Event, 0, FALSE);
679 }
680 
681 VOID
683  PVFAT_IRP_CONTEXT IrpContext,
685  BOOLEAN PagingIo)
686 {
687  KEVENT Event;
688 
690 
692 
693  /* If paging IO, call the non failing but blocking routine */
694  if (PagingIo)
695  {
697  }
698  else
699  {
701  }
702 
703  /* Wait till it's done */
705 }
706 
707 NTSTATUS
709  PVFAT_IRP_CONTEXT IrpContext)
710 {
712  PVFATFCB Fcb;
713  ULONG Length = 0;
716  ULONG BytesPerSector;
717  BOOLEAN PagingIo, CanWait, IsVolume, NoCache;
718 
719  ASSERT(IrpContext);
720 
721  DPRINT("VfatRead(IrpContext %p)\n", IrpContext);
722 
723  ASSERT(IrpContext->DeviceObject);
724 
725  PagingIo = BooleanFlagOn(IrpContext->Irp->Flags, IRP_PAGING_IO);
726  CanWait = BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT);
727  NoCache = BooleanFlagOn(IrpContext->Irp->Flags, IRP_NOCACHE);
728 
729  // This request is not allowed on the main device object
730  if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
731  {
732  DPRINT("VfatRead is called with the main device object.\n");
734  goto ByeBye;
735  }
736 
737  ASSERT(IrpContext->DeviceExt);
738  ASSERT(IrpContext->FileObject);
739  Fcb = IrpContext->FileObject->FsContext;
740  ASSERT(Fcb);
741 
742  IsVolume = BooleanFlagOn(Fcb->Flags, FCB_IS_VOLUME);
743 
745  {
746  PFATINFO FatInfo = &IrpContext->DeviceExt->FatInfo;
747  IrpContext->Stack->Parameters.Read.ByteOffset.QuadPart += FatInfo->dataStart * FatInfo->BytesPerSector;
748  IoSkipCurrentIrpStackLocation(IrpContext->Irp);
749  IrpContext->Flags &= ~IRPCONTEXT_COMPLETE;
750  DPRINT("Read from page file, disk offset %I64x\n", IrpContext->Stack->Parameters.Read.ByteOffset.QuadPart);
751  Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, IrpContext->Irp);
752  return Status;
753  }
754 
755  DPRINT("<%wZ>\n", &Fcb->PathNameU);
756 
757  ByteOffset = IrpContext->Stack->Parameters.Read.ByteOffset;
758  Length = IrpContext->Stack->Parameters.Read.Length;
759  BytesPerSector = IrpContext->DeviceExt->FatInfo.BytesPerSector;
760 
761  /* fail if file is a directory and no paged read */
762  if (vfatFCBIsDirectory(Fcb) && !PagingIo)
763  {
765  goto ByeBye;
766  }
767 
768  DPRINT("'%wZ', Offset: %u, Length %u\n", &Fcb->PathNameU, ByteOffset.u.LowPart, Length);
769 
770  if (ByteOffset.u.HighPart && !IsVolume)
771  {
773  goto ByeBye;
774  }
775 
776  if (Length == 0)
777  {
778  IrpContext->Irp->IoStatus.Information = 0;
780  goto ByeBye;
781  }
782 
783  if (ByteOffset.QuadPart >= Fcb->RFCB.FileSize.QuadPart)
784  {
785  IrpContext->Irp->IoStatus.Information = 0;
787  goto ByeBye;
788  }
789 
790  if (NoCache || PagingIo || IsVolume)
791  {
792  if (ByteOffset.u.LowPart % BytesPerSector != 0 || Length % BytesPerSector != 0)
793  {
794  DPRINT("%u %u\n", ByteOffset.u.LowPart, Length);
795  // non cached read must be sector aligned
797  goto ByeBye;
798  }
799  }
800 
801  if (IsVolume)
802  {
803  Resource = &IrpContext->DeviceExt->DirResource;
804  }
805  else if (PagingIo)
806  {
808  }
809  else
810  {
812  }
813 
814  /* Are we out of stack for the rest of the operation? */
815  if (IoGetRemainingStackSize() < OVERFLOW_READ_THRESHHOLD)
816  {
817  /* Lock the buffer */
819  if (!NT_SUCCESS(Status))
820  {
821  return Status;
822  }
823 
824  /* And post the read to the overflow thread */
825  VfatPostRead(IrpContext, Resource, PagingIo);
826 
827  /* Return the appropriate status */
828  return IrpContext->Irp->IoStatus.Status;
829  }
830 
831  if (!ExAcquireResourceSharedLite(Resource, CanWait))
832  {
833  Resource = NULL;
835  goto ByeBye;
836  }
837 
838  Status = VfatCommonRead(IrpContext);
839 
840 ByeBye:
841  if (Resource)
842  {
844  }
845 
846  if (Status == STATUS_PENDING)
847  {
849  if (NT_SUCCESS(Status))
850  {
851  Status = VfatMarkIrpContextForQueue(IrpContext);
852  }
853  }
854  else
855  {
856  IrpContext->Irp->IoStatus.Status = Status;
857  if (BooleanFlagOn(IrpContext->FileObject->Flags, FO_SYNCHRONOUS_IO) &&
858  !PagingIo &&
860  {
861  IrpContext->FileObject->CurrentByteOffset.QuadPart =
862  ByteOffset.QuadPart + IrpContext->Irp->IoStatus.Information;
863  }
864 
865  if (NT_SUCCESS(Status))
866  IrpContext->PriorityBoost = IO_DISK_INCREMENT;
867  }
868  DPRINT("%x\n", Status);
869  return Status;
870 }
871 
872 NTSTATUS
874  PVFAT_IRP_CONTEXT *pIrpContext)
875 {
876  PVFAT_IRP_CONTEXT IrpContext = *pIrpContext;
877  PVFATFCB Fcb;
880  LARGE_INTEGER OldFileSize;
882  ULONG Length = 0;
883  PVOID Buffer;
884  ULONG BytesPerSector;
885  BOOLEAN PagingIo, CanWait, IsVolume, IsFAT, NoCache;
886 
887  ASSERT(IrpContext);
888 
889  DPRINT("VfatWrite(IrpContext %p)\n", IrpContext);
890 
891  ASSERT(IrpContext->DeviceObject);
892 
893  PagingIo = BooleanFlagOn(IrpContext->Irp->Flags, IRP_PAGING_IO);
894  CanWait = BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT);
895  NoCache = BooleanFlagOn(IrpContext->Irp->Flags, IRP_NOCACHE);
896 
897  // This request is not allowed on the main device object
898  if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
899  {
900  DPRINT("VfatWrite is called with the main device object.\n");
902  goto ByeBye;
903  }
904 
905  ASSERT(IrpContext->DeviceExt);
906  ASSERT(IrpContext->FileObject);
907  Fcb = IrpContext->FileObject->FsContext;
908  ASSERT(Fcb);
909 
910  IsVolume = BooleanFlagOn(Fcb->Flags, FCB_IS_VOLUME);
911  IsFAT = BooleanFlagOn(Fcb->Flags, FCB_IS_FAT);
912 
914  {
915  PFATINFO FatInfo = &IrpContext->DeviceExt->FatInfo;
916  IrpContext->Stack->Parameters.Write.ByteOffset.QuadPart += FatInfo->dataStart * FatInfo->BytesPerSector;
917  IoSkipCurrentIrpStackLocation(IrpContext->Irp);
918  IrpContext->Flags &= ~IRPCONTEXT_COMPLETE;
919  DPRINT("Write to page file, disk offset %I64x\n", IrpContext->Stack->Parameters.Write.ByteOffset.QuadPart);
920  Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, IrpContext->Irp);
921  return Status;
922  }
923 
924  DPRINT("<%wZ>\n", &Fcb->PathNameU);
925 
926  /* fail if file is a directory and no paged read */
927  if (vfatFCBIsDirectory(Fcb) && !PagingIo)
928  {
930  goto ByeBye;
931  }
932 
933  ByteOffset = IrpContext->Stack->Parameters.Write.ByteOffset;
934  if (ByteOffset.u.LowPart == FILE_WRITE_TO_END_OF_FILE &&
935  ByteOffset.u.HighPart == -1)
936  {
937  ByteOffset.QuadPart = Fcb->RFCB.FileSize.QuadPart;
938  }
939  Length = IrpContext->Stack->Parameters.Write.Length;
940  BytesPerSector = IrpContext->DeviceExt->FatInfo.BytesPerSector;
941 
942  if (ByteOffset.u.HighPart && !IsVolume)
943  {
945  goto ByeBye;
946  }
947 
948  if (IsFAT || IsVolume ||
949  vfatDirEntryGetFirstCluster(IrpContext->DeviceExt, &Fcb->entry) == 1)
950  {
951  if (ByteOffset.QuadPart + Length > Fcb->RFCB.FileSize.QuadPart)
952  {
953  // we can't extend the FAT, the volume or the root on FAT12/FAT16
955  goto ByeBye;
956  }
957  }
958 
959  if (PagingIo || NoCache || IsVolume)
960  {
961  if (ByteOffset.u.LowPart % BytesPerSector != 0 || Length % BytesPerSector != 0)
962  {
963  // non cached write must be sector aligned
965  goto ByeBye;
966  }
967  }
968 
969  OldFileSize = Fcb->RFCB.FileSize;
970 
971  if (Length == 0)
972  {
973  /* Update last write time */
974  IrpContext->Irp->IoStatus.Information = 0;
976  goto Metadata;
977  }
978 
979  if (PagingIo)
980  {
981  if (ByteOffset.u.LowPart + Length > Fcb->RFCB.AllocationSize.u.LowPart)
982  {
984  goto ByeBye;
985  }
986 
987  if (ByteOffset.u.LowPart + Length > ROUND_UP(Fcb->RFCB.AllocationSize.u.LowPart, BytesPerSector))
988  {
989  Length = ROUND_UP(Fcb->RFCB.FileSize.u.LowPart, BytesPerSector) - ByteOffset.u.LowPart;
990  }
991  }
992 
993  if (!NoCache && !CcCanIWrite(IrpContext->FileObject, Length, CanWait,
995  {
996  BOOLEAN Retrying;
997 
998  Retrying = BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_DEFERRED_WRITE);
1000 
1001  IoMarkIrpPending(IrpContext->Irp);
1003 
1004  DPRINT1("Deferring write for Irp %p, context %p!\n", IrpContext->Irp, IrpContext);
1006  IrpContext, NULL, Length, Retrying);
1007  *pIrpContext = NULL;
1008 
1009  return Status;
1010  }
1011 
1012  if (IsVolume)
1013  {
1014  Resource = &IrpContext->DeviceExt->DirResource;
1015  }
1016  else if (PagingIo)
1017  {
1019  }
1020  else
1021  {
1023  }
1024 
1025  if (PagingIo)
1026  {
1027  if (!ExAcquireResourceSharedLite(Resource, CanWait))
1028  {
1029  Resource = NULL;
1031  goto ByeBye;
1032  }
1033  }
1034  else
1035  {
1037  {
1038  Resource = NULL;
1040  goto ByeBye;
1041  }
1042  }
1043 
1044  if (!PagingIo &&
1046  {
1047  if (!FsRtlCheckLockForWriteAccess(&Fcb->FileLock, IrpContext->Irp))
1048  {
1050  goto ByeBye;
1051  }
1052  }
1053 
1054  if (!CanWait && !IsVolume)
1055  {
1056  if (ByteOffset.u.LowPart + Length > Fcb->RFCB.AllocationSize.u.LowPart)
1057  {
1059  goto ByeBye;
1060  }
1061  }
1062 
1063  Buffer = VfatGetUserBuffer(IrpContext->Irp, PagingIo);
1064 
1065  if (!IsFAT && !IsVolume && !PagingIo &&
1066  ByteOffset.u.LowPart + Length > Fcb->RFCB.FileSize.u.LowPart)
1067  {
1069 
1070  if (!ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource, CanWait))
1071  {
1073  goto ByeBye;
1074  }
1075 
1076  AllocationSize.QuadPart = ByteOffset.u.LowPart + Length;
1078  IrpContext->DeviceExt, &AllocationSize);
1079 
1080  ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource);
1081 
1082  if (!NT_SUCCESS (Status))
1083  {
1084  goto ByeBye;
1085  }
1086  }
1087 
1088  if (!NoCache && !PagingIo && !IsVolume)
1089  {
1090  // cached write
1091 
1092  vfatAddToStat(IrpContext->DeviceExt, Base.UserFileWrites, 1);
1093  vfatAddToStat(IrpContext->DeviceExt, Base.UserFileWriteBytes, Length);
1094 
1095  _SEH2_TRY
1096  {
1097  if (IrpContext->FileObject->PrivateCacheMap == NULL)
1098  {
1099  CcInitializeCacheMap(IrpContext->FileObject,
1101  FALSE,
1103  Fcb);
1104  }
1105 
1106  if (ByteOffset.QuadPart > OldFileSize.QuadPart)
1107  {
1108  CcZeroData(IrpContext->FileObject, &OldFileSize, &ByteOffset, TRUE);
1109  }
1110 
1111  if (CcCopyWrite(IrpContext->FileObject,
1112  &ByteOffset,
1113  Length,
1114  TRUE /*CanWait*/,
1115  Buffer))
1116  {
1117  IrpContext->Irp->IoStatus.Information = Length;
1119  }
1120  else
1121  {
1122  ASSERT(FALSE );
1124  }
1125  }
1127  {
1129  }
1130  _SEH2_END;
1131  }
1132  else
1133  {
1134  // non cached write
1135  Status = VfatLockUserBuffer(IrpContext->Irp, Length, IoReadAccess);
1136  if (!NT_SUCCESS(Status))
1137  {
1139  goto ByeBye;
1140  }
1141 
1142  if (ByteOffset.QuadPart > OldFileSize.QuadPart)
1143  {
1144  CcZeroData(IrpContext->FileObject, &OldFileSize, &ByteOffset, TRUE);
1145  }
1146 
1147  if (!IsVolume)
1148  {
1149  vfatAddToStat(IrpContext->DeviceExt, Fat.NonCachedWrites, 1);
1150  vfatAddToStat(IrpContext->DeviceExt, Fat.NonCachedWriteBytes, Length);
1151  }
1152  else
1153  {
1154  vfatAddToStat(IrpContext->DeviceExt, Base.MetaDataWrites, 1);
1155  vfatAddToStat(IrpContext->DeviceExt, Base.MetaDataWriteBytes, Length);
1156  }
1157 
1158  Status = VfatWriteFileData(IrpContext, Length, ByteOffset);
1159  if (NT_SUCCESS(Status))
1160  {
1161  IrpContext->Irp->IoStatus.Information = Length;
1162  }
1163  }
1164 
1165 Metadata:
1166  if (!PagingIo && !IsFAT && !IsVolume)
1167  {
1168  if(!vfatFCBIsDirectory(Fcb))
1169  {
1170  LARGE_INTEGER SystemTime;
1171  ULONG Filter;
1172 
1173  // set dates and times
1174  KeQuerySystemTime (&SystemTime);
1175  if (vfatVolumeIsFatX(IrpContext->DeviceExt))
1176  {
1178  &SystemTime, &Fcb->entry.FatX.UpdateDate,
1179  &Fcb->entry.FatX.UpdateTime);
1180  Fcb->entry.FatX.AccessDate = Fcb->entry.FatX.UpdateDate;
1181  Fcb->entry.FatX.AccessTime = Fcb->entry.FatX.UpdateTime;
1182  }
1183  else
1184  {
1186  &SystemTime, &Fcb->entry.Fat.UpdateDate,
1187  &Fcb->entry.Fat.UpdateTime);
1188  Fcb->entry.Fat.AccessDate = Fcb->entry.Fat.UpdateDate;
1189  }
1190  /* set date and times to dirty */
1191  Fcb->Flags |= FCB_IS_DIRTY;
1192 
1193  /* Time to notify the OS */
1195  if (ByteOffset.QuadPart != OldFileSize.QuadPart) Filter |= FILE_NOTIFY_CHANGE_SIZE;
1196 
1198  }
1199  }
1200 
1201 ByeBye:
1202  if (Resource)
1203  {
1205  }
1206 
1207  if (Status == STATUS_PENDING)
1208  {
1209  Status = VfatLockUserBuffer(IrpContext->Irp, Length, IoReadAccess);
1210  if (NT_SUCCESS(Status))
1211  {
1212  Status = VfatMarkIrpContextForQueue(IrpContext);
1213  }
1214  }
1215  else
1216  {
1217  IrpContext->Irp->IoStatus.Status = Status;
1218  if (BooleanFlagOn(IrpContext->FileObject->Flags, FO_SYNCHRONOUS_IO) &&
1219  !PagingIo && NT_SUCCESS(Status))
1220  {
1221  IrpContext->FileObject->CurrentByteOffset.QuadPart =
1222  ByteOffset.QuadPart + IrpContext->Irp->IoStatus.Information;
1223  }
1224 
1225  if (NT_SUCCESS(Status))
1226  IrpContext->PriorityBoost = IO_DISK_INCREMENT;
1227  }
1228  DPRINT("%x\n", Status);
1229  return Status;
1230 }
struct _LARGE_INTEGER::@2253 u
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
_SEH2_TRY
Definition: create.c:4226
PVOID VfatGetUserBuffer(IN PIRP Irp, IN BOOLEAN Paging)
Definition: misc.c:443
FILE_LOCK FileLock
Definition: fatstruc.h:1071
#define IN
Definition: typedefs.h:39
NTSTATUS VfatCommonRead(PVFAT_IRP_CONTEXT IrpContext)
Definition: rw.c:545
VOID NTAPI VfatStackOverflowRead(PVOID Context, IN PKEVENT Event)
Definition: rw.c:664
BOOLEAN FsdSystemTimeToDosDateTime(PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER SystemTime, PUSHORT pDosDate, PUSHORT pDosTime)
Definition: dir.c:52
NTSTATUS VfatWrite(PVFAT_IRP_CONTEXT *pIrpContext)
Definition: rw.c:873
VOID NTAPI Extend(VOID)
Definition: extend.c:14
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
static NTSTATUS VfatReadFileData(PVFAT_IRP_CONTEXT IrpContext, ULONG Length, LARGE_INTEGER ReadOffset, PULONG LengthRead)
Definition: rw.c:119
NTSTATUS VfatReadDiskPartial(IN PVFAT_IRP_CONTEXT IrpContext, IN PLARGE_INTEGER ReadOffset, IN ULONG ReadLength, ULONG BufferOffset, IN BOOLEAN Wait)
Definition: blockdev.c:151
#define IRPCONTEXT_DEFERRED_WRITE
Definition: vfat.h:579
#define ROUND_UP(n, align)
Definition: eventvwr.h:34
#define FCB_IS_DIRTY
Definition: vfat.h:438
#define DbgPrint
Definition: hal.h:12
Definition: vfat.h:447
NTSTATUS VfatLockUserBuffer(IN PIRP Irp, IN ULONG Length, IN LOCK_OPERATION Operation)
Definition: misc.c:460
NTSTATUS GetNextClusterExtend(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:773
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:18
#define TRUE
Definition: types.h:120
#define IRPCONTEXT_COMPLETE
Definition: ntfs.h:475
#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:710
VOID VfatPostRead(PVFAT_IRP_CONTEXT IrpContext, PERESOURCE Lock, BOOLEAN PagingIo)
Definition: rw.c:682
_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:2427
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
VOID NTAPI VfatHandleDeferredWrite(IN PVOID IrpContext, IN PVOID Unused)
Definition: misc.c:220
#define FILE_NOTIFY_CHANGE_SIZE
#define FILE_NOTIFY_CHANGE_LAST_WRITE
#define vfatAddToStat(Vcb, Stat, Inc)
Definition: vfat.h:671
ULONGLONG ClusterToSector(PDEVICE_EXTENSION DeviceExt, ULONG Cluster)
Definition: fat.c:731
IO_STATUS_BLOCK IoStatus
_SEH2_END
Definition: create.c:4400
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
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
ULONG RefCount
Definition: vfat.h:592
#define STATUS_END_OF_FILE
Definition: shellext.h:67
#define FO_SYNCHRONOUS_IO
Definition: iotypes.h:1776
static NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext, ULONG Length, LARGE_INTEGER WriteOffset)
Definition: rw.c:331
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
_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
_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
NTSTATUS VfatRead(PVFAT_IRP_CONTEXT IrpContext)
Definition: rw.c:708
#define FILE_ACTION_MODIFIED
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
_In_ PVOID _In_ ULONG Event
Definition: iotypes.h:467
KEVENT Event
Definition: vfat.h:593
unsigned char BOOLEAN
Definition: bufpool.h:45
#define FsRtlAreThereCurrentFileLocks(FL)
Definition: fsrtlfuncs.h:1584
FSRTL_COMMON_FCB_HEADER RFCB
Definition: ntfs.h:517
#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
NTSTATUS VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject, PVFATFCB Fcb, PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER AllocationSize)
Definition: finfo.c:1211
int Count
Definition: noreturn.cpp:7
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
BOOLEAN NTAPI FsRtlCheckLockForReadAccess(IN PFILE_LOCK FileLock, IN PIRP Irp)
Definition: filelock.c:672
#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
NTSTATUS VfatWriteDiskPartial(IN PVFAT_IRP_CONTEXT IrpContext, IN PLARGE_INTEGER WriteOffset, IN ULONG WriteLength, IN ULONG BufferOffset, IN BOOLEAN Wait)
Definition: blockdev.c:334
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
ULONG Flags
Definition: ntfs.h:536
#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:528
NTSTATUS OffsetToCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, ULONG FileOffset, PULONG Cluster, BOOLEAN Extend)
Definition: rw.c:59
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
CACHE_MANAGER_CALLBACKS CacheMgrCallbacks
Definition: vfat.h:422
#define ROUND_DOWN(n, align)
Definition: eventvwr.h:33
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#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
PVFAT_GLOBAL_DATA VfatGlobalData
Definition: iface.c:18
_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 OVERFLOW_READ_THRESHHOLD
Definition: rw.c:29
#define FCB_IS_VOLUME
Definition: ntfs.h:510
#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
NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, PULONG CurrentCluster, BOOLEAN Extend)
Definition: rw.c:38
#define STATUS_FILE_LOCK_CONFLICT
Definition: ntstatus.h:320
struct tagContext Context
Definition: acpixf.h:1038
_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:527
ULONG Flags
Definition: vfat.h:586
#define IRPCONTEXT_CANWAIT
Definition: ntfs.h:474
#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
IoMarkIrpPending(Irp)
signed int * PLONG
Definition: retypes.h:5
NTSTATUS GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:744
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