|
|
/*++
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.
// @@BEGIN_DDKSPLIT
Author:
Gary Kimura [GaryKi] 28-Dec-1989
Revision History:
// @@END_DDKSPLIT
--*/
#ifndef _FATPROCS_
#define _FATPROCS_
#include <ntifs.h>
#include <ntddcdrm.h>
#include <ntdddisk.h>
#include <ntddstor.h>
#include "nodetype.h"
#include "Fat.h"
#include "Lfn.h"
#include "FatStruc.h"
#include "FatData.h"
#ifndef INLINE
#define INLINE __inline
#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( IN PVOID String );
VOID FatEnsureStringBufferEnough( IN OUT 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 SectorCount 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 SectorCount );
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 );
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
//
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
Return Value:
BOOLEAN - if, considering the cluster size, the neccesary size of the object to contain the range can be represented in 32 bits.
--*/
{ //
// 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); }
VOID FatSetupAllocationSupport ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb );
VOID FatTearDownAllocationSupport ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb );
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 );
VOID FatAddFileAllocation ( IN PIRP_CONTEXT IrpContext, IN PFCB FcbOrDcb, IN PFILE_OBJECT FileObject OPTIONAL, IN ULONG AllocationSize );
VOID FatTruncateFileAllocation ( IN PIRP_CONTEXT IrpContext, IN PFCB FcbOrDcb, IN ULONG AllocationSize );
VOID FatLookupFileAllocationSize ( IN PIRP_CONTEXT IrpContext, IN PFCB FcbOrDcb );
VOID FatAllocateDiskSpace ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN ULONG AbsoluteClusterHint, IN OUT PULONG ByteCount, IN BOOLEAN ExactMatchRequired, OUT PLARGE_MCB Mcb );
VOID FatDeallocateDiskSpace ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PLARGE_MCB Mcb );
VOID FatSplitAllocation ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN OUT PLARGE_MCB Mcb, IN VBO SplitAtVbo, OUT PLARGE_MCB RemainingMcb );
VOID FatMergeAllocation ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN OUT PLARGE_MCB Mcb, IN PLARGE_MCB SecondMcb );
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 );
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 );
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 );
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 );
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 );
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 );
//
// 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)); \ ASSERT( (IRPCONTEXT)->PinCount ); \ (IRPCONTEXT)->PinCount -= 1; \ (BCB) = NULL; \ } \ }
#else
#define FatUnpinBcb(IRPCONTEXT,BCB) { \
if ((BCB) != NULL) { \ CcUnpinData((BCB)); \ (BCB) = NULL; \ } \ }
#endif // DBG
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 );
NTSTATUS FatNonCachedIo ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp, IN PFCB FcbOrDcb, IN ULONG StartingVbo, IN ULONG ByteCount, IN ULONG UserByteCount );
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, OUT PVOID OutputBuffer OPTIONAL, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN BOOLEAN OverrideVerify, OUT PIO_STATUS_BLOCK Iosb OPTIONAL );
//
// 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 );
ULONG FatCreateNewDirent ( IN PIRP_CONTEXT IrpContext, IN PDCB ParentDirectory, IN ULONG DirentsNeeded );
VOID FatInitializeDirectoryDirent ( IN PIRP_CONTEXT IrpContext, IN PDCB Dcb, IN PDIRENT ParentDirent );
VOID FatDeleteDirent ( IN PIRP_CONTEXT IrpContext, IN PFCB FcbOrDcb, IN PDELETE_CONTEXT DeleteContext OPTIONAL, IN BOOLEAN DeleteEa );
VOID FatLocateDirent ( IN PIRP_CONTEXT IrpContext, IN PDCB ParentDirectory, IN PCCB Ccb, IN VBO OffsetToStartSearchFrom, OUT PDIRENT *Dirent, OUT PBCB *Bcb, OUT PVBO ByteOffset, OUT PBOOLEAN FileNameDos OPTIONAL, OUT PUNICODE_STRING Lfn OPTIONAL );
VOID FatLocateSimpleOemDirent ( IN PIRP_CONTEXT IrpContext, IN PDCB ParentDirectory, IN POEM_STRING FileName, OUT PDIRENT *Dirent, OUT PBCB *Bcb, OUT PVBO ByteOffset );
BOOLEAN FatLfnDirentExists ( IN PIRP_CONTEXT IrpContext, IN PDCB Dcb, IN PUNICODE_STRING Lfn, IN PUNICODE_STRING LfnTmp );
VOID FatLocateVolumeLabel ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, OUT PDIRENT *Dirent, OUT PBCB *Bcb, OUT PVBO ByteOffset );
VOID FatGetDirentFromFcbOrDcb ( IN PIRP_CONTEXT IrpContext, IN PFCB FcbOrDcb, OUT PDIRENT *Dirent, OUT PBCB *Bcb );
BOOLEAN FatIsDirectoryEmpty ( IN PIRP_CONTEXT IrpContext, IN PDCB Dcb );
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 UCHAR Attributes, IN BOOLEAN ZeroAndSetTimeFields, IN PLARGE_INTEGER SetCreationTime OPTIONAL );
VOID FatConstructLabelDirent ( IN PIRP_CONTEXT IrpContext, IN OUT PDIRENT Dirent, IN POEM_STRING Label );
VOID FatSetFileSizeInDirent ( IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN PULONG AlternativeFileSize OPTIONAL );
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 )
VOID FatGetEaLength ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PDIRENT Dirent, OUT PULONG EaLength );
VOID FatGetNeedEaCount ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PDIRENT Dirent, OUT PULONG NeedEaCount );
VOID FatCreateEa ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PUCHAR Buffer, IN ULONG Length, IN POEM_STRING FileName, OUT PUSHORT EaHandle );
VOID FatDeleteEa ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN USHORT EaHandle, IN POEM_STRING FileName );
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 );
VOID FatDeleteEaSet ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PBCB EaBcb, OUT PDIRENT EaDirent, IN USHORT EaHandle, IN POEM_STRING Filename );
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
//
typedef enum _TYPE_OF_OPEN {
UnopenedFileObject = 1, UserFileOpen, UserDirectoryOpen, UserVolumeOpen, VirtualVolumeFile, DirectoryFile, EaFile
} TYPE_OF_OPEN;
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, OUT PVCB *Vcb, OUT PFCB *FcbOrDcb, OUT PCCB *Ccb );
VOID FatPurgeReferencedFileObjects ( IN PIRP_CONTEXT IrpContext, IN PFCB FcbOrDcb, IN FAT_FLUSH_TYPE FlushType );
VOID FatForceCacheMiss ( IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN FAT_FLUSH_TYPE FlushType );
//
// File system control routines, implemented in FsCtrl.c
//
VOID FatFlushAndCleanVolume( IN PIRP_CONTEXT IrpContext, IN PIRP Irp, IN PVCB Vcb, IN FAT_FLUSH_TYPE FlushType );
BOOLEAN FatIsBootSectorFat ( IN PPACKED_BOOT_SECTOR BootSector );
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
//
//
// VOID
// FatDissectName (
// IN PIRP_CONTEXT IrpContext,
// IN OEM_STRING InputString,
// OUT POEM_STRING FirstPart,
// OUT POEM_STRING RemainingPart
// )
//
// /*++
//
// Routine Description:
//
// This routine takes an input string and dissects it into two substrings.
// The first output string contains the name that appears at the beginning
// of the input string, the second output string contains the remainder of
// the input string.
//
// In the input string backslashes are used to separate names. The input
// string must not start with a backslash. Both output strings will not
// begin with a backslash.
//
// If the input string does not contain any names then both output strings
// are empty. If the input string contains only one name then the first
// output string contains the name and the second string is empty.
//
// Note that both output strings use the same string buffer memory of the
// input string.
//
// Example of its results are:
//
// //. . InputString FirstPart RemainingPart
// //
// //. . empty empty empty
// //
// //. . A A empty
// //
// //. . A\B\C\D\E A B\C\D\E
// //
// //. . *A? *A? empty
// //
// //. . \A A empty
// //
// //. . A[,] A[,] empty
// //
// //. . A\\B+;\C A \B+;\C
//
// Arguments:
//
// InputString - Supplies the input string being dissected
//
// FirstPart - Receives the first name in the input string
//
// RemainingPart - Receives the remaining part of the input string
//
// Return Value:
//
// BOOLEAN - TRUE if the input string is well formed and its first part
// does not contain any illegal characters, and FALSE otherwise.
//
// --*/
//
#define FatDissectName(IRPCONTEXT,INPUT_STRING,FIRST_PART,REMAINING_PART) { \
FsRtlDissectDbcs( (INPUT_STRING), \ (FIRST_PART), \ (REMAINING_PART) ); \ }
//
// BOOLEAN
// FatDoesNameContainWildCards (
// IN PIRP_CONTEXT IrpContext,
// IN OEM_STRING Name
// )
//
// /*++
//
// Routine Description:
//
// This routine checks if the input name contains any wild card characters.
//
// Arguments:
//
// Name - Supplies the name to examine
//
// Return Value:
//
// BOOLEAN - TRUE if the input name contains any wildcard characters and
// FALSE otherwise.
//
// --*/
//
#define FatDoesNameContainWildCards(IRPCONTEXT,NAME) ( \
FsRtlDoesDbcsContainWildCards( &(NAME) ) \ )
//
// 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)) \ )
INLINE BOOLEAN FatIsNameLongUnicodeValid ( PIRP_CONTEXT IrpContext, PUNICODE_STRING Name, BOOLEAN CanContainWildcards, BOOLEAN PathNameOk, BOOLEAN LeadingBackslashOk ) { ULONG i;
//
// I'm not bothering to do the whole thing, just enough to make this call look
// the same as the others.
//
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 PFAT8DOT3 Output8dot3 );
VOID Fat8dot3ToString ( IN PIRP_CONTEXT IrpContext, IN PDIRENT Dirent, IN BOOLEAN RestoreCase, OUT POEM_STRING OutputString );
VOID FatGetUnicodeNameFromFcb ( IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN OUT PUNICODE_STRING Lfn );
VOID FatSetFullFileNameInFcb ( IN PIRP_CONTEXT IrpContext, IN PFCB Fcb );
VOID FatSetFullNameInFcb( IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN PUNICODE_STRING FinalName );
VOID FatUnicodeToUpcaseOem ( IN PIRP_CONTEXT IrpContext, IN POEM_STRING OemString, IN PUNICODE_STRING UnicodeString );
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 );
//
// 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 Fcb = NULL; \ ASSERT(FlagOn((IRPCONTEXT)->Flags, IRP_CONTEXT_FLAG_WAIT)); \ (VOID)FatAcquireExclusiveVcb( (IRPCONTEXT), (VCB) ); \ while ( (Fcb = FatGetNextFcbBottomUp((IRPCONTEXT), Fcb, (VCB)->RootDcb)) != NULL) { \ (VOID)FatAcquireExclusiveFcb((IRPCONTEXT), Fcb ); \ } \ }
#define FatReleaseVolume(IRPCONTEXT,VCB) { \
PFCB Fcb = NULL; \ ASSERT(FlagOn((IRPCONTEXT)->Flags, IRP_CONTEXT_FLAG_WAIT)); \ while ( (Fcb = FatGetNextFcbBottomUp((IRPCONTEXT), Fcb, (VCB)->RootDcb)) != NULL) { \ (VOID)ExReleaseResourceLite( Fcb->Header.Resource ); \ } \ FatReleaseVcb((IRPCONTEXT), (VCB)); \ }
//
// 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))
FINISHED FatAcquireExclusiveVcb ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb );
FINISHED FatAcquireSharedVcb ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb );
FINISHED FatAcquireExclusiveFcb ( IN PIRP_CONTEXT IrpContext, IN PFCB Fcb );
FINISHED FatAcquireSharedFcb ( IN PIRP_CONTEXT IrpContext, IN PFCB Fcb );
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 FatAcquireDirectoryFileMutex(VCB) { \
ASSERT(KeAreApcsDisabled()); \ ExAcquireFastMutexUnsafe(&(VCB)->DirectoryFileCreationMutex); \ }
#define FatReleaseDirectoryFileMutex(VCB) { \
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 );
BOOLEAN FatAcquireFcbForLazyWrite ( IN PVOID Null, IN BOOLEAN Wait );
VOID FatReleaseFcbFromLazyWrite ( IN PVOID Null );
BOOLEAN FatAcquireFcbForReadAhead ( IN PVOID Null, IN BOOLEAN Wait );
VOID FatReleaseFcbFromReadAhead ( IN PVOID Null );
NTSTATUS FatAcquireForCcFlush ( IN PFILE_OBJECT FileObject, IN PDEVICE_OBJECT DeviceObject );
NTSTATUS FatReleaseForCcFlush ( IN PFILE_OBJECT FileObject, IN PDEVICE_OBJECT DeviceObject );
BOOLEAN FatNoOpAcquire ( IN PVOID Fcb, IN BOOLEAN Wait );
VOID FatNoOpRelease ( IN PVOID Fcb );
//
// 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 ); \ }
//
// In-memory structure support routine, implemented in StrucSup.c
//
VOID FatInitializeVcb ( IN PIRP_CONTEXT IrpContext, IN OUT PVCB Vcb, IN PDEVICE_OBJECT TargetDeviceObject, IN PVPB Vpb, IN PDEVICE_OBJECT FsDeviceObject ); VOID FatDeleteVcb ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb );
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 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_Real ( IN PIRP_CONTEXT IrpContext, IN PFCB Fcb );
#ifdef FASTFATDBG
#define FatDeleteFcb(IRPCONTEXT,FCB) { \
FatDeleteFcb_Real((IRPCONTEXT),(FCB)); \ (FCB) = NULL; \ } #else
#define FatDeleteFcb(IRPCONTEXT,VCB) { \
FatDeleteFcb_Real((IRPCONTEXT),(VCB)); \ } #endif // FASTFAT_DBG
PCCB FatCreateCcb ( IN PIRP_CONTEXT IrpContext ); VOID FatDeallocateCcbStrings( IN PCCB Ccb ); VOID FatDeleteCcb_Real ( IN PIRP_CONTEXT IrpContext, IN PCCB Ccb );
#ifdef FASTFATDBG
#define FatDeleteCcb(IRPCONTEXT,CCB) { \
FatDeleteCcb_Real((IRPCONTEXT),(CCB)); \ (CCB) = NULL; \ } #else
#define FatDeleteCcb(IRPCONTEXT,VCB) { \
FatDeleteCcb_Real((IRPCONTEXT),(VCB)); \ } #endif // FASTFAT_DBG
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)))
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 );
VOID FatCheckFreeDirentBitmap ( IN PIRP_CONTEXT IrpContext, IN PDCB Dcb );
ULONG FatVolumeUncleanCount ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb );
VOID FatPreallocateCloseContext ( );
// VOID
// FatAllocateCloseContext (
// )
//
// This routine allocates a close context, presumeably on behalf
// of a fileobject which does not have a structure we can embed one
// in.
#define FatAllocateCloseContext() (PCLOSE_CONTEXT) \
ExInterlockedPopEntrySList( &FatCloseContextSList, \ &FatData.GeneralSpinLock )
//
// 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 );
//
// Time conversion support routines, implemented in TimeSup.c
//
BOOLEAN FatNtTimeToFatTime ( IN PIRP_CONTEXT IrpContext, IN PLARGE_INTEGER NtTime, IN BOOLEAN Rounding, OUT PFAT_TIME_STAMP FatTime, OUT OPTIONAL PCHAR 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 );
VOID FatVerifyFcb ( IN PIRP_CONTEXT IrpContext, IN PFCB Fcb );
VOID FatCleanVolumeDpc ( IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2 );
VOID FatMarkVolume ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN FAT_VOLUME_STATE VolumeState );
VOID 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 );
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 FatOplockComplete ( IN PVOID Context, IN PIRP Irp );
VOID FatPrePostIrp ( IN PVOID Context, IN PIRP Irp );
VOID FatAddToWorkque ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp );
NTSTATUS FatFsdPostRequest ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp );
//
// Miscellaneous support routines
//
//
// This macro returns TRUE if a flag in a set of flags is on and FALSE
// otherwise. It is followed by two macros for setting and clearing
// flags
//
//#ifndef BooleanFlagOn
//#define BooleanFlagOn(Flags,SingleFlag) ((BOOLEAN)((((Flags) & (SingleFlag)) != 0)))
//#endif
//#ifndef SetFlag
//#define SetFlag(Flags,SingleFlag) { \ // (Flags) |= (SingleFlag); \ //}
//#endif
//#ifndef ClearFlag
//#define ClearFlag(Flags,SingleFlag) { \ // (Flags) &= ~(SingleFlag); \ //}
//#endif
//
// 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)); \ } \ ASSERT( (F)->FullFileName.Length != 0 ); \ ASSERT( (F)->FinalNameLength != 0 ); \ ASSERT( (F)->FullFileName.Length > (F)->FinalNameLength ); \ 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.
//
NTSTATUS FatFsdCleanup ( // implemented in Cleanup.c
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp );
NTSTATUS FatFsdClose ( // implemented in Close.c
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp );
NTSTATUS FatFsdCreate ( // implemented in Create.c
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp );
NTSTATUS FatFsdDeviceControl ( // implemented in DevCtrl.c
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp );
NTSTATUS FatFsdDirectoryControl ( // implemented in DirCtrl.c
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp );
NTSTATUS FatFsdQueryEa ( // implemented in Ea.c
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp );
NTSTATUS FatFsdSetEa ( // implemented in Ea.c
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp );
NTSTATUS FatFsdQueryInformation ( // implemented in FileInfo.c
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp );
NTSTATUS FatFsdSetInformation ( // implemented in FileInfo.c
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp );
NTSTATUS FatFsdFlushBuffers ( // implemented in Flush.c
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp );
NTSTATUS FatFsdFileSystemControl ( // implemented in FsCtrl.c
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp );
NTSTATUS FatFsdLockControl ( // implemented in LockCtrl.c
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp );
NTSTATUS FatFsdPnp ( // implemented in Pnp.c
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp );
NTSTATUS FatFsdRead ( // implemented in Read.c
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp );
NTSTATUS FatFsdShutdown ( // implemented in Shutdown.c
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp );
NTSTATUS FatFsdQueryVolumeInformation ( // implemented in VolInfo.c
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp );
NTSTATUS FatFsdSetVolumeInformation ( // implemented in VolInfo.c
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp );
NTSTATUS FatFsdWrite ( // implemented in Write.c
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN 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.
//
VOID 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.
//
NTSTATUS FatCommonCleanup ( // implemented in Cleanup.c
IN PIRP_CONTEXT IrpContext, IN PIRP Irp );
NTSTATUS FatCommonClose ( // implemented in Close.c
IN PVCB Vcb, IN PFCB Fcb, IN PCCB Ccb, IN TYPE_OF_OPEN TypeOfOpen, IN BOOLEAN Wait, IN PVOLUME_DEVICE_OBJECT *VolDo OPTIONAL );
VOID FatFspClose ( // implemented in Close.c
IN PVCB Vcb OPTIONAL );
NTSTATUS FatCommonCreate ( // implemented in Create.c
IN PIRP_CONTEXT IrpContext, IN PIRP Irp );
NTSTATUS FatCommonDirectoryControl ( // implemented in DirCtrl.c
IN PIRP_CONTEXT IrpContext, IN PIRP Irp );
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 );
NTSTATUS FatCommonQueryInformation ( // implemented in FileInfo.c
IN PIRP_CONTEXT IrpContext, IN PIRP Irp );
NTSTATUS FatCommonSetInformation ( // implemented in FileInfo.c
IN PIRP_CONTEXT IrpContext, IN PIRP Irp );
NTSTATUS FatCommonFlushBuffers ( // implemented in Flush.c
IN PIRP_CONTEXT IrpContext, IN PIRP Irp );
NTSTATUS FatCommonFileSystemControl ( // implemented in FsCtrl.c
IN PIRP_CONTEXT IrpContext, IN PIRP Irp );
NTSTATUS FatCommonLockControl ( // implemented in LockCtrl.c
IN PIRP_CONTEXT IrpContext, IN PIRP Irp );
NTSTATUS FatCommonPnp ( // implemented in Pnp.c
IN PIRP_CONTEXT IrpContext, IN PIRP Irp );
NTSTATUS FatCommonRead ( // implemented in Read.c
IN PIRP_CONTEXT IrpContext, IN PIRP Irp );
NTSTATUS FatCommonShutdown ( // implemented in Shutdown.c
IN PIRP_CONTEXT IrpContext, IN PIRP Irp );
NTSTATUS FatCommonQueryVolumeInfo ( // implemented in VolInfo.c
IN PIRP_CONTEXT IrpContext, IN PIRP Irp );
NTSTATUS FatCommonSetVolumeInfo ( // implemented in VolInfo.c
IN PIRP_CONTEXT IrpContext, IN PIRP Irp );
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.
//
NTSTATUS FatFlushFile ( IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN FAT_FLUSH_TYPE FlushType );
NTSTATUS FatFlushDirectory ( IN PIRP_CONTEXT IrpContext, IN PDCB Dcb, IN FAT_FLUSH_TYPE FlushType );
NTSTATUS FatFlushFat ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb );
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
//
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.
//
BOOLEAN 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 );
BOOLEAN FatFastQueryBasicInfo ( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, IN OUT PFILE_BASIC_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject );
BOOLEAN FatFastQueryStdInfo ( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, IN OUT PFILE_STANDARD_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject );
BOOLEAN FatFastQueryNetworkOpenInfo ( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, IN OUT PFILE_NETWORK_OPEN_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject );
BOOLEAN 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 );
BOOLEAN 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 );
BOOLEAN FatFastUnlockAll ( IN PFILE_OBJECT FileObject, PEPROCESS ProcessId, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject );
BOOLEAN 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
//
//
// BOOLEAN
// FatIsFastIoPossible (
// IN PFCB Fcb
// );
//
#define FatIsFastIoPossible(FCB) ((BOOLEAN) \
(((FCB)->FcbCondition != FcbGood || !FsRtlOplockIsFastIoPossible( &(FCB)->Specific.Fcb.Oplock )) ? \ FastIoIsNotPossible \ : \ (!FsRtlAreThereCurrentFileLocks( &(FCB)->Specific.Fcb.FileLock ) && \ ((FCB)->NonPaged->OutstandingAsyncWrites == 0) && \ !FlagOn( (FCB)->Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED ) ? \ FastIoIsPossible \ : \ FastIoIsQuestionable \ ) \ ) \ )
//
// 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 nasty 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
NTSTATUS FatProcessException ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp, IN NTSTATUS ExceptionCode );
//
// VOID
// FatRaiseStatus (
// IN PRIP_CONTEXT IrpContext,
// IN NT_STATUS Status
// );
//
//
#if DBG
#define DebugBreakOnStatus(S) { \
if (FatTestRaisedStatus) { \ if ((S) == STATUS_DISK_CORRUPT_ERROR || (S) == STATUS_FILE_CORRUPT_ERROR) { \ DbgPrint( "FAT: Breaking on interesting raised status (%08x)\n", (S) ); \ DbgPrint( "FAT: Set FatTestRaisedStatus @ %08x to 0 to disable\n", \ &FatTestRaisedStatus ); \ DbgBreakPoint(); \ } \ } \ } #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; 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))
#endif // _FATPROCS_
|