3 Copyright (c) 1989-2000 Microsoft Corporation
11 This module implements the volume information routines for Fat called by
20 // The local debug trace level
23 #define Dbg (DEBUG_TRACE_VOLINFO)
26 FatQueryFsVolumeInfo (
27 IN PIRP_CONTEXT IrpContext
,
29 IN PFILE_FS_VOLUME_INFORMATION Buffer
,
35 IN PIRP_CONTEXT IrpContext
,
37 IN PFILE_FS_SIZE_INFORMATION Buffer
,
42 FatQueryFsDeviceInfo (
43 IN PIRP_CONTEXT IrpContext
,
45 IN PFILE_FS_DEVICE_INFORMATION Buffer
,
50 FatQueryFsAttributeInfo (
51 IN PIRP_CONTEXT IrpContext
,
53 IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer
,
58 FatQueryFsFullSizeInfo (
59 IN PIRP_CONTEXT IrpContext
,
61 IN PFILE_FS_FULL_SIZE_INFORMATION Buffer
,
67 IN PIRP_CONTEXT IrpContext
,
69 IN PFILE_FS_LABEL_INFORMATION Buffer
72 #if (NTDDI_VERSION >= NTDDI_WIN8)
74 FatQueryFsSectorSizeInfo (
75 _In_ PIRP_CONTEXT IrpContext
,
77 _Out_writes_bytes_(*Length
) PFILE_FS_SECTOR_SIZE_INFORMATION Buffer
,
83 #pragma alloc_text(PAGE, FatCommonQueryVolumeInfo)
84 #pragma alloc_text(PAGE, FatCommonSetVolumeInfo)
85 #pragma alloc_text(PAGE, FatFsdQueryVolumeInformation)
86 #pragma alloc_text(PAGE, FatFsdSetVolumeInformation)
87 #pragma alloc_text(PAGE, FatQueryFsAttributeInfo)
88 #pragma alloc_text(PAGE, FatQueryFsDeviceInfo)
89 #pragma alloc_text(PAGE, FatQueryFsSizeInfo)
90 #pragma alloc_text(PAGE, FatQueryFsVolumeInfo)
91 #pragma alloc_text(PAGE, FatQueryFsFullSizeInfo)
92 #pragma alloc_text(PAGE, FatSetFsLabelInfo)
93 #if (NTDDI_VERSION >= NTDDI_WIN8)
94 #pragma alloc_text(PAGE, FatQueryFsSectorSizeInfo)
99 _Function_class_(IRP_MJ_QUERY_VOLUME_INFORMATION
)
100 _Function_class_(DRIVER_DISPATCH
)
103 FatFsdQueryVolumeInformation (
104 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject
,
112 This routine implements the Fsd part of the NtQueryVolumeInformation API
117 VolumeDeviceObject - Supplies the volume device object where the file
118 being queried exists.
120 Irp - Supplies the Irp being processed.
124 NTSTATUS - The FSD status for the Irp.
130 PIRP_CONTEXT IrpContext
= NULL
;
136 DebugTrace(+1, Dbg
, "FatFsdQueryVolumeInformation\n", 0);
139 // Call the common query routine, with blocking allowed if synchronous
142 FsRtlEnterFileSystem();
144 TopLevel
= FatIsIrpTopLevel( Irp
);
148 IrpContext
= FatCreateIrpContext( Irp
, CanFsdWait( Irp
) );
150 Status
= FatCommonQueryVolumeInfo( IrpContext
, Irp
);
152 } _SEH2_EXCEPT(FatExceptionFilter( IrpContext
, _SEH2_GetExceptionInformation() )) {
155 // We had some trouble trying to perform the requested
156 // operation, so we'll abort the I/O request with
157 // the error status that we get back from the
161 Status
= FatProcessException( IrpContext
, Irp
, _SEH2_GetExceptionCode() );
164 if (TopLevel
) { IoSetTopLevelIrp( NULL
); }
166 FsRtlExitFileSystem();
169 // And return to our caller
172 DebugTrace(-1, Dbg
, "FatFsdQueryVolumeInformation -> %08lx\n", Status
);
174 UNREFERENCED_PARAMETER( VolumeDeviceObject
);
180 _Function_class_(IRP_MJ_SET_VOLUME_INFORMATION
)
181 _Function_class_(DRIVER_DISPATCH
)
184 FatFsdSetVolumeInformation (
185 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject
,
193 This routine implements the FSD part of the NtSetVolumeInformation API
198 VolumeDeviceObject - Supplies the volume device object where the file
201 Irp - Supplies the Irp being processed.
205 NTSTATUS - The FSD status for the Irp.
211 PIRP_CONTEXT IrpContext
= NULL
;
217 DebugTrace(+1, Dbg
, "FatFsdSetVolumeInformation\n", 0);
220 // Call the common set routine
223 FsRtlEnterFileSystem();
225 TopLevel
= FatIsIrpTopLevel( Irp
);
229 IrpContext
= FatCreateIrpContext( Irp
, CanFsdWait( Irp
) );
231 Status
= FatCommonSetVolumeInfo( IrpContext
, Irp
);
233 } _SEH2_EXCEPT(FatExceptionFilter( IrpContext
, _SEH2_GetExceptionInformation() )) {
236 // We had some trouble trying to perform the requested
237 // operation, so we'll abort the I/O request with
238 // the error status that we get back from the
242 Status
= FatProcessException( IrpContext
, Irp
, _SEH2_GetExceptionCode() );
245 if (TopLevel
) { IoSetTopLevelIrp( NULL
); }
247 FsRtlExitFileSystem();
250 // And return to our caller
253 DebugTrace(-1, Dbg
, "FatFsdSetVolumeInformation -> %08lx\n", Status
);
255 UNREFERENCED_PARAMETER( VolumeDeviceObject
);
261 _Requires_lock_held_(_Global_critical_region_
)
263 FatCommonQueryVolumeInfo (
264 IN PIRP_CONTEXT IrpContext
,
272 This is the common routine for querying volume information called by both
273 the fsd and fsp threads.
277 Irp - Supplies the Irp being processed
281 NTSTATUS - The return status for the operation
286 NTSTATUS Status
= STATUS_SUCCESS
;
287 PIO_STACK_LOCATION IrpSp
;
294 FS_INFORMATION_CLASS FsInformationClass
;
297 BOOLEAN WeAcquiredVcb
= FALSE
;
302 // Get the current stack location
305 IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
307 DebugTrace(+1, Dbg
, "FatCommonQueryVolumeInfo...\n", 0);
308 DebugTrace( 0, Dbg
, "Irp = %p\n", Irp
);
309 DebugTrace( 0, Dbg
, "->Length = %08lx\n", IrpSp
->Parameters
.QueryVolume
.Length
);
310 DebugTrace( 0, Dbg
, "->FsInformationClass = %08lx\n", IrpSp
->Parameters
.QueryVolume
.FsInformationClass
);
311 DebugTrace( 0, Dbg
, "->Buffer = %p\n", Irp
->AssociatedIrp
.SystemBuffer
);
314 // Reference our input parameters to make things easier
317 Length
= IrpSp
->Parameters
.QueryVolume
.Length
;
318 FsInformationClass
= IrpSp
->Parameters
.QueryVolume
.FsInformationClass
;
319 Buffer
= Irp
->AssociatedIrp
.SystemBuffer
;
322 // Decode the file object to get the Vcb
325 (VOID
) FatDecodeFileObject( IrpSp
->FileObject
, &Vcb
, &Fcb
, &Ccb
);
327 NT_ASSERT( Vcb
!= NULL
);
328 _Analysis_assume_( Vcb
!= NULL
);
333 // Make sure the vcb is in a usable condition. This will raise
334 // and error condition if the volume is unusable
336 // Also verify the Root Dcb since we need info from there.
339 FatVerifyFcb( IrpContext
, Vcb
->RootDcb
);
342 // Based on the information class we'll do different actions. Each
343 // of the procedures that we're calling fills up the output buffer
344 // if possible and returns true if it successfully filled the buffer
345 // and false if it couldn't wait for any I/O to complete.
348 switch (FsInformationClass
) {
350 case FileFsVolumeInformation
:
353 // This is the only routine we need the Vcb shared because of
354 // copying the volume label. All other routines copy fields that
355 // cannot change or are just manifest constants.
358 if (!FatAcquireSharedVcb( IrpContext
, Vcb
)) {
360 DebugTrace(0, Dbg
, "Cannot acquire Vcb\n", 0);
362 Status
= FatFsdPostRequest( IrpContext
, Irp
);
368 WeAcquiredVcb
= TRUE
;
370 Status
= FatQueryFsVolumeInfo( IrpContext
, Vcb
, Buffer
, &Length
);
375 case FileFsSizeInformation
:
377 Status
= FatQueryFsSizeInfo( IrpContext
, Vcb
, Buffer
, &Length
);
380 case FileFsDeviceInformation
:
382 Status
= FatQueryFsDeviceInfo( IrpContext
, Vcb
, Buffer
, &Length
);
385 case FileFsAttributeInformation
:
387 Status
= FatQueryFsAttributeInfo( IrpContext
, Vcb
, Buffer
, &Length
);
390 case FileFsFullSizeInformation
:
392 Status
= FatQueryFsFullSizeInfo( IrpContext
, Vcb
, Buffer
, &Length
);
395 #if (NTDDI_VERSION >= NTDDI_WIN8)
396 case FileFsSectorSizeInformation
:
398 Status
= FatQueryFsSectorSizeInfo( IrpContext
, Vcb
, Buffer
, &Length
);
404 Status
= STATUS_INVALID_PARAMETER
;
409 // Set the information field to the number of bytes actually filled in.
414 Irp
->IoStatus
.Information
= IrpSp
->Parameters
.QueryVolume
.Length
- Length
;
419 DebugUnwind( FatCommonQueryVolumeInfo
);
423 FatReleaseVcb( IrpContext
, Vcb
);
426 if (!_SEH2_AbnormalTermination()) {
428 FatCompleteRequest( IrpContext
, Irp
, Status
);
431 DebugTrace(-1, Dbg
, "FatCommonQueryVolumeInfo -> %08lx\n", Status
);
438 _Requires_lock_held_(_Global_critical_region_
)
440 FatCommonSetVolumeInfo (
441 IN PIRP_CONTEXT IrpContext
,
449 This is the common routine for setting Volume Information called by both
450 the fsd and fsp threads.
454 Irp - Supplies the Irp being processed
458 NTSTATUS - The return status for the operation
463 NTSTATUS Status
= STATUS_SUCCESS
;
464 PIO_STACK_LOCATION IrpSp
;
469 TYPE_OF_OPEN TypeOfOpen
;
471 FS_INFORMATION_CLASS FsInformationClass
;
477 // Get the current stack location
480 IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
482 DebugTrace(+1, Dbg
, "FatCommonSetVolumeInfo...\n", 0);
483 DebugTrace( 0, Dbg
, "Irp = %p\n", Irp
);
484 DebugTrace( 0, Dbg
, "->Length = %08lx\n", IrpSp
->Parameters
.SetVolume
.Length
);
485 DebugTrace( 0, Dbg
, "->FsInformationClass = %08lx\n", IrpSp
->Parameters
.SetVolume
.FsInformationClass
);
486 DebugTrace( 0, Dbg
, "->Buffer = %p\n", Irp
->AssociatedIrp
.SystemBuffer
);
489 // Reference our input parameters to make things easier
492 FsInformationClass
= IrpSp
->Parameters
.SetVolume
.FsInformationClass
;
493 Buffer
= Irp
->AssociatedIrp
.SystemBuffer
;
496 // Decode the file object to get the Vcb
499 TypeOfOpen
= FatDecodeFileObject( IrpSp
->FileObject
, &Vcb
, &Fcb
, &Ccb
);
501 if (TypeOfOpen
!= UserVolumeOpen
) {
503 FatCompleteRequest( IrpContext
, Irp
, STATUS_ACCESS_DENIED
);
505 DebugTrace(-1, Dbg
, "FatCommonSetVolumeInfo -> STATUS_ACCESS_DENIED\n", 0);
507 return STATUS_ACCESS_DENIED
;
511 // Acquire exclusive access to the Vcb and enqueue the Irp if we didn't
515 if (!FatAcquireExclusiveVcb( IrpContext
, Vcb
)) {
517 DebugTrace(0, Dbg
, "Cannot acquire Vcb\n", 0);
519 Status
= FatFsdPostRequest( IrpContext
, Irp
);
521 DebugTrace(-1, Dbg
, "FatCommonSetVolumeInfo -> %08lx\n", Status
);
528 // Make sure the vcb is in a usable condition. This will raise
529 // and error condition if the volume is unusable
531 // Also verify the Root Dcb since we need info from there.
534 FatVerifyFcb( IrpContext
, Vcb
->RootDcb
);
537 // Based on the information class we'll do different actions. Each
538 // of the procedures that we're calling performs the action if
539 // possible and returns true if it successful and false if it couldn't
540 // wait for any I/O to complete.
543 switch (FsInformationClass
) {
545 case FileFsLabelInformation
:
547 Status
= FatSetFsLabelInfo( IrpContext
, Vcb
, Buffer
);
552 Status
= STATUS_INVALID_PARAMETER
;
556 FatUnpinRepinnedBcbs( IrpContext
);
560 DebugUnwind( FatCommonSetVolumeInfo
);
562 FatReleaseVcb( IrpContext
, Vcb
);
564 if (!_SEH2_AbnormalTermination()) {
566 FatCompleteRequest( IrpContext
, Irp
, Status
);
569 DebugTrace(-1, Dbg
, "FatCommonSetVolumeInfo -> %08lx\n", Status
);
577 // Internal support routine
581 FatQueryFsVolumeInfo (
582 IN PIRP_CONTEXT IrpContext
,
584 IN PFILE_FS_VOLUME_INFORMATION Buffer
,
592 This routine implements the query volume info call
596 Vcb - Supplies the Vcb being queried
598 Buffer - Supplies a pointer to the output buffer where the information
601 Length - Supplies the length of the buffer in byte. This variable
602 upon return recieves the remaining bytes free in the buffer
606 NTSTATUS - Returns the status for the query
617 DebugTrace(0, Dbg
, "FatQueryFsVolumeInfo...\n", 0);
620 // Zero out the buffer, then extract and fill up the non zero fields.
623 RtlZeroMemory( Buffer
, sizeof(FILE_FS_VOLUME_INFORMATION
) );
625 Buffer
->VolumeSerialNumber
= Vcb
->Vpb
->SerialNumber
;
627 Buffer
->SupportsObjects
= FALSE
;
629 *Length
-= FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION
, VolumeLabel
[0]);
632 // Check if the buffer we're given is long enough
635 if ( *Length
>= (ULONG
)Vcb
->Vpb
->VolumeLabelLength
) {
637 BytesToCopy
= Vcb
->Vpb
->VolumeLabelLength
;
639 Status
= STATUS_SUCCESS
;
643 BytesToCopy
= *Length
;
645 Status
= STATUS_BUFFER_OVERFLOW
;
649 // Copy over what we can of the volume label, and adjust *Length
652 Buffer
->VolumeLabelLength
= Vcb
->Vpb
->VolumeLabelLength
;
654 RtlCopyMemory( &Buffer
->VolumeLabel
[0],
655 &Vcb
->Vpb
->VolumeLabel
[0],
658 *Length
-= BytesToCopy
;
661 // Set our status and return to our caller
664 UNREFERENCED_PARAMETER( IrpContext
);
671 // Internal support routine
676 IN PIRP_CONTEXT IrpContext
,
678 IN PFILE_FS_SIZE_INFORMATION Buffer
,
686 This routine implements the query volume size call
690 Vcb - Supplies the Vcb being queried
692 Buffer - Supplies a pointer to the output buffer where the information
695 Length - Supplies the length of the buffer in byte. This variable
696 upon return recieves the remaining bytes free in the buffer
700 Status - Returns the status for the query
707 DebugTrace(0, Dbg
, "FatQueryFsSizeInfo...\n", 0);
709 RtlZeroMemory( Buffer
, sizeof(FILE_FS_SIZE_INFORMATION
) );
712 // Set the output buffer.
715 Buffer
->TotalAllocationUnits
.LowPart
=
716 Vcb
->AllocationSupport
.NumberOfClusters
;
717 Buffer
->AvailableAllocationUnits
.LowPart
=
718 Vcb
->AllocationSupport
.NumberOfFreeClusters
;
720 Buffer
->SectorsPerAllocationUnit
= Vcb
->Bpb
.SectorsPerCluster
;
721 Buffer
->BytesPerSector
= Vcb
->Bpb
.BytesPerSector
;
724 // Adjust the length variable
727 *Length
-= sizeof(FILE_FS_SIZE_INFORMATION
);
730 // And return success to our caller
733 UNREFERENCED_PARAMETER( IrpContext
);
735 return STATUS_SUCCESS
;
740 // Internal support routine
744 FatQueryFsDeviceInfo (
745 IN PIRP_CONTEXT IrpContext
,
747 IN PFILE_FS_DEVICE_INFORMATION Buffer
,
755 This routine implements the query volume device call
759 Vcb - Supplies the Vcb being queried
761 Buffer - Supplies a pointer to the output buffer where the information
764 Length - Supplies the length of the buffer in byte. This variable
765 upon return recieves the remaining bytes free in the buffer
769 Status - Returns the status for the query
776 DebugTrace(0, Dbg
, "FatQueryFsDeviceInfo...\n", 0);
778 RtlZeroMemory( Buffer
, sizeof(FILE_FS_DEVICE_INFORMATION
) );
781 // Set the output buffer
784 Buffer
->DeviceType
= FILE_DEVICE_DISK
;
786 Buffer
->Characteristics
= Vcb
->TargetDeviceObject
->Characteristics
;
789 // Adjust the length variable
792 *Length
-= sizeof(FILE_FS_DEVICE_INFORMATION
);
795 // And return success to our caller
798 UNREFERENCED_PARAMETER( IrpContext
);
800 return STATUS_SUCCESS
;
805 // Internal support routine
809 FatQueryFsAttributeInfo (
810 IN PIRP_CONTEXT IrpContext
,
812 IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer
,
820 This routine implements the query volume attribute call
824 Vcb - Supplies the Vcb being queried
826 Buffer - Supplies a pointer to the output buffer where the information
829 Length - Supplies the length of the buffer in byte. This variable
830 upon return recieves the remaining bytes free in the buffer
834 Status - Returns the status for the query
845 DebugTrace(0, Dbg
, "FatQueryFsAttributeInfo...\n", 0);
848 // Set the output buffer
851 Buffer
->FileSystemAttributes
= FILE_CASE_PRESERVED_NAMES
|
852 FILE_UNICODE_ON_DISK
;
854 if (FlagOn( Vcb
->VcbState
, VCB_STATE_FLAG_WRITE_PROTECTED
)) {
856 SetFlag( Buffer
->FileSystemAttributes
, FILE_READ_ONLY_VOLUME
);
860 Buffer
->MaximumComponentNameLength
= FatData
.ChicagoMode
? 255 : 12;
862 if (FatIsFat32(Vcb
)) {
865 // Determine how much of the file system name will fit.
868 if ( (*Length
- FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION
,
869 FileSystemName
[0] )) >= 10 ) {
872 *Length
-= FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION
,
873 FileSystemName
[0] ) + 10;
874 Status
= STATUS_SUCCESS
;
878 BytesToCopy
= *Length
- FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION
,
882 Status
= STATUS_BUFFER_OVERFLOW
;
885 RtlCopyMemory( &Buffer
->FileSystemName
[0], L
"FAT32", BytesToCopy
);
890 // Determine how much of the file system name will fit.
893 if ( (*Length
- FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION
,
894 FileSystemName
[0] )) >= 6 ) {
897 *Length
-= FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION
,
898 FileSystemName
[0] ) + 6;
899 Status
= STATUS_SUCCESS
;
903 BytesToCopy
= *Length
- FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION
,
907 Status
= STATUS_BUFFER_OVERFLOW
;
911 RtlCopyMemory( &Buffer
->FileSystemName
[0], L
"FAT", BytesToCopy
);
914 Buffer
->FileSystemNameLength
= BytesToCopy
;
917 // And return success to our caller
920 UNREFERENCED_PARAMETER( IrpContext
);
921 UNREFERENCED_PARAMETER( Vcb
);
928 // Internal support routine
932 FatQueryFsFullSizeInfo (
933 IN PIRP_CONTEXT IrpContext
,
935 IN PFILE_FS_FULL_SIZE_INFORMATION Buffer
,
943 This routine implements the query volume full size call
947 Vcb - Supplies the Vcb being queried
949 Buffer - Supplies a pointer to the output buffer where the information
952 Length - Supplies the length of the buffer in byte. This variable
953 upon return recieves the remaining bytes free in the buffer
957 Status - Returns the status for the query
964 DebugTrace(0, Dbg
, "FatQueryFsSizeInfo...\n", 0);
966 RtlZeroMemory( Buffer
, sizeof(FILE_FS_FULL_SIZE_INFORMATION
) );
968 Buffer
->TotalAllocationUnits
.LowPart
=
969 Vcb
->AllocationSupport
.NumberOfClusters
;
970 Buffer
->CallerAvailableAllocationUnits
.LowPart
=
971 Vcb
->AllocationSupport
.NumberOfFreeClusters
;
972 Buffer
->ActualAvailableAllocationUnits
.LowPart
=
973 Buffer
->CallerAvailableAllocationUnits
.LowPart
;
974 Buffer
->SectorsPerAllocationUnit
= Vcb
->Bpb
.SectorsPerCluster
;
975 Buffer
->BytesPerSector
= Vcb
->Bpb
.BytesPerSector
;
978 // Adjust the length variable
981 *Length
-= sizeof(FILE_FS_FULL_SIZE_INFORMATION
);
984 // And return success to our caller
987 UNREFERENCED_PARAMETER( IrpContext
);
989 return STATUS_SUCCESS
;
994 // Internal support routine
999 IN PIRP_CONTEXT IrpContext
,
1001 IN PFILE_FS_LABEL_INFORMATION Buffer
1006 Routine Description:
1008 This routine implements the set volume label call
1012 Vcb - Supplies the Vcb being queried
1014 Buffer - Supplies the input where the information is stored.
1018 NTSTATUS - Returns the status for the operation
1026 PBCB DirentBcb
= NULL
;
1029 WCHAR TmpBuffer
[11];
1030 UCHAR OemBuffer
[11];
1031 OEM_STRING OemLabel
;
1032 UNICODE_STRING UnicodeString
;
1033 UNICODE_STRING UpcasedLabel
;
1037 DebugTrace(+1, Dbg
, "FatSetFsLabelInfo...\n", 0);
1040 // Setup our local variable
1043 UnicodeString
.Length
= (USHORT
)Buffer
->VolumeLabelLength
;
1044 UnicodeString
.MaximumLength
= UnicodeString
.Length
;
1045 UnicodeString
.Buffer
= (PWSTR
) &Buffer
->VolumeLabel
[0];
1048 // Make sure the name can fit into the stack buffer
1051 if ( UnicodeString
.Length
> 11*sizeof(WCHAR
) ) {
1053 return STATUS_INVALID_VOLUME_LABEL
;
1057 // Upcase the name and convert it to the Oem code page.
1060 OemLabel
.Buffer
= (PCHAR
)&OemBuffer
[0];
1061 OemLabel
.Length
= 0;
1062 OemLabel
.MaximumLength
= 11;
1064 Status
= RtlUpcaseUnicodeStringToCountedOemString( &OemLabel
,
1069 // Volume label that fits in 11 unicode character length limit
1070 // is not necessary within 11 characters in OEM character set.
1073 if (!NT_SUCCESS( Status
)) {
1075 DebugTrace(-1, Dbg
, "FatSetFsLabelInfo: Label must be too long. %08lx\n", Status
);
1077 return STATUS_INVALID_VOLUME_LABEL
;
1081 // Strip spaces off of the label.
1084 if (OemLabel
.Length
> 0) {
1087 USHORT LastSpaceIndex
= MAXUSHORT
;
1090 // Check the label for illegal characters
1093 for ( i
= 0; i
< (ULONG
)OemLabel
.Length
; i
+= 1 ) {
1095 if ( FsRtlIsLeadDbcsCharacter( OemLabel
.Buffer
[i
] ) ) {
1097 LastSpaceIndex
= MAXUSHORT
;
1102 if (!FsRtlIsAnsiCharacterLegalFat(OemLabel
.Buffer
[i
], FALSE
) ||
1103 (OemLabel
.Buffer
[i
] == '.')) {
1105 return STATUS_INVALID_VOLUME_LABEL
;
1109 // Watch for the last run of spaces, so we can strip them.
1112 if (OemLabel
.Buffer
[i
] == ' ' &&
1113 LastSpaceIndex
== MAXUSHORT
) {
1116 LastSpaceIndex
= MAXUSHORT
;
1120 if (LastSpaceIndex
!= MAXUSHORT
) {
1121 OemLabel
.Length
= LastSpaceIndex
;
1126 // Get the Unicode upcased string to store in the VPB.
1129 UpcasedLabel
.Length
= UnicodeString
.Length
;
1130 UpcasedLabel
.MaximumLength
= 11*sizeof(WCHAR
);
1131 UpcasedLabel
.Buffer
= &TmpBuffer
[0];
1133 Status
= RtlOemStringToCountedUnicodeString( &UpcasedLabel
,
1137 if (!NT_SUCCESS( Status
)) {
1139 DebugTrace(-1, Dbg
, "FatSetFsLabelInfo: Label must be too long. %08lx\n", Status
);
1141 return STATUS_INVALID_VOLUME_LABEL
;
1147 // Make this look like a write through to disk. This is important to
1148 // avoid a unpleasant window where it looks like we have the wrong volume.
1151 SetFlag( IrpContext
->Flags
, IRP_CONTEXT_FLAG_WRITE_THROUGH
);
1156 // Are we setting or removing the label? Note that shaving spaces could
1157 // make this different than wondering if the input buffer is non-zero length.
1160 if (OemLabel
.Length
> 0) {
1163 // Locate the volume label if there already is one
1166 FatLocateVolumeLabel( IrpContext
,
1170 (PVBO
)&ByteOffset
);
1173 // Check that we really got one, if not then we need to create
1174 // a new one. The procedure we call will raise an appropriate
1175 // status if we are not able to allocate a new dirent
1178 if (Dirent
== NULL
) {
1180 ByteOffset
= FatCreateNewDirent( IrpContext
,
1185 FatPrepareWriteDirectoryFile( IrpContext
,
1199 NT_ASSERT( NT_SUCCESS( Status
));
1204 // Just mark this guy dirty now.
1207 FatSetDirtyBcb( IrpContext
, DirentBcb
, Vcb
, TRUE
);
1211 // Now reconstruct the volume label dirent.
1214 FatConstructLabelDirent( IrpContext
,
1219 // Unpin the Bcb here so that we will get any IO errors
1220 // here before changing the VPB label.
1223 FatUnpinBcb( IrpContext
, DirentBcb
);
1224 FatUnpinRepinnedBcbs( IrpContext
);
1227 // Now set the upcased label in the VPB
1230 RtlCopyMemory( &Vcb
->Vpb
->VolumeLabel
[0],
1231 &UpcasedLabel
.Buffer
[0],
1232 UpcasedLabel
.Length
);
1234 Vcb
->Vpb
->VolumeLabelLength
= UpcasedLabel
.Length
;
1239 // Otherwise we're trying to delete the label
1240 // Locate the current volume label if there already is one
1243 FatLocateVolumeLabel( IrpContext
,
1247 (PVBO
)&ByteOffset
);
1250 // Check that we really got one
1253 if (Dirent
== NULL
) {
1255 try_return( Status
= STATUS_SUCCESS
);
1259 // Now delete the current label.
1262 Dirent
->FileName
[0] = FAT_DIRENT_DELETED
;
1264 NT_ASSERT( (Vcb
->RootDcb
->Specific
.Dcb
.UnusedDirentVbo
== 0xffffffff) ||
1265 RtlAreBitsSet( &Vcb
->RootDcb
->Specific
.Dcb
.FreeDirentBitmap
,
1266 ByteOffset
/ sizeof(DIRENT
),
1269 RtlClearBits( &Vcb
->RootDcb
->Specific
.Dcb
.FreeDirentBitmap
,
1270 ByteOffset
/ sizeof(DIRENT
),
1273 FatSetDirtyBcb( IrpContext
, DirentBcb
, Vcb
, TRUE
);
1276 // Unpin the Bcb here so that we will get any IO errors
1277 // here before changing the VPB label.
1280 FatUnpinBcb( IrpContext
, DirentBcb
);
1281 FatUnpinRepinnedBcbs( IrpContext
);
1284 // Now set the label in the VPB
1287 Vcb
->Vpb
->VolumeLabelLength
= 0;
1290 Status
= STATUS_SUCCESS
;
1295 DebugUnwind( FatSetFsALabelInfo
);
1297 FatUnpinBcb( IrpContext
, DirentBcb
);
1299 DebugTrace(-1, Dbg
, "FatSetFsALabelInfo -> STATUS_SUCCESS\n", 0);
1305 #if (NTDDI_VERSION >= NTDDI_WIN8)
1308 FatQueryFsSectorSizeInfo (
1309 _In_ PIRP_CONTEXT IrpContext
,
1311 _Out_writes_bytes_(*Length
) PFILE_FS_SECTOR_SIZE_INFORMATION Buffer
,
1312 _Inout_ PULONG Length
1317 Routine Description:
1319 This routine implements the query sector size information call
1320 This operation will work on any handle and requires no privilege.
1324 Vcb - Supplies the Vcb being queried
1326 Buffer - Supplies a pointer to the output buffer where the information
1329 Length - Supplies the length of the buffer in byte. This variable
1330 upon return receives the remaining bytes free in the buffer
1334 NTSTATUS - Returns the status for the query
1342 UNREFERENCED_PARAMETER( IrpContext
);
1345 // Sufficient buffer size is guaranteed by the I/O manager or the
1346 // originating kernel mode driver.
1349 ASSERT( *Length
>= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION
));
1350 _Analysis_assume_( *Length
>= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION
));
1353 // Retrieve the sector size information
1356 Status
= FsRtlGetSectorSizeInformation( Vcb
->Vpb
->RealDevice
,
1360 // Adjust the length variable
1363 if (NT_SUCCESS( Status
)) {
1365 *Length
-= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION
);