2 * COPYRIGHT: See COPYRIGHT.TXT
3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP
5 * PROGRAMMER: Matt Wu <mattwu@163.com>
6 * HOMEPAGE: http://www.ext2fsd.com
10 /* INCLUDES *****************************************************************/
14 /* GLOBALS ***************************************************************/
16 extern PEXT2_GLOBAL Ext2Global
;
18 /* DEFINITIONS *************************************************************/
21 #pragma alloc_text(PAGE, Ext2QueryVolumeInformation)
22 #pragma alloc_text(PAGE, Ext2SetVolumeInformation)
27 Ext2QueryVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext
)
29 PDEVICE_OBJECT DeviceObject
;
32 PIO_STACK_LOCATION IoStackLocation
= NULL
;
35 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
36 FS_INFORMATION_CLASS FsInformationClass
;
37 BOOLEAN VcbResourceAcquired
= FALSE
;
41 ASSERT(IrpContext
!= NULL
);
42 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
43 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
45 DeviceObject
= IrpContext
->DeviceObject
;
48 // This request is not allowed on the main device object
50 if (IsExt2FsDevice(DeviceObject
)) {
51 Status
= STATUS_INVALID_DEVICE_REQUEST
;
55 Vcb
= (PEXT2_VCB
) DeviceObject
->DeviceExtension
;
57 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
58 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
60 if (!IsMounted(Vcb
)) {
61 Status
= STATUS_VOLUME_DISMOUNTED
;
65 if (!ExAcquireResourceSharedLite(
67 IsFlagOn(IrpContext
->Flags
, IRP_CONTEXT_FLAG_WAIT
)
70 Status
= STATUS_PENDING
;
73 VcbResourceAcquired
= TRUE
;
75 Irp
= IrpContext
->Irp
;
76 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
78 IoStackLocation
->Parameters
.QueryVolume
.FsInformationClass
;
80 Length
= IoStackLocation
->Parameters
.QueryVolume
.Length
;
81 Buffer
= Irp
->AssociatedIrp
.SystemBuffer
;
83 RtlZeroMemory(Buffer
, Length
);
85 switch (FsInformationClass
) {
87 case FileFsVolumeInformation
:
89 PFILE_FS_VOLUME_INFORMATION FsVolInfo
;
90 ULONG VolumeLabelLength
;
93 if (Length
< sizeof(FILE_FS_VOLUME_INFORMATION
)) {
94 Status
= STATUS_BUFFER_OVERFLOW
;
98 FsVolInfo
= (PFILE_FS_VOLUME_INFORMATION
) Buffer
;
99 FsVolInfo
->VolumeCreationTime
.QuadPart
= 0;
100 FsVolInfo
->VolumeSerialNumber
= Vcb
->Vpb
->SerialNumber
;
101 VolumeLabelLength
= Vcb
->Vpb
->VolumeLabelLength
;
102 FsVolInfo
->VolumeLabelLength
= VolumeLabelLength
;
103 /* We don't support ObjectId */
104 FsVolInfo
->SupportsObjects
= FALSE
;
106 RequiredLength
= sizeof(FILE_FS_VOLUME_INFORMATION
)
107 + VolumeLabelLength
- sizeof(WCHAR
);
109 if (Length
< RequiredLength
) {
110 Irp
->IoStatus
.Information
=
111 sizeof(FILE_FS_VOLUME_INFORMATION
);
112 Status
= STATUS_BUFFER_OVERFLOW
;
116 RtlCopyMemory(FsVolInfo
->VolumeLabel
, Vcb
->Vpb
->VolumeLabel
, Vcb
->Vpb
->VolumeLabelLength
);
118 Irp
->IoStatus
.Information
= RequiredLength
;
119 Status
= STATUS_SUCCESS
;
123 case FileFsSizeInformation
:
125 PFILE_FS_SIZE_INFORMATION FsSizeInfo
;
127 if (Length
< sizeof(FILE_FS_SIZE_INFORMATION
)) {
128 Status
= STATUS_BUFFER_OVERFLOW
;
132 FsSizeInfo
= (PFILE_FS_SIZE_INFORMATION
) Buffer
;
133 FsSizeInfo
->TotalAllocationUnits
.QuadPart
=
134 ext3_blocks_count(SUPER_BLOCK
);
135 FsSizeInfo
->AvailableAllocationUnits
.QuadPart
=
136 ext3_free_blocks_count(SUPER_BLOCK
);
137 FsSizeInfo
->SectorsPerAllocationUnit
=
138 Vcb
->BlockSize
/ Vcb
->DiskGeometry
.BytesPerSector
;
139 FsSizeInfo
->BytesPerSector
=
140 Vcb
->DiskGeometry
.BytesPerSector
;
142 Irp
->IoStatus
.Information
= sizeof(FILE_FS_SIZE_INFORMATION
);
143 Status
= STATUS_SUCCESS
;
147 case FileFsDeviceInformation
:
149 PFILE_FS_DEVICE_INFORMATION FsDevInfo
;
151 if (Length
< sizeof(FILE_FS_DEVICE_INFORMATION
)) {
152 Status
= STATUS_BUFFER_OVERFLOW
;
156 FsDevInfo
= (PFILE_FS_DEVICE_INFORMATION
) Buffer
;
157 FsDevInfo
->DeviceType
=
158 Vcb
->TargetDeviceObject
->DeviceType
;
160 if (FsDevInfo
->DeviceType
!= FILE_DEVICE_DISK
) {
164 FsDevInfo
->Characteristics
=
165 Vcb
->TargetDeviceObject
->Characteristics
;
167 if (IsVcbReadOnly(Vcb
)) {
168 SetFlag( FsDevInfo
->Characteristics
,
169 FILE_READ_ONLY_DEVICE
);
172 Irp
->IoStatus
.Information
= sizeof(FILE_FS_DEVICE_INFORMATION
);
173 Status
= STATUS_SUCCESS
;
177 case FileFsAttributeInformation
:
179 PFILE_FS_ATTRIBUTE_INFORMATION FsAttrInfo
;
180 ULONG RequiredLength
;
182 if (Length
< sizeof(FILE_FS_ATTRIBUTE_INFORMATION
)) {
183 Status
= STATUS_BUFFER_OVERFLOW
;
188 (PFILE_FS_ATTRIBUTE_INFORMATION
) Buffer
;
189 FsAttrInfo
->FileSystemAttributes
= FILE_SUPPORTS_HARD_LINKS
|
190 FILE_CASE_SENSITIVE_SEARCH
| FILE_CASE_PRESERVED_NAMES
|
191 FILE_SUPPORTS_REPARSE_POINTS
| FILE_SUPPORTS_EXTENDED_ATTRIBUTES
;
192 if (IsVcbReadOnly(Vcb
)) {
193 FsAttrInfo
->FileSystemAttributes
|= FILE_READ_ONLY_VOLUME
;
195 FsAttrInfo
->MaximumComponentNameLength
= EXT2_NAME_LEN
;
196 FsAttrInfo
->FileSystemNameLength
= 8;
198 RequiredLength
= sizeof(FILE_FS_ATTRIBUTE_INFORMATION
) +
201 if (Length
< RequiredLength
) {
202 Irp
->IoStatus
.Information
=
203 sizeof(FILE_FS_ATTRIBUTE_INFORMATION
);
204 Status
= STATUS_BUFFER_OVERFLOW
;
208 if (IsFlagOn(SUPER_BLOCK
->s_feature_incompat
, EXT4_FEATURE_INCOMPAT_EXTENTS
)) {
209 RtlCopyMemory(FsAttrInfo
->FileSystemName
, L
"EXT4\0", 10);
210 } else if (Vcb
->IsExt3fs
) {
211 RtlCopyMemory(FsAttrInfo
->FileSystemName
, L
"EXT3\0", 10);
213 RtlCopyMemory(FsAttrInfo
->FileSystemName
, L
"EXT2\0", 10);
216 Irp
->IoStatus
.Information
= RequiredLength
;
217 Status
= STATUS_SUCCESS
;
221 #if (_WIN32_WINNT >= 0x0500)
223 case FileFsFullSizeInformation
:
225 PFILE_FS_FULL_SIZE_INFORMATION PFFFSI
;
227 if (Length
< sizeof(FILE_FS_FULL_SIZE_INFORMATION
)) {
228 Status
= STATUS_BUFFER_OVERFLOW
;
232 PFFFSI
= (PFILE_FS_FULL_SIZE_INFORMATION
) Buffer
;
235 typedef struct _FILE_FS_FULL_SIZE_INFORMATION {
236 LARGE_INTEGER TotalAllocationUnits;
237 LARGE_INTEGER CallerAvailableAllocationUnits;
238 LARGE_INTEGER ActualAvailableAllocationUnits;
239 ULONG SectorsPerAllocationUnit;
240 ULONG BytesPerSector;
241 } FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION;
245 PFFFSI
->TotalAllocationUnits
.QuadPart
=
246 ext3_blocks_count(SUPER_BLOCK
);
248 PFFFSI
->CallerAvailableAllocationUnits
.QuadPart
=
249 ext3_free_blocks_count(SUPER_BLOCK
);
251 /* - Vcb->SuperBlock->s_r_blocks_count; */
252 PFFFSI
->ActualAvailableAllocationUnits
.QuadPart
=
253 ext3_free_blocks_count(SUPER_BLOCK
);
256 PFFFSI
->SectorsPerAllocationUnit
=
257 Vcb
->BlockSize
/ Vcb
->DiskGeometry
.BytesPerSector
;
259 PFFFSI
->BytesPerSector
= Vcb
->DiskGeometry
.BytesPerSector
;
261 Irp
->IoStatus
.Information
= sizeof(FILE_FS_FULL_SIZE_INFORMATION
);
262 Status
= STATUS_SUCCESS
;
266 #endif // (_WIN32_WINNT >= 0x0500)
269 Status
= STATUS_INVALID_INFO_CLASS
;
275 if (VcbResourceAcquired
) {
276 ExReleaseResourceLite(&Vcb
->MainResource
);
279 if (!IrpContext
->ExceptionInProgress
) {
280 if (Status
== STATUS_PENDING
) {
281 Ext2QueueRequest(IrpContext
);
283 Ext2CompleteIrpContext(IrpContext
, Status
);
292 Ext2SetVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext
)
294 PDEVICE_OBJECT DeviceObject
;
295 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
296 PEXT2_VCB Vcb
= NULL
;
298 PIO_STACK_LOCATION IoStackLocation
;
299 FS_INFORMATION_CLASS FsInformationClass
;
300 BOOLEAN VcbResourceAcquired
= FALSE
;
304 ASSERT(IrpContext
!= NULL
);
306 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
307 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
309 DeviceObject
= IrpContext
->DeviceObject
;
312 // This request is not allowed on the main device object
314 if (IsExt2FsDevice(DeviceObject
)) {
315 Status
= STATUS_INVALID_DEVICE_REQUEST
;
319 Vcb
= (PEXT2_VCB
) DeviceObject
->DeviceExtension
;
321 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
322 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
323 ASSERT(IsMounted(Vcb
));
325 if (IsVcbReadOnly(Vcb
)) {
326 Status
= STATUS_MEDIA_WRITE_PROTECTED
;
330 if (!ExAcquireResourceExclusiveLite(
331 &Vcb
->MainResource
, TRUE
)) {
332 Status
= STATUS_PENDING
;
335 VcbResourceAcquired
= TRUE
;
337 Ext2VerifyVcb(IrpContext
, Vcb
);
339 Irp
= IrpContext
->Irp
;
340 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
342 //Notes: SetVolume is not defined in ntddk.h of win2k ddk,
343 // But it's same to QueryVolume ....
345 IoStackLocation
->Parameters
./*SetVolume*/QueryVolume
.FsInformationClass
;
347 switch (FsInformationClass
) {
349 case FileFsLabelInformation
:
351 PFILE_FS_LABEL_INFORMATION VolLabelInfo
= NULL
;
353 UNICODE_STRING LabelName
;
357 VolLabelInfo
= (PFILE_FS_LABEL_INFORMATION
) Irp
->AssociatedIrp
.SystemBuffer
;
358 VolLabelLen
= VolLabelInfo
->VolumeLabelLength
;
360 if (VolLabelLen
> (16 * sizeof(WCHAR
))) {
361 Status
= STATUS_INVALID_VOLUME_LABEL
;
365 RtlCopyMemory( Vcb
->Vpb
->VolumeLabel
,
366 VolLabelInfo
->VolumeLabel
,
369 RtlZeroMemory(Vcb
->SuperBlock
->s_volume_name
, 16);
370 LabelName
.Buffer
= VolLabelInfo
->VolumeLabel
;
371 LabelName
.MaximumLength
= (USHORT
)16 * sizeof(WCHAR
);
372 LabelName
.Length
= (USHORT
)VolLabelLen
;
374 OemName
.Buffer
= SUPER_BLOCK
->s_volume_name
;
376 OemName
.MaximumLength
= 16;
378 Ext2UnicodeToOEM(Vcb
, &OemName
, &LabelName
);
379 Vcb
->Vpb
->VolumeLabelLength
= (USHORT
) VolLabelLen
;
381 if (Ext2SaveSuper(IrpContext
, Vcb
)) {
382 Status
= STATUS_SUCCESS
;
385 Irp
->IoStatus
.Information
= 0;
390 Status
= STATUS_INVALID_INFO_CLASS
;
395 if (VcbResourceAcquired
) {
396 ExReleaseResourceLite(&Vcb
->MainResource
);
399 if (!IrpContext
->ExceptionInProgress
) {
400 if (Status
== STATUS_PENDING
) {
401 Ext2QueueRequest(IrpContext
);
403 Ext2CompleteIrpContext(IrpContext
, Status
);