1 /* 2 * COPYRIGHT: See COPYRIGHT.TXT 3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP 4 * FILE: volinfo.c 5 * PROGRAMMER: Matt Wu <mattwu@163.com> 6 * HOMEPAGE: http://www.ext2fsd.com 7 * UPDATE HISTORY: 8 */ 9 10 /* INCLUDES *****************************************************************/ 11 12 #include "ext2fs.h" 13 14 /* GLOBALS ***************************************************************/ 15 16 extern PEXT2_GLOBAL Ext2Global; 17 18 /* DEFINITIONS *************************************************************/ 19 20 #ifdef ALLOC_PRAGMA 21 #pragma alloc_text(PAGE, Ext2QueryVolumeInformation) 22 #pragma alloc_text(PAGE, Ext2SetVolumeInformation) 23 #endif 24 25 26 NTSTATUS 27 Ext2QueryVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext) 28 { 29 PDEVICE_OBJECT DeviceObject; 30 PEXT2_VCB Vcb = NULL; 31 PIRP Irp = NULL; 32 PIO_STACK_LOCATION IoStackLocation = NULL; 33 PVOID Buffer; 34 ULONG Length; 35 NTSTATUS Status = STATUS_UNSUCCESSFUL; 36 FS_INFORMATION_CLASS FsInformationClass; 37 BOOLEAN VcbResourceAcquired = FALSE; 38 39 _SEH2_TRY { 40 41 ASSERT(IrpContext != NULL); 42 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 43 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 44 45 DeviceObject = IrpContext->DeviceObject; 46 47 // 48 // This request is not allowed on the main device object 49 // 50 if (IsExt2FsDevice(DeviceObject)) { 51 Status = STATUS_INVALID_DEVICE_REQUEST; 52 _SEH2_LEAVE; 53 } 54 55 Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; 56 ASSERT(Vcb != NULL); 57 ASSERT((Vcb->Identifier.Type == EXT2VCB) && 58 (Vcb->Identifier.Size == sizeof(EXT2_VCB))); 59 60 if (!IsMounted(Vcb)) { 61 Status = STATUS_VOLUME_DISMOUNTED; 62 _SEH2_LEAVE; 63 } 64 65 if (!ExAcquireResourceSharedLite( 66 &Vcb->MainResource, 67 IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) 68 )) { 69 70 Status = STATUS_PENDING; 71 _SEH2_LEAVE; 72 } 73 VcbResourceAcquired = TRUE; 74 75 Irp = IrpContext->Irp; 76 IoStackLocation = IoGetCurrentIrpStackLocation(Irp); 77 FsInformationClass = 78 IoStackLocation->Parameters.QueryVolume.FsInformationClass; 79 80 Length = IoStackLocation->Parameters.QueryVolume.Length; 81 Buffer = Irp->AssociatedIrp.SystemBuffer; 82 83 RtlZeroMemory(Buffer, Length); 84 85 switch (FsInformationClass) { 86 87 case FileFsVolumeInformation: 88 { 89 PFILE_FS_VOLUME_INFORMATION FsVolInfo; 90 ULONG VolumeLabelLength; 91 ULONG RequiredLength; 92 93 if (Length < sizeof(FILE_FS_VOLUME_INFORMATION)) { 94 Status = STATUS_BUFFER_OVERFLOW; 95 _SEH2_LEAVE; 96 } 97 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; 105 106 RequiredLength = sizeof(FILE_FS_VOLUME_INFORMATION) 107 + VolumeLabelLength - sizeof(WCHAR); 108 109 if (Length < RequiredLength) { 110 Irp->IoStatus.Information = 111 sizeof(FILE_FS_VOLUME_INFORMATION); 112 Status = STATUS_BUFFER_OVERFLOW; 113 _SEH2_LEAVE; 114 } 115 116 RtlCopyMemory(FsVolInfo->VolumeLabel, Vcb->Vpb->VolumeLabel, Vcb->Vpb->VolumeLabelLength); 117 118 Irp->IoStatus.Information = RequiredLength; 119 Status = STATUS_SUCCESS; 120 } 121 break; 122 123 case FileFsSizeInformation: 124 { 125 PFILE_FS_SIZE_INFORMATION FsSizeInfo; 126 127 if (Length < sizeof(FILE_FS_SIZE_INFORMATION)) { 128 Status = STATUS_BUFFER_OVERFLOW; 129 _SEH2_LEAVE; 130 } 131 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; 141 142 Irp->IoStatus.Information = sizeof(FILE_FS_SIZE_INFORMATION); 143 Status = STATUS_SUCCESS; 144 } 145 break; 146 147 case FileFsDeviceInformation: 148 { 149 PFILE_FS_DEVICE_INFORMATION FsDevInfo; 150 151 if (Length < sizeof(FILE_FS_DEVICE_INFORMATION)) { 152 Status = STATUS_BUFFER_OVERFLOW; 153 _SEH2_LEAVE; 154 } 155 156 FsDevInfo = (PFILE_FS_DEVICE_INFORMATION) Buffer; 157 FsDevInfo->DeviceType = 158 Vcb->TargetDeviceObject->DeviceType; 159 160 if (FsDevInfo->DeviceType != FILE_DEVICE_DISK) { 161 DbgBreak(); 162 } 163 164 FsDevInfo->Characteristics = 165 Vcb->TargetDeviceObject->Characteristics; 166 167 if (IsVcbReadOnly(Vcb)) { 168 SetFlag( FsDevInfo->Characteristics, 169 FILE_READ_ONLY_DEVICE ); 170 } 171 172 Irp->IoStatus.Information = sizeof(FILE_FS_DEVICE_INFORMATION); 173 Status = STATUS_SUCCESS; 174 } 175 break; 176 177 case FileFsAttributeInformation: 178 { 179 PFILE_FS_ATTRIBUTE_INFORMATION FsAttrInfo; 180 ULONG RequiredLength; 181 182 if (Length < sizeof(FILE_FS_ATTRIBUTE_INFORMATION)) { 183 Status = STATUS_BUFFER_OVERFLOW; 184 _SEH2_LEAVE; 185 } 186 187 FsAttrInfo = 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; 192 if (IsVcbReadOnly(Vcb)) { 193 FsAttrInfo->FileSystemAttributes |= FILE_READ_ONLY_VOLUME; 194 } 195 FsAttrInfo->MaximumComponentNameLength = EXT2_NAME_LEN; 196 FsAttrInfo->FileSystemNameLength = 8; 197 198 RequiredLength = sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 199 8 - sizeof(WCHAR); 200 201 if (Length < RequiredLength) { 202 Irp->IoStatus.Information = 203 sizeof(FILE_FS_ATTRIBUTE_INFORMATION); 204 Status = STATUS_BUFFER_OVERFLOW; 205 _SEH2_LEAVE; 206 } 207 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); 212 } else { 213 RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT2\0", 10); 214 } 215 216 Irp->IoStatus.Information = RequiredLength; 217 Status = STATUS_SUCCESS; 218 } 219 break; 220 221 #if (_WIN32_WINNT >= 0x0500) 222 223 case FileFsFullSizeInformation: 224 { 225 PFILE_FS_FULL_SIZE_INFORMATION PFFFSI; 226 227 if (Length < sizeof(FILE_FS_FULL_SIZE_INFORMATION)) { 228 Status = STATUS_BUFFER_OVERFLOW; 229 _SEH2_LEAVE; 230 } 231 232 PFFFSI = (PFILE_FS_FULL_SIZE_INFORMATION) Buffer; 233 234 /* 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; 242 */ 243 244 { 245 PFFFSI->TotalAllocationUnits.QuadPart = 246 ext3_blocks_count(SUPER_BLOCK); 247 248 PFFFSI->CallerAvailableAllocationUnits.QuadPart = 249 ext3_free_blocks_count(SUPER_BLOCK); 250 251 /* - Vcb->SuperBlock->s_r_blocks_count; */ 252 PFFFSI->ActualAvailableAllocationUnits.QuadPart = 253 ext3_free_blocks_count(SUPER_BLOCK); 254 } 255 256 PFFFSI->SectorsPerAllocationUnit = 257 Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector; 258 259 PFFFSI->BytesPerSector = Vcb->DiskGeometry.BytesPerSector; 260 261 Irp->IoStatus.Information = sizeof(FILE_FS_FULL_SIZE_INFORMATION); 262 Status = STATUS_SUCCESS; 263 } 264 break; 265 266 #endif // (_WIN32_WINNT >= 0x0500) 267 268 default: 269 Status = STATUS_INVALID_INFO_CLASS; 270 break; 271 } 272 273 } _SEH2_FINALLY { 274 275 if (VcbResourceAcquired) { 276 ExReleaseResourceLite(&Vcb->MainResource); 277 } 278 279 if (!IrpContext->ExceptionInProgress) { 280 if (Status == STATUS_PENDING) { 281 Ext2QueueRequest(IrpContext); 282 } else { 283 Ext2CompleteIrpContext(IrpContext, Status); 284 } 285 } 286 } _SEH2_END; 287 288 return Status; 289 } 290 291 NTSTATUS 292 Ext2SetVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext) 293 { 294 PDEVICE_OBJECT DeviceObject; 295 NTSTATUS Status = STATUS_UNSUCCESSFUL; 296 PEXT2_VCB Vcb = NULL; 297 PIRP Irp; 298 PIO_STACK_LOCATION IoStackLocation; 299 FS_INFORMATION_CLASS FsInformationClass; 300 BOOLEAN VcbResourceAcquired = FALSE; 301 302 _SEH2_TRY { 303 304 ASSERT(IrpContext != NULL); 305 306 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 307 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 308 309 DeviceObject = IrpContext->DeviceObject; 310 311 // 312 // This request is not allowed on the main device object 313 // 314 if (IsExt2FsDevice(DeviceObject)) { 315 Status = STATUS_INVALID_DEVICE_REQUEST; 316 _SEH2_LEAVE; 317 } 318 319 Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; 320 ASSERT(Vcb != NULL); 321 ASSERT((Vcb->Identifier.Type == EXT2VCB) && 322 (Vcb->Identifier.Size == sizeof(EXT2_VCB))); 323 ASSERT(IsMounted(Vcb)); 324 325 if (IsVcbReadOnly(Vcb)) { 326 Status = STATUS_MEDIA_WRITE_PROTECTED; 327 _SEH2_LEAVE; 328 } 329 330 if (!ExAcquireResourceExclusiveLite( 331 &Vcb->MainResource, TRUE)) { 332 Status = STATUS_PENDING; 333 _SEH2_LEAVE; 334 } 335 VcbResourceAcquired = TRUE; 336 337 Ext2VerifyVcb(IrpContext, Vcb); 338 339 Irp = IrpContext->Irp; 340 IoStackLocation = IoGetCurrentIrpStackLocation(Irp); 341 342 //Notes: SetVolume is not defined in ntddk.h of win2k ddk, 343 // But it's same to QueryVolume .... 344 FsInformationClass = 345 IoStackLocation->Parameters./*SetVolume*/QueryVolume.FsInformationClass; 346 347 switch (FsInformationClass) { 348 349 case FileFsLabelInformation: 350 { 351 PFILE_FS_LABEL_INFORMATION VolLabelInfo = NULL; 352 ULONG VolLabelLen; 353 UNICODE_STRING LabelName ; 354 355 OEM_STRING OemName; 356 357 VolLabelInfo = (PFILE_FS_LABEL_INFORMATION) Irp->AssociatedIrp.SystemBuffer; 358 VolLabelLen = VolLabelInfo->VolumeLabelLength; 359 360 if (VolLabelLen > (16 * sizeof(WCHAR))) { 361 Status = STATUS_INVALID_VOLUME_LABEL; 362 _SEH2_LEAVE; 363 } 364 365 RtlCopyMemory( Vcb->Vpb->VolumeLabel, 366 VolLabelInfo->VolumeLabel, 367 VolLabelLen ); 368 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; 373 374 OemName.Buffer = SUPER_BLOCK->s_volume_name; 375 OemName.Length = 0; 376 OemName.MaximumLength = 16; 377 378 Ext2UnicodeToOEM(Vcb, &OemName, &LabelName); 379 Vcb->Vpb->VolumeLabelLength = (USHORT) VolLabelLen; 380 381 if (Ext2SaveSuper(IrpContext, Vcb)) { 382 Status = STATUS_SUCCESS; 383 } 384 385 Irp->IoStatus.Information = 0; 386 } 387 break; 388 389 default: 390 Status = STATUS_INVALID_INFO_CLASS; 391 } 392 393 } _SEH2_FINALLY { 394 395 if (VcbResourceAcquired) { 396 ExReleaseResourceLite(&Vcb->MainResource); 397 } 398 399 if (!IrpContext->ExceptionInProgress) { 400 if (Status == STATUS_PENDING) { 401 Ext2QueueRequest(IrpContext); 402 } else { 403 Ext2CompleteIrpContext(IrpContext, Status); 404 } 405 } 406 } _SEH2_END; 407 408 return Status; 409 } 410