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)
8 * Herve Poussineau (reactos@poussine.freesurf.fr)
12 /* INCLUDES *****************************************************************/
17 /* GLOBALS ******************************************************************/
19 const char* FileInformationClassNames
[] =
22 "FileDirectoryInformation",
23 "FileFullDirectoryInformation",
24 "FileBothDirectoryInformation",
25 "FileBasicInformation",
26 "FileStandardInformation",
27 "FileInternalInformation",
29 "FileAccessInformation",
30 "FileNameInformation",
31 "FileRenameInformation",
32 "FileLinkInformation",
33 "FileNamesInformation",
34 "FileDispositionInformation",
35 "FilePositionInformation",
36 "FileFullEaInformation",
37 "FileModeInformation",
38 "FileAlignmentInformation",
40 "FileAllocationInformation",
41 "FileEndOfFileInformation",
42 "FileAlternateNameInformation",
43 "FileStreamInformation",
44 "FilePipeInformation",
45 "FilePipeLocalInformation",
46 "FilePipeRemoteInformation",
47 "FileMailslotQueryInformation",
48 "FileMailslotSetInformation",
49 "FileCompressionInformation",
50 "FileObjectIdInformation",
51 "FileCompletionInformation",
52 "FileMoveClusterInformation",
53 "FileQuotaInformation",
54 "FileReparsePointInformation",
55 "FileNetworkOpenInformation",
56 "FileAttributeTagInformation",
57 "FileTrackingInformation",
58 "FileIdBothDirectoryInformation",
59 "FileIdFullDirectoryInformation",
60 "FileValidDataLengthInformation",
61 "FileShortNameInformation",
62 "FileMaximumInformation"
65 /* FUNCTIONS ****************************************************************/
68 VfatGetStandardInformation(PVFATFCB FCB
,
69 PFILE_STANDARD_INFORMATION StandardInfo
,
72 * FUNCTION: Retrieve the standard file information
76 if (*BufferLength
< sizeof(FILE_STANDARD_INFORMATION
))
77 return STATUS_BUFFER_OVERFLOW
;
80 ASSERT(StandardInfo
!= NULL
);
83 if (vfatFCBIsDirectory(FCB
))
85 StandardInfo
->AllocationSize
.QuadPart
= 0;
86 StandardInfo
->EndOfFile
.QuadPart
= 0;
87 StandardInfo
->Directory
= TRUE
;
91 StandardInfo
->AllocationSize
= FCB
->RFCB
.AllocationSize
;
92 StandardInfo
->EndOfFile
= FCB
->RFCB
.FileSize
;
93 StandardInfo
->Directory
= FALSE
;
95 StandardInfo
->NumberOfLinks
= 0;
96 StandardInfo
->DeletePending
= FCB
->Flags
& FCB_DELETE_PENDING
? TRUE
: FALSE
;
98 *BufferLength
-= sizeof(FILE_STANDARD_INFORMATION
);
99 return(STATUS_SUCCESS
);
103 VfatSetPositionInformation(PFILE_OBJECT FileObject
,
104 PFILE_POSITION_INFORMATION PositionInfo
)
106 DPRINT ("FsdSetPositionInformation()\n");
108 DPRINT ("PositionInfo %x\n", PositionInfo
);
109 DPRINT ("Setting position %d\n", PositionInfo
->CurrentByteOffset
.u
.LowPart
);
111 FileObject
->CurrentByteOffset
.QuadPart
=
112 PositionInfo
->CurrentByteOffset
.QuadPart
;
114 return (STATUS_SUCCESS
);
118 VfatGetPositionInformation(PFILE_OBJECT FileObject
,
120 PDEVICE_OBJECT DeviceObject
,
121 PFILE_POSITION_INFORMATION PositionInfo
,
124 DPRINT ("VfatGetPositionInformation()\n");
126 if (*BufferLength
< sizeof(FILE_POSITION_INFORMATION
))
127 return STATUS_BUFFER_OVERFLOW
;
129 PositionInfo
->CurrentByteOffset
.QuadPart
=
130 FileObject
->CurrentByteOffset
.QuadPart
;
132 DPRINT("Getting position %I64x\n",
133 PositionInfo
->CurrentByteOffset
.QuadPart
);
135 *BufferLength
-= sizeof(FILE_POSITION_INFORMATION
);
136 return(STATUS_SUCCESS
);
140 VfatSetBasicInformation(PFILE_OBJECT FileObject
,
142 PDEVICE_EXTENSION DeviceExt
,
143 PFILE_BASIC_INFORMATION BasicInfo
)
145 DPRINT("VfatSetBasicInformation()\n");
147 ASSERT(NULL
!= FileObject
);
149 ASSERT(NULL
!= DeviceExt
);
150 ASSERT(NULL
!= BasicInfo
);
151 /* Check volume label bit */
152 ASSERT(0 == (*FCB
->Attributes
& 0x08));
154 if (FCB
->Flags
& FCB_IS_FATX_ENTRY
)
156 FsdSystemTimeToDosDateTime(DeviceExt
,
157 &BasicInfo
->CreationTime
,
158 &FCB
->entry
.FatX
.CreationDate
,
159 &FCB
->entry
.FatX
.CreationTime
);
160 FsdSystemTimeToDosDateTime(DeviceExt
,
161 &BasicInfo
->LastAccessTime
,
162 &FCB
->entry
.FatX
.AccessDate
,
163 &FCB
->entry
.FatX
.AccessTime
);
164 FsdSystemTimeToDosDateTime(DeviceExt
,
165 &BasicInfo
->LastWriteTime
,
166 &FCB
->entry
.FatX
.UpdateDate
,
167 &FCB
->entry
.FatX
.UpdateTime
);
171 FsdSystemTimeToDosDateTime(DeviceExt
,
172 &BasicInfo
->CreationTime
,
173 &FCB
->entry
.Fat
.CreationDate
,
174 &FCB
->entry
.Fat
.CreationTime
);
175 FsdSystemTimeToDosDateTime(DeviceExt
,
176 &BasicInfo
->LastAccessTime
,
177 &FCB
->entry
.Fat
.AccessDate
,
179 FsdSystemTimeToDosDateTime(DeviceExt
,
180 &BasicInfo
->LastWriteTime
,
181 &FCB
->entry
.Fat
.UpdateDate
,
182 &FCB
->entry
.Fat
.UpdateTime
);
185 *FCB
->Attributes
= (unsigned char)((*FCB
->Attributes
&
186 (FILE_ATTRIBUTE_DIRECTORY
| 0x48)) |
187 (BasicInfo
->FileAttributes
&
188 (FILE_ATTRIBUTE_ARCHIVE
|
189 FILE_ATTRIBUTE_SYSTEM
|
190 FILE_ATTRIBUTE_HIDDEN
|
191 FILE_ATTRIBUTE_READONLY
)));
192 DPRINT("Setting attributes 0x%02x\n", *FCB
->Attributes
);
194 VfatUpdateEntry(FCB
);
196 return(STATUS_SUCCESS
);
200 VfatGetBasicInformation(PFILE_OBJECT FileObject
,
202 PDEVICE_OBJECT DeviceObject
,
203 PFILE_BASIC_INFORMATION BasicInfo
,
206 PDEVICE_EXTENSION DeviceExt
;
207 DPRINT("VfatGetBasicInformation()\n");
209 DeviceExt
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
211 if (*BufferLength
< sizeof(FILE_BASIC_INFORMATION
))
212 return STATUS_BUFFER_OVERFLOW
;
214 if (FCB
->Flags
& FCB_IS_FATX_ENTRY
)
216 FsdDosDateTimeToSystemTime(DeviceExt
,
217 FCB
->entry
.FatX
.CreationDate
,
218 FCB
->entry
.FatX
.CreationTime
,
219 &BasicInfo
->CreationTime
);
220 FsdDosDateTimeToSystemTime(DeviceExt
,
221 FCB
->entry
.FatX
.AccessDate
,
222 FCB
->entry
.FatX
.AccessTime
,
223 &BasicInfo
->LastAccessTime
);
224 FsdDosDateTimeToSystemTime(DeviceExt
,
225 FCB
->entry
.FatX
.UpdateDate
,
226 FCB
->entry
.FatX
.UpdateTime
,
227 &BasicInfo
->LastWriteTime
);
228 BasicInfo
->ChangeTime
= BasicInfo
->LastWriteTime
;
232 FsdDosDateTimeToSystemTime(DeviceExt
,
233 FCB
->entry
.Fat
.CreationDate
,
234 FCB
->entry
.Fat
.CreationTime
,
235 &BasicInfo
->CreationTime
);
236 FsdDosDateTimeToSystemTime(DeviceExt
,
237 FCB
->entry
.Fat
.AccessDate
,
239 &BasicInfo
->LastAccessTime
);
240 FsdDosDateTimeToSystemTime(DeviceExt
,
241 FCB
->entry
.Fat
.UpdateDate
,
242 FCB
->entry
.Fat
.UpdateTime
,
243 &BasicInfo
->LastWriteTime
);
244 BasicInfo
->ChangeTime
= BasicInfo
->LastWriteTime
;
247 BasicInfo
->FileAttributes
= *FCB
->Attributes
& 0x3f;
248 /* Synthesize FILE_ATTRIBUTE_NORMAL */
249 if (0 == (BasicInfo
->FileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|
250 FILE_ATTRIBUTE_ARCHIVE
|
251 FILE_ATTRIBUTE_SYSTEM
|
252 FILE_ATTRIBUTE_HIDDEN
|
253 FILE_ATTRIBUTE_READONLY
)))
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 if (*BufferLength
< sizeof(FILE_NAME_INFORMATION
) + FCB
->PathNameU
.Length
+ sizeof(WCHAR
))
345 return STATUS_BUFFER_OVERFLOW
;
347 NameInfo
->FileNameLength
= FCB
->PathNameU
.Length
;
348 RtlCopyMemory(NameInfo
->FileName
, FCB
->PathNameU
.Buffer
, FCB
->PathNameU
.Length
);
349 NameInfo
->FileName
[FCB
->PathNameU
.Length
/ sizeof(WCHAR
)] = 0;
351 *BufferLength
-= (sizeof(FILE_NAME_INFORMATION
) + FCB
->PathNameU
.Length
+ sizeof(WCHAR
));
353 return STATUS_SUCCESS
;
357 VfatGetInternalInformation(PVFATFCB Fcb
,
358 PFILE_INTERNAL_INFORMATION InternalInfo
,
361 ASSERT(InternalInfo
);
364 if (*BufferLength
< sizeof(FILE_INTERNAL_INFORMATION
))
365 return STATUS_BUFFER_OVERFLOW
;
366 // FIXME: get a real index, that can be used in a create operation
367 InternalInfo
->IndexNumber
.QuadPart
= 0;
368 *BufferLength
-= sizeof(FILE_INTERNAL_INFORMATION
);
369 return STATUS_SUCCESS
;
374 VfatGetNetworkOpenInformation(PVFATFCB Fcb
,
375 PDEVICE_EXTENSION DeviceExt
,
376 PFILE_NETWORK_OPEN_INFORMATION NetworkInfo
,
379 * FUNCTION: Retrieve the file network open information
385 if (*BufferLength
< sizeof(FILE_NETWORK_OPEN_INFORMATION
))
386 return(STATUS_BUFFER_OVERFLOW
);
388 if (Fcb
->Flags
& FCB_IS_FATX_ENTRY
)
390 FsdDosDateTimeToSystemTime(DeviceExt
,
391 Fcb
->entry
.FatX
.CreationDate
,
392 Fcb
->entry
.FatX
.CreationTime
,
393 &NetworkInfo
->CreationTime
);
394 FsdDosDateTimeToSystemTime(DeviceExt
,
395 Fcb
->entry
.FatX
.AccessDate
,
396 Fcb
->entry
.FatX
.AccessTime
,
397 &NetworkInfo
->LastAccessTime
);
398 FsdDosDateTimeToSystemTime(DeviceExt
,
399 Fcb
->entry
.FatX
.UpdateDate
,
400 Fcb
->entry
.FatX
.UpdateTime
,
401 &NetworkInfo
->LastWriteTime
);
402 NetworkInfo
->ChangeTime
.QuadPart
= NetworkInfo
->LastWriteTime
.QuadPart
;
406 FsdDosDateTimeToSystemTime(DeviceExt
,
407 Fcb
->entry
.Fat
.CreationDate
,
408 Fcb
->entry
.Fat
.CreationTime
,
409 &NetworkInfo
->CreationTime
);
410 FsdDosDateTimeToSystemTime(DeviceExt
,
411 Fcb
->entry
.Fat
.AccessDate
,
413 &NetworkInfo
->LastAccessTime
);
414 FsdDosDateTimeToSystemTime(DeviceExt
,
415 Fcb
->entry
.Fat
.UpdateDate
,
416 Fcb
->entry
.Fat
.UpdateTime
,
417 &NetworkInfo
->LastWriteTime
);
418 NetworkInfo
->ChangeTime
.QuadPart
= NetworkInfo
->LastWriteTime
.QuadPart
;
420 if (vfatFCBIsDirectory(Fcb
))
422 NetworkInfo
->EndOfFile
.QuadPart
= 0L;
423 NetworkInfo
->AllocationSize
.QuadPart
= 0L;
427 NetworkInfo
->AllocationSize
= Fcb
->RFCB
.AllocationSize
;
428 NetworkInfo
->EndOfFile
= Fcb
->RFCB
.FileSize
;
430 NetworkInfo
->FileAttributes
= *Fcb
->Attributes
& 0x3f;
432 *BufferLength
-= sizeof(FILE_NETWORK_OPEN_INFORMATION
);
433 return STATUS_SUCCESS
;
438 VfatGetAllInformation(PFILE_OBJECT FileObject
,
440 PDEVICE_OBJECT DeviceObject
,
441 PFILE_ALL_INFORMATION Info
,
444 * FUNCTION: Retrieve the all file information
448 ULONG InitialBufferLength
= *BufferLength
;
453 if (*BufferLength
< sizeof(FILE_ALL_INFORMATION
) + Fcb
->PathNameU
.Length
+ sizeof(WCHAR
))
454 return(STATUS_BUFFER_OVERFLOW
);
456 /* Basic Information */
457 Status
= VfatGetBasicInformation(FileObject
, Fcb
, DeviceObject
, &Info
->BasicInformation
, BufferLength
);
458 if (!NT_SUCCESS(Status
)) return Status
;
459 /* Standard Information */
460 Status
= VfatGetStandardInformation(Fcb
, &Info
->StandardInformation
, BufferLength
);
461 if (!NT_SUCCESS(Status
)) return Status
;
462 /* Internal Information */
463 Status
= VfatGetInternalInformation(Fcb
, &Info
->InternalInformation
, BufferLength
);
464 if (!NT_SUCCESS(Status
)) return Status
;
466 Info
->EaInformation
.EaSize
= 0;
467 /* Access Information: The IO-Manager adds this information */
468 /* Position Information */
469 Status
= VfatGetPositionInformation(FileObject
, Fcb
, DeviceObject
, &Info
->PositionInformation
, BufferLength
);
470 if (!NT_SUCCESS(Status
)) return Status
;
471 /* Mode Information: The IO-Manager adds this information */
472 /* Alignment Information: The IO-Manager adds this information */
473 /* Name Information */
474 Status
= VfatGetNameInformation(FileObject
, Fcb
, DeviceObject
, &Info
->NameInformation
, BufferLength
);
475 if (!NT_SUCCESS(Status
)) return Status
;
477 *BufferLength
= InitialBufferLength
- (sizeof(FILE_ALL_INFORMATION
) + Fcb
->PathNameU
.Length
+ sizeof(WCHAR
));
479 return STATUS_SUCCESS
;
482 VOID
UpdateFileSize(PFILE_OBJECT FileObject
, PVFATFCB Fcb
, ULONG Size
, ULONG ClusterSize
)
486 Fcb
->RFCB
.AllocationSize
.QuadPart
= ROUND_UP(Size
, ClusterSize
);
490 Fcb
->RFCB
.AllocationSize
.QuadPart
= (LONGLONG
)0;
492 if (!vfatFCBIsDirectory(Fcb
))
494 if (Fcb
->Flags
& FCB_IS_FATX_ENTRY
)
495 Fcb
->entry
.FatX
.FileSize
= Size
;
497 Fcb
->entry
.Fat
.FileSize
= Size
;
499 Fcb
->RFCB
.FileSize
.QuadPart
= Size
;
500 Fcb
->RFCB
.ValidDataLength
.QuadPart
= Size
;
502 if (FileObject
->SectionObjectPointer
->SharedCacheMap
!= NULL
)
504 CcSetFileSizes(FileObject
, (PCC_FILE_SIZES
)&Fcb
->RFCB
.AllocationSize
);
509 VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject
,
511 PDEVICE_EXTENSION DeviceExt
,
512 PLARGE_INTEGER AllocationSize
)
515 ULONG Cluster
, FirstCluster
;
518 ULONG ClusterSize
= DeviceExt
->FatInfo
.BytesPerCluster
;
519 ULONG NewSize
= AllocationSize
->u
.LowPart
;
521 BOOLEAN AllocSizeChanged
= FALSE
;
523 DPRINT("VfatSetAllocationSizeInformation()\n");
525 if (Fcb
->Flags
& FCB_IS_FATX_ENTRY
)
526 OldSize
= Fcb
->entry
.FatX
.FileSize
;
528 OldSize
= Fcb
->entry
.Fat
.FileSize
;
529 if (AllocationSize
->u
.HighPart
> 0)
531 return STATUS_INVALID_PARAMETER
;
533 if (OldSize
== NewSize
)
535 return(STATUS_SUCCESS
);
538 FirstCluster
= vfatDirEntryGetFirstCluster (DeviceExt
, &Fcb
->entry
);
540 if (NewSize
> Fcb
->RFCB
.AllocationSize
.u
.LowPart
)
542 AllocSizeChanged
= TRUE
;
543 if (FirstCluster
== 0)
545 Fcb
->LastCluster
= Fcb
->LastOffset
= 0;
546 Status
= NextCluster (DeviceExt
, FirstCluster
, &FirstCluster
, TRUE
);
547 if (!NT_SUCCESS(Status
))
549 DPRINT1("NextCluster failed. Status = %x\n", Status
);
552 if (FirstCluster
== 0xffffffff)
554 return STATUS_DISK_FULL
;
556 Status
= OffsetToCluster(DeviceExt
, FirstCluster
,
557 ROUND_DOWN(NewSize
- 1, ClusterSize
),
559 if (NCluster
== 0xffffffff || !NT_SUCCESS(Status
))
562 NCluster
= Cluster
= FirstCluster
;
563 Status
= STATUS_SUCCESS
;
564 while (NT_SUCCESS(Status
) && Cluster
!= 0xffffffff && Cluster
> 1)
566 Status
= NextCluster (DeviceExt
, FirstCluster
, &NCluster
, FALSE
);
567 WriteCluster (DeviceExt
, Cluster
, 0);
570 return STATUS_DISK_FULL
;
572 if (Fcb
->Flags
& FCB_IS_FATX_ENTRY
)
574 Fcb
->entry
.FatX
.FirstCluster
= FirstCluster
;
578 Fcb
->entry
.Fat
.FirstCluster
= (unsigned short)(FirstCluster
& 0x0000FFFF);
579 Fcb
->entry
.Fat
.FirstClusterHigh
= (unsigned short)((FirstCluster
& 0xFFFF0000) >> 16);
584 if (Fcb
->LastCluster
> 0 &&
585 (Fcb
->RFCB
.AllocationSize
.u
.LowPart
- ClusterSize
) > Fcb
->LastOffset
)
587 Status
= OffsetToCluster(DeviceExt
, Fcb
->LastCluster
,
588 Fcb
->RFCB
.AllocationSize
.u
.LowPart
-
589 ClusterSize
- Fcb
->LastOffset
,
594 Status
= OffsetToCluster(DeviceExt
, FirstCluster
,
595 Fcb
->RFCB
.AllocationSize
.u
.LowPart
- ClusterSize
,
599 Fcb
->LastCluster
= Cluster
;
600 Fcb
->LastOffset
= Fcb
->RFCB
.AllocationSize
.u
.LowPart
- ClusterSize
;
602 /* FIXME: Check status */
603 /* Cluster points now to the last cluster within the chain */
604 Status
= OffsetToCluster(DeviceExt
, FirstCluster
,
605 ROUND_DOWN(NewSize
- 1, ClusterSize
),
607 if (NCluster
== 0xffffffff || !NT_SUCCESS(Status
))
611 Status
= NextCluster (DeviceExt
, FirstCluster
, &NCluster
, FALSE
);
612 WriteCluster(DeviceExt
, Cluster
, 0xffffffff);
614 while (NT_SUCCESS(Status
) && Cluster
!= 0xffffffff && Cluster
> 1)
616 Status
= NextCluster (DeviceExt
, FirstCluster
, &NCluster
, FALSE
);
617 WriteCluster (DeviceExt
, Cluster
, 0);
620 return STATUS_DISK_FULL
;
623 UpdateFileSize(FileObject
, Fcb
, NewSize
, ClusterSize
);
625 else if (NewSize
+ ClusterSize
<= Fcb
->RFCB
.AllocationSize
.u
.LowPart
)
627 AllocSizeChanged
= TRUE
;
628 /* FIXME: Use the cached cluster/offset better way. */
629 Fcb
->LastCluster
= Fcb
->LastCluster
= 0;
630 UpdateFileSize(FileObject
, Fcb
, NewSize
, ClusterSize
);
633 Status
= OffsetToCluster(DeviceExt
, FirstCluster
,
634 ROUND_DOWN(NewSize
- 1, ClusterSize
),
638 Status
= NextCluster (DeviceExt
, FirstCluster
, &NCluster
, FALSE
);
639 WriteCluster(DeviceExt
, Cluster
, 0xffffffff);
644 if (Fcb
->Flags
& FCB_IS_FATX_ENTRY
)
646 Fcb
->entry
.FatX
.FirstCluster
= 0;
650 Fcb
->entry
.Fat
.FirstCluster
= 0;
651 Fcb
->entry
.Fat
.FirstClusterHigh
= 0;
654 NCluster
= Cluster
= FirstCluster
;
655 Status
= STATUS_SUCCESS
;
657 while (NT_SUCCESS(Status
) && 0xffffffff != Cluster
&& Cluster
> 1)
659 Status
= NextCluster (DeviceExt
, FirstCluster
, &NCluster
, FALSE
);
660 WriteCluster (DeviceExt
, Cluster
, 0);
666 UpdateFileSize(FileObject
, Fcb
, NewSize
, ClusterSize
);
668 /* Update the on-disk directory entry */
669 Fcb
->Flags
|= FCB_IS_DIRTY
;
670 if (AllocSizeChanged
)
672 VfatUpdateEntry(Fcb
);
674 return STATUS_SUCCESS
;
677 NTSTATUS
VfatQueryInformation(PVFAT_IRP_CONTEXT IrpContext
)
679 * FUNCTION: Retrieve the specified file information
682 FILE_INFORMATION_CLASS FileInformationClass
;
685 NTSTATUS RC
= STATUS_SUCCESS
;
693 FileInformationClass
= IrpContext
->Stack
->Parameters
.QueryFile
.FileInformationClass
;
694 FCB
= (PVFATFCB
) IrpContext
->FileObject
->FsContext
;
696 DPRINT("VfatQueryInformation is called for '%s'\n",
697 FileInformationClass
>= FileMaximumInformation
- 1 ? "????" : FileInformationClassNames
[FileInformationClass
]);
700 SystemBuffer
= IrpContext
->Irp
->AssociatedIrp
.SystemBuffer
;
701 BufferLength
= IrpContext
->Stack
->Parameters
.QueryFile
.Length
;
703 if (!(FCB
->Flags
& FCB_IS_PAGE_FILE
))
705 if (!ExAcquireResourceSharedLite(&FCB
->MainResource
,
706 (BOOLEAN
)(IrpContext
->Flags
& IRPCONTEXT_CANWAIT
)))
708 return VfatQueueRequest (IrpContext
);
713 switch (FileInformationClass
)
715 case FileStandardInformation
:
716 RC
= VfatGetStandardInformation(FCB
,
720 case FilePositionInformation
:
721 RC
= VfatGetPositionInformation(IrpContext
->FileObject
,
723 IrpContext
->DeviceObject
,
727 case FileBasicInformation
:
728 RC
= VfatGetBasicInformation(IrpContext
->FileObject
,
730 IrpContext
->DeviceObject
,
734 case FileNameInformation
:
735 RC
= VfatGetNameInformation(IrpContext
->FileObject
,
737 IrpContext
->DeviceObject
,
741 case FileInternalInformation
:
742 RC
= VfatGetInternalInformation(FCB
,
746 case FileNetworkOpenInformation
:
747 RC
= VfatGetNetworkOpenInformation(FCB
,
748 IrpContext
->DeviceExt
,
752 case FileAllInformation
:
753 RC
= VfatGetAllInformation(IrpContext
->FileObject
,
755 IrpContext
->DeviceObject
,
760 case FileAlternateNameInformation
:
761 RC
= STATUS_NOT_IMPLEMENTED
;
764 RC
= STATUS_NOT_SUPPORTED
;
767 if (!(FCB
->Flags
& FCB_IS_PAGE_FILE
))
769 ExReleaseResourceLite(&FCB
->MainResource
);
771 IrpContext
->Irp
->IoStatus
.Status
= RC
;
773 IrpContext
->Irp
->IoStatus
.Information
=
774 IrpContext
->Stack
->Parameters
.QueryFile
.Length
- BufferLength
;
776 IrpContext
->Irp
->IoStatus
.Information
= 0;
777 IoCompleteRequest(IrpContext
->Irp
, IO_NO_INCREMENT
);
778 VfatFreeIrpContext(IrpContext
);
783 NTSTATUS
VfatSetInformation(PVFAT_IRP_CONTEXT IrpContext
)
785 * FUNCTION: Retrieve the specified file information
788 FILE_INFORMATION_CLASS FileInformationClass
;
790 NTSTATUS RC
= STATUS_SUCCESS
;
792 BOOLEAN CanWait
= (IrpContext
->Flags
& IRPCONTEXT_CANWAIT
) != 0;
797 DPRINT("VfatSetInformation(IrpContext %x)\n", IrpContext
);
800 FileInformationClass
=
801 IrpContext
->Stack
->Parameters
.SetFile
.FileInformationClass
;
802 FCB
= (PVFATFCB
) IrpContext
->FileObject
->FsContext
;
803 SystemBuffer
= IrpContext
->Irp
->AssociatedIrp
.SystemBuffer
;
805 DPRINT("VfatSetInformation is called for '%s'\n",
806 FileInformationClass
>= FileMaximumInformation
- 1 ? "????" : FileInformationClassNames
[ FileInformationClass
]);
808 DPRINT("FileInformationClass %d\n", FileInformationClass
);
809 DPRINT("SystemBuffer %x\n", SystemBuffer
);
811 if (!(FCB
->Flags
& FCB_IS_PAGE_FILE
))
813 if (!ExAcquireResourceExclusiveLite(&FCB
->MainResource
,
816 return(VfatQueueRequest (IrpContext
));
820 switch (FileInformationClass
)
822 case FilePositionInformation
:
823 RC
= VfatSetPositionInformation(IrpContext
->FileObject
,
826 case FileDispositionInformation
:
827 RC
= VfatSetDispositionInformation(IrpContext
->FileObject
,
829 IrpContext
->DeviceObject
,
832 case FileAllocationInformation
:
833 case FileEndOfFileInformation
:
834 RC
= VfatSetAllocationSizeInformation(IrpContext
->FileObject
,
836 IrpContext
->DeviceExt
,
837 (PLARGE_INTEGER
)SystemBuffer
);
839 case FileBasicInformation
:
840 RC
= VfatSetBasicInformation(IrpContext
->FileObject
,
842 IrpContext
->DeviceExt
,
845 case FileRenameInformation
:
846 RC
= STATUS_NOT_IMPLEMENTED
;
849 RC
= STATUS_NOT_SUPPORTED
;
852 if (!(FCB
->Flags
& FCB_IS_PAGE_FILE
))
854 ExReleaseResourceLite(&FCB
->MainResource
);
857 IrpContext
->Irp
->IoStatus
.Status
= RC
;
858 IrpContext
->Irp
->IoStatus
.Information
= 0;
859 IoCompleteRequest(IrpContext
->Irp
, IO_NO_INCREMENT
);
860 VfatFreeIrpContext(IrpContext
);