3 * Copyright (C) 2002 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* $Id: fsctl.c,v 1.35 2004/08/05 02:48:18 navaraf Exp $
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * FILE: drivers/fs/vfat/fsctl.c
24 * PURPOSE: VFAT Filesystem
27 /* INCLUDES *****************************************************************/
29 #include <ddk/ntddk.h>
30 #include <ntos/kefuncs.h>
31 #include <rosrtl/string.h>
39 /* FUNCTIONS ****************************************************************/
41 #define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->FatInfo.BytesPerCluster > PAGE_SIZE ? \
42 (pDeviceExt)->FatInfo.BytesPerCluster : PAGE_SIZE)
46 VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount
,
47 PBOOLEAN RecognizedFS
,
51 PARTITION_INFORMATION PartitionInfo
;
52 DISK_GEOMETRY DiskGeometry
;
57 struct _BootSector
* Boot
;
58 BOOL PartitionInfoIsValid
= FALSE
;
60 DPRINT("VfatHasFileSystem\n");
62 *RecognizedFS
= FALSE
;
64 Size
= sizeof(DISK_GEOMETRY
);
65 Status
= VfatBlockDeviceIoControl(DeviceToMount
,
66 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
72 if (!NT_SUCCESS(Status
))
74 DPRINT("VfatBlockDeviceIoControl faild (%x)\n", Status
);
77 FatInfo
.FixedMedia
= DiskGeometry
.MediaType
== FixedMedia
? TRUE
: FALSE
;
78 if (DiskGeometry
.MediaType
== FixedMedia
|| DiskGeometry
.MediaType
== RemovableMedia
)
80 // We have found a hard disk
81 Size
= sizeof(PARTITION_INFORMATION
);
82 Status
= VfatBlockDeviceIoControl(DeviceToMount
,
83 IOCTL_DISK_GET_PARTITION_INFO
,
89 if (!NT_SUCCESS(Status
))
91 DPRINT("VfatBlockDeviceIoControl faild (%x)\n", Status
);
94 PartitionInfoIsValid
= TRUE
;
95 #if defined(DBG) && !defined(NDEBUG)
96 DbgPrint("Partition Information:\n");
97 DbgPrint("StartingOffset %u\n", PartitionInfo
.StartingOffset
.QuadPart
/ 512);
98 DbgPrint("PartitionLength %u\n", PartitionInfo
.PartitionLength
.QuadPart
/ 512);
99 DbgPrint("HiddenSectors %u\n", PartitionInfo
.HiddenSectors
);
100 DbgPrint("PartitionNumber %u\n", PartitionInfo
.PartitionNumber
);
101 DbgPrint("PartitionType %u\n", PartitionInfo
.PartitionType
);
102 DbgPrint("BootIndicator %u\n", PartitionInfo
.BootIndicator
);
103 DbgPrint("RecognizedPartition %u\n", PartitionInfo
.RecognizedPartition
);
104 DbgPrint("RewritePartition %u\n", PartitionInfo
.RewritePartition
);
106 if (PartitionInfo
.PartitionType
)
108 if (PartitionInfo
.PartitionType
== PARTITION_FAT_12
||
109 PartitionInfo
.PartitionType
== PARTITION_FAT_16
||
110 PartitionInfo
.PartitionType
== PARTITION_HUGE
||
111 PartitionInfo
.PartitionType
== PARTITION_FAT32
||
112 PartitionInfo
.PartitionType
== PARTITION_FAT32_XINT13
||
113 PartitionInfo
.PartitionType
== PARTITION_XINT13
)
115 *RecognizedFS
= TRUE
;
118 else if (DiskGeometry
.MediaType
== RemovableMedia
&&
119 PartitionInfo
.PartitionNumber
> 0 &&
120 PartitionInfo
.StartingOffset
.QuadPart
== 0LL &&
121 PartitionInfo
.PartitionLength
.QuadPart
> 0LL)
123 /* This is possible a removable media formated as super floppy */
124 *RecognizedFS
= TRUE
;
128 * Floppy disk driver can return Unknown as media type if it
129 * doesn't know yet what floppy in the drive really is. This is
130 * perfectly correct to do under Windows.
132 if (DiskGeometry
.MediaType
== Unknown
)
134 *RecognizedFS
= TRUE
;
135 DiskGeometry
.BytesPerSector
= 512;
137 if (DiskGeometry
.MediaType
> Unknown
&& DiskGeometry
.MediaType
< RemovableMedia
)
139 *RecognizedFS
= TRUE
;
141 if (*RecognizedFS
== FALSE
)
143 return STATUS_SUCCESS
;
146 Boot
= ExAllocatePool(NonPagedPool
, DiskGeometry
.BytesPerSector
);
150 return STATUS_INSUFFICIENT_RESOURCES
;
155 Status
= VfatReadDisk(DeviceToMount
, &Offset
, DiskGeometry
.BytesPerSector
, (PUCHAR
) Boot
, FALSE
);
156 if (NT_SUCCESS(Status
))
158 if (Boot
->Signatur1
!= 0xaa55)
160 DPRINT1("Signature %04x\n", Boot
->Signatur1
);
164 Boot
->BytesPerSector
!= 512 &&
165 Boot
->BytesPerSector
!= 1024 &&
166 Boot
->BytesPerSector
!= 2048 &&
167 Boot
->BytesPerSector
!= 4096)
169 DPRINT1("BytesPerSector %d\n", Boot
->BytesPerSector
);
174 Boot
->FATCount
!= 1 &&
177 DPRINT1("FATCount %d\n", Boot
->FATCount
);
182 Boot
->Media
!= 0xf0 &&
183 Boot
->Media
!= 0xf8 &&
184 Boot
->Media
!= 0xf9 &&
185 Boot
->Media
!= 0xfa &&
186 Boot
->Media
!= 0xfb &&
187 Boot
->Media
!= 0xfc &&
188 Boot
->Media
!= 0xfd &&
189 Boot
->Media
!= 0xfe &&
192 DPRINT1("Media %02x\n", Boot
->Media
);
197 Boot
->SectorsPerCluster
!= 1 &&
198 Boot
->SectorsPerCluster
!= 2 &&
199 Boot
->SectorsPerCluster
!= 4 &&
200 Boot
->SectorsPerCluster
!= 8 &&
201 Boot
->SectorsPerCluster
!= 16 &&
202 Boot
->SectorsPerCluster
!= 32 &&
203 Boot
->SectorsPerCluster
!= 64 &&
204 Boot
->SectorsPerCluster
!= 128)
206 DPRINT1("SectorsPerCluster %02x\n", Boot
->SectorsPerCluster
);
211 Boot
->BytesPerSector
* Boot
->SectorsPerCluster
> 32 * 1024)
213 DPRINT1("ClusterSize %dx\n", Boot
->BytesPerSector
* Boot
->SectorsPerCluster
);
219 FatInfo
.VolumeID
= Boot
->VolumeID
;
220 FatInfo
.FATStart
= Boot
->ReservedSectors
;
221 FatInfo
.FATCount
= Boot
->FATCount
;
222 FatInfo
.FATSectors
= Boot
->FATSectors
? Boot
->FATSectors
: ((struct _BootSector32
*) Boot
)->FATSectors32
;
223 FatInfo
.BytesPerSector
= Boot
->BytesPerSector
;
224 FatInfo
.SectorsPerCluster
= Boot
->SectorsPerCluster
;
225 FatInfo
.BytesPerCluster
= FatInfo
.BytesPerSector
* FatInfo
.SectorsPerCluster
;
226 FatInfo
.rootDirectorySectors
= ((Boot
->RootEntries
* 32) + Boot
->BytesPerSector
- 1) / Boot
->BytesPerSector
;
227 FatInfo
.rootStart
= FatInfo
.FATStart
+ FatInfo
.FATCount
* FatInfo
.FATSectors
;
228 FatInfo
.dataStart
= FatInfo
.rootStart
+ FatInfo
.rootDirectorySectors
;
229 FatInfo
.Sectors
= Sectors
= Boot
->Sectors
? Boot
->Sectors
: Boot
->SectorsHuge
;
230 Sectors
-= Boot
->ReservedSectors
+ FatInfo
.FATCount
* FatInfo
.FATSectors
+ FatInfo
.rootDirectorySectors
;
231 FatInfo
.NumberOfClusters
= Sectors
/ Boot
->SectorsPerCluster
;
232 if (FatInfo
.NumberOfClusters
< 4085)
235 FatInfo
.FatType
= FAT12
;
237 else if (FatInfo
.NumberOfClusters
>= 65525)
240 FatInfo
.FatType
= FAT32
;
241 FatInfo
.RootCluster
= ((struct _BootSector32
*) Boot
)->RootCluster
;
242 FatInfo
.rootStart
= FatInfo
.dataStart
+ ((FatInfo
.RootCluster
- 2) * FatInfo
.SectorsPerCluster
);
243 FatInfo
.VolumeID
= ((struct _BootSector32
*) Boot
)->VolumeID
;
248 FatInfo
.FatType
= FAT16
;
250 if (PartitionInfoIsValid
&&
251 FatInfo
.Sectors
> PartitionInfo
.PartitionLength
.QuadPart
/ FatInfo
.BytesPerSector
)
254 *RecognizedFS
= FALSE
;
257 if (pFatInfo
&& *RecognizedFS
)
265 DPRINT("VfatHasFileSystem done\n");
270 VfatMountDevice(PDEVICE_EXTENSION DeviceExt
,
271 PDEVICE_OBJECT DeviceToMount
)
273 * FUNCTION: Mounts the device
277 BOOLEAN RecognizedFS
;
279 DPRINT("Mounting VFAT device...\n");
281 Status
= VfatHasFileSystem(DeviceToMount
, &RecognizedFS
, &DeviceExt
->FatInfo
);
282 if (!NT_SUCCESS(Status
))
286 DPRINT("MountVfatdev %d, PAGE_SIZE = %d\n", DeviceExt
->FatInfo
.BytesPerCluster
, PAGE_SIZE
);
289 return(STATUS_SUCCESS
);
294 VfatMount (PVFAT_IRP_CONTEXT IrpContext
)
296 * FUNCTION: Mount the filesystem
299 PDEVICE_OBJECT DeviceObject
= NULL
;
300 PDEVICE_EXTENSION DeviceExt
= NULL
;
301 BOOLEAN RecognizedFS
;
304 PVFATFCB VolumeFcb
= NULL
;
306 PDEVICE_OBJECT DeviceToMount
;
307 UNICODE_STRING NameU
;
309 DPRINT("VfatMount(IrpContext %x)\n", IrpContext
);
313 if (IrpContext
->DeviceObject
!= VfatGlobalData
->DeviceObject
)
315 Status
= STATUS_INVALID_DEVICE_REQUEST
;
319 DeviceToMount
= IrpContext
->Stack
->Parameters
.MountVolume
.DeviceObject
;
321 Status
= VfatHasFileSystem (DeviceToMount
, &RecognizedFS
, NULL
);
322 if (!NT_SUCCESS(Status
))
327 if (RecognizedFS
== FALSE
)
329 DPRINT("VFAT: Unrecognized Volume\n");
330 Status
= STATUS_UNRECOGNIZED_VOLUME
;
334 DPRINT("VFAT: Recognized volume\n");
335 Status
= IoCreateDevice(VfatGlobalData
->DriverObject
,
336 sizeof (DEVICE_EXTENSION
),
338 FILE_DEVICE_FILE_SYSTEM
,
342 if (!NT_SUCCESS(Status
))
347 DeviceObject
->Flags
= DeviceObject
->Flags
| DO_DIRECT_IO
;
348 DeviceExt
= (PVOID
) DeviceObject
->DeviceExtension
;
349 RtlZeroMemory(DeviceExt
, sizeof(DEVICE_EXTENSION
));
351 /* use same vpb as device disk */
352 DeviceObject
->Vpb
= DeviceToMount
->Vpb
;
353 Status
= VfatMountDevice(DeviceExt
, DeviceToMount
);
354 if (!NT_SUCCESS(Status
))
356 /* FIXME: delete device object */
361 DbgPrint("BytesPerSector: %d\n", DeviceExt
->FatInfo
.BytesPerSector
);
362 DbgPrint("SectorsPerCluster: %d\n", DeviceExt
->FatInfo
.SectorsPerCluster
);
363 DbgPrint("FATCount: %d\n", DeviceExt
->FatInfo
.FATCount
);
364 DbgPrint("FATSectors: %d\n", DeviceExt
->FatInfo
.FATSectors
);
365 DbgPrint("RootStart: %d\n", DeviceExt
->FatInfo
.rootStart
);
366 DbgPrint("DataStart: %d\n", DeviceExt
->FatInfo
.dataStart
);
367 if (DeviceExt
->FatInfo
.FatType
== FAT32
)
369 DbgPrint("RootCluster: %d\n", DeviceExt
->FatInfo
.RootCluster
);
373 DeviceExt
->StorageDevice
= DeviceToMount
;
374 DeviceExt
->StorageDevice
->Vpb
->DeviceObject
= DeviceObject
;
375 DeviceExt
->StorageDevice
->Vpb
->RealDevice
= DeviceExt
->StorageDevice
;
376 DeviceExt
->StorageDevice
->Vpb
->Flags
|= VPB_MOUNTED
;
377 DeviceObject
->StackSize
= DeviceExt
->StorageDevice
->StackSize
+ 1;
378 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
380 DPRINT("FsDeviceObject %lx\n", DeviceObject
);
382 DeviceExt
->FATFileObject
= IoCreateStreamFileObject(NULL
, DeviceExt
->StorageDevice
);
383 RtlRosInitUnicodeStringFromLiteral(&NameU
, L
"\\$$Fat$$");
384 Fcb
= vfatNewFCB(&NameU
);
387 Status
= STATUS_INSUFFICIENT_RESOURCES
;
390 Ccb
= ExAllocateFromNPagedLookasideList(&VfatGlobalData
->CcbLookasideList
);
393 Status
= STATUS_INSUFFICIENT_RESOURCES
;
397 memset(Ccb
, 0, sizeof (VFATCCB
));
398 DeviceExt
->FATFileObject
->Flags
= DeviceExt
->FATFileObject
->Flags
| FO_FCB_IS_VALID
| FO_DIRECT_CACHE_PAGING_READ
;
399 DeviceExt
->FATFileObject
->FsContext
= Fcb
;
400 DeviceExt
->FATFileObject
->FsContext2
= Ccb
;
401 DeviceExt
->FATFileObject
->SectionObjectPointer
= &Fcb
->SectionObjectPointers
;
402 DeviceExt
->FATFileObject
->PrivateCacheMap
= NULL
;
403 DeviceExt
->FATFileObject
->Vpb
= DeviceObject
->Vpb
;
404 Fcb
->FileObject
= DeviceExt
->FATFileObject
;
406 Fcb
->Flags
= FCB_IS_FAT
;
408 Fcb
->RFCB
.FileSize
.QuadPart
= DeviceExt
->FatInfo
.FATSectors
* DeviceExt
->FatInfo
.BytesPerSector
;
409 Fcb
->RFCB
.ValidDataLength
= Fcb
->RFCB
.FileSize
;
410 Fcb
->RFCB
.AllocationSize
= Fcb
->RFCB
.FileSize
;
412 if (DeviceExt
->FatInfo
.FatType
!= FAT12
)
414 Status
= CcRosInitializeFileCache(DeviceExt
->FATFileObject
, CACHEPAGESIZE(DeviceExt
));
418 Status
= CcRosInitializeFileCache(DeviceExt
->FATFileObject
, 2 * PAGE_SIZE
);
420 if (!NT_SUCCESS (Status
))
422 DbgPrint ("CcRosInitializeFileCache failed\n");
425 DeviceExt
->LastAvailableCluster
= 2;
426 ExInitializeResourceLite(&DeviceExt
->DirResource
);
427 ExInitializeResourceLite(&DeviceExt
->FatResource
);
429 switch (DeviceExt
->FatInfo
.FatType
)
432 DeviceExt
->GetNextCluster
= FAT12GetNextCluster
;
433 DeviceExt
->FindAndMarkAvailableCluster
= FAT12FindAndMarkAvailableCluster
;
434 DeviceExt
->WriteCluster
= FAT12WriteCluster
;
438 DeviceExt
->GetNextCluster
= FAT16GetNextCluster
;
439 DeviceExt
->FindAndMarkAvailableCluster
= FAT16FindAndMarkAvailableCluster
;
440 DeviceExt
->WriteCluster
= FAT16WriteCluster
;
444 DeviceExt
->GetNextCluster
= FAT32GetNextCluster
;
445 DeviceExt
->FindAndMarkAvailableCluster
= FAT32FindAndMarkAvailableCluster
;
446 DeviceExt
->WriteCluster
= FAT32WriteCluster
;
450 InitializeListHead(&DeviceExt
->FcbListHead
);
451 RtlRosInitUnicodeStringFromLiteral(&NameU
, L
"\\$$Volume$$");
453 VolumeFcb
= vfatNewFCB(&NameU
);
454 if (VolumeFcb
== NULL
)
456 Status
= STATUS_INSUFFICIENT_RESOURCES
;
459 VolumeFcb
->Flags
= FCB_IS_VOLUME
;
460 VolumeFcb
->RFCB
.FileSize
.QuadPart
= DeviceExt
->FatInfo
.Sectors
* DeviceExt
->FatInfo
.BytesPerSector
;
461 VolumeFcb
->RFCB
.ValidDataLength
= VolumeFcb
->RFCB
.FileSize
;
462 VolumeFcb
->RFCB
.AllocationSize
= VolumeFcb
->RFCB
.FileSize
;
463 DeviceExt
->VolumeFcb
= VolumeFcb
;
465 ExAcquireResourceExclusiveLite(&VfatGlobalData
->VolumeListLock
, TRUE
);
466 InsertHeadList(&VfatGlobalData
->VolumeListHead
, &DeviceExt
->VolumeListEntry
);
467 ExReleaseResourceLite(&VfatGlobalData
->VolumeListLock
);
469 /* read serial number */
470 DeviceObject
->Vpb
->SerialNumber
= DeviceExt
->FatInfo
.VolumeID
;
472 /* read volume label */
473 ReadVolumeLabel(DeviceExt
, DeviceObject
->Vpb
);
475 Status
= STATUS_SUCCESS
;
478 if (!NT_SUCCESS(Status
))
481 if (DeviceExt
&& DeviceExt
->FATFileObject
)
482 ObDereferenceObject (DeviceExt
->FATFileObject
);
488 IoDeleteDevice(DeviceObject
);
490 vfatDestroyFCB(VolumeFcb
);
497 VfatVerify (PVFAT_IRP_CONTEXT IrpContext
)
499 * FUNCTION: Verify the filesystem
502 PDEVICE_OBJECT DeviceToVerify
;
503 NTSTATUS Status
= STATUS_SUCCESS
;
505 BOOLEAN RecognizedFS
;
506 PDEVICE_EXTENSION DeviceExt
= IrpContext
->DeviceExt
;
508 DPRINT("VfatVerify(IrpContext %x)\n", IrpContext
);
510 DeviceToVerify
= IrpContext
->Stack
->Parameters
.VerifyVolume
.DeviceObject
;
511 Status
= VfatBlockDeviceIoControl(DeviceToVerify
,
512 IOCTL_DISK_CHECK_VERIFY
,
518 DeviceToVerify
->Flags
&= ~DO_VERIFY_VOLUME
;
519 if (!NT_SUCCESS(Status
) && Status
!= STATUS_VERIFY_REQUIRED
)
521 DPRINT("VfatBlockDeviceIoControl() failed (Status %lx)\n", Status
);
522 Status
= STATUS_WRONG_VOLUME
;
526 Status
= VfatHasFileSystem(DeviceToVerify
, &RecognizedFS
, &FatInfo
);
527 if (!NT_SUCCESS(Status
) || RecognizedFS
== FALSE
)
529 Status
= STATUS_WRONG_VOLUME
;
531 else if (sizeof(FATINFO
) == RtlCompareMemory(&FatInfo
, &DeviceExt
->FatInfo
, sizeof(FATINFO
)))
535 * Preformated floppy disks have very often a serial number of 0000:0000.
536 * We should calculate a crc sum over the sectors from the root directory as secondary volume number.
537 * Each write to the root directory must update this crc sum.
543 Status
= STATUS_WRONG_VOLUME
;
552 VfatGetVolumeBitmap(PVFAT_IRP_CONTEXT IrpContext
)
554 DPRINT("VfatGetVolumeBitmap (IrpContext %x)\n", IrpContext
);
556 return STATUS_INVALID_DEVICE_REQUEST
;
561 VfatGetRetrievalPointers(PVFAT_IRP_CONTEXT IrpContext
)
563 PIO_STACK_LOCATION Stack
;
565 PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers
;
566 PFILE_OBJECT FileObject
;
567 ULONG MaxExtentCount
;
569 PDEVICE_EXTENSION DeviceExt
;
571 ULONG CurrentCluster
;
575 DPRINT("VfatGetRetrievalPointers(IrpContext %x)\n", IrpContext
);
577 DeviceExt
= IrpContext
->DeviceExt
;
578 FileObject
= IrpContext
->FileObject
;
579 Stack
= IrpContext
->Stack
;
580 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(LARGE_INTEGER
) ||
581 Stack
->Parameters
.DeviceIoControl
.Type3InputBuffer
== NULL
)
583 return STATUS_INVALID_PARAMETER
;
585 if (IrpContext
->Irp
->UserBuffer
== NULL
||
586 Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(GET_RETRIEVAL_DESCRIPTOR
) + sizeof(MAPPING_PAIR
))
588 return STATUS_BUFFER_TOO_SMALL
;
591 Fcb
= FileObject
->FsContext
;
593 ExAcquireResourceSharedLite(&Fcb
->MainResource
, TRUE
);
595 Vcn
= *(PLARGE_INTEGER
)Stack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
596 RetrievalPointers
= IrpContext
->Irp
->UserBuffer
;
598 MaxExtentCount
= ((Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
- sizeof(GET_RETRIEVAL_DESCRIPTOR
)) / sizeof(MAPPING_PAIR
));
601 if (Vcn
.QuadPart
>= Fcb
->RFCB
.AllocationSize
.QuadPart
/ DeviceExt
->FatInfo
.BytesPerCluster
)
603 Status
= STATUS_INVALID_PARAMETER
;
607 CurrentCluster
= FirstCluster
= vfatDirEntryGetFirstCluster(DeviceExt
, &Fcb
->entry
);
608 Status
= OffsetToCluster(DeviceExt
, FirstCluster
,
609 Vcn
.u
.LowPart
* DeviceExt
->FatInfo
.BytesPerCluster
,
610 &CurrentCluster
, FALSE
);
611 if (!NT_SUCCESS(Status
))
616 RetrievalPointers
->StartVcn
= Vcn
.QuadPart
;
617 RetrievalPointers
->NumberOfPairs
= 0;
618 RetrievalPointers
->Pair
[0].Lcn
= CurrentCluster
- 2;
620 while (CurrentCluster
!= 0xffffffff && RetrievalPointers
->NumberOfPairs
< MaxExtentCount
)
623 LastCluster
= CurrentCluster
;
624 Status
= NextCluster(DeviceExt
, CurrentCluster
, &CurrentCluster
, FALSE
);
626 if (!NT_SUCCESS(Status
))
631 if (LastCluster
+ 1 != CurrentCluster
)
633 RetrievalPointers
->Pair
[RetrievalPointers
->NumberOfPairs
].Vcn
= Vcn
.QuadPart
;
634 RetrievalPointers
->NumberOfPairs
++;
635 if (RetrievalPointers
->NumberOfPairs
< MaxExtentCount
)
637 RetrievalPointers
->Pair
[RetrievalPointers
->NumberOfPairs
].Lcn
= CurrentCluster
- 2;
642 IrpContext
->Irp
->IoStatus
.Information
= sizeof(GET_RETRIEVAL_DESCRIPTOR
) + sizeof(MAPPING_PAIR
) * RetrievalPointers
->NumberOfPairs
;
643 Status
= STATUS_SUCCESS
;
646 ExReleaseResourceLite(&Fcb
->MainResource
);
652 VfatMoveFile(PVFAT_IRP_CONTEXT IrpContext
)
654 DPRINT("VfatMoveFile(IrpContext %x)\n", IrpContext
);
656 return STATUS_INVALID_DEVICE_REQUEST
;
660 VfatRosQueryLcnMapping(PVFAT_IRP_CONTEXT IrpContext
)
662 PDEVICE_EXTENSION DeviceExt
;
663 PROS_QUERY_LCN_MAPPING LcnQuery
;
664 PIO_STACK_LOCATION Stack
;
666 DPRINT("VfatGetRetrievalPointers(IrpContext %x)\n", IrpContext
);
668 DeviceExt
= IrpContext
->DeviceExt
;
669 Stack
= IrpContext
->Stack
;
670 if (IrpContext
->Irp
->AssociatedIrp
.SystemBuffer
== NULL
||
671 Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(ROS_QUERY_LCN_MAPPING
))
673 return STATUS_BUFFER_TOO_SMALL
;
675 LcnQuery
= (PROS_QUERY_LCN_MAPPING
)(IrpContext
->Irp
->AssociatedIrp
.SystemBuffer
);
676 LcnQuery
->LcnDiskOffset
.QuadPart
= DeviceExt
->FatInfo
.dataStart
* DeviceExt
->FatInfo
.BytesPerSector
;
677 IrpContext
->Irp
->IoStatus
.Information
= sizeof(ROS_QUERY_LCN_MAPPING
);
678 return(STATUS_SUCCESS
);
681 NTSTATUS
VfatFileSystemControl(PVFAT_IRP_CONTEXT IrpContext
)
683 * FUNCTION: File system control
689 DPRINT("VfatFileSystemControl(IrpContext %x)\n", IrpContext
);
692 assert (IrpContext
->Irp
);
693 assert (IrpContext
->Stack
);
695 IrpContext
->Irp
->IoStatus
.Information
= 0;
697 switch (IrpContext
->MinorFunction
)
699 case IRP_MN_USER_FS_REQUEST
:
700 switch(IrpContext
->Stack
->Parameters
.DeviceIoControl
.IoControlCode
)
702 case FSCTL_GET_VOLUME_BITMAP
:
703 Status
= VfatGetVolumeBitmap(IrpContext
);
705 case FSCTL_GET_RETRIEVAL_POINTERS
:
706 Status
= VfatGetRetrievalPointers(IrpContext
);
708 case FSCTL_MOVE_FILE
:
709 Status
= VfatMoveFile(IrpContext
);
711 case FSCTL_ROS_QUERY_LCN_MAPPING
:
712 Status
= VfatRosQueryLcnMapping(IrpContext
);
715 Status
= STATUS_INVALID_DEVICE_REQUEST
;
719 case IRP_MN_MOUNT_VOLUME
:
720 Status
= VfatMount(IrpContext
);
723 case IRP_MN_VERIFY_VOLUME
:
724 DPRINT("VFATFS: IRP_MN_VERIFY_VOLUME\n");
725 Status
= VfatVerify(IrpContext
);
729 DPRINT("VFAT FSC: MinorFunction %d\n", IrpContext
->MinorFunction
);
730 Status
= STATUS_INVALID_DEVICE_REQUEST
;
734 IrpContext
->Irp
->IoStatus
.Status
= Status
;
736 IoCompleteRequest (IrpContext
->Irp
, IO_NO_INCREMENT
);
737 VfatFreeIrpContext(IrpContext
);