ReactOS 0.4.15-dev-8428-g6910fa6
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");
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 */
117static
120 PVFAT_IRP_CONTEXT IrpContext,
123 PULONG LengthRead)
124{
125 ULONG CurrentCluster;
126 ULONG FirstCluster;
127 ULONG StartCluster;
128 ULONG ClusterCount;
129 LARGE_INTEGER StartOffset;
130 PDEVICE_EXTENSION DeviceExt;
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
329static
332 PVFAT_IRP_CONTEXT IrpContext,
335{
336 PDEVICE_EXTENSION DeviceExt;
338 ULONG Count;
339 ULONG FirstCluster;
340 ULONG CurrentCluster;
341 ULONG BytesDone;
342 ULONG StartCluster;
343 ULONG ClusterCount;
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 {
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 {
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
546 PVFAT_IRP_CONTEXT IrpContext)
547{
551 ULONG Length = 0;
552 ULONG BytesPerSector;
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
592 {
593 if (IrpContext->FileObject->PrivateCacheMap == NULL)
594 {
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
658ByeBye:
659 return Status;
660}
661
662VOID
663NTAPI
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
679}
680
681VOID
683 PVFAT_IRP_CONTEXT IrpContext,
685 BOOLEAN PagingIo)
686{
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
709 PVFAT_IRP_CONTEXT IrpContext)
710{
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;
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
832 {
833 Resource = NULL;
835 goto ByeBye;
836 }
837
838 Status = VfatCommonRead(IrpContext);
839
840ByeBye:
841 if (Resource)
842 {
844 }
845
846 if (Status == STATUS_PENDING)
847 {
849 if (NT_SUCCESS(Status))
850 {
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
874 PVFAT_IRP_CONTEXT *pIrpContext)
875{
876 PVFAT_IRP_CONTEXT IrpContext = *pIrpContext;
880 LARGE_INTEGER OldFileSize;
882 ULONG Length = 0;
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);
912
914 {
915 PFATINFO FatInfo = &IrpContext->DeviceExt->FatInfo;
916 IrpContext->Stack->Parameters.Write.ByteOffset.QuadPart += FatInfo->dataStart * FatInfo->BytesPerSector;
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 {
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
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
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
1165Metadata:
1166 if (!PagingIo && !IsFAT && !IsVolume)
1167 {
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 */
1192
1193 /* Time to notify the OS */
1195 if (ByteOffset.QuadPart != OldFileSize.QuadPart) Filter |= FILE_NOTIFY_CHANGE_SIZE;
1196
1198 }
1199 }
1200
1201ByeBye:
1202 if (Resource)
1203 {
1205 }
1206
1207 if (Status == STATUS_PENDING)
1208 {
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}
WCHAR First[]
Definition: FormatMessage.c:11
unsigned char BOOLEAN
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
_In_ ULONG _In_ BATTERY_QUERY_INFORMATION_LEVEL _In_ LONG _In_ ULONG _Out_ PULONG ReturnedLength
Definition: batclass.h:188
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1430
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
_In_ PFCB Fcb
Definition: cdprocs.h:159
_Acquires_exclusive_lock_ Resource _Acquires_shared_lock_ Resource _Inout_ PERESOURCE Resource
Definition: cdprocs.h:843
Definition: bufpool.h:45
ULONG vfatDirEntryGetFirstCluster(PDEVICE_EXTENSION pDeviceExt, PDIR_ENTRY pFatDirEntry)
Definition: direntry.c:18
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
VOID NTAPI Extend(VOID)
Definition: extend.c:14
#define IRPCONTEXT_CANWAIT
Definition: ntfs.h:474
#define FCB_IS_VOLUME
Definition: ntfs.h:510
BOOLEAN FsdSystemTimeToDosDateTime(PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER SystemTime, PUSHORT pDosDate, PUSHORT pDosTime)
Definition: dir.c:52
NTSTATUS GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:744
NTSTATUS GetNextClusterExtend(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:773
ULONGLONG ClusterToSector(PDEVICE_EXTENSION DeviceExt, ULONG Cluster)
Definition: fat.c:731
NTSTATUS VfatLockUserBuffer(IN PIRP Irp, IN ULONG Length, IN LOCK_OPERATION Operation)
Definition: misc.c:460
VOID NTAPI VfatHandleDeferredWrite(IN PVOID IrpContext, IN PVOID Unused)
Definition: misc.c:220
PVOID VfatGetUserBuffer(IN PIRP Irp, IN BOOLEAN Paging)
Definition: misc.c:443
VOID NTAPI VfatStackOverflowRead(PVOID Context, IN PKEVENT Event)
Definition: rw.c:664
VOID VfatPostRead(PVFAT_IRP_CONTEXT IrpContext, PERESOURCE Lock, BOOLEAN PagingIo)
Definition: rw.c:682
NTSTATUS VfatRead(PVFAT_IRP_CONTEXT IrpContext)
Definition: rw.c:708
NTSTATUS VfatWrite(PVFAT_IRP_CONTEXT *pIrpContext)
Definition: rw.c:873
NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, PULONG CurrentCluster, BOOLEAN Extend)
Definition: rw.c:38
static NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext, ULONG Length, LARGE_INTEGER WriteOffset)
Definition: rw.c:331
#define OVERFLOW_READ_THRESHHOLD
Definition: rw.c:29
static NTSTATUS VfatReadFileData(PVFAT_IRP_CONTEXT IrpContext, ULONG Length, LARGE_INTEGER ReadOffset, PULONG LengthRead)
Definition: rw.c:119
NTSTATUS VfatCommonRead(PVFAT_IRP_CONTEXT IrpContext)
Definition: rw.c:545
NTSTATUS OffsetToCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, ULONG FileOffset, PULONG Cluster, BOOLEAN Extend)
Definition: rw.c:59
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
ERESOURCE * PERESOURCE
Definition: env_spec_w32.h:595
#define ExAcquireResourceSharedLite(res, wait)
Definition: env_spec_w32.h:621
#define ROUND_UP(n, align)
Definition: eventvwr.h:34
#define ROUND_DOWN(n, align)
Definition: eventvwr.h:33
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define FILE_WRITE_TO_END_OF_FILE
Definition: ext2fs.h:278
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:731
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:322
BOOLEAN NTAPI FsRtlCheckLockForWriteAccess(IN PFILE_LOCK FileLock, IN PIRP Irp)
Definition: filelock.c:710
BOOLEAN NTAPI FsRtlCheckLockForReadAccess(IN PFILE_LOCK FileLock, IN PIRP Irp)
Definition: filelock.c:672
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
PVFAT_GLOBAL_DATA VfatGlobalData
Definition: iface.c:18
_Must_inspect_result_ _In_opt_ PFLT_FILTER Filter
Definition: fltkernel.h:1801
#define FsRtlAreThereCurrentFileLocks(FL)
Definition: fsrtlfuncs.h:1584
VOID NTAPI CcInitializeCacheMap(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes, IN BOOLEAN PinAccess, IN PCACHE_MANAGER_CALLBACKS Callbacks, IN PVOID LazyWriteContext)
Definition: fssup.c:195
BOOLEAN NTAPI CcZeroData(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER StartOffset, IN PLARGE_INTEGER EndOffset, IN BOOLEAN Wait)
Definition: fssup.c:414
Status
Definition: gdiplustypes.h:25
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
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
#define DbgPrint
Definition: hal.h:12
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
IoMarkIrpPending(Irp)
#define ASSERT(a)
Definition: mode.c:44
#define min(a, b)
Definition: monoChain.cc:55
#define KernelMode
Definition: asm.h:34
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2451
int Count
Definition: noreturn.cpp:7
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ NotificationEvent
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
BOOLEAN NTAPI CcCopyWrite(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN PVOID Buffer)
Definition: copysup.c:129
BOOLEAN NTAPI CcCanIWrite(IN PFILE_OBJECT FileObject, IN ULONG BytesToWrite, IN BOOLEAN Wait, IN UCHAR Retrying)
Definition: copysup.c:214
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
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
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
#define IoCallDriver
Definition: irp.c:1225
#define STATUS_FILE_LOCK_CONFLICT
Definition: ntstatus.h:320
#define STATUS_PENDING
Definition: ntstatus.h:82
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define STATUS_END_OF_FILE
Definition: shellext.h:67
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
VOID NTAPI FsRtlPostStackOverflow(IN PVOID Context, IN PKEVENT Event, IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine)
Definition: stackovf.c:232
VOID NTAPI FsRtlPostPagingFileStackOverflow(IN PVOID Context, IN PKEVENT Event, IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine)
Definition: stackovf.c:206
PDEVICE_OBJECT StorageDevice
Definition: ntfs.h:110
ERESOURCE DirResource
Definition: ntfs.h:103
FATINFO FatInfo
Definition: vfat.h:324
Definition: vfat.h:250
ULONG dataStart
Definition: vfat.h:258
ULONG BytesPerSector
Definition: vfat.h:261
CACHE_MANAGER_CALLBACKS CacheMgrCallbacks
Definition: vfat.h:422
PDEVICE_OBJECT DeviceObject
Definition: vfat.h:412
CCHAR PriorityBoost
Definition: vfat.h:594
PDEVICE_OBJECT DeviceObject
Definition: vfat.h:584
KEVENT Event
Definition: vfat.h:593
ULONG Flags
Definition: vfat.h:586
PDEVICE_EXTENSION DeviceExt
Definition: vfat.h:585
PIO_STACK_LOCATION Stack
Definition: vfat.h:588
ULONG RefCount
Definition: vfat.h:592
PFILE_OBJECT FileObject
Definition: vfat.h:591
ULONG Flags
Definition: ntfs.h:536
FSRTL_COMMON_FCB_HEADER RFCB
Definition: ntfs.h:517
ERESOURCE PagingIoResource
Definition: ntfs.h:527
FILE_LOCK FileLock
Definition: fatstruc.h:1071
ERESOURCE MainResource
Definition: ntfs.h:528
LARGE_INTEGER AllocationSize
Definition: env_spec_w32.h:755
struct _IO_STACK_LOCATION::@3976::@3981 Write
union _IO_STACK_LOCATION::@1567 Parameters
struct _IO_STACK_LOCATION::@3976::@3980 Read
IO_STATUS_BLOCK IoStatus
Definition: vfat.h:448
uint32_t * PULONG
Definition: typedefs.h:59
#define NTAPI
Definition: typedefs.h:36
#define IN
Definition: typedefs.h:39
int32_t * PLONG
Definition: typedefs.h:58
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
LONGLONG QuadPart
Definition: typedefs.h:114
struct _LARGE_INTEGER::@2291 u
#define IRPCONTEXT_DEFERRED_WRITE
Definition: vfat.h:579
#define vfatAddToStat(Vcb, Stat, Inc)
Definition: vfat.h:671
#define ROUND_UP_64(n, align)
Definition: vfat.h:34
#define FCB_IS_PAGE_FILE
Definition: vfat.h:436
FORCEINLINE BOOLEAN vfatFCBIsDirectory(PVFATFCB FCB)
Definition: vfat.h:637
#define FCB_IS_DIRTY
Definition: vfat.h:438
#define FCB_IS_FAT
Definition: vfat.h:435
FORCEINLINE BOOLEAN vfatVolumeIsFatX(PDEVICE_EXTENSION DeviceExt)
Definition: vfat.h:651
FORCEINLINE NTSTATUS VfatMarkIrpContextForQueue(PVFAT_IRP_CONTEXT IrpContext)
Definition: vfat.h:625
FORCEINLINE VOID vfatReportChange(IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB Fcb, IN ULONG FilterMatch, IN ULONG Action)
Definition: vfat.h:658
NTSTATUS VfatReadDiskPartial(IN PVFAT_IRP_CONTEXT IrpContext, IN PLARGE_INTEGER ReadOffset, IN ULONG ReadLength, ULONG BufferOffset, IN BOOLEAN Wait)
Definition: blockdev.c:151
NTSTATUS VfatWriteDiskPartial(IN PVFAT_IRP_CONTEXT IrpContext, IN PLARGE_INTEGER WriteOffset, IN ULONG WriteLength, IN ULONG BufferOffset, IN BOOLEAN Wait)
Definition: blockdev.c:334
NTSTATUS VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject, PVFATFCB Fcb, PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER AllocationSize)
Definition: finfo.c:1211
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:127
_Must_inspect_result_ _In_ WDFUSBPIPE _In_ WDFREQUEST _In_opt_ WDFMEMORY _In_opt_ PWDFMEMORY_OFFSET ReadOffset
Definition: wdfusb.h:2003
_Must_inspect_result_ _In_ WDFUSBPIPE _In_ WDFREQUEST _In_opt_ WDFMEMORY _In_opt_ PWDFMEMORY_OFFSET WriteOffset
Definition: wdfusb.h:1921
#define FILE_NOTIFY_CHANGE_SIZE
#define FILE_ACTION_MODIFIED
#define IRP_PAGING_IO
#define FILE_NOTIFY_CHANGE_ATTRIBUTES
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
#define FO_SYNCHRONOUS_IO
Definition: iotypes.h:1776
#define FILE_NOTIFY_CHANGE_LAST_WRITE
#define IRP_NOCACHE
@ Executive
Definition: ketypes.h:415
@ IoReadAccess
Definition: ketypes.h:863
@ IoWriteAccess
Definition: ketypes.h:864