reactos/drivers/filesystems/fastfat/fatprocs.h
Timo Kreuzer d9a287e9a5 [FASTFAT] Use debug bitmap
This is to figure out, whether the bitmap gets corrupted or if there is something else going on.
2024-09-14 20:15:07 +03:00

3111 lines
73 KiB
C

/*++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
FatProcs.h
Abstract:
This module defines all of the globally used procedures in the FAT
file system.
--*/
#ifndef _FATPROCS_
#define _FATPROCS_
#ifdef _MSC_VER
#pragma warning( disable: 4127 ) // conditional expression is constant
#pragma warning( push )
#pragma warning( disable: 4201 ) // nonstandard extension used : nameless struct/union
#pragma warning( disable: 4214 ) // nonstandard extension used : bit field types
#endif
#include <ntifs.h>
#include <ntddscsi.h>
#include <scsi.h>
#include <ntddcdrm.h>
#include <ntdddisk.h>
#include <ntddstor.h>
#include <ntintsafe.h>
#ifdef __REACTOS__
#include <pseh/pseh2.h>
#include <dbgbitmap.h>
#endif
#ifdef __REACTOS__
// Downgrade unsupported NT6.2+ features.
#undef MdlMappingNoExecute
#define MdlMappingNoExecute 0
#define NonPagedPoolNx NonPagedPool
#define NonPagedPoolNxCacheAligned NonPagedPoolCacheAligned
#undef POOL_NX_ALLOCATION
#define POOL_NX_ALLOCATION 0
// Moved up: needed in 'fatstruc.h'.
typedef enum _TYPE_OF_OPEN {
UnopenedFileObject = 1,
UserFileOpen,
UserDirectoryOpen,
UserVolumeOpen,
VirtualVolumeFile,
DirectoryFile,
EaFile,
} TYPE_OF_OPEN;
#endif
#include "nodetype.h"
#include "fat.h"
#include "lfn.h"
#include "fatstruc.h"
#include "fatdata.h"
#ifdef _MSC_VER
#pragma warning( pop )
#endif
#ifndef INLINE
#define INLINE __inline
#endif
#define Add2Ptr(P,I) ((PVOID)((PUCHAR)(P) + (I)))
#ifndef MAX_ULONG
#define MAX_ULONG ((ULONG)-1)
#endif
#ifndef MAX_USHORT
#define MAX_USHORT ((USHORT)-1)
#endif
//
// We must explicitly tag our allocations.
//
#undef FsRtlAllocatePool
#undef FsRtlAllocatePoolWithQuota
//
// A function that returns finished denotes if it was able to complete the
// operation (TRUE) or could not complete the operation (FALSE) because the
// wait value stored in the irp context was false and we would have had
// to block for a resource or I/O
//
typedef BOOLEAN FINISHED;
//
// Size (characters) of stack allocated name component buffers in
// the create/rename paths.
//
#define FAT_CREATE_INITIAL_NAME_BUF_SIZE 32
//
// Some string buffer handling functions, implemented in strucsup.c
//
VOID
FatFreeStringBuffer (
_Inout_ PVOID String
);
VOID
FatExtendString(
_Inout_ PVOID String,
_In_ USHORT DesiredBufferSize,
_In_ BOOLEAN FreeOldBuffer,
__out_opt PBOOLEAN NeedsFree
);
VOID
FatEnsureStringBufferEnough (
_Inout_ PVOID String,
_In_ USHORT DesiredBufferSize
);
BOOLEAN
FatAddMcbEntry (
IN PVCB Vcb,
IN PLARGE_MCB Mcb,
IN VBO Vbo,
IN LBO Lbo,
IN ULONG SectorCount
);
BOOLEAN
FatLookupMcbEntry (
IN PVCB Vcb,
IN PLARGE_MCB Mcb,
IN VBO Vbo,
OUT PLBO Lbo,
OUT PULONG ByteCount OPTIONAL,
OUT PULONG Index OPTIONAL
);
BOOLEAN
FatLookupLastMcbEntry (
IN PVCB Vcb,
IN PLARGE_MCB Mcb,
OUT PVBO Vbo,
OUT PLBO Lbo,
OUT PULONG Index OPTIONAL
);
BOOLEAN
FatGetNextMcbEntry (
IN PVCB Vcb,
IN PLARGE_MCB Mcb,
IN ULONG RunIndex,
OUT PVBO Vbo,
OUT PLBO Lbo,
OUT PULONG ByteCount
);
VOID
FatRemoveMcbEntry (
IN PVCB Vcb,
IN PLARGE_MCB Mcb,
IN VBO Vbo,
IN ULONG SectorCount
);
//
// File access check routine, implemented in AcChkSup.c
//
BOOLEAN
FatCheckFileAccess (
PIRP_CONTEXT IrpContext,
IN UCHAR DirentAttributes,
IN PACCESS_MASK DesiredAccess
);
BOOLEAN
FatCheckManageVolumeAccess (
_In_ PIRP_CONTEXT IrpContext,
_In_ PACCESS_STATE AccessState,
_In_ KPROCESSOR_MODE ProcessorMode
);
NTSTATUS
FatExplicitDeviceAccessGranted (
IN PIRP_CONTEXT IrpContext,
IN PDEVICE_OBJECT DeviceObject,
IN PACCESS_STATE AccessState,
IN KPROCESSOR_MODE ProcessorMode
);
//
// Allocation support routines, implemented in AllocSup.c
//
static
INLINE
BOOLEAN
FatIsIoRangeValid (
IN PVCB Vcb,
IN LARGE_INTEGER Start,
IN ULONG Length
)
/*++
Routine Description:
This routine enforces the restriction that object space must be
representable in 32 bits.
Arguments:
Vcb - the volume the range is on
Start - starting byte (zero based) of the range
Length - size of the range
HeaderSize - if the file has a header
Return Value:
BOOLEAN - if, considering the cluster size, the neccesary size of
the object to contain the range can be represented in 32 bits.
--*/
{
UNREFERENCED_PARAMETER( Vcb );
//
// The only restriction on a FAT object is that the filesize must
// fit in 32bits, i.e. <= 0xffffffff. This then implies that the
// range of valid byte offsets is [0, fffffffe].
//
// Two phases which check for illegality
//
// - if the high 32bits are nonzero
// - if the length would cause a 32bit overflow
//
return !(Start.HighPart ||
Start.LowPart + Length < Start.LowPart);
}
//
// This strucure is used by FatLookupFatEntry to remember a pinned page
// of fat.
//
typedef struct _FAT_ENUMERATION_CONTEXT {
VBO VboOfPinnedPage;
PBCB Bcb;
PVOID PinnedPage;
} FAT_ENUMERATION_CONTEXT, *PFAT_ENUMERATION_CONTEXT;
VOID
FatLookupFatEntry (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN ULONG FatIndex,
IN OUT PULONG FatEntry,
IN OUT PFAT_ENUMERATION_CONTEXT Context
);
VOID
FatSetupAllocationSupport (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb
);
VOID
FatTearDownAllocationSupport (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatLookupFileAllocation (
IN PIRP_CONTEXT IrpContext,
IN PFCB FcbOrDcb,
IN VBO Vbo,
OUT PLBO Lbo,
OUT PULONG ByteCount,
OUT PBOOLEAN Allocated,
OUT PBOOLEAN EndOnMax,
OUT PULONG Index OPTIONAL
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatAddFileAllocation (
IN PIRP_CONTEXT IrpContext,
IN PFCB FcbOrDcb,
IN PFILE_OBJECT FileObject OPTIONAL,
IN ULONG AllocationSize
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatTruncateFileAllocation (
IN PIRP_CONTEXT IrpContext,
IN PFCB FcbOrDcb,
IN ULONG AllocationSize
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatLookupFileAllocationSize (
IN PIRP_CONTEXT IrpContext,
IN PFCB FcbOrDcb
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatAllocateDiskSpace (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN ULONG AbsoluteClusterHint,
IN OUT PULONG ByteCount,
IN BOOLEAN ExactMatchRequired,
OUT PLARGE_MCB Mcb
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatDeallocateDiskSpace (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PLARGE_MCB Mcb,
IN BOOLEAN ZeroOnDeallocate
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatSplitAllocation (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN OUT PLARGE_MCB Mcb,
IN VBO SplitAtVbo,
OUT PLARGE_MCB RemainingMcb
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatMergeAllocation (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN OUT PLARGE_MCB Mcb,
IN PLARGE_MCB SecondMcb
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatSetFatEntry (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN ULONG FatIndex,
IN FAT_ENTRY FatEntry
);
UCHAR
FatLogOf(
IN ULONG Value
);
//
// Buffer control routines for data caching, implemented in CacheSup.c
//
VOID
FatReadVolumeFile (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN VBO StartingVbo,
IN ULONG ByteCount,
OUT PBCB *Bcb,
OUT PVOID *Buffer
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatPrepareWriteVolumeFile (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN VBO StartingVbo,
IN ULONG ByteCount,
OUT PBCB *Bcb,
OUT PVOID *Buffer,
IN BOOLEAN Reversible,
IN BOOLEAN Zero
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatReadDirectoryFile (
IN PIRP_CONTEXT IrpContext,
IN PDCB Dcb,
IN VBO StartingVbo,
IN ULONG ByteCount,
IN BOOLEAN Pin,
OUT PBCB *Bcb,
OUT PVOID *Buffer,
OUT PNTSTATUS Status
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatPrepareWriteDirectoryFile (
IN PIRP_CONTEXT IrpContext,
IN PDCB Dcb,
IN VBO StartingVbo,
IN ULONG ByteCount,
OUT PBCB *Bcb,
OUT PVOID *Buffer,
IN BOOLEAN Zero,
IN BOOLEAN Reversible,
OUT PNTSTATUS Status
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatOpenDirectoryFile (
IN PIRP_CONTEXT IrpContext,
IN PDCB Dcb
);
PFILE_OBJECT
FatOpenEaFile (
IN PIRP_CONTEXT IrpContext,
IN PFCB EaFcb
);
VOID
FatCloseEaFile (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN BOOLEAN FlushFirst
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatSetDirtyBcb (
IN PIRP_CONTEXT IrpContext,
IN PBCB Bcb,
IN PVCB Vcb OPTIONAL,
IN BOOLEAN Reversible
);
VOID
FatRepinBcb (
IN PIRP_CONTEXT IrpContext,
IN PBCB Bcb
);
VOID
FatUnpinRepinnedBcbs (
IN PIRP_CONTEXT IrpContext
);
FINISHED
FatZeroData (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFILE_OBJECT FileObject,
IN ULONG StartingZero,
IN ULONG ByteCount
);
NTSTATUS
FatCompleteMdl (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
VOID
FatPinMappedData (
IN PIRP_CONTEXT IrpContext,
IN PDCB Dcb,
IN VBO StartingVbo,
IN ULONG ByteCount,
OUT PBCB *Bcb
);
NTSTATUS
FatPrefetchPages (
IN PIRP_CONTEXT IrpContext,
IN PFILE_OBJECT FileObject,
IN ULONG StartingPage,
IN ULONG PageCount
);
//
// VOID
// FatUnpinBcb (
// IN PIRP_CONTEXT IrpContext,
// IN OUT PBCB Bcb,
// );
//
//
// This macro unpins a Bcb, in the checked build make sure all
// requests unpin all Bcbs before leaving.
//
#if DBG
#define FatUnpinBcb(IRPCONTEXT,BCB) { \
if ((BCB) != NULL) { \
CcUnpinData((BCB)); \
NT_ASSERT( (IRPCONTEXT)->PinCount );\
(IRPCONTEXT)->PinCount -= 1; \
(BCB) = NULL; \
} \
}
#else
#define FatUnpinBcb(IRPCONTEXT,BCB) { \
if ((BCB) != NULL) { \
CcUnpinData((BCB)); \
(BCB) = NULL; \
} \
}
#endif // DBG
VOID
FatInitializeCacheMap (
_In_ PFILE_OBJECT FileObject,
_In_ PCC_FILE_SIZES FileSizes,
_In_ BOOLEAN PinAccess,
_In_ PCACHE_MANAGER_CALLBACKS Callbacks,
_In_ PVOID LazyWriteContext
);
VOID
FatSyncUninitializeCacheMap (
IN PIRP_CONTEXT IrpContext,
IN PFILE_OBJECT FileObject
);
//
// Device I/O routines, implemented in DevIoSup.c
//
// These routines perform the actual device read and writes. They only affect
// the on disk structure and do not alter any other data structures.
//
VOID
FatPagingFileIo (
IN PIRP Irp,
IN PFCB Fcb
);
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatNonCachedIo (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp,
IN PFCB FcbOrDcb,
IN ULONG StartingVbo,
IN ULONG ByteCount,
IN ULONG UserByteCount,
IN ULONG StreamFlags
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatNonCachedNonAlignedRead (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp,
IN PFCB FcbOrDcb,
IN ULONG StartingVbo,
IN ULONG ByteCount
);
VOID
FatMultipleAsync (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PIRP Irp,
IN ULONG MultipleIrpCount,
IN PIO_RUN IoRuns
);
VOID
FatSingleAsync (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN LBO Lbo,
IN ULONG ByteCount,
IN PIRP Irp
);
VOID
FatWaitSync (
IN PIRP_CONTEXT IrpContext
);
VOID
FatLockUserBuffer (
IN PIRP_CONTEXT IrpContext,
IN OUT PIRP Irp,
IN LOCK_OPERATION Operation,
IN ULONG BufferLength
);
PVOID
FatBufferUserBuffer (
IN PIRP_CONTEXT IrpContext,
IN OUT PIRP Irp,
IN ULONG BufferLength
);
PVOID
FatMapUserBuffer (
IN PIRP_CONTEXT IrpContext,
IN OUT PIRP Irp
);
NTSTATUS
FatToggleMediaEjectDisable (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN BOOLEAN PreventRemoval
);
NTSTATUS
FatPerformDevIoCtrl (
IN PIRP_CONTEXT IrpContext,
IN ULONG IoControlCode,
IN PDEVICE_OBJECT Device,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer OPTIONAL,
IN ULONG OutputBufferLength,
IN BOOLEAN InternalDeviceIoControl,
IN BOOLEAN OverrideVerify,
OUT PIO_STATUS_BLOCK Iosb OPTIONAL
);
PMDL
FatBuildZeroMdl (
__in PIRP_CONTEXT IrpContext,
__in ULONG Length
);
//
// Dirent support routines, implemented in DirSup.c
//
//
// Tunneling is a deletion precursor (all tunneling cases do
// not involve deleting dirents, however)
//
VOID
FatTunnelFcbOrDcb (
IN PFCB FcbOrDcb,
IN PCCB Ccb OPTIONAL
);
_Requires_lock_held_(_Global_critical_region_)
ULONG
FatCreateNewDirent (
IN PIRP_CONTEXT IrpContext,
IN PDCB ParentDirectory,
IN ULONG DirentsNeeded,
IN BOOLEAN RescanDir
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatInitializeDirectoryDirent (
IN PIRP_CONTEXT IrpContext,
IN PDCB Dcb,
IN PDIRENT ParentDirent
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatDeleteDirent (
IN PIRP_CONTEXT IrpContext,
IN PFCB FcbOrDcb,
IN PDELETE_CONTEXT DeleteContext OPTIONAL,
IN BOOLEAN DeleteEa
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatLocateDirent (
IN PIRP_CONTEXT IrpContext,
IN PDCB ParentDirectory,
IN PCCB Ccb,
IN VBO OffsetToStartSearchFrom,
IN OUT PULONG Flags,
OUT PDIRENT *Dirent,
OUT PBCB *Bcb,
OUT PVBO ByteOffset,
OUT PBOOLEAN FileNameDos OPTIONAL,
IN OUT PUNICODE_STRING Lfn OPTIONAL,
IN OUT PUNICODE_STRING OrigLfn OPTIONAL
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatLocateSimpleOemDirent (
IN PIRP_CONTEXT IrpContext,
IN PDCB ParentDirectory,
IN POEM_STRING FileName,
OUT PDIRENT *Dirent,
OUT PBCB *Bcb,
OUT PVBO ByteOffset
);
_Requires_lock_held_(_Global_critical_region_)
BOOLEAN
FatLfnDirentExists (
IN PIRP_CONTEXT IrpContext,
IN PDCB Dcb,
IN PUNICODE_STRING Lfn,
IN PUNICODE_STRING LfnTmp
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatLocateVolumeLabel (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
OUT PDIRENT *Dirent,
OUT PBCB *Bcb,
OUT PVBO ByteOffset
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatGetDirentFromFcbOrDcb (
IN PIRP_CONTEXT IrpContext,
IN PFCB FcbOrDcb,
IN BOOLEAN ReturnOnFailure,
OUT PDIRENT *Dirent,
OUT PBCB *Bcb
);
_Requires_lock_held_(_Global_critical_region_)
BOOLEAN
FatIsDirectoryEmpty (
IN PIRP_CONTEXT IrpContext,
IN PDCB Dcb
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatDeleteFile (
IN PIRP_CONTEXT IrpContext,
IN PDCB TargetDcb,
IN ULONG LfnOffset,
IN ULONG DirentOffset,
IN PDIRENT Dirent,
IN PUNICODE_STRING Lfn
);
VOID
FatConstructDirent (
IN PIRP_CONTEXT IrpContext,
IN OUT PDIRENT Dirent,
IN POEM_STRING FileName,
IN BOOLEAN ComponentReallyLowercase,
IN BOOLEAN ExtensionReallyLowercase,
IN PUNICODE_STRING Lfn OPTIONAL,
IN USHORT Attributes,
IN BOOLEAN ZeroAndSetTimeFields,
IN PLARGE_INTEGER SetCreationTime OPTIONAL
);
VOID
FatConstructLabelDirent (
IN PIRP_CONTEXT IrpContext,
IN OUT PDIRENT Dirent,
IN POEM_STRING Label
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatSetFileSizeInDirent (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN PULONG AlternativeFileSize OPTIONAL
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatSetFileSizeInDirentNoRaise (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN PULONG AlternativeFileSize OPTIONAL
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatUpdateDirentFromFcb (
IN PIRP_CONTEXT IrpContext,
IN PFILE_OBJECT FileObject,
IN PFCB FcbOrDcb,
IN PCCB Ccb
);
//
// Generate a relatively unique static 64bit ID from a FAT Fcb/Dcb
//
// ULONGLONG
// FatDirectoryKey (FcbOrDcb);
//
#define FatDirectoryKey(FcbOrDcb) ((ULONGLONG)((FcbOrDcb)->CreationTime.QuadPart ^ (FcbOrDcb)->FirstClusterOfFile))
//
// The following routines are used to access and manipulate the
// clusters containing EA data in the ea data file. They are
// implemented in EaSup.c
//
//
// VOID
// FatUpcaseEaName (
// IN PIRP_CONTEXT IrpContext,
// IN POEM_STRING EaName,
// OUT POEM_STRING UpcasedEaName
// );
//
#define FatUpcaseEaName( IRPCONTEXT, NAME, UPCASEDNAME ) \
RtlUpperString( UPCASEDNAME, NAME )
_Requires_lock_held_(_Global_critical_region_)
VOID
FatGetEaLength (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PDIRENT Dirent,
OUT PULONG EaLength
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatGetNeedEaCount (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PDIRENT Dirent,
OUT PULONG NeedEaCount
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatCreateEa (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PUCHAR Buffer,
IN ULONG Length,
IN POEM_STRING FileName,
OUT PUSHORT EaHandle
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatDeleteEa (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN USHORT EaHandle,
IN POEM_STRING FileName
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatGetEaFile (
IN PIRP_CONTEXT IrpContext,
IN OUT PVCB Vcb,
OUT PDIRENT *EaDirent,
OUT PBCB *EaBcb,
IN BOOLEAN CreateFile,
IN BOOLEAN ExclusiveFcb
);
VOID
FatReadEaSet (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN USHORT EaHandle,
IN POEM_STRING FileName,
IN BOOLEAN ReturnEntireSet,
OUT PEA_RANGE EaSetRange
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatDeleteEaSet (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PBCB EaBcb,
OUT PDIRENT EaDirent,
IN USHORT EaHandle,
IN POEM_STRING Filename
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatAddEaSet (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN ULONG EaSetLength,
IN PBCB EaBcb,
OUT PDIRENT EaDirent,
OUT PUSHORT EaHandle,
OUT PEA_RANGE EaSetRange
);
VOID
FatDeletePackedEa (
IN PIRP_CONTEXT IrpContext,
IN OUT PEA_SET_HEADER EaSetHeader,
IN OUT PULONG PackedEasLength,
IN ULONG Offset
);
VOID
FatAppendPackedEa (
IN PIRP_CONTEXT IrpContext,
IN OUT PEA_SET_HEADER *EaSetHeader,
IN OUT PULONG PackedEasLength,
IN OUT PULONG AllocationLength,
IN PFILE_FULL_EA_INFORMATION FullEa,
IN ULONG BytesPerCluster
);
ULONG
FatLocateNextEa (
IN PIRP_CONTEXT IrpContext,
IN PPACKED_EA FirstPackedEa,
IN ULONG PackedEasLength,
IN ULONG PreviousOffset
);
BOOLEAN
FatLocateEaByName (
IN PIRP_CONTEXT IrpContext,
IN PPACKED_EA FirstPackedEa,
IN ULONG PackedEasLength,
IN POEM_STRING EaName,
OUT PULONG Offset
);
BOOLEAN
FatIsEaNameValid (
IN PIRP_CONTEXT IrpContext,
IN OEM_STRING Name
);
VOID
FatPinEaRange (
IN PIRP_CONTEXT IrpContext,
IN PFILE_OBJECT VirtualEaFile,
IN PFCB EaFcb,
IN OUT PEA_RANGE EaRange,
IN ULONG StartingVbo,
IN ULONG Length,
IN NTSTATUS ErrorStatus
);
VOID
FatMarkEaRangeDirty (
IN PIRP_CONTEXT IrpContext,
IN PFILE_OBJECT EaFileObject,
IN OUT PEA_RANGE EaRange
);
VOID
FatUnpinEaRange (
IN PIRP_CONTEXT IrpContext,
IN OUT PEA_RANGE EaRange
);
//
// The following macro computes the size of a full ea (not including
// padding to bring it to a longword. A full ea has a 4 byte offset,
// folowed by 1 byte flag, 1 byte name length, 2 bytes value length,
// the name, 1 null byte, and the value.
//
// ULONG
// SizeOfFullEa (
// IN PFILE_FULL_EA_INFORMATION FullEa
// );
//
#define SizeOfFullEa(EA) (4+1+1+2+(EA)->EaNameLength+1+(EA)->EaValueLength)
//
// The following routines are used to manipulate the fscontext fields
// of the file object, implemented in FilObSup.c
//
#ifndef __REACTOS__
typedef enum _TYPE_OF_OPEN {
UnopenedFileObject = 1,
UserFileOpen,
UserDirectoryOpen,
UserVolumeOpen,
VirtualVolumeFile,
DirectoryFile,
EaFile,
} TYPE_OF_OPEN;
#endif
typedef enum _FAT_FLUSH_TYPE {
NoFlush = 0,
Flush,
FlushAndInvalidate,
FlushWithoutPurge
} FAT_FLUSH_TYPE;
VOID
FatSetFileObject (
IN PFILE_OBJECT FileObject OPTIONAL,
IN TYPE_OF_OPEN TypeOfOpen,
IN PVOID VcbOrFcbOrDcb,
IN PCCB Ccb OPTIONAL
);
TYPE_OF_OPEN
FatDecodeFileObject (
_In_ PFILE_OBJECT FileObject,
_Outptr_ PVCB *Vcb,
_Outptr_ PFCB *FcbOrDcb,
_Outptr_ PCCB *Ccb
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatPurgeReferencedFileObjects (
IN PIRP_CONTEXT IrpContext,
IN PFCB FcbOrDcb,
IN FAT_FLUSH_TYPE FlushType
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatForceCacheMiss (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN FAT_FLUSH_TYPE FlushType
);
//
// File system control routines, implemented in FsCtrl.c
//
_Requires_lock_held_(_Global_critical_region_)
VOID
FatFlushAndCleanVolume(
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp,
IN PVCB Vcb,
IN FAT_FLUSH_TYPE FlushType
);
BOOLEAN
FatIsBootSectorFat (
IN PPACKED_BOOT_SECTOR BootSector
);
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatLockVolumeInternal (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFILE_OBJECT FileObject OPTIONAL
);
NTSTATUS
FatUnlockVolumeInternal (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFILE_OBJECT FileObject OPTIONAL
);
//
// Name support routines, implemented in NameSup.c
//
//
// BOOLEAN
// FatAreNamesEqual (
// IN PIRP_CONTEXT IrpContext,
// IN OEM_STRING ConstantNameA,
// IN OEM_STRING ConstantNameB
// )
//
// /*++
//
// Routine Description:
//
// This routine simple returns whether the two names are exactly equal.
// If the two names are known to be constant, this routine is much
// faster than FatIsDbcsInExpression.
//
// Arguments:
//
// ConstantNameA - Constant name.
//
// ConstantNameB - Constant name.
//
// Return Value:
//
// BOOLEAN - TRUE if the two names are lexically equal.
//
#define FatAreNamesEqual(IRPCONTEXT,NAMEA,NAMEB) ( \
((ULONG)(NAMEA).Length == (ULONG)(NAMEB).Length) && \
(RtlEqualMemory( &(NAMEA).Buffer[0], \
&(NAMEB).Buffer[0], \
(NAMEA).Length )) \
)
//
// BOOLEAN
// FatIsNameShortOemValid (
// IN PIRP_CONTEXT IrpContext,
// IN OEM_STRING Name,
// IN BOOLEAN CanContainWildCards,
// IN BOOLEAN PathNamePermissible,
// IN BOOLEAN LeadingBackslashPermissible
// )
//
// /*++
//
// Routine Description:
//
// This routine scans the input name and verifies that if only
// contains valid characters
//
// Arguments:
//
// Name - Supplies the input name to check.
//
// CanContainWildCards - Indicates if the name can contain wild cards
// (i.e., * and ?).
//
// Return Value:
//
// BOOLEAN - Returns TRUE if the name is valid and FALSE otherwise.
//
// --*/
//
// The FatIsNameLongOemValid and FatIsNameLongUnicodeValid are similar.
//
#define FatIsNameShortOemValid(IRPCONTEXT,NAME,CAN_CONTAIN_WILD_CARDS,PATH_NAME_OK,LEADING_BACKSLASH_OK) ( \
FsRtlIsFatDbcsLegal((NAME), \
(CAN_CONTAIN_WILD_CARDS), \
(PATH_NAME_OK), \
(LEADING_BACKSLASH_OK)) \
)
#define FatIsNameLongOemValid(IRPCONTEXT,NAME,CAN_CONTAIN_WILD_CARDS,PATH_NAME_OK,LEADING_BACKSLASH_OK) ( \
FsRtlIsHpfsDbcsLegal((NAME), \
(CAN_CONTAIN_WILD_CARDS), \
(PATH_NAME_OK), \
(LEADING_BACKSLASH_OK)) \
)
static
INLINE
BOOLEAN
FatIsNameLongUnicodeValid (
PIRP_CONTEXT IrpContext,
PUNICODE_STRING Name,
BOOLEAN CanContainWildcards,
BOOLEAN PathNameOk,
BOOLEAN LeadingBackslashOk
)
{
ULONG i;
UNREFERENCED_PARAMETER( IrpContext );
UNREFERENCED_PARAMETER( LeadingBackslashOk );
UNREFERENCED_PARAMETER( PathNameOk );
//
// I'm not bothering to do the whole thing, just enough to make this call look
// the same as the others.
//
NT_ASSERT( !PathNameOk && !LeadingBackslashOk );
for (i=0; i < Name->Length/sizeof(WCHAR); i++) {
if ((Name->Buffer[i] < 0x80) &&
!(FsRtlIsAnsiCharacterLegalHpfs(Name->Buffer[i], CanContainWildcards))) {
return FALSE;
}
}
return TRUE;
}
BOOLEAN
FatIsNameInExpression (
IN PIRP_CONTEXT IrpContext,
IN OEM_STRING Expression,
IN OEM_STRING Name
);
VOID
FatStringTo8dot3 (
_In_ PIRP_CONTEXT IrpContext,
_In_ OEM_STRING InputString,
_Out_writes_bytes_(11) PFAT8DOT3 Output8dot3
);
VOID
Fat8dot3ToString (
_In_ PIRP_CONTEXT IrpContext,
_In_ PDIRENT Dirent,
_In_ BOOLEAN RestoreCase,
_Out_ POEM_STRING OutputString
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatGetUnicodeNameFromFcb (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN OUT PUNICODE_STRING Lfn
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatSetFullFileNameInFcb (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb
);
VOID
FatSetFullNameInFcb (
_In_ PIRP_CONTEXT IrpContext,
_Inout_ PFCB Fcb,
_In_ PUNICODE_STRING FinalName
);
VOID
FatUnicodeToUpcaseOem (
IN PIRP_CONTEXT IrpContext,
IN POEM_STRING OemString,
IN PUNICODE_STRING UnicodeString
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatSelectNames (
IN PIRP_CONTEXT IrpContext,
IN PDCB Parent,
IN POEM_STRING OemName,
IN PUNICODE_STRING UnicodeName,
IN OUT POEM_STRING ShortName,
IN PUNICODE_STRING SuggestedShortName OPTIONAL,
IN OUT BOOLEAN *AllLowerComponent,
IN OUT BOOLEAN *AllLowerExtension,
IN OUT BOOLEAN *CreateLfn
);
VOID
FatEvaluateNameCase (
IN PIRP_CONTEXT IrpContext,
IN PUNICODE_STRING Name,
IN OUT BOOLEAN *AllLowerComponent,
IN OUT BOOLEAN *AllLowerExtension,
IN OUT BOOLEAN *CreateLfn
);
BOOLEAN
FatSpaceInName (
IN PIRP_CONTEXT IrpContext,
IN PUNICODE_STRING UnicodeName
);
VOID
FatUnicodeRestoreShortNameCase(
IN PUNICODE_STRING ShortNameWithCase,
IN BOOLEAN LowerCase8,
IN BOOLEAN LowerCase3
);
//
// Resources support routines/macros, implemented in ResrcSup.c
//
// The following routines/macros are used for gaining shared and exclusive
// access to the global/vcb data structures. The routines are implemented
// in ResrcSup.c. There is a global resources that everyone tries to take
// out shared to do their work, with the exception of mount/dismount which
// take out the global resource exclusive. All other resources only work
// on their individual item. For example, an Fcb resource does not take out
// a Vcb resource. But the way the file system is structured we know
// that when we are processing an Fcb other threads cannot be trying to remove
// or alter the Fcb, so we do not need to acquire the Vcb.
//
// The procedures/macros are:
//
// Macro FatData Vcb Fcb Subsequent macros
//
// AcquireExclusiveGlobal Read/Write None None ReleaseGlobal
//
// AcquireSharedGlobal Read None None ReleaseGlobal
//
// AcquireExclusiveVcb Read Read/Write None ReleaseVcb
//
// AcquireSharedVcb Read Read None ReleaseVcb
//
// AcquireExclusiveFcb Read None Read/Write ConvertToSharFcb
// ReleaseFcb
//
// AcquireSharedFcb Read None Read ReleaseFcb
//
// ConvertToSharedFcb Read None Read ReleaseFcb
//
// ReleaseGlobal
//
// ReleaseVcb
//
// ReleaseFcb
//
//
// FINISHED
// FatAcquireExclusiveGlobal (
// IN PIRP_CONTEXT IrpContext
// );
//
// FINISHED
// FatAcquireSharedGlobal (
// IN PIRP_CONTEXT IrpContext
// );
//
#define FatAcquireExclusiveGlobal(IRPCONTEXT) ( \
ExAcquireResourceExclusiveLite( &FatData.Resource, BooleanFlagOn((IRPCONTEXT)->Flags, IRP_CONTEXT_FLAG_WAIT) ) \
)
#define FatAcquireSharedGlobal(IRPCONTEXT) ( \
ExAcquireResourceSharedLite( &FatData.Resource, BooleanFlagOn((IRPCONTEXT)->Flags, IRP_CONTEXT_FLAG_WAIT) ) \
)
//
// The following macro must only be called when Wait is TRUE!
//
// FatAcquireExclusiveVolume (
// IN PIRP_CONTEXT IrpContext,
// IN PVCB Vcb
// );
//
// FatReleaseVolume (
// IN PIRP_CONTEXT IrpContext,
// IN PVCB Vcb
// );
//
#define FatAcquireExclusiveVolume(IRPCONTEXT,VCB) { \
PFCB __FFFFFcb = NULL; \
NT_ASSERT(FlagOn((IRPCONTEXT)->Flags, IRP_CONTEXT_FLAG_WAIT)); \
(VOID)FatAcquireExclusiveVcb( (IRPCONTEXT), (VCB) ); \
while ( (__FFFFFcb = FatGetNextFcbBottomUp((IRPCONTEXT), __FFFFFcb, (VCB)->RootDcb)) != NULL) { \
(VOID)FatAcquireExclusiveFcb((IRPCONTEXT), __FFFFFcb ); \
} \
}
#define FatReleaseVolume(IRPCONTEXT,VCB) { \
PFCB __FFFFFcb = NULL; \
NT_ASSERT(FlagOn((IRPCONTEXT)->Flags, IRP_CONTEXT_FLAG_WAIT)); \
while ( (__FFFFFcb = FatGetNextFcbBottomUp((IRPCONTEXT), __FFFFFcb, (VCB)->RootDcb)) != NULL) { \
(VOID)ExReleaseResourceLite( __FFFFFcb->Header.Resource ); \
} \
FatReleaseVcb((IRPCONTEXT), (VCB)); \
}
//
// Macro to enable easy tracking of Vcb state transitions.
//
#ifdef FASTFATDBG
#define FatSetVcbCondition( V, X) { \
DebugTrace(0,DEBUG_TRACE_VERFYSUP,"%d -> ",(V)->VcbCondition); \
DebugTrace(0,DEBUG_TRACE_VERFYSUP,"%x\n",(X)); \
(V)->VcbCondition = (X); \
}
#else
#define FatSetVcbCondition( V, X) (V)->VcbCondition = (X)
#endif
//
// These macros can be used to determine what kind of FAT we have for an
// initialized Vcb. It is somewhat more elegant to use these (visually).
//
#define FatIsFat32(VCB) ((BOOLEAN)((VCB)->AllocationSupport.FatIndexBitSize == 32))
#define FatIsFat16(VCB) ((BOOLEAN)((VCB)->AllocationSupport.FatIndexBitSize == 16))
#define FatIsFat12(VCB) ((BOOLEAN)((VCB)->AllocationSupport.FatIndexBitSize == 12))
_Requires_lock_held_(_Global_critical_region_)
_When_(return != FALSE && NoOpCheck != FALSE, _Acquires_exclusive_lock_(Vcb->Resource))
FINISHED
FatAcquireExclusiveVcb_Real (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN BOOLEAN NoOpCheck
);
#define FatAcquireExclusiveVcb( IC, V) FatAcquireExclusiveVcb_Real( IC, V, FALSE)
#define FatAcquireExclusiveVcbNoOpCheck( IC, V) FatAcquireExclusiveVcb_Real( IC, V, TRUE)
_Requires_lock_held_(_Global_critical_region_)
_When_(return != 0, _Acquires_shared_lock_(Vcb->Resource))
FINISHED
FatAcquireSharedVcb (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb
);
_Requires_lock_held_(_Global_critical_region_)
_Acquires_exclusive_lock_(*Fcb->Header.Resource)
FINISHED
FatAcquireExclusiveFcb (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb
);
_Requires_lock_held_(_Global_critical_region_)
_Acquires_shared_lock_(*Fcb->Header.Resource)
FINISHED
FatAcquireSharedFcb (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb
);
_Requires_lock_held_(_Global_critical_region_)
_When_(return != 0, _Acquires_shared_lock_(*Fcb->Header.Resource))
FINISHED
FatAcquireSharedFcbWaitForEx (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb
);
#define FatVcbAcquiredExclusive(IRPCONTEXT,VCB) ( \
ExIsResourceAcquiredExclusiveLite(&(VCB)->Resource) || \
ExIsResourceAcquiredExclusiveLite(&FatData.Resource) \
)
#define FatFcbAcquiredShared(IRPCONTEXT,FCB) ( \
ExIsResourceAcquiredSharedLite((FCB)->Header.Resource) \
)
#define FatFcbAcquiredExclusive(IRPCONTEXT,FCB) ( \
ExIsResourceAcquiredExclusiveLite((FCB)->Header.Resource) \
)
#define FatAcquireDirectoryFileMutex(VCB) { \
NT_ASSERT(KeAreApcsDisabled()); \
ExAcquireFastMutexUnsafe(&(VCB)->DirectoryFileCreationMutex); \
}
#define FatReleaseDirectoryFileMutex(VCB) { \
NT_ASSERT(KeAreApcsDisabled()); \
ExReleaseFastMutexUnsafe(&(VCB)->DirectoryFileCreationMutex); \
}
//
// The following are cache manager call backs
BOOLEAN
FatAcquireVolumeForClose (
IN PVOID Vcb,
IN BOOLEAN Wait
);
VOID
FatReleaseVolumeFromClose (
IN PVOID Vcb
);
_Requires_lock_held_(_Global_critical_region_)
BOOLEAN
NTAPI
FatAcquireFcbForLazyWrite (
IN PVOID Null,
IN BOOLEAN Wait
);
_Requires_lock_held_(_Global_critical_region_)
VOID
NTAPI
FatReleaseFcbFromLazyWrite (
IN PVOID Null
);
_Requires_lock_held_(_Global_critical_region_)
BOOLEAN
NTAPI
FatAcquireFcbForReadAhead (
IN PVOID Null,
IN BOOLEAN Wait
);
_Requires_lock_held_(_Global_critical_region_)
VOID
NTAPI
FatReleaseFcbFromReadAhead (
IN PVOID Null
);
_Function_class_(FAST_IO_ACQUIRE_FOR_CCFLUSH)
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
NTAPI
FatAcquireForCcFlush (
IN PFILE_OBJECT FileObject,
IN PDEVICE_OBJECT DeviceObject
);
_Function_class_(FAST_IO_RELEASE_FOR_CCFLUSH)
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
NTAPI
FatReleaseForCcFlush (
IN PFILE_OBJECT FileObject,
IN PDEVICE_OBJECT DeviceObject
);
BOOLEAN
NTAPI
FatNoOpAcquire (
IN PVOID Fcb,
IN BOOLEAN Wait
);
VOID
NTAPI
FatNoOpRelease (
IN PVOID Fcb
);
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
NTAPI
FatFilterCallbackAcquireForCreateSection (
IN PFS_FILTER_CALLBACK_DATA CallbackData,
OUT PVOID *CompletionContext
);
//
// VOID
// FatConvertToSharedFcb (
// IN PIRP_CONTEXT IrpContext,
// IN PFCB Fcb
// );
//
#define FatConvertToSharedFcb(IRPCONTEXT,Fcb) { \
ExConvertExclusiveToSharedLite( (Fcb)->Header.Resource ); \
}
//
// VOID
// FatReleaseGlobal (
// IN PIRP_CONTEXT IrpContext
// );
//
// VOID
// FatReleaseVcb (
// IN PIRP_CONTEXT IrpContext,
// IN PVCB Vcb
// );
//
// VOID
// FatReleaseFcb (
// IN PIRP_CONTEXT IrpContext,
// IN PVCB Vcb
// );
//
#define FatDeleteResource(RESRC) { \
ExDeleteResourceLite( (RESRC) ); \
}
#define FatReleaseGlobal(IRPCONTEXT) { \
ExReleaseResourceLite( &(FatData.Resource) ); \
}
#define FatReleaseVcb(IRPCONTEXT,Vcb) { \
ExReleaseResourceLite( &((Vcb)->Resource) ); \
}
#define FatReleaseFcb(IRPCONTEXT,Fcb) { \
ExReleaseResourceLite( (Fcb)->Header.Resource ); \
}
//
// The following macro is used to retrieve the oplock structure within
// the Fcb. This structure was moved to the advanced Fcb header
// in Win8.
//
#if (NTDDI_VERSION >= NTDDI_WIN8)
#define FatGetFcbOplock(F) &(F)->Header.Oplock
#else
#define FatGetFcbOplock(F) &(F)->Specific.Fcb.Oplock
#endif
//
// In-memory structure support routine, implemented in StrucSup.c
//
_Requires_lock_held_(_Global_critical_region_)
VOID
FatInitializeVcb (
IN PIRP_CONTEXT IrpContext,
IN OUT PVCB Vcb,
IN PDEVICE_OBJECT TargetDeviceObject,
IN PVPB Vpb,
IN PDEVICE_OBJECT FsDeviceObject
);
VOID
FatTearDownVcb (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb
);
VOID
FatDeleteVcb (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatCreateRootDcb (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb
);
PFCB
FatCreateFcb (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PDCB ParentDcb,
IN ULONG LfnOffsetWithinDirectory,
IN ULONG DirentOffsetWithinDirectory,
IN PDIRENT Dirent,
IN PUNICODE_STRING Lfn OPTIONAL,
IN PUNICODE_STRING OrigLfn OPTIONAL,
IN BOOLEAN IsPagingFile,
IN BOOLEAN SingleResource
);
PDCB
FatCreateDcb (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PDCB ParentDcb,
IN ULONG LfnOffsetWithinDirectory,
IN ULONG DirentOffsetWithinDirectory,
IN PDIRENT Dirent,
IN PUNICODE_STRING Lfn OPTIONAL
);
VOID
FatDeleteFcb (
IN PIRP_CONTEXT IrpContext,
IN PFCB *Fcb
);
PCCB
FatCreateCcb (
IN PIRP_CONTEXT IrpContext
);
VOID
FatDeallocateCcbStrings(
IN PCCB Ccb
);
VOID
FatDeleteCcb (
IN PIRP_CONTEXT IrpContext,
IN PCCB *Ccb
);
PIRP_CONTEXT
FatCreateIrpContext (
IN PIRP Irp,
IN BOOLEAN Wait
);
VOID
FatDeleteIrpContext_Real (
IN PIRP_CONTEXT IrpContext
);
#ifdef FASTFATDBG
#define FatDeleteIrpContext(IRPCONTEXT) { \
FatDeleteIrpContext_Real((IRPCONTEXT)); \
(IRPCONTEXT) = NULL; \
}
#else
#define FatDeleteIrpContext(IRPCONTEXT) { \
FatDeleteIrpContext_Real((IRPCONTEXT)); \
}
#endif // FASTFAT_DBG
PFCB
FatGetNextFcbTopDown (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN PFCB TerminationFcb
);
PFCB
FatGetNextFcbBottomUp (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN PFCB TerminationFcb
);
//
// These two macros just make the code a bit cleaner.
//
#define FatGetFirstChild(DIR) ((PFCB)( \
IsListEmpty(&(DIR)->Specific.Dcb.ParentDcbQueue) ? NULL : \
CONTAINING_RECORD((DIR)->Specific.Dcb.ParentDcbQueue.Flink, \
DCB, \
ParentDcbLinks.Flink)))
#define FatGetNextSibling(FILE) ((PFCB)( \
&(FILE)->ParentDcb->Specific.Dcb.ParentDcbQueue.Flink == \
(PVOID)(FILE)->ParentDcbLinks.Flink ? NULL : \
CONTAINING_RECORD((FILE)->ParentDcbLinks.Flink, \
FCB, \
ParentDcbLinks.Flink)))
_Requires_lock_held_(_Global_critical_region_)
BOOLEAN
FatCheckForDismount (
IN PIRP_CONTEXT IrpContext,
PVCB Vcb,
IN BOOLEAN Force
);
VOID
FatConstructNamesInFcb (
IN PIRP_CONTEXT IrpContext,
PFCB Fcb,
PDIRENT Dirent,
PUNICODE_STRING Lfn OPTIONAL
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatCheckFreeDirentBitmap (
IN PIRP_CONTEXT IrpContext,
IN PDCB Dcb
);
ULONG
FatVolumeUncleanCount (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb
);
VOID
FatPreallocateCloseContext (
IN PVCB Vcb
);
PCLOSE_CONTEXT
FatAllocateCloseContext(
IN PVCB Vcb
);
//
// BOOLEAN
// FatIsRawDevice (
// IN PIRP_CONTEXT IrpContext,
// IN NTSTATUS Status
// );
//
#define FatIsRawDevice(IC,S) ( \
((S) == STATUS_DEVICE_NOT_READY) || \
((S) == STATUS_NO_MEDIA_IN_DEVICE) \
)
//
// Routines to support managing file names Fcbs and Dcbs.
// Implemented in SplaySup.c
//
VOID
FatInsertName (
IN PIRP_CONTEXT IrpContext,
IN PRTL_SPLAY_LINKS *RootNode,
IN PFILE_NAME_NODE Name
);
VOID
FatRemoveNames (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb
);
PFCB
FatFindFcb (
IN PIRP_CONTEXT IrpContext,
IN OUT PRTL_SPLAY_LINKS *RootNode,
IN PSTRING Name,
OUT PBOOLEAN FileNameDos OPTIONAL
);
BOOLEAN
FatIsHandleCountZero (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb
);
typedef enum _COMPARISON {
IsLessThan,
IsGreaterThan,
IsEqual
} COMPARISON;
COMPARISON
FatCompareNames (
IN PSTRING NameA,
IN PSTRING NameB
);
//
// Do a macro here to check for a common case.
//
#define CompareNames(NAMEA,NAMEB) ( \
*(PUCHAR)(NAMEA)->Buffer != *(PUCHAR)(NAMEB)->Buffer ? \
*(PUCHAR)(NAMEA)->Buffer < *(PUCHAR)(NAMEB)->Buffer ? \
IsLessThan : IsGreaterThan : \
FatCompareNames((PSTRING)(NAMEA), (PSTRING)(NAMEB)) \
)
//
// Time conversion support routines, implemented in TimeSup.c
//
_Success_(return != FALSE)
BOOLEAN
FatNtTimeToFatTime (
_In_ PIRP_CONTEXT IrpContext,
_In_ PLARGE_INTEGER NtTime,
_In_ BOOLEAN Rounding,
_Out_ PFAT_TIME_STAMP FatTime,
_Out_opt_ PUCHAR TenMsecs
);
LARGE_INTEGER
FatFatTimeToNtTime (
_In_ PIRP_CONTEXT IrpContext,
_In_ FAT_TIME_STAMP FatTime,
_In_ UCHAR TenMilliSeconds
);
LARGE_INTEGER
FatFatDateToNtTime (
_In_ PIRP_CONTEXT IrpContext,
_In_ FAT_DATE FatDate
);
FAT_TIME_STAMP
FatGetCurrentFatTime (
_In_ PIRP_CONTEXT IrpContext
);
//
// Low level verification routines, implemented in VerfySup.c
//
// The first routine is called to help process a verify IRP. Its job is
// to walk every Fcb/Dcb and mark them as need to be verified.
//
// The other routines are used by every dispatch routine to verify that
// an Vcb/Fcb/Dcb is still good. The routine walks as much of the opened
// file/directory tree as necessary to make sure that the path is still valid.
// The function result indicates if the procedure needed to block for I/O.
// If the structure is bad the procedure raise the error condition
// STATUS_FILE_INVALID, otherwise they simply return to their caller
//
typedef enum _FAT_VOLUME_STATE {
VolumeClean,
VolumeDirty,
VolumeDirtyWithSurfaceTest
} FAT_VOLUME_STATE, *PFAT_VOLUME_STATE;
VOID
FatMarkFcbCondition (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN FCB_CONDITION FcbCondition,
IN BOOLEAN Recursive
);
VOID
FatVerifyVcb (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatVerifyFcb (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb
);
KDEFERRED_ROUTINE FatCleanVolumeDpc;
VOID
NTAPI
FatCleanVolumeDpc (
_In_ PKDPC Dpc,
_In_opt_ PVOID DeferredContext,
_In_opt_ PVOID SystemArgument1,
_In_opt_ PVOID SystemArgument2
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatMarkVolume (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN FAT_VOLUME_STATE VolumeState
);
WORKER_THREAD_ROUTINE FatFspMarkVolumeDirtyWithRecover;
VOID
NTAPI
FatFspMarkVolumeDirtyWithRecover (
PVOID Parameter
);
VOID
FatCheckDirtyBit (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb
);
VOID
FatQuickVerifyVcb (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb
);
VOID
FatVerifyOperationIsLegal (
IN PIRP_CONTEXT IrpContext
);
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatPerformVerify (
_In_ PIRP_CONTEXT IrpContext,
_In_ PIRP Irp,
_In_ PDEVICE_OBJECT Device
);
//
// Work queue routines for posting and retrieving an Irp, implemented in
// workque.c
//
VOID
NTAPI
FatOplockComplete (
IN PVOID Context,
IN PIRP Irp
);
VOID
NTAPI
FatPrePostIrp (
IN PVOID Context,
IN PIRP Irp
);
VOID
#ifdef __REACTOS__
NTAPI
#endif
FatAddToWorkque (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
NTSTATUS
FatFsdPostRequest (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
//
// Miscellaneous support routines
//
//
// ULONG
// PtrOffset (
// IN PVOID BasePtr,
// IN PVOID OffsetPtr
// );
//
#define PtrOffset(BASE,OFFSET) ((ULONG)((ULONG_PTR)(OFFSET) - (ULONG_PTR)(BASE)))
//
// This macro takes a pointer (or ulong) and returns its rounded up word
// value
//
#define WordAlign(Ptr) ( \
((((ULONG)(Ptr)) + 1) & 0xfffffffe) \
)
//
// This macro takes a pointer (or ulong) and returns its rounded up longword
// value
//
#define LongAlign(Ptr) ( \
((((ULONG)(Ptr)) + 3) & 0xfffffffc) \
)
//
// This macro takes a pointer (or ulong) and returns its rounded up quadword
// value
//
#define QuadAlign(Ptr) ( \
((((ULONG)(Ptr)) + 7) & 0xfffffff8) \
)
//
// The following types and macros are used to help unpack the packed and
// misaligned fields found in the Bios parameter block
//
typedef union _UCHAR1 {
UCHAR Uchar[1];
UCHAR ForceAlignment;
} UCHAR1, *PUCHAR1;
typedef union _UCHAR2 {
UCHAR Uchar[2];
USHORT ForceAlignment;
} UCHAR2, *PUCHAR2;
typedef union _UCHAR4 {
UCHAR Uchar[4];
ULONG ForceAlignment;
} UCHAR4, *PUCHAR4;
//
// This macro copies an unaligned src byte to an aligned dst byte
//
#define CopyUchar1(Dst,Src) { \
*((UCHAR1 *)(Dst)) = *((UNALIGNED UCHAR1 *)(Src)); \
}
//
// This macro copies an unaligned src word to an aligned dst word
//
#define CopyUchar2(Dst,Src) { \
*((UCHAR2 *)(Dst)) = *((UNALIGNED UCHAR2 *)(Src)); \
}
//
// This macro copies an unaligned src longword to an aligned dsr longword
//
#define CopyUchar4(Dst,Src) { \
*((UCHAR4 *)(Dst)) = *((UNALIGNED UCHAR4 *)(Src)); \
}
#define CopyU4char(Dst,Src) { \
*((UNALIGNED UCHAR4 *)(Dst)) = *((UCHAR4 *)(Src)); \
}
//
// VOID
// FatNotifyReportChange (
// IN PIRP_CONTEXT IrpContext,
// IN PVCB Vcb,
// IN PFCB Fcb,
// IN ULONG Filter,
// IN ULONG Action
// );
//
#define FatNotifyReportChange(I,V,F,FL,A) { \
if ((F)->FullFileName.Buffer == NULL) { \
FatSetFullFileNameInFcb((I),(F)); \
} \
NT_ASSERT( (F)->FullFileName.Length != 0 ); \
NT_ASSERT( (F)->FinalNameLength != 0 ); \
NT_ASSERT( (F)->FullFileName.Length > (F)->FinalNameLength ); \
NT_ASSERT( (F)->FullFileName.Buffer[((F)->FullFileName.Length - (F)->FinalNameLength)/sizeof(WCHAR) - 1] == L'\\' ); \
FsRtlNotifyFullReportChange( (V)->NotifySync, \
&(V)->DirNotifyList, \
(PSTRING)&(F)->FullFileName, \
(USHORT) ((F)->FullFileName.Length - \
(F)->FinalNameLength), \
(PSTRING)NULL, \
(PSTRING)NULL, \
(ULONG)FL, \
(ULONG)A, \
(PVOID)NULL ); \
}
//
// The FSD Level dispatch routines. These routines are called by the
// I/O system via the dispatch table in the Driver Object.
//
// They each accept as input a pointer to a device object (actually most
// expect a volume device object, with the exception of the file system
// control function which can also take a file system device object), and
// a pointer to the IRP. They either perform the function at the FSD level
// or post the request to the FSP work queue for FSP level processing.
//
_Function_class_(IRP_MJ_CLEANUP)
_Function_class_(DRIVER_DISPATCH)
NTSTATUS
NTAPI
FatFsdCleanup ( // implemented in Cleanup.c
_In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
_Inout_ PIRP Irp
);
_Function_class_(IRP_MJ_CLOSE)
_Function_class_(DRIVER_DISPATCH)
NTSTATUS
NTAPI
FatFsdClose ( // implemented in Close.c
_In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
_Inout_ PIRP Irp
);
_Function_class_(IRP_MJ_CREATE)
_Function_class_(DRIVER_DISPATCH)
NTSTATUS
NTAPI
FatFsdCreate ( // implemented in Create.c
_In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
_Inout_ PIRP Irp
);
_Function_class_(IRP_MJ_DEVICE_CONTROL)
_Function_class_(DRIVER_DISPATCH)
NTSTATUS
NTAPI
FatFsdDeviceControl ( // implemented in DevCtrl.c
_In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
_Inout_ PIRP Irp
);
_Function_class_(IRP_MJ_DIRECTORY_CONTROL)
_Function_class_(DRIVER_DISPATCH)
NTSTATUS
NTAPI
FatFsdDirectoryControl ( // implemented in DirCtrl.c
_In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
_Inout_ PIRP Irp
);
_Function_class_(IRP_MJ_QUERY_EA)
_Function_class_(DRIVER_DISPATCH)
NTSTATUS
NTAPI
FatFsdQueryEa ( // implemented in Ea.c
_In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
_Inout_ PIRP Irp
);
_Function_class_(IRP_MJ_SET_EA)
_Function_class_(DRIVER_DISPATCH)
NTSTATUS
NTAPI
FatFsdSetEa ( // implemented in Ea.c
_In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
_Inout_ PIRP Irp
);
_Function_class_(IRP_MJ_QUERY_INFORMATION)
_Function_class_(DRIVER_DISPATCH)
NTSTATUS
NTAPI
FatFsdQueryInformation ( // implemented in FileInfo.c
_In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
_Inout_ PIRP Irp
);
_Function_class_(IRP_MJ_SET_INFORMATION)
_Function_class_(DRIVER_DISPATCH)
NTSTATUS
NTAPI
FatFsdSetInformation ( // implemented in FileInfo.c
_In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
_Inout_ PIRP Irp
);
_Function_class_(IRP_MJ_FLUSH_BUFFERS)
_Function_class_(DRIVER_DISPATCH)
NTSTATUS
NTAPI
FatFsdFlushBuffers ( // implemented in Flush.c
_In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
_Inout_ PIRP Irp
);
_Function_class_(IRP_MJ_FILE_SYSTEM_CONTROL)
_Function_class_(DRIVER_DISPATCH)
NTSTATUS
NTAPI
FatFsdFileSystemControl ( // implemented in FsCtrl.c
_In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
_Inout_ PIRP Irp
);
_Function_class_(IRP_MJ_LOCK_CONTROL)
_Function_class_(DRIVER_DISPATCH)
NTSTATUS
NTAPI
FatFsdLockControl ( // implemented in LockCtrl.c
_In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
_Inout_ PIRP Irp
);
_Function_class_(IRP_MJ_PNP)
_Function_class_(DRIVER_DISPATCH)
NTSTATUS
NTAPI
FatFsdPnp ( // implemented in Pnp.c
_In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
_Inout_ PIRP Irp
);
_Function_class_(IRP_MJ_READ)
_Function_class_(DRIVER_DISPATCH)
NTSTATUS
NTAPI
FatFsdRead ( // implemented in Read.c
_In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
_Inout_ PIRP Irp
);
_Function_class_(IRP_MJ_SHUTDOWN)
_Function_class_(DRIVER_DISPATCH)
NTSTATUS
NTAPI
FatFsdShutdown ( // implemented in Shutdown.c
_In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
_Inout_ PIRP Irp
);
_Function_class_(IRP_MJ_QUERY_VOLUME_INFORMATION)
_Function_class_(DRIVER_DISPATCH)
NTSTATUS
NTAPI
FatFsdQueryVolumeInformation ( // implemented in VolInfo.c
_In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
_Inout_ PIRP Irp
);
_Function_class_(IRP_MJ_SET_VOLUME_INFORMATION)
_Function_class_(DRIVER_DISPATCH)
NTSTATUS
NTAPI
FatFsdSetVolumeInformation ( // implemented in VolInfo.c
_In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
_Inout_ PIRP Irp
);
_Function_class_(IRP_MJ_WRITE)
_Function_class_(DRIVER_DISPATCH)
NTSTATUS
NTAPI
FatFsdWrite ( // implemented in Write.c
_In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
_Inout_ PIRP Irp
);
//
// The following macro is used to determine if an FSD thread can block
// for I/O or wait for a resource. It returns TRUE if the thread can
// block and FALSE otherwise. This attribute can then be used to call
// the FSD & FSP common work routine with the proper wait value.
//
#define CanFsdWait(IRP) IoIsOperationSynchronous(Irp)
//
// The FSP level dispatch/main routine. This is the routine that takes
// IRP's off of the work queue and calls the appropriate FSP level
// work routine.
//
WORKER_THREAD_ROUTINE FatFspDispatch;
VOID
NTAPI
FatFspDispatch ( // implemented in FspDisp.c
_In_ PVOID Context
);
//
// The following routines are the FSP work routines that are called
// by the preceding FatFspDispath routine. Each takes as input a pointer
// to the IRP, perform the function, and return a pointer to the volume
// device object that they just finished servicing (if any). The return
// pointer is then used by the main Fsp dispatch routine to check for
// additional IRPs in the volume's overflow queue.
//
// Each of the following routines is also responsible for completing the IRP.
// We moved this responsibility from the main loop to the individual routines
// to allow them the ability to complete the IRP and continue post processing
// actions.
//
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatCommonCleanup ( // implemented in Cleanup.c
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatCommonClose ( // implemented in Close.c
IN PVCB Vcb,
IN PFCB Fcb,
IN PCCB Ccb,
IN TYPE_OF_OPEN TypeOfOpen,
IN BOOLEAN Wait,
IN BOOLEAN TopLevel,
OUT PBOOLEAN VcbDeleted OPTIONAL
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatFspClose ( // implemented in Close.c
IN PVCB Vcb OPTIONAL
);
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatCommonCreate ( // implemented in Create.c
_Inout_ PIRP_CONTEXT IrpContext,
_Inout_ PIRP Irp
);
#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatCommonCreateOnNewStack ( // implemented in Create.c
_Inout_ PIRP_CONTEXT IrpContext,
_Inout_ PIRP Irp
);
_Requires_lock_held_(_Global_critical_region_)
VOID
FatCommonCreateCallout ( // implemented in Create.c
_In_ PFAT_CALLOUT_PARAMETERS CalloutParameters
);
#endif
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatCommonDirectoryControl ( // implemented in DirCtrl.c
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatCommonDeviceControl ( // implemented in DevCtrl.c
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
NTSTATUS
FatCommonQueryEa ( // implemented in Ea.c
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
NTSTATUS
FatCommonSetEa ( // implemented in Ea.c
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatCommonQueryInformation ( // implemented in FileInfo.c
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatCommonSetInformation ( // implemented in FileInfo.c
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatCommonFlushBuffers ( // implemented in Flush.c
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatCommonFileSystemControl ( // implemented in FsCtrl.c
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatCommonLockControl ( // implemented in LockCtrl.c
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatCommonPnp ( // implemented in Pnp.c
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatCommonRead ( // implemented in Read.c
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatCommonShutdown ( // implemented in Shutdown.c
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatCommonQueryVolumeInfo ( // implemented in VolInfo.c
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatCommonSetVolumeInfo ( // implemented in VolInfo.c
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatCommonWrite ( // implemented in Write.c
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
//
// The following is implemented in Flush.c, and does what is says.
//
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatFlushFile (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN FAT_FLUSH_TYPE FlushType
);
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatFlushDirectory (
IN PIRP_CONTEXT IrpContext,
IN PDCB Dcb,
IN FAT_FLUSH_TYPE FlushType
);
NTSTATUS
FatFlushFat (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb
);
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatFlushVolume (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN FAT_FLUSH_TYPE FlushType
);
NTSTATUS
FatHijackIrpAndFlushDevice (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp,
IN PDEVICE_OBJECT TargetDeviceObject
);
VOID
FatFlushFatEntries (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN ULONG Cluster,
IN ULONG Count
);
VOID
FatFlushDirentForFile (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb
);
//
// The following procedure is used by the FSP and FSD routines to complete
// an IRP.
//
// Note that this macro allows either the Irp or the IrpContext to be
// null, however the only legal order to do this in is:
//
// FatCompleteRequest( NULL, Irp, Status ); // completes Irp & preserves context
// ...
// FatCompleteRequest( IrpContext, NULL, DontCare ); // deallocates context
//
// This would typically be done in order to pass a "naked" IrpContext off to
// the Fsp for post processing, such as read ahead.
//
VOID
FatCompleteRequest_Real (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp,
IN NTSTATUS Status
);
#define FatCompleteRequest(IRPCONTEXT,IRP,STATUS) { \
FatCompleteRequest_Real(IRPCONTEXT,IRP,STATUS); \
}
BOOLEAN
FatIsIrpTopLevel (
IN PIRP Irp
);
//
// The Following routine makes a popup
//
_Requires_lock_held_(_Global_critical_region_)
VOID
FatPopUpFileCorrupt (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb
);
//
// Here are the callbacks used by the I/O system for checking for fast I/O or
// doing a fast query info call, or doing fast lock calls.
//
_Function_class_(FAST_IO_CHECK_IF_POSSIBLE)
BOOLEAN
NTAPI
FatFastIoCheckIfPossible (
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN BOOLEAN CheckForReadOperation,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject
);
_Function_class_(FAST_IO_QUERY_BASIC_INFO)
BOOLEAN
NTAPI
FatFastQueryBasicInfo (
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN OUT PFILE_BASIC_INFORMATION Buffer,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject
);
_Function_class_(FAST_IO_QUERY_STANDARD_INFO)
BOOLEAN
NTAPI
FatFastQueryStdInfo (
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN OUT PFILE_STANDARD_INFORMATION Buffer,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject
);
_Function_class_(FAST_IO_QUERY_NETWORK_OPEN_INFO)
BOOLEAN
NTAPI
FatFastQueryNetworkOpenInfo (
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject
);
_Function_class_(FAST_IO_LOCK)
BOOLEAN
NTAPI
FatFastLock (
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN PLARGE_INTEGER Length,
PEPROCESS ProcessId,
ULONG Key,
BOOLEAN FailImmediately,
BOOLEAN ExclusiveLock,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject
);
_Function_class_(FAST_IO_UNLOCK_SINGLE)
BOOLEAN
NTAPI
FatFastUnlockSingle (
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN PLARGE_INTEGER Length,
PEPROCESS ProcessId,
ULONG Key,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject
);
_Function_class_(FAST_IO_UNLOCK_ALL)
BOOLEAN
NTAPI
FatFastUnlockAll (
IN PFILE_OBJECT FileObject,
PEPROCESS ProcessId,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject
);
_Function_class_(FAST_IO_UNLOCK_ALL_BY_KEY)
BOOLEAN
NTAPI
FatFastUnlockAllByKey (
IN PFILE_OBJECT FileObject,
PVOID ProcessId,
ULONG Key,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject
);
VOID
FatExamineFatEntries(
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN ULONG StartIndex OPTIONAL,
IN ULONG EndIndex OPTIONAL,
IN BOOLEAN SetupWindows,
IN PFAT_WINDOW SwitchToWindow OPTIONAL,
IN PULONG BitMapBuffer OPTIONAL
);
BOOLEAN
FatScanForDataTrack(
IN PIRP_CONTEXT IrpContext,
IN PDEVICE_OBJECT TargetDeviceObject
);
//
// The following macro is used to determine is a file has been deleted.
//
// BOOLEAN
// IsFileDeleted (
// IN PIRP_CONTEXT IrpContext,
// IN PFCB Fcb
// );
//
#define IsFileDeleted(IRPCONTEXT,FCB) \
(FlagOn((FCB)->FcbState, FCB_STATE_DELETE_ON_CLOSE) && \
((FCB)->UncleanCount == 0))
//
// The following macro is used by the dispatch routines to determine if
// an operation is to be done with or without Write Through.
//
// BOOLEAN
// IsFileWriteThrough (
// IN PFILE_OBJECT FileObject,
// IN PVCB Vcb
// );
//
#define IsFileWriteThrough(FO,VCB) ( \
BooleanFlagOn((FO)->Flags, FO_WRITE_THROUGH) \
)
//
// The following macro is used to set the is fast i/o possible field in
// the common part of the nonpaged fcb. It checks that this is actually
// an FCB (as opposed to a DCB) so that directory oplock code works properly.
//
//
// BOOLEAN
// FatIsFastIoPossible (
// IN PFCB Fcb
// );
//
#define FatIsFastIoPossible(FCB) ((BOOLEAN) \
((((FCB)->FcbCondition != FcbGood) || \
(NodeType( (FCB) ) != FAT_NTC_FCB) || \
!FsRtlOplockIsFastIoPossible( FatGetFcbOplock(FCB) )) ? \
FastIoIsNotPossible \
: \
(!FsRtlAreThereCurrentFileLocks( &(FCB)->Specific.Fcb.FileLock ) && \
((FCB)->NonPaged->OutstandingAsyncWrites == 0) && \
!FlagOn( (FCB)->Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED ) ? \
FastIoIsPossible \
: \
FastIoIsQuestionable \
) \
) \
)
#if (NTDDI_VERSION >= NTDDI_WIN8)
//
// Detect whether this file can have an oplock on it. As of Windows 8 file and
// directories can have oplocks.
//
#define FatIsNodeTypeOplockable(N) ( \
((N) == FAT_NTC_FCB) || \
((N) == FAT_NTC_ROOT_DCB) || \
((N) == FAT_NTC_DCB) \
)
#else
#define FatIsNodeTypeOplockable(N) ( \
((N) == FAT_NTC_FCB) \
)
#endif
#define FatIsFileOplockable(F) ( \
FatIsNodeTypeOplockable( NodeType( (F) )) \
)
//
// The following macro is used to detemine if the file object is opened
// for read only access (i.e., it is not also opened for write access or
// delete access).
//
// BOOLEAN
// IsFileObjectReadOnly (
// IN PFILE_OBJECT FileObject
// );
//
#define IsFileObjectReadOnly(FO) (!((FO)->WriteAccess | (FO)->DeleteAccess))
//
// The following two macro are used by the Fsd/Fsp exception handlers to
// process an exception. The first macro is the exception filter used in the
// Fsd/Fsp to decide if an exception should be handled at this level.
// The second macro decides if the exception is to be finished off by
// completing the IRP, and cleaning up the Irp Context, or if we should
// bugcheck. Exception values such as STATUS_FILE_INVALID (raised by
// VerfySup.c) cause us to complete the Irp and cleanup, while exceptions
// such as accvio cause us to bugcheck.
//
// The basic structure for fsd/fsp exception handling is as follows:
//
// FatFsdXxx(...)
// {
// try {
//
// ...
//
// } except(FatExceptionFilter( IrpContext, GetExceptionCode() )) {
//
// Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
// }
//
// Return Status;
// }
//
// To explicitly raise an exception that we expect, such as
// STATUS_FILE_INVALID, use the below macro FatRaiseStatus(). To raise a
// status from an unknown origin (such as CcFlushCache()), use the macro
// FatNormalizeAndRaiseStatus. This will raise the status if it is expected,
// or raise STATUS_UNEXPECTED_IO_ERROR if it is not.
//
// If we are vicariously handling exceptions without using FatProcessException(),
// if there is the possibility that we raised that exception, one *must*
// reset the IrpContext so a subsequent raise in the course of handling this
// request that is *not* explicit, i.e. like a pagein error, does not get
// spoofed into believing that the first raise status is the reason the second
// occured. This could have really serious consequences.
//
// It is an excellent idea to always FatResetExceptionState in these cases.
//
// Note that when using these two macros, the original status is placed in
// IrpContext->ExceptionStatus, signaling FatExceptionFilter and
// FatProcessException that the status we actually raise is by definition
// expected.
//
ULONG
FatExceptionFilter (
IN PIRP_CONTEXT IrpContext,
IN PEXCEPTION_POINTERS ExceptionPointer
);
#if DBG
ULONG
FatBugCheckExceptionFilter (
IN PEXCEPTION_POINTERS ExceptionPointer
);
#endif
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
FatProcessException (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp,
IN NTSTATUS ExceptionCode
);
//
// VOID
// FatRaiseStatus (
// IN PRIP_CONTEXT IrpContext,
// IN NT_STATUS Status
// );
//
//
#if DBG
#ifdef _MSC_VER
#define DebugBreakOnStatus(S) { \
__pragma(warning(push)) \
__pragma(warning(disable:4127)) \
if (FatTestRaisedStatus) { \
if ((S) == STATUS_DISK_CORRUPT_ERROR || (S) == STATUS_FILE_CORRUPT_ERROR) { \
__pragma(warning(pop)) \
DbgPrint( "FAT: Breaking on interesting raised status (0x%08x)\n", (S) );\
DbgPrint( "FAT: Set FatTestRaisedStatus @ 0x%p to 0 to disable\n", \
&FatTestRaisedStatus ); \
NT_ASSERT(FALSE); \
} \
} \
}
#else
#define DebugBreakOnStatus(S) { \
if (FatTestRaisedStatus) { \
if ((S) == STATUS_DISK_CORRUPT_ERROR || (S) == STATUS_FILE_CORRUPT_ERROR) { \
DbgPrint( "FAT: Breaking on interesting raised status (0x%08x)\n", (S) );\
DbgPrint( "FAT: Set FatTestRaisedStatus @ 0x%p to 0 to disable\n", \
&FatTestRaisedStatus ); \
NT_ASSERT(FALSE); \
} \
} \
}
#endif
#else
#define DebugBreakOnStatus(S)
#endif
#define FatRaiseStatus(IRPCONTEXT,STATUS) { \
(IRPCONTEXT)->ExceptionStatus = (STATUS); \
DebugBreakOnStatus( (STATUS) ) \
ExRaiseStatus( (STATUS) ); \
}
#define FatResetExceptionState( IRPCONTEXT ) { \
(IRPCONTEXT)->ExceptionStatus = STATUS_SUCCESS; \
}
//
// VOID
// FatNormalAndRaiseStatus (
// IN PRIP_CONTEXT IrpContext,
// IN NT_STATUS Status
// );
//
#define FatNormalizeAndRaiseStatus(IRPCONTEXT,STATUS) { \
(IRPCONTEXT)->ExceptionStatus = (STATUS); \
ExRaiseStatus(FsRtlNormalizeNtstatus((STATUS),STATUS_UNEXPECTED_IO_ERROR)); \
}
//
// The following macros are used to establish the semantics needed
// to do a return from within a try-finally clause. As a rule every
// try clause must end with a label call try_exit. For example,
//
// try {
// :
// :
//
// try_exit: NOTHING;
// } finally {
//
// :
// :
// }
//
// Every return statement executed inside of a try clause should use the
// try_return macro. If the compiler fully supports the try-finally construct
// then the macro should be
//
// #define try_return(S) { return(S); }
//
// If the compiler does not support the try-finally construct then the macro
// should be
//
// #define try_return(S) { S; goto try_exit; }
//
#define try_return(S) { S; goto try_exit; }
#define try_leave(S) { S; _SEH2_LEAVE; }
CLUSTER_TYPE
FatInterpretClusterType (
IN PVCB Vcb,
IN FAT_ENTRY Entry
);
//
// These routines define the FileId for FAT. Lacking a fixed/uniquifiable
// notion, we simply come up with one which is unique in a given snapshot
// of the volume. As long as the parent directory is not moved or compacted,
// it may even be permanent.
//
//
// The internal information used to identify the fcb/dcb on the
// volume is the byte offset of the dirent of the file on disc.
// Our root always has fileid 0. FAT32 roots are chains and can
// use the LBO of the cluster, 12/16 roots use the lbo in the Vcb.
//
#define FatGenerateFileIdFromDirentOffset(ParentDcb,DirentOffset) \
((ParentDcb) ? ((NodeType(ParentDcb) != FAT_NTC_ROOT_DCB || FatIsFat32((ParentDcb)->Vcb)) ? \
FatGetLboFromIndex( (ParentDcb)->Vcb, \
(ParentDcb)->FirstClusterOfFile ) : \
(ParentDcb)->Vcb->AllocationSupport.RootDirectoryLbo) + \
(DirentOffset) \
: \
0)
//
//
#define FatGenerateFileIdFromFcb(Fcb) \
FatGenerateFileIdFromDirentOffset( (Fcb)->ParentDcb, (Fcb)->DirentOffsetWithinDirectory )
//
// Wrap to handle the ./.. cases appropriately. Note that we commute NULL parent to 0. This would
// only occur in an illegal root ".." entry.
//
#define FATDOT ((ULONG)0x2020202E)
#define FATDOTDOT ((ULONG)0x20202E2E)
#define FatGenerateFileIdFromDirentAndOffset(Dcb,Dirent,DirentOffset) \
((*((PULONG)(Dirent)->FileName)) == FATDOT ? FatGenerateFileIdFromFcb(Dcb) : \
((*((PULONG)(Dirent)->FileName)) == FATDOTDOT ? ((Dcb)->ParentDcb ? \
FatGenerateFileIdFromFcb((Dcb)->ParentDcb) : \
0) : \
FatGenerateFileIdFromDirentOffset(Dcb,DirentOffset)))
//
// BOOLEAN
// FatDeviceIsFatFsdo(
// IN PDEVICE_OBJECT D
// );
//
// Evaluates to TRUE if the supplied device object is one of the file system devices
// we created at initialisation.
//
#define FatDeviceIsFatFsdo( D) (((D) == FatData.DiskFileSystemDeviceObject) || ((D) == FatData.CdromFileSystemDeviceObject))
//
// BlockAlign(): Aligns P on the next V boundary.
// BlockAlignTruncate(): Aligns P on the prev V boundary.
//
#define BlockAlign(P,V) ((ASSERT( V != 0)), (((P)) + (V-1) & (0-(V))))
#define BlockAlignTruncate(P,V) ((P) & (0-(V)))
#define IsDirectory(FcbOrDcb) ((NodeType((FcbOrDcb)) == FAT_NTC_DCB) || (NodeType((FcbOrDcb)) == FAT_NTC_ROOT_DCB))
#endif // _FATPROCS_