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 along
00016  *  with this program; if not, write to the Free Software Foundation, Inc.,
00017  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00018  */
00019 /*
00020  * COPYRIGHT:        See COPYING in the top level directory
00021  * PROJECT:          ReactOS kernel
00022  * FILE:             drivers/fs/vfat/fsctl.c
00023  * PURPOSE:          VFAT Filesystem
00024  */
00025 
00026 /* INCLUDES *****************************************************************/
00027 
00028 #define NDEBUG
00029 #include "vfat.h"
00030 
00031 /* FUNCTIONS ****************************************************************/
00032 
00033 #define  CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->FatInfo.BytesPerCluster > PAGE_SIZE ? \
00034                                     (pDeviceExt)->FatInfo.BytesPerCluster : PAGE_SIZE)
00035 
00036 static NTSTATUS
00037 VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount,
00038                   PBOOLEAN RecognizedFS,
00039                   PFATINFO pFatInfo)
00040 {
00041    NTSTATUS Status;
00042    PARTITION_INFORMATION PartitionInfo;
00043    DISK_GEOMETRY DiskGeometry;
00044    FATINFO FatInfo;
00045    ULONG Size;
00046    ULONG Sectors;
00047    LARGE_INTEGER Offset;
00048    struct _BootSector* Boot;
00049    struct _BootSectorFatX* BootFatX;
00050    BOOLEAN PartitionInfoIsValid = FALSE;
00051 
00052    DPRINT("VfatHasFileSystem\n");
00053 
00054    *RecognizedFS = FALSE;
00055 
00056    Size = sizeof(DISK_GEOMETRY);
00057    Status = VfatBlockDeviceIoControl(DeviceToMount,
00058                                      IOCTL_DISK_GET_DRIVE_GEOMETRY,
00059                                      NULL,
00060                                      0,
00061                                      &DiskGeometry,
00062                                      &Size,
00063                                      FALSE);
00064    if (!NT_SUCCESS(Status))
00065    {
00066       DPRINT("VfatBlockDeviceIoControl faild (%x)\n", Status);
00067       return Status;
00068    }
00069    FatInfo.FixedMedia = DiskGeometry.MediaType == FixedMedia ? TRUE : FALSE;
00070    if (DiskGeometry.MediaType == FixedMedia || DiskGeometry.MediaType == RemovableMedia)
00071    {
00072       // We have found a hard disk
00073       Size = sizeof(PARTITION_INFORMATION);
00074       Status = VfatBlockDeviceIoControl(DeviceToMount,
00075                                         IOCTL_DISK_GET_PARTITION_INFO,
00076                                         NULL,
00077                                         0,
00078                                         &PartitionInfo,
00079                                         &Size,
00080                                         FALSE);
00081       if (!NT_SUCCESS(Status))
00082       {
00083          DPRINT("VfatBlockDeviceIoControl faild (%x)\n", Status);
00084          return Status;
00085       }
00086       PartitionInfoIsValid = TRUE;
00087       DPRINT("Partition Information:\n");
00088       DPRINT("StartingOffset      %I64u\n", PartitionInfo.StartingOffset.QuadPart  / 512);
00089       DPRINT("PartitionLength     %I64u\n", PartitionInfo.PartitionLength.QuadPart / 512);
00090       DPRINT("HiddenSectors       %u\n", PartitionInfo.HiddenSectors);
00091       DPRINT("PartitionNumber     %u\n", PartitionInfo.PartitionNumber);
00092       DPRINT("PartitionType       %u\n", PartitionInfo.PartitionType);
00093       DPRINT("BootIndicator       %u\n", PartitionInfo.BootIndicator);
00094       DPRINT("RecognizedPartition %u\n", PartitionInfo.RecognizedPartition);
00095       DPRINT("RewritePartition    %u\n", PartitionInfo.RewritePartition);
00096       if (PartitionInfo.PartitionType)
00097       {
00098          if (PartitionInfo.PartitionType == PARTITION_FAT_12       ||
00099              PartitionInfo.PartitionType == PARTITION_FAT_16       ||
00100              PartitionInfo.PartitionType == PARTITION_HUGE         ||
00101              PartitionInfo.PartitionType == PARTITION_FAT32        ||
00102              PartitionInfo.PartitionType == PARTITION_FAT32_XINT13 ||
00103              PartitionInfo.PartitionType == PARTITION_XINT13)
00104          {
00105             *RecognizedFS = TRUE;
00106          }
00107       }
00108       else if (DiskGeometry.MediaType == RemovableMedia &&
00109                PartitionInfo.PartitionNumber > 0 &&
00110                PartitionInfo.StartingOffset.QuadPart == 0 &&
00111                PartitionInfo.PartitionLength.QuadPart > 0)
00112       {
00113          /* This is possible a removable media formated as super floppy */
00114          *RecognizedFS = TRUE;
00115       }
00116    }
00117    else if (DiskGeometry.MediaType == Unknown)
00118    {
00119       /*
00120        * Floppy disk driver can return Unknown as media type if it
00121        * doesn't know yet what floppy in the drive really is. This is
00122        * perfectly correct to do under Windows.
00123        */
00124       *RecognizedFS = TRUE;
00125       DiskGeometry.BytesPerSector = 512;
00126    }
00127    else
00128    {
00129       *RecognizedFS = TRUE;
00130    }
00131    if (*RecognizedFS)
00132    {
00133 
00134       Boot = ExAllocatePoolWithTag(NonPagedPool, DiskGeometry.BytesPerSector, TAG_VFAT);
00135       if (Boot == NULL)
00136       {
00137          return STATUS_INSUFFICIENT_RESOURCES;
00138       }
00139 
00140       Offset.QuadPart = 0;
00141 
00142       /* Try to recognize FAT12/FAT16/FAT32 partitions */
00143       Status = VfatReadDisk(DeviceToMount, &Offset, DiskGeometry.BytesPerSector, (PUCHAR) Boot, FALSE);
00144       if (NT_SUCCESS(Status))
00145       {
00146          if (Boot->Signatur1 != 0xaa55)
00147          {
00148             *RecognizedFS = FALSE;
00149          }
00150          if (*RecognizedFS &&
00151          Boot->BytesPerSector != 512 &&
00152          Boot->BytesPerSector != 1024 &&
00153              Boot->BytesPerSector != 2048 &&
00154          Boot->BytesPerSector != 4096)
00155          {
00156             DPRINT1("BytesPerSector %d\n", Boot->BytesPerSector);
00157             *RecognizedFS = FALSE;
00158          }
00159 
00160          if (*RecognizedFS &&
00161              Boot->FATCount != 1 &&
00162              Boot->FATCount != 2)
00163          {
00164             DPRINT1("FATCount %d\n", Boot->FATCount);
00165             *RecognizedFS = FALSE;
00166          }
00167 
00168          if (*RecognizedFS &&
00169              Boot->Media != 0xf0 &&
00170              Boot->Media != 0xf8 &&
00171              Boot->Media != 0xf9 &&
00172              Boot->Media != 0xfa &&
00173              Boot->Media != 0xfb &&
00174              Boot->Media != 0xfc &&
00175              Boot->Media != 0xfd &&
00176              Boot->Media != 0xfe &&
00177              Boot->Media != 0xff)
00178          {
00179             DPRINT1("Media             %02x\n", Boot->Media);
00180             *RecognizedFS = FALSE;
00181          }
00182 
00183          if (*RecognizedFS &&
00184              Boot->SectorsPerCluster != 1 &&
00185              Boot->SectorsPerCluster != 2 &&
00186              Boot->SectorsPerCluster != 4 &&
00187              Boot->SectorsPerCluster != 8 &&
00188              Boot->SectorsPerCluster != 16 &&
00189              Boot->SectorsPerCluster != 32 &&
00190              Boot->SectorsPerCluster != 64 &&
00191              Boot->SectorsPerCluster != 128)
00192          {
00193             DPRINT1("SectorsPerCluster %02x\n", Boot->SectorsPerCluster);
00194             *RecognizedFS = FALSE;
00195          }
00196 
00197          if (*RecognizedFS &&
00198              Boot->BytesPerSector * Boot->SectorsPerCluster > 32 * 1024)
00199          {
00200             DPRINT1("ClusterSize %dx\n", Boot->BytesPerSector * Boot->SectorsPerCluster);
00201             *RecognizedFS = FALSE;
00202          }
00203 
00204          if (*RecognizedFS)
00205          {
00206             FatInfo.VolumeID = Boot->VolumeID;
00207             FatInfo.FATStart = Boot->ReservedSectors;
00208             FatInfo.FATCount = Boot->FATCount;
00209             FatInfo.FATSectors = Boot->FATSectors ? Boot->FATSectors : ((struct _BootSector32*) Boot)->FATSectors32;
00210             FatInfo.BytesPerSector = Boot->BytesPerSector;
00211             FatInfo.SectorsPerCluster = Boot->SectorsPerCluster;
00212             FatInfo.BytesPerCluster = FatInfo.BytesPerSector * FatInfo.SectorsPerCluster;
00213             FatInfo.rootDirectorySectors = ((Boot->RootEntries * 32) + Boot->BytesPerSector - 1) / Boot->BytesPerSector;
00214             FatInfo.rootStart = FatInfo.FATStart + FatInfo.FATCount * FatInfo.FATSectors;
00215             FatInfo.dataStart = FatInfo.rootStart + FatInfo.rootDirectorySectors;
00216             FatInfo.Sectors = Sectors = Boot->Sectors ? Boot->Sectors : Boot->SectorsHuge;
00217             Sectors -= Boot->ReservedSectors + FatInfo.FATCount * FatInfo.FATSectors + FatInfo.rootDirectorySectors;
00218             FatInfo.NumberOfClusters = Sectors / Boot->SectorsPerCluster;
00219             if (FatInfo.NumberOfClusters < 4085)
00220             {
00221                DPRINT("FAT12\n");
00222                FatInfo.FatType = FAT12;
00223                FatInfo.RootCluster = (FatInfo.rootStart - 1) / FatInfo.SectorsPerCluster;
00224             }
00225             else if (FatInfo.NumberOfClusters >= 65525)
00226             {
00227                DPRINT("FAT32\n");
00228                FatInfo.FatType = FAT32;
00229                FatInfo.RootCluster = ((struct _BootSector32*) Boot)->RootCluster;
00230                FatInfo.rootStart = FatInfo.dataStart + ((FatInfo.RootCluster - 2) * FatInfo.SectorsPerCluster);
00231                FatInfo.VolumeID = ((struct _BootSector32*) Boot)->VolumeID;
00232             }
00233             else
00234             {
00235                DPRINT("FAT16\n");
00236                FatInfo.FatType = FAT16;
00237                FatInfo.RootCluster = FatInfo.rootStart / FatInfo.SectorsPerCluster;
00238             }
00239             if (PartitionInfoIsValid &&
00240                 FatInfo.Sectors > PartitionInfo.PartitionLength.QuadPart / FatInfo.BytesPerSector)
00241             {
00242                *RecognizedFS = FALSE;
00243             }
00244 
00245             if (pFatInfo && *RecognizedFS)
00246             {
00247                *pFatInfo = FatInfo;
00248             }
00249          }
00250       }
00251 
00252       ExFreePool(Boot);
00253    }
00254 
00255    if (!*RecognizedFS && PartitionInfoIsValid)
00256    {
00257       BootFatX = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct _BootSectorFatX), TAG_VFAT);
00258       if (BootFatX == NULL)
00259       {
00260          *RecognizedFS=FALSE;
00261          return STATUS_INSUFFICIENT_RESOURCES;
00262       }
00263 
00264       Offset.QuadPart = 0;
00265 
00266       /* Try to recognize FATX16/FATX32 partitions (Xbox) */
00267       Status = VfatReadDisk(DeviceToMount, &Offset, sizeof(struct _BootSectorFatX), (PUCHAR) BootFatX, FALSE);
00268       if (NT_SUCCESS(Status))
00269       {
00270          *RecognizedFS = TRUE;
00271          if (BootFatX->SysType[0] != 'F' ||
00272              BootFatX->SysType[1] != 'A' ||
00273              BootFatX->SysType[2] != 'T' ||
00274              BootFatX->SysType[3] != 'X')
00275          {
00276             DPRINT1("SysType %c%c%c%c\n", BootFatX->SysType[0], BootFatX->SysType[1], BootFatX->SysType[2], BootFatX->SysType[3]);
00277             *RecognizedFS=FALSE;
00278          }
00279 
00280          if (*RecognizedFS &&
00281             BootFatX->SectorsPerCluster != 1 &&
00282             BootFatX->SectorsPerCluster != 2 &&
00283             BootFatX->SectorsPerCluster != 4 &&
00284             BootFatX->SectorsPerCluster != 8 &&
00285             BootFatX->SectorsPerCluster != 16 &&
00286             BootFatX->SectorsPerCluster != 32 &&
00287             BootFatX->SectorsPerCluster != 64 &&
00288             BootFatX->SectorsPerCluster != 128)
00289          {
00290             DPRINT1("SectorsPerCluster %lu\n", BootFatX->SectorsPerCluster);
00291             *RecognizedFS=FALSE;
00292          }
00293 
00294          if (*RecognizedFS)
00295          {
00296             FatInfo.BytesPerSector = DiskGeometry.BytesPerSector;
00297             FatInfo.SectorsPerCluster = BootFatX->SectorsPerCluster;
00298             FatInfo.rootDirectorySectors = BootFatX->SectorsPerCluster;
00299             FatInfo.BytesPerCluster = BootFatX->SectorsPerCluster * DiskGeometry.BytesPerSector;
00300             FatInfo.Sectors = (ULONG)(PartitionInfo.PartitionLength.QuadPart / DiskGeometry.BytesPerSector);
00301             if (FatInfo.Sectors / FatInfo.SectorsPerCluster < 65525)
00302             {
00303                DPRINT("FATX16\n");
00304                FatInfo.FatType = FATX16;
00305             }
00306             else
00307             {
00308                DPRINT("FATX32\n");
00309                FatInfo.FatType = FATX32;
00310             }
00311             FatInfo.VolumeID = BootFatX->VolumeID;
00312             FatInfo.FATStart = sizeof(struct _BootSectorFatX) / DiskGeometry.BytesPerSector;
00313             FatInfo.FATCount = BootFatX->FATCount;
00314             FatInfo.FATSectors =
00315                   ROUND_UP(FatInfo.Sectors / FatInfo.SectorsPerCluster * (FatInfo.FatType == FATX16 ? 2 : 4), 4096) /
00316                   FatInfo.BytesPerSector;
00317             FatInfo.rootStart = FatInfo.FATStart + FatInfo.FATCount * FatInfo.FATSectors;
00318             FatInfo.RootCluster = (FatInfo.rootStart - 1) / FatInfo.SectorsPerCluster;
00319             FatInfo.dataStart = FatInfo.rootStart + FatInfo.rootDirectorySectors;
00320             FatInfo.NumberOfClusters = (FatInfo.Sectors - FatInfo.dataStart) / FatInfo.SectorsPerCluster;
00321 
00322             if (pFatInfo && *RecognizedFS)
00323             {
00324                *pFatInfo = FatInfo;
00325             }
00326          }
00327       }
00328       ExFreePool(BootFatX);
00329    }
00330 
00331    DPRINT("VfatHasFileSystem done\n");
00332    return Status;
00333 }
00334 
00335 static NTSTATUS
00336 VfatMountDevice(PDEVICE_EXTENSION DeviceExt,
00337                 PDEVICE_OBJECT DeviceToMount)
00338 /*
00339  * FUNCTION: Mounts the device
00340  */
00341 {
00342    NTSTATUS Status;
00343    BOOLEAN RecognizedFS;
00344 
00345    DPRINT("Mounting VFAT device...\n");
00346 
00347    Status = VfatHasFileSystem(DeviceToMount, &RecognizedFS, &DeviceExt->FatInfo);
00348    if (!NT_SUCCESS(Status))
00349    {
00350       return(Status);
00351    }
00352    DPRINT("MountVfatdev %d, PAGE_SIZE = %d\n", DeviceExt->FatInfo.BytesPerCluster, PAGE_SIZE);
00353 
00354 
00355    return(STATUS_SUCCESS);
00356 }
00357 
00358 
00359 static NTSTATUS
00360 VfatMount (PVFAT_IRP_CONTEXT IrpContext)
00361 /*
00362  * FUNCTION: Mount the filesystem
00363  */
00364 {
00365    PDEVICE_OBJECT DeviceObject = NULL;
00366    PDEVICE_EXTENSION DeviceExt = NULL;
00367    BOOLEAN RecognizedFS;
00368    NTSTATUS Status;
00369    PVFATFCB Fcb = NULL;
00370    PVFATFCB VolumeFcb = NULL;
00371    PVFATCCB Ccb = NULL;
00372    PDEVICE_OBJECT DeviceToMount;
00373    PVPB Vpb;
00374    UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"\\$$Fat$$");
00375    UNICODE_STRING VolumeNameU = RTL_CONSTANT_STRING(L"\\$$Volume$$");
00376    ULONG HashTableSize;
00377    ULONG eocMark;
00378    FATINFO FatInfo;
00379 
00380    DPRINT("VfatMount(IrpContext %p)\n", IrpContext);
00381 
00382    ASSERT(IrpContext);
00383 
00384    if (IrpContext->DeviceObject != VfatGlobalData->DeviceObject)
00385    {
00386       Status = STATUS_INVALID_DEVICE_REQUEST;
00387       goto ByeBye;
00388    }
00389 
00390    DeviceToMount = IrpContext->Stack->Parameters.MountVolume.DeviceObject;
00391    Vpb = IrpContext->Stack->Parameters.MountVolume.Vpb;
00392 
00393    Status = VfatHasFileSystem (DeviceToMount, &RecognizedFS, &FatInfo);
00394    if (!NT_SUCCESS(Status))
00395    {
00396       goto ByeBye;
00397    }
00398 
00399    if (RecognizedFS == FALSE)
00400    {
00401       DPRINT("VFAT: Unrecognized Volume\n");
00402       Status = STATUS_UNRECOGNIZED_VOLUME;
00403       goto ByeBye;
00404    }
00405 
00406    /* Use prime numbers for the table size */
00407    if (FatInfo.FatType == FAT12)
00408    {
00409       HashTableSize = 4099; // 4096 = 4 * 1024
00410    }
00411    else if (FatInfo.FatType == FAT16 ||
00412             FatInfo.FatType == FATX16)
00413    {
00414       HashTableSize = 16411; // 16384 = 16 * 1024
00415    }
00416    else
00417    {
00418       HashTableSize = 65537; // 65536 = 64 * 1024;
00419    }
00420    HashTableSize = FCB_HASH_TABLE_SIZE;
00421    DPRINT("VFAT: Recognized volume\n");
00422    Status = IoCreateDevice(VfatGlobalData->DriverObject,
00423                            ROUND_UP(sizeof (DEVICE_EXTENSION), sizeof(ULONG)) + sizeof(HASHENTRY*) * HashTableSize,
00424                            NULL,
00425                            FILE_DEVICE_DISK_FILE_SYSTEM,
00426                            DeviceToMount->Characteristics,
00427                            FALSE,
00428                            &DeviceObject);
00429    if (!NT_SUCCESS(Status))
00430    {
00431       goto ByeBye;
00432    }
00433 
00434    DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
00435    DeviceExt = (PVOID) DeviceObject->DeviceExtension;
00436    RtlZeroMemory(DeviceExt, ROUND_UP(sizeof(DEVICE_EXTENSION), sizeof(ULONG)) + sizeof(HASHENTRY*) * HashTableSize);
00437    DeviceExt->FcbHashTable = (HASHENTRY**)((ULONG_PTR)DeviceExt + ROUND_UP(sizeof(DEVICE_EXTENSION), sizeof(ULONG)));
00438    DeviceExt->HashTableSize = HashTableSize;
00439 
00440    /* use same vpb as device disk */
00441    DeviceObject->Vpb = Vpb;
00442    DeviceToMount->Vpb = Vpb;
00443 
00444    Status = VfatMountDevice(DeviceExt, DeviceToMount);
00445    if (!NT_SUCCESS(Status))
00446    {
00447       /* FIXME: delete device object */
00448       goto ByeBye;
00449    }
00450 
00451    DPRINT("BytesPerSector:     %d\n", DeviceExt->FatInfo.BytesPerSector);
00452    DPRINT("SectorsPerCluster:  %d\n", DeviceExt->FatInfo.SectorsPerCluster);
00453    DPRINT("FATCount:           %d\n", DeviceExt->FatInfo.FATCount);
00454    DPRINT("FATSectors:         %d\n", DeviceExt->FatInfo.FATSectors);
00455    DPRINT("RootStart:          %d\n", DeviceExt->FatInfo.rootStart);
00456    DPRINT("DataStart:          %d\n", DeviceExt->FatInfo.dataStart);
00457    if (DeviceExt->FatInfo.FatType == FAT32)
00458    {
00459       DPRINT("RootCluster:        %d\n", DeviceExt->FatInfo.RootCluster);
00460    }
00461 
00462    switch (DeviceExt->FatInfo.FatType)
00463    {
00464       case FAT12:
00465          DeviceExt->GetNextCluster = FAT12GetNextCluster;
00466          DeviceExt->FindAndMarkAvailableCluster = FAT12FindAndMarkAvailableCluster;
00467          DeviceExt->WriteCluster = FAT12WriteCluster;
00468          DeviceExt->CleanShutBitMask = 0;
00469          break;
00470 
00471       case FAT16:
00472       case FATX16:
00473          DeviceExt->GetNextCluster = FAT16GetNextCluster;
00474          DeviceExt->FindAndMarkAvailableCluster = FAT16FindAndMarkAvailableCluster;
00475          DeviceExt->WriteCluster = FAT16WriteCluster;
00476          DeviceExt->CleanShutBitMask = 0x8000;
00477          break;
00478 
00479       case FAT32:
00480       case FATX32:
00481          DeviceExt->GetNextCluster = FAT32GetNextCluster;
00482          DeviceExt->FindAndMarkAvailableCluster = FAT32FindAndMarkAvailableCluster;
00483          DeviceExt->WriteCluster = FAT32WriteCluster;
00484          DeviceExt->CleanShutBitMask = 0x80000000;
00485          break;
00486    }
00487 
00488    if (DeviceExt->FatInfo.FatType == FATX16
00489       || DeviceExt->FatInfo.FatType == FATX32)
00490    {
00491       DeviceExt->Flags |= VCB_IS_FATX;
00492       DeviceExt->GetNextDirEntry = FATXGetNextDirEntry;
00493       DeviceExt->BaseDateYear = 2000;
00494    }
00495    else
00496    {
00497       DeviceExt->GetNextDirEntry = FATGetNextDirEntry;
00498       DeviceExt->BaseDateYear = 1980;
00499    }
00500 
00501    DeviceExt->StorageDevice = DeviceToMount;
00502    DeviceExt->StorageDevice->Vpb->DeviceObject = DeviceObject;
00503    DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice;
00504    DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED;
00505    DeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1;
00506    DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
00507 
00508    DPRINT("FsDeviceObject %p\n", DeviceObject);
00509 
00510    /* Initialize this resource early ... it's used in VfatCleanup */
00511    ExInitializeResourceLite(&DeviceExt->DirResource);
00512 
00513    DeviceExt->FATFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice);
00514    Fcb = vfatNewFCB(DeviceExt, &NameU);
00515    if (Fcb == NULL)
00516    {
00517       Status = STATUS_INSUFFICIENT_RESOURCES;
00518       goto ByeBye;
00519    }
00520    Ccb = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
00521    if (Ccb == NULL)
00522    {
00523       Status =  STATUS_INSUFFICIENT_RESOURCES;
00524       goto ByeBye;
00525    }
00526 
00527    RtlZeroMemory(Ccb, sizeof (VFATCCB));
00528    DeviceExt->FATFileObject->FsContext = Fcb;
00529    DeviceExt->FATFileObject->FsContext2 = Ccb;
00530    DeviceExt->FATFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
00531    DeviceExt->FATFileObject->PrivateCacheMap = NULL;
00532    DeviceExt->FATFileObject->Vpb = DeviceObject->Vpb;
00533    Fcb->FileObject = DeviceExt->FATFileObject;
00534 
00535    Fcb->Flags |= FCB_IS_FAT;
00536 
00537    Fcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector;
00538    Fcb->RFCB.ValidDataLength = Fcb->RFCB.FileSize;
00539    Fcb->RFCB.AllocationSize = Fcb->RFCB.FileSize;
00540 
00541    CcInitializeCacheMap(DeviceExt->FATFileObject,
00542                         (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
00543                         TRUE,
00544                         &VfatGlobalData->CacheMgrCallbacks,
00545                         Fcb);
00546 
00547    DeviceExt->LastAvailableCluster = 2;
00548    ExInitializeResourceLite(&DeviceExt->FatResource);
00549 
00550    InitializeListHead(&DeviceExt->FcbListHead);
00551 
00552    VolumeFcb = vfatNewFCB(DeviceExt, &VolumeNameU);
00553    if (VolumeFcb == NULL)
00554    {
00555       Status = STATUS_INSUFFICIENT_RESOURCES;
00556       goto ByeBye;
00557    }
00558    VolumeFcb->Flags = FCB_IS_VOLUME;
00559    VolumeFcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.Sectors * DeviceExt->FatInfo.BytesPerSector;
00560    VolumeFcb->RFCB.ValidDataLength = VolumeFcb->RFCB.FileSize;
00561    VolumeFcb->RFCB.AllocationSize = VolumeFcb->RFCB.FileSize;
00562    DeviceExt->VolumeFcb = VolumeFcb;
00563 
00564    ExAcquireResourceExclusiveLite(&VfatGlobalData->VolumeListLock, TRUE);
00565    InsertHeadList(&VfatGlobalData->VolumeListHead, &DeviceExt->VolumeListEntry);
00566    ExReleaseResourceLite(&VfatGlobalData->VolumeListLock);
00567 
00568    /* read serial number */
00569    DeviceObject->Vpb->SerialNumber = DeviceExt->FatInfo.VolumeID;
00570 
00571    /* read volume label */
00572    ReadVolumeLabel(DeviceExt,  DeviceObject->Vpb);
00573 
00574    /* read clean shutdown bit status */
00575    Status = GetNextCluster(DeviceExt, 1, &eocMark);
00576    if (NT_SUCCESS(Status))
00577    {
00578       if (eocMark & DeviceExt->CleanShutBitMask)
00579       {
00580          /* unset clean shutdown bit */
00581          eocMark &= ~DeviceExt->CleanShutBitMask;
00582          WriteCluster(DeviceExt, 1, eocMark);
00583          VolumeFcb->Flags |= VCB_CLEAR_DIRTY;
00584       }
00585    }
00586    VolumeFcb->Flags |= VCB_IS_DIRTY;
00587 
00588    FsRtlNotifyVolumeEvent(DeviceExt->FATFileObject, FSRTL_VOLUME_MOUNT);
00589 
00590    Status = STATUS_SUCCESS;
00591 ByeBye:
00592 
00593   if (!NT_SUCCESS(Status))
00594   {
00595      // cleanup
00596      if (DeviceExt && DeviceExt->FATFileObject)
00597         ObDereferenceObject (DeviceExt->FATFileObject);
00598      if (Fcb)
00599         vfatDestroyFCB(Fcb);
00600      if (Ccb)
00601         vfatDestroyCCB(Ccb);
00602      if (DeviceObject)
00603        IoDeleteDevice(DeviceObject);
00604      if (VolumeFcb)
00605         vfatDestroyFCB(VolumeFcb);
00606   }
00607   return Status;
00608 }
00609 
00610 
00611 static NTSTATUS
00612 VfatVerify (PVFAT_IRP_CONTEXT IrpContext)
00613 /*
00614  * FUNCTION: Verify the filesystem
00615  */
00616 {
00617   PDEVICE_OBJECT DeviceToVerify;
00618   NTSTATUS Status = STATUS_SUCCESS;
00619   FATINFO FatInfo;
00620   BOOLEAN RecognizedFS;
00621   PDEVICE_EXTENSION DeviceExt = IrpContext->DeviceExt;
00622 
00623   DPRINT("VfatVerify(IrpContext %p)\n", IrpContext);
00624 
00625   DeviceToVerify = IrpContext->Stack->Parameters.VerifyVolume.DeviceObject;
00626   Status = VfatBlockDeviceIoControl(DeviceToVerify,
00627                                     IOCTL_DISK_CHECK_VERIFY,
00628                                     NULL,
00629                                     0,
00630                                     NULL,
00631                                     0,
00632                                     TRUE);
00633   DeviceToVerify->Flags &= ~DO_VERIFY_VOLUME;
00634   if (!NT_SUCCESS(Status) && Status != STATUS_VERIFY_REQUIRED)
00635     {
00636       DPRINT("VfatBlockDeviceIoControl() failed (Status %lx)\n", Status);
00637       Status = STATUS_WRONG_VOLUME;
00638     }
00639   else
00640     {
00641       Status = VfatHasFileSystem(DeviceToVerify, &RecognizedFS, &FatInfo);
00642       if (!NT_SUCCESS(Status) || RecognizedFS == FALSE)
00643         {
00644           Status = STATUS_WRONG_VOLUME;
00645         }
00646       else if (sizeof(FATINFO) == RtlCompareMemory(&FatInfo, &DeviceExt->FatInfo, sizeof(FATINFO)))
00647         {
00648           /*
00649            * FIXME:
00650            *   Preformated floppy disks have very often a serial number of 0000:0000.
00651            *   We should calculate a crc sum over the sectors from the root directory as secondary volume number.
00652            *   Each write to the root directory must update this crc sum.
00653            */
00654 
00655         }
00656       else
00657         {
00658           Status = STATUS_WRONG_VOLUME;
00659         }
00660      }
00661 
00662   return Status;
00663 }
00664 
00665 
00666 static NTSTATUS
00667 VfatGetVolumeBitmap(PVFAT_IRP_CONTEXT IrpContext)
00668 {
00669    DPRINT("VfatGetVolumeBitmap (IrpContext %p)\n", IrpContext);
00670 
00671    return STATUS_INVALID_DEVICE_REQUEST;
00672 }
00673 
00674 
00675 static NTSTATUS
00676 VfatGetRetrievalPointers(PVFAT_IRP_CONTEXT IrpContext)
00677 {
00678    PIO_STACK_LOCATION Stack;
00679    LARGE_INTEGER Vcn;
00680    PRETRIEVAL_POINTERS_BUFFER RetrievalPointers;
00681    PFILE_OBJECT FileObject;
00682    ULONG MaxExtentCount;
00683    PVFATFCB Fcb;
00684    PDEVICE_EXTENSION DeviceExt;
00685    ULONG FirstCluster;
00686    ULONG CurrentCluster;
00687    ULONG LastCluster;
00688    NTSTATUS Status;
00689 
00690    DPRINT("VfatGetRetrievalPointers(IrpContext %p)\n", IrpContext);
00691 
00692    DeviceExt = IrpContext->DeviceExt;
00693    FileObject = IrpContext->FileObject;
00694    Stack = IrpContext->Stack;
00695    if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(STARTING_VCN_INPUT_BUFFER) ||
00696        Stack->Parameters.DeviceIoControl.Type3InputBuffer == NULL)
00697    {
00698       return STATUS_INVALID_PARAMETER;
00699    }
00700    if (IrpContext->Irp->UserBuffer == NULL ||
00701        Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(RETRIEVAL_POINTERS_BUFFER))
00702    {
00703       return STATUS_BUFFER_TOO_SMALL;
00704    }
00705 
00706    Fcb = FileObject->FsContext;
00707 
00708    ExAcquireResourceSharedLite(&Fcb->MainResource, TRUE);
00709 
00710    Vcn = ((PSTARTING_VCN_INPUT_BUFFER)Stack->Parameters.DeviceIoControl.Type3InputBuffer)->StartingVcn;
00711    RetrievalPointers = IrpContext->Irp->UserBuffer;
00712 
00713    MaxExtentCount = ((Stack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(RetrievalPointers->ExtentCount) - sizeof(RetrievalPointers->StartingVcn)) / sizeof(RetrievalPointers->Extents[0]));
00714 
00715 
00716    if (Vcn.QuadPart >= Fcb->RFCB.AllocationSize.QuadPart / DeviceExt->FatInfo.BytesPerCluster)
00717    {
00718       Status = STATUS_INVALID_PARAMETER;
00719       goto ByeBye;
00720    }
00721 
00722    CurrentCluster = FirstCluster = vfatDirEntryGetFirstCluster(DeviceExt, &Fcb->entry);
00723    Status = OffsetToCluster(DeviceExt, FirstCluster,
00724                             Vcn.u.LowPart * DeviceExt->FatInfo.BytesPerCluster,
00725                             &CurrentCluster, FALSE);
00726    if (!NT_SUCCESS(Status))
00727    {
00728       goto ByeBye;
00729    }
00730 
00731    RetrievalPointers->StartingVcn = Vcn;
00732    RetrievalPointers->ExtentCount = 0;
00733    RetrievalPointers->Extents[0].Lcn.u.HighPart = 0;
00734    RetrievalPointers->Extents[0].Lcn.u.LowPart = CurrentCluster - 2;
00735    LastCluster = 0;
00736    while (CurrentCluster != 0xffffffff && RetrievalPointers->ExtentCount < MaxExtentCount)
00737    {
00738 
00739       LastCluster = CurrentCluster;
00740       Status = NextCluster(DeviceExt, CurrentCluster, &CurrentCluster, FALSE);
00741       Vcn.QuadPart++;
00742       if (!NT_SUCCESS(Status))
00743       {
00744          goto ByeBye;
00745       }
00746 
00747       if (LastCluster + 1 != CurrentCluster)
00748       {
00749          RetrievalPointers->Extents[RetrievalPointers->ExtentCount].NextVcn = Vcn;
00750          RetrievalPointers->ExtentCount++;
00751          if (RetrievalPointers->ExtentCount < MaxExtentCount)
00752          {
00753             RetrievalPointers->Extents[RetrievalPointers->ExtentCount].Lcn.u.HighPart = 0;
00754             RetrievalPointers->Extents[RetrievalPointers->ExtentCount].Lcn.u.LowPart = CurrentCluster - 2;
00755          }
00756       }
00757    }
00758 
00759    IrpContext->Irp->IoStatus.Information = sizeof(RETRIEVAL_POINTERS_BUFFER) + (sizeof(RetrievalPointers->Extents[0]) * (RetrievalPointers->ExtentCount - 1));
00760    Status = STATUS_SUCCESS;
00761 
00762 ByeBye:
00763    ExReleaseResourceLite(&Fcb->MainResource);
00764 
00765    return Status;
00766 }
00767 
00768 static NTSTATUS
00769 VfatMoveFile(PVFAT_IRP_CONTEXT IrpContext)
00770 {
00771    DPRINT("VfatMoveFile(IrpContext %p)\n", IrpContext);
00772 
00773    return STATUS_INVALID_DEVICE_REQUEST;
00774 }
00775 
00776 static NTSTATUS
00777 VfatIsVolumeDirty(PVFAT_IRP_CONTEXT IrpContext)
00778 {
00779    PULONG Flags;
00780 
00781    DPRINT("VfatIsVolumeDirty(IrpContext %p)\n", IrpContext);
00782 
00783    if (IrpContext->Stack->Parameters.FileSystemControl.OutputBufferLength != sizeof(ULONG))
00784       return STATUS_INVALID_BUFFER_SIZE;
00785    else if (!IrpContext->Irp->AssociatedIrp.SystemBuffer)
00786       return STATUS_INVALID_USER_BUFFER;
00787 
00788    Flags = (PULONG)IrpContext->Irp->AssociatedIrp.SystemBuffer;
00789    *Flags = 0;
00790 
00791    if (IrpContext->DeviceExt->VolumeFcb->Flags & VCB_IS_DIRTY
00792       && !(IrpContext->DeviceExt->VolumeFcb->Flags & VCB_CLEAR_DIRTY))
00793    {
00794       *Flags |= VOLUME_IS_DIRTY;
00795    }
00796 
00797    return STATUS_SUCCESS;
00798 }
00799 
00800 static NTSTATUS
00801 VfatMarkVolumeDirty(PVFAT_IRP_CONTEXT IrpContext)
00802 {
00803    ULONG eocMark;
00804    PDEVICE_EXTENSION DeviceExt;
00805    NTSTATUS Status = STATUS_SUCCESS;
00806 
00807    DPRINT("VfatMarkVolumeDirty(IrpContext %p)\n", IrpContext);
00808    DeviceExt = IrpContext->DeviceExt;
00809 
00810    if (!(DeviceExt->VolumeFcb->Flags & VCB_IS_DIRTY))
00811    {
00812       Status = GetNextCluster(DeviceExt, 1, &eocMark);
00813       if (NT_SUCCESS(Status))
00814       {
00815          /* unset clean shutdown bit */
00816          eocMark &= ~DeviceExt->CleanShutBitMask;
00817          Status = WriteCluster(DeviceExt, 1, eocMark);
00818       }
00819    }
00820 
00821    DeviceExt->VolumeFcb->Flags &= ~VCB_CLEAR_DIRTY;
00822 
00823    return Status;
00824 }
00825 
00826 NTSTATUS VfatFileSystemControl(PVFAT_IRP_CONTEXT IrpContext)
00827 /*
00828  * FUNCTION: File system control
00829  */
00830 {
00831 
00832    NTSTATUS Status;
00833 
00834    DPRINT("VfatFileSystemControl(IrpContext %p)\n", IrpContext);
00835 
00836    ASSERT(IrpContext);
00837    ASSERT(IrpContext->Irp);
00838    ASSERT(IrpContext->Stack);
00839 
00840    IrpContext->Irp->IoStatus.Information = 0;
00841 
00842    switch (IrpContext->MinorFunction)
00843    {
00844       case IRP_MN_KERNEL_CALL:
00845       case IRP_MN_USER_FS_REQUEST:
00846          switch(IrpContext->Stack->Parameters.DeviceIoControl.IoControlCode)
00847          {
00848             case FSCTL_GET_VOLUME_BITMAP:
00849                Status = VfatGetVolumeBitmap(IrpContext);
00850                break;
00851             case FSCTL_GET_RETRIEVAL_POINTERS:
00852                Status = VfatGetRetrievalPointers(IrpContext);
00853                break;
00854             case FSCTL_MOVE_FILE:
00855                Status = VfatMoveFile(IrpContext);
00856                break;
00857             case FSCTL_IS_VOLUME_DIRTY:
00858                Status = VfatIsVolumeDirty(IrpContext);
00859                break;
00860             case FSCTL_MARK_VOLUME_DIRTY:
00861                Status = VfatMarkVolumeDirty(IrpContext);
00862                break;
00863             default:
00864                Status = STATUS_INVALID_DEVICE_REQUEST;
00865          }
00866          break;
00867 
00868       case IRP_MN_MOUNT_VOLUME:
00869          Status = VfatMount(IrpContext);
00870          break;
00871 
00872       case IRP_MN_VERIFY_VOLUME:
00873         DPRINT("VFATFS: IRP_MN_VERIFY_VOLUME\n");
00874          Status = VfatVerify(IrpContext);
00875          break;
00876 
00877       default:
00878            DPRINT("VFAT FSC: MinorFunction %d\n", IrpContext->MinorFunction);
00879            Status = STATUS_INVALID_DEVICE_REQUEST;
00880            break;
00881    }
00882 
00883    IrpContext->Irp->IoStatus.Status = Status;
00884 
00885    IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT);
00886    VfatFreeIrpContext(IrpContext);
00887    return (Status);
00888 }

Generated on Sun May 27 2012 04:27:36 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.