ReactOS 0.4.15-dev-7953-g1f49173
finfo.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: File information routines
5 * COPYRIGHT: Copyright 1998 Jason Filby <jasonfilby@yahoo.com>
6 * Copyright 2005 Hervé Poussineau <hpoussin@reactos.org>
7 * Copyright 2008-2018 Pierre Schweitzer <pierre@reactos.org>
8 */
9
10/* INCLUDES *****************************************************************/
11
12#include "vfat.h"
13
14#define NDEBUG
15#include <debug.h>
16
17#define NASSERTS_RENAME
18
19/* GLOBALS ******************************************************************/
20
22{
23 "??????",
24 "FileDirectoryInformation",
25 "FileFullDirectoryInformation",
26 "FileBothDirectoryInformation",
27 "FileBasicInformation",
28 "FileStandardInformation",
29 "FileInternalInformation",
30 "FileEaInformation",
31 "FileAccessInformation",
32 "FileNameInformation",
33 "FileRenameInformation",
34 "FileLinkInformation",
35 "FileNamesInformation",
36 "FileDispositionInformation",
37 "FilePositionInformation",
38 "FileFullEaInformation",
39 "FileModeInformation",
40 "FileAlignmentInformation",
41 "FileAllInformation",
42 "FileAllocationInformation",
43 "FileEndOfFileInformation",
44 "FileAlternateNameInformation",
45 "FileStreamInformation",
46 "FilePipeInformation",
47 "FilePipeLocalInformation",
48 "FilePipeRemoteInformation",
49 "FileMailslotQueryInformation",
50 "FileMailslotSetInformation",
51 "FileCompressionInformation",
52 "FileObjectIdInformation",
53 "FileCompletionInformation",
54 "FileMoveClusterInformation",
55 "FileQuotaInformation",
56 "FileReparsePointInformation",
57 "FileNetworkOpenInformation",
58 "FileAttributeTagInformation",
59 "FileTrackingInformation",
60 "FileIdBothDirectoryInformation",
61 "FileIdFullDirectoryInformation",
62 "FileValidDataLengthInformation",
63 "FileShortNameInformation",
64 "FileMaximumInformation"
65};
66
67/* FUNCTIONS ****************************************************************/
68
69/*
70 * FUNCTION: Retrieve the standard file information
71 */
75 PFILE_STANDARD_INFORMATION StandardInfo,
77{
80
81 /* PRECONDITION */
82 ASSERT(StandardInfo != NULL);
83 ASSERT(FCB != NULL);
84
86 {
87 StandardInfo->AllocationSize.QuadPart = 0;
88 StandardInfo->EndOfFile.QuadPart = 0;
89 StandardInfo->Directory = TRUE;
90 }
91 else
92 {
93 StandardInfo->AllocationSize = FCB->RFCB.AllocationSize;
94 StandardInfo->EndOfFile = FCB->RFCB.FileSize;
95 StandardInfo->Directory = FALSE;
96 }
97 StandardInfo->NumberOfLinks = 1;
99
101 return STATUS_SUCCESS;
102}
103
104static
108 PFILE_POSITION_INFORMATION PositionInfo)
109{
110 DPRINT("FsdSetPositionInformation()\n");
111
112 DPRINT("PositionInfo %p\n", PositionInfo);
113 DPRINT("Setting position %u\n", PositionInfo->CurrentByteOffset.u.LowPart);
114
115 FileObject->CurrentByteOffset.QuadPart =
116 PositionInfo->CurrentByteOffset.QuadPart;
117
118 return STATUS_SUCCESS;
119}
120
121static
126 PDEVICE_EXTENSION DeviceExt,
127 PFILE_POSITION_INFORMATION PositionInfo,
129{
132 UNREFERENCED_PARAMETER(DeviceExt);
133
134 DPRINT("VfatGetPositionInformation()\n");
135
138
139 PositionInfo->CurrentByteOffset.QuadPart =
140 FileObject->CurrentByteOffset.QuadPart;
141
142 DPRINT("Getting position %I64x\n",
143 PositionInfo->CurrentByteOffset.QuadPart);
144
146 return STATUS_SUCCESS;
147}
148
149static
154 PDEVICE_EXTENSION DeviceExt,
155 PFILE_BASIC_INFORMATION BasicInfo)
156{
158
159 DPRINT("VfatSetBasicInformation()\n");
160
162 ASSERT(NULL != FCB);
163 ASSERT(NULL != DeviceExt);
164 ASSERT(NULL != BasicInfo);
165 /* Check volume label bit */
166 ASSERT(0 == (*FCB->Attributes & _A_VOLID));
167
168 NotifyFilter = 0;
169
170 if (BasicInfo->FileAttributes != 0)
171 {
173
179
181 {
183 {
184 DPRINT("Setting temporary attribute on a directory!\n");
186 }
187
189 }
190 else
191 {
193 {
194 DPRINT("Setting directory attribute on a file!\n");
196 }
197 }
198
199 if (Attributes != *FCB->Attributes)
200 {
201 *FCB->Attributes = Attributes;
202 DPRINT("Setting attributes 0x%02x\n", *FCB->Attributes);
204 }
205 }
206
207 if (vfatVolumeIsFatX(DeviceExt))
208 {
209 if (BasicInfo->CreationTime.QuadPart != 0 && BasicInfo->CreationTime.QuadPart != -1)
210 {
212 &BasicInfo->CreationTime,
213 &FCB->entry.FatX.CreationDate,
214 &FCB->entry.FatX.CreationTime);
216 }
217
218 if (BasicInfo->LastAccessTime.QuadPart != 0 && BasicInfo->LastAccessTime.QuadPart != -1)
219 {
221 &BasicInfo->LastAccessTime,
222 &FCB->entry.FatX.AccessDate,
223 &FCB->entry.FatX.AccessTime);
225 }
226
227 if (BasicInfo->LastWriteTime.QuadPart != 0 && BasicInfo->LastWriteTime.QuadPart != -1)
228 {
230 &BasicInfo->LastWriteTime,
231 &FCB->entry.FatX.UpdateDate,
232 &FCB->entry.FatX.UpdateTime);
234 }
235 }
236 else
237 {
238 if (BasicInfo->CreationTime.QuadPart != 0 && BasicInfo->CreationTime.QuadPart != -1)
239 {
241 &BasicInfo->CreationTime,
242 &FCB->entry.Fat.CreationDate,
243 &FCB->entry.Fat.CreationTime);
245 }
246
247 if (BasicInfo->LastAccessTime.QuadPart != 0 && BasicInfo->LastAccessTime.QuadPart != -1)
248 {
250 &BasicInfo->LastAccessTime,
251 &FCB->entry.Fat.AccessDate,
252 NULL);
254 }
255
256 if (BasicInfo->LastWriteTime.QuadPart != 0 && BasicInfo->LastWriteTime.QuadPart != -1)
257 {
259 &BasicInfo->LastWriteTime,
260 &FCB->entry.Fat.UpdateDate,
261 &FCB->entry.Fat.UpdateTime);
263 }
264 }
265
266 VfatUpdateEntry(DeviceExt, FCB);
267
268 if (NotifyFilter != 0)
269 {
270 vfatReportChange(DeviceExt,
271 FCB,
274 }
275
276 return STATUS_SUCCESS;
277}
278
283 PDEVICE_EXTENSION DeviceExt,
284 PFILE_BASIC_INFORMATION BasicInfo,
286{
288
289 DPRINT("VfatGetBasicInformation()\n");
290
293
294 RtlZeroMemory(BasicInfo, sizeof(FILE_BASIC_INFORMATION));
295
296 if (vfatVolumeIsFatX(DeviceExt))
297 {
299 FCB->entry.FatX.CreationDate,
300 FCB->entry.FatX.CreationTime,
301 &BasicInfo->CreationTime);
303 FCB->entry.FatX.AccessDate,
304 FCB->entry.FatX.AccessTime,
305 &BasicInfo->LastAccessTime);
307 FCB->entry.FatX.UpdateDate,
308 FCB->entry.FatX.UpdateTime,
309 &BasicInfo->LastWriteTime);
310 BasicInfo->ChangeTime = BasicInfo->LastWriteTime;
311 }
312 else
313 {
315 FCB->entry.Fat.CreationDate,
316 FCB->entry.Fat.CreationTime,
317 &BasicInfo->CreationTime);
319 FCB->entry.Fat.AccessDate,
320 0,
321 &BasicInfo->LastAccessTime);
323 FCB->entry.Fat.UpdateDate,
324 FCB->entry.Fat.UpdateTime,
325 &BasicInfo->LastWriteTime);
326 BasicInfo->ChangeTime = BasicInfo->LastWriteTime;
327 }
328
329 BasicInfo->FileAttributes = *FCB->Attributes & 0x3f;
330 /* Synthesize FILE_ATTRIBUTE_NORMAL */
331 if (0 == (BasicInfo->FileAttributes & (FILE_ATTRIBUTE_DIRECTORY |
336 {
337 DPRINT("Synthesizing FILE_ATTRIBUTE_NORMAL\n");
339 }
340 DPRINT("Getting attributes 0x%02x\n", BasicInfo->FileAttributes);
341
343 return STATUS_SUCCESS;
344}
345
346
347static
352 PDEVICE_EXTENSION DeviceExt,
353 PFILE_DISPOSITION_INFORMATION DispositionInfo)
354{
355 DPRINT("FsdSetDispositionInformation(<%wZ>, Delete %u)\n", &FCB->PathNameU, DispositionInfo->DeleteFile);
356
357 ASSERT(DeviceExt != NULL);
358 ASSERT(DeviceExt->FatInfo.BytesPerCluster != 0);
359 ASSERT(FCB != NULL);
360
361 if (!DispositionInfo->DeleteFile)
362 {
363 /* undelete the file */
364 FCB->Flags &= ~FCB_DELETE_PENDING;
365 FileObject->DeletePending = FALSE;
366 return STATUS_SUCCESS;
367 }
368
370 {
371 /* stream already marked for deletion. just update the file object */
372 FileObject->DeletePending = TRUE;
373 return STATUS_SUCCESS;
374 }
375
377 {
379 }
380
381 if (vfatFCBIsRoot(FCB) || IsDotOrDotDot(&FCB->LongNameU))
382 {
383 /* we cannot delete a '.', '..' or the root directory */
385 }
386
387 if (!MmFlushImageSection (FileObject->SectionObjectPointer, MmFlushForDelete))
388 {
389 /* can't delete a file if its mapped into a process */
390
391 DPRINT("MmFlushImageSection returned FALSE\n");
393 }
394
395 if (vfatFCBIsDirectory(FCB) && !VfatIsDirectoryEmpty(DeviceExt, FCB))
396 {
397 /* can't delete a non-empty directory */
398
400 }
401
402 /* all good */
404 FileObject->DeletePending = TRUE;
405
406 return STATUS_SUCCESS;
407}
408
409static NTSTATUS
411 IN PDEVICE_EXTENSION DeviceExt,
412 IN PVFATFCB * ParentFCB,
414 IN BOOLEAN ReplaceIfExists,
415 IN PUNICODE_STRING ParentName,
417{
419 PVFATFCB TargetFcb;
420
421 DPRINT("vfatPrepareTargetForRename(%p, %p, %wZ, %d, %wZ, %p)\n", DeviceExt, ParentFCB, NewName, ReplaceIfExists, ParentName);
422
423 *Deleted = FALSE;
424 /* Try to open target */
425 Status = vfatGetFCBForFile(DeviceExt, ParentFCB, &TargetFcb, NewName);
426 /* If it exists */
427 if (NT_SUCCESS(Status))
428 {
429 DPRINT("Target file %wZ exists. FCB Flags %08x\n", NewName, TargetFcb->Flags);
430 /* Check whether we are allowed to replace */
431 if (ReplaceIfExists)
432 {
433 /* If that's a directory or a read-only file, we're not allowed */
434 if (vfatFCBIsDirectory(TargetFcb) || vfatFCBIsReadOnly(TargetFcb))
435 {
436 DPRINT("And this is a readonly file!\n");
437 vfatReleaseFCB(DeviceExt, *ParentFCB);
438 *ParentFCB = NULL;
439 vfatReleaseFCB(DeviceExt, TargetFcb);
441 }
442
443
444 /* If we still have a file object, close it. */
445 if (TargetFcb->FileObject)
446 {
447 if (!MmFlushImageSection(TargetFcb->FileObject->SectionObjectPointer, MmFlushForDelete))
448 {
449 DPRINT("MmFlushImageSection failed.\n");
450 vfatReleaseFCB(DeviceExt, *ParentFCB);
451 *ParentFCB = NULL;
452 vfatReleaseFCB(DeviceExt, TargetFcb);
454 }
455
456 TargetFcb->FileObject->DeletePending = TRUE;
457 VfatCloseFile(DeviceExt, TargetFcb->FileObject);
458 }
459
460 /* If we are here, ensure the file isn't open by anyone! */
461 if (TargetFcb->OpenHandleCount != 0)
462 {
463 DPRINT("There are still open handles for this file.\n");
464 vfatReleaseFCB(DeviceExt, *ParentFCB);
465 *ParentFCB = NULL;
466 vfatReleaseFCB(DeviceExt, TargetFcb);
468 }
469
470 /* Effectively delete old file to allow renaming */
471 DPRINT("Effectively deleting the file.\n");
472 VfatDelEntry(DeviceExt, TargetFcb, NULL);
473 vfatReleaseFCB(DeviceExt, TargetFcb);
474 *Deleted = TRUE;
475 return STATUS_SUCCESS;
476 }
477 else
478 {
479 vfatReleaseFCB(DeviceExt, *ParentFCB);
480 *ParentFCB = NULL;
481 vfatReleaseFCB(DeviceExt, TargetFcb);
483 }
484 }
485 else if (*ParentFCB != NULL)
486 {
487 return STATUS_SUCCESS;
488 }
489
490 /* Failure */
491 return Status;
492}
493
494static
497{
499 PVFATFCB VolFCB;
500
501 for (Entry = FCB->ParentListHead.Flink; Entry != &FCB->ParentListHead; Entry = Entry->Flink)
502 {
503 VolFCB = CONTAINING_RECORD(Entry, VFATFCB, ParentListEntry);
504 if (VolFCB->OpenHandleCount != 0)
505 {
506 ASSERT(VolFCB->parentFcb == FCB);
507 DPRINT1("At least one children file opened! %wZ (%u, %u)\n", &VolFCB->PathNameU, VolFCB->RefCount, VolFCB->OpenHandleCount);
508 return TRUE;
509 }
510
511 if (vfatFCBIsDirectory(VolFCB) && !IsListEmpty(&VolFCB->ParentListHead))
512 {
513 if (IsThereAChildOpened(VolFCB))
514 {
515 return TRUE;
516 }
517 }
518 }
519
520 return FALSE;
521}
522
523static
524VOID
526 PDEVICE_EXTENSION DeviceExt,
528{
531
532 if (IsListEmpty(&FCB->ParentListHead))
533 return;
534
535 for (Entry = FCB->ParentListHead.Flink; Entry != &FCB->ParentListHead; Entry = Entry->Flink)
536 {
538
539 Child = CONTAINING_RECORD(Entry, VFATFCB, ParentListEntry);
540 DPRINT("Found %wZ with still %lu references (parent: %lu)!\n", &Child->PathNameU, Child->RefCount, FCB->RefCount);
541
542 Status = vfatSetFCBNewDirName(DeviceExt, Child, FCB);
543 if (!NT_SUCCESS(Status))
544 continue;
545
547 {
548 VfatRenameChildFCB(DeviceExt, Child);
549 }
550 }
551}
552
553/*
554 * FUNCTION: Set the file name information
555 */
556static
561 PDEVICE_EXTENSION DeviceExt,
562 PFILE_RENAME_INFORMATION RenameInfo,
563 PFILE_OBJECT TargetFileObject)
564{
565#ifdef NASSERTS_RENAME
566#pragma push_macro("ASSERT")
567#undef ASSERT
568#define ASSERT(x) ((VOID) 0)
569#endif
572 UNICODE_STRING SourcePath;
573 UNICODE_STRING SourceFile;
574 UNICODE_STRING NewPath;
575 UNICODE_STRING NewFile;
576 PFILE_OBJECT RootFileObject;
577 PVFATFCB RootFCB;
578 UNICODE_STRING RenameInfoString;
579 PVFATFCB ParentFCB;
583 BOOLEAN DeletedTarget;
584 ULONG OldReferences, NewReferences;
585 PVFATFCB OldParent;
586
587 DPRINT("VfatSetRenameInfo(%p, %p, %p, %p, %p)\n", FileObject, FCB, DeviceExt, RenameInfo, TargetFileObject);
588
589 /* Disallow renaming root */
590 if (vfatFCBIsRoot(FCB))
591 {
593 }
594
595 OldReferences = FCB->parentFcb->RefCount;
596#ifdef NASSERTS_RENAME
597 UNREFERENCED_PARAMETER(OldReferences);
598#endif
599
600 /* If we are performing relative opening for rename, get FO for getting FCB and path name */
601 if (RenameInfo->RootDirectory != NULL)
602 {
603 /* We cannot tolerate relative opening with a full path */
604 if (RenameInfo->FileName[0] == L'\\')
605 {
607 }
608
613 (PVOID *)&RootFileObject,
614 NULL);
615 if (!NT_SUCCESS(Status))
616 {
617 return Status;
618 }
619
620 RootFCB = RootFileObject->FsContext;
621 }
622
623 RtlInitEmptyUnicodeString(&NewName, NULL, 0);
624 ParentFCB = NULL;
625
626 if (TargetFileObject == NULL)
627 {
628 /* If we don't have target file object, construct paths thanks to relative FCB, if any, and with
629 * information supplied by the user
630 */
631
632 /* First, setup a string we'll work on */
633 RenameInfoString.Length = RenameInfo->FileNameLength;
634 RenameInfoString.MaximumLength = RenameInfo->FileNameLength;
635 RenameInfoString.Buffer = RenameInfo->FileName;
636
637 /* Check whether we have FQN */
638 if (RenameInfoString.Length > 6 * sizeof(WCHAR))
639 {
640 if (RenameInfoString.Buffer[0] == L'\\' && RenameInfoString.Buffer[1] == L'?' &&
641 RenameInfoString.Buffer[2] == L'?' && RenameInfoString.Buffer[3] == L'\\' &&
642 RenameInfoString.Buffer[5] == L':' && (RenameInfoString.Buffer[4] >= L'A' &&
643 RenameInfoString.Buffer[4] <= L'Z'))
644 {
645 /* If so, open its target directory */
647 &RenameInfoString,
649 NULL, NULL);
650
655 NULL, 0,
657 FILE_OPEN,
659 NULL, 0,
661 NULL,
663 if (!NT_SUCCESS(Status))
664 {
665 goto Cleanup;
666 }
667
668 /* Get its FO to get the FCB */
673 (PVOID *)&TargetFileObject,
674 NULL);
675 if (!NT_SUCCESS(Status))
676 {
678 goto Cleanup;
679 }
680
681 /* Are we working on the same volume? */
683 {
684 ObDereferenceObject(TargetFileObject);
686 TargetFileObject = NULL;
688 goto Cleanup;
689 }
690 }
691 }
692
693 NewName.Length = 0;
695 if (RenameInfo->RootDirectory != NULL)
696 {
697 NewName.MaximumLength += sizeof(WCHAR) + RootFCB->PathNameU.Length;
698 }
699 else if (RenameInfo->FileName[0] != L'\\')
700 {
701 /* We don't have full path, and we don't have root directory:
702 * => we move inside the same directory
703 */
704 NewName.MaximumLength += sizeof(WCHAR) + FCB->DirNameU.Length;
705 }
706 else if (TargetFileObject != NULL)
707 {
708 /* We had a FQN:
709 * => we need to use its correct path
710 */
711 NewName.MaximumLength += sizeof(WCHAR) + ((PVFATFCB)TargetFileObject->FsContext)->PathNameU.Length;
712 }
713
715 if (NewName.Buffer == NULL)
716 {
717 if (TargetFileObject != NULL)
718 {
719 ObDereferenceObject(TargetFileObject);
721 TargetFileObject = NULL;
722 }
724 goto Cleanup;
725 }
726
727 if (RenameInfo->RootDirectory != NULL)
728 {
729 /* Here, copy first absolute and then append relative */
731 NewName.Buffer[NewName.Length / sizeof(WCHAR)] = L'\\';
732 NewName.Length += sizeof(WCHAR);
733 RtlAppendUnicodeStringToString(&NewName, &RenameInfoString);
734 }
735 else if (RenameInfo->FileName[0] != L'\\')
736 {
737 /* Here, copy first work directory and then append filename */
738 RtlCopyUnicodeString(&NewName, &FCB->DirNameU);
739 NewName.Buffer[NewName.Length / sizeof(WCHAR)] = L'\\';
740 NewName.Length += sizeof(WCHAR);
741 RtlAppendUnicodeStringToString(&NewName, &RenameInfoString);
742 }
743 else if (TargetFileObject != NULL)
744 {
745 /* Here, copy first path name and then append filename */
746 RtlCopyUnicodeString(&NewName, &((PVFATFCB)TargetFileObject->FsContext)->PathNameU);
747 NewName.Buffer[NewName.Length / sizeof(WCHAR)] = L'\\';
748 NewName.Length += sizeof(WCHAR);
749 RtlAppendUnicodeStringToString(&NewName, &RenameInfoString);
750 }
751 else
752 {
753 /* Here we should have full path, so simply copy it */
754 RtlCopyUnicodeString(&NewName, &RenameInfoString);
755 }
756
757 /* Do we have to cleanup some stuff? */
758 if (TargetFileObject != NULL)
759 {
760 ObDereferenceObject(TargetFileObject);
762 TargetFileObject = NULL;
763 }
764 }
765 else
766 {
767 /* At that point, we shouldn't care about whether we are relative opening
768 * Target FO FCB should already have full path
769 */
770
771 /* Before constructing string, just make a sanity check (just to be sure!) */
773 {
775 goto Cleanup;
776 }
777
778 NewName.Length = 0;
779 NewName.MaximumLength = TargetFileObject->FileName.Length + ((PVFATFCB)TargetFileObject->FsContext)->PathNameU.Length + sizeof(WCHAR);
781 if (NewName.Buffer == NULL)
782 {
784 goto Cleanup;
785 }
786
787 RtlCopyUnicodeString(&NewName, &((PVFATFCB)TargetFileObject->FsContext)->PathNameU);
788 /* If \, it's already backslash terminated, don't add it */
789 if (!vfatFCBIsRoot(TargetFileObject->FsContext))
790 {
791 NewName.Buffer[NewName.Length / sizeof(WCHAR)] = L'\\';
792 NewName.Length += sizeof(WCHAR);
793 }
794 RtlAppendUnicodeStringToString(&NewName, &TargetFileObject->FileName);
795 }
796
797 /* Explode our paths to get path & filename */
798 vfatSplitPathName(&FCB->PathNameU, &SourcePath, &SourceFile);
799 DPRINT("Old dir: %wZ, Old file: %wZ\n", &SourcePath, &SourceFile);
800 vfatSplitPathName(&NewName, &NewPath, &NewFile);
801 DPRINT("New dir: %wZ, New file: %wZ\n", &NewPath, &NewFile);
802
803 if (IsDotOrDotDot(&NewFile))
804 {
806 goto Cleanup;
807 }
808
809 if (vfatFCBIsDirectory(FCB) && !IsListEmpty(&FCB->ParentListHead))
810 {
812 {
814 ASSERT(OldReferences == FCB->parentFcb->RefCount);
815 goto Cleanup;
816 }
817 }
818
819 /* Are we working in place? */
820 if (FsRtlAreNamesEqual(&SourcePath, &NewPath, TRUE, NULL))
821 {
822 if (FsRtlAreNamesEqual(&SourceFile, &NewFile, FALSE, NULL))
823 {
825 ASSERT(OldReferences == FCB->parentFcb->RefCount);
826 goto Cleanup;
827 }
828
829 if (FsRtlAreNamesEqual(&SourceFile, &NewFile, TRUE, NULL))
830 {
831 vfatReportChange(DeviceExt,
832 FCB,
836 Status = vfatRenameEntry(DeviceExt, FCB, &NewFile, TRUE);
837 if (NT_SUCCESS(Status))
838 {
839 vfatReportChange(DeviceExt,
840 FCB,
844 }
845 }
846 else
847 {
848 /* Try to find target */
849 ParentFCB = FCB->parentFcb;
850 vfatGrabFCB(DeviceExt, ParentFCB);
852 &ParentFCB,
853 &NewFile,
854 RenameInfo->ReplaceIfExists,
855 &NewPath,
856 &DeletedTarget);
857 if (!NT_SUCCESS(Status))
858 {
859 ASSERT(OldReferences == FCB->parentFcb->RefCount - 1);
860 ASSERT(OldReferences == ParentFCB->RefCount - 1);
861 goto Cleanup;
862 }
863
864 vfatReportChange(DeviceExt,
865 FCB,
869 Status = vfatRenameEntry(DeviceExt, FCB, &NewFile, FALSE);
870 if (NT_SUCCESS(Status))
871 {
872 if (DeletedTarget)
873 {
874 vfatReportChange(DeviceExt,
875 FCB,
879 }
880 else
881 {
882 vfatReportChange(DeviceExt,
883 FCB,
887 }
888 }
889 }
890
891 ASSERT(OldReferences == FCB->parentFcb->RefCount - 1); // extra grab
892 ASSERT(OldReferences == ParentFCB->RefCount - 1); // extra grab
893 }
894 else
895 {
896
897 /* Try to find target */
898 ParentFCB = NULL;
899 OldParent = FCB->parentFcb;
900#ifdef NASSERTS_RENAME
901 UNREFERENCED_PARAMETER(OldParent);
902#endif
904 &ParentFCB,
905 &NewName,
906 RenameInfo->ReplaceIfExists,
907 &NewPath,
908 &DeletedTarget);
909 if (!NT_SUCCESS(Status))
910 {
911 ASSERT(OldReferences == FCB->parentFcb->RefCount);
912 goto Cleanup;
913 }
914
915 NewReferences = ParentFCB->RefCount;
916#ifdef NASSERTS_RENAME
917 UNREFERENCED_PARAMETER(NewReferences);
918#endif
919
920 vfatReportChange(DeviceExt,
921 FCB,
925 Status = VfatMoveEntry(DeviceExt, FCB, &NewFile, ParentFCB);
926 if (NT_SUCCESS(Status))
927 {
928 if (DeletedTarget)
929 {
930 vfatReportChange(DeviceExt,
931 FCB,
935 }
936 else
937 {
938 vfatReportChange(DeviceExt,
939 FCB,
943 }
944 }
945 }
946
948 {
949 VfatRenameChildFCB(DeviceExt, FCB);
950 }
951
952 ASSERT(OldReferences == OldParent->RefCount + 1); // removed file
953 ASSERT(NewReferences == ParentFCB->RefCount - 1); // new file
954Cleanup:
955 if (ParentFCB != NULL) vfatReleaseFCB(DeviceExt, ParentFCB);
957 if (RenameInfo->RootDirectory != NULL) ObDereferenceObject(RootFileObject);
958
959 return Status;
960#ifdef NASSERTS_RENAME
961#pragma pop_macro("ASSERT")
962#endif
963}
964
965/*
966 * FUNCTION: Retrieve the file name information
967 */
968static
973 PDEVICE_EXTENSION DeviceExt,
974 PFILE_NAME_INFORMATION NameInfo,
976{
978
980 UNREFERENCED_PARAMETER(DeviceExt);
981
982 ASSERT(NameInfo != NULL);
983 ASSERT(FCB != NULL);
984
985 /* If buffer can't hold at least the file name length, bail out */
988
989 /* Save file name length, and as much file len, as buffer length allows */
990 NameInfo->FileNameLength = FCB->PathNameU.Length;
991
992 /* Calculate amount of bytes to copy not to overflow the buffer */
993 BytesToCopy = min(FCB->PathNameU.Length,
995
996 /* Fill in the bytes */
997 RtlCopyMemory(NameInfo->FileName, FCB->PathNameU.Buffer, BytesToCopy);
998
999 /* Check if we could write more but are not able to */
1000 if (*BufferLength < FCB->PathNameU.Length + (ULONG)FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]))
1001 {
1002 /* Return number of bytes written */
1005 }
1006
1007 /* We filled up as many bytes, as needed */
1008 *BufferLength -= (FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]) + FCB->PathNameU.Length);
1009
1010 return STATUS_SUCCESS;
1011}
1012
1013static
1016 PVFATFCB Fcb,
1017 PDEVICE_EXTENSION DeviceExt,
1018 PFILE_INTERNAL_INFORMATION InternalInfo,
1020{
1021 ASSERT(InternalInfo);
1022 ASSERT(Fcb);
1023
1026
1027 InternalInfo->IndexNumber.QuadPart = (LONGLONG)vfatDirEntryGetFirstCluster(DeviceExt, &Fcb->entry) * DeviceExt->FatInfo.BytesPerCluster;
1028
1030 return STATUS_SUCCESS;
1031}
1032
1033
1034/*
1035 * FUNCTION: Retrieve the file network open information
1036 */
1037static
1040 PVFATFCB Fcb,
1041 PDEVICE_EXTENSION DeviceExt,
1044{
1045 ASSERT(NetworkInfo);
1046 ASSERT(Fcb);
1047
1049 return(STATUS_BUFFER_OVERFLOW);
1050
1051 if (vfatVolumeIsFatX(DeviceExt))
1052 {
1054 Fcb->entry.FatX.CreationDate,
1055 Fcb->entry.FatX.CreationTime,
1056 &NetworkInfo->CreationTime);
1058 Fcb->entry.FatX.AccessDate,
1059 Fcb->entry.FatX.AccessTime,
1060 &NetworkInfo->LastAccessTime);
1062 Fcb->entry.FatX.UpdateDate,
1063 Fcb->entry.FatX.UpdateTime,
1064 &NetworkInfo->LastWriteTime);
1065 NetworkInfo->ChangeTime.QuadPart = NetworkInfo->LastWriteTime.QuadPart;
1066 }
1067 else
1068 {
1070 Fcb->entry.Fat.CreationDate,
1071 Fcb->entry.Fat.CreationTime,
1072 &NetworkInfo->CreationTime);
1074 Fcb->entry.Fat.AccessDate,
1075 0,
1076 &NetworkInfo->LastAccessTime);
1078 Fcb->entry.Fat.UpdateDate,
1079 Fcb->entry.Fat.UpdateTime,
1080 &NetworkInfo->LastWriteTime);
1081 NetworkInfo->ChangeTime.QuadPart = NetworkInfo->LastWriteTime.QuadPart;
1082 }
1083
1085 {
1086 NetworkInfo->EndOfFile.QuadPart = 0L;
1087 NetworkInfo->AllocationSize.QuadPart = 0L;
1088 }
1089 else
1090 {
1091 NetworkInfo->AllocationSize = Fcb->RFCB.AllocationSize;
1092 NetworkInfo->EndOfFile = Fcb->RFCB.FileSize;
1093 }
1094
1095 NetworkInfo->FileAttributes = *Fcb->Attributes & 0x3f;
1096 /* Synthesize FILE_ATTRIBUTE_NORMAL */
1097 if (0 == (NetworkInfo->FileAttributes & (FILE_ATTRIBUTE_DIRECTORY |
1102 {
1103 DPRINT("Synthesizing FILE_ATTRIBUTE_NORMAL\n");
1104 NetworkInfo->FileAttributes |= FILE_ATTRIBUTE_NORMAL;
1105 }
1106
1108 return STATUS_SUCCESS;
1109}
1110
1111
1112static
1116 PVFATFCB Fcb,
1117 PDEVICE_EXTENSION DeviceExt,
1120{
1123
1124 /* FIXME - use SEH to access the buffer! */
1125 Info->EaSize = 0;
1126 *BufferLength -= sizeof(*Info);
1127 if (DeviceExt->FatInfo.FatType == FAT12 ||
1128 DeviceExt->FatInfo.FatType == FAT16)
1129 {
1130 /* FIXME */
1131 DPRINT1("VFAT: FileEaInformation not implemented!\n");
1132 }
1133 return STATUS_SUCCESS;
1134}
1135
1136
1137/*
1138 * FUNCTION: Retrieve the all file information
1139 */
1140static
1144 PVFATFCB Fcb,
1145 PDEVICE_EXTENSION DeviceExt,
1148{
1150
1151 ASSERT(Info);
1152 ASSERT(Fcb);
1153
1154 if (*BufferLength < FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName))
1156
1158
1159 /* Basic Information */
1160 Status = VfatGetBasicInformation(FileObject, Fcb, DeviceExt, &Info->BasicInformation, BufferLength);
1161 if (!NT_SUCCESS(Status)) return Status;
1162 /* Standard Information */
1163 Status = VfatGetStandardInformation(Fcb, &Info->StandardInformation, BufferLength);
1164 if (!NT_SUCCESS(Status)) return Status;
1165 /* Internal Information */
1166 Status = VfatGetInternalInformation(Fcb, DeviceExt, &Info->InternalInformation, BufferLength);
1167 if (!NT_SUCCESS(Status)) return Status;
1168 /* EA Information */
1169 Status = VfatGetEaInformation(FileObject, Fcb, DeviceExt, &Info->EaInformation, BufferLength);
1170 if (!NT_SUCCESS(Status)) return Status;
1171 /* Position Information */
1172 Status = VfatGetPositionInformation(FileObject, Fcb, DeviceExt, &Info->PositionInformation, BufferLength);
1173 if (!NT_SUCCESS(Status)) return Status;
1174 /* Name Information */
1175 Status = VfatGetNameInformation(FileObject, Fcb, DeviceExt, &Info->NameInformation, BufferLength);
1176
1177 return Status;
1178}
1179
1180static
1181VOID
1184 PVFATFCB Fcb,
1185 ULONG Size,
1187 BOOLEAN IsFatX)
1188{
1189 if (Size > 0)
1190 {
1192 }
1193 else
1194 {
1196 }
1197 if (!vfatFCBIsDirectory(Fcb))
1198 {
1199 if (IsFatX)
1200 Fcb->entry.FatX.FileSize = Size;
1201 else
1202 Fcb->entry.Fat.FileSize = Size;
1203 }
1206
1208}
1209
1213 PVFATFCB Fcb,
1214 PDEVICE_EXTENSION DeviceExt,
1216{
1217 ULONG OldSize;
1218 ULONG Cluster, FirstCluster;
1220
1221 ULONG ClusterSize = DeviceExt->FatInfo.BytesPerCluster;
1222 ULONG NewSize = AllocationSize->u.LowPart;
1223 ULONG NCluster;
1224 BOOLEAN AllocSizeChanged = FALSE, IsFatX = vfatVolumeIsFatX(DeviceExt);
1225
1226 DPRINT("VfatSetAllocationSizeInformation(File <%wZ>, AllocationSize %d %u)\n",
1227 &Fcb->PathNameU, AllocationSize->HighPart, AllocationSize->LowPart);
1228
1229 if (IsFatX)
1230 OldSize = Fcb->entry.FatX.FileSize;
1231 else
1232 OldSize = Fcb->entry.Fat.FileSize;
1233
1234 if (AllocationSize->u.HighPart > 0)
1235 {
1237 }
1238
1239 if (OldSize == NewSize)
1240 {
1241 return STATUS_SUCCESS;
1242 }
1243
1244 FirstCluster = vfatDirEntryGetFirstCluster(DeviceExt, &Fcb->entry);
1245
1246 if (NewSize > Fcb->RFCB.AllocationSize.u.LowPart)
1247 {
1248 AllocSizeChanged = TRUE;
1249 if (FirstCluster == 0)
1250 {
1251 Fcb->LastCluster = Fcb->LastOffset = 0;
1252 Status = NextCluster(DeviceExt, FirstCluster, &FirstCluster, TRUE);
1253 if (!NT_SUCCESS(Status))
1254 {
1255 DPRINT1("NextCluster failed. Status = %x\n", Status);
1256 return Status;
1257 }
1258
1259 if (FirstCluster == 0xffffffff)
1260 {
1261 return STATUS_DISK_FULL;
1262 }
1263
1264 Status = OffsetToCluster(DeviceExt, FirstCluster,
1266 &NCluster, TRUE);
1267 if (NCluster == 0xffffffff || !NT_SUCCESS(Status))
1268 {
1269 /* disk is full */
1270 NCluster = Cluster = FirstCluster;
1272 while (NT_SUCCESS(Status) && Cluster != 0xffffffff && Cluster > 1)
1273 {
1274 Status = NextCluster(DeviceExt, FirstCluster, &NCluster, FALSE);
1275 WriteCluster(DeviceExt, Cluster, 0);
1276 Cluster = NCluster;
1277 }
1278 return STATUS_DISK_FULL;
1279 }
1280
1281 if (IsFatX)
1282 {
1283 Fcb->entry.FatX.FirstCluster = FirstCluster;
1284 }
1285 else
1286 {
1287 if (DeviceExt->FatInfo.FatType == FAT32)
1288 {
1289 Fcb->entry.Fat.FirstCluster = (unsigned short)(FirstCluster & 0x0000FFFF);
1290 Fcb->entry.Fat.FirstClusterHigh = FirstCluster >> 16;
1291 }
1292 else
1293 {
1294 ASSERT((FirstCluster >> 16) == 0);
1295 Fcb->entry.Fat.FirstCluster = (unsigned short)(FirstCluster & 0x0000FFFF);
1296 }
1297 }
1298 }
1299 else
1300 {
1301 if (Fcb->LastCluster > 0)
1302 {
1303 if (Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize == Fcb->LastOffset)
1304 {
1305 Cluster = Fcb->LastCluster;
1307 }
1308 else
1309 {
1310 Status = OffsetToCluster(DeviceExt, Fcb->LastCluster,
1311 Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize - Fcb->LastOffset,
1312 &Cluster, FALSE);
1313 }
1314 }
1315 else
1316 {
1317 Status = OffsetToCluster(DeviceExt, FirstCluster,
1318 Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize,
1319 &Cluster, FALSE);
1320 }
1321
1322 if (!NT_SUCCESS(Status))
1323 {
1324 return Status;
1325 }
1326
1327 Fcb->LastCluster = Cluster;
1328 Fcb->LastOffset = Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize;
1329
1330 /* FIXME: Check status */
1331 /* Cluster points now to the last cluster within the chain */
1332 Status = OffsetToCluster(DeviceExt, Cluster,
1333 ROUND_DOWN(NewSize - 1, ClusterSize) - Fcb->LastOffset,
1334 &NCluster, TRUE);
1335 if (NCluster == 0xffffffff || !NT_SUCCESS(Status))
1336 {
1337 /* disk is full */
1338 NCluster = Cluster;
1339 Status = NextCluster(DeviceExt, FirstCluster, &NCluster, FALSE);
1340 WriteCluster(DeviceExt, Cluster, 0xffffffff);
1341 Cluster = NCluster;
1342 while (NT_SUCCESS(Status) && Cluster != 0xffffffff && Cluster > 1)
1343 {
1344 Status = NextCluster(DeviceExt, FirstCluster, &NCluster, FALSE);
1345 WriteCluster(DeviceExt, Cluster, 0);
1346 Cluster = NCluster;
1347 }
1348 return STATUS_DISK_FULL;
1349 }
1350 }
1352 }
1353 else if (NewSize + ClusterSize <= Fcb->RFCB.AllocationSize.u.LowPart)
1354 {
1355 DPRINT("Check for the ability to set file size\n");
1356 if (!MmCanFileBeTruncated(FileObject->SectionObjectPointer,
1358 {
1359 DPRINT("Couldn't set file size!\n");
1361 }
1362 DPRINT("Can set file size\n");
1363
1364 AllocSizeChanged = TRUE;
1365 /* FIXME: Use the cached cluster/offset better way. */
1366 Fcb->LastCluster = Fcb->LastOffset = 0;
1368 if (NewSize > 0)
1369 {
1370 Status = OffsetToCluster(DeviceExt, FirstCluster,
1372 &Cluster, FALSE);
1373
1374 NCluster = Cluster;
1375 Status = NextCluster(DeviceExt, FirstCluster, &NCluster, FALSE);
1376 WriteCluster(DeviceExt, Cluster, 0xffffffff);
1377 Cluster = NCluster;
1378 }
1379 else
1380 {
1381 if (IsFatX)
1382 {
1383 Fcb->entry.FatX.FirstCluster = 0;
1384 }
1385 else
1386 {
1387 if (DeviceExt->FatInfo.FatType == FAT32)
1388 {
1389 Fcb->entry.Fat.FirstCluster = 0;
1390 Fcb->entry.Fat.FirstClusterHigh = 0;
1391 }
1392 else
1393 {
1394 Fcb->entry.Fat.FirstCluster = 0;
1395 }
1396 }
1397
1398 NCluster = Cluster = FirstCluster;
1400 }
1401
1402 while (NT_SUCCESS(Status) && 0xffffffff != Cluster && Cluster > 1)
1403 {
1404 Status = NextCluster(DeviceExt, FirstCluster, &NCluster, FALSE);
1405 WriteCluster(DeviceExt, Cluster, 0);
1406 Cluster = NCluster;
1407 }
1408
1409 if (DeviceExt->FatInfo.FatType == FAT32)
1410 {
1412 }
1413 }
1414 else
1415 {
1417 }
1418
1419 /* Update the on-disk directory entry */
1421 if (AllocSizeChanged)
1422 {
1423 VfatUpdateEntry(DeviceExt, Fcb);
1424
1426 }
1427 return STATUS_SUCCESS;
1428}
1429
1430/*
1431 * FUNCTION: Retrieve the specified file information
1432 */
1435 PVFAT_IRP_CONTEXT IrpContext)
1436{
1438 PVFATFCB FCB;
1439
1441 PVOID SystemBuffer;
1443
1444 /* PRECONDITION */
1445 ASSERT(IrpContext);
1446
1447 /* INITIALIZATION */
1448 FileInformationClass = IrpContext->Stack->Parameters.QueryFile.FileInformationClass;
1449 FCB = (PVFATFCB) IrpContext->FileObject->FsContext;
1450
1451 DPRINT("VfatQueryInformation is called for '%s'\n",
1453
1454 if (FCB == NULL)
1455 {
1456 DPRINT1("IRP_MJ_QUERY_INFORMATION without FCB!\n");
1457 IrpContext->Irp->IoStatus.Information = 0;
1459 }
1460
1461 SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
1462 BufferLength = IrpContext->Stack->Parameters.QueryFile.Length;
1463
1465 {
1467 BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
1468 {
1469 return VfatMarkIrpContextForQueue(IrpContext);
1470 }
1471 }
1472
1473 switch (FileInformationClass)
1474 {
1477 SystemBuffer,
1478 &BufferLength);
1479 break;
1480
1483 FCB,
1484 IrpContext->DeviceExt,
1485 SystemBuffer,
1486 &BufferLength);
1487 break;
1488
1491 FCB,
1492 IrpContext->DeviceExt,
1493 SystemBuffer,
1494 &BufferLength);
1495 break;
1496
1499 FCB,
1500 IrpContext->DeviceExt,
1501 SystemBuffer,
1502 &BufferLength);
1503 break;
1504
1507 IrpContext->DeviceExt,
1508 SystemBuffer,
1509 &BufferLength);
1510 break;
1511
1514 IrpContext->DeviceExt,
1515 SystemBuffer,
1516 &BufferLength);
1517 break;
1518
1519 case FileAllInformation:
1521 FCB,
1522 IrpContext->DeviceExt,
1523 SystemBuffer,
1524 &BufferLength);
1525 break;
1526
1527 case FileEaInformation:
1529 FCB,
1530 IrpContext->DeviceExt,
1531 SystemBuffer,
1532 &BufferLength);
1533 break;
1534
1537 break;
1538
1539 default:
1541 }
1542
1544 {
1546 }
1547
1549 IrpContext->Irp->IoStatus.Information =
1550 IrpContext->Stack->Parameters.QueryFile.Length - BufferLength;
1551 else
1552 IrpContext->Irp->IoStatus.Information = 0;
1553
1554 return Status;
1555}
1556
1557/*
1558 * FUNCTION: Retrieve the specified file information
1559 */
1562 PVFAT_IRP_CONTEXT IrpContext)
1563{
1565 PVFATFCB FCB;
1567 PVOID SystemBuffer;
1568 BOOLEAN LockDir;
1569
1570 /* PRECONDITION */
1571 ASSERT(IrpContext);
1572
1573 DPRINT("VfatSetInformation(IrpContext %p)\n", IrpContext);
1574
1575 /* INITIALIZATION */
1577 IrpContext->Stack->Parameters.SetFile.FileInformationClass;
1578 FCB = (PVFATFCB) IrpContext->FileObject->FsContext;
1579 SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
1580
1581 DPRINT("VfatSetInformation is called for '%s'\n",
1583
1584 DPRINT("FileInformationClass %d\n", FileInformationClass);
1585 DPRINT("SystemBuffer %p\n", SystemBuffer);
1586
1587 if (FCB == NULL)
1588 {
1589 DPRINT1("IRP_MJ_SET_INFORMATION without FCB!\n");
1590 IrpContext->Irp->IoStatus.Information = 0;
1592 }
1593
1594 /* Special: We should call MmCanFileBeTruncated here to determine if changing
1595 the file size would be allowed. If not, we bail with the right error.
1596 We must do this before acquiring the lock. */
1598 {
1599 DPRINT("Check for the ability to set file size\n");
1600 if (!MmCanFileBeTruncated(IrpContext->FileObject->SectionObjectPointer,
1601 (PLARGE_INTEGER)SystemBuffer))
1602 {
1603 DPRINT("Couldn't set file size!\n");
1604 IrpContext->Irp->IoStatus.Information = 0;
1606 }
1607 DPRINT("Can set file size\n");
1608 }
1609
1610 LockDir = FALSE;
1613 {
1614 LockDir = TRUE;
1615 }
1616
1617 if (LockDir)
1618 {
1620 BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
1621 {
1622 return VfatMarkIrpContextForQueue(IrpContext);
1623 }
1624 }
1625
1627 {
1629 BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
1630 {
1631 if (LockDir)
1632 {
1634 }
1635
1636 return VfatMarkIrpContextForQueue(IrpContext);
1637 }
1638 }
1639
1640 switch (FileInformationClass)
1641 {
1644 SystemBuffer);
1645 break;
1646
1649 FCB,
1650 IrpContext->DeviceExt,
1651 SystemBuffer);
1652 break;
1653
1657 FCB,
1658 IrpContext->DeviceExt,
1659 (PLARGE_INTEGER)SystemBuffer);
1660 break;
1661
1664 FCB,
1665 IrpContext->DeviceExt,
1666 SystemBuffer);
1667 break;
1668
1671 FCB,
1672 IrpContext->DeviceExt,
1673 SystemBuffer,
1674 IrpContext->Stack->Parameters.SetFile.FileObject);
1675 break;
1676
1677 default:
1679 }
1680
1682 {
1684 }
1685
1686 if (LockDir)
1687 {
1689 }
1690
1691 IrpContext->Irp->IoStatus.Information = 0;
1692 return Status;
1693}
1694
1695/* EOF */
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
DWORD ClusterSize
Definition: format.c:67
#define FAT32
Definition: fat.h:169
#define FAT12
Definition: fat.h:167
#define FAT16
Definition: fat.h:168
_In_ PFCB Fcb
Definition: cdprocs.h:159
struct _FCB FCB
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
ULONG vfatDirEntryGetFirstCluster(PDEVICE_EXTENSION pDeviceExt, PDIR_ENTRY pFatDirEntry)
Definition: direntry.c:18
NTSTATUS vfatRenameEntry(IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb, IN PUNICODE_STRING FileName, IN BOOLEAN CaseChangeOnly)
Definition: dirwr.c:178
NTSTATUS VfatMoveEntry(IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb, IN PUNICODE_STRING FileName, IN PVFATFCB ParentFcb)
Definition: dirwr.c:1122
NTSTATUS VfatUpdateEntry(IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb)
Definition: dirwr.c:115
#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:32
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define FILE_SHARE_READ
Definition: compat.h:136
unsigned short(__cdecl typeof(TIFFCurrentDirectory))(struct tiff *)
Definition: typeof.h:94
static const WCHAR Cleanup[]
Definition: register.c:80
#define IRPCONTEXT_CANWAIT
Definition: ntfs.h:474
NTSTATUS VfatCloseFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject)
Definition: close.c:159
BOOLEAN FsdDosDateTimeToSystemTime(PDEVICE_EXTENSION DeviceExt, USHORT DosDate, USHORT DosTime, PLARGE_INTEGER SystemTime)
Definition: dir.c:21
BOOLEAN FsdSystemTimeToDosDateTime(PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER SystemTime, PUSHORT pDosDate, PUSHORT pDosTime)
Definition: dir.c:52
NTSTATUS FAT32UpdateFreeClustersCount(PDEVICE_EXTENSION DeviceExt)
Definition: fat.c:1215
NTSTATUS WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, ULONG NewValue)
Definition: fat.c:705
NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, PULONG CurrentCluster, BOOLEAN Extend)
Definition: rw.c:38
NTSTATUS OffsetToCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, ULONG FileOffset, PULONG Cluster, BOOLEAN Extend)
Definition: rw.c:59
BOOLEAN IsDotOrDotDot(PCUNICODE_STRING Name)
Definition: string.c:28
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#define NonPagedPool
Definition: env_spec_w32.h:307
#define ExAcquireResourceSharedLite(res, wait)
Definition: env_spec_w32.h:621
#define ROUND_DOWN(n, align)
Definition: eventvwr.h:33
#define ExGetPreviousMode
Definition: ex.h:140
#define FCB_DELETE_PENDING
Definition: ext2fs.h:888
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:322
_Must_inspect_result_ _In_ USHORT NewSize
Definition: fltkernel.h:975
@ FilePositionInformation
Definition: from_kernel.h:75
@ FileMaximumInformation
Definition: from_kernel.h:112
@ FileEndOfFileInformation
Definition: from_kernel.h:81
@ FileRenameInformation
Definition: from_kernel.h:71
@ FileAllInformation
Definition: from_kernel.h:79
@ FileInternalInformation
Definition: from_kernel.h:67
@ FileEaInformation
Definition: from_kernel.h:68
@ FileAlternateNameInformation
Definition: from_kernel.h:82
@ FileNameInformation
Definition: from_kernel.h:70
@ FileAllocationInformation
Definition: from_kernel.h:80
@ FileNetworkOpenInformation
Definition: from_kernel.h:95
@ FileBasicInformation
Definition: from_kernel.h:65
@ FileDispositionInformation
Definition: from_kernel.h:74
struct _FILE_NETWORK_OPEN_INFORMATION FILE_NETWORK_OPEN_INFORMATION
#define FILE_OPEN
Definition: from_kernel.h:54
enum _FILE_INFORMATION_CLASS FILE_INFORMATION_CLASS
Definition: directory.c:44
struct _FILE_INTERNAL_INFORMATION FILE_INTERNAL_INFORMATION
#define FILE_OPEN_FOR_BACKUP_INTENT
Definition: from_kernel.h:42
VOID NTAPI CcSetFileSizes(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes)
Definition: fssup.c:356
Status
Definition: gdiplustypes.h:25
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
@ Deleted
Definition: kstypes.h:187
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define FILE_STANDARD_INFORMATION
Definition: disk.h:54
#define FILE_BASIC_INFORMATION
Definition: disk.h:53
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
static OUT PIO_STATUS_BLOCK OUT PVOID IN ULONG IN FILE_INFORMATION_CLASS FileInformationClass
Definition: pipe.c:75
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define min(a, b)
Definition: monoChain.cc:55
_In_ UINT _In_ UINT BytesToCopy
Definition: ndis.h:3168
#define KernelMode
Definition: asm.h:34
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
_In_ HANDLE _In_opt_ HANDLE _Out_opt_ PHANDLE TargetHandle
Definition: obfuncs.h:431
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define SYNCHRONIZE
Definition: nt_native.h:61
#define FILE_WRITE_DATA
Definition: nt_native.h:631
#define FILE_READ_DATA
Definition: nt_native.h:628
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
#define FILE_ATTRIBUTE_SYSTEM
Definition: nt_native.h:704
struct _FILE_POSITION_INFORMATION FILE_POSITION_INFORMATION
struct _FILE_ALIGNMENT_INFORMATION FILE_ALIGNMENT_INFORMATION
#define FILE_ATTRIBUTE_ARCHIVE
Definition: nt_native.h:706
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define FILE_ATTRIBUTE_TEMPORARY
Definition: nt_native.h:708
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
BOOLEAN NTAPI FsRtlAreNamesEqual(IN PCUNICODE_STRING Name1, IN PCUNICODE_STRING Name2, IN BOOLEAN IgnoreCase, IN PCWCH UpcaseTable OPTIONAL)
Definition: name.c:296
PDEVICE_OBJECT NTAPI IoGetRelatedDeviceObject(IN PFILE_OBJECT FileObject)
Definition: device.c:1539
NTSTATUS NTAPI IoCreateFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG Disposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength, IN CREATE_FILE_TYPE CreateFileType, IN PVOID ExtraCreateParameters OPTIONAL, IN ULONG Options)
Definition: file.c:3010
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
#define STATUS_USER_MAPPED_FILE
Definition: ntstatus.h:711
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define STATUS_NOT_SAME_DEVICE
Definition: ntstatus.h:448
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
struct _FILE_ACCESS_INFORMATION FILE_ACCESS_INFORMATION
#define FileStandardInformation
Definition: propsheet.cpp:61
#define _A_VOLID
Definition: dos.h:33
BOOLEAN NTAPI MmCanFileBeTruncated(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER NewFileSize)
Definition: section.c:4255
BOOLEAN NTAPI MmFlushImageSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN MMFLUSH_TYPE FlushType)
Definition: section.c:4356
#define STATUS_CANNOT_DELETE
Definition: shellext.h:71
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define DPRINT
Definition: sndvol32.h:71
base of all file and directory entries
Definition: entries.h:83
PDEVICE_OBJECT DeviceObject
Definition: vfat.h:584
ULONG Flags
Definition: vfat.h:586
PDEVICE_EXTENSION DeviceExt
Definition: vfat.h:585
PIO_STACK_LOCATION Stack
Definition: vfat.h:588
PFILE_OBJECT FileObject
Definition: vfat.h:591
PVOID DeviceExtension
Definition: env_spec_w32.h:418
Definition: cdstruc.h:902
LONGLONG CreationTime
Definition: cdstruc.h:1030
ULONG Flags
Definition: ntfs.h:536
FSRTL_COMMON_FCB_HEADER RFCB
Definition: ntfs.h:517
LONG RefCount
Definition: ntfs.h:535
ERESOURCE MainResource
Definition: ntfs.h:528
LARGE_INTEGER LastWriteTime
Definition: nt_native.h:941
LARGE_INTEGER CreationTime
Definition: nt_native.h:939
LARGE_INTEGER ChangeTime
Definition: nt_native.h:942
LARGE_INTEGER LastAccessTime
Definition: nt_native.h:940
LARGE_INTEGER CurrentByteOffset
Definition: nt_native.h:955
LARGE_INTEGER AllocationSize
Definition: propsheet.cpp:54
LARGE_INTEGER AllocationSize
Definition: env_spec_w32.h:755
LARGE_INTEGER ValidDataLength
Definition: env_spec_w32.h:757
union _IO_STACK_LOCATION::@1564 Parameters
struct _IO_STACK_LOCATION::@3978::@3988 SetFile
struct _IO_STACK_LOCATION::@3978::@3987 QueryFile
PVOID SystemBuffer
IO_STATUS_BLOCK IoStatus
union _IRP::@1566 AssociatedIrp
Definition: typedefs.h:120
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: vfat.h:448
PFILE_OBJECT FileObject
Definition: vfat.h:499
ULONG Flags
Definition: vfat.h:496
UNICODE_STRING PathNameU
Definition: vfat.h:472
struct _VFATFCB * parentFcb
Definition: vfat.h:490
LIST_ENTRY ParentListHead
Definition: vfat.h:493
ULONG OpenHandleCount
Definition: vfat.h:511
LONG RefCount
Definition: vfat.h:481
uint32_t * PULONG
Definition: typedefs.h:59
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned char * PBOOLEAN
Definition: typedefs.h:53
int64_t LONGLONG
Definition: typedefs.h:68
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_DIRECTORY_NOT_EMPTY
Definition: udferr_usr.h:167
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONGLONG QuadPart
Definition: typedefs.h:114
struct _LARGE_INTEGER::@2295 u
struct _VFATFCB * PVFATFCB
FORCEINLINE BOOLEAN vfatFCBIsReadOnly(PVFATFCB FCB)
Definition: vfat.h:644
#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
FORCEINLINE BOOLEAN VfatIsDirectoryEmpty(PDEVICE_EXTENSION DeviceExt, struct _VFATFCB *Fcb)
Definition: vfat.h:367
#define FCB_IS_DIRTY
Definition: vfat.h:438
FORCEINLINE NTSTATUS VfatDelEntry(PDEVICE_EXTENSION DeviceExt, struct _VFATFCB *Fcb, struct _VFAT_MOVE_CONTEXT *MoveContext)
Definition: vfat.h:388
#define TAG_NAME
Definition: vfat.h:553
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
VOID vfatSplitPathName(PUNICODE_STRING PathNameU, PUNICODE_STRING DirNameU, PUNICODE_STRING FileNameU)
Definition: fcb.c:54
BOOLEAN vfatFCBIsRoot(PVFATFCB FCB)
Definition: fcb.c:293
NTSTATUS vfatSetFCBNewDirName(PDEVICE_EXTENSION pVCB, PVFATFCB Fcb, PVFATFCB ParentFcb)
Definition: fcb.c:492
NTSTATUS vfatGetFCBForFile(PDEVICE_EXTENSION pVCB, PVFATFCB *pParentFCB, PVFATFCB *pFCB, PUNICODE_STRING pFileNameU)
Definition: fcb.c:883
VOID vfatReleaseFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
Definition: fcb.c:335
VOID vfatGrabFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
Definition: fcb.c:301
static NTSTATUS VfatGetInternalInformation(PVFATFCB Fcb, PDEVICE_EXTENSION DeviceExt, PFILE_INTERNAL_INFORMATION InternalInfo, PULONG BufferLength)
Definition: finfo.c:1015
static NTSTATUS vfatPrepareTargetForRename(IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB *ParentFCB, IN PUNICODE_STRING NewName, IN BOOLEAN ReplaceIfExists, IN PUNICODE_STRING ParentName, OUT PBOOLEAN Deleted)
Definition: finfo.c:410
static NTSTATUS VfatSetBasicInformation(PFILE_OBJECT FileObject, PVFATFCB FCB, PDEVICE_EXTENSION DeviceExt, PFILE_BASIC_INFORMATION BasicInfo)
Definition: finfo.c:151
static NTSTATUS VfatSetRenameInformation(PFILE_OBJECT FileObject, PVFATFCB FCB, PDEVICE_EXTENSION DeviceExt, PFILE_RENAME_INFORMATION RenameInfo, PFILE_OBJECT TargetFileObject)
Definition: finfo.c:558
static VOID UpdateFileSize(PFILE_OBJECT FileObject, PVFATFCB Fcb, ULONG Size, ULONG ClusterSize, BOOLEAN IsFatX)
Definition: finfo.c:1182
NTSTATUS VfatSetInformation(PVFAT_IRP_CONTEXT IrpContext)
Definition: finfo.c:1561
NTSTATUS VfatGetBasicInformation(PFILE_OBJECT FileObject, PVFATFCB FCB, PDEVICE_EXTENSION DeviceExt, PFILE_BASIC_INFORMATION BasicInfo, PULONG BufferLength)
Definition: finfo.c:280
static NTSTATUS VfatSetDispositionInformation(PFILE_OBJECT FileObject, PVFATFCB FCB, PDEVICE_EXTENSION DeviceExt, PFILE_DISPOSITION_INFORMATION DispositionInfo)
Definition: finfo.c:349
static NTSTATUS VfatGetNetworkOpenInformation(PVFATFCB Fcb, PDEVICE_EXTENSION DeviceExt, PFILE_NETWORK_OPEN_INFORMATION NetworkInfo, PULONG BufferLength)
Definition: finfo.c:1039
static NTSTATUS VfatGetPositionInformation(PFILE_OBJECT FileObject, PVFATFCB FCB, PDEVICE_EXTENSION DeviceExt, PFILE_POSITION_INFORMATION PositionInfo, PULONG BufferLength)
Definition: finfo.c:123
static VOID VfatRenameChildFCB(PDEVICE_EXTENSION DeviceExt, PVFATFCB FCB)
Definition: finfo.c:525
static NTSTATUS VfatGetAllInformation(PFILE_OBJECT FileObject, PVFATFCB Fcb, PDEVICE_EXTENSION DeviceExt, PFILE_ALL_INFORMATION Info, PULONG BufferLength)
Definition: finfo.c:1142
NTSTATUS VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject, PVFATFCB Fcb, PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER AllocationSize)
Definition: finfo.c:1211
static NTSTATUS VfatGetNameInformation(PFILE_OBJECT FileObject, PVFATFCB FCB, PDEVICE_EXTENSION DeviceExt, PFILE_NAME_INFORMATION NameInfo, PULONG BufferLength)
Definition: finfo.c:970
static BOOLEAN IsThereAChildOpened(PVFATFCB FCB)
Definition: finfo.c:496
NTSTATUS VfatQueryInformation(PVFAT_IRP_CONTEXT IrpContext)
Definition: finfo.c:1434
static NTSTATUS VfatGetEaInformation(PFILE_OBJECT FileObject, PVFATFCB Fcb, PDEVICE_EXTENSION DeviceExt, PFILE_EA_INFORMATION Info, PULONG BufferLength)
Definition: finfo.c:1114
NTSTATUS VfatGetStandardInformation(PVFATFCB FCB, PFILE_STANDARD_INFORMATION StandardInfo, PULONG BufferLength)
Definition: finfo.c:73
const char * FileInformationClassNames[]
Definition: finfo.c:21
static NTSTATUS VfatSetPositionInformation(PFILE_OBJECT FileObject, PFILE_POSITION_INFORMATION PositionInfo)
Definition: finfo.c:106
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFDEVICE Child
Definition: wdffdo.h:536
#define FILE_NOTIFY_CHANGE_SIZE
#define IO_FORCE_ACCESS_CHECK
Definition: iotypes.h:540
#define IO_OPEN_TARGET_DIRECTORY
Definition: iotypes.h:7352
#define FILE_ACTION_MODIFIED
#define FILE_ACTION_RENAMED_OLD_NAME
#define FILE_NOTIFY_CHANGE_LAST_ACCESS
#define FILE_NOTIFY_CHANGE_ATTRIBUTES
#define FILE_ACTION_REMOVED
#define FILE_NOTIFY_CHANGE_FILE_NAME
* PFILE_OBJECT
Definition: iotypes.h:1998
#define FILE_ACTION_RENAMED_NEW_NAME
@ CreateFileTypeNone
Definition: iotypes.h:535
#define FILE_NOTIFY_CHANGE_CREATION
#define FILE_NOTIFY_CHANGE_LAST_WRITE
#define FILE_NOTIFY_CHANGE_EA
#define FILE_ACTION_ADDED
#define FILE_NOTIFY_CHANGE_DIR_NAME
#define ObDereferenceObject
Definition: obfuncs.h:203
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
_In_opt_ HANDLE _In_opt_ PIO_APC_ROUTINE _In_opt_ PVOID _Out_ PIO_STATUS_BLOCK _In_ ULONG NotifyFilter
Definition: zwfuncs.h:504
_In_ PUNICODE_STRING NewName
Definition: zwfuncs.h:1203