Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfsctl.c
Go to the documentation of this file.
00001 /* 00002 * ReactOS kernel 00003 * Copyright (C) 2002 ReactOS Team 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. 00018 * 00019 * COPYRIGHT: See COPYING in the top level directory 00020 * PROJECT: ReactOS kernel 00021 * FILE: drivers/filesystems/ntfs/fsctl.c 00022 * PURPOSE: NTFS filesystem driver 00023 * PROGRAMMER: Eric Kohl 00024 * Valentin Verkhovsky 00025 * Pierre Schweitzer 00026 */ 00027 00028 /* INCLUDES *****************************************************************/ 00029 00030 #include "ntfs.h" 00031 00032 #define NDEBUG 00033 #include <debug.h> 00034 00035 /* GLOBALS *****************************************************************/ 00036 00037 /* FUNCTIONS ****************************************************************/ 00038 00039 static NTSTATUS 00040 NtfsHasFileSystem(PDEVICE_OBJECT DeviceToMount) 00041 /* 00042 * FUNCTION: Tests if the device contains a filesystem that can be mounted 00043 * by this fsd 00044 */ 00045 { 00046 PARTITION_INFORMATION PartitionInfo; 00047 DISK_GEOMETRY DiskGeometry; 00048 ULONG ClusterSize, Size, k; 00049 PBOOT_SECTOR BootSector; 00050 NTSTATUS Status; 00051 00052 DPRINT1("NtfsHasFileSystem() called\n"); 00053 00054 Size = sizeof(DISK_GEOMETRY); 00055 Status = NtfsDeviceIoControl(DeviceToMount, 00056 IOCTL_DISK_GET_DRIVE_GEOMETRY, 00057 NULL, 00058 0, 00059 &DiskGeometry, 00060 &Size, 00061 TRUE); 00062 if (!NT_SUCCESS(Status)) 00063 { 00064 DPRINT1("NtfsDeviceIoControl() failed (Status %lx)\n", Status); 00065 return(Status); 00066 } 00067 00068 if (DiskGeometry.MediaType == FixedMedia) 00069 { 00070 /* We have found a hard disk */ 00071 Size = sizeof(PARTITION_INFORMATION); 00072 Status = NtfsDeviceIoControl(DeviceToMount, 00073 IOCTL_DISK_GET_PARTITION_INFO, 00074 NULL, 00075 0, 00076 &PartitionInfo, 00077 &Size, 00078 TRUE); 00079 if (!NT_SUCCESS(Status)) 00080 { 00081 DPRINT1("NtfsDeviceIoControl() failed (Status %lx)\n", Status); 00082 return(Status); 00083 } 00084 00085 if (PartitionInfo.PartitionType != PARTITION_IFS) 00086 { 00087 DPRINT1("Invalid partition type\n"); 00088 return(STATUS_UNRECOGNIZED_VOLUME); 00089 } 00090 } 00091 00092 DPRINT1("BytesPerSector: %lu\n", DiskGeometry.BytesPerSector); 00093 BootSector = ExAllocatePoolWithTag(NonPagedPool, 00094 DiskGeometry.BytesPerSector, TAG_NTFS); 00095 if (BootSector == NULL) 00096 { 00097 return(STATUS_INSUFFICIENT_RESOURCES); 00098 } 00099 00100 Status = NtfsReadSectors (DeviceToMount, 00101 0, 00102 1, 00103 DiskGeometry.BytesPerSector, 00104 (PVOID)BootSector, 00105 TRUE); 00106 if (!NT_SUCCESS(Status)) 00107 { 00108 goto ByeBye; 00109 } 00110 00111 /* Check values of different fields. If those fields have not expected 00112 * values, we fail, to avoid mounting partitions that Windows won't mount. 00113 */ 00114 /* OEMID: this field must be NTFS */ 00115 if (RtlCompareMemory(BootSector->OEMID, "NTFS ", 8) != 8) 00116 { 00117 DPRINT1("Failed with NTFS-identifier: [%.8s]\n", BootSector->OEMID); 00118 Status = STATUS_UNRECOGNIZED_VOLUME; 00119 goto ByeBye; 00120 } 00121 /* Unused0: this field must be COMPLETELY null */ 00122 for (k=0; k<7; k++) 00123 { 00124 if (BootSector->BPB.Unused0[k] != 0) 00125 { 00126 DPRINT1("Failed in field Unused0: [%.7s]\n", BootSector->BPB.Unused0); 00127 Status = STATUS_UNRECOGNIZED_VOLUME; 00128 goto ByeBye; 00129 } 00130 } 00131 /* Unused3: this field must be COMPLETELY null */ 00132 for (k=0; k<4; k++) 00133 { 00134 if (BootSector->BPB.Unused3[k] != 0) 00135 { 00136 DPRINT1("Failed in field Unused3: [%.4s]\n", BootSector->BPB.Unused3); 00137 Status = STATUS_UNRECOGNIZED_VOLUME; 00138 goto ByeBye; 00139 } 00140 } 00141 /* Check cluster size */ 00142 ClusterSize = BootSector->BPB.BytesPerSector * BootSector->BPB.SectorsPerCluster; 00143 if (ClusterSize != 512 && ClusterSize != 1024 && 00144 ClusterSize != 2048 && ClusterSize != 4096 && 00145 ClusterSize != 8192 && ClusterSize != 16384 && 00146 ClusterSize != 32768 && ClusterSize != 65536) 00147 { 00148 DPRINT1("Cluster size failed: %hu, %hu, %hu\n", BootSector->BPB.BytesPerSector, 00149 BootSector->BPB.SectorsPerCluster, 00150 ClusterSize); 00151 Status = STATUS_UNRECOGNIZED_VOLUME; 00152 goto ByeBye; 00153 } 00154 00155 ByeBye: 00156 ExFreePool(BootSector); 00157 return Status; 00158 } 00159 00160 00161 static NTSTATUS 00162 NtfsGetVolumeData(PDEVICE_OBJECT DeviceObject, 00163 PDEVICE_EXTENSION DeviceExt) 00164 { 00165 DISK_GEOMETRY DiskGeometry; 00166 PFILE_RECORD_HEADER MftRecord; 00167 PFILE_RECORD_HEADER VolumeRecord; 00168 PVOLINFO_ATTRIBUTE VolumeInfo; 00169 PBOOT_SECTOR BootSector; 00170 PATTRIBUTE Attribute; 00171 ULONG Size; 00172 NTSTATUS Status; 00173 PNTFS_INFO NtfsInfo = &DeviceExt->NtfsInfo; 00174 00175 DPRINT("NtfsGetVolumeData() called\n"); 00176 00177 Size = sizeof(DISK_GEOMETRY); 00178 Status = NtfsDeviceIoControl(DeviceObject, 00179 IOCTL_DISK_GET_DRIVE_GEOMETRY, 00180 NULL, 00181 0, 00182 &DiskGeometry, 00183 &Size, 00184 TRUE); 00185 if (!NT_SUCCESS(Status)) 00186 { 00187 DPRINT("NtfsDeviceIoControl() failed (Status %lx)\n", Status); 00188 return(Status); 00189 } 00190 00191 DPRINT("BytesPerSector: %lu\n", DiskGeometry.BytesPerSector); 00192 BootSector = ExAllocatePoolWithTag(NonPagedPool, 00193 DiskGeometry.BytesPerSector, TAG_NTFS); 00194 if (BootSector == NULL) 00195 { 00196 return(STATUS_INSUFFICIENT_RESOURCES); 00197 } 00198 00199 Status = NtfsReadSectors(DeviceObject, 00200 0, /* Partition boot sector */ 00201 1, 00202 DiskGeometry.BytesPerSector, 00203 (PVOID)BootSector, 00204 TRUE); 00205 if (!NT_SUCCESS(Status)) 00206 { 00207 ExFreePool(BootSector); 00208 return Status; 00209 } 00210 00211 /* Read data from the bootsector */ 00212 NtfsInfo->BytesPerSector = BootSector->BPB.BytesPerSector; 00213 NtfsInfo->SectorsPerCluster = BootSector->BPB.SectorsPerCluster; 00214 NtfsInfo->BytesPerCluster = BootSector->BPB.BytesPerSector * BootSector->BPB.SectorsPerCluster; 00215 NtfsInfo->SectorCount = BootSector->EBPB.SectorCount; 00216 00217 NtfsInfo->MftStart.QuadPart = BootSector->EBPB.MftLocation; 00218 NtfsInfo->MftMirrStart.QuadPart = BootSector->EBPB.MftMirrLocation; 00219 NtfsInfo->SerialNumber = BootSector->EBPB.SerialNumber; 00220 if (BootSector->EBPB.ClustersPerMftRecord > 0) 00221 NtfsInfo->BytesPerFileRecord = BootSector->EBPB.ClustersPerMftRecord * NtfsInfo->BytesPerCluster; 00222 else 00223 NtfsInfo->BytesPerFileRecord = 1 << (-BootSector->EBPB.ClustersPerMftRecord); 00224 00225 DPRINT("Boot sector information:\n"); 00226 DPRINT(" BytesPerSector: %hu\n", BootSector->BPB.BytesPerSector); 00227 DPRINT(" SectorsPerCluster: %hu\n", BootSector->BPB.SectorsPerCluster); 00228 DPRINT(" SectorCount: %I64u\n", BootSector->EBPB.SectorCount); 00229 DPRINT(" MftStart: %I64u\n", BootSector->EBPB.MftLocation); 00230 DPRINT(" MftMirrStart: %I64u\n", BootSector->EBPB.MftMirrLocation); 00231 DPRINT(" ClustersPerMftRecord: %lx\n", BootSector->EBPB.ClustersPerMftRecord); 00232 DPRINT(" ClustersPerIndexRecord: %lx\n", BootSector->EBPB.ClustersPerIndexRecord); 00233 DPRINT(" SerialNumber: %I64x\n", BootSector->EBPB.SerialNumber); 00234 00235 ExFreePool(BootSector); 00236 00237 MftRecord = ExAllocatePoolWithTag(NonPagedPool, 00238 NtfsInfo->BytesPerFileRecord, TAG_NTFS); 00239 if (MftRecord == NULL) 00240 { 00241 return STATUS_INSUFFICIENT_RESOURCES; 00242 } 00243 00244 Status = NtfsReadSectors(DeviceObject, 00245 NtfsInfo->MftStart.u.LowPart * NtfsInfo->SectorsPerCluster, 00246 NtfsInfo->BytesPerFileRecord / NtfsInfo->BytesPerSector, 00247 NtfsInfo->BytesPerSector, 00248 (PVOID)MftRecord, 00249 TRUE); 00250 if (!NT_SUCCESS(Status)) 00251 { 00252 ExFreePool(MftRecord); 00253 return Status; 00254 } 00255 00256 VolumeRecord = ExAllocatePoolWithTag(NonPagedPool, NtfsInfo->BytesPerFileRecord, TAG_NTFS); 00257 if (VolumeRecord == NULL) 00258 { 00259 ExFreePool (MftRecord); 00260 return STATUS_INSUFFICIENT_RESOURCES; 00261 } 00262 00263 /* Read Volume File (MFT index 3) */ 00264 DeviceExt->StorageDevice = DeviceObject; 00265 Status = ReadFileRecord(DeviceExt, 3, VolumeRecord, MftRecord); 00266 if (!NT_SUCCESS(Status)) 00267 { 00268 ExFreePool(MftRecord); 00269 return Status; 00270 } 00271 00272 /* Enumerate attributes */ 00273 NtfsDumpFileAttributes (MftRecord); 00274 00275 /* Enumerate attributes */ 00276 NtfsDumpFileAttributes (VolumeRecord); 00277 00278 /* Get volume name */ 00279 Attribute = FindAttribute (VolumeRecord, AttributeVolumeName, NULL); 00280 DPRINT("Attribute %p\n", Attribute); 00281 00282 if (Attribute != NULL && ((PRESIDENT_ATTRIBUTE)Attribute)->ValueLength != 0) 00283 { 00284 DPRINT("Data length %lu\n", AttributeDataLength (Attribute)); 00285 NtfsInfo->VolumeLabelLength = 00286 min (((PRESIDENT_ATTRIBUTE)Attribute)->ValueLength, MAXIMUM_VOLUME_LABEL_LENGTH); 00287 RtlCopyMemory (NtfsInfo->VolumeLabel, 00288 (PVOID)((ULONG_PTR)Attribute + ((PRESIDENT_ATTRIBUTE)Attribute)->ValueOffset), 00289 NtfsInfo->VolumeLabelLength); 00290 } 00291 else 00292 { 00293 NtfsInfo->VolumeLabelLength = 0; 00294 } 00295 00296 /* Get volume information */ 00297 Attribute = FindAttribute (VolumeRecord, AttributeVolumeInformation, NULL); 00298 DPRINT("Attribute %p\n", Attribute); 00299 00300 if (Attribute != NULL && ((PRESIDENT_ATTRIBUTE)Attribute)->ValueLength != 0) 00301 { 00302 DPRINT("Data length %lu\n", AttributeDataLength (Attribute)); 00303 VolumeInfo = (PVOID)((ULONG_PTR)Attribute + ((PRESIDENT_ATTRIBUTE)Attribute)->ValueOffset); 00304 00305 NtfsInfo->MajorVersion = VolumeInfo->MajorVersion; 00306 NtfsInfo->MinorVersion = VolumeInfo->MinorVersion; 00307 NtfsInfo->Flags = VolumeInfo->Flags; 00308 } 00309 00310 ExFreePool(MftRecord); 00311 ExFreePool(VolumeRecord); 00312 00313 return Status; 00314 } 00315 00316 00317 static NTSTATUS 00318 NtfsMountVolume(PDEVICE_OBJECT DeviceObject, 00319 PIRP Irp) 00320 { 00321 PDEVICE_OBJECT NewDeviceObject = NULL; 00322 PDEVICE_OBJECT DeviceToMount; 00323 PIO_STACK_LOCATION Stack; 00324 PNTFS_FCB Fcb = NULL; 00325 PNTFS_CCB Ccb = NULL; 00326 PNTFS_VCB Vcb = NULL; 00327 NTSTATUS Status; 00328 00329 DPRINT1("NtfsMountVolume() called\n"); 00330 00331 if (DeviceObject != NtfsGlobalData->DeviceObject) 00332 { 00333 Status = STATUS_INVALID_DEVICE_REQUEST; 00334 goto ByeBye; 00335 } 00336 00337 Stack = IoGetCurrentIrpStackLocation(Irp); 00338 DeviceToMount = Stack->Parameters.MountVolume.DeviceObject; 00339 00340 Status = NtfsHasFileSystem(DeviceToMount); 00341 if (!NT_SUCCESS(Status)) 00342 { 00343 goto ByeBye; 00344 } 00345 00346 Status = IoCreateDevice(NtfsGlobalData->DriverObject, 00347 sizeof(DEVICE_EXTENSION), 00348 NULL, 00349 FILE_DEVICE_DISK_FILE_SYSTEM, 00350 0, 00351 FALSE, 00352 &NewDeviceObject); 00353 if (!NT_SUCCESS(Status)) 00354 goto ByeBye; 00355 00356 NewDeviceObject->Flags |= DO_DIRECT_IO; 00357 Vcb = (PVOID)NewDeviceObject->DeviceExtension; 00358 RtlZeroMemory(Vcb, sizeof(NTFS_VCB)); 00359 00360 Vcb->Identifier.Type = NTFS_TYPE_VCB; 00361 Vcb->Identifier.Size = sizeof(NTFS_TYPE_VCB); 00362 00363 Status = NtfsGetVolumeData(DeviceToMount, 00364 Vcb); 00365 if (!NT_SUCCESS(Status)) 00366 goto ByeBye; 00367 00368 NewDeviceObject->Vpb = DeviceToMount->Vpb; 00369 00370 Vcb->StorageDevice = DeviceToMount; 00371 Vcb->StorageDevice->Vpb->DeviceObject = NewDeviceObject; 00372 Vcb->StorageDevice->Vpb->RealDevice = Vcb->StorageDevice; 00373 Vcb->StorageDevice->Vpb->Flags |= VPB_MOUNTED; 00374 NewDeviceObject->StackSize = Vcb->StorageDevice->StackSize + 1; 00375 NewDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 00376 00377 Vcb->StreamFileObject = IoCreateStreamFileObject(NULL, 00378 Vcb->StorageDevice); 00379 00380 InitializeListHead(&Vcb->FcbListHead); 00381 00382 Fcb = NtfsCreateFCB(NULL, Vcb); 00383 if (Fcb == NULL) 00384 { 00385 Status = STATUS_INSUFFICIENT_RESOURCES; 00386 goto ByeBye; 00387 } 00388 00389 Ccb = ExAllocatePoolWithTag(NonPagedPool, 00390 sizeof(NTFS_CCB), 00391 TAG_CCB); 00392 if (Ccb == NULL) 00393 { 00394 Status = STATUS_INSUFFICIENT_RESOURCES; 00395 goto ByeBye; 00396 } 00397 RtlZeroMemory(Ccb, sizeof(NTFS_CCB)); 00398 00399 Ccb->Identifier.Type = NTFS_TYPE_CCB; 00400 Ccb->Identifier.Size = sizeof(NTFS_TYPE_CCB); 00401 00402 Vcb->StreamFileObject->FsContext = Fcb; 00403 Vcb->StreamFileObject->FsContext2 = Ccb; 00404 Vcb->StreamFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers; 00405 Vcb->StreamFileObject->PrivateCacheMap = NULL; 00406 Vcb->StreamFileObject->Vpb = Vcb->Vpb; 00407 Ccb->PtrFileObject = Vcb->StreamFileObject; 00408 Fcb->FileObject = Vcb->StreamFileObject; 00409 Fcb->Vcb = (PDEVICE_EXTENSION)Vcb->StorageDevice; 00410 00411 Fcb->Flags = FCB_IS_VOLUME_STREAM; 00412 00413 Fcb->RFCB.FileSize.QuadPart = Vcb->NtfsInfo.SectorCount * Vcb->NtfsInfo.BytesPerSector; 00414 Fcb->RFCB.ValidDataLength.QuadPart = Vcb->NtfsInfo.SectorCount * Vcb->NtfsInfo.BytesPerSector; 00415 Fcb->RFCB.AllocationSize.QuadPart = Vcb->NtfsInfo.SectorCount * Vcb->NtfsInfo.BytesPerSector; /* Correct? */ 00416 00417 // Fcb->Entry.ExtentLocationL = 0; 00418 // Fcb->Entry.DataLengthL = DeviceExt->CdInfo.VolumeSpaceSize * BLOCKSIZE; 00419 00420 CcInitializeCacheMap(Vcb->StreamFileObject, 00421 (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize), 00422 FALSE, 00423 &(NtfsGlobalData->CacheMgrCallbacks), 00424 Fcb); 00425 00426 ExInitializeResourceLite(&Vcb->DirResource); 00427 00428 KeInitializeSpinLock(&Vcb->FcbListLock); 00429 00430 /* Get serial number */ 00431 NewDeviceObject->Vpb->SerialNumber = Vcb->NtfsInfo.SerialNumber; 00432 00433 /* Get volume label */ 00434 NewDeviceObject->Vpb->VolumeLabelLength = Vcb->NtfsInfo.VolumeLabelLength; 00435 RtlCopyMemory(NewDeviceObject->Vpb->VolumeLabel, 00436 Vcb->NtfsInfo.VolumeLabel, 00437 Vcb->NtfsInfo.VolumeLabelLength); 00438 00439 Status = STATUS_SUCCESS; 00440 00441 ByeBye: 00442 if (!NT_SUCCESS(Status)) 00443 { 00444 /* Cleanup */ 00445 if (Vcb && Vcb->StreamFileObject) 00446 ObDereferenceObject(Vcb->StreamFileObject); 00447 if (Fcb) 00448 ExFreePool(Fcb); 00449 if (Ccb) 00450 ExFreePool(Ccb); 00451 if (NewDeviceObject) 00452 IoDeleteDevice(NewDeviceObject); 00453 } 00454 00455 DPRINT("NtfsMountVolume() done (Status: %lx)\n", Status); 00456 00457 return Status; 00458 } 00459 00460 00461 static NTSTATUS 00462 NtfsVerifyVolume(PDEVICE_OBJECT DeviceObject, 00463 PIRP Irp) 00464 { 00465 DPRINT1("NtfsVerifyVolume() called\n"); 00466 00467 return STATUS_WRONG_VOLUME; 00468 } 00469 00470 00471 NTSTATUS NTAPI 00472 NtfsFsdFileSystemControl(PDEVICE_OBJECT DeviceObject, 00473 PIRP Irp) 00474 { 00475 PIO_STACK_LOCATION Stack; 00476 NTSTATUS Status; 00477 00478 DPRINT1("NtfsFileSystemControl() called\n"); 00479 00480 Stack = IoGetCurrentIrpStackLocation(Irp); 00481 00482 switch (Stack->MinorFunction) 00483 { 00484 case IRP_MN_KERNEL_CALL: 00485 case IRP_MN_USER_FS_REQUEST: 00486 DPRINT("NTFS: IRP_MN_USER_FS_REQUEST/IRP_MN_KERNEL_CALL\n"); 00487 Status = STATUS_INVALID_DEVICE_REQUEST; 00488 break; 00489 00490 case IRP_MN_MOUNT_VOLUME: 00491 DPRINT("NTFS: IRP_MN_MOUNT_VOLUME\n"); 00492 Status = NtfsMountVolume(DeviceObject, Irp); 00493 break; 00494 00495 case IRP_MN_VERIFY_VOLUME: 00496 DPRINT1("NTFS: IRP_MN_VERIFY_VOLUME\n"); 00497 Status = NtfsVerifyVolume(DeviceObject, Irp); 00498 break; 00499 00500 default: 00501 DPRINT("NTFS FSC: MinorFunction %d\n", Stack->MinorFunction); 00502 Status = STATUS_INVALID_DEVICE_REQUEST; 00503 break; 00504 } 00505 00506 Irp->IoStatus.Status = Status; 00507 Irp->IoStatus.Information = 0; 00508 00509 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00510 00511 return(Status); 00512 } 00513 00514 /* EOF */ Generated on Mon May 28 2012 04:27:22 for ReactOS by
1.7.6.1
|