You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
450 lines
12 KiB
450 lines
12 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
FsRtlP.h
|
|
|
|
Abstract:
|
|
|
|
This module defines private part of the File System Rtl component
|
|
|
|
Author:
|
|
|
|
Gary Kimura [GaryKi] 30-Jul-1990
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#ifndef _FSRTLP_
|
|
#define _FSRTLP_
|
|
|
|
#pragma warning(disable:4214) // bit field types other than int
|
|
#pragma warning(disable:4201) // nameless struct/union
|
|
#pragma warning(disable:4127) // condition expression is constant
|
|
#pragma warning(disable:4115) // named type definition in parentheses
|
|
#pragma warning(disable:4706) // assignment within conditional expression
|
|
|
|
#include <ntos.h>
|
|
#include <FsRtl.h>
|
|
#include <NtDdFt.h>
|
|
#include <zwapi.h>
|
|
|
|
#define FsRtlAllocatePool(PoolType, NumberOfBytes ) \
|
|
ExAllocatePoolWithTag((POOL_TYPE)((PoolType) | POOL_RAISE_IF_ALLOCATION_FAILURE), \
|
|
NumberOfBytes, \
|
|
'trSF')
|
|
|
|
|
|
#define FsRtlAllocatePoolWithQuota(PoolType, NumberOfBytes ) \
|
|
ExAllocatePoolWithQuotaTag((POOL_TYPE)((PoolType) | POOL_RAISE_IF_ALLOCATION_FAILURE), \
|
|
NumberOfBytes, \
|
|
'trSF')
|
|
|
|
#define FsRtlpAllocatePool(a,b) FsRtlAllocatePoolWithTag((a),(b),MODULE_POOL_TAG)
|
|
|
|
//
|
|
// The global FsRtl debug level variable, its values are:
|
|
//
|
|
// 0x00000000 Always gets printed (used when about to bug check)
|
|
//
|
|
// 0x00000001 Error conditions
|
|
// 0x00000002 Debug hooks
|
|
// 0x00000004
|
|
// 0x00000008
|
|
//
|
|
// 0x00000010
|
|
// 0x00000020
|
|
// 0x00000040
|
|
// 0x00000080
|
|
//
|
|
// 0x00000100
|
|
// 0x00000200
|
|
// 0x00000400
|
|
// 0x00000800
|
|
//
|
|
// 0x00001000
|
|
// 0x00002000
|
|
// 0x00004000
|
|
// 0x00008000
|
|
//
|
|
// 0x00010000
|
|
// 0x00020000
|
|
// 0x00040000
|
|
// 0x00080000
|
|
//
|
|
// 0x00100000
|
|
// 0x00200000
|
|
// 0x00400000
|
|
// 0x00800000
|
|
//
|
|
// 0x01000000
|
|
// 0x02000000
|
|
// 0x04000000 NotifyChange routines
|
|
// 0x08000000 Oplock routines
|
|
//
|
|
// 0x10000000 Name routines
|
|
// 0x20000000 FileLock routines
|
|
// 0x40000000 Vmcb routines
|
|
// 0x80000000 Mcb routines
|
|
//
|
|
|
|
//
|
|
// Debug trace support
|
|
//
|
|
|
|
#ifdef FSRTLDBG
|
|
|
|
extern LONG FsRtlDebugTraceLevel;
|
|
extern LONG FsRtlDebugTraceIndent;
|
|
|
|
#define DebugTrace(INDENT,LEVEL,X,Y) { \
|
|
LONG _i; \
|
|
if (((LEVEL) == 0) || (FsRtlDebugTraceLevel & (LEVEL))) { \
|
|
_i = (ULONG)PsGetCurrentThread(); \
|
|
DbgPrint("%08lx:",_i); \
|
|
if ((INDENT) < 0) { \
|
|
FsRtlDebugTraceIndent += (INDENT); \
|
|
} \
|
|
if (FsRtlDebugTraceIndent < 0) { \
|
|
FsRtlDebugTraceIndent = 0; \
|
|
} \
|
|
for (_i=0; _i<FsRtlDebugTraceIndent; _i+=1) { \
|
|
DbgPrint(" "); \
|
|
} \
|
|
DbgPrint(X,Y); \
|
|
if ((INDENT) > 0) { \
|
|
FsRtlDebugTraceIndent += (INDENT); \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
#define DebugDump(STR,LEVEL,PTR) { \
|
|
ULONG _i; \
|
|
VOID FsRtlDump(); \
|
|
if (((LEVEL) == 0) || (FsRtlDebugTraceLevel & (LEVEL))) { \
|
|
_i = (ULONG)PsGetCurrentThread(); \
|
|
DbgPrint("%08lx:",_i); \
|
|
DbgPrint(STR); \
|
|
if (PTR != NULL) {FsRtlDump(PTR);} \
|
|
DbgBreakPoint(); \
|
|
} \
|
|
}
|
|
|
|
#else
|
|
|
|
#define DebugTrace(INDENT,LEVEL,X,Y) {NOTHING;}
|
|
|
|
#define DebugDump(STR,LEVEL,PTR) {NOTHING;}
|
|
|
|
#endif // FSRTLDBG
|
|
|
|
|
|
//
|
|
// Miscellaneous support routines
|
|
//
|
|
|
|
VOID
|
|
FsRtlInitializeFileLocks (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
FsRtlInitializeLargeMcbs (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
FsRtlInitializeTunnels(
|
|
VOID
|
|
);
|
|
|
|
NTSTATUS
|
|
FsRtlInitializeWorkerThread (
|
|
VOID
|
|
);
|
|
|
|
//
|
|
// This macro returns TRUE if a flag in a set of flags is on and FALSE
|
|
// otherwise
|
|
//
|
|
|
|
#define FlagOn(Flags,SingleFlag) ((Flags) & (SingleFlag))
|
|
|
|
#define BooleanFlagOn(Flags,SingleFlag) ((BOOLEAN)(((Flags) & (SingleFlag)) != 0))
|
|
|
|
#define SetFlag(F,SF) { \
|
|
(F) |= (SF); \
|
|
}
|
|
|
|
#define ClearFlag(F,SF) { \
|
|
(F) &= ~(SF); \
|
|
}
|
|
|
|
//
|
|
// This macro takes a pointer (or ulong) and returns its rounded up word
|
|
// value
|
|
//
|
|
|
|
#define WordAlign(Ptr) ( \
|
|
((((ULONG_PTR)(Ptr)) + 1) & -2) \
|
|
)
|
|
|
|
//
|
|
// This macro takes a pointer (or ulong) and returns its rounded up longword
|
|
// value
|
|
//
|
|
|
|
#define LongAlign(Ptr) ( \
|
|
((((ULONG_PTR)(Ptr)) + 3) & -4) \
|
|
)
|
|
|
|
//
|
|
// This macro takes a pointer (or ulong) and returns its rounded up quadword
|
|
// value
|
|
//
|
|
|
|
#define QuadAlign(Ptr) ( \
|
|
((((ULONG_PTR)(Ptr)) + 7) & -8) \
|
|
)
|
|
|
|
//
|
|
// This macro takes a ulong and returns its value rounded up to a sector
|
|
// boundary
|
|
//
|
|
|
|
#define SectorAlign(Ptr) ( \
|
|
((((ULONG_PTR)(Ptr)) + 511) & -512) \
|
|
)
|
|
|
|
//
|
|
// This macro takes a number of bytes and returns the number of sectors
|
|
// required to contain that many bytes, i.e., it sector aligns and divides
|
|
// by the size of a sector.
|
|
//
|
|
|
|
#define SectorsFromBytes(bytes) ( \
|
|
((bytes) + 511) / 512 \
|
|
)
|
|
|
|
//
|
|
// This macro takes a number of sectors and returns the number of bytes
|
|
// contained in that many sectors.
|
|
//
|
|
|
|
#define BytesFromSectors(sectors) ( \
|
|
(sectors) * 512 \
|
|
)
|
|
|
|
//
|
|
// 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)); \
|
|
}
|
|
|
|
|
|
//
|
|
// 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 GET_FAST_IO_DISPATCH(DevObj) \
|
|
((DevObj)->DriverObject->FastIoDispatch)
|
|
|
|
#define GET_FS_FILTER_CALLBACKS(DevObj) \
|
|
((DevObj)->DriverObject->DriverExtension->FsFilterCallbacks)
|
|
|
|
//
|
|
// Macro for validating the FastIo dispatch routines before calling
|
|
// them in the FastIo pass through functions.
|
|
//
|
|
|
|
#define VALID_FAST_IO_DISPATCH_HANDLER(FastIoDispatchPtr, FieldName) \
|
|
(((FastIoDispatchPtr) != NULL) && \
|
|
(((FastIoDispatchPtr)->SizeOfFastIoDispatch) >= \
|
|
(FIELD_OFFSET(FAST_IO_DISPATCH, FieldName) + sizeof(VOID *))) && \
|
|
((FastIoDispatchPtr)->FieldName != NULL))
|
|
|
|
#define VALID_FS_FILTER_CALLBACK_HANDLER(FsFilterCallbackPtr, FieldName) \
|
|
(((FsFilterCallbackPtr) != NULL) && \
|
|
(((FsFilterCallbackPtr)->SizeOfFsFilterCallbacks) >= \
|
|
(FIELD_OFFSET(FS_FILTER_CALLBACKS, FieldName) + sizeof(VOID *))) && \
|
|
((FsFilterCallbackPtr)->FieldName != NULL))
|
|
|
|
#define FSRTL_FILTER_MEMORY_TAG 'gmSF'
|
|
|
|
typedef struct _FS_FILTER_COMPLETION_NODE {
|
|
|
|
PDEVICE_OBJECT DeviceObject;
|
|
PFILE_OBJECT FileObject;
|
|
PVOID CompletionContext;
|
|
PFS_FILTER_COMPLETION_CALLBACK CompletionCallback;
|
|
|
|
} FS_FILTER_COMPLETION_NODE, *PFS_FILTER_COMPLETION_NODE;
|
|
|
|
#define FS_FILTER_DEFAULT_STACK_SIZE 15
|
|
|
|
typedef struct _FS_FILTER_COMPLETION_STACK {
|
|
|
|
USHORT StackLength;
|
|
USHORT NextStackPosition;
|
|
PFS_FILTER_COMPLETION_NODE Stack;
|
|
FS_FILTER_COMPLETION_NODE DefaultStack[FS_FILTER_DEFAULT_STACK_SIZE];
|
|
|
|
} FS_FILTER_COMPLETION_STACK, *PFS_FILTER_COMPLETION_STACK;
|
|
|
|
typedef struct _FS_FILTER_CTRL {
|
|
|
|
FS_FILTER_CALLBACK_DATA Data;
|
|
|
|
ULONG Flags;
|
|
ULONG Reserved;
|
|
|
|
FS_FILTER_COMPLETION_STACK CompletionStack;
|
|
|
|
} FS_FILTER_CTRL, *PFS_FILTER_CTRL;
|
|
|
|
//
|
|
// Flag values for FS_FILTER_CTRL
|
|
//
|
|
|
|
#define FS_FILTER_ALLOCATED_COMPLETION_STACK 0x00000001
|
|
#define FS_FILTER_USED_RESERVE_POOL 0x00000002
|
|
#define FS_FILTER_CHANGED_DEVICE_STACKS 0x00000004
|
|
|
|
NTSTATUS
|
|
FsFilterInit(
|
|
);
|
|
|
|
NTSTATUS
|
|
FsFilterAllocateCompletionStack (
|
|
IN PFS_FILTER_CTRL FsFilterCtrl,
|
|
IN BOOLEAN CanFail,
|
|
OUT PULONG AllocationSize
|
|
);
|
|
|
|
VOID
|
|
FsFilterFreeCompletionStack (
|
|
IN PFS_FILTER_CTRL FsFilterCtrl
|
|
);
|
|
|
|
NTSTATUS
|
|
FsFilterCtrlInit (
|
|
IN OUT PFS_FILTER_CTRL FsFilterCtrl,
|
|
IN UCHAR Operation,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PDEVICE_OBJECT BaseFsDeviceObject,
|
|
IN PFILE_OBJECT FileObject,
|
|
IN BOOLEAN CanFail
|
|
);
|
|
|
|
VOID
|
|
FsFilterCtrlFree (
|
|
IN PFS_FILTER_CTRL FsFilterCtrl
|
|
);
|
|
|
|
#define PUSH_COMPLETION_NODE( completionStack ) \
|
|
(((completionStack)->NextStackPosition < (completionStack)->StackLength ) ? \
|
|
&(completionStack)->Stack[(completionStack)->NextStackPosition++] : \
|
|
(ASSERT( FALSE ), NULL) )
|
|
|
|
#define POP_COMPLETION_NODE( completionStack ) \
|
|
(ASSERT((completionStack)->NextStackPosition > 0), \
|
|
((completionStack)->NextStackPosition--))
|
|
|
|
#define GET_COMPLETION_NODE( completionStack ) \
|
|
(ASSERT((completionStack)->NextStackPosition > 0),\
|
|
(&(completionStack)->Stack[(completionStack)->NextStackPosition-1]))
|
|
|
|
#define FS_FILTER_HAVE_COMPLETIONS( fsFilterCtrl ) \
|
|
((fsFilterCtrl)->CompletionStack.NextStackPosition > 0)
|
|
|
|
VOID
|
|
FsFilterGetCallbacks (
|
|
IN UCHAR Operation,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
OUT PFS_FILTER_CALLBACK *PreOperationCallback,
|
|
OUT PFS_FILTER_COMPLETION_CALLBACK *PostOperationCallback
|
|
);
|
|
|
|
NTSTATUS
|
|
FsFilterPerformCallbacks (
|
|
IN PFS_FILTER_CTRL FsFilterCtrl,
|
|
IN BOOLEAN AllowFilterToFail,
|
|
IN BOOLEAN AllowBaseFsToFail,
|
|
OUT BOOLEAN *BaseFsFailedOp
|
|
);
|
|
|
|
VOID
|
|
FsFilterPerformCompletionCallbacks(
|
|
IN PFS_FILTER_CTRL FsFilterCtrl,
|
|
IN NTSTATUS OperationStatus
|
|
);
|
|
|
|
|
|
#endif // _FSRTLP_
|