3 * Copyright (C) 2002 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19 * COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS kernel
21 * FILE: drivers/filesystem/ntfs/volume.c
22 * PURPOSE: NTFS filesystem driver
23 * PROGRAMMER: Eric Kohl
26 /* INCLUDES *****************************************************************/
33 /* FUNCTIONS ****************************************************************/
36 NtfsGetFreeClusters(PDEVICE_EXTENSION DeviceExt
)
39 PFILE_RECORD_HEADER BitmapRecord
;
40 PNTFS_ATTR_CONTEXT DataContext
;
41 ULONGLONG BitmapDataSize
;
43 ULONGLONG FreeClusters
= 0;
47 DPRINT1("NtfsGetFreeClusters(%p)\n", DeviceExt
);
49 BitmapRecord
= ExAllocatePoolWithTag(NonPagedPool
,
50 DeviceExt
->NtfsInfo
.BytesPerFileRecord
,
52 if (BitmapRecord
== NULL
)
57 Status
= ReadFileRecord(DeviceExt
, NTFS_FILE_BITMAP
, BitmapRecord
);
58 if (!NT_SUCCESS(Status
))
60 ExFreePoolWithTag(BitmapRecord
, TAG_NTFS
);
64 Status
= FindAttribute(DeviceExt
, BitmapRecord
, AttributeData
, L
"", 0, &DataContext
);
65 if (!NT_SUCCESS(Status
))
67 ExFreePoolWithTag(BitmapRecord
, TAG_NTFS
);
71 BitmapDataSize
= AttributeDataLength(&DataContext
->Record
);
72 ASSERT((BitmapDataSize
* 8) >= (DeviceExt
->NtfsInfo
.SectorCount
/ DeviceExt
->NtfsInfo
.SectorsPerCluster
));
73 BitmapData
= ExAllocatePoolWithTag(NonPagedPool
, ROUND_UP(BitmapDataSize
, DeviceExt
->NtfsInfo
.BytesPerSector
), TAG_NTFS
);
74 if (BitmapData
== NULL
)
76 ReleaseAttributeContext(DataContext
);
77 ExFreePoolWithTag(BitmapRecord
, TAG_NTFS
);
81 /* FIXME: Totally underoptimized! */
82 for (; Read
< BitmapDataSize
; Read
+= DeviceExt
->NtfsInfo
.BytesPerSector
)
84 ReadAttribute(DeviceExt
, DataContext
, Read
, (PCHAR
)((ULONG_PTR
)BitmapData
+ Read
), DeviceExt
->NtfsInfo
.BytesPerSector
);
86 ReleaseAttributeContext(DataContext
);
88 DPRINT1("Total clusters: %I64x\n", DeviceExt
->NtfsInfo
.SectorCount
/ DeviceExt
->NtfsInfo
.SectorsPerCluster
);
89 DPRINT1("Total clusters in bitmap: %I64x\n", BitmapDataSize
* 8);
90 DPRINT1("Diff in size: %I64d B\n", ((BitmapDataSize
* 8) - (DeviceExt
->NtfsInfo
.SectorCount
/ DeviceExt
->NtfsInfo
.SectorsPerCluster
)) * DeviceExt
->NtfsInfo
.SectorsPerCluster
* DeviceExt
->NtfsInfo
.BytesPerSector
);
92 RtlInitializeBitMap(&Bitmap
, (PULONG
)BitmapData
, DeviceExt
->NtfsInfo
.SectorCount
/ DeviceExt
->NtfsInfo
.SectorsPerCluster
);
93 FreeClusters
= RtlNumberOfClearBits(&Bitmap
);
95 ExFreePoolWithTag(BitmapData
, TAG_NTFS
);
96 ExFreePoolWithTag(BitmapRecord
, TAG_NTFS
);
103 NtfsGetFsVolumeInformation(PDEVICE_OBJECT DeviceObject
,
104 PFILE_FS_VOLUME_INFORMATION FsVolumeInfo
,
107 DPRINT("NtfsGetFsVolumeInformation() called\n");
108 DPRINT("FsVolumeInfo = %p\n", FsVolumeInfo
);
109 DPRINT("BufferLength %lu\n", *BufferLength
);
111 DPRINT("Vpb %p\n", DeviceObject
->Vpb
);
113 DPRINT("Required length %lu\n",
114 sizeof(FILE_FS_VOLUME_INFORMATION
) + DeviceObject
->Vpb
->VolumeLabelLength
);
115 DPRINT("LabelLength %hu\n",
116 DeviceObject
->Vpb
->VolumeLabelLength
);
117 DPRINT("Label %*.S\n",
118 DeviceObject
->Vpb
->VolumeLabelLength
/ sizeof(WCHAR
),
119 DeviceObject
->Vpb
->VolumeLabel
);
121 if (*BufferLength
< sizeof(FILE_FS_VOLUME_INFORMATION
))
122 return STATUS_INFO_LENGTH_MISMATCH
;
124 if (*BufferLength
< (sizeof(FILE_FS_VOLUME_INFORMATION
) + DeviceObject
->Vpb
->VolumeLabelLength
))
125 return STATUS_BUFFER_OVERFLOW
;
128 FsVolumeInfo
->VolumeSerialNumber
= DeviceObject
->Vpb
->SerialNumber
;
129 FsVolumeInfo
->VolumeLabelLength
= DeviceObject
->Vpb
->VolumeLabelLength
;
130 memcpy(FsVolumeInfo
->VolumeLabel
,
131 DeviceObject
->Vpb
->VolumeLabel
,
132 DeviceObject
->Vpb
->VolumeLabelLength
);
135 FsVolumeInfo
->VolumeCreationTime
.QuadPart
= 0;
136 FsVolumeInfo
->SupportsObjects
= FALSE
;
138 *BufferLength
-= (sizeof(FILE_FS_VOLUME_INFORMATION
) + DeviceObject
->Vpb
->VolumeLabelLength
);
140 DPRINT("BufferLength %lu\n", *BufferLength
);
141 DPRINT("NtfsGetFsVolumeInformation() done\n");
143 return STATUS_SUCCESS
;
149 NtfsGetFsAttributeInformation(PDEVICE_EXTENSION DeviceExt
,
150 PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo
,
153 UNREFERENCED_PARAMETER(DeviceExt
);
155 DPRINT("NtfsGetFsAttributeInformation()\n");
156 DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo
);
157 DPRINT("BufferLength %lu\n", *BufferLength
);
158 DPRINT("Required length %lu\n", (sizeof(FILE_FS_ATTRIBUTE_INFORMATION
) + 8));
160 if (*BufferLength
< sizeof (FILE_FS_ATTRIBUTE_INFORMATION
))
161 return STATUS_INFO_LENGTH_MISMATCH
;
163 if (*BufferLength
< (sizeof(FILE_FS_ATTRIBUTE_INFORMATION
) + 8))
164 return STATUS_BUFFER_OVERFLOW
;
166 FsAttributeInfo
->FileSystemAttributes
=
167 FILE_CASE_PRESERVED_NAMES
| FILE_UNICODE_ON_DISK
;
168 FsAttributeInfo
->MaximumComponentNameLength
= 255;
169 FsAttributeInfo
->FileSystemNameLength
= 8;
171 memcpy(FsAttributeInfo
->FileSystemName
, L
"NTFS", 8);
173 DPRINT("Finished NtfsGetFsAttributeInformation()\n");
175 *BufferLength
-= (sizeof(FILE_FS_ATTRIBUTE_INFORMATION
) + 8);
176 DPRINT("BufferLength %lu\n", *BufferLength
);
178 return STATUS_SUCCESS
;
184 NtfsGetFsSizeInformation(PDEVICE_OBJECT DeviceObject
,
185 PFILE_FS_SIZE_INFORMATION FsSizeInfo
,
188 PDEVICE_EXTENSION DeviceExt
;
189 NTSTATUS Status
= STATUS_SUCCESS
;
191 DPRINT("NtfsGetFsSizeInformation()\n");
192 DPRINT("FsSizeInfo = %p\n", FsSizeInfo
);
194 if (*BufferLength
< sizeof(FILE_FS_SIZE_INFORMATION
))
195 return STATUS_BUFFER_OVERFLOW
;
197 DeviceExt
= DeviceObject
->DeviceExtension
;
199 FsSizeInfo
->AvailableAllocationUnits
.QuadPart
= NtfsGetFreeClusters(DeviceExt
);
200 FsSizeInfo
->TotalAllocationUnits
.QuadPart
= DeviceExt
->NtfsInfo
.SectorCount
/ DeviceExt
->NtfsInfo
.SectorsPerCluster
;
201 FsSizeInfo
->SectorsPerAllocationUnit
= DeviceExt
->NtfsInfo
.SectorsPerCluster
;
202 FsSizeInfo
->BytesPerSector
= DeviceExt
->NtfsInfo
.BytesPerSector
;
204 DPRINT("Finished NtfsGetFsSizeInformation()\n");
205 if (NT_SUCCESS(Status
))
206 *BufferLength
-= sizeof(FILE_FS_SIZE_INFORMATION
);
214 NtfsGetFsDeviceInformation(PDEVICE_OBJECT DeviceObject
,
215 PFILE_FS_DEVICE_INFORMATION FsDeviceInfo
,
218 DPRINT("NtfsGetFsDeviceInformation()\n");
219 DPRINT("FsDeviceInfo = %p\n", FsDeviceInfo
);
220 DPRINT("BufferLength %lu\n", *BufferLength
);
221 DPRINT("Required length %lu\n", sizeof(FILE_FS_DEVICE_INFORMATION
));
223 if (*BufferLength
< sizeof(FILE_FS_DEVICE_INFORMATION
))
224 return STATUS_BUFFER_OVERFLOW
;
226 FsDeviceInfo
->DeviceType
= FILE_DEVICE_DISK
;
227 FsDeviceInfo
->Characteristics
= DeviceObject
->Characteristics
;
229 DPRINT("NtfsGetFsDeviceInformation() finished.\n");
231 *BufferLength
-= sizeof(FILE_FS_DEVICE_INFORMATION
);
232 DPRINT("BufferLength %lu\n", *BufferLength
);
234 return STATUS_SUCCESS
;
239 NtfsQueryVolumeInformation(PNTFS_IRP_CONTEXT IrpContext
)
242 PDEVICE_OBJECT DeviceObject
;
243 FS_INFORMATION_CLASS FsInformationClass
;
244 PIO_STACK_LOCATION Stack
;
245 NTSTATUS Status
= STATUS_SUCCESS
;
249 DPRINT("NtfsQueryVolumeInformation() called\n");
253 Irp
= IrpContext
->Irp
;
254 DeviceObject
= IrpContext
->DeviceObject
;
255 Stack
= IoGetCurrentIrpStackLocation(Irp
);
256 FsInformationClass
= Stack
->Parameters
.QueryVolume
.FsInformationClass
;
257 BufferLength
= Stack
->Parameters
.QueryVolume
.Length
;
258 SystemBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
259 RtlZeroMemory(SystemBuffer
, BufferLength
);
261 DPRINT("FsInformationClass %d\n", FsInformationClass
);
262 DPRINT("SystemBuffer %p\n", SystemBuffer
);
264 switch (FsInformationClass
)
266 case FileFsVolumeInformation
:
267 Status
= NtfsGetFsVolumeInformation(DeviceObject
,
272 case FileFsAttributeInformation
:
273 Status
= NtfsGetFsAttributeInformation(DeviceObject
->DeviceExtension
,
278 case FileFsSizeInformation
:
279 Status
= NtfsGetFsSizeInformation(DeviceObject
,
284 case FileFsDeviceInformation
:
285 Status
= NtfsGetFsDeviceInformation(DeviceObject
,
291 Status
= STATUS_NOT_SUPPORTED
;
294 if (NT_SUCCESS(Status
))
295 Irp
->IoStatus
.Information
=
296 Stack
->Parameters
.QueryVolume
.Length
- BufferLength
;
298 Irp
->IoStatus
.Information
= 0;
305 NtfsSetVolumeInformation(PNTFS_IRP_CONTEXT IrpContext
)
309 DPRINT("NtfsSetVolumeInformation() called\n");
313 Irp
= IrpContext
->Irp
;
314 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
315 Irp
->IoStatus
.Information
= 0;
317 return STATUS_NOT_SUPPORTED
;