24#define BugCheckFileId (FAT_BUG_CHECK_FSCTRL)
30#define Dbg (DEBUG_TRACE_FSCTRL)
119FatInvalidateVolumes (
125FatScanForDismountedVcb (
141FatQueryRetrievalPointers (
173FatGetRetrievalPointerBase (
193FatSetPurgeFailureMode (
211FatGetRetrievalPointers (
218FatMoveFileNeedsWriteThrough (
237 ULONG BytesToReallocate,
238 PULONG FirstSpliceSourceCluster,
239 PULONG FirstSpliceTargetCluster,
240 PULONG SecondSpliceSourceCluster,
241 PULONG SecondSpliceTargetCluster,
247FatComputeMoveFileParameter (
276#pragma alloc_text(PAGE, FatAddMcbEntry)
277#pragma alloc_text(PAGE, FatAllowExtendedDasdIo)
278#pragma alloc_text(PAGE, FatCommonFileSystemControl)
279#pragma alloc_text(PAGE, FatComputeMoveFileParameter)
280#pragma alloc_text(PAGE, FatComputeMoveFileSplicePoints)
281#pragma alloc_text(PAGE, FatDirtyVolume)
282#pragma alloc_text(PAGE, FatFsdFileSystemControl)
283#pragma alloc_text(PAGE, FatGetRetrievalPointerBase)
284#pragma alloc_text(PAGE, FatGetBootAreaInfo)
285#pragma alloc_text(PAGE, FatMarkHandle)
286#pragma alloc_text(PAGE, FatGetRetrievalPointers)
287#pragma alloc_text(PAGE, FatGetStatistics)
288#pragma alloc_text(PAGE, FatGetVolumeBitmap)
289#pragma alloc_text(PAGE, FatIsMediaWriteProtected)
290#pragma alloc_text(PAGE, FatIsPathnameValid)
291#pragma alloc_text(PAGE, FatIsVolumeDirty)
292#pragma alloc_text(PAGE, FatIsVolumeMounted)
293#pragma alloc_text(PAGE, FatLockVolume)
294#pragma alloc_text(PAGE, FatLookupLastMcbEntry)
295#pragma alloc_text(PAGE, FatGetNextMcbEntry)
296#pragma alloc_text(PAGE, FatMountVolume)
297#pragma alloc_text(PAGE, FatMoveFileNeedsWriteThrough)
298#pragma alloc_text(PAGE, FatMoveFile)
299#pragma alloc_text(PAGE, FatOplockRequest)
300#pragma alloc_text(PAGE, FatPerformVerifyDiskRead)
301#pragma alloc_text(PAGE, FatQueryBpb)
302#pragma alloc_text(PAGE, FatQueryRetrievalPointers)
303#pragma alloc_text(PAGE, FatRemoveMcbEntry)
304#pragma alloc_text(PAGE, FatScanForDismountedVcb)
305#pragma alloc_text(PAGE, FatFlushAndCleanVolume)
306#pragma alloc_text(PAGE, FatSearchBufferForLabel)
307#pragma alloc_text(PAGE, FatSetPurgeFailureMode)
308#pragma alloc_text(PAGE, FatUnlockVolume)
309#pragma alloc_text(PAGE, FatUserFsCtrl)
310#pragma alloc_text(PAGE, FatVerifyLookupFatEntry)
311#pragma alloc_text(PAGE, FatVerifyVolume)
330#define MCB_SCALE_LOG2 (Vcb->AllocationSupport.LogOfBytesPerSector)
331#define MCB_SCALE (1 << MCB_SCALE_LOG2)
332#define MCB_SCALE_MODULO (MCB_SCALE - 1)
398 if (
Mcb != &
Vcb->DirtyFatMcb) {
399 NT_ASSERT( FatNonSparseMcb(
Vcb,
Mcb, &SparseVbo, &SparseByteCount ) ||
408 if (
Mcb != &
Vcb->DirtyFatMcb) {
409 NT_ASSERT( FatNonSparseMcb(
Vcb,
Mcb, &SparseVbo, &SparseByteCount ) ||
445 if ((
ULONG) LiLbo != -1) {
520 if (((
ULONG) LiLbo) != -1) {
570 if (((
ULONG) LiLbo) != -1) {
581 if ((*
ByteCount == 0) && (LiSectorCount != 0)) {
639FatFsdFileSystemControl (
720 Status = FatCommonFileSystemControl( IrpContext,
Irp );
751FatCommonFileSystemControl (
799 Status = FatUserFsCtrl( IrpContext,
Irp );
804 Status = FatMountVolume( IrpContext,
824 Status = FatVerifyVolume( IrpContext,
Irp );
920 ULONG ChangeCount = 0;
927#if (NTDDI_VERSION > NTDDI_WIN8)
928 GUID VolumeGuid = {0};
1016 &PartitionInformation,
1032 FatScanForDismountedVcb( IrpContext );
1044 MountNewVolume =
FALSE;
1053#pragma prefast( push )
1054#pragma prefast( disable: 28137, "prefast wants the wait to be a constant, but that isn't possible for the way fastfat is designed" )
1055#pragma prefast( disable: 28193, "this will always wait" )
1061#pragma prefast( pop )
1095 VolDo->OverflowQueueCount = 0;
1098 VolDo->PostedRequestCount = 0;
1133#pragma prefast( suppress: 28175, "this is a filesystem driver, touching SectorSize is fine" )
1157 RealDevice =
Vpb->RealDevice;
1163 WeClearedVerifyRequiredBit =
TRUE;
1170 FatInitializeVcb( IrpContext,
1221#if (NTDDI_VERSION > NTDDI_WIN8)
1226 if (
NT_SUCCESS( IoVolumeDeviceToGuid(
Vcb->TargetDeviceObject, &VolumeGuid ))) {
1242 if (
Vcb->VolumeGuidPath.Buffer) {
1244 Vcb->VolumeGuidPath.Buffer =
NULL;
1245 Vcb->VolumeGuidPath.Length =
Vcb->VolumeGuidPath.MaximumLength = 0;
1248 IoVolumeDeviceToGuidPath(
Vcb->TargetDeviceObject, &
Vcb->VolumeGuidPath );
1284 (
Vcb->Bpb.Sectors != 0 &&
1285 Vcb->Bpb.Sectors < 0x80)) {
1287 DebugTrace( 0,
Dbg,
"OS/2 Boot Manager volume detected, volume not mounted. \n", 0 );
1315 if (
Vcb->Bpb.Sectors != 0) {
Vcb->Bpb.LargeSectors = 0; }
1332 Vcb->First0x24BytesOfBootSector =
1366 if (
Vcb->Bpb.FsInfoSector >=
Vcb->Bpb.ReservedSectors) {
1368 Vcb->Bpb.FsInfoSector = 0;
1386 FatCreateRootDcb( IrpContext,
Vcb );
1417 FatLocateVolumeLabel( IrpContext,
1425 UCHAR OemBuffer[11];
1471 Vpb->VolumeLabelLength = 0;
1480 Vcb->ChangeCount = ChangeCount;
1490 Links = Links->
Flink) {
1493 OldVpb = OldVcb->
Vpb;
1499 if (OldVpb ==
Vpb) {
continue; }
1515 &
Vpb->VolumeLabel[0],
1516 Vpb->VolumeLabelLength)) &&
1522 LargeSectorsPerFat) ))) {
1562#pragma prefast( suppress: 28175, "touching Vpb is ok for a filesystem" )
1579 if (*IrpVpb ==
Vpb) {
1606 DebugTrace(0,
Dbg,
"Truncate and reinitialize the volume file\n", 0);
1724 MountNewVolume =
TRUE;
1736 RootDirectoryFile =
Vcb->RootDcb->Specific.Dcb.DirectoryFile;
1762 if ( !MountNewVolume ) {
1770 FatCheckForDismount( IrpContext,
1774 IrpContext->Vcb =
NULL;
1776 }
else if (VolDo !=
NULL) {
1796 FatCheckForDismount( IrpContext,
1802 if ( WeClearedVerifyRequiredBit ==
TRUE ) {
1818 if (RootDirectoryFile !=
NULL) {
1820#if (NTDDI_VERSION >= NTDDI_WIN8)
1913 LBO RootDirectoryLbo;
1914 ULONG RootDirectorySize;
1917 ULONG ChangeCount = 0;
1940 IrpContext->Vcb =
Vcb = &VolDo->
Vcb;
1965#pragma prefast( push )
1966#pragma prefast( disable: 28137, "prefast wants the wait to be a constant, but that isn't possible for the way fastfat is designed" )
1967#pragma prefast( disable: 28193, "this will always wait" )
1973#pragma prefast( pop )
1999 DebugTrace(0,
Dbg,
"RealDevice has already been verified\n", 0);
2001 VerifyAlreadyDone =
TRUE;
2014 Vcb->TargetDeviceObject,
2017 &PartitionInformation,
2036 Vcb->TargetDeviceObject,
2052 if (AllowRawMount) {
2062 if (
Iosb.Information !=
sizeof(
ULONG)) {
2076 Vcb->ChangeCount = ChangeCount;
2097 Vcb->TargetDeviceObject,
2113 if (AllowRawMount) {
2200 LargeSectorsPerFat) )) {
2255 if (!LabelFound &&
Vpb->VolumeLabelLength > 0) {
2262 ULONG RootDirectoryCluster;
2303 RootDirectoryCluster,
2304 &RootDirectoryCluster );
2327 Vpb->VolumeLabelLength > 0) {
2354 if (!VerifyAlreadyDone) {
2357 ReleaseEntireVolume =
TRUE;
2383 if (!ReleaseEntireVolume) {
2385 ReleaseEntireVolume =
TRUE;
2392 FatPurgeReferencedFileObjects( IrpContext,
Vcb->RootDcb,
NoFlush );
2411 }
else if (!VerifyAlreadyDone) {
2418 if (!ReleaseEntireVolume) {
2420 ReleaseEntireVolume =
TRUE;
2432 FatPurgeReferencedFileObjects( IrpContext,
Vcb->RootDcb,
Flush );
2493 if (ReleaseEntireVolume) {
2607 }
else if (Bpb.
Fats == 0) {
2630 }
else if ((Bpb.
Media != 0xf0) &&
2631 (Bpb.
Media != 0xf8) &&
2632 (Bpb.
Media != 0xf9) &&
2633 (Bpb.
Media != 0xfb) &&
2634 (Bpb.
Media != 0xfc) &&
2635 (Bpb.
Media != 0xfd) &&
2636 (Bpb.
Media != 0xfe) &&
2637 (Bpb.
Media != 0xff) &&
2639 (Bpb.
Media != 0x01) &&
2640 (Bpb.
Media != 0xfa)))) {
2829#if (NTDDI_VERSION >= NTDDI_WIN7)
2830 case FSCTL_REQUEST_OPLOCK:
2832 Status = FatOplockRequest( IrpContext,
Irp );
2837 Status = FatLockVolume( IrpContext,
Irp );
2847 Status = FatDismountVolume( IrpContext,
Irp );
2852 Status = FatDirtyVolume( IrpContext,
Irp );
2870 Status = FatQueryRetrievalPointers( IrpContext,
Irp );
2881#if (NTDDI_VERSION >= NTDDI_WIN7)
2883 Status = FatGetRetrievalPointerBase( IrpContext,
Irp );
2886 case FSCTL_GET_BOOT_AREA_INFO:
2887 Status = FatGetBootAreaInfo( IrpContext,
Irp );
2892 Status = FatGetVolumeBitmap( IrpContext,
Irp );
2896 Status = FatGetRetrievalPointers( IrpContext,
Irp );
2900 Status = FatMoveFile( IrpContext,
Irp );
2908 Status = FatMarkHandle( IrpContext,
Irp );
2911#if (NTDDI_VERSION >= NTDDI_WIN8)
2913 case FSCTL_SET_PURGE_FAILURE_MODE:
2914 Status = FatSetPurgeFailureMode( IrpContext,
Irp );
2920#if (NTDDI_VERSION >= NTDDI_WIN7)
2976 ULONG OplockCount = 0;
2983#if (NTDDI_VERSION >= NTDDI_WIN7)
3016 DebugTrace(-1,
Dbg,
"FatOplockRequest -> STATUS_INVALID_PARAMETER\n", 0);
3020#if (NTDDI_VERSION >= NTDDI_WIN7)
3029 InputBuffer = (PREQUEST_OPLOCK_INPUT_BUFFER)
Irp->AssociatedIrp.SystemBuffer;
3041 DebugTrace(-1,
Dbg,
"FatOplockRequest -> STATUS_BUFFER_TOO_SMALL\n", 0);
3053 !FsRtlOplockIsSharedRequest(
Irp ))) {
3056 DebugTrace(-1,
Dbg,
"FatOplockRequest -> STATUS_INVALID_PARAMETER\n", 0);
3090 FatAcquireSharedVcb( IrpContext,
Fcb->
Vcb );
3092 FatAcquireExclusiveFcb( IrpContext,
Fcb );
3095#if (NTDDI_VERSION >= NTDDI_WIN7)
3096 if (FsRtlOplockIsSharedRequest(
Irp )) {
3112#if (NTDDI_VERSION >= NTDDI_WIN8)
3114#elif (NTDDI_VERSION >= NTDDI_WIN7)
3115 OplockCount = (
ULONG) FsRtlAreThereCurrentOrInProgressFileLocks( &
Fcb->
Specific.
Fcb.FileLock );
3137 FatAcquireSharedFcb( IrpContext,
Fcb );
3139#if (NTDDI_VERSION >= NTDDI_WIN7)
3155#pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
3433FatLockVolumeInternal (
3495 FatPurgeReferencedFileObjects( IrpContext,
Vcb->RootDcb,
Flush );
3530 FatPurgeReferencedFileObjects( IrpContext,
Vcb->RootDcb,
Flush );
3567 (
Vcb->Vpb->ReferenceCount <= 2 + RemainingUserReferences) &&
3646 Vcb->FileObjectWithVcbLocked =
NULL;
3774#pragma prefast( push )
3775#pragma prefast( disable: 28137, "prefast wants the wait to be a constant, but that isn't possible for the way fastfat is designed" )
3776#pragma prefast( disable: 28193, "this will always wait" )
3782#pragma prefast( pop )
3836#if (NTDDI_VERSION >= NTDDI_WIN8)
3838 FsRtlDismountComplete(
Vcb->TargetDeviceObject,
Status );
3954 DebugTrace(-1,
Dbg,
"FatDirtyVolume -> STATUS_SUCCESS\n", 0);
4010 if (
Irp->AssociatedIrp.SystemBuffer !=
NULL) {
4014 }
else if (
Irp->MdlAddress !=
NULL) {
4084 Irp->IoStatus.Information =
sizeof(
ULONG );
4254 if (
Vcb->First0x24BytesOfBootSector ==
NULL) {
4283 Vcb->First0x24BytesOfBootSector,
4286 Irp->IoStatus.Information = 0x24;
4300FatInvalidateVolumes (
4357#if defined(_WIN64) && defined(BUILD_WOW64_ENABLED)
4358 if (IoIs32bitProcess(
Irp )) {
4380#
if defined(_WIN64) && defined(BUILD_WOW64_ENABLED)
4392 (
PVOID *)&FileToMarkBad,
4415 DeviceToMarkBad = FileToMarkBad->DeviceObject;
4425#pragma prefast( push )
4426#pragma prefast( disable: 28137, "prefast wants the wait to be a constant, but that isn't possible for the way fastfat is designed" )
4427#pragma prefast( disable: 28193, "this will always wait" )
4433#pragma prefast( pop )
4452 Links = Links->
Flink;
4473#pragma prefast( push )
4474#pragma prefast( disable: 28175, "touching Vpb is ok for a filesystem" )
4477 if (ExistingVcb->
Vpb == DeviceToMarkBad->Vpb) {
4487 NewVpb = ExistingVcb->
SwapVpb;
4497 DeviceToMarkBad->Vpb = NewVpb;
4503#pragma prefast( pop )
4534 FatPurgeReferencedFileObjects( &IrpContext,
4540 VcbDeleted = FatCheckForDismount( &IrpContext, ExistingVcb,
FALSE );
4558 DebugTrace(-1,
Dbg,
"FatInvalidateVolumes -> STATUS_SUCCESS\n", 0);
4631 Vcb->TargetDeviceObject,
4633 NumberOfBytesToRead,
4676 if (ReturnOnError) {
4700FatQueryRetrievalPointers (
4787 MappingPairs =
Irp->UserBuffer;
4793 FatAcquireExclusiveFcb( IrpContext,
Fcb );
4801 FatVerifyFcb( IrpContext,
Fcb );
4807 if ((*RequestedMapSize).QuadPart >
Fcb->
Header.FileSize.QuadPart) {
4821 RequestedMapSize->
LowPart - 1,
4842 MapSize = RequestedMapSize->
LowPart;
4853 (*MappingPairs)[
i*2 + 1 ].QuadPart =
Lbo;
4858 (*MappingPairs)[
i*2 + 0 ].QuadPart = 0;
4940 Buffer =
Irp->AssociatedIrp.SystemBuffer;
5036 ULONG TotalClusters;
5037 ULONG DesiredClusters;
5038 ULONG StartingCluster;
5039 ULONG EndingCluster;
5053 DebugTrace(+1,
Dbg,
"FatGetVolumeBitmap, FsControlCode = %08lx\n",
5101 TotalClusters =
Vcb->AllocationSupport.NumberOfClusters;
5136 StartingCluster = StartingLcn.
LowPart & ~7;
5146 DesiredClusters = TotalClusters - StartingCluster;
5180 if (
Vcb->NumberOfWindows == 1) {
5189 (
PUCHAR)
Vcb->FreeClusterBitMap.Buffer + StartingCluster/8,
5205 EndingCluster = StartingCluster + (
BytesToCopy * 8);
5211 if (EndingCluster > TotalClusters) {
5213 EndingCluster = TotalClusters;
5218 StartingCluster + 2,
5219 EndingCluster + 2 - 1,
5256FatGetRetrievalPointers (
5292 ULONG ClusterShift = 0;