2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/filesystems/fastfat/finfo.c
5 * PURPOSE: VFAT Filesystem
6 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
7 * Herve Poussineau (reactos@poussine.freesurf.fr)
8 * Pierre Schweitzer (pierre@reactos.org)
12 /* INCLUDES *****************************************************************/
19 /* GLOBALS ******************************************************************/
21 const char* FileInformationClassNames
[] =
24 "FileDirectoryInformation",
25 "FileFullDirectoryInformation",
26 "FileBothDirectoryInformation",
27 "FileBasicInformation",
28 "FileStandardInformation",
29 "FileInternalInformation",
31 "FileAccessInformation",
32 "FileNameInformation",
33 "FileRenameInformation",
34 "FileLinkInformation",
35 "FileNamesInformation",
36 "FileDispositionInformation",
37 "FilePositionInformation",
38 "FileFullEaInformation",
39 "FileModeInformation",
40 "FileAlignmentInformation",
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"
67 /* FUNCTIONS ****************************************************************/
70 * FUNCTION: Retrieve the standard file information
74 VfatGetStandardInformation(
76 PFILE_STANDARD_INFORMATION StandardInfo
,
79 if (*BufferLength
< sizeof(FILE_STANDARD_INFORMATION
))
80 return STATUS_BUFFER_OVERFLOW
;
83 ASSERT(StandardInfo
!= NULL
);
86 if (vfatFCBIsDirectory(FCB
))
88 StandardInfo
->AllocationSize
.QuadPart
= 0;
89 StandardInfo
->EndOfFile
.QuadPart
= 0;
90 StandardInfo
->Directory
= TRUE
;
94 StandardInfo
->AllocationSize
= FCB
->RFCB
.AllocationSize
;
95 StandardInfo
->EndOfFile
= FCB
->RFCB
.FileSize
;
96 StandardInfo
->Directory
= FALSE
;
98 StandardInfo
->NumberOfLinks
= 1;
99 StandardInfo
->DeletePending
= FCB
->Flags
& FCB_DELETE_PENDING
? TRUE
: FALSE
;
101 *BufferLength
-= sizeof(FILE_STANDARD_INFORMATION
);
102 return STATUS_SUCCESS
;
107 VfatSetPositionInformation(
108 PFILE_OBJECT FileObject
,
109 PFILE_POSITION_INFORMATION PositionInfo
)
111 DPRINT("FsdSetPositionInformation()\n");
113 DPRINT("PositionInfo %p\n", PositionInfo
);
114 DPRINT("Setting position %u\n", PositionInfo
->CurrentByteOffset
.u
.LowPart
);
116 FileObject
->CurrentByteOffset
.QuadPart
=
117 PositionInfo
->CurrentByteOffset
.QuadPart
;
119 return STATUS_SUCCESS
;
124 VfatGetPositionInformation(
125 PFILE_OBJECT FileObject
,
127 PDEVICE_OBJECT DeviceObject
,
128 PFILE_POSITION_INFORMATION PositionInfo
,
131 UNREFERENCED_PARAMETER(FileObject
);
132 UNREFERENCED_PARAMETER(FCB
);
133 UNREFERENCED_PARAMETER(DeviceObject
);
135 DPRINT("VfatGetPositionInformation()\n");
137 if (*BufferLength
< sizeof(FILE_POSITION_INFORMATION
))
138 return STATUS_BUFFER_OVERFLOW
;
140 PositionInfo
->CurrentByteOffset
.QuadPart
=
141 FileObject
->CurrentByteOffset
.QuadPart
;
143 DPRINT("Getting position %I64x\n",
144 PositionInfo
->CurrentByteOffset
.QuadPart
);
146 *BufferLength
-= sizeof(FILE_POSITION_INFORMATION
);
147 return STATUS_SUCCESS
;
152 VfatSetBasicInformation(
153 PFILE_OBJECT FileObject
,
155 PDEVICE_EXTENSION DeviceExt
,
156 PFILE_BASIC_INFORMATION BasicInfo
)
158 DPRINT("VfatSetBasicInformation()\n");
160 ASSERT(NULL
!= FileObject
);
162 ASSERT(NULL
!= DeviceExt
);
163 ASSERT(NULL
!= BasicInfo
);
164 /* Check volume label bit */
165 ASSERT(0 == (*FCB
->Attributes
& _A_VOLID
));
167 if (FCB
->Flags
& FCB_IS_FATX_ENTRY
)
169 if (BasicInfo
->CreationTime
.QuadPart
!= 0 && BasicInfo
->CreationTime
.QuadPart
!= -1)
171 FsdSystemTimeToDosDateTime(DeviceExt
,
172 &BasicInfo
->CreationTime
,
173 &FCB
->entry
.FatX
.CreationDate
,
174 &FCB
->entry
.FatX
.CreationTime
);
177 if (BasicInfo
->LastAccessTime
.QuadPart
!= 0 && BasicInfo
->LastAccessTime
.QuadPart
!= -1)
179 FsdSystemTimeToDosDateTime(DeviceExt
,
180 &BasicInfo
->LastAccessTime
,
181 &FCB
->entry
.FatX
.AccessDate
,
182 &FCB
->entry
.FatX
.AccessTime
);
185 if (BasicInfo
->LastWriteTime
.QuadPart
!= 0 && BasicInfo
->LastWriteTime
.QuadPart
!= -1)
187 FsdSystemTimeToDosDateTime(DeviceExt
,
188 &BasicInfo
->LastWriteTime
,
189 &FCB
->entry
.FatX
.UpdateDate
,
190 &FCB
->entry
.FatX
.UpdateTime
);
195 if (BasicInfo
->CreationTime
.QuadPart
!= 0 && BasicInfo
->CreationTime
.QuadPart
!= -1)
197 FsdSystemTimeToDosDateTime(DeviceExt
,
198 &BasicInfo
->CreationTime
,
199 &FCB
->entry
.Fat
.CreationDate
,
200 &FCB
->entry
.Fat
.CreationTime
);
203 if (BasicInfo
->LastAccessTime
.QuadPart
!= 0 && BasicInfo
->LastAccessTime
.QuadPart
!= -1)
205 FsdSystemTimeToDosDateTime(DeviceExt
,
206 &BasicInfo
->LastAccessTime
,
207 &FCB
->entry
.Fat
.AccessDate
,
211 if (BasicInfo
->LastWriteTime
.QuadPart
!= 0 && BasicInfo
->LastWriteTime
.QuadPart
!= -1)
213 FsdSystemTimeToDosDateTime(DeviceExt
,
214 &BasicInfo
->LastWriteTime
,
215 &FCB
->entry
.Fat
.UpdateDate
,
216 &FCB
->entry
.Fat
.UpdateTime
);
220 if (BasicInfo
->FileAttributes
)
222 *FCB
->Attributes
= (unsigned char)((*FCB
->Attributes
&
223 (FILE_ATTRIBUTE_DIRECTORY
| 0x48)) |
224 (BasicInfo
->FileAttributes
&
225 (FILE_ATTRIBUTE_ARCHIVE
|
226 FILE_ATTRIBUTE_SYSTEM
|
227 FILE_ATTRIBUTE_HIDDEN
|
228 FILE_ATTRIBUTE_READONLY
)));
229 DPRINT("Setting attributes 0x%02x\n", *FCB
->Attributes
);
232 VfatUpdateEntry(FCB
);
234 return STATUS_SUCCESS
;
239 VfatGetBasicInformation(
240 PFILE_OBJECT FileObject
,
242 PDEVICE_OBJECT DeviceObject
,
243 PFILE_BASIC_INFORMATION BasicInfo
,
246 PDEVICE_EXTENSION DeviceExt
;
248 UNREFERENCED_PARAMETER(FileObject
);
250 DPRINT("VfatGetBasicInformation()\n");
252 DeviceExt
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
254 if (*BufferLength
< sizeof(FILE_BASIC_INFORMATION
))
255 return STATUS_BUFFER_OVERFLOW
;
257 if (FCB
->Flags
& FCB_IS_FATX_ENTRY
)
259 FsdDosDateTimeToSystemTime(DeviceExt
,
260 FCB
->entry
.FatX
.CreationDate
,
261 FCB
->entry
.FatX
.CreationTime
,
262 &BasicInfo
->CreationTime
);
263 FsdDosDateTimeToSystemTime(DeviceExt
,
264 FCB
->entry
.FatX
.AccessDate
,
265 FCB
->entry
.FatX
.AccessTime
,
266 &BasicInfo
->LastAccessTime
);
267 FsdDosDateTimeToSystemTime(DeviceExt
,
268 FCB
->entry
.FatX
.UpdateDate
,
269 FCB
->entry
.FatX
.UpdateTime
,
270 &BasicInfo
->LastWriteTime
);
271 BasicInfo
->ChangeTime
= BasicInfo
->LastWriteTime
;
275 FsdDosDateTimeToSystemTime(DeviceExt
,
276 FCB
->entry
.Fat
.CreationDate
,
277 FCB
->entry
.Fat
.CreationTime
,
278 &BasicInfo
->CreationTime
);
279 FsdDosDateTimeToSystemTime(DeviceExt
,
280 FCB
->entry
.Fat
.AccessDate
,
282 &BasicInfo
->LastAccessTime
);
283 FsdDosDateTimeToSystemTime(DeviceExt
,
284 FCB
->entry
.Fat
.UpdateDate
,
285 FCB
->entry
.Fat
.UpdateTime
,
286 &BasicInfo
->LastWriteTime
);
287 BasicInfo
->ChangeTime
= BasicInfo
->LastWriteTime
;
290 BasicInfo
->FileAttributes
= *FCB
->Attributes
& 0x3f;
291 /* Synthesize FILE_ATTRIBUTE_NORMAL */
292 if (0 == (BasicInfo
->FileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|
293 FILE_ATTRIBUTE_ARCHIVE
|
294 FILE_ATTRIBUTE_SYSTEM
|
295 FILE_ATTRIBUTE_HIDDEN
|
296 FILE_ATTRIBUTE_READONLY
)))
298 DPRINT("Synthesizing FILE_ATTRIBUTE_NORMAL\n");
299 BasicInfo
->FileAttributes
|= FILE_ATTRIBUTE_NORMAL
;
301 DPRINT("Getting attributes 0x%02x\n", BasicInfo
->FileAttributes
);
303 *BufferLength
-= sizeof(FILE_BASIC_INFORMATION
);
304 return STATUS_SUCCESS
;
310 VfatSetDispositionInformation(
311 PFILE_OBJECT FileObject
,
313 PDEVICE_OBJECT DeviceObject
,
314 PFILE_DISPOSITION_INFORMATION DispositionInfo
)
317 PDEVICE_EXTENSION DeviceExt
= DeviceObject
->DeviceExtension
;
320 DPRINT("FsdSetDispositionInformation(<%wZ>, Delete %u)\n", &FCB
->PathNameU
, DispositionInfo
->DeleteFile
);
322 ASSERT(DeviceExt
!= NULL
);
323 ASSERT(DeviceExt
->FatInfo
.BytesPerCluster
!= 0);
326 if (!DispositionInfo
->DeleteFile
)
328 /* undelete the file */
329 FCB
->Flags
&= ~FCB_DELETE_PENDING
;
330 FileObject
->DeletePending
= FALSE
;
331 return STATUS_SUCCESS
;
334 if (FCB
->Flags
& FCB_DELETE_PENDING
)
336 /* stream already marked for deletion. just update the file object */
337 FileObject
->DeletePending
= TRUE
;
338 return STATUS_SUCCESS
;
341 if (*FCB
->Attributes
& FILE_ATTRIBUTE_READONLY
)
343 return STATUS_CANNOT_DELETE
;
346 if (vfatFCBIsRoot(FCB
) ||
347 (FCB
->LongNameU
.Length
== sizeof(WCHAR
) && FCB
->LongNameU
.Buffer
[0] == L
'.') ||
348 (FCB
->LongNameU
.Length
== 2 * sizeof(WCHAR
) && FCB
->LongNameU
.Buffer
[0] == L
'.' && FCB
->LongNameU
.Buffer
[1] == L
'.'))
350 // we cannot delete a '.', '..' or the root directory
351 return STATUS_ACCESS_DENIED
;
355 if (!MmFlushImageSection (FileObject
->SectionObjectPointer
, MmFlushForDelete
))
357 /* can't delete a file if its mapped into a process */
359 DPRINT("MmFlushImageSection returned FALSE\n");
360 return STATUS_CANNOT_DELETE
;
363 if (vfatFCBIsDirectory(FCB
) && !VfatIsDirectoryEmpty(FCB
))
365 /* can't delete a non-empty directory */
367 return STATUS_DIRECTORY_NOT_EMPTY
;
371 FCB
->Flags
|= FCB_DELETE_PENDING
;
372 FileObject
->DeletePending
= TRUE
;
374 return STATUS_SUCCESS
;
378 vfatPrepareTargetForRename(
379 IN PDEVICE_EXTENSION DeviceExt
,
380 IN PVFATFCB
* ParentFCB
,
381 IN PUNICODE_STRING NewName
,
382 IN BOOLEAN ReplaceIfExists
,
383 IN PUNICODE_STRING ParentName
,
384 OUT PBOOLEAN Deleted
)
389 DPRINT("vfatPrepareTargetForRename(%p, %p, %wZ, %d, %wZ, %p)\n", DeviceExt
, ParentFCB
, NewName
, ReplaceIfExists
, ParentName
);
392 /* Try to open target */
393 Status
= vfatGetFCBForFile(DeviceExt
, ParentFCB
, &TargetFcb
, NewName
);
395 if (NT_SUCCESS(Status
))
397 /* Check whether we are allowed to replace */
400 /* If that's a directory or a read-only file, we're not allowed */
401 if (vfatFCBIsDirectory(TargetFcb
) || ((*TargetFcb
->Attributes
& FILE_ATTRIBUTE_READONLY
) == FILE_ATTRIBUTE_READONLY
));
403 vfatReleaseFCB(DeviceExt
, *ParentFCB
);
405 vfatReleaseFCB(DeviceExt
, TargetFcb
);
406 return STATUS_OBJECT_NAME_COLLISION
;
409 /* Attempt to flush (might close the file) */
410 if (!MmFlushImageSection(TargetFcb
->FileObject
->SectionObjectPointer
, MmFlushForDelete
))
412 vfatReleaseFCB(DeviceExt
, *ParentFCB
);
414 vfatReleaseFCB(DeviceExt
, TargetFcb
);
415 return STATUS_ACCESS_DENIED
;
418 /* If we are, ensure the file isn't open by anyone! */
419 if (TargetFcb
->OpenHandleCount
!= 0)
421 vfatReleaseFCB(DeviceExt
, *ParentFCB
);
423 vfatReleaseFCB(DeviceExt
, TargetFcb
);
424 return STATUS_ACCESS_DENIED
;
427 /* Effectively delete old file to allow renaming */
428 VfatDelEntry(DeviceExt
, TargetFcb
, NULL
);
429 vfatGrabFCB(DeviceExt
, *ParentFCB
);
430 vfatReleaseFCB(DeviceExt
, TargetFcb
);
435 vfatReleaseFCB(DeviceExt
, *ParentFCB
);
437 vfatReleaseFCB(DeviceExt
, TargetFcb
);
438 return STATUS_OBJECT_NAME_COLLISION
;
441 else if (*ParentFCB
!= NULL
)
443 return STATUS_SUCCESS
;
451 * FUNCTION: Set the file name information
455 VfatSetRenameInformation(
456 PFILE_OBJECT FileObject
,
458 PDEVICE_EXTENSION DeviceExt
,
459 PFILE_RENAME_INFORMATION RenameInfo
,
460 PFILE_OBJECT TargetFileObject
)
463 UNICODE_STRING NewName
;
464 UNICODE_STRING SourcePath
;
465 UNICODE_STRING SourceFile
;
466 UNICODE_STRING NewPath
;
467 UNICODE_STRING NewFile
;
468 PFILE_OBJECT RootFileObject
;
470 UNICODE_STRING RenameInfoString
;
472 IO_STATUS_BLOCK IoStatusBlock
;
473 OBJECT_ATTRIBUTES ObjectAttributes
;
475 BOOLEAN DeletedTarget
;
477 DPRINT("VfatSetRenameInfo(%p, %p, %p, %p, %p)\n", FileObject
, FCB
, DeviceExt
, RenameInfo
, TargetFileObject
);
479 /* Disallow renaming root */
480 if (vfatFCBIsRoot(FCB
))
482 return STATUS_INVALID_PARAMETER
;
485 /* If we are performing relative opening for rename, get FO for getting FCB and path name */
486 if (RenameInfo
->RootDirectory
!= NULL
)
488 /* We cannot tolerate relative opening with a full path */
489 if (RenameInfo
->FileName
[0] == L
'\\')
491 return STATUS_OBJECT_NAME_INVALID
;
494 Status
= ObReferenceObjectByHandle(RenameInfo
->RootDirectory
,
498 (PVOID
*)&RootFileObject
,
500 if (!NT_SUCCESS(Status
))
505 RootFCB
= RootFileObject
->FsContext
;
510 if (TargetFileObject
== NULL
)
512 /* If we don't have target file object, construct paths thanks to relative FCB, if any, and with
513 * information supplied by the user
516 /* First, setup a string we'll work on */
517 RenameInfoString
.Length
= RenameInfo
->FileNameLength
;
518 RenameInfoString
.MaximumLength
= RenameInfo
->FileNameLength
;
519 RenameInfoString
.Buffer
= RenameInfo
->FileName
;
521 /* Check whether we have FQN */
522 if (RenameInfoString
.Length
> 6 * sizeof(WCHAR
))
524 if (RenameInfoString
.Buffer
[0] == L
'\\' && RenameInfoString
.Buffer
[1] == L
'?' &&
525 RenameInfoString
.Buffer
[2] == L
'?' && RenameInfoString
.Buffer
[3] == L
'\\' &&
526 RenameInfoString
.Buffer
[5] == L
':' && (RenameInfoString
.Buffer
[4] >= L
'A' &&
527 RenameInfoString
.Buffer
[4] <= L
'Z'))
529 /* If so, open its target directory */
530 InitializeObjectAttributes(&ObjectAttributes
,
532 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
535 Status
= IoCreateFile(&TargetHandle
,
536 FILE_WRITE_DATA
| SYNCHRONIZE
,
540 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
542 FILE_OPEN_FOR_BACKUP_INTENT
,
546 IO_FORCE_ACCESS_CHECK
| IO_OPEN_TARGET_DIRECTORY
);
547 if (!NT_SUCCESS(Status
))
552 /* Get its FO to get the FCB */
553 Status
= ObReferenceObjectByHandle(TargetHandle
,
557 (PVOID
*)&TargetFileObject
,
559 if (!NT_SUCCESS(Status
))
561 ZwClose(TargetHandle
);
565 /* Are we working on the same volume? */
566 if (IoGetRelatedDeviceObject(TargetFileObject
) != IoGetRelatedDeviceObject(FileObject
))
568 ObDereferenceObject(TargetFileObject
);
569 ZwClose(TargetHandle
);
570 TargetFileObject
= NULL
;
571 Status
= STATUS_NOT_SAME_DEVICE
;
578 NewName
.MaximumLength
= RenameInfo
->FileNameLength
;
579 if (RenameInfo
->RootDirectory
!= NULL
)
581 NewName
.MaximumLength
+= sizeof(WCHAR
) + RootFCB
->PathNameU
.Length
;
583 else if (RenameInfo
->FileName
[0] != L
'\\')
585 /* We don't have full path, and we don't have root directory:
586 * => we move inside the same directory
588 NewName
.MaximumLength
+= sizeof(WCHAR
) + FCB
->DirNameU
.Length
;
590 else if (TargetFileObject
!= NULL
)
593 * => we need to use its correct path
595 NewName
.MaximumLength
+= sizeof(WCHAR
) + ((PVFATFCB
)TargetFileObject
->FsContext
)->PathNameU
.Length
;
598 NewName
.Buffer
= ExAllocatePoolWithTag(NonPagedPool
, NewName
.MaximumLength
, TAG_VFAT
);
599 if (NewName
.Buffer
== NULL
)
601 if (TargetFileObject
!= NULL
)
603 ObDereferenceObject(TargetFileObject
);
604 ZwClose(TargetHandle
);
605 TargetFileObject
= NULL
;
607 Status
= STATUS_INSUFFICIENT_RESOURCES
;
611 if (RenameInfo
->RootDirectory
!= NULL
)
613 /* Here, copy first absolute and then append relative */
614 RtlCopyUnicodeString(&NewName
, &RootFCB
->PathNameU
);
615 NewName
.Buffer
[NewName
.Length
/ sizeof(WCHAR
)] = L
'\\';
616 NewName
.Length
+= sizeof(WCHAR
);
617 RtlAppendUnicodeStringToString(&NewName
, &RenameInfoString
);
619 else if (RenameInfo
->FileName
[0] != L
'\\')
621 /* Here, copy first work directory and then append filename */
622 RtlCopyUnicodeString(&NewName
, &FCB
->DirNameU
);
623 NewName
.Buffer
[NewName
.Length
/ sizeof(WCHAR
)] = L
'\\';
624 NewName
.Length
+= sizeof(WCHAR
);
625 RtlAppendUnicodeStringToString(&NewName
, &RenameInfoString
);
627 else if (TargetFileObject
!= NULL
)
629 /* Here, copy first path name and then append filename */
630 RtlCopyUnicodeString(&NewName
, &((PVFATFCB
)TargetFileObject
->FsContext
)->PathNameU
);
631 NewName
.Buffer
[NewName
.Length
/ sizeof(WCHAR
)] = L
'\\';
632 NewName
.Length
+= sizeof(WCHAR
);
633 RtlAppendUnicodeStringToString(&NewName
, &RenameInfoString
);
637 /* Here we should have full path, so simply copy it */
638 RtlCopyUnicodeString(&NewName
, &RenameInfoString
);
641 /* Do we have to cleanup some stuff? */
642 if (TargetFileObject
!= NULL
)
644 ObDereferenceObject(TargetFileObject
);
645 ZwClose(TargetHandle
);
646 TargetFileObject
= NULL
;
651 /* At that point, we shouldn't care about whether we are relative opening
652 * Target FO FCB should already have full path
655 /* Before constructing string, just make a sanity check (just to be sure!) */
656 if (IoGetRelatedDeviceObject(TargetFileObject
) != IoGetRelatedDeviceObject(FileObject
))
658 Status
= STATUS_NOT_SAME_DEVICE
;
663 NewName
.MaximumLength
= TargetFileObject
->FileName
.Length
+ ((PVFATFCB
)TargetFileObject
->FsContext
)->PathNameU
.Length
+ sizeof(WCHAR
);
664 NewName
.Buffer
= ExAllocatePoolWithTag(NonPagedPool
, NewName
.MaximumLength
, TAG_VFAT
);
665 if (NewName
.Buffer
== NULL
)
667 Status
= STATUS_INSUFFICIENT_RESOURCES
;
671 RtlCopyUnicodeString(&NewName
, &((PVFATFCB
)TargetFileObject
->FsContext
)->PathNameU
);
672 NewName
.Buffer
[NewName
.Length
/ sizeof(WCHAR
)] = L
'\\';
673 NewName
.Length
+= sizeof(WCHAR
);
674 RtlAppendUnicodeStringToString(&NewName
, &TargetFileObject
->FileName
);
677 /* Explode our paths to get path & filename */
678 vfatSplitPathName(&FCB
->PathNameU
, &SourcePath
, &SourceFile
);
679 DPRINT("Old dir: %wZ, Old file: %wZ\n", &SourcePath
, &SourceFile
);
680 vfatSplitPathName(&NewName
, &NewPath
, &NewFile
);
681 DPRINT("New dir: %wZ, New file: %wZ\n", &NewPath
, &NewFile
);
683 /* Are we working in place? */
684 if (FsRtlAreNamesEqual(&SourcePath
, &NewPath
, TRUE
, NULL
))
686 if (FsRtlAreNamesEqual(&SourceFile
, &NewFile
, FALSE
, NULL
))
688 Status
= STATUS_SUCCESS
;
692 if (FsRtlAreNamesEqual(&SourceFile
, &NewFile
, TRUE
, NULL
))
694 FsRtlNotifyFullReportChange(DeviceExt
->NotifySync
,
695 &(DeviceExt
->NotifyList
),
696 (PSTRING
)&FCB
->PathNameU
,
697 FCB
->PathNameU
.Length
- FCB
->LongNameU
.Length
,
700 ((*FCB
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
) ?
701 FILE_NOTIFY_CHANGE_DIR_NAME
: FILE_NOTIFY_CHANGE_FILE_NAME
),
702 FILE_ACTION_RENAMED_OLD_NAME
,
704 Status
= vfatRenameEntry(DeviceExt
, FCB
, &NewFile
, TRUE
);
705 if (NT_SUCCESS(Status
))
707 FsRtlNotifyFullReportChange(DeviceExt
->NotifySync
,
708 &(DeviceExt
->NotifyList
),
709 (PSTRING
)&FCB
->PathNameU
,
710 FCB
->PathNameU
.Length
- FCB
->LongNameU
.Length
,
713 ((*FCB
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
) ?
714 FILE_NOTIFY_CHANGE_DIR_NAME
: FILE_NOTIFY_CHANGE_FILE_NAME
),
715 FILE_ACTION_RENAMED_NEW_NAME
,
721 /* Try to find target */
722 ParentFCB
= FCB
->parentFcb
;
723 vfatGrabFCB(DeviceExt
, ParentFCB
);
724 Status
= vfatPrepareTargetForRename(DeviceExt
,
727 RenameInfo
->ReplaceIfExists
,
730 if (!NT_SUCCESS(Status
))
735 FsRtlNotifyFullReportChange(DeviceExt
->NotifySync
,
736 &(DeviceExt
->NotifyList
),
737 (PSTRING
)&FCB
->PathNameU
,
738 FCB
->PathNameU
.Length
- FCB
->LongNameU
.Length
,
741 ((*FCB
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
) ?
742 FILE_NOTIFY_CHANGE_DIR_NAME
: FILE_NOTIFY_CHANGE_FILE_NAME
),
743 (DeletedTarget
? FILE_ACTION_REMOVED
: FILE_ACTION_RENAMED_OLD_NAME
),
745 Status
= vfatRenameEntry(DeviceExt
, FCB
, &NewFile
, FALSE
);
746 if (NT_SUCCESS(Status
))
750 FsRtlNotifyFullReportChange(DeviceExt
->NotifySync
,
751 &(DeviceExt
->NotifyList
),
752 (PSTRING
)&FCB
->PathNameU
,
753 FCB
->PathNameU
.Length
- FCB
->LongNameU
.Length
,
756 FILE_NOTIFY_CHANGE_ATTRIBUTES
| FILE_NOTIFY_CHANGE_SIZE
| FILE_NOTIFY_CHANGE_LAST_WRITE
757 | FILE_NOTIFY_CHANGE_LAST_ACCESS
| FILE_NOTIFY_CHANGE_CREATION
| FILE_NOTIFY_CHANGE_EA
,
758 FILE_ACTION_MODIFIED
,
763 FsRtlNotifyFullReportChange(DeviceExt
->NotifySync
,
764 &(DeviceExt
->NotifyList
),
765 (PSTRING
)&FCB
->PathNameU
,
766 FCB
->PathNameU
.Length
- FCB
->LongNameU
.Length
,
769 ((*FCB
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
) ?
770 FILE_NOTIFY_CHANGE_DIR_NAME
: FILE_NOTIFY_CHANGE_FILE_NAME
),
771 FILE_ACTION_RENAMED_NEW_NAME
,
779 /* Try to find target */
781 Status
= vfatPrepareTargetForRename(DeviceExt
,
784 RenameInfo
->ReplaceIfExists
,
787 if (!NT_SUCCESS(Status
))
792 FsRtlNotifyFullReportChange(DeviceExt
->NotifySync
,
793 &(DeviceExt
->NotifyList
),
794 (PSTRING
)&FCB
->PathNameU
,
795 FCB
->PathNameU
.Length
- FCB
->LongNameU
.Length
,
798 ((*FCB
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
) ?
799 FILE_NOTIFY_CHANGE_DIR_NAME
: FILE_NOTIFY_CHANGE_FILE_NAME
),
802 Status
= VfatMoveEntry(DeviceExt
, FCB
, &NewFile
, ParentFCB
);
803 if (NT_SUCCESS(Status
))
807 FsRtlNotifyFullReportChange(DeviceExt
->NotifySync
,
808 &(DeviceExt
->NotifyList
),
809 (PSTRING
)&FCB
->PathNameU
,
810 FCB
->PathNameU
.Length
- FCB
->LongNameU
.Length
,
813 FILE_NOTIFY_CHANGE_ATTRIBUTES
| FILE_NOTIFY_CHANGE_SIZE
| FILE_NOTIFY_CHANGE_LAST_WRITE
814 | FILE_NOTIFY_CHANGE_LAST_ACCESS
| FILE_NOTIFY_CHANGE_CREATION
| FILE_NOTIFY_CHANGE_EA
,
815 FILE_ACTION_MODIFIED
,
820 FsRtlNotifyFullReportChange(DeviceExt
->NotifySync
,
821 &(DeviceExt
->NotifyList
),
822 (PSTRING
)&FCB
->PathNameU
,
823 FCB
->PathNameU
.Length
- FCB
->LongNameU
.Length
,
826 ((*FCB
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
) ?
827 FILE_NOTIFY_CHANGE_DIR_NAME
: FILE_NOTIFY_CHANGE_FILE_NAME
),
835 if (ParentFCB
!= NULL
) vfatReleaseFCB(DeviceExt
, ParentFCB
);
836 if (NewName
.Buffer
!= NULL
) ExFreePoolWithTag(NewName
.Buffer
, TAG_VFAT
);
837 if (RenameInfo
->RootDirectory
!= NULL
) ObDereferenceObject(RootFileObject
);
843 * FUNCTION: Retrieve the file name information
847 VfatGetNameInformation(
848 PFILE_OBJECT FileObject
,
850 PDEVICE_OBJECT DeviceObject
,
851 PFILE_NAME_INFORMATION NameInfo
,
856 UNREFERENCED_PARAMETER(FileObject
);
857 UNREFERENCED_PARAMETER(DeviceObject
);
859 ASSERT(NameInfo
!= NULL
);
862 /* If buffer can't hold at least the file name length, bail out */
863 if (*BufferLength
< (ULONG
)FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
[0]))
864 return STATUS_BUFFER_OVERFLOW
;
866 /* Save file name length, and as much file len, as buffer length allows */
867 NameInfo
->FileNameLength
= FCB
->PathNameU
.Length
;
869 /* Calculate amount of bytes to copy not to overflow the buffer */
870 BytesToCopy
= min(FCB
->PathNameU
.Length
,
871 *BufferLength
- FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
[0]));
873 /* Fill in the bytes */
874 RtlCopyMemory(NameInfo
->FileName
, FCB
->PathNameU
.Buffer
, BytesToCopy
);
876 /* Check if we could write more but are not able to */
877 if (*BufferLength
< FCB
->PathNameU
.Length
+ (ULONG
)FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
[0]))
879 /* Return number of bytes written */
880 *BufferLength
-= FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
[0]) + BytesToCopy
;
881 return STATUS_BUFFER_OVERFLOW
;
884 /* We filled up as many bytes, as needed */
885 *BufferLength
-= (FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
[0]) + FCB
->PathNameU
.Length
);
887 return STATUS_SUCCESS
;
892 VfatGetInternalInformation(
894 PFILE_INTERNAL_INFORMATION InternalInfo
,
897 ASSERT(InternalInfo
);
900 if (*BufferLength
< sizeof(FILE_INTERNAL_INFORMATION
))
901 return STATUS_BUFFER_OVERFLOW
;
902 // FIXME: get a real index, that can be used in a create operation
903 InternalInfo
->IndexNumber
.QuadPart
= 0;
904 *BufferLength
-= sizeof(FILE_INTERNAL_INFORMATION
);
905 return STATUS_SUCCESS
;
910 * FUNCTION: Retrieve the file network open information
914 VfatGetNetworkOpenInformation(
916 PDEVICE_EXTENSION DeviceExt
,
917 PFILE_NETWORK_OPEN_INFORMATION NetworkInfo
,
923 if (*BufferLength
< sizeof(FILE_NETWORK_OPEN_INFORMATION
))
924 return(STATUS_BUFFER_OVERFLOW
);
926 if (Fcb
->Flags
& FCB_IS_FATX_ENTRY
)
928 FsdDosDateTimeToSystemTime(DeviceExt
,
929 Fcb
->entry
.FatX
.CreationDate
,
930 Fcb
->entry
.FatX
.CreationTime
,
931 &NetworkInfo
->CreationTime
);
932 FsdDosDateTimeToSystemTime(DeviceExt
,
933 Fcb
->entry
.FatX
.AccessDate
,
934 Fcb
->entry
.FatX
.AccessTime
,
935 &NetworkInfo
->LastAccessTime
);
936 FsdDosDateTimeToSystemTime(DeviceExt
,
937 Fcb
->entry
.FatX
.UpdateDate
,
938 Fcb
->entry
.FatX
.UpdateTime
,
939 &NetworkInfo
->LastWriteTime
);
940 NetworkInfo
->ChangeTime
.QuadPart
= NetworkInfo
->LastWriteTime
.QuadPart
;
944 FsdDosDateTimeToSystemTime(DeviceExt
,
945 Fcb
->entry
.Fat
.CreationDate
,
946 Fcb
->entry
.Fat
.CreationTime
,
947 &NetworkInfo
->CreationTime
);
948 FsdDosDateTimeToSystemTime(DeviceExt
,
949 Fcb
->entry
.Fat
.AccessDate
,
951 &NetworkInfo
->LastAccessTime
);
952 FsdDosDateTimeToSystemTime(DeviceExt
,
953 Fcb
->entry
.Fat
.UpdateDate
,
954 Fcb
->entry
.Fat
.UpdateTime
,
955 &NetworkInfo
->LastWriteTime
);
956 NetworkInfo
->ChangeTime
.QuadPart
= NetworkInfo
->LastWriteTime
.QuadPart
;
959 if (vfatFCBIsDirectory(Fcb
))
961 NetworkInfo
->EndOfFile
.QuadPart
= 0L;
962 NetworkInfo
->AllocationSize
.QuadPart
= 0L;
966 NetworkInfo
->AllocationSize
= Fcb
->RFCB
.AllocationSize
;
967 NetworkInfo
->EndOfFile
= Fcb
->RFCB
.FileSize
;
970 NetworkInfo
->FileAttributes
= *Fcb
->Attributes
& 0x3f;
971 /* Synthesize FILE_ATTRIBUTE_NORMAL */
972 if (0 == (NetworkInfo
->FileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|
973 FILE_ATTRIBUTE_ARCHIVE
|
974 FILE_ATTRIBUTE_SYSTEM
|
975 FILE_ATTRIBUTE_HIDDEN
|
976 FILE_ATTRIBUTE_READONLY
)))
978 DPRINT("Synthesizing FILE_ATTRIBUTE_NORMAL\n");
979 NetworkInfo
->FileAttributes
|= FILE_ATTRIBUTE_NORMAL
;
982 *BufferLength
-= sizeof(FILE_NETWORK_OPEN_INFORMATION
);
983 return STATUS_SUCCESS
;
989 VfatGetEaInformation(
990 PFILE_OBJECT FileObject
,
992 PDEVICE_OBJECT DeviceObject
,
993 PFILE_EA_INFORMATION Info
,
996 PDEVICE_EXTENSION DeviceExt
= DeviceObject
->DeviceExtension
;
998 UNREFERENCED_PARAMETER(FileObject
);
999 UNREFERENCED_PARAMETER(Fcb
);
1001 /* FIXME - use SEH to access the buffer! */
1003 *BufferLength
-= sizeof(*Info
);
1004 if (DeviceExt
->FatInfo
.FatType
== FAT12
||
1005 DeviceExt
->FatInfo
.FatType
== FAT16
)
1008 DPRINT1("VFAT: FileEaInformation not implemented!\n");
1010 return STATUS_SUCCESS
;
1015 * FUNCTION: Retrieve the all file information
1019 VfatGetAllInformation(
1020 PFILE_OBJECT FileObject
,
1022 PDEVICE_OBJECT DeviceObject
,
1023 PFILE_ALL_INFORMATION Info
,
1024 PULONG BufferLength
)
1027 ULONG InitialBufferLength
= *BufferLength
;
1032 if (*BufferLength
< sizeof(FILE_ALL_INFORMATION
) + Fcb
->PathNameU
.Length
+ sizeof(WCHAR
))
1033 return(STATUS_BUFFER_OVERFLOW
);
1035 /* Basic Information */
1036 Status
= VfatGetBasicInformation(FileObject
, Fcb
, DeviceObject
, &Info
->BasicInformation
, BufferLength
);
1037 if (!NT_SUCCESS(Status
)) return Status
;
1038 /* Standard Information */
1039 Status
= VfatGetStandardInformation(Fcb
, &Info
->StandardInformation
, BufferLength
);
1040 if (!NT_SUCCESS(Status
)) return Status
;
1041 /* Internal Information */
1042 Status
= VfatGetInternalInformation(Fcb
, &Info
->InternalInformation
, BufferLength
);
1043 if (!NT_SUCCESS(Status
)) return Status
;
1044 /* EA Information */
1045 Info
->EaInformation
.EaSize
= 0;
1046 /* Access Information: The IO-Manager adds this information */
1047 /* Position Information */
1048 Status
= VfatGetPositionInformation(FileObject
, Fcb
, DeviceObject
, &Info
->PositionInformation
, BufferLength
);
1049 if (!NT_SUCCESS(Status
)) return Status
;
1050 /* Mode Information: The IO-Manager adds this information */
1051 /* Alignment Information: The IO-Manager adds this information */
1052 /* Name Information */
1053 Status
= VfatGetNameInformation(FileObject
, Fcb
, DeviceObject
, &Info
->NameInformation
, BufferLength
);
1054 if (!NT_SUCCESS(Status
)) return Status
;
1056 *BufferLength
= InitialBufferLength
- (sizeof(FILE_ALL_INFORMATION
) + Fcb
->PathNameU
.Length
+ sizeof(WCHAR
));
1058 return STATUS_SUCCESS
;
1064 PFILE_OBJECT FileObject
,
1071 Fcb
->RFCB
.AllocationSize
.QuadPart
= ROUND_UP(Size
, ClusterSize
);
1075 Fcb
->RFCB
.AllocationSize
.QuadPart
= (LONGLONG
)0;
1077 if (!vfatFCBIsDirectory(Fcb
))
1079 if (Fcb
->Flags
& FCB_IS_FATX_ENTRY
)
1080 Fcb
->entry
.FatX
.FileSize
= Size
;
1082 Fcb
->entry
.Fat
.FileSize
= Size
;
1084 Fcb
->RFCB
.FileSize
.QuadPart
= Size
;
1085 Fcb
->RFCB
.ValidDataLength
.QuadPart
= Size
;
1087 CcSetFileSizes(FileObject
, (PCC_FILE_SIZES
)&Fcb
->RFCB
.AllocationSize
);
1091 VfatSetAllocationSizeInformation(
1092 PFILE_OBJECT FileObject
,
1094 PDEVICE_EXTENSION DeviceExt
,
1095 PLARGE_INTEGER AllocationSize
)
1098 ULONG Cluster
, FirstCluster
;
1101 ULONG ClusterSize
= DeviceExt
->FatInfo
.BytesPerCluster
;
1102 ULONG NewSize
= AllocationSize
->u
.LowPart
;
1104 BOOLEAN AllocSizeChanged
= FALSE
;
1106 DPRINT("VfatSetAllocationSizeInformation(File <%wZ>, AllocationSize %d %u)\n",
1107 &Fcb
->PathNameU
, AllocationSize
->HighPart
, AllocationSize
->LowPart
);
1109 if (Fcb
->Flags
& FCB_IS_FATX_ENTRY
)
1110 OldSize
= Fcb
->entry
.FatX
.FileSize
;
1112 OldSize
= Fcb
->entry
.Fat
.FileSize
;
1114 if (AllocationSize
->u
.HighPart
> 0)
1116 return STATUS_INVALID_PARAMETER
;
1119 if (OldSize
== NewSize
)
1121 return STATUS_SUCCESS
;
1124 FirstCluster
= vfatDirEntryGetFirstCluster(DeviceExt
, &Fcb
->entry
);
1126 if (NewSize
> Fcb
->RFCB
.AllocationSize
.u
.LowPart
)
1128 AllocSizeChanged
= TRUE
;
1129 if (FirstCluster
== 0)
1131 Fcb
->LastCluster
= Fcb
->LastOffset
= 0;
1132 Status
= NextCluster(DeviceExt
, FirstCluster
, &FirstCluster
, TRUE
);
1133 if (!NT_SUCCESS(Status
))
1135 DPRINT1("NextCluster failed. Status = %x\n", Status
);
1139 if (FirstCluster
== 0xffffffff)
1141 return STATUS_DISK_FULL
;
1144 Status
= OffsetToCluster(DeviceExt
, FirstCluster
,
1145 ROUND_DOWN(NewSize
- 1, ClusterSize
),
1147 if (NCluster
== 0xffffffff || !NT_SUCCESS(Status
))
1150 NCluster
= Cluster
= FirstCluster
;
1151 Status
= STATUS_SUCCESS
;
1152 while (NT_SUCCESS(Status
) && Cluster
!= 0xffffffff && Cluster
> 1)
1154 Status
= NextCluster(DeviceExt
, FirstCluster
, &NCluster
, FALSE
);
1155 WriteCluster(DeviceExt
, Cluster
, 0);
1158 return STATUS_DISK_FULL
;
1161 if (Fcb
->Flags
& FCB_IS_FATX_ENTRY
)
1163 Fcb
->entry
.FatX
.FirstCluster
= FirstCluster
;
1167 if (DeviceExt
->FatInfo
.FatType
== FAT32
)
1169 Fcb
->entry
.Fat
.FirstCluster
= (unsigned short)(FirstCluster
& 0x0000FFFF);
1170 Fcb
->entry
.Fat
.FirstClusterHigh
= FirstCluster
>> 16;
1174 ASSERT((FirstCluster
>> 16) == 0);
1175 Fcb
->entry
.Fat
.FirstCluster
= (unsigned short)(FirstCluster
& 0x0000FFFF);
1181 if (Fcb
->LastCluster
> 0)
1183 if (Fcb
->RFCB
.AllocationSize
.u
.LowPart
- ClusterSize
== Fcb
->LastOffset
)
1185 Cluster
= Fcb
->LastCluster
;
1186 Status
= STATUS_SUCCESS
;
1190 Status
= OffsetToCluster(DeviceExt
, Fcb
->LastCluster
,
1191 Fcb
->RFCB
.AllocationSize
.u
.LowPart
- ClusterSize
- Fcb
->LastOffset
,
1197 Status
= OffsetToCluster(DeviceExt
, FirstCluster
,
1198 Fcb
->RFCB
.AllocationSize
.u
.LowPart
- ClusterSize
,
1202 if (!NT_SUCCESS(Status
))
1207 Fcb
->LastCluster
= Cluster
;
1208 Fcb
->LastOffset
= Fcb
->RFCB
.AllocationSize
.u
.LowPart
- ClusterSize
;
1210 /* FIXME: Check status */
1211 /* Cluster points now to the last cluster within the chain */
1212 Status
= OffsetToCluster(DeviceExt
, Cluster
,
1213 ROUND_DOWN(NewSize
- 1, ClusterSize
) - Fcb
->LastOffset
,
1215 if (NCluster
== 0xffffffff || !NT_SUCCESS(Status
))
1219 Status
= NextCluster(DeviceExt
, FirstCluster
, &NCluster
, FALSE
);
1220 WriteCluster(DeviceExt
, Cluster
, 0xffffffff);
1222 while (NT_SUCCESS(Status
) && Cluster
!= 0xffffffff && Cluster
> 1)
1224 Status
= NextCluster(DeviceExt
, FirstCluster
, &NCluster
, FALSE
);
1225 WriteCluster(DeviceExt
, Cluster
, 0);
1228 return STATUS_DISK_FULL
;
1231 UpdateFileSize(FileObject
, Fcb
, NewSize
, ClusterSize
);
1233 else if (NewSize
+ ClusterSize
<= Fcb
->RFCB
.AllocationSize
.u
.LowPart
)
1235 DPRINT("Check for the ability to set file size\n");
1236 if (!MmCanFileBeTruncated(FileObject
->SectionObjectPointer
,
1237 (PLARGE_INTEGER
)AllocationSize
))
1239 DPRINT("Couldn't set file size!\n");
1240 return STATUS_USER_MAPPED_FILE
;
1242 DPRINT("Can set file size\n");
1244 AllocSizeChanged
= TRUE
;
1245 /* FIXME: Use the cached cluster/offset better way. */
1246 Fcb
->LastCluster
= Fcb
->LastOffset
= 0;
1247 UpdateFileSize(FileObject
, Fcb
, NewSize
, ClusterSize
);
1250 Status
= OffsetToCluster(DeviceExt
, FirstCluster
,
1251 ROUND_DOWN(NewSize
- 1, ClusterSize
),
1255 Status
= NextCluster(DeviceExt
, FirstCluster
, &NCluster
, FALSE
);
1256 WriteCluster(DeviceExt
, Cluster
, 0xffffffff);
1261 if (Fcb
->Flags
& FCB_IS_FATX_ENTRY
)
1263 Fcb
->entry
.FatX
.FirstCluster
= 0;
1267 if (DeviceExt
->FatInfo
.FatType
== FAT32
)
1269 Fcb
->entry
.Fat
.FirstCluster
= 0;
1270 Fcb
->entry
.Fat
.FirstClusterHigh
= 0;
1274 Fcb
->entry
.Fat
.FirstCluster
= 0;
1278 NCluster
= Cluster
= FirstCluster
;
1279 Status
= STATUS_SUCCESS
;
1282 while (NT_SUCCESS(Status
) && 0xffffffff != Cluster
&& Cluster
> 1)
1284 Status
= NextCluster(DeviceExt
, FirstCluster
, &NCluster
, FALSE
);
1285 WriteCluster(DeviceExt
, Cluster
, 0);
1291 UpdateFileSize(FileObject
, Fcb
, NewSize
, ClusterSize
);
1294 /* Update the on-disk directory entry */
1295 Fcb
->Flags
|= FCB_IS_DIRTY
;
1296 if (AllocSizeChanged
)
1298 VfatUpdateEntry(Fcb
);
1300 return STATUS_SUCCESS
;
1304 * FUNCTION: Retrieve the specified file information
1307 VfatQueryInformation(
1308 PVFAT_IRP_CONTEXT IrpContext
)
1310 FILE_INFORMATION_CLASS FileInformationClass
;
1311 PVFATFCB FCB
= NULL
;
1313 NTSTATUS Status
= STATUS_SUCCESS
;
1320 /* INITIALIZATION */
1321 FileInformationClass
= IrpContext
->Stack
->Parameters
.QueryFile
.FileInformationClass
;
1322 FCB
= (PVFATFCB
) IrpContext
->FileObject
->FsContext
;
1324 DPRINT("VfatQueryInformation is called for '%s'\n",
1325 FileInformationClass
>= FileMaximumInformation
- 1 ? "????" : FileInformationClassNames
[FileInformationClass
]);
1328 SystemBuffer
= IrpContext
->Irp
->AssociatedIrp
.SystemBuffer
;
1329 BufferLength
= IrpContext
->Stack
->Parameters
.QueryFile
.Length
;
1331 if (!(FCB
->Flags
& FCB_IS_PAGE_FILE
))
1333 if (!ExAcquireResourceSharedLite(&FCB
->MainResource
,
1334 (BOOLEAN
)(IrpContext
->Flags
& IRPCONTEXT_CANWAIT
)))
1336 return VfatQueueRequest(IrpContext
);
1340 switch (FileInformationClass
)
1342 case FileStandardInformation
:
1343 Status
= VfatGetStandardInformation(FCB
,
1348 case FilePositionInformation
:
1349 Status
= VfatGetPositionInformation(IrpContext
->FileObject
,
1351 IrpContext
->DeviceObject
,
1356 case FileBasicInformation
:
1357 Status
= VfatGetBasicInformation(IrpContext
->FileObject
,
1359 IrpContext
->DeviceObject
,
1364 case FileNameInformation
:
1365 Status
= VfatGetNameInformation(IrpContext
->FileObject
,
1367 IrpContext
->DeviceObject
,
1372 case FileInternalInformation
:
1373 Status
= VfatGetInternalInformation(FCB
,
1378 case FileNetworkOpenInformation
:
1379 Status
= VfatGetNetworkOpenInformation(FCB
,
1380 IrpContext
->DeviceExt
,
1385 case FileAllInformation
:
1386 Status
= VfatGetAllInformation(IrpContext
->FileObject
,
1388 IrpContext
->DeviceObject
,
1393 case FileEaInformation
:
1394 Status
= VfatGetEaInformation(IrpContext
->FileObject
,
1396 IrpContext
->DeviceObject
,
1401 case FileAlternateNameInformation
:
1402 Status
= STATUS_NOT_IMPLEMENTED
;
1406 Status
= STATUS_INVALID_PARAMETER
;
1409 if (!(FCB
->Flags
& FCB_IS_PAGE_FILE
))
1411 ExReleaseResourceLite(&FCB
->MainResource
);
1414 IrpContext
->Irp
->IoStatus
.Status
= Status
;
1415 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_OVERFLOW
)
1416 IrpContext
->Irp
->IoStatus
.Information
=
1417 IrpContext
->Stack
->Parameters
.QueryFile
.Length
- BufferLength
;
1419 IrpContext
->Irp
->IoStatus
.Information
= 0;
1420 IoCompleteRequest(IrpContext
->Irp
, IO_NO_INCREMENT
);
1421 VfatFreeIrpContext(IrpContext
);
1427 * FUNCTION: Retrieve the specified file information
1431 PVFAT_IRP_CONTEXT IrpContext
)
1433 FILE_INFORMATION_CLASS FileInformationClass
;
1434 PVFATFCB FCB
= NULL
;
1435 NTSTATUS Status
= STATUS_SUCCESS
;
1441 DPRINT("VfatSetInformation(IrpContext %p)\n", IrpContext
);
1443 /* INITIALIZATION */
1444 FileInformationClass
=
1445 IrpContext
->Stack
->Parameters
.SetFile
.FileInformationClass
;
1446 FCB
= (PVFATFCB
) IrpContext
->FileObject
->FsContext
;
1447 SystemBuffer
= IrpContext
->Irp
->AssociatedIrp
.SystemBuffer
;
1449 DPRINT("VfatSetInformation is called for '%s'\n",
1450 FileInformationClass
>= FileMaximumInformation
- 1 ? "????" : FileInformationClassNames
[ FileInformationClass
]);
1452 DPRINT("FileInformationClass %d\n", FileInformationClass
);
1453 DPRINT("SystemBuffer %p\n", SystemBuffer
);
1455 /* Special: We should call MmCanFileBeTruncated here to determine if changing
1456 the file size would be allowed. If not, we bail with the right error.
1457 We must do this before acquiring the lock. */
1458 if (FileInformationClass
== FileEndOfFileInformation
)
1460 DPRINT("Check for the ability to set file size\n");
1461 if (!MmCanFileBeTruncated(IrpContext
->FileObject
->SectionObjectPointer
,
1462 (PLARGE_INTEGER
)SystemBuffer
))
1464 DPRINT("Couldn't set file size!\n");
1465 IrpContext
->Irp
->IoStatus
.Status
= STATUS_USER_MAPPED_FILE
;
1466 IrpContext
->Irp
->IoStatus
.Information
= 0;
1467 IoCompleteRequest(IrpContext
->Irp
, IO_NO_INCREMENT
);
1468 VfatFreeIrpContext(IrpContext
);
1469 return STATUS_USER_MAPPED_FILE
;
1471 DPRINT("Can set file size\n");
1474 if (FileInformationClass
== FileRenameInformation
)
1476 if (!ExAcquireResourceExclusiveLite(&((PDEVICE_EXTENSION
)IrpContext
->DeviceObject
->DeviceExtension
)->DirResource
,
1477 (BOOLEAN
)(IrpContext
->Flags
& IRPCONTEXT_CANWAIT
)))
1479 return VfatQueueRequest(IrpContext
);
1483 if (!(FCB
->Flags
& FCB_IS_PAGE_FILE
))
1485 if (!ExAcquireResourceExclusiveLite(&FCB
->MainResource
,
1486 (BOOLEAN
)(IrpContext
->Flags
& IRPCONTEXT_CANWAIT
)))
1488 if (FileInformationClass
== FileRenameInformation
)
1490 ExReleaseResourceLite(&((PDEVICE_EXTENSION
)IrpContext
->DeviceObject
->DeviceExtension
)->DirResource
);
1492 return VfatQueueRequest(IrpContext
);
1496 switch (FileInformationClass
)
1498 case FilePositionInformation
:
1499 Status
= VfatSetPositionInformation(IrpContext
->FileObject
,
1503 case FileDispositionInformation
:
1504 Status
= VfatSetDispositionInformation(IrpContext
->FileObject
,
1506 IrpContext
->DeviceObject
,
1510 case FileAllocationInformation
:
1511 case FileEndOfFileInformation
:
1512 Status
= VfatSetAllocationSizeInformation(IrpContext
->FileObject
,
1514 IrpContext
->DeviceExt
,
1515 (PLARGE_INTEGER
)SystemBuffer
);
1518 case FileBasicInformation
:
1519 Status
= VfatSetBasicInformation(IrpContext
->FileObject
,
1521 IrpContext
->DeviceExt
,
1525 case FileRenameInformation
:
1526 Status
= VfatSetRenameInformation(IrpContext
->FileObject
,
1528 IrpContext
->DeviceExt
,
1530 IrpContext
->Stack
->Parameters
.SetFile
.FileObject
);
1534 Status
= STATUS_NOT_SUPPORTED
;
1537 if (!(FCB
->Flags
& FCB_IS_PAGE_FILE
))
1539 ExReleaseResourceLite(&FCB
->MainResource
);
1542 if (FileInformationClass
== FileRenameInformation
)
1544 ExReleaseResourceLite(&((PDEVICE_EXTENSION
)IrpContext
->DeviceObject
->DeviceExtension
)->DirResource
);
1547 IrpContext
->Irp
->IoStatus
.Status
= Status
;
1548 IrpContext
->Irp
->IoStatus
.Information
= 0;
1549 IoCompleteRequest(IrpContext
->Irp
, IO_NO_INCREMENT
);
1550 VfatFreeIrpContext(IrpContext
);