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 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
1.7.6.1
|