2526 lines
59 KiB
C
2526 lines
59 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989-2000 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
UdfProcs.h
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module defines all of the globally used procedures in the Udfs
|
|||
|
file system.
|
|||
|
|
|||
|
// @@BEGIN_DDKSPLIT
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Dan Lovinger [DanLo] 29-May-1996
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
Tom Jolly [TomJolly] 1-March-2000 UDF 2.01 support
|
|||
|
|
|||
|
// @@END_DDKSPLIT
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#ifndef _UDFPROCS_
|
|||
|
#define _UDFPROCS_
|
|||
|
|
|||
|
#include <ntifs.h>
|
|||
|
|
|||
|
#include <ntddcdrm.h>
|
|||
|
#include <ntddcdvd.h>
|
|||
|
#include <ntdddisk.h>
|
|||
|
|
|||
|
#ifndef INLINE
|
|||
|
#define INLINE __inline
|
|||
|
#endif
|
|||
|
|
|||
|
#include "nodetype.h"
|
|||
|
#include "Udf.h"
|
|||
|
#include "UdfStruc.h"
|
|||
|
#include "UdfData.h"
|
|||
|
|
|||
|
//
|
|||
|
// The Bug check file id for this module
|
|||
|
//
|
|||
|
|
|||
|
#define BugCheckFileId (UDFS_BUG_CHECK_STRUCSUP)
|
|||
|
|
|||
|
//
|
|||
|
// The local debug trace level
|
|||
|
//
|
|||
|
|
|||
|
#define Dbg (UDFS_DEBUG_LEVEL_STRUCSUP)
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Miscellaneous support routines/macros
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// Yet another declaration of Min/Max
|
|||
|
//
|
|||
|
|
|||
|
#ifndef Min
|
|||
|
#define Min(a, b) ((a) < (b) ? (a) : (b))
|
|||
|
#endif
|
|||
|
|
|||
|
#ifndef Max
|
|||
|
#define Max(a, b) ((a) > (b) ? (a) : (b))
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Yet another declaration of the basic bit fiddlers
|
|||
|
//
|
|||
|
|
|||
|
#ifndef FlagMask
|
|||
|
#define FlagMask(F,SF) ( \
|
|||
|
((F) & (SF)) \
|
|||
|
)
|
|||
|
#endif
|
|||
|
|
|||
|
//#ifndef BooleanFlagOn
|
|||
|
//#define BooleanFlagOn(F,SF) ( \
|
|||
|
// (BOOLEAN)(FlagOn(F, SF) != 0) \
|
|||
|
//)
|
|||
|
//#endif
|
|||
|
|
|||
|
#ifndef BooleanFlagOff
|
|||
|
#define BooleanFlagOff(F,SF) ( \
|
|||
|
(BOOLEAN)(FlagOn(F, SF)) == 0) \
|
|||
|
)
|
|||
|
#endif
|
|||
|
|
|||
|
//#ifndef SetFlag
|
|||
|
//#define SetFlag(Flags,SingleFlag) ( \
|
|||
|
// (Flags) |= (SingleFlag) \
|
|||
|
//)
|
|||
|
//#endif
|
|||
|
|
|||
|
//#ifndef ClearFlag
|
|||
|
//#define ClearFlag(Flags,SingleFlag) ( \
|
|||
|
// (Flags) &= ~(SingleFlag) \
|
|||
|
//)
|
|||
|
//#endif
|
|||
|
|
|||
|
//
|
|||
|
// CAST
|
|||
|
// Add2Ptr (
|
|||
|
// IN PVOID Pointer,
|
|||
|
// IN ULONG Increment
|
|||
|
// IN (CAST)
|
|||
|
// );
|
|||
|
//
|
|||
|
// ULONG
|
|||
|
// PtrOffset (
|
|||
|
// IN PVOID BasePtr,
|
|||
|
// IN PVOID OffsetPtr
|
|||
|
// );
|
|||
|
//
|
|||
|
|
|||
|
#define Add2Ptr(PTR,INC,CAST) ((CAST)((ULONG_PTR)(PTR) + (INC)))
|
|||
|
|
|||
|
#define PtrOffset(BASE,OFFSET) ((ULONG)((ULONG)(OFFSET) - (ULONG)(BASE)))
|
|||
|
|
|||
|
//
|
|||
|
// Generic truncation/align/offset/remainder macros for power-of-two units.
|
|||
|
//
|
|||
|
// The offset and remainder functions range from zero to (unit - 1). The
|
|||
|
// re-offset in the remainder performs this work.
|
|||
|
//
|
|||
|
|
|||
|
#define GenericTruncate(B, U) ( \
|
|||
|
(B) & ~((U) - 1) \
|
|||
|
)
|
|||
|
|
|||
|
#define GenericAlign(B, U) ( \
|
|||
|
GenericTruncate((B) + (U) - 1, U) \
|
|||
|
)
|
|||
|
|
|||
|
#define GenericOffset(B, U) ( \
|
|||
|
(B) & ((U) - 1) \
|
|||
|
)
|
|||
|
|
|||
|
#define GenericRemainder(B, U) ( \
|
|||
|
GenericOffset( (U) - GenericOffset((B), (U)), (U) ) \
|
|||
|
)
|
|||
|
|
|||
|
|
|||
|
#define GenericTruncatePtr(B, U) ( \
|
|||
|
(PVOID)(((ULONG_PTR)(B)) & ~((U) - 1)) \
|
|||
|
)
|
|||
|
|
|||
|
#define GenericAlignPtr(B, U) ( \
|
|||
|
GenericTruncatePtr((B) + (U) - 1, (U)) \
|
|||
|
)
|
|||
|
|
|||
|
#define GenericOffsetPtr(B, U) ( \
|
|||
|
(ULONG)(((ULONG_PTR)(B)) & ((U) - 1)) \
|
|||
|
)
|
|||
|
|
|||
|
#define GenericRemainderPtr(B, U) ( \
|
|||
|
(ULONG)GenericOffset( (U) - GenericOffsetPtr((B), (U)), (U) ) \
|
|||
|
)
|
|||
|
|
|||
|
//
|
|||
|
// Useful compositions of the defaults for common types.
|
|||
|
//
|
|||
|
|
|||
|
#define WordAlign(B) GenericAlign((B), 2)
|
|||
|
|
|||
|
#define LongAlign(B) GenericAlign((B), 4)
|
|||
|
|
|||
|
#define QuadAlign(B) GenericAlign((B), 8)
|
|||
|
|
|||
|
|
|||
|
#define WordOffset(B) GenericOffset((B), 2)
|
|||
|
|
|||
|
#define LongOffset(B) GenericOffset((B), 4)
|
|||
|
|
|||
|
#define QuadOffset(B) GenericOffset((B), 8)
|
|||
|
|
|||
|
|
|||
|
#define WordAlignPtr(P) GenericAlignPtr((P), 2)
|
|||
|
|
|||
|
#define LongAlignPtr(P) GenericAlignPtr((P), 4)
|
|||
|
|
|||
|
#define QuadAlignPtr(P) GenericAlignPtr((P), 8)
|
|||
|
|
|||
|
|
|||
|
#define WordOffsetPtr(P) GenericOffsetPtr((P), 2)
|
|||
|
|
|||
|
#define LongOffsetPtr(P) GenericOffsetPtr((P), 4)
|
|||
|
|
|||
|
#define QuadOffsetPtr(P) GenericOffsetPtr((P), 8)
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Macros to round up and down on sector and logical block boundaries. Although
|
|||
|
// UDF 1.01 specifies that a physical sector is the logical block size we will
|
|||
|
// be general and treat sectors and logical blocks as distinct. Since UDF may
|
|||
|
// at some point relax the restriction, these definitions will be the only
|
|||
|
// acknowledgement outside of the mount path (which merely checks the volume's
|
|||
|
// conformance).
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// Sector
|
|||
|
//
|
|||
|
|
|||
|
#define SectorAlignN(SECTORSIZE, L) ( \
|
|||
|
((((ULONG)(L)) + ((SECTORSIZE) - 1)) & ~((SECTORSIZE) - 1)) \
|
|||
|
)
|
|||
|
|
|||
|
#define SectorAlign(V, L) ( \
|
|||
|
((((ULONG)(L)) + (((V)->SectorSize) - 1)) & ~(((V)->SectorSize) - 1)) \
|
|||
|
)
|
|||
|
|
|||
|
#define LlSectorAlign(V, L) ( \
|
|||
|
((((LONGLONG)(L)) + (((V)->SectorSize) - 1)) & ~(((LONGLONG)(V)->SectorSize) - 1)) \
|
|||
|
)
|
|||
|
|
|||
|
#define SectorTruncate(V, L) ( \
|
|||
|
((ULONG)(L)) & ~(((V)->SectorSize) - 1) \
|
|||
|
)
|
|||
|
|
|||
|
#define LlSectorTruncate(V, L) ( \
|
|||
|
((LONGLONG)(L)) & ~(((LONGLONG)(V)->SectorSize) - 1) \
|
|||
|
)
|
|||
|
|
|||
|
#define BytesFromSectors(V, L) ( \
|
|||
|
((ULONG) (L)) << ((V)->SectorShift) \
|
|||
|
)
|
|||
|
|
|||
|
#define SectorsFromBytes(V, L) ( \
|
|||
|
((ULONG) (L)) >> ((V)->SectorShift) \
|
|||
|
)
|
|||
|
|
|||
|
#define LlBytesFromSectors(V, L) ( \
|
|||
|
Int64ShllMod32( (ULONGLONG)(L), ((V)->SectorShift) ) \
|
|||
|
)
|
|||
|
|
|||
|
#define LlSectorsFromBytes(V, L) ( \
|
|||
|
Int64ShrlMod32( (ULONGLONG)(L), ((V)->SectorShift) ) \
|
|||
|
)
|
|||
|
|
|||
|
#define SectorsFromBlocks(V, B) (B)
|
|||
|
|
|||
|
#define SectorSize(V) ((V)->SectorSize)
|
|||
|
|
|||
|
#define SectorOffset(V, L) ( \
|
|||
|
((ULONG) (L)) & (((V)->SectorSize) - 1) \
|
|||
|
)
|
|||
|
|
|||
|
//
|
|||
|
// Logical Block
|
|||
|
//
|
|||
|
|
|||
|
#define BlockAlignN(BLOCKSIZE, L) ( \
|
|||
|
SectorAlighN((BLOCKSIZE), (L)) \
|
|||
|
)
|
|||
|
|
|||
|
#define BlockAlign(V, L) ( \
|
|||
|
SectorAlign((V), (L)) \
|
|||
|
)
|
|||
|
|
|||
|
#define LlBlockAlign(V, L) ( \
|
|||
|
LlSectorAlign((V), (L)) \
|
|||
|
)
|
|||
|
|
|||
|
#define BlockTruncate(V, L) ( \
|
|||
|
SectorTruncate((V), (L)) \
|
|||
|
)
|
|||
|
|
|||
|
#define LlBlockTruncate(V, L) ( \
|
|||
|
LlSectorTruncate((V), (L)) \
|
|||
|
)
|
|||
|
|
|||
|
#define BytesFromBlocks(V, L) ( \
|
|||
|
BytesFromSectors((V), (L)) \
|
|||
|
)
|
|||
|
|
|||
|
#define BlocksFromBytes(V, L) ( \
|
|||
|
SectorsFromBytes((V), (L)) \
|
|||
|
)
|
|||
|
|
|||
|
#define LlBytesFromBlocks(V, L) ( \
|
|||
|
LlBytesFromSectors((V), (L)) \
|
|||
|
)
|
|||
|
|
|||
|
#define LlBlocksFromBytes(V, L) ( \
|
|||
|
LlSectorsFromBytes((V), (L)) \
|
|||
|
)
|
|||
|
|
|||
|
#define BlocksFromSectors(V, S) (S)
|
|||
|
|
|||
|
#define BlockSize(V) (SectorSize(V))
|
|||
|
|
|||
|
#define BlockOffset(V, L) ( \
|
|||
|
SectorOffset((V), (L)) \
|
|||
|
)
|
|||
|
|
|||
|
//
|
|||
|
// The following types and macros are used to help unpack the packed and
|
|||
|
// misaligned fields found in various structures.
|
|||
|
//
|
|||
|
|
|||
|
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;
|
|||
|
|
|||
|
typedef union _USHORT2 {
|
|||
|
USHORT Ushort[2];
|
|||
|
ULONG ForceAlignment;
|
|||
|
} USHORT2, *PUSHORT2;
|
|||
|
|
|||
|
//
|
|||
|
// 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 word to a dst word,
|
|||
|
// performing an little/big endian swap.
|
|||
|
//
|
|||
|
|
|||
|
#define SwapCopyUchar2(Dst,Src) { \
|
|||
|
*((UNALIGNED UCHAR1 *)(Dst)) = *((UNALIGNED UCHAR1 *)(Src) + 1); \
|
|||
|
*((UNALIGNED UCHAR1 *)(Dst) + 1) = *((UNALIGNED UCHAR1 *)(Src)); \
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// This macro copies an unaligned src longword to an aligned dst longword
|
|||
|
//
|
|||
|
|
|||
|
#define CopyUchar4(Dst,Src) { \
|
|||
|
*((UCHAR4 *)(Dst)) = *((UNALIGNED UCHAR4 *)(Src)); \
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// This macro copies an unaligned src longword to a dst longword,
|
|||
|
// performing an little/big endian swap.
|
|||
|
//
|
|||
|
|
|||
|
#define SwapCopyUchar4(Dst,Src) { \
|
|||
|
*((UNALIGNED UCHAR1 *)(Dst)) = *((UNALIGNED UCHAR1 *)(Src) + 3); \
|
|||
|
*((UNALIGNED UCHAR1 *)(Dst) + 1) = *((UNALIGNED UCHAR1 *)(Src) + 2); \
|
|||
|
*((UNALIGNED UCHAR1 *)(Dst) + 2) = *((UNALIGNED UCHAR1 *)(Src) + 1); \
|
|||
|
*((UNALIGNED UCHAR1 *)(Dst) + 3) = *((UNALIGNED UCHAR1 *)(Src)); \
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// This macro copies an unaligned src longword to an aligned dsr longword
|
|||
|
// accessing the source on a word boundary.
|
|||
|
//
|
|||
|
|
|||
|
#define CopyUshort2(Dst,Src) { \
|
|||
|
*((USHORT2 *)(Dst)) = *((UNALIGNED USHORT2 *)(Src));\
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// 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(I) IoIsOperationSynchronous(I)
|
|||
|
|
|||
|
//
|
|||
|
// The following macro is used to set the fast i/o possible bits in the
|
|||
|
// FsRtl header.
|
|||
|
//
|
|||
|
// FastIoIsNotPossible - If the Fcb is bad or there are oplocks on the file.
|
|||
|
//
|
|||
|
// FastIoIsQuestionable - If there are file locks.
|
|||
|
//
|
|||
|
// FastIoIsPossible - In all other cases.
|
|||
|
//
|
|||
|
//
|
|||
|
|
|||
|
#define UdfIsFastIoPossible(F) ((BOOLEAN) \
|
|||
|
((((F)->Vcb->VcbCondition != VcbMounted ) || \
|
|||
|
!FsRtlOplockIsFastIoPossible( &(F)->Oplock )) ? \
|
|||
|
\
|
|||
|
FastIoIsNotPossible : \
|
|||
|
\
|
|||
|
((((F)->FileLock != NULL) && FsRtlAreThereCurrentFileLocks( (F)->FileLock )) ? \
|
|||
|
\
|
|||
|
FastIoIsQuestionable : \
|
|||
|
\
|
|||
|
FastIoIsPossible)) \
|
|||
|
)
|
|||
|
|
|||
|
//
|
|||
|
// The following macros encapsulate the common work of raising exceptions while storing
|
|||
|
// the exception in the IrpContext.
|
|||
|
//
|
|||
|
|
|||
|
INLINE
|
|||
|
DECLSPEC_NORETURN
|
|||
|
VOID
|
|||
|
UdfRaiseStatus (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN NTSTATUS Status
|
|||
|
)
|
|||
|
{
|
|||
|
IrpContext->ExceptionStatus = Status;
|
|||
|
DebugBreakOnStatus( Status );
|
|||
|
ExRaiseStatus( Status );
|
|||
|
}
|
|||
|
|
|||
|
INLINE
|
|||
|
VOID
|
|||
|
UdfNormalizeAndRaiseStatus (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN NTSTATUS Status
|
|||
|
)
|
|||
|
{
|
|||
|
IrpContext->ExceptionStatus = FsRtlNormalizeNtstatus( Status, STATUS_UNEXPECTED_IO_ERROR );
|
|||
|
ExRaiseStatus( IrpContext->ExceptionStatus );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// The following is a convenience macro to execute a little code before making
|
|||
|
// a shortcircuit out of a surrounding try-finally clause. This is usually to
|
|||
|
// set a status value.
|
|||
|
//
|
|||
|
// Note that our compilers support the leave keyword now and we don't have to
|
|||
|
// use the old try_exit: labels and goto.
|
|||
|
//
|
|||
|
|
|||
|
#define try_leave(S) { S; leave; }
|
|||
|
|
|||
|
//
|
|||
|
// For debugging purposes we sometimes want to allocate our structures from nonpaged
|
|||
|
// pool so that in the kernel debugger we can walk all the structures.
|
|||
|
//
|
|||
|
|
|||
|
#define UdfPagedPool PagedPool
|
|||
|
#define UdfNonPagedPool NonPagedPool
|
|||
|
#define UdfNonPagedPoolCacheAligned NonPagedPoolCacheAligned
|
|||
|
|
|||
|
//
|
|||
|
// Encapsulate safe pool freeing
|
|||
|
//
|
|||
|
|
|||
|
INLINE
|
|||
|
VOID
|
|||
|
UdfFreePool(
|
|||
|
IN PVOID *Pool
|
|||
|
)
|
|||
|
{
|
|||
|
if (*Pool != NULL) {
|
|||
|
|
|||
|
ExFreePool(*Pool);
|
|||
|
*Pool = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Encapsulate counted string compares with uncounted fields. Thanks to a
|
|||
|
// very smart compiler, we have to carefully tell it that no matter what it
|
|||
|
// thinks, it *cannot* do anything other than a bytewise compare.
|
|||
|
//
|
|||
|
|
|||
|
INLINE
|
|||
|
BOOLEAN
|
|||
|
UdfEqualCountedString(
|
|||
|
IN PSTRING String,
|
|||
|
IN PCHAR Field
|
|||
|
)
|
|||
|
{
|
|||
|
return (RtlEqualMemory( (CHAR UNALIGNED *)String->Buffer,
|
|||
|
(CHAR UNALIGNED *)Field,
|
|||
|
String->Length ) != 0);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Type of opens. FilObSup.c depends on this order.
|
|||
|
//
|
|||
|
|
|||
|
typedef enum _TYPE_OF_OPEN {
|
|||
|
|
|||
|
UnopenedFileObject = 0,
|
|||
|
StreamFileOpen,
|
|||
|
UserVolumeOpen,
|
|||
|
UserDirectoryOpen,
|
|||
|
UserFileOpen,
|
|||
|
BeyondValidType
|
|||
|
|
|||
|
} TYPE_OF_OPEN, *PTYPE_OF_OPEN;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Following routines handle entry in and out of the filesystem. They are
|
|||
|
// contained in UdfData.c. We also get some very generic utility functions
|
|||
|
// here that aren't associated with any particular datastructure.
|
|||
|
//
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
UdfFsdDispatch (
|
|||
|
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
|
|||
|
IN PIRP Irp
|
|||
|
);
|
|||
|
|
|||
|
LONG
|
|||
|
UdfExceptionFilter (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PEXCEPTION_POINTERS ExceptionPointer
|
|||
|
);
|
|||
|
|
|||
|
LONG
|
|||
|
UdfQueryDirExceptionFilter(
|
|||
|
IN PEXCEPTION_POINTERS ExceptionPointers
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
UdfProcessException (
|
|||
|
IN PIRP_CONTEXT IrpContext OPTIONAL,
|
|||
|
IN PIRP Irp,
|
|||
|
IN NTSTATUS ExceptionCode
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfCompleteRequest (
|
|||
|
IN PIRP_CONTEXT IrpContext OPTIONAL,
|
|||
|
IN PIRP Irp OPTIONAL,
|
|||
|
IN NTSTATUS Status
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Following are the routines to handle the top level thread logic.
|
|||
|
//
|
|||
|
|
|||
|
VOID
|
|||
|
UdfSetThreadContext (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PTHREAD_CONTEXT ThreadContext
|
|||
|
);
|
|||
|
|
|||
|
INLINE
|
|||
|
VOID
|
|||
|
UdfRestoreThreadContext (
|
|||
|
IN PIRP_CONTEXT IrpContext
|
|||
|
)
|
|||
|
{
|
|||
|
IrpContext->ThreadContext->Udfs = 0;
|
|||
|
IoSetTopLevelIrp( IrpContext->ThreadContext->SavedTopLevelIrp );
|
|||
|
IrpContext->ThreadContext = NULL;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Following are some generic utility functions we have to carry along for the ride
|
|||
|
//
|
|||
|
|
|||
|
INLINE
|
|||
|
BOOLEAN
|
|||
|
UdfDeviceIsFsDo(
|
|||
|
IN PDEVICE_OBJECT Device
|
|||
|
)
|
|||
|
{
|
|||
|
#if (NUMBER_OF_FS_OBJECTS != 2)
|
|||
|
#error "Size of fsdo array changed - fixme!"
|
|||
|
#endif
|
|||
|
|
|||
|
return (Device == UdfData.FileSystemDeviceObjects[0]) ||
|
|||
|
(Device == UdfData.FileSystemDeviceObjects[1]);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
ULONG
|
|||
|
UdfSerial32 (
|
|||
|
IN PCHAR Buffer,
|
|||
|
IN ULONG ByteCount
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfInitializeCrc16 (
|
|||
|
ULONG Polynomial
|
|||
|
);
|
|||
|
|
|||
|
USHORT
|
|||
|
UdfComputeCrc16 (
|
|||
|
IN PUCHAR Buffer,
|
|||
|
IN ULONG ByteCount
|
|||
|
);
|
|||
|
|
|||
|
USHORT
|
|||
|
UdfComputeCrc16Uni (
|
|||
|
PWCHAR Buffer,
|
|||
|
ULONG CharCount
|
|||
|
);
|
|||
|
|
|||
|
ULONG
|
|||
|
UdfHighBit (
|
|||
|
ULONG Word
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Following are the fast entry points.
|
|||
|
//
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfFastQueryBasicInfo (
|
|||
|
IN PFILE_OBJECT FileObject,
|
|||
|
IN BOOLEAN Wait,
|
|||
|
IN OUT PFILE_BASIC_INFORMATION Buffer,
|
|||
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|||
|
IN PDEVICE_OBJECT DeviceObject
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfFastIoCheckIfPossible (
|
|||
|
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
|
|||
|
UdfFastLock (
|
|||
|
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
|
|||
|
UdfFastQueryNetworkInfo (
|
|||
|
IN PFILE_OBJECT FileObject,
|
|||
|
IN BOOLEAN Wait,
|
|||
|
OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
|
|||
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|||
|
IN PDEVICE_OBJECT DeviceObject
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfFastQueryStdInfo (
|
|||
|
IN PFILE_OBJECT FileObject,
|
|||
|
IN BOOLEAN Wait,
|
|||
|
IN OUT PFILE_STANDARD_INFORMATION Buffer,
|
|||
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|||
|
IN PDEVICE_OBJECT DeviceObject
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfFastUnlockSingle (
|
|||
|
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
|
|||
|
UdfFastUnlockAll (
|
|||
|
IN PFILE_OBJECT FileObject,
|
|||
|
PEPROCESS ProcessId,
|
|||
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|||
|
IN PDEVICE_OBJECT DeviceObject
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfFastUnlockAllByKey (
|
|||
|
IN PFILE_OBJECT FileObject,
|
|||
|
PVOID ProcessId,
|
|||
|
ULONG Key,
|
|||
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|||
|
IN PDEVICE_OBJECT DeviceObject
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// File access check routine, implemented in AcChkSup.c
|
|||
|
//
|
|||
|
|
|||
|
INLINE
|
|||
|
BOOLEAN
|
|||
|
UdfIllegalFcbAccess (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN TYPE_OF_OPEN TypeOfOpen,
|
|||
|
IN ACCESS_MASK DesiredAccess
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine simply asserts that the access is legal for a readonly filesystem.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
TypeOfOpen - type of open for the Fcb in question.
|
|||
|
|
|||
|
DesiredAccess - mask of access the caller is trying for.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOLEAN True if illegal access, false otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
return BooleanFlagOn( DesiredAccess,
|
|||
|
(TypeOfOpen != UserVolumeOpen ?
|
|||
|
(FILE_WRITE_ATTRIBUTES |
|
|||
|
FILE_WRITE_DATA |
|
|||
|
FILE_WRITE_EA |
|
|||
|
FILE_ADD_FILE |
|
|||
|
FILE_ADD_SUBDIRECTORY |
|
|||
|
FILE_APPEND_DATA) : 0) |
|
|||
|
FILE_DELETE_CHILD |
|
|||
|
DELETE |
|
|||
|
WRITE_DAC );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Sector lookup routines, implemented in AllocSup.c
|
|||
|
//
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfLookupAllocation (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PCCB Ccb,
|
|||
|
IN LONGLONG FileOffset,
|
|||
|
OUT PLONGLONG DiskOffset,
|
|||
|
OUT PULONG ByteCount
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfDeletePcb (
|
|||
|
IN PPCB Pcb
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
UdfInitializePcb (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PVCB Vcb,
|
|||
|
IN OUT PPCB *Pcb,
|
|||
|
IN PNSR_LVOL LVD
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfAddToPcb (
|
|||
|
IN PPCB Pcb,
|
|||
|
IN PNSR_PART PartitionDescriptor
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
UdfCompletePcb(
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PVCB Vcb,
|
|||
|
IN PPCB Pcb );
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfEquivalentPcb (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PPCB Pcb1,
|
|||
|
IN PPCB Pcb2
|
|||
|
);
|
|||
|
|
|||
|
ULONG
|
|||
|
UdfLookupPsnOfExtent (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PVCB Vcb,
|
|||
|
IN USHORT Reference,
|
|||
|
IN ULONG Lbn,
|
|||
|
IN ULONG Len
|
|||
|
);
|
|||
|
|
|||
|
ULONG
|
|||
|
UdfLookupMetaVsnOfExtent (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PVCB Vcb,
|
|||
|
IN USHORT Reference,
|
|||
|
IN ULONG Lbn,
|
|||
|
IN ULONG Len,
|
|||
|
IN BOOLEAN ExactEnd
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
//
|
|||
|
// Buffer control routines for data caching, implemented in CacheSup.c
|
|||
|
//
|
|||
|
|
|||
|
VOID
|
|||
|
UdfCreateInternalStream (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PVCB Vcb,
|
|||
|
IN PFCB Fcb
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfDeleteInternalStream (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PFCB Fcb
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
UdfCompleteMdl (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PIRP Irp
|
|||
|
);
|
|||
|
|
|||
|
typedef enum {
|
|||
|
METAMAPOP_INIT_VIEW_ONLY = 0,
|
|||
|
METAMAPOP_REMAP_VIEW,
|
|||
|
METAMAPOP_INIT_AND_MAP
|
|||
|
} MAPMETAOP;
|
|||
|
|
|||
|
VOID
|
|||
|
UdfMapMetadataView (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PMAPPED_PVIEW View,
|
|||
|
IN PVCB Vcb,
|
|||
|
IN USHORT Partition,
|
|||
|
IN ULONG Lbn,
|
|||
|
IN ULONG Length,
|
|||
|
IN MAPMETAOP Operation
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
UdfPurgeVolume (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PVCB Vcb,
|
|||
|
IN BOOLEAN DismountUnderway
|
|||
|
);
|
|||
|
|
|||
|
// VOID
|
|||
|
// UdfUnpinView (
|
|||
|
// IN PIRP_CONTEXT IrpContext,
|
|||
|
// IN PMAPPED_VIEW View
|
|||
|
// );
|
|||
|
//
|
|||
|
//
|
|||
|
// Also releases the Vcb->VmcbMappingResource if the view was actually CcMapped.
|
|||
|
|
|||
|
#define UdfUnpinView(IC,V) \
|
|||
|
if (((V)->Bcb) != NULL) { \
|
|||
|
CcUnpinData( ((V)->Bcb) ); \
|
|||
|
UdfReleaseVmcb( (IC), (IC)->Vcb); \
|
|||
|
((V)->Bcb) = NULL; \
|
|||
|
((V)->View) = NULL; \
|
|||
|
((V)->Vsn) = UDF_INVALID_VSN; \
|
|||
|
}
|
|||
|
|
|||
|
// VOID
|
|||
|
// UdfUnpinData (
|
|||
|
// IN PIRP_CONTEXT IrpContext,
|
|||
|
// IN OUT PBCB *Bcb
|
|||
|
// );
|
|||
|
//
|
|||
|
|
|||
|
#define UdfUnpinData(IC,B) \
|
|||
|
if (*(B) != NULL) { CcUnpinData( *(B) ); *(B) = NULL; }
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Device I/O routines, implemented in DevIoSup.c
|
|||
|
//
|
|||
|
// These routines perform the actual device reads and other communcation.
|
|||
|
// They do not affect any data structures.
|
|||
|
//
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
UdfPerformDevIoCtrl (
|
|||
|
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
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
UdfReadSectors (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN LONGLONG StartingOffset,
|
|||
|
IN ULONG ByteCount,
|
|||
|
IN BOOLEAN ReturnError,
|
|||
|
IN OUT PVOID Buffer,
|
|||
|
IN PDEVICE_OBJECT TargetDeviceObject
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
UdfNonCachedRead (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PCCB Ccb,
|
|||
|
IN LONGLONG StartingOffset,
|
|||
|
IN ULONG ByteCount
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
UdfCreateUserMdl (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN ULONG BufferLength,
|
|||
|
IN BOOLEAN RaiseOnError,
|
|||
|
IN ULONG Operation
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfWaitSync (
|
|||
|
IN PIRP_CONTEXT IrpContext
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfSingleAsync (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN LONGLONG ByteOffset,
|
|||
|
IN ULONG ByteCount
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// UdfMapUserBuffer (
|
|||
|
// IN PIRP_CONTEXT IrpContext,
|
|||
|
// OUT PVOID Buffer
|
|||
|
// );
|
|||
|
//
|
|||
|
// Will raise on failure.
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// UdfLockUserBuffer (
|
|||
|
// IN PIRP_CONTEXT IrpContext,
|
|||
|
// IN ULONG BufferLength
|
|||
|
// );
|
|||
|
//
|
|||
|
|
|||
|
#define UdfMapUserBuffer(IC,UB) { \
|
|||
|
*(UB) = ((PVOID) (((IC)->Irp->MdlAddress == NULL) ? \
|
|||
|
(IC)->Irp->UserBuffer : \
|
|||
|
MmGetSystemAddressForMdlSafe( (IC)->Irp->MdlAddress, NormalPagePriority ))); \
|
|||
|
if (NULL == *(UB)) { \
|
|||
|
UdfRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES); \
|
|||
|
} \
|
|||
|
}
|
|||
|
|
|||
|
#define UdfLockUserBuffer(IC,BL,OP) { \
|
|||
|
if ((IC)->Irp->MdlAddress == NULL) { \
|
|||
|
(VOID) UdfCreateUserMdl( (IC), (BL), TRUE, (OP) ); \
|
|||
|
} \
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Udf*RawBufferSize and Udf*RawReadSize calculate how big a buffer must be
|
|||
|
// to do a direct read of a given sector aligned structure (UdfReadSectors)
|
|||
|
// and how much data the read must recover. Reads must write into whole-page
|
|||
|
// sized buffers and be in whole-sector units.
|
|||
|
//
|
|||
|
// Note that although all descriptors are constrained to fit in one logical
|
|||
|
// block, it is not always going to be neccesary to read the entire logical
|
|||
|
// block to get the descriptor. The underlying restriction is the physical
|
|||
|
// sector.
|
|||
|
//
|
|||
|
|
|||
|
INLINE
|
|||
|
ULONG
|
|||
|
UdfRawBufferSize (
|
|||
|
IN PVCB Vcb,
|
|||
|
IN ULONG StructureSize
|
|||
|
)
|
|||
|
{
|
|||
|
return (ULONG)ROUND_TO_PAGES( SectorAlign( Vcb, StructureSize ));
|
|||
|
}
|
|||
|
|
|||
|
INLINE
|
|||
|
ULONG
|
|||
|
UdfRawReadSize (
|
|||
|
IN PVCB Vcb,
|
|||
|
IN ULONG StructureSize
|
|||
|
)
|
|||
|
{
|
|||
|
return SectorAlign( Vcb, StructureSize );
|
|||
|
}
|
|||
|
|
|||
|
INLINE
|
|||
|
ULONG
|
|||
|
UdfRawBufferSizeN (
|
|||
|
IN ULONG SectorSize,
|
|||
|
IN ULONG StructureSize
|
|||
|
)
|
|||
|
{
|
|||
|
return (ULONG)ROUND_TO_PAGES( SectorAlignN( SectorSize, StructureSize ));
|
|||
|
}
|
|||
|
|
|||
|
INLINE
|
|||
|
ULONG
|
|||
|
UdfRawReadSizeN (
|
|||
|
IN ULONG SectorSize,
|
|||
|
IN ULONG StructureSize
|
|||
|
)
|
|||
|
{
|
|||
|
return SectorAlignN( SectorSize, StructureSize );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// The following routines are used to read on-disk directory structures, implemented
|
|||
|
// in DirSup.c
|
|||
|
//
|
|||
|
|
|||
|
VOID
|
|||
|
UdfInitializeDirContext (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PDIR_ENUM_CONTEXT DirContext
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfCleanupDirContext (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PDIR_ENUM_CONTEXT DirContext
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfLookupInitialDirEntry (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PDIR_ENUM_CONTEXT DirContext,
|
|||
|
IN PLONGLONG InitialOffset OPTIONAL
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfLookupNextDirEntry (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PDIR_ENUM_CONTEXT DirContext
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfUpdateDirNames (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PDIR_ENUM_CONTEXT DirContext,
|
|||
|
IN BOOLEAN IgnoreCase
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfFindDirEntry (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PUNICODE_STRING Name,
|
|||
|
IN BOOLEAN IgnoreCase,
|
|||
|
IN BOOLEAN ShortName,
|
|||
|
IN PDIR_ENUM_CONTEXT DirContext
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// The following routines are used to manipulate the fscontext fields
|
|||
|
// of the file object, implemented in FilObSup.c
|
|||
|
//
|
|||
|
|
|||
|
VOID
|
|||
|
UdfSetFileObject (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PFILE_OBJECT FileObject,
|
|||
|
IN TYPE_OF_OPEN TypeOfOpen,
|
|||
|
IN PFCB Fcb OPTIONAL,
|
|||
|
IN PCCB Ccb OPTIONAL
|
|||
|
);
|
|||
|
|
|||
|
TYPE_OF_OPEN
|
|||
|
UdfDecodeFileObject (
|
|||
|
IN PFILE_OBJECT FileObject,
|
|||
|
OUT PFCB *Fcb,
|
|||
|
OUT PCCB *Ccb
|
|||
|
);
|
|||
|
|
|||
|
TYPE_OF_OPEN
|
|||
|
UdfFastDecodeFileObject (
|
|||
|
IN PFILE_OBJECT FileObject,
|
|||
|
OUT PFCB *Fcb
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// FSCTL request support routines. Contained in FsCtrl.c
|
|||
|
//
|
|||
|
|
|||
|
VOID
|
|||
|
UdfStoreVolumeDescriptorIfPrevailing (
|
|||
|
IN OUT PNSR_VD_GENERIC *StoredVD,
|
|||
|
IN OUT PNSR_VD_GENERIC NewVD
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Name mangling routines. Implemented in Namesup.c
|
|||
|
//
|
|||
|
|
|||
|
VOID
|
|||
|
UdfDissectName (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN OUT PUNICODE_STRING RemainingName,
|
|||
|
OUT PUNICODE_STRING FinalName
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfIs8dot3Name (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN UNICODE_STRING FileName
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfCandidateShortName (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PUNICODE_STRING Name
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfGenerate8dot3Name (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PUNICODE_STRING FileName,
|
|||
|
OUT PUNICODE_STRING ShortFileName
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfConvertCS0DstringToUnicode (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PUCHAR Dstring,
|
|||
|
IN UCHAR Length OPTIONAL,
|
|||
|
IN UCHAR FieldLength OPTIONAL,
|
|||
|
IN OUT PUNICODE_STRING Name
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfCheckLegalCS0Dstring (
|
|||
|
PIRP_CONTEXT IrpContext,
|
|||
|
PUCHAR Dstring,
|
|||
|
UCHAR Length OPTIONAL,
|
|||
|
UCHAR FieldLength OPTIONAL,
|
|||
|
BOOLEAN ReturnOnError
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfRenderNameToLegalUnicode (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PUNICODE_STRING Name,
|
|||
|
IN PUNICODE_STRING RenderedName
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfIsNameInExpression (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PUNICODE_STRING CurrentName,
|
|||
|
IN PUNICODE_STRING SearchExpression,
|
|||
|
IN BOOLEAN Wild
|
|||
|
);
|
|||
|
|
|||
|
FSRTL_COMPARISON_RESULT
|
|||
|
UdfFullCompareNames (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PUNICODE_STRING NameA,
|
|||
|
IN PUNICODE_STRING NameB
|
|||
|
);
|
|||
|
|
|||
|
INLINE
|
|||
|
VOID
|
|||
|
UdfUpcaseName (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PUNICODE_STRING Name,
|
|||
|
IN OUT PUNICODE_STRING UpcaseName
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine upcases a name with an assertion of success.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Name - an name to upcase
|
|||
|
|
|||
|
Length - a place to put the upcased name (can be the same as Name)
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
|
|||
|
//
|
|||
|
// Upcase the string using the correct upcase routine.
|
|||
|
//
|
|||
|
|
|||
|
Status = RtlUpcaseUnicodeString( UpcaseName,
|
|||
|
Name,
|
|||
|
FALSE );
|
|||
|
|
|||
|
//
|
|||
|
// This should never fail.
|
|||
|
//
|
|||
|
|
|||
|
ASSERT( Status == STATUS_SUCCESS );
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
INLINE
|
|||
|
USHORT
|
|||
|
UdfCS0DstringUnicodeSize (
|
|||
|
PIRP_CONTEXT IrpContext,
|
|||
|
PCHAR Dstring,
|
|||
|
UCHAR Length
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine computes the number of bytes required for the UNICODE representation
|
|||
|
of a CS0 Dstring (1/7.2.12)
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Dstring - a dstring
|
|||
|
|
|||
|
Length - length of the dstring
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ULONG number of bytes.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
return (16 / *Dstring) * (Length - 1);
|
|||
|
}
|
|||
|
|
|||
|
INLINE
|
|||
|
BOOLEAN
|
|||
|
UdfIsCharacterLegal (
|
|||
|
IN WCHAR Character
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine checks that a given UNICODE character is legal.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Character - a character to check
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOLEAN True if a legal character, False otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
if (Character < 0xff && !FsRtlIsAnsiCharacterLegalHpfs( Character, FALSE )) {
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
INLINE
|
|||
|
BOOLEAN
|
|||
|
UdfCS0DstringIsLegalFileName(
|
|||
|
IN PCHAR Dstring,
|
|||
|
IN ULONG Length
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine inspects a CS0 dstring for illegal characters, and illegal
|
|||
|
trailing characters. The assumption is made that the string is legal CS0.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Name - a name to check
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOLEAN True if legal characters are found, False otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
ULONG Step;
|
|||
|
WCHAR Char;
|
|||
|
PCHAR Bound = Dstring + Length;
|
|||
|
|
|||
|
//
|
|||
|
// Determine how big a step we take in the string according to the
|
|||
|
// "compression" applied.
|
|||
|
//
|
|||
|
|
|||
|
if (*Dstring == 16) {
|
|||
|
|
|||
|
Step = sizeof( WCHAR );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
Step = sizeof( CHAR );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Advance past the compression marker and loop over the string.
|
|||
|
//
|
|||
|
|
|||
|
for (Dstring++; Dstring < Bound; Dstring += Step) {
|
|||
|
|
|||
|
if ( sizeof(WCHAR) == Step) {
|
|||
|
|
|||
|
//
|
|||
|
// Perform the endianess swapcopy to convert from UDF bigendian CS0 to our
|
|||
|
// little endian wide characters.
|
|||
|
//
|
|||
|
|
|||
|
SwapCopyUchar2( &Char, Dstring );
|
|||
|
}
|
|||
|
else {
|
|||
|
|
|||
|
Char = *Dstring;
|
|||
|
}
|
|||
|
|
|||
|
if (!UdfIsCharacterLegal( Char )) {
|
|||
|
|
|||
|
DebugTrace(( 0, Dbg, "UdfCS0DstringIsLegalFileName, Char %04x @ %08x\n", (WCHAR) Char, Dstring ));
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now check for illegal trailing characters (' ' or '.') We know that Char
|
|||
|
// will be the last character in the string.
|
|||
|
//
|
|||
|
|
|||
|
if ((PERIOD == Char) || (SPACE == Char)) {
|
|||
|
|
|||
|
DebugTrace(( 0, Dbg, "UdfCS0DstringIsLegalFileName, has trailing space or period\n"));
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Filesystem control operations. Implemented in Fsctrl.c
|
|||
|
//
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
UdfLockVolumeInternal (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PVCB Vcb,
|
|||
|
IN PFILE_OBJECT FileObject OPTIONAL
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
UdfUnlockVolumeInternal (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PVCB Vcb,
|
|||
|
IN PFILE_OBJECT FileObject OPTIONAL
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Routines to handle the prefix trees attached to directories, used to quickly travel common
|
|||
|
// bits of the hierarchy. Implemented in PrefxSup.c
|
|||
|
//
|
|||
|
|
|||
|
PLCB
|
|||
|
UdfFindPrefix (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN OUT PFCB *CurrentFcb,
|
|||
|
IN OUT PUNICODE_STRING RemainingName,
|
|||
|
IN BOOLEAN IgnoreCase
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfInitializeLcbFromDirContext (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PLCB Lcb,
|
|||
|
IN PDIR_ENUM_CONTEXT DirContext
|
|||
|
);
|
|||
|
|
|||
|
PLCB
|
|||
|
UdfInsertPrefix (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PUNICODE_STRING Name,
|
|||
|
IN BOOLEAN ShortNameMatch,
|
|||
|
IN BOOLEAN IgnoreCase,
|
|||
|
IN PFCB ParentFcb
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfRemovePrefix (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PLCB Lcb
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Synchronization routines. Implemented in Resrcsup.c
|
|||
|
//
|
|||
|
// The following routines/macros are used to synchronize the in-memory structures.
|
|||
|
//
|
|||
|
// Routine/Macro Synchronizes Subsequent
|
|||
|
//
|
|||
|
// UdfAcquireUdfData Volume Mounts/Dismounts,Vcb Queue UdfReleaseUdfData
|
|||
|
// UdfAcquireVcbExclusive Vcb for open/close UdfReleaseVcb
|
|||
|
// UdfAcquireVcbShared Vcb for open/close UdfReleaseVcb
|
|||
|
// UdfAcquireAllFiles Locks out operations to all files UdfReleaseAllFiles
|
|||
|
// UdfAcquireFileExclusive Locks out file operations UdfReleaseFile
|
|||
|
// UdfAcquireFileShared Files for file operations UdfReleaseFile
|
|||
|
// UdfAcquireFcbExclusive Fcb for open/close UdfReleaseFcb
|
|||
|
// UdfAcquireFcbShared Fcb for open/close UdfReleaseFcb
|
|||
|
// UdfLockUdfData Fields in UdfData UdfUnlockUdfData
|
|||
|
// UdfLockVcb Vcb fields, FcbReference, FcbTable UdfUnlockVcb
|
|||
|
// UdfLockFcb Fcb fields, prefix table, Mcb UdfUnlockFcb
|
|||
|
//
|
|||
|
|
|||
|
typedef enum _TYPE_OF_ACQUIRE {
|
|||
|
|
|||
|
AcquireExclusive,
|
|||
|
AcquireShared,
|
|||
|
AcquireSharedStarveExclusive
|
|||
|
|
|||
|
} TYPE_OF_ACQUIRE, *PTYPE_OF_ACQUIRE;
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfAcquireResource (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PERESOURCE Resource,
|
|||
|
IN BOOLEAN IgnoreWait,
|
|||
|
IN TYPE_OF_ACQUIRE Type
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// BOOLEAN
|
|||
|
// UdfAcquireUdfData (
|
|||
|
// IN PIRP_CONTEXT IrpContext
|
|||
|
// );
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// UdfReleaseUdfData (
|
|||
|
// IN PIRP_CONTEXT IrpContext
|
|||
|
// );
|
|||
|
//
|
|||
|
// BOOLEAN
|
|||
|
// UdfAcquireVcbExclusive (
|
|||
|
// IN PIRP_CONTEXT IrpContext,
|
|||
|
// IN PVCB Vcb,
|
|||
|
// IN BOOLEAN IgnoreWait
|
|||
|
// );
|
|||
|
//
|
|||
|
// BOOLEAN
|
|||
|
// UdfAcquireVcbShared (
|
|||
|
// IN PIRP_CONTEXT IrpContext,
|
|||
|
// IN PVCB Vcb,
|
|||
|
// IN BOOLEAN IgnoreWait
|
|||
|
// );
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// UdfReleaseVcb (
|
|||
|
// IN PIRP_CONTEXT IrpContext,
|
|||
|
// IN PVCB Vcb
|
|||
|
// );
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// UdfAcquireAllFiles (
|
|||
|
// IN PIRP_CONTEXT,
|
|||
|
// IN PVCB Vcb
|
|||
|
// );
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// UdfReleaseAllFiles (
|
|||
|
// IN PIRP_CONTEXT,
|
|||
|
// IN PVCB Vcb
|
|||
|
// );
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// UdfAcquireFileExclusive (
|
|||
|
// IN PIRP_CONTEXT IrpContext,
|
|||
|
// IN PFCB Fcb,
|
|||
|
// );
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// UdfAcquireFileShared (
|
|||
|
// IN PIRP_CONTEXT IrpContext,
|
|||
|
// IN PFCB Fcb
|
|||
|
// );
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// UdfReleaseFile (
|
|||
|
// IN PIRP_CONTEXT IrpContext,
|
|||
|
// IN PFCB Fcb
|
|||
|
// );
|
|||
|
//
|
|||
|
// BOOLEAN
|
|||
|
// UdfAcquireFcbExclusive (
|
|||
|
// IN PIRP_CONTEXT IrpContext,
|
|||
|
// IN PFCB Fcb,
|
|||
|
// IN BOOLEAN IgnoreWait
|
|||
|
// );
|
|||
|
//
|
|||
|
// BOOLEAN
|
|||
|
// UdfAcquireFcbShared (
|
|||
|
// IN PIRP_CONTEXT IrpContext,
|
|||
|
// IN PFCB Fcb,
|
|||
|
// IN BOOLEAN IgnoreWait
|
|||
|
// );
|
|||
|
//
|
|||
|
// BOOLEAN
|
|||
|
// UdfReleaseFcb (
|
|||
|
// IN PIRP_CONTEXT IrpContext,
|
|||
|
// IN PFCB Fcb
|
|||
|
// );
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// UdfLockUdfData (
|
|||
|
// );
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// UdfUnlockUdfData (
|
|||
|
// );
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// UdfLockVcb (
|
|||
|
// IN PIRP_CONTEXT IrpContext
|
|||
|
// );
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// UdfUnlockVcb (
|
|||
|
// IN PIRP_CONTEXT IrpContext
|
|||
|
// );
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// UdfLockFcb (
|
|||
|
// IN PIRP_CONTEXT IrpContext,
|
|||
|
// IN PFCB Fcb
|
|||
|
// );
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// UdfUnlockFcb (
|
|||
|
// IN PIRP_CONTEXT IrpContext,
|
|||
|
// IN PFCB Fcb
|
|||
|
// );
|
|||
|
//
|
|||
|
|
|||
|
#define UdfAcquireUdfData(IC) \
|
|||
|
ExAcquireResourceExclusiveLite( &UdfData.DataResource, TRUE )
|
|||
|
|
|||
|
#define UdfReleaseUdfData(IC) \
|
|||
|
ExReleaseResourceLite( &UdfData.DataResource )
|
|||
|
|
|||
|
#define UdfAcquireVcbExclusive(IC,V,I) \
|
|||
|
UdfAcquireResource( (IC), &(V)->VcbResource, (I), AcquireExclusive )
|
|||
|
|
|||
|
#define UdfAcquireVcbShared(IC,V,I) \
|
|||
|
UdfAcquireResource( (IC), &(V)->VcbResource, (I), AcquireShared )
|
|||
|
|
|||
|
#define UdfReleaseVcb(IC,V) \
|
|||
|
ExReleaseResourceLite( &(V)->VcbResource )
|
|||
|
|
|||
|
#define UdfAcquireAllFiles(IC,V) \
|
|||
|
UdfAcquireResource( (IC), &(V)->FileResource, FALSE, AcquireExclusive )
|
|||
|
|
|||
|
#define UdfReleaseAllFiles(IC,V) \
|
|||
|
ExReleaseResourceLite( &(V)->FileResource )
|
|||
|
|
|||
|
#define UdfAcquireFileExclusive(IC,F) \
|
|||
|
UdfAcquireResource( (IC), (F)->Resource, FALSE, AcquireExclusive )
|
|||
|
|
|||
|
#define UdfAcquireFileShared(IC,F) \
|
|||
|
UdfAcquireResource( (IC), (F)->Resource, FALSE, AcquireShared )
|
|||
|
|
|||
|
#define UdfAcquireFileSharedStarveExclusive(IC,F) \
|
|||
|
UdfAcquireResource( (IC), (F)->Resource, FALSE, AcquireSharedStarveExclusive )
|
|||
|
|
|||
|
#define UdfReleaseFile(IC,F) \
|
|||
|
ExReleaseResourceLite( (F)->Resource )
|
|||
|
|
|||
|
#define UdfAcquireVmcbForCcMap(IC,V) \
|
|||
|
UdfAcquireResource( (IC), &(V)->VmcbMappingResource, FALSE, AcquireShared)
|
|||
|
|
|||
|
#define UdfAcquireVmcbForCcPurge(IC,V) \
|
|||
|
UdfAcquireResource( (IC), &(V)->VmcbMappingResource, FALSE, AcquireExclusive)
|
|||
|
|
|||
|
#define UdfReleaseVmcb( IC, V) \
|
|||
|
ExReleaseResourceLite( &(V)->VmcbMappingResource)
|
|||
|
|
|||
|
#define UdfAcquireFcbExclusive(IC,F,I) \
|
|||
|
UdfAcquireResource( (IC), &(F)->FcbNonpaged->FcbResource, (I), AcquireExclusive )
|
|||
|
|
|||
|
#define UdfAcquireFcbShared(IC,F,I) \
|
|||
|
UdfAcquireResource( (IC), &(F)->FcbNonpaged->FcbResource, (I), AcquireShared )
|
|||
|
|
|||
|
#define UdfReleaseFcb(IC,F) \
|
|||
|
ExReleaseResourceLite( &(F)->FcbNonpaged->FcbResource )
|
|||
|
|
|||
|
#define UdfLockUdfData() \
|
|||
|
ExAcquireFastMutex( &UdfData.UdfDataMutex ); \
|
|||
|
UdfData.UdfDataLockThread = PsGetCurrentThread()
|
|||
|
|
|||
|
#define UdfUnlockUdfData() \
|
|||
|
UdfData.UdfDataLockThread = NULL; \
|
|||
|
ExReleaseFastMutex( &UdfData.UdfDataMutex )
|
|||
|
|
|||
|
#define UdfLockVcb(IC,V) \
|
|||
|
ASSERT(KeAreApcsDisabled()); \
|
|||
|
ExAcquireFastMutexUnsafe( &(V)->VcbMutex ); \
|
|||
|
(V)->VcbLockThread = PsGetCurrentThread()
|
|||
|
|
|||
|
#define UdfUnlockVcb(IC,V) \
|
|||
|
(V)->VcbLockThread = NULL; \
|
|||
|
ExReleaseFastMutexUnsafe( &(V)->VcbMutex )
|
|||
|
|
|||
|
#define UdfLockFcb(IC,F) { \
|
|||
|
PVOID _CurrentThread = PsGetCurrentThread(); \
|
|||
|
if (_CurrentThread != (F)->FcbLockThread) { \
|
|||
|
ASSERT(KeAreApcsDisabled()); \
|
|||
|
ExAcquireFastMutexUnsafe( &(F)->FcbNonpaged->FcbMutex ); \
|
|||
|
ASSERT( (F)->FcbLockCount == 0 ); \
|
|||
|
(F)->FcbLockThread = _CurrentThread; \
|
|||
|
} \
|
|||
|
(F)->FcbLockCount += 1; \
|
|||
|
}
|
|||
|
|
|||
|
#define UdfUnlockFcb(IC,F) { \
|
|||
|
ASSERT( PsGetCurrentThread() == (F)->FcbLockThread); \
|
|||
|
(F)->FcbLockCount -= 1; \
|
|||
|
if ((F)->FcbLockCount == 0) { \
|
|||
|
(F)->FcbLockThread = NULL; \
|
|||
|
ExReleaseFastMutexUnsafe( &(F)->FcbNonpaged->FcbMutex ); \
|
|||
|
} \
|
|||
|
}
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfNoopAcquire (
|
|||
|
IN PVOID Fcb,
|
|||
|
IN BOOLEAN Wait
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfNoopRelease (
|
|||
|
IN PVOID Fcb
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfAcquireForCache (
|
|||
|
IN PFCB Fcb,
|
|||
|
IN BOOLEAN Wait
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfReleaseFromCache (
|
|||
|
IN PFCB Fcb
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfAcquireForCreateSection (
|
|||
|
IN PFILE_OBJECT FileObject
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfReleaseForCreateSection (
|
|||
|
IN PFILE_OBJECT FileObject
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Structure support routines, implemented in StrucSup.c
|
|||
|
//
|
|||
|
// These routines perform in-memory structure manipulations. They do *not* operate
|
|||
|
// on disk structures.
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// Encapsulate manipulation of the Vcb condition for tracing purposes.
|
|||
|
//
|
|||
|
|
|||
|
#ifndef UDF_SANITY
|
|||
|
|
|||
|
#define UdfSetVcbCondition( V, C) (V)->VcbCondition = (C)
|
|||
|
#define UdfSetMediaChangeCount( V, C) (V)->MediaChangeCount = (C)
|
|||
|
|
|||
|
#else
|
|||
|
|
|||
|
#define UdfSetVcbCondition( V, C) { \
|
|||
|
DebugTrace(( 0, UDFS_DEBUG_LEVEL_VERFYSUP, "VcbCondition %p transitioning %d -> %d (%s : %d)\n", \
|
|||
|
(V), (V)->VcbCondition, (C), __FILE__, __LINE__)); \
|
|||
|
(V)->VcbCondition = (C); \
|
|||
|
}
|
|||
|
|
|||
|
#define UdfSetMediaChangeCount( V, C) { \
|
|||
|
DebugTrace(( 0, UDFS_DEBUG_LEVEL_VERFYSUP, "Vcb MCT %p transitioning %d -> %d (%s : %d)\n", \
|
|||
|
(V), (V)->MediaChangeCount, (C), __FILE__, __LINE__)); \
|
|||
|
(V)->MediaChangeCount = (C); \
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfInitializeVcb (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN OUT PVCB Vcb,
|
|||
|
IN PDEVICE_OBJECT TargetDeviceObject,
|
|||
|
IN PVPB Vpb,
|
|||
|
IN PDISK_GEOMETRY DiskGeometry,
|
|||
|
IN ULONG MediaChangeCount
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfUpdateVcbPhase0 (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN OUT PVCB Vcb
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfUpdateVcbPhase1 (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN OUT PVCB Vcb,
|
|||
|
IN PNSR_FSD Fsd
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfDeleteVcb (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN OUT PVCB Vcb
|
|||
|
);
|
|||
|
|
|||
|
PIRP_CONTEXT
|
|||
|
UdfCreateIrpContext (
|
|||
|
IN PIRP Irp,
|
|||
|
IN BOOLEAN Wait
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfCleanupIrpContext (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN BOOLEAN Post
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfInitializeStackIrpContext (
|
|||
|
OUT PIRP_CONTEXT IrpContext,
|
|||
|
IN PIRP_CONTEXT_LITE IrpContextLite
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// PIRP_CONTEXT_LITE
|
|||
|
// UdfCreateIrpContextLite (
|
|||
|
// IN PIRP_CONTEXT IrpContext
|
|||
|
// );
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// UdfFreeIrpContextLite (
|
|||
|
// IN PIRP_CONTEXT_LITE IrpContextLite
|
|||
|
// );
|
|||
|
//
|
|||
|
|
|||
|
#define UdfCreateIrpContextLite(IC) \
|
|||
|
ExAllocatePoolWithTag( UdfNonPagedPool, sizeof( IRP_CONTEXT_LITE ), TAG_IRP_CONTEXT_LITE )
|
|||
|
|
|||
|
#define UdfFreeIrpContextLite(ICL) \
|
|||
|
ExFreePool( ICL )
|
|||
|
|
|||
|
//
|
|||
|
// PUDF_IO_CONTEXT
|
|||
|
// UdfAllocateIoContext (
|
|||
|
// );
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// UdfFreeIoContext (
|
|||
|
// PUDF_IO_CONTEXT IoContext
|
|||
|
// );
|
|||
|
//
|
|||
|
|
|||
|
#define UdfAllocateIoContext() \
|
|||
|
FsRtlAllocatePoolWithTag( UdfNonPagedPool, \
|
|||
|
sizeof( UDF_IO_CONTEXT ), \
|
|||
|
TAG_IO_CONTEXT )
|
|||
|
|
|||
|
#define UdfFreeIoContext(IO) ExFreePool( IO )
|
|||
|
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// UdfIncrementCleanupCounts (
|
|||
|
// IN PIRP_CONTEXT IrpContext,
|
|||
|
// IN PFCB Fcb
|
|||
|
// );
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// UdfDecrementCleanupCounts (
|
|||
|
// IN PIRP_CONTEXT IrpContext,
|
|||
|
// IN PFCB Fcb
|
|||
|
// );
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// UdfIncrementReferenceCounts (
|
|||
|
// IN PIRP_CONTEXT IrpContext,
|
|||
|
// IN PFCB Fcb,
|
|||
|
// IN ULONG ReferenceCount
|
|||
|
// IN ULONG UserReferenceCount
|
|||
|
// );
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// UdfDecrementReferenceCounts (
|
|||
|
// IN PIRP_CONTEXT IrpContext,
|
|||
|
// IN PFCB Fcb,
|
|||
|
// IN ULONG ReferenceCount
|
|||
|
// IN ULONG UserReferenceCount
|
|||
|
// );
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// UdfIncrementFcbReference (
|
|||
|
// IN PIRP_CONTEXT IrpContext,
|
|||
|
// IN PFCB Fcb
|
|||
|
// );
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// UdfDecrementFcbReference (
|
|||
|
// IN PIRP_CONTEXT IrpContext,
|
|||
|
// IN PFCB Fcb
|
|||
|
// );
|
|||
|
//
|
|||
|
|
|||
|
#define UdfIncrementCleanupCounts(IC,F) { \
|
|||
|
ASSERT_LOCKED_VCB( (F)->Vcb ); \
|
|||
|
(F)->FcbCleanup += 1; \
|
|||
|
(F)->Vcb->VcbCleanup += 1; \
|
|||
|
}
|
|||
|
|
|||
|
#define UdfDecrementCleanupCounts(IC,F) { \
|
|||
|
ASSERT_LOCKED_VCB( (F)->Vcb ); \
|
|||
|
(F)->FcbCleanup -= 1; \
|
|||
|
(F)->Vcb->VcbCleanup -= 1; \
|
|||
|
}
|
|||
|
|
|||
|
#define UdfIncrementReferenceCounts(IC,F,C,UC) { \
|
|||
|
ASSERT_LOCKED_VCB( (F)->Vcb ); \
|
|||
|
(F)->FcbReference += (C); \
|
|||
|
(F)->FcbUserReference += (UC); \
|
|||
|
(F)->Vcb->VcbReference += (C); \
|
|||
|
(F)->Vcb->VcbUserReference += (UC); \
|
|||
|
}
|
|||
|
|
|||
|
#define UdfDecrementReferenceCounts(IC,F,C,UC) { \
|
|||
|
ASSERT_LOCKED_VCB( (F)->Vcb ); \
|
|||
|
(F)->FcbReference -= (C); \
|
|||
|
(F)->FcbUserReference -= (UC); \
|
|||
|
(F)->Vcb->VcbReference -= (C); \
|
|||
|
(F)->Vcb->VcbUserReference -= (UC); \
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
UdfTeardownStructures (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PFCB StartingFcb,
|
|||
|
IN BOOLEAN Recursive,
|
|||
|
OUT PBOOLEAN RemovedStartingFcb
|
|||
|
);
|
|||
|
|
|||
|
PFCB
|
|||
|
UdfLookupFcbTable (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PVCB Vcb,
|
|||
|
IN FILE_ID FileId
|
|||
|
);
|
|||
|
|
|||
|
PFCB
|
|||
|
UdfGetNextFcb (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PVCB Vcb,
|
|||
|
IN PVOID *RestartKey
|
|||
|
);
|
|||
|
|
|||
|
PFCB
|
|||
|
UdfCreateFcb (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN FILE_ID FileId,
|
|||
|
IN NODE_TYPE_CODE NodeTypeCode,
|
|||
|
OUT PBOOLEAN FcbExisted OPTIONAL
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfDeleteFcb (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PFCB Fcb
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfInitializeFcbFromIcbContext (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PICB_SEARCH_CONTEXT IcbContext,
|
|||
|
IN PFCB ParentFcb OPTIONAL
|
|||
|
);
|
|||
|
|
|||
|
PCCB
|
|||
|
UdfCreateCcb (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PLCB Lcb OPTIONAL,
|
|||
|
IN ULONG Flags
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfDeleteCcb (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PCCB Ccb
|
|||
|
);
|
|||
|
|
|||
|
ULONG
|
|||
|
UdfFindInParseTable (
|
|||
|
IN PPARSE_KEYVALUE ParseTable,
|
|||
|
IN PCHAR Id,
|
|||
|
IN ULONG MaxIdLen
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfVerifyDescriptor (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PDESTAG Descriptor,
|
|||
|
IN USHORT Tag,
|
|||
|
IN ULONG Size,
|
|||
|
IN ULONG Lbn,
|
|||
|
IN BOOLEAN ReturnError
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfInitializeIcbContextFromFcb (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PICB_SEARCH_CONTEXT IcbContext,
|
|||
|
IN PFCB Fcb
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfInitializeIcbContext (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PICB_SEARCH_CONTEXT IcbContext,
|
|||
|
IN PVCB Vcb,
|
|||
|
IN USHORT IcbType,
|
|||
|
IN USHORT Partition,
|
|||
|
IN ULONG Lbn,
|
|||
|
IN ULONG Length
|
|||
|
);
|
|||
|
|
|||
|
INLINE
|
|||
|
VOID
|
|||
|
UdfFastInitializeIcbContext (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PICB_SEARCH_CONTEXT IcbContext
|
|||
|
)
|
|||
|
{
|
|||
|
|
|||
|
RtlZeroMemory( IcbContext, sizeof( ICB_SEARCH_CONTEXT ));
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
UdfLookupActiveIcb (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PICB_SEARCH_CONTEXT IcbContext,
|
|||
|
IN ULONG IcbExtentLength
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
UdfCleanupIcbContext (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PICB_SEARCH_CONTEXT IcbContext
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfInitializeAllocations (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PICB_SEARCH_CONTEXT IcbContext,
|
|||
|
IN BOOLEAN AllowOneGigWorkaround
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfUpdateTimestampsFromIcbContext (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PICB_SEARCH_CONTEXT IcbContext,
|
|||
|
IN PTIMESTAMP_BUNDLE Timestamps
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfCreateFileLock (
|
|||
|
IN PIRP_CONTEXT IrpContext OPTIONAL,
|
|||
|
IN PFCB Fcb,
|
|||
|
IN BOOLEAN RaiseOnError
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// The following macro converts from UDF time to NT time.
|
|||
|
//
|
|||
|
|
|||
|
INLINE
|
|||
|
VOID
|
|||
|
UdfConvertUdfTimeToNtTime (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PTIMESTAMP UdfTime,
|
|||
|
OUT PLARGE_INTEGER NtTime
|
|||
|
)
|
|||
|
{
|
|||
|
TIME_FIELDS TimeField;
|
|||
|
|
|||
|
TimeField.Year = UdfTime->Year;
|
|||
|
TimeField.Month = UdfTime->Month;
|
|||
|
TimeField.Day = UdfTime->Day;
|
|||
|
TimeField.Hour = UdfTime->Hour;
|
|||
|
TimeField.Minute = UdfTime->Minute;
|
|||
|
TimeField.Second = UdfTime->Second;
|
|||
|
|
|||
|
//
|
|||
|
// This is where it gets hairy. For some unholy reason, ISO 13346 timestamps
|
|||
|
// carve the right of the decimal point up into three fields of precision
|
|||
|
// 10-2, 10-4, and 10-6, each ranging from 0-99. Lawdy.
|
|||
|
//
|
|||
|
// To make it easier, since they cannot cause a wrap into the next second,
|
|||
|
// just save it all up and add it in after the conversion.
|
|||
|
//
|
|||
|
|
|||
|
TimeField.Milliseconds = 0;
|
|||
|
|
|||
|
if (UdfTime->Type <= 1 &&
|
|||
|
((UdfTime->Zone >= TIMESTAMP_Z_MIN && UdfTime->Zone <= TIMESTAMP_Z_MAX) ||
|
|||
|
UdfTime->Zone == TIMESTAMP_Z_NONE) &&
|
|||
|
RtlTimeFieldsToTime( &TimeField, NtTime )) {
|
|||
|
|
|||
|
//
|
|||
|
// Now fold in the remaining sub-second "precision". Read as coversions
|
|||
|
// through the 10-3 units, then into our 10-7 base. (centi->milli->micro,
|
|||
|
// etc).
|
|||
|
//
|
|||
|
|
|||
|
NtTime->QuadPart += ((UdfTime->CentiSecond * (10 * 1000)) +
|
|||
|
(UdfTime->Usec100 * 100) +
|
|||
|
UdfTime->Usec) * 10;
|
|||
|
|
|||
|
//
|
|||
|
// Perform TZ normalization if this is a local time with
|
|||
|
// specified timezone.
|
|||
|
//
|
|||
|
|
|||
|
if (UdfTime->Type == 1 && UdfTime->Zone != TIMESTAMP_Z_NONE) {
|
|||
|
|
|||
|
NtTime->QuadPart += Int32x32To64( -UdfTime->Zone, (60 * 10 * 1000 * 1000) );
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Epoch. Malformed timestamp.
|
|||
|
//
|
|||
|
|
|||
|
NtTime->QuadPart = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// An equivalence test for Entity IDs.
|
|||
|
//
|
|||
|
|
|||
|
INLINE
|
|||
|
BOOLEAN
|
|||
|
UdfEqualEntityId (
|
|||
|
IN PREGID RegID,
|
|||
|
IN PSTRING Id,
|
|||
|
IN OPTIONAL PSTRING Suffix
|
|||
|
)
|
|||
|
{
|
|||
|
|
|||
|
return (UdfEqualCountedString( Id, RegID->Identifier ) &&
|
|||
|
|
|||
|
#ifndef UDF_SUPPORT_NONSTANDARD_ENTITY_STRINGTERM
|
|||
|
|
|||
|
//
|
|||
|
// Allow disabling of the check that the identifier
|
|||
|
// seems to be padded with zero.
|
|||
|
//
|
|||
|
// Reason: a couple samples that are otherwise useful
|
|||
|
// padded some identifiers with junk.
|
|||
|
//
|
|||
|
|
|||
|
((Id->Length == sizeof(RegID->Identifier) ||
|
|||
|
RegID->Identifier[Id->Length] == '\0') ||
|
|||
|
|
|||
|
!DebugTrace(( 0, Dbg,
|
|||
|
"UdfEqualEntityId, RegID seems to be terminated with junk!\n" ))) &&
|
|||
|
#endif
|
|||
|
|
|||
|
((Suffix == NULL) || UdfEqualCountedString( Suffix, RegID->Suffix )));
|
|||
|
}
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfDomainIdentifierContained (
|
|||
|
IN PREGID RegID,
|
|||
|
IN PSTRING Domain,
|
|||
|
IN USHORT RevisionMin,
|
|||
|
IN USHORT RevisionMax
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// In like fashion, we define containment for a UDF Identifier RegID.
|
|||
|
//
|
|||
|
|
|||
|
INLINE
|
|||
|
BOOLEAN
|
|||
|
UdfUdfIdentifierContained (
|
|||
|
IN PREGID RegID,
|
|||
|
IN PSTRING Type,
|
|||
|
IN USHORT RevisionMin,
|
|||
|
IN USHORT RevisionMax,
|
|||
|
IN UCHAR OSClass,
|
|||
|
IN UCHAR OSIdentifier
|
|||
|
)
|
|||
|
{
|
|||
|
PUDF_SUFFIX_UDF UdfSuffix = (PUDF_SUFFIX_UDF) RegID->Suffix;
|
|||
|
|
|||
|
return ((UdfSuffix->UdfRevision <= RevisionMax && UdfSuffix->UdfRevision >= RevisionMin) &&
|
|||
|
(OSClass == OSCLASS_INVALID || UdfSuffix->OSClass == OSClass) &&
|
|||
|
(OSIdentifier == OSIDENTIFIER_INVALID || UdfSuffix->OSIdentifier == OSIdentifier) &&
|
|||
|
UdfEqualEntityId( RegID, Type, NULL ));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Verification support routines. Contained in verfysup.c
|
|||
|
//
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfCheckForDismount (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PVCB Vcb,
|
|||
|
IN BOOLEAN Force
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfDismountVcb (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PVCB Vcb
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfVerifyVcb (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PVCB Vcb
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfVerifyFcbOperation (
|
|||
|
IN PIRP_CONTEXT IrpContext OPTIONAL,
|
|||
|
IN PFCB Fcb
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// BOOLEAN
|
|||
|
// UdfIsRawDevice (
|
|||
|
// IN PIRP_CONTEXT IrpContext,
|
|||
|
// IN NTSTATUS Status
|
|||
|
// );
|
|||
|
//
|
|||
|
|
|||
|
#define UdfIsRawDevice(IC,S) ( \
|
|||
|
((S) == STATUS_DEVICE_NOT_READY) || \
|
|||
|
((S) == STATUS_NO_MEDIA_IN_DEVICE) \
|
|||
|
)
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Volume Mapped Control Blocks routines, implemented in VmcbSup.c
|
|||
|
//
|
|||
|
|
|||
|
VOID
|
|||
|
UdfInitializeVmcb (
|
|||
|
IN PVMCB Vmcb,
|
|||
|
IN POOL_TYPE PoolType,
|
|||
|
IN ULONG MaximumLbn,
|
|||
|
IN ULONG LbSize
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfUninitializeVmcb (
|
|||
|
IN PVMCB Vmcb
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfResetVmcb (
|
|||
|
IN PVMCB Vmcb
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfSetMaximumLbnVmcb (
|
|||
|
IN PVMCB Vmcb,
|
|||
|
IN ULONG MaximumLbn
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfVmcbVbnToLbn (
|
|||
|
IN PVMCB Vmcb,
|
|||
|
IN VBN Vbn,
|
|||
|
OUT PLBN Lbn,
|
|||
|
OUT PULONG SectorCount OPTIONAL
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfVmcbLbnToVbn (
|
|||
|
IN PVMCB Vmcb,
|
|||
|
IN LBN Lbn,
|
|||
|
OUT PVBN Vbn,
|
|||
|
OUT PULONG SectorCount OPTIONAL
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UdfAddVmcbMapping (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PVMCB Vmcb,
|
|||
|
IN LBN Lbn,
|
|||
|
IN ULONG SectorCount,
|
|||
|
IN BOOLEAN ExactEnd,
|
|||
|
OUT PVBN Vbn,
|
|||
|
OUT PULONG AlignedSectorCount
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfRemoveVmcbMapping (
|
|||
|
IN PVMCB Vmcb,
|
|||
|
IN LBN Lbn,
|
|||
|
IN ULONG SectorCount
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Routines to verify the correspondance of the underlying media, implemented in
|
|||
|
// verfysup.c
|
|||
|
//
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
UdfPerformVerify (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PIRP Irp,
|
|||
|
IN PDEVICE_OBJECT DeviceToVerify
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Some macros for hiding/tracing the device object verify flag.
|
|||
|
//
|
|||
|
|
|||
|
#ifndef UDF_SANITY
|
|||
|
|
|||
|
#define UdfMarkRealDevForVerify( DO) SetFlag( (DO)->Flags, DO_VERIFY_VOLUME)
|
|||
|
#define UdfMarkRealDevVerifyOk( DO) ClearFlag( (DO)->Flags, DO_VERIFY_VOLUME)
|
|||
|
|
|||
|
#else
|
|||
|
|
|||
|
#define UdfMarkRealDevForVerify( DO) { \
|
|||
|
DebugTrace((0,UDFS_DEBUG_LEVEL_VERFYSUP,"Mark for verify %p (at %s %d)\n", \
|
|||
|
(DO), __FILE__, __LINE__)); \
|
|||
|
SetFlag( (DO)->Flags, DO_VERIFY_VOLUME); \
|
|||
|
}
|
|||
|
|
|||
|
#define UdfMarkRealDevVerifyOk( DO) { \
|
|||
|
DebugTrace((0,UDFS_DEBUG_LEVEL_VERFYSUP,"Clear verify %p (at %s %d)\n", \
|
|||
|
(DO), __FILE__, __LINE__)); \
|
|||
|
ClearFlag( (DO)->Flags, DO_VERIFY_VOLUME); \
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
#define UdfRealDevNeedsVerify( DO) BooleanFlagOn( (DO)->Flags, DO_VERIFY_VOLUME)
|
|||
|
|
|||
|
//
|
|||
|
// Work queue routines for posting and retrieving an Irp, implemented in
|
|||
|
// workque.c
|
|||
|
//
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
UdfFsdPostRequest(
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PIRP Irp
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfPrePostIrp (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PIRP Irp
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfOplockComplete (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PIRP Irp
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Charspecs are small containers that specify a CS<N> type and a text
|
|||
|
// string specifying a version, etc. This is a convenient way of bottling
|
|||
|
// up equivalence checks of a charspec.
|
|||
|
//
|
|||
|
|
|||
|
INLINE
|
|||
|
BOOLEAN
|
|||
|
UdfEqualCharspec (
|
|||
|
IN PCHARSPEC Charspec,
|
|||
|
IN PSTRING Identifier,
|
|||
|
IN UCHAR Type
|
|||
|
)
|
|||
|
{
|
|||
|
return ((Charspec->Type == Type) && UdfEqualCountedString( Identifier, Charspec->Info));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// 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
|
|||
|
UdfFspDispatch ( // implemented in FspDisp.c
|
|||
|
IN PIRP_CONTEXT IrpContext
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
UdfFspClose ( // Implemented in Close.c
|
|||
|
IN PVCB Vcb OPTIONAL
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// The following routines are the entry points for the different operations
|
|||
|
// based on the IrpSp major functions.
|
|||
|
//
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
UdfCommonCleanup ( // Implemented in Cleanup.c
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PIRP Irp
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
UdfCommonClose ( // Implemented in Close.c
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PIRP Irp
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
UdfCommonCreate ( // Implemented in Create.c
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PIRP Irp
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS // Implemented in DevCtrl.c
|
|||
|
UdfCommonDevControl (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PIRP Irp
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS // Implemented in DirCtrl.c
|
|||
|
UdfCommonDirControl (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PIRP Irp
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
UdfCommonFsControl ( // Implemented in FsCtrl.c
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PIRP Irp
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS // Implemented in LockCtrl.c
|
|||
|
UdfCommonLockControl (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PIRP Irp
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS // Implemented in Pnp.c
|
|||
|
UdfCommonPnp (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PIRP Irp
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS // Implemented in FileInfo.c
|
|||
|
UdfCommonQueryInfo (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PIRP Irp
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS // Implemented in VolInfo.c
|
|||
|
UdfCommonQueryVolInfo (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PIRP Irp
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS // Implemented in Read.c
|
|||
|
UdfCommonRead (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PIRP Irp
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
UdfCommonWrite (
|
|||
|
IN PIRP_CONTEXT IrpContext, // write.c
|
|||
|
IN PIRP Irp
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS // Implemented in FileInfo.c
|
|||
|
UdfCommonSetInfo (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PIRP Irp
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
UdfHijackIrpAndFlushDevice ( // flush.c
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PIRP Irp,
|
|||
|
IN PDEVICE_OBJECT TargetDeviceObject
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
// BOOLEAN
|
|||
|
// UdfExtendedFEAllowed(
|
|||
|
// PVCB Vcb
|
|||
|
// )
|
|||
|
//
|
|||
|
// Decides, based on the NSR revision encountered on the volume, whether or not the
|
|||
|
// extended FE is legal and expected on this volume
|
|||
|
|
|||
|
#define UdfExtendedFEAllowed( V) (VsdIdentNSR03 == (V)->NsrVersion)
|
|||
|
|
|||
|
|
|||
|
// BOOLEAN
|
|||
|
// UdfMinLegalVATSize(
|
|||
|
// PVCB Vcb
|
|||
|
// )
|
|||
|
//
|
|||
|
// Decides based on the NSR revision encountered on the volume
|
|||
|
|
|||
|
#define UdfMinLegalVATSize( V) ((VsdIdentNSR03 == (V)->NsrVersion) ? UDF_CDUDF_MINIMUM_20x_VAT_SIZE : UDF_CDUDF_MINIMUM_150_VAT_SIZE)
|
|||
|
|
|||
|
|
|||
|
// BOOLEAN
|
|||
|
// UdfVATIcbFileTypeExpected(
|
|||
|
// PVCB Vcb
|
|||
|
// )
|
|||
|
//
|
|||
|
// Decides, based on the NSR revision encountered on the volume, what value we
|
|||
|
// expect the FileType field in the VAT Icb to have
|
|||
|
|
|||
|
#define UdfVATIcbFileTypeExpected( V) ((VsdIdentNSR03 == (V)->NsrVersion) ? ICBTAG_FILE_T_VAT : ICBTAG_FILE_T_NOTSPEC)
|
|||
|
|
|||
|
|
|||
|
// BOOLEAN
|
|||
|
// UdfVATHasHeaderRecord(
|
|||
|
// PVCB Vcb
|
|||
|
// )
|
|||
|
//
|
|||
|
// Decides, based on the NSR revision encountered on the volume, if the VAT should have
|
|||
|
// the header (2.00) record, or the 1.5 style trailing regid.
|
|||
|
|
|||
|
#define UdfVATHasHeaderRecord( V) (VsdIdentNSR03 == (V)->NsrVersion)
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Clean up our internal-to-the-header definitions so they do not leak out.
|
|||
|
//
|
|||
|
|
|||
|
#undef BugCheckFileId
|
|||
|
#undef Dbg
|
|||
|
|
|||
|
|
|||
|
#endif // _UDFPROCS_
|