ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

fsctl.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.