2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/fs/vfat/finfo.c
5 * PURPOSE: VFAT Filesystem
6 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
7 * Herve Poussineau (reactos@poussine.freesurf.fr)
11 /* INCLUDES *****************************************************************/
16 /* GLOBALS ******************************************************************/
18 const char* FileInformationClassNames
[] =
21 "FileDirectoryInformation",
22 "FileFullDirectoryInformation",
23 "FileBothDirectoryInformation",
24 "FileBasicInformation",
25 "FileStandardInformation",
26 "FileInternalInformation",
28 "FileAccessInformation",
29 "FileNameInformation",
30 "FileRenameInformation",
31 "FileLinkInformation",
32 "FileNamesInformation",
33 "FileDispositionInformation",
34 "FilePositionInformation",
35 "FileFullEaInformation",
36 "FileModeInformation",
37 "FileAlignmentInformation",
39 "FileAllocationInformation",
40 "FileEndOfFileInformation",
41 "FileAlternateNameInformation",
42 "FileStreamInformation",
43 "FilePipeInformation",
44 "FilePipeLocalInformation",
45 "FilePipeRemoteInformation",
46 "FileMailslotQueryInformation",
47 "FileMailslotSetInformation",
48 "FileCompressionInformation",
49 "FileObjectIdInformation",
50 "FileCompletionInformation",
51 "FileMoveClusterInformation",
52 "FileQuotaInformation",
53 "FileReparsePointInformation",
54 "FileNetworkOpenInformation",
55 "FileAttributeTagInformation",
56 "FileTrackingInformation",
57 "FileIdBothDirectoryInformation",
58 "FileIdFullDirectoryInformation",
59 "FileValidDataLengthInformation",
60 "FileShortNameInformation",
61 "FileMaximumInformation"
64 /* FUNCTIONS ****************************************************************/
67 VfatGetStandardInformation(PVFATFCB FCB
,
68 PFILE_STANDARD_INFORMATION StandardInfo
,
71 * FUNCTION: Retrieve the standard file information
75 if (*BufferLength
< sizeof(FILE_STANDARD_INFORMATION
))
76 return STATUS_BUFFER_OVERFLOW
;
79 ASSERT(StandardInfo
!= NULL
);
82 if (vfatFCBIsDirectory(FCB
))
84 StandardInfo
->AllocationSize
.QuadPart
= 0;
85 StandardInfo
->EndOfFile
.QuadPart
= 0;
86 StandardInfo
->Directory
= TRUE
;
90 StandardInfo
->AllocationSize
= FCB
->RFCB
.AllocationSize
;
91 StandardInfo
->EndOfFile
= FCB
->RFCB
.FileSize
;
92 StandardInfo
->Directory
= FALSE
;
94 StandardInfo
->NumberOfLinks
= 0;
95 StandardInfo
->DeletePending
= FCB
->Flags
& FCB_DELETE_PENDING
? TRUE
: FALSE
;
97 *BufferLength
-= sizeof(FILE_STANDARD_INFORMATION
);
98 return(STATUS_SUCCESS
);
102 VfatSetPositionInformation(PFILE_OBJECT FileObject
,
103 PFILE_POSITION_INFORMATION PositionInfo
)
105 DPRINT ("FsdSetPositionInformation()\n");
107 DPRINT ("PositionInfo %p\n", PositionInfo
);
108 DPRINT ("Setting position %d\n", PositionInfo
->CurrentByteOffset
.u
.LowPart
);
110 FileObject
->CurrentByteOffset
.QuadPart
=
111 PositionInfo
->CurrentByteOffset
.QuadPart
;
113 return (STATUS_SUCCESS
);
117 VfatGetPositionInformation(PFILE_OBJECT FileObject
,
119 PDEVICE_OBJECT DeviceObject
,
120 PFILE_POSITION_INFORMATION PositionInfo
,
123 DPRINT ("VfatGetPositionInformation()\n");
125 if (*BufferLength
< sizeof(FILE_POSITION_INFORMATION
))
126 return STATUS_BUFFER_OVERFLOW
;
128 PositionInfo
->CurrentByteOffset
.QuadPart
=
129 FileObject
->CurrentByteOffset
.QuadPart
;
131 DPRINT("Getting position %I64x\n",
132 PositionInfo
->CurrentByteOffset
.QuadPart
);
134 *BufferLength
-= sizeof(FILE_POSITION_INFORMATION
);
135 return(STATUS_SUCCESS
);
139 VfatSetBasicInformation(PFILE_OBJECT FileObject
,
141 PDEVICE_EXTENSION DeviceExt
,
142 PFILE_BASIC_INFORMATION BasicInfo
)
144 DPRINT("VfatSetBasicInformation()\n");
146 ASSERT(NULL
!= FileObject
);
148 ASSERT(NULL
!= DeviceExt
);
149 ASSERT(NULL
!= BasicInfo
);
150 /* Check volume label bit */
151 ASSERT(0 == (*FCB
->Attributes
& 0x08));
153 if (FCB
->Flags
& FCB_IS_FATX_ENTRY
)
155 FsdSystemTimeToDosDateTime(DeviceExt
,
156 &BasicInfo
->CreationTime
,
157 &FCB
->entry
.FatX
.CreationDate
,
158 &FCB
->entry
.FatX
.CreationTime
);
159 FsdSystemTimeToDosDateTime(DeviceExt
,
160 &BasicInfo
->LastAccessTime
,
161 &FCB
->entry
.FatX
.AccessDate
,
162 &FCB
->entry
.FatX
.AccessTime
);
163 FsdSystemTimeToDosDateTime(DeviceExt
,
164 &BasicInfo
->LastWriteTime
,
165 &FCB
->entry
.FatX
.UpdateDate
,
166 &FCB
->entry
.FatX
.UpdateTime
);
170 FsdSystemTimeToDosDateTime(DeviceExt
,
171 &BasicInfo
->CreationTime
,
172 &FCB
->entry
.Fat
.CreationDate
,
173 &FCB
->entry
.Fat
.CreationTime
);
174 FsdSystemTimeToDosDateTime(DeviceExt
,
175 &BasicInfo
->LastAccessTime
,
176 &FCB
->entry
.Fat
.AccessDate
,
178 FsdSystemTimeToDosDateTime(DeviceExt
,
179 &BasicInfo
->LastWriteTime
,
180 &FCB
->entry
.Fat
.UpdateDate
,
181 &FCB
->entry
.Fat
.UpdateTime
);
184 *FCB
->Attributes
= (unsigned char)((*FCB
->Attributes
&
185 (FILE_ATTRIBUTE_DIRECTORY
| 0x48)) |
186 (BasicInfo
->FileAttributes
&
187 (FILE_ATTRIBUTE_ARCHIVE
|
188 FILE_ATTRIBUTE_SYSTEM
|
189 FILE_ATTRIBUTE_HIDDEN
|
190 FILE_ATTRIBUTE_READONLY
)));
191 DPRINT("Setting attributes 0x%02x\n", *FCB
->Attributes
);
193 VfatUpdateEntry(FCB
);
195 return(STATUS_SUCCESS
);
199 VfatGetBasicInformation(PFILE_OBJECT FileObject
,
201 PDEVICE_OBJECT DeviceObject
,
202 PFILE_BASIC_INFORMATION BasicInfo
,
205 PDEVICE_EXTENSION DeviceExt
;
206 DPRINT("VfatGetBasicInformation()\n");
208 DeviceExt
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
210 if (*BufferLength
< sizeof(FILE_BASIC_INFORMATION
))
211 return STATUS_BUFFER_OVERFLOW
;
213 if (FCB
->Flags
& FCB_IS_FATX_ENTRY
)
215 FsdDosDateTimeToSystemTime(DeviceExt
,
216 FCB
->entry
.FatX
.CreationDate
,
217 FCB
->entry
.FatX
.CreationTime
,
218 &BasicInfo
->CreationTime
);
219 FsdDosDateTimeToSystemTime(DeviceExt
,
220 FCB
->entry
.FatX
.AccessDate
,
221 FCB
->entry
.FatX
.AccessTime
,
222 &BasicInfo
->LastAccessTime
);
223 FsdDosDateTimeToSystemTime(DeviceExt
,
224 FCB
->entry
.FatX
.UpdateDate
,
225 FCB
->entry
.FatX
.UpdateTime
,
226 &BasicInfo
->LastWriteTime
);
227 BasicInfo
->ChangeTime
= BasicInfo
->LastWriteTime
;
231 FsdDosDateTimeToSystemTime(DeviceExt
,
232 FCB
->entry
.Fat
.CreationDate
,
233 FCB
->entry
.Fat
.CreationTime
,
234 &BasicInfo
->CreationTime
);
235 FsdDosDateTimeToSystemTime(DeviceExt
,
236 FCB
->entry
.Fat
.AccessDate
,
238 &BasicInfo
->LastAccessTime
);
239 FsdDosDateTimeToSystemTime(DeviceExt
,
240 FCB
->entry
.Fat
.UpdateDate
,
241 FCB
->entry
.Fat
.UpdateTime
,
242 &BasicInfo
->LastWriteTime
);
243 BasicInfo
->ChangeTime
= BasicInfo
->LastWriteTime
;
246 BasicInfo
->FileAttributes
= *FCB
->Attributes
& 0x3f;
247 /* Synthesize FILE_ATTRIBUTE_NORMAL */
248 if (0 == (BasicInfo
->FileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|
249 FILE_ATTRIBUTE_ARCHIVE
|
250 FILE_ATTRIBUTE_SYSTEM
|
251 FILE_ATTRIBUTE_HIDDEN
|
252 FILE_ATTRIBUTE_READONLY
)))
254 DPRINT("Synthesizing FILE_ATTRIBUTE_NORMAL\n");
255 BasicInfo
->FileAttributes
|= FILE_ATTRIBUTE_NORMAL
;
257 DPRINT("Getting attributes 0x%02x\n", BasicInfo
->FileAttributes
);
259 *BufferLength
-= sizeof(FILE_BASIC_INFORMATION
);
260 return(STATUS_SUCCESS
);
265 VfatSetDispositionInformation(PFILE_OBJECT FileObject
,
267 PDEVICE_OBJECT DeviceObject
,
268 PFILE_DISPOSITION_INFORMATION DispositionInfo
)
271 PDEVICE_EXTENSION DeviceExt
= DeviceObject
->DeviceExtension
;
274 DPRINT ("FsdSetDispositionInformation()\n");
276 ASSERT(DeviceExt
!= NULL
);
277 ASSERT(DeviceExt
->FatInfo
.BytesPerCluster
!= 0);
280 if (!DispositionInfo
->DeleteFile
)
282 /* undelete the file */
283 FCB
->Flags
&= ~FCB_DELETE_PENDING
;
284 FileObject
->DeletePending
= FALSE
;
285 return STATUS_SUCCESS
;
288 if (FCB
->Flags
& FCB_DELETE_PENDING
)
290 /* stream already marked for deletion. just update the file object */
291 FileObject
->DeletePending
= TRUE
;
292 return STATUS_SUCCESS
;
295 if (*FCB
->Attributes
& FILE_ATTRIBUTE_READONLY
)
297 return STATUS_CANNOT_DELETE
;
300 if (vfatFCBIsRoot(FCB
) ||
301 (FCB
->LongNameU
.Length
== sizeof(WCHAR
) && FCB
->LongNameU
.Buffer
[0] == L
'.') ||
302 (FCB
->LongNameU
.Length
== 2 * sizeof(WCHAR
) && FCB
->LongNameU
.Buffer
[0] == L
'.' && FCB
->LongNameU
.Buffer
[1] == L
'.'))
304 // we cannot delete a '.', '..' or the root directory
305 return STATUS_ACCESS_DENIED
;
309 if (!MmFlushImageSection (FileObject
->SectionObjectPointer
, MmFlushForDelete
))
311 /* can't delete a file if its mapped into a process */
313 DPRINT("MmFlushImageSection returned FALSE\n");
314 return STATUS_CANNOT_DELETE
;
317 if (vfatFCBIsDirectory(FCB
) && !VfatIsDirectoryEmpty(FCB
))
319 /* can't delete a non-empty directory */
321 return STATUS_DIRECTORY_NOT_EMPTY
;
325 FCB
->Flags
|= FCB_DELETE_PENDING
;
326 FileObject
->DeletePending
= TRUE
;
328 return STATUS_SUCCESS
;
332 VfatGetNameInformation(PFILE_OBJECT FileObject
,
334 PDEVICE_OBJECT DeviceObject
,
335 PFILE_NAME_INFORMATION NameInfo
,
338 * FUNCTION: Retrieve the file name information
341 ASSERT(NameInfo
!= NULL
);
344 NameInfo
->FileNameLength
= FCB
->PathNameU
.Length
;
345 if (*BufferLength
< FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
[0]) + FCB
->PathNameU
.Length
)
346 return STATUS_BUFFER_OVERFLOW
;
348 RtlCopyMemory(NameInfo
->FileName
, FCB
->PathNameU
.Buffer
, FCB
->PathNameU
.Length
);
350 *BufferLength
-= (FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
[0]) + FCB
->PathNameU
.Length
);
352 return STATUS_SUCCESS
;
356 VfatGetInternalInformation(PVFATFCB Fcb
,
357 PFILE_INTERNAL_INFORMATION InternalInfo
,
360 ASSERT(InternalInfo
);
363 if (*BufferLength
< sizeof(FILE_INTERNAL_INFORMATION
))
364 return STATUS_BUFFER_OVERFLOW
;
365 // FIXME: get a real index, that can be used in a create operation
366 InternalInfo
->IndexNumber
.QuadPart
= 0;
367 *BufferLength
-= sizeof(FILE_INTERNAL_INFORMATION
);
368 return STATUS_SUCCESS
;
373 VfatGetNetworkOpenInformation(PVFATFCB Fcb
,
374 PDEVICE_EXTENSION DeviceExt
,
375 PFILE_NETWORK_OPEN_INFORMATION NetworkInfo
,
378 * FUNCTION: Retrieve the file network open information
384 if (*BufferLength
< sizeof(FILE_NETWORK_OPEN_INFORMATION
))
385 return(STATUS_BUFFER_OVERFLOW
);
387 if (Fcb
->Flags
& FCB_IS_FATX_ENTRY
)
389 FsdDosDateTimeToSystemTime(DeviceExt
,
390 Fcb
->entry
.FatX
.CreationDate
,
391 Fcb
->entry
.FatX
.CreationTime
,
392 &NetworkInfo
->CreationTime
);
393 FsdDosDateTimeToSystemTime(DeviceExt
,
394 Fcb
->entry
.FatX
.AccessDate
,
395 Fcb
->entry
.FatX
.AccessTime
,
396 &NetworkInfo
->LastAccessTime
);
397 FsdDosDateTimeToSystemTime(DeviceExt
,
398 Fcb
->entry
.FatX
.UpdateDate
,
399 Fcb
->entry
.FatX
.UpdateTime
,
400 &NetworkInfo
->LastWriteTime
);
401 NetworkInfo
->ChangeTime
.QuadPart
= NetworkInfo
->LastWriteTime
.QuadPart
;
405 FsdDosDateTimeToSystemTime(DeviceExt
,
406 Fcb
->entry
.Fat
.CreationDate
,
407 Fcb
->entry
.Fat
.CreationTime
,
408 &NetworkInfo
->CreationTime
);
409 FsdDosDateTimeToSystemTime(DeviceExt
,
410 Fcb
->entry
.Fat
.AccessDate
,
412 &NetworkInfo
->LastAccessTime
);
413 FsdDosDateTimeToSystemTime(DeviceExt
,
414 Fcb
->entry
.Fat
.UpdateDate
,
415 Fcb
->entry
.Fat
.UpdateTime
,
416 &NetworkInfo
->LastWriteTime
);
417 NetworkInfo
->ChangeTime
.QuadPart
= NetworkInfo
->LastWriteTime
.QuadPart
;
419 if (vfatFCBIsDirectory(Fcb
))
421 NetworkInfo
->EndOfFile
.QuadPart
= 0L;
422 NetworkInfo
->AllocationSize
.QuadPart
= 0L;
426 NetworkInfo
->AllocationSize
= Fcb
->RFCB
.AllocationSize
;
427 NetworkInfo
->EndOfFile
= Fcb
->RFCB
.FileSize
;
429 NetworkInfo
->FileAttributes
= *Fcb
->Attributes
& 0x3f;
430 /* Synthesize FILE_ATTRIBUTE_NORMAL */
431 if (0 == (NetworkInfo
->FileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|
432 FILE_ATTRIBUTE_ARCHIVE
|
433 FILE_ATTRIBUTE_SYSTEM
|
434 FILE_ATTRIBUTE_HIDDEN
|
435 FILE_ATTRIBUTE_READONLY
)))
437 DPRINT("Synthesizing FILE_ATTRIBUTE_NORMAL\n");
438 NetworkInfo
->FileAttributes
|= FILE_ATTRIBUTE_NORMAL
;
441 *BufferLength
-= sizeof(FILE_NETWORK_OPEN_INFORMATION
);
442 return STATUS_SUCCESS
;
447 VfatGetEaInformation(PFILE_OBJECT FileObject
,
449 PDEVICE_OBJECT DeviceObject
,
450 PFILE_EA_INFORMATION Info
,
453 PDEVICE_EXTENSION DeviceExt
= DeviceObject
->DeviceExtension
;
455 /* FIXME - use SEH to access the buffer! */
457 *BufferLength
-= sizeof(*Info
);
458 if (DeviceExt
->FatInfo
.FatType
== FAT12
||
459 DeviceExt
->FatInfo
.FatType
== FAT16
)
462 DPRINT1("VFAT: FileEaInformation not implemented!\n");
464 return STATUS_SUCCESS
;
469 VfatGetAllInformation(PFILE_OBJECT FileObject
,
471 PDEVICE_OBJECT DeviceObject
,
472 PFILE_ALL_INFORMATION Info
,
475 * FUNCTION: Retrieve the all file information
479 ULONG InitialBufferLength
= *BufferLength
;
484 if (*BufferLength
< sizeof(FILE_ALL_INFORMATION
) + Fcb
->PathNameU
.Length
+ sizeof(WCHAR
))
485 return(STATUS_BUFFER_OVERFLOW
);
487 /* Basic Information */
488 Status
= VfatGetBasicInformation(FileObject
, Fcb
, DeviceObject
, &Info
->BasicInformation
, BufferLength
);
489 if (!NT_SUCCESS(Status
)) return Status
;
490 /* Standard Information */
491 Status
= VfatGetStandardInformation(Fcb
, &Info
->StandardInformation
, BufferLength
);
492 if (!NT_SUCCESS(Status
)) return Status
;
493 /* Internal Information */
494 Status
= VfatGetInternalInformation(Fcb
, &Info
->InternalInformation
, BufferLength
);
495 if (!NT_SUCCESS(Status
)) return Status
;
497 Info
->EaInformation
.EaSize
= 0;
498 /* Access Information: The IO-Manager adds this information */
499 /* Position Information */
500 Status
= VfatGetPositionInformation(FileObject
, Fcb
, DeviceObject
, &Info
->PositionInformation
, BufferLength
);
501 if (!NT_SUCCESS(Status
)) return Status
;
502 /* Mode Information: The IO-Manager adds this information */
503 /* Alignment Information: The IO-Manager adds this information */
504 /* Name Information */
505 Status
= VfatGetNameInformation(FileObject
, Fcb
, DeviceObject
, &Info
->NameInformation
, BufferLength
);
506 if (!NT_SUCCESS(Status
)) return Status
;
508 *BufferLength
= InitialBufferLength
- (sizeof(FILE_ALL_INFORMATION
) + Fcb
->PathNameU
.Length
+ sizeof(WCHAR
));
510 return STATUS_SUCCESS
;
513 static VOID
UpdateFileSize(PFILE_OBJECT FileObject
, PVFATFCB Fcb
, ULONG Size
, ULONG ClusterSize
)
517 Fcb
->RFCB
.AllocationSize
.QuadPart
= ROUND_UP(Size
, ClusterSize
);
521 Fcb
->RFCB
.AllocationSize
.QuadPart
= (LONGLONG
)0;
523 if (!vfatFCBIsDirectory(Fcb
))
525 if (Fcb
->Flags
& FCB_IS_FATX_ENTRY
)
526 Fcb
->entry
.FatX
.FileSize
= Size
;
528 Fcb
->entry
.Fat
.FileSize
= Size
;
530 Fcb
->RFCB
.FileSize
.QuadPart
= Size
;
531 Fcb
->RFCB
.ValidDataLength
.QuadPart
= Size
;
533 if (FileObject
->SectionObjectPointer
->SharedCacheMap
!= NULL
)
535 CcSetFileSizes(FileObject
, (PCC_FILE_SIZES
)&Fcb
->RFCB
.AllocationSize
);
540 VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject
,
542 PDEVICE_EXTENSION DeviceExt
,
543 PLARGE_INTEGER AllocationSize
)
546 ULONG Cluster
, FirstCluster
;
549 ULONG ClusterSize
= DeviceExt
->FatInfo
.BytesPerCluster
;
550 ULONG NewSize
= AllocationSize
->u
.LowPart
;
552 BOOLEAN AllocSizeChanged
= FALSE
;
554 DPRINT("VfatSetAllocationSizeInformation()\n");
556 if (Fcb
->Flags
& FCB_IS_FATX_ENTRY
)
557 OldSize
= Fcb
->entry
.FatX
.FileSize
;
559 OldSize
= Fcb
->entry
.Fat
.FileSize
;
560 if (AllocationSize
->u
.HighPart
> 0)
562 return STATUS_INVALID_PARAMETER
;
564 if (OldSize
== NewSize
)
566 return(STATUS_SUCCESS
);
569 FirstCluster
= vfatDirEntryGetFirstCluster (DeviceExt
, &Fcb
->entry
);
571 if (NewSize
> Fcb
->RFCB
.AllocationSize
.u
.LowPart
)
573 AllocSizeChanged
= TRUE
;
574 if (FirstCluster
== 0)
576 Fcb
->LastCluster
= Fcb
->LastOffset
= 0;
577 Status
= NextCluster (DeviceExt
, FirstCluster
, &FirstCluster
, TRUE
);
578 if (!NT_SUCCESS(Status
))
580 DPRINT1("NextCluster failed. Status = %x\n", Status
);
583 if (FirstCluster
== 0xffffffff)
585 return STATUS_DISK_FULL
;
587 Status
= OffsetToCluster(DeviceExt
, FirstCluster
,
588 ROUND_DOWN(NewSize
- 1, ClusterSize
),
590 if (NCluster
== 0xffffffff || !NT_SUCCESS(Status
))
593 NCluster
= Cluster
= FirstCluster
;
594 Status
= STATUS_SUCCESS
;
595 while (NT_SUCCESS(Status
) && Cluster
!= 0xffffffff && Cluster
> 1)
597 Status
= NextCluster (DeviceExt
, FirstCluster
, &NCluster
, FALSE
);
598 WriteCluster (DeviceExt
, Cluster
, 0);
601 return STATUS_DISK_FULL
;
603 if (Fcb
->Flags
& FCB_IS_FATX_ENTRY
)
605 Fcb
->entry
.FatX
.FirstCluster
= FirstCluster
;
609 if (DeviceExt
->FatInfo
.FatType
== FAT32
)
611 Fcb
->entry
.Fat
.FirstCluster
= (unsigned short)(FirstCluster
& 0x0000FFFF);
612 Fcb
->entry
.Fat
.FirstClusterHigh
= FirstCluster
>> 16;
616 ASSERT((FirstCluster
>> 16) == 0);
617 Fcb
->entry
.Fat
.FirstCluster
= (unsigned short)(FirstCluster
& 0x0000FFFF);
624 if (Fcb
->LastCluster
> 0)
626 if (Fcb
->RFCB
.AllocationSize
.u
.LowPart
- ClusterSize
== Fcb
->LastOffset
)
628 Cluster
= Fcb
->LastCluster
;
629 Status
= STATUS_SUCCESS
;
633 Status
= OffsetToCluster(DeviceExt
, Fcb
->LastCluster
,
634 Fcb
->RFCB
.AllocationSize
.u
.LowPart
- ClusterSize
- Fcb
->LastOffset
,
640 Status
= OffsetToCluster(DeviceExt
, FirstCluster
,
641 Fcb
->RFCB
.AllocationSize
.u
.LowPart
- ClusterSize
,
644 if (!NT_SUCCESS(Status
))
649 if (Fcb
->LastCluster
== 0)
651 Fcb
->LastCluster
= Cluster
;
652 Fcb
->LastOffset
= Fcb
->RFCB
.AllocationSize
.u
.LowPart
- ClusterSize
;
655 /* FIXME: Check status */
656 /* Cluster points now to the last cluster within the chain */
657 Status
= OffsetToCluster(DeviceExt
, Cluster
,
658 ROUND_DOWN(NewSize
- 1, ClusterSize
) - Fcb
->LastOffset
,
661 Status
= OffsetToCluster(DeviceExt
, FirstCluster
,
662 ROUND_DOWN(NewSize
- 1, ClusterSize
),
666 if (NCluster
== 0xffffffff || !NT_SUCCESS(Status
))
670 Status
= NextCluster (DeviceExt
, FirstCluster
, &NCluster
, FALSE
);
671 WriteCluster(DeviceExt
, Cluster
, 0xffffffff);
673 while (NT_SUCCESS(Status
) && Cluster
!= 0xffffffff && Cluster
> 1)
675 Status
= NextCluster (DeviceExt
, FirstCluster
, &NCluster
, FALSE
);
676 WriteCluster (DeviceExt
, Cluster
, 0);
679 return STATUS_DISK_FULL
;
682 UpdateFileSize(FileObject
, Fcb
, NewSize
, ClusterSize
);
684 else if (NewSize
+ ClusterSize
<= Fcb
->RFCB
.AllocationSize
.u
.LowPart
)
686 AllocSizeChanged
= TRUE
;
687 /* FIXME: Use the cached cluster/offset better way. */
688 Fcb
->LastCluster
= Fcb
->LastOffset
= 0;
689 UpdateFileSize(FileObject
, Fcb
, NewSize
, ClusterSize
);
692 Status
= OffsetToCluster(DeviceExt
, FirstCluster
,
693 ROUND_DOWN(NewSize
- 1, ClusterSize
),
697 Status
= NextCluster (DeviceExt
, FirstCluster
, &NCluster
, FALSE
);
698 WriteCluster(DeviceExt
, Cluster
, 0xffffffff);
703 if (Fcb
->Flags
& FCB_IS_FATX_ENTRY
)
705 Fcb
->entry
.FatX
.FirstCluster
= 0;
709 if (DeviceExt
->FatInfo
.FatType
== FAT32
)
711 Fcb
->entry
.Fat
.FirstCluster
= 0;
712 Fcb
->entry
.Fat
.FirstClusterHigh
= 0;
716 Fcb
->entry
.Fat
.FirstCluster
= 0;
720 NCluster
= Cluster
= FirstCluster
;
721 Status
= STATUS_SUCCESS
;
723 while (NT_SUCCESS(Status
) && 0xffffffff != Cluster
&& Cluster
> 1)
725 Status
= NextCluster (DeviceExt
, FirstCluster
, &NCluster
, FALSE
);
726 WriteCluster (DeviceExt
, Cluster
, 0);
732 UpdateFileSize(FileObject
, Fcb
, NewSize
, ClusterSize
);
734 /* Update the on-disk directory entry */
735 Fcb
->Flags
|= FCB_IS_DIRTY
;
736 if (AllocSizeChanged
)
738 VfatUpdateEntry(Fcb
);
740 return STATUS_SUCCESS
;
743 NTSTATUS
VfatQueryInformation(PVFAT_IRP_CONTEXT IrpContext
)
745 * FUNCTION: Retrieve the specified file information
748 FILE_INFORMATION_CLASS FileInformationClass
;
751 NTSTATUS RC
= STATUS_SUCCESS
;
759 FileInformationClass
= IrpContext
->Stack
->Parameters
.QueryFile
.FileInformationClass
;
760 FCB
= (PVFATFCB
) IrpContext
->FileObject
->FsContext
;
762 DPRINT("VfatQueryInformation is called for '%s'\n",
763 FileInformationClass
>= FileMaximumInformation
- 1 ? "????" : FileInformationClassNames
[FileInformationClass
]);
766 SystemBuffer
= IrpContext
->Irp
->AssociatedIrp
.SystemBuffer
;
767 BufferLength
= IrpContext
->Stack
->Parameters
.QueryFile
.Length
;
769 if (!(FCB
->Flags
& FCB_IS_PAGE_FILE
))
771 if (!ExAcquireResourceSharedLite(&FCB
->MainResource
,
772 (BOOLEAN
)(IrpContext
->Flags
& IRPCONTEXT_CANWAIT
)))
774 return VfatQueueRequest (IrpContext
);
779 switch (FileInformationClass
)
781 case FileStandardInformation
:
782 RC
= VfatGetStandardInformation(FCB
,
786 case FilePositionInformation
:
787 RC
= VfatGetPositionInformation(IrpContext
->FileObject
,
789 IrpContext
->DeviceObject
,
793 case FileBasicInformation
:
794 RC
= VfatGetBasicInformation(IrpContext
->FileObject
,
796 IrpContext
->DeviceObject
,
800 case FileNameInformation
:
801 RC
= VfatGetNameInformation(IrpContext
->FileObject
,
803 IrpContext
->DeviceObject
,
807 case FileInternalInformation
:
808 RC
= VfatGetInternalInformation(FCB
,
812 case FileNetworkOpenInformation
:
813 RC
= VfatGetNetworkOpenInformation(FCB
,
814 IrpContext
->DeviceExt
,
818 case FileAllInformation
:
819 RC
= VfatGetAllInformation(IrpContext
->FileObject
,
821 IrpContext
->DeviceObject
,
826 case FileEaInformation
:
827 RC
= VfatGetEaInformation(IrpContext
->FileObject
,
829 IrpContext
->DeviceObject
,
834 case FileAlternateNameInformation
:
835 RC
= STATUS_NOT_IMPLEMENTED
;
838 RC
= STATUS_INVALID_PARAMETER
;
841 if (!(FCB
->Flags
& FCB_IS_PAGE_FILE
))
843 ExReleaseResourceLite(&FCB
->MainResource
);
845 IrpContext
->Irp
->IoStatus
.Status
= RC
;
847 IrpContext
->Irp
->IoStatus
.Information
=
848 IrpContext
->Stack
->Parameters
.QueryFile
.Length
- BufferLength
;
850 IrpContext
->Irp
->IoStatus
.Information
= 0;
851 IoCompleteRequest(IrpContext
->Irp
, IO_NO_INCREMENT
);
852 VfatFreeIrpContext(IrpContext
);
857 NTSTATUS
VfatSetInformation(PVFAT_IRP_CONTEXT IrpContext
)
859 * FUNCTION: Retrieve the specified file information
862 FILE_INFORMATION_CLASS FileInformationClass
;
864 NTSTATUS RC
= STATUS_SUCCESS
;
866 BOOLEAN CanWait
= (IrpContext
->Flags
& IRPCONTEXT_CANWAIT
) != 0;
871 DPRINT("VfatSetInformation(IrpContext %p)\n", IrpContext
);
874 FileInformationClass
=
875 IrpContext
->Stack
->Parameters
.SetFile
.FileInformationClass
;
876 FCB
= (PVFATFCB
) IrpContext
->FileObject
->FsContext
;
877 SystemBuffer
= IrpContext
->Irp
->AssociatedIrp
.SystemBuffer
;
879 DPRINT("VfatSetInformation is called for '%s'\n",
880 FileInformationClass
>= FileMaximumInformation
- 1 ? "????" : FileInformationClassNames
[ FileInformationClass
]);
882 DPRINT("FileInformationClass %d\n", FileInformationClass
);
883 DPRINT("SystemBuffer %p\n", SystemBuffer
);
885 if (!(FCB
->Flags
& FCB_IS_PAGE_FILE
))
887 if (!ExAcquireResourceExclusiveLite(&FCB
->MainResource
,
890 return(VfatQueueRequest (IrpContext
));
894 switch (FileInformationClass
)
896 case FilePositionInformation
:
897 RC
= VfatSetPositionInformation(IrpContext
->FileObject
,
900 case FileDispositionInformation
:
901 RC
= VfatSetDispositionInformation(IrpContext
->FileObject
,
903 IrpContext
->DeviceObject
,
906 case FileAllocationInformation
:
907 case FileEndOfFileInformation
:
908 RC
= VfatSetAllocationSizeInformation(IrpContext
->FileObject
,
910 IrpContext
->DeviceExt
,
911 (PLARGE_INTEGER
)SystemBuffer
);
913 case FileBasicInformation
:
914 RC
= VfatSetBasicInformation(IrpContext
->FileObject
,
916 IrpContext
->DeviceExt
,
919 case FileRenameInformation
:
920 RC
= STATUS_NOT_IMPLEMENTED
;
923 RC
= STATUS_NOT_SUPPORTED
;
926 if (!(FCB
->Flags
& FCB_IS_PAGE_FILE
))
928 ExReleaseResourceLite(&FCB
->MainResource
);
931 IrpContext
->Irp
->IoStatus
.Status
= RC
;
932 IrpContext
->Irp
->IoStatus
.Information
= 0;
933 IoCompleteRequest(IrpContext
->Irp
, IO_NO_INCREMENT
);
934 VfatFreeIrpContext(IrpContext
);