mirror of
https://github.com/reactos/reactos.git
synced 2024-08-21 02:43:48 +00:00
2319 lines
61 KiB
C
2319 lines
61 KiB
C
/*++
|
|
|
|
Copyright (c) 1989-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
CdProcs.h
|
|
|
|
Abstract:
|
|
|
|
This module defines all of the globally used procedures in the Cdfs
|
|
file system.
|
|
|
|
|
|
--*/
|
|
|
|
#ifndef _CDPROCS_
|
|
#define _CDPROCS_
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning( disable: 4127 ) // conditional expression is constant
|
|
|
|
#pragma warning( push )
|
|
#pragma warning( disable: 4201 ) // nonstandard extension used : nameless struct/union
|
|
#pragma warning( disable: 4214 ) // nonstandard extension used : bit field types
|
|
#endif
|
|
|
|
#include <ntifs.h>
|
|
|
|
#include <ntddcdrm.h>
|
|
#include <ntdddisk.h>
|
|
#include <ntddscsi.h>
|
|
#ifdef __REACTOS__
|
|
#include <pseh/pseh2.h>
|
|
#endif
|
|
|
|
#ifndef INLINE
|
|
#define INLINE __inline
|
|
#endif
|
|
|
|
#include "nodetype.h"
|
|
#include "cd.h"
|
|
#include "cdstruc.h"
|
|
#include "cddata.h"
|
|
|
|
#ifdef CDFS_TELEMETRY_DATA
|
|
|
|
#include <winmeta.h>
|
|
#include <TraceLoggingProvider.h>
|
|
#include <telemetry\MicrosoftTelemetry.h>
|
|
|
|
#endif // CDFS_TELEMETRY_DATA
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning( pop )
|
|
#endif
|
|
|
|
#ifdef __REACTOS__
|
|
// Downgrade unsupported NT6.2+ features.
|
|
#undef MdlMappingNoExecute
|
|
#define MdlMappingNoExecute 0
|
|
#define NonPagedPoolNx NonPagedPool
|
|
#define NonPagedPoolNxCacheAligned NonPagedPoolCacheAligned
|
|
#endif
|
|
|
|
//**** x86 compiler bug ****
|
|
|
|
#if defined(_M_IX86)
|
|
#undef Int64ShraMod32
|
|
#define Int64ShraMod32(a, b) ((LONGLONG)(a) >> (b))
|
|
#endif
|
|
|
|
#ifndef Min
|
|
#define Min(a, b) ((a) < (b) ? (a) : (b))
|
|
#endif
|
|
|
|
#ifndef Max
|
|
#define Max(a, b) ((a) > (b) ? (a) : (b))
|
|
#endif
|
|
|
|
//
|
|
// Here are the different pool tags.
|
|
//
|
|
|
|
#define TAG_CCB 'ccdC' // Ccb
|
|
#define TAG_CDROM_TOC 'ctdC' // TOC
|
|
#define TAG_DIRENT_NAME 'nddC' // CdName in dirent
|
|
#define TAG_ENUM_EXPRESSION 'eedC' // Search expression for enumeration
|
|
#define TAG_FCB_DATA 'dfdC' // Data Fcb
|
|
#define TAG_FCB_INDEX 'ifdC' // Index Fcb
|
|
#define TAG_FCB_NONPAGED 'nfdC' // Nonpaged Fcb
|
|
#define TAG_FCB_TABLE 'tfdC' // Fcb Table entry
|
|
#define TAG_FILE_NAME 'nFdC' // Filename buffer
|
|
#define TAG_GEN_SHORT_NAME 'sgdC' // Generated short name
|
|
#define TAG_IO_BUFFER 'fbdC' // Temporary IO buffer
|
|
#define TAG_IO_CONTEXT 'oidC' // Io context for async reads
|
|
#define TAG_IRP_CONTEXT 'cidC' // Irp Context
|
|
#define TAG_IRP_CONTEXT_LITE 'lidC' // Irp Context lite
|
|
#define TAG_MCB_ARRAY 'amdC' // Mcb array
|
|
#define TAG_PATH_ENTRY_NAME 'nPdC' // CdName in path entry
|
|
#define TAG_PREFIX_ENTRY 'epdC' // Prefix Entry
|
|
#define TAG_PREFIX_NAME 'npdC' // Prefix Entry name
|
|
#define TAG_SPANNING_PATH_TABLE 'psdC' // Buffer for spanning path table
|
|
#define TAG_UPCASE_NAME 'nudC' // Buffer for upcased name
|
|
#define TAG_VOL_DESC 'dvdC' // Buffer for volume descriptor
|
|
#define TAG_VPB 'pvdC' // Vpb allocated in filesystem
|
|
|
|
//
|
|
// Tag all of our allocations if tagging is turned on
|
|
//
|
|
|
|
#ifdef POOL_TAGGING
|
|
|
|
#undef FsRtlAllocatePool
|
|
#undef FsRtlAllocatePoolWithQuota
|
|
#define FsRtlAllocatePool(a,b) FsRtlAllocatePoolWithTag(a,b,'sfdC')
|
|
#define FsRtlAllocatePoolWithQuota(a,b) FsRtlAllocatePoolWithQuotaTag(a,b,'sfdC')
|
|
|
|
#endif // POOL_TAGGING
|
|
|
|
|
|
//
|
|
// File access check routine, implemented in AcChkSup.c
|
|
//
|
|
|
|
//
|
|
// BOOLEAN
|
|
// CdIllegalFcbAccess (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _In_ TYPE_OF_OPEN TypeOfOpen,
|
|
// _In_ ACCESS_MASK DesiredAccess
|
|
// );
|
|
//
|
|
|
|
#define CdIllegalFcbAccess(IC,T,DA) ( \
|
|
BooleanFlagOn( (DA), \
|
|
((T) != 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 ))
|
|
|
|
|
|
//
|
|
// Allocation support routines, implemented in AllocSup.c
|
|
//
|
|
// These routines are for querying allocation on individual streams.
|
|
//
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
VOID
|
|
CdLookupAllocation (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PFCB Fcb,
|
|
_In_ LONGLONG FileOffset,
|
|
_Out_ PLONGLONG DiskOffset,
|
|
_Out_ PULONG ByteCount
|
|
);
|
|
|
|
VOID
|
|
CdAddAllocationFromDirent (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PFCB Fcb,
|
|
_In_ ULONG McbEntryOffset,
|
|
_In_ LONGLONG StartingFileOffset,
|
|
_In_ PDIRENT Dirent
|
|
);
|
|
|
|
VOID
|
|
CdAddInitialAllocation (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PFCB Fcb,
|
|
_In_ ULONG StartingBlock,
|
|
_In_ LONGLONG DataLength
|
|
);
|
|
|
|
VOID
|
|
CdTruncateAllocation (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PFCB Fcb,
|
|
_In_ LONGLONG StartingFileOffset
|
|
);
|
|
|
|
_At_(Fcb->NodeByteSize, _In_range_(>=, FIELD_OFFSET( FCB, FcbType )))
|
|
VOID
|
|
CdInitializeMcb (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_updates_bytes_(Fcb->NodeByteSize) PFCB Fcb
|
|
);
|
|
|
|
_At_(Fcb->NodeByteSize, _In_range_(>=, FIELD_OFFSET( FCB, FcbType )))
|
|
_When_(Fcb->NodeTypeCode == CDFS_NTC_FCB_PATH_TABLE, _At_(Fcb->NodeByteSize, _In_range_(==, SIZEOF_FCB_INDEX)))
|
|
_When_(Fcb->NodeTypeCode == CDFS_NTC_FCB_INDEX, _At_(Fcb->NodeByteSize, _In_range_(==, SIZEOF_FCB_INDEX)))
|
|
_When_(Fcb->NodeTypeCode == CDFS_NTC_FCB_DATA, _At_(Fcb->NodeByteSize, _In_range_(==, SIZEOF_FCB_DATA)))
|
|
VOID
|
|
CdUninitializeMcb (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_updates_bytes_(Fcb->NodeByteSize) PFCB Fcb
|
|
);
|
|
|
|
|
|
//
|
|
// Buffer control routines for data caching, implemented in CacheSup.c
|
|
//
|
|
|
|
VOID
|
|
CdCreateInternalStream (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PVCB Vcb,
|
|
_Inout_ PFCB Fcb,
|
|
_In_ PUNICODE_STRING Name
|
|
);
|
|
|
|
VOID
|
|
CdDeleteInternalStream (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PFCB Fcb
|
|
);
|
|
|
|
NTSTATUS
|
|
CdCompleteMdl (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PIRP Irp
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
NTSTATUS
|
|
CdPurgeVolume (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PVCB Vcb,
|
|
_In_ BOOLEAN DismountUnderway
|
|
);
|
|
|
|
static /* ReactOS Change: GCC "multiple definition" */
|
|
INLINE /* GCC only accepts __inline as the first modifier */
|
|
VOID
|
|
CdVerifyOrCreateDirStreamFile (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PFCB Fcb
|
|
)
|
|
{
|
|
//
|
|
// Unsafe test to see if call / lock neccessary.
|
|
//
|
|
|
|
if (NULL == Fcb->FileObject) {
|
|
|
|
CdCreateInternalStream( IrpContext,
|
|
Fcb->Vcb,
|
|
Fcb,
|
|
&Fcb->FileNamePrefix.ExactCaseName.FileName);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// VOID
|
|
// CdUnpinData (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Inout_ PBCB *Bcb
|
|
// );
|
|
//
|
|
|
|
#define CdUnpinData(IC,B) \
|
|
if (*(B) != NULL) { CcUnpinData( *(B) ); *(B) = NULL; }
|
|
|
|
|
|
//
|
|
// 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.
|
|
//
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
VOID
|
|
CdFreeDirCache (
|
|
_In_ PIRP_CONTEXT IrpContext
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
NTSTATUS
|
|
CdNonCachedRead (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PFCB Fcb,
|
|
_In_ LONGLONG StartingOffset,
|
|
_In_ ULONG ByteCount
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
NTSTATUS
|
|
CdNonCachedXARead (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PFCB Fcb,
|
|
_In_ LONGLONG StartingOffset,
|
|
_In_ ULONG ByteCount
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
NTSTATUS
|
|
CdVolumeDasdWrite (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PFCB Fcb,
|
|
_In_ LONGLONG StartingOffset,
|
|
_In_ ULONG ByteCount
|
|
);
|
|
|
|
BOOLEAN
|
|
CdReadSectors (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ LONGLONG StartingOffset,
|
|
_In_ ULONG ByteCount,
|
|
_In_ BOOLEAN ReturnError,
|
|
_Out_writes_bytes_(ByteCount) PVOID Buffer,
|
|
_In_ PDEVICE_OBJECT TargetDeviceObject
|
|
);
|
|
|
|
NTSTATUS
|
|
CdCreateUserMdl (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ ULONG BufferLength,
|
|
_In_ BOOLEAN RaiseOnError,
|
|
_In_ LOCK_OPERATION Operation
|
|
);
|
|
|
|
NTSTATUS
|
|
FASTCALL
|
|
CdPerformDevIoCtrl (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ ULONG IoControlCode,
|
|
_In_ PDEVICE_OBJECT Device,
|
|
_Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
|
|
_In_ ULONG OutputBufferLength,
|
|
_In_ BOOLEAN InternalDeviceIoControl,
|
|
_In_ BOOLEAN OverrideVerify,
|
|
_Out_opt_ PIO_STATUS_BLOCK Iosb
|
|
);
|
|
|
|
NTSTATUS
|
|
CdPerformDevIoCtrlEx (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ ULONG IoControlCode,
|
|
_In_ PDEVICE_OBJECT Device,
|
|
_In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
|
|
_In_ ULONG InputBufferLength,
|
|
_Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
|
|
_In_ ULONG OutputBufferLength,
|
|
_In_ BOOLEAN InternalDeviceIoControl,
|
|
_In_ BOOLEAN OverrideVerify,
|
|
_Out_opt_ PIO_STATUS_BLOCK Iosb
|
|
);
|
|
|
|
NTSTATUS
|
|
CdHijackIrpAndFlushDevice (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PIRP Irp,
|
|
_In_ PDEVICE_OBJECT TargetDeviceObject
|
|
);
|
|
|
|
|
|
//
|
|
// VOID
|
|
// CdMapUserBuffer (
|
|
// _In_ PIRP_CONTEXT IrpContext
|
|
// _Out_ PVOID UserBuffer
|
|
// );
|
|
//
|
|
// Returns pointer to sys address. Will raise on failure.
|
|
//
|
|
//
|
|
// VOID
|
|
// CdLockUserBuffer (
|
|
// _Inout_ PIRP_CONTEXT IrpContext,
|
|
// _In_ ULONG BufferLength
|
|
// );
|
|
//
|
|
|
|
#define CdMapUserBuffer(IC, UB) { \
|
|
*(UB) = (PVOID) ( ((IC)->Irp->MdlAddress == NULL) ? \
|
|
(IC)->Irp->UserBuffer : \
|
|
(MmGetSystemAddressForMdlSafe( (IC)->Irp->MdlAddress, NormalPagePriority | MdlMappingNoExecute))); \
|
|
if (NULL == *(UB)) { \
|
|
CdRaiseStatus( (IC), STATUS_INSUFFICIENT_RESOURCES); \
|
|
} \
|
|
}
|
|
|
|
|
|
#define CdLockUserBuffer(IC,BL,OP) { \
|
|
if ((IC)->Irp->MdlAddress == NULL) { \
|
|
(VOID) CdCreateUserMdl( (IC), (BL), TRUE, (OP) ); \
|
|
} \
|
|
}
|
|
|
|
|
|
//
|
|
// Dirent support routines, implemented in DirSup.c
|
|
//
|
|
|
|
VOID
|
|
CdLookupDirent (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PFCB Fcb,
|
|
_In_ ULONG DirentOffset,
|
|
_Out_ PDIRENT_ENUM_CONTEXT DirContext
|
|
);
|
|
|
|
BOOLEAN
|
|
CdLookupNextDirent (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PFCB Fcb,
|
|
_In_ PDIRENT_ENUM_CONTEXT CurrentDirContext,
|
|
_Inout_ PDIRENT_ENUM_CONTEXT NextDirContext
|
|
);
|
|
|
|
_At_(Dirent->CdTime, _Post_notnull_)
|
|
VOID
|
|
CdUpdateDirentFromRawDirent (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PFCB Fcb,
|
|
_In_ PDIRENT_ENUM_CONTEXT DirContext,
|
|
_Inout_ PDIRENT Dirent
|
|
);
|
|
|
|
VOID
|
|
CdUpdateDirentName (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PDIRENT Dirent,
|
|
_In_ ULONG IgnoreCase
|
|
);
|
|
|
|
_Success_(return != FALSE) BOOLEAN
|
|
CdFindFile (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PFCB Fcb,
|
|
_In_ PCD_NAME Name,
|
|
_In_ BOOLEAN IgnoreCase,
|
|
_Inout_ PFILE_ENUM_CONTEXT FileContext,
|
|
_Out_ PCD_NAME *MatchingName
|
|
);
|
|
|
|
BOOLEAN
|
|
CdFindDirectory (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PFCB Fcb,
|
|
_In_ PCD_NAME Name,
|
|
_In_ BOOLEAN IgnoreCase,
|
|
_Inout_ PFILE_ENUM_CONTEXT FileContext
|
|
);
|
|
|
|
_At_(FileContext->ShortName.FileName.MaximumLength, _In_range_(>=, BYTE_COUNT_8_DOT_3))
|
|
BOOLEAN
|
|
CdFindFileByShortName (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PFCB Fcb,
|
|
_In_ PCD_NAME Name,
|
|
_In_ BOOLEAN IgnoreCase,
|
|
_In_ ULONG ShortNameDirentOffset,
|
|
_Inout_ PFILE_ENUM_CONTEXT FileContext
|
|
);
|
|
|
|
BOOLEAN
|
|
CdLookupNextInitialFileDirent (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PFCB Fcb,
|
|
_Inout_ PFILE_ENUM_CONTEXT FileContext
|
|
);
|
|
|
|
VOID
|
|
CdLookupLastFileDirent (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PFCB Fcb,
|
|
_In_ PFILE_ENUM_CONTEXT FileContext
|
|
);
|
|
|
|
VOID
|
|
CdCleanupFileContext (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PFILE_ENUM_CONTEXT FileContext
|
|
);
|
|
|
|
//
|
|
// VOID
|
|
// CdInitializeFileContext (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Out_ PFILE_ENUM_CONTEXT FileContext
|
|
// );
|
|
//
|
|
//
|
|
// VOID
|
|
// CdInitializeDirent (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Out_ PDIRENT Dirent
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdInitializeDirContext (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Out_ PDIRENT_ENUM_CONTEXT DirContext
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdCleanupDirent (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Inout_ PDIRENT Dirent
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdCleanupDirContext (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Inout_ PDIRENT_ENUM_CONTEXT DirContext
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdLookupInitialFileDirent (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _In_ PFCB Fcb,
|
|
// _Out_ PFILE_ENUM_CONTEXT FileContext,
|
|
// _In_ ULONG DirentOffset
|
|
// );
|
|
//
|
|
|
|
#define CdInitializeFileContext(IC,FC) { \
|
|
RtlZeroMemory( FC, sizeof( FILE_ENUM_CONTEXT )); \
|
|
(FC)->PriorDirent = &(FC)->Dirents[0]; \
|
|
(FC)->InitialDirent = &(FC)->Dirents[1]; \
|
|
(FC)->CurrentDirent = &(FC)->Dirents[2]; \
|
|
(FC)->ShortName.FileName.MaximumLength = BYTE_COUNT_8_DOT_3; \
|
|
(FC)->ShortName.FileName.Buffer = (FC)->ShortNameBuffer; \
|
|
}
|
|
|
|
#define CdInitializeDirent(IC,D) \
|
|
RtlZeroMemory( D, sizeof( DIRENT ))
|
|
|
|
#define CdInitializeDirContext(IC,DC) \
|
|
RtlZeroMemory( DC, sizeof( DIRENT_ENUM_CONTEXT ))
|
|
|
|
#define CdCleanupDirent(IC,D) { \
|
|
if (FlagOn( (D)->Flags, DIRENT_FLAG_ALLOC_BUFFER )) { \
|
|
CdFreePool( &(D)->CdFileName.FileName.Buffer ); \
|
|
} \
|
|
}
|
|
|
|
#define CdCleanupDirContext(IC,DC) \
|
|
CdUnpinData( (IC), &(DC)->Bcb )
|
|
|
|
#define CdLookupInitialFileDirent(IC,F,FC,DO) \
|
|
CdLookupDirent( IC, \
|
|
F, \
|
|
DO, \
|
|
&(FC)->InitialDirent->DirContext ); \
|
|
CdUpdateDirentFromRawDirent( IC, \
|
|
F, \
|
|
&(FC)->InitialDirent->DirContext, \
|
|
&(FC)->InitialDirent->Dirent )
|
|
|
|
|
|
//
|
|
// The following routines are used to manipulate the fscontext fields
|
|
// of the file object, implemented in FilObSup.c
|
|
//
|
|
|
|
//
|
|
// Type of opens. FilObSup.c depends on this order.
|
|
//
|
|
|
|
typedef enum _TYPE_OF_OPEN {
|
|
|
|
UnopenedFileObject = 0,
|
|
StreamFileOpen,
|
|
UserVolumeOpen,
|
|
UserDirectoryOpen,
|
|
UserFileOpen,
|
|
BeyondValidType
|
|
|
|
} TYPE_OF_OPEN;
|
|
typedef TYPE_OF_OPEN *PTYPE_OF_OPEN;
|
|
|
|
_When_(TypeOfOpen == UnopenedFileObject, _At_(Fcb, _In_opt_))
|
|
_When_(TypeOfOpen != UnopenedFileObject, _At_(Fcb, _In_))
|
|
VOID
|
|
CdSetFileObject (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PFILE_OBJECT FileObject,
|
|
_In_ TYPE_OF_OPEN TypeOfOpen,
|
|
PFCB Fcb,
|
|
_In_opt_ PCCB Ccb
|
|
);
|
|
|
|
_When_(return == UnopenedFileObject, _At_(*Fcb, _Post_null_))
|
|
_When_(return != UnopenedFileObject, _At_(Fcb, _Outptr_))
|
|
_When_(return == UnopenedFileObject, _At_(*Ccb, _Post_null_))
|
|
_When_(return != UnopenedFileObject, _At_(Ccb, _Outptr_))
|
|
TYPE_OF_OPEN
|
|
CdDecodeFileObject (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PFILE_OBJECT FileObject,
|
|
PFCB *Fcb,
|
|
PCCB *Ccb
|
|
);
|
|
|
|
TYPE_OF_OPEN
|
|
CdFastDecodeFileObject (
|
|
_In_ PFILE_OBJECT FileObject,
|
|
_Out_ PFCB *Fcb
|
|
);
|
|
|
|
|
|
//
|
|
// Name support routines, implemented in NameSup.c
|
|
//
|
|
|
|
_Post_satisfies_(_Old_(CdName->FileName.Length) >=
|
|
CdName->FileName.Length + CdName->VersionString.Length)
|
|
VOID
|
|
CdConvertNameToCdName (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PCD_NAME CdName
|
|
);
|
|
|
|
VOID
|
|
CdConvertBigToLittleEndian (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_reads_bytes_(ByteCount) PCHAR BigEndian,
|
|
_In_ ULONG ByteCount,
|
|
_Out_writes_bytes_(ByteCount) PCHAR LittleEndian
|
|
);
|
|
|
|
VOID
|
|
CdUpcaseName (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PCD_NAME Name,
|
|
_Inout_ PCD_NAME UpcaseName
|
|
);
|
|
|
|
VOID
|
|
CdDissectName (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PUNICODE_STRING RemainingName,
|
|
_Out_ PUNICODE_STRING FinalName
|
|
);
|
|
|
|
BOOLEAN
|
|
CdIsLegalName (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PUNICODE_STRING FileName
|
|
);
|
|
|
|
BOOLEAN
|
|
CdIs8dot3Name (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ UNICODE_STRING FileName
|
|
);
|
|
|
|
VOID
|
|
CdGenerate8dot3Name (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PUNICODE_STRING FileName,
|
|
_In_ ULONG DirentOffset,
|
|
_Out_writes_bytes_to_(BYTE_COUNT_8_DOT_3, *ShortByteCount) PWCHAR ShortFileName,
|
|
_Out_ PUSHORT ShortByteCount
|
|
);
|
|
|
|
BOOLEAN
|
|
CdIsNameInExpression (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PCD_NAME CurrentName,
|
|
_In_ PCD_NAME SearchExpression,
|
|
_In_ ULONG WildcardFlags,
|
|
_In_ BOOLEAN CheckVersion
|
|
);
|
|
|
|
ULONG
|
|
CdShortNameDirentOffset (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PUNICODE_STRING Name
|
|
);
|
|
|
|
FSRTL_COMPARISON_RESULT
|
|
CdFullCompareNames (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PUNICODE_STRING NameA,
|
|
_In_ PUNICODE_STRING NameB
|
|
);
|
|
|
|
|
|
//
|
|
// Filesystem control operations. Implemented in Fsctrl.c
|
|
//
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
_Requires_lock_held_(Vcb->VcbResource)
|
|
NTSTATUS
|
|
CdLockVolumeInternal (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PVCB Vcb,
|
|
_In_opt_ PFILE_OBJECT FileObject
|
|
);
|
|
|
|
NTSTATUS
|
|
CdUnlockVolumeInternal (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PVCB Vcb,
|
|
_In_opt_ PFILE_OBJECT FileObject
|
|
);
|
|
|
|
|
|
//
|
|
// Path table enumeration routines. Implemented in PathSup.c
|
|
//
|
|
|
|
VOID
|
|
CdLookupPathEntry (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ ULONG PathEntryOffset,
|
|
_In_ ULONG Ordinal,
|
|
_In_ BOOLEAN VerifyBounds,
|
|
_Inout_ PCOMPOUND_PATH_ENTRY CompoundPathEntry
|
|
);
|
|
|
|
BOOLEAN
|
|
CdLookupNextPathEntry (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PPATH_ENUM_CONTEXT PathContext,
|
|
_Inout_ PPATH_ENTRY PathEntry
|
|
);
|
|
|
|
_Success_(return != FALSE)
|
|
BOOLEAN
|
|
CdFindPathEntry (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PFCB ParentFcb,
|
|
_In_ PCD_NAME DirName,
|
|
_In_ BOOLEAN IgnoreCase,
|
|
_Inout_ PCOMPOUND_PATH_ENTRY CompoundPathEntry
|
|
);
|
|
|
|
VOID
|
|
CdUpdatePathEntryName (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PPATH_ENTRY PathEntry,
|
|
_In_ BOOLEAN IgnoreCase
|
|
);
|
|
|
|
//
|
|
// VOID
|
|
// CdInitializeCompoundPathEntry (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Out_ PCOMPOUND_PATH_ENTRY CompoundPathEntry
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdCleanupCompoundPathEntry (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Out_ PCOMPOUND_PATH_ENTRY CompoundPathEntry
|
|
// );
|
|
//
|
|
|
|
#define CdInitializeCompoundPathEntry(IC,CP) \
|
|
RtlZeroMemory( CP, sizeof( COMPOUND_PATH_ENTRY ))
|
|
|
|
#define CdCleanupCompoundPathEntry(IC,CP) { \
|
|
CdUnpinData( (IC), &(CP)->PathContext.Bcb ); \
|
|
if ((CP)->PathContext.AllocatedData) { \
|
|
CdFreePool( &(CP)->PathContext.Data ); \
|
|
} \
|
|
if (FlagOn( (CP)->PathEntry.Flags, PATH_ENTRY_FLAG_ALLOC_BUFFER )) { \
|
|
CdFreePool( &(CP)->PathEntry.CdDirName.FileName.Buffer ); \
|
|
} \
|
|
}
|
|
|
|
|
|
//
|
|
// Largest matching prefix searching routines, implemented in PrefxSup.c
|
|
//
|
|
|
|
VOID
|
|
CdInsertPrefix (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PFCB Fcb,
|
|
_In_ PCD_NAME Name,
|
|
_In_ BOOLEAN IgnoreCase,
|
|
_In_ BOOLEAN ShortNameMatch,
|
|
_Inout_ PFCB ParentFcb
|
|
);
|
|
|
|
VOID
|
|
CdRemovePrefix (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PFCB Fcb
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
VOID
|
|
CdFindPrefix (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PFCB *CurrentFcb,
|
|
_Inout_ PUNICODE_STRING RemainingName,
|
|
_In_ BOOLEAN IgnoreCase
|
|
);
|
|
|
|
|
|
//
|
|
// Synchronization routines. Implemented in Resrcsup.c
|
|
//
|
|
// The following routines/macros are used to synchronize the in-memory structures.
|
|
//
|
|
// Routine/Macro Synchronizes Subsequent
|
|
//
|
|
// CdAcquireCdData Volume Mounts/Dismounts,Vcb Queue CdReleaseCdData
|
|
// CdAcquireVcbExclusive Vcb for open/close CdReleaseVcb
|
|
// CdAcquireVcbShared Vcb for open/close CdReleaseVcb
|
|
// CdAcquireAllFiles Locks out operations to all files CdReleaseAllFiles
|
|
// CdAcquireFileExclusive Locks out file operations CdReleaseFile
|
|
// CdAcquireFileShared Files for file operations CdReleaseFile
|
|
// CdAcquireFcbExclusive Fcb for open/close CdReleaseFcb
|
|
// CdAcquireFcbShared Fcb for open/close CdReleaseFcb
|
|
// CdLockCdData Fields in CdData CdUnlockCdData
|
|
// CdLockVcb Vcb fields, FcbReference, FcbTable CdUnlockVcb
|
|
// CdLockFcb Fcb fields, prefix table, Mcb CdUnlockFcb
|
|
//
|
|
|
|
typedef enum _TYPE_OF_ACQUIRE {
|
|
|
|
AcquireExclusive,
|
|
AcquireShared,
|
|
AcquireSharedStarveExclusive
|
|
|
|
} TYPE_OF_ACQUIRE, *PTYPE_OF_ACQUIRE;
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
_When_(Type == AcquireExclusive && return != FALSE, _Acquires_exclusive_lock_(*Resource))
|
|
_When_(Type == AcquireShared && return != FALSE, _Acquires_shared_lock_(*Resource))
|
|
_When_(Type == AcquireSharedStarveExclusive && return != FALSE, _Acquires_shared_lock_(*Resource))
|
|
_When_(IgnoreWait == FALSE, _Post_satisfies_(return == TRUE))
|
|
BOOLEAN
|
|
CdAcquireResource (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PERESOURCE Resource,
|
|
_In_ BOOLEAN IgnoreWait,
|
|
_In_ TYPE_OF_ACQUIRE Type
|
|
);
|
|
|
|
//
|
|
// BOOLEAN
|
|
// CdAcquireCdData (
|
|
// _In_ PIRP_CONTEXT IrpContext
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdReleaseCdData (
|
|
// _In_ PIRP_CONTEXT IrpContext
|
|
// );
|
|
//
|
|
// BOOLEAN
|
|
// CdAcquireVcbExclusive (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Inout_ PVCB Vcb,
|
|
// _In_ BOOLEAN IgnoreWait
|
|
// );
|
|
//
|
|
// BOOLEAN
|
|
// CdAcquireVcbShared (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Inout_ PVCB Vcb,
|
|
// _In_ BOOLEAN IgnoreWait
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdReleaseVcb (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Inout_ PVCB Vcb
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdAcquireAllFiles (
|
|
// _In_ PIRP_CONTEXT,
|
|
// _In_ PVCB Vcb
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdReleaseAllFiles (
|
|
// _In_ PIRP_CONTEXT,
|
|
// _In_ PVCB Vcb
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdAcquireFileExclusive (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Inout_ PFCB Fcb,
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdAcquireFileShared (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Inout_ PFCB Fcb
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdReleaseFile (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Inout_ PFCB Fcb
|
|
// );
|
|
//
|
|
// BOOLEAN
|
|
// CdAcquireFcbExclusive (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Inout_ PFCB Fcb,
|
|
// _In_ BOOLEAN IgnoreWait
|
|
// );
|
|
//
|
|
// BOOLEAN
|
|
// CdAcquireFcbShared (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Inout_ PFCB Fcb,
|
|
// _In_ BOOLEAN IgnoreWait
|
|
// );
|
|
//
|
|
// BOOLEAN
|
|
// CdReleaseFcb (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Inout_ PFCB Fcb
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdLockCdData (
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdUnlockCdData (
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdLockVcb (
|
|
// _In_ PIRP_CONTEXT IrpContext
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdUnlockVcb (
|
|
// _In_ PIRP_CONTEXT IrpContext
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdLockFcb (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Inout_ PFCB Fcb
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdUnlockFcb (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Inout_ PFCB Fcb
|
|
// );
|
|
//
|
|
|
|
|
|
#define CdAcquireCacheForRead( IC) \
|
|
ExAcquireResourceSharedLite( &(IC)->Vcb->SectorCacheResource, TRUE)
|
|
|
|
#define CdAcquireCacheForUpdate( IC) \
|
|
ExAcquireResourceExclusiveLite( &(IC)->Vcb->SectorCacheResource, TRUE)
|
|
|
|
#define CdReleaseCache( IC) \
|
|
ExReleaseResourceLite( &(IC)->Vcb->SectorCacheResource);
|
|
|
|
#define CdConvertCacheToShared( IC) \
|
|
ExConvertExclusiveToSharedLite( &(IC)->Vcb->SectorCacheResource);
|
|
|
|
#define CdAcquireCdData(IC) \
|
|
ExAcquireResourceExclusiveLite( &CdData.DataResource, TRUE )
|
|
|
|
#define CdReleaseCdData(IC) \
|
|
ExReleaseResourceLite( &CdData.DataResource )
|
|
|
|
#define CdAcquireVcbExclusive(IC,V,I) \
|
|
CdAcquireResource( (IC), &(V)->VcbResource, (I), AcquireExclusive )
|
|
|
|
#define CdAcquireVcbShared(IC,V,I) \
|
|
CdAcquireResource( (IC), &(V)->VcbResource, (I), AcquireShared )
|
|
|
|
#define CdReleaseVcb(IC,V) \
|
|
ExReleaseResourceLite( &(V)->VcbResource )
|
|
|
|
#define CdAcquireAllFiles(IC,V) \
|
|
CdAcquireResource( (IC), &(V)->FileResource, FALSE, AcquireExclusive )
|
|
|
|
#define CdReleaseAllFiles(IC,V) \
|
|
ExReleaseResourceLite( &(V)->FileResource )
|
|
|
|
#define CdAcquireFileExclusive(IC,F) \
|
|
CdAcquireResource( (IC), (F)->Resource, FALSE, AcquireExclusive )
|
|
|
|
#define CdAcquireFileShared(IC,F) \
|
|
CdAcquireResource( (IC), (F)->Resource, FALSE, AcquireShared )
|
|
|
|
#define CdAcquireFileSharedStarveExclusive(IC,F) \
|
|
CdAcquireResource( (IC), (F)->Resource, FALSE, AcquireSharedStarveExclusive )
|
|
|
|
#define CdReleaseFile(IC,F) \
|
|
ExReleaseResourceLite( (F)->Resource )
|
|
|
|
#define CdAcquireFcbExclusive(IC,F,I) \
|
|
CdAcquireResource( (IC), &(F)->FcbNonpaged->FcbResource, (I), AcquireExclusive )
|
|
|
|
#define CdAcquireFcbShared(IC,F,I) \
|
|
CdAcquireResource( (IC), &(F)->FcbNonpaged->FcbResource, (I), AcquireShared )
|
|
|
|
#define CdReleaseFcb(IC,F) \
|
|
ExReleaseResourceLite( &(F)->FcbNonpaged->FcbResource )
|
|
|
|
#define CdLockCdData() \
|
|
ExAcquireFastMutex( &CdData.CdDataMutex ); \
|
|
CdData.CdDataLockThread = PsGetCurrentThread()
|
|
|
|
#define CdUnlockCdData() \
|
|
CdData.CdDataLockThread = NULL; \
|
|
ExReleaseFastMutex( &CdData.CdDataMutex )
|
|
|
|
#define CdLockVcb(IC,V) \
|
|
ExAcquireFastMutex( &(V)->VcbMutex ); \
|
|
NT_ASSERT( NULL == (V)->VcbLockThread); \
|
|
(V)->VcbLockThread = PsGetCurrentThread()
|
|
|
|
#define CdUnlockVcb(IC,V) \
|
|
NT_ASSERT( NULL != (V)->VcbLockThread); \
|
|
(V)->VcbLockThread = NULL; \
|
|
ExReleaseFastMutex( &(V)->VcbMutex )
|
|
|
|
#if defined(_PREFAST_)
|
|
|
|
_Success_(return)
|
|
_IRQL_saves_global_(OldIrql, FastMutex)
|
|
BOOLEAN DummySaveIrql(_Inout_ PFAST_MUTEX FastMutex);
|
|
|
|
_Success_(return)
|
|
_IRQL_restores_global_(OldIrql, FastMutex)
|
|
BOOLEAN DummyRestoreIrql(_Inout_ PFAST_MUTEX FastMutex);
|
|
#endif // _PREFAST_
|
|
|
|
#define CdLockFcb(IC,F) { \
|
|
PVOID _CurrentThread = PsGetCurrentThread(); \
|
|
if (_CurrentThread != (F)->FcbLockThread) { \
|
|
ExAcquireFastMutex( &(F)->FcbNonpaged->FcbMutex ); \
|
|
NT_ASSERT( (F)->FcbLockCount == 0 ); \
|
|
_Analysis_assume_( (F)->FcbLockCount == 0 ); \
|
|
(F)->FcbLockThread = _CurrentThread; \
|
|
} \
|
|
else \
|
|
{ \
|
|
_Analysis_assume_lock_held_( (F)->FcbNonpaged->FcbMutex ); \
|
|
_Analysis_assume_(FALSE != DummySaveIrql(&(F)->FcbNonpaged->FcbMutex)); \
|
|
} \
|
|
(F)->FcbLockCount += 1; \
|
|
}
|
|
|
|
#define CdUnlockFcb(IC,F) { \
|
|
(F)->FcbLockCount -= 1; \
|
|
if ((F)->FcbLockCount == 0) { \
|
|
(F)->FcbLockThread = NULL; \
|
|
ExReleaseFastMutex( &(F)->FcbNonpaged->FcbMutex ); \
|
|
} \
|
|
else \
|
|
{ \
|
|
_Analysis_assume_lock_not_held_( (F)->FcbNonpaged->FcbMutex ); \
|
|
_Analysis_assume_(FALSE != DummyRestoreIrql(&(F)->FcbNonpaged->FcbMutex)); \
|
|
} \
|
|
}
|
|
|
|
//
|
|
// The following macro is used to retrieve the oplock structure within
|
|
// the Fcb. This structure was moved to the advanced Fcb header
|
|
// in Win8.
|
|
//
|
|
|
|
#if (NTDDI_VERSION >= NTDDI_WIN8)
|
|
|
|
#define CdGetFcbOplock(F) &(F)->Header.Oplock
|
|
|
|
#else
|
|
|
|
#define CdGetFcbOplock(F) &(F)->Oplock
|
|
|
|
#endif
|
|
|
|
BOOLEAN
|
|
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
|
|
CdNoopAcquire (
|
|
_In_ PVOID Fcb,
|
|
_In_ BOOLEAN Wait
|
|
);
|
|
|
|
VOID
|
|
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
|
|
CdNoopRelease (
|
|
_In_ PVOID Fcb
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
_When_(return!=0, _Acquires_shared_lock_(*Fcb->Resource))
|
|
BOOLEAN
|
|
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
|
|
CdAcquireForCache (
|
|
_Inout_ PFCB Fcb,
|
|
_In_ BOOLEAN Wait
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
_Releases_lock_(*Fcb->Resource)
|
|
VOID
|
|
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
|
|
CdReleaseFromCache (
|
|
_Inout_ PFCB Fcb
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
NTSTATUS
|
|
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
|
|
CdFilterCallbackAcquireForCreateSection (
|
|
_In_ PFS_FILTER_CALLBACK_DATA CallbackData,
|
|
_Unreferenced_parameter_ PVOID *CompletionContext
|
|
);
|
|
|
|
_Function_class_(FAST_IO_RELEASE_FILE)
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
VOID
|
|
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
|
|
CdReleaseForCreateSection (
|
|
_In_ PFILE_OBJECT FileObject
|
|
);
|
|
|
|
|
|
//
|
|
// In-memory structure support routines. Implemented in StrucSup.c
|
|
//
|
|
|
|
VOID
|
|
CdInitializeVcb (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PVCB Vcb,
|
|
_In_ __drv_aliasesMem PDEVICE_OBJECT TargetDeviceObject,
|
|
_In_ __drv_aliasesMem PVPB Vpb,
|
|
_In_ __drv_aliasesMem PCDROM_TOC_LARGE CdromToc,
|
|
_In_ ULONG TocLength,
|
|
_In_ ULONG TocTrackCount,
|
|
_In_ ULONG TocDiskFlags,
|
|
_In_ ULONG BlockFactor,
|
|
_In_ ULONG MediaChangeCount
|
|
);
|
|
|
|
VOID
|
|
CdUpdateVcbFromVolDescriptor (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PVCB Vcb,
|
|
_In_reads_bytes_opt_(SECTOR_SIZE) PCHAR RawIsoVd
|
|
);
|
|
|
|
VOID
|
|
CdDeleteVcb (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PVCB Vcb
|
|
);
|
|
|
|
PFCB
|
|
CdCreateFcb (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ FILE_ID FileId,
|
|
_In_ NODE_TYPE_CODE NodeTypeCode,
|
|
_Out_opt_ PBOOLEAN FcbExisted
|
|
);
|
|
|
|
VOID
|
|
CdInitializeFcbFromPathEntry (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PFCB Fcb,
|
|
_In_opt_ PFCB ParentFcb,
|
|
_In_ PPATH_ENTRY PathEntry
|
|
);
|
|
|
|
VOID
|
|
CdInitializeFcbFromFileContext (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PFCB Fcb,
|
|
_In_ PFCB ParentFcb,
|
|
_In_ PFILE_ENUM_CONTEXT FileContext
|
|
);
|
|
|
|
PCCB
|
|
CdCreateCcb (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PFCB Fcb,
|
|
_In_ ULONG Flags
|
|
);
|
|
|
|
VOID
|
|
CdDeleteCcb (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ __drv_freesMem( Pool ) PCCB Ccb
|
|
);
|
|
|
|
_When_(RaiseOnError || return, _At_(Fcb->FileLock, _Post_notnull_))
|
|
_When_(RaiseOnError, _At_(IrpContext, _Pre_notnull_))
|
|
BOOLEAN
|
|
CdCreateFileLock (
|
|
_In_opt_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PFCB Fcb,
|
|
_In_ BOOLEAN RaiseOnError
|
|
);
|
|
|
|
VOID
|
|
CdDeleteFileLock (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PFILE_LOCK FileLock
|
|
);
|
|
|
|
_Ret_valid_ PIRP_CONTEXT
|
|
CdCreateIrpContext (
|
|
_In_ PIRP Irp,
|
|
_In_ BOOLEAN Wait
|
|
);
|
|
|
|
VOID
|
|
CdCleanupIrpContext (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ BOOLEAN Post
|
|
);
|
|
|
|
VOID
|
|
CdInitializeStackIrpContext (
|
|
_Out_ PIRP_CONTEXT IrpContext,
|
|
_In_ PIRP_CONTEXT_LITE IrpContextLite
|
|
);
|
|
|
|
//
|
|
// PIRP_CONTEXT_LITE
|
|
// CdCreateIrpContextLite (
|
|
// _In_ PIRP_CONTEXT IrpContext
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdFreeIrpContextLite (
|
|
// _Inout_ PIRP_CONTEXT_LITE IrpContextLite
|
|
// );
|
|
//
|
|
|
|
#define CdCreateIrpContextLite(IC) \
|
|
ExAllocatePoolWithTag( CdNonPagedPool, sizeof( IRP_CONTEXT_LITE ), TAG_IRP_CONTEXT_LITE )
|
|
|
|
#define CdFreeIrpContextLite(ICL) \
|
|
CdFreePool( &(ICL) )
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
VOID
|
|
CdTeardownStructures (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PFCB StartingFcb,
|
|
_Out_ PBOOLEAN RemovedStartingFcb
|
|
);
|
|
|
|
//
|
|
// VOID
|
|
// CdIncrementCleanupCounts (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Inout_ PFCB Fcb
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdDecrementCleanupCounts (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Inout_ PFCB Fcb
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdIncrementReferenceCounts (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Inout_ PFCB Fcb,
|
|
// _In_ ULONG ReferenceCount
|
|
// _In_ ULONG UserReferenceCount
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdDecrementReferenceCounts (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Inout_ PFCB Fcb,
|
|
// _In_ ULONG ReferenceCount
|
|
// _In_ ULONG UserReferenceCount
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdIncrementFcbReference (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Inout_ PFCB Fcb
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdDecrementFcbReference (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _Inout_ PFCB Fcb
|
|
// );
|
|
//
|
|
|
|
#define CdIncrementCleanupCounts(IC,F) { \
|
|
ASSERT_LOCKED_VCB( (F)->Vcb ); \
|
|
(F)->FcbCleanup += 1; \
|
|
(F)->Vcb->VcbCleanup += 1; \
|
|
}
|
|
|
|
#define CdDecrementCleanupCounts(IC,F) { \
|
|
ASSERT_LOCKED_VCB( (F)->Vcb ); \
|
|
(F)->FcbCleanup -= 1; \
|
|
(F)->Vcb->VcbCleanup -= 1; \
|
|
}
|
|
|
|
#define CdIncrementReferenceCounts(IC,F,C,UC) { \
|
|
ASSERT_LOCKED_VCB( (F)->Vcb ); \
|
|
(F)->FcbReference += (C); \
|
|
(F)->FcbUserReference += (UC); \
|
|
(F)->Vcb->VcbReference += (C); \
|
|
(F)->Vcb->VcbUserReference += (UC); \
|
|
}
|
|
|
|
#define CdDecrementReferenceCounts(IC,F,C,UC) { \
|
|
ASSERT_LOCKED_VCB( (F)->Vcb ); \
|
|
(F)->FcbReference -= (C); \
|
|
(F)->FcbUserReference -= (UC); \
|
|
(F)->Vcb->VcbReference -= (C); \
|
|
(F)->Vcb->VcbUserReference -= (UC); \
|
|
}
|
|
|
|
//
|
|
// PCD_IO_CONTEXT
|
|
// CdAllocateIoContext (
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdFreeIoContext (
|
|
// PCD_IO_CONTEXT IoContext
|
|
// );
|
|
//
|
|
|
|
#define CdAllocateIoContext() \
|
|
FsRtlAllocatePoolWithTag( CdNonPagedPool, \
|
|
sizeof( CD_IO_CONTEXT ), \
|
|
TAG_IO_CONTEXT )
|
|
|
|
#define CdFreeIoContext(IO) CdFreePool( (PVOID) &(IO) ) /* ReactOS Change: GCC "passing argument 1 from incompatible pointer type" */
|
|
|
|
PFCB
|
|
CdLookupFcbTable (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PVCB Vcb,
|
|
_In_ FILE_ID FileId
|
|
);
|
|
|
|
PFCB
|
|
CdGetNextFcb (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PVCB Vcb,
|
|
_In_ PVOID *RestartKey
|
|
);
|
|
|
|
NTSTATUS
|
|
CdProcessToc (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ PDEVICE_OBJECT TargetDeviceObject,
|
|
_In_ PCDROM_TOC_LARGE CdromToc,
|
|
_Inout_ PULONG Length,
|
|
_Out_ PULONG TrackCount,
|
|
_Inout_ PULONG DiskFlags
|
|
);
|
|
|
|
//
|
|
// 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 CdPagedPool PagedPool
|
|
#define CdNonPagedPool NonPagedPoolNx
|
|
#define CdNonPagedPoolCacheAligned NonPagedPoolNxCacheAligned
|
|
|
|
|
|
//
|
|
// Verification support routines. Contained in verfysup.c
|
|
//
|
|
|
|
static /* ReactOS Change: GCC "multiple definition" */
|
|
INLINE
|
|
BOOLEAN
|
|
CdOperationIsDasdOpen (
|
|
_In_ PIRP_CONTEXT IrpContext
|
|
)
|
|
{
|
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( IrpContext->Irp);
|
|
|
|
return ((IrpContext->MajorFunction == IRP_MJ_CREATE) &&
|
|
(IrpSp->FileObject->FileName.Length == 0) &&
|
|
(IrpSp->FileObject->RelatedFileObject == NULL));
|
|
}
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
NTSTATUS
|
|
CdPerformVerify (
|
|
_Inout_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PIRP Irp,
|
|
_In_ PDEVICE_OBJECT DeviceToVerify
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
BOOLEAN
|
|
CdCheckForDismount (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PVCB Vcb,
|
|
_In_ BOOLEAN Force
|
|
);
|
|
|
|
BOOLEAN
|
|
CdMarkDevForVerifyIfVcbMounted (
|
|
_Inout_ PVCB Vcb
|
|
);
|
|
|
|
VOID
|
|
CdVerifyVcb (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PVCB Vcb
|
|
);
|
|
|
|
BOOLEAN
|
|
CdVerifyFcbOperation (
|
|
_In_opt_ PIRP_CONTEXT IrpContext,
|
|
_In_ PFCB Fcb
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
BOOLEAN
|
|
CdDismountVcb (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PVCB Vcb
|
|
);
|
|
|
|
|
|
//
|
|
// Macros to abstract device verify flag changes.
|
|
//
|
|
|
|
#define CdUpdateMediaChangeCount( V, C) (V)->MediaChangeCount = (C)
|
|
#define CdUpdateVcbCondition( V, C) (V)->VcbCondition = (C)
|
|
|
|
#define CdMarkRealDevForVerify( DO) SetFlag( (DO)->Flags, DO_VERIFY_VOLUME)
|
|
|
|
#define CdMarkRealDevVerifyOk( DO) ClearFlag( (DO)->Flags, DO_VERIFY_VOLUME)
|
|
|
|
|
|
#define CdRealDevNeedsVerify( DO) BooleanFlagOn( (DO)->Flags, DO_VERIFY_VOLUME)
|
|
|
|
//
|
|
// BOOLEAN
|
|
// CdIsRawDevice (
|
|
// _In_ PIRP_CONTEXT IrpContext,
|
|
// _In_ NTSTATUS Status
|
|
// );
|
|
//
|
|
|
|
#define CdIsRawDevice(IC,S) ( \
|
|
((S) == STATUS_DEVICE_NOT_READY) || \
|
|
((S) == STATUS_NO_MEDIA_IN_DEVICE) \
|
|
)
|
|
|
|
|
|
//
|
|
// Work queue routines for posting and retrieving an Irp, implemented in
|
|
// workque.c
|
|
//
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
NTSTATUS
|
|
CdFsdPostRequest (
|
|
_Inout_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PIRP Irp
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
VOID
|
|
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
|
|
CdPrePostIrp (
|
|
_Inout_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PIRP Irp
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
VOID
|
|
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
|
|
CdOplockComplete (
|
|
_Inout_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PIRP Irp
|
|
);
|
|
|
|
|
|
//
|
|
// Miscellaneous support routines
|
|
//
|
|
|
|
//
|
|
// This macro returns TRUE if a flag in a set of flags is on and FALSE
|
|
// otherwise
|
|
//
|
|
|
|
/* GCC complains about multi-line comments.
|
|
//#ifndef BooleanFlagOn
|
|
//#define BooleanFlagOn(F,SF) ( \
|
|
// (BOOLEAN)(((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)((PUCHAR)(PTR) + (INC)))
|
|
|
|
#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 macros round up and down to sector boundaries.
|
|
//
|
|
|
|
#define SectorAlign(L) ( \
|
|
((((ULONG)(L)) + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1)) \
|
|
)
|
|
|
|
#define LlSectorAlign(L) ( \
|
|
((((LONGLONG)(L)) + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1)) \
|
|
)
|
|
|
|
#define SectorTruncate(L) ( \
|
|
((ULONG)(L)) & ~(SECTOR_SIZE - 1) \
|
|
)
|
|
|
|
#define LlSectorTruncate(L) ( \
|
|
((LONGLONG)(L)) & ~(SECTOR_SIZE - 1) \
|
|
)
|
|
|
|
#define BytesFromSectors(L) ( \
|
|
((ULONG) (L)) << SECTOR_SHIFT \
|
|
)
|
|
|
|
#define SectorsFromBytes(L) ( \
|
|
((ULONG) (L)) >> SECTOR_SHIFT \
|
|
)
|
|
|
|
static /* ReactOS Change: GCC "multiple definition" */
|
|
INLINE
|
|
ULONG
|
|
SectorsFromLlBytes(
|
|
ULONGLONG Bytes
|
|
) {
|
|
|
|
return (ULONG)(Bytes >> SECTOR_SHIFT);
|
|
}
|
|
|
|
#define LlBytesFromSectors(L) ( \
|
|
Int64ShllMod32( (LONGLONG)(L), SECTOR_SHIFT ) \
|
|
)
|
|
|
|
#define LlSectorsFromBytes(L) ( \
|
|
Int64ShraMod32( (LONGLONG)(L), SECTOR_SHIFT ) \
|
|
)
|
|
|
|
#define SectorOffset(L) ( \
|
|
((ULONG)(ULONG_PTR) (L)) & SECTOR_MASK \
|
|
)
|
|
|
|
#define SectorBlockOffset(V,LB) ( \
|
|
((ULONG) (LB)) & ((V)->BlocksPerSector - 1) \
|
|
)
|
|
|
|
#define BytesFromBlocks(V,B) ( \
|
|
(ULONG) (B) << (V)->BlockToByteShift \
|
|
)
|
|
|
|
#define LlBytesFromBlocks(V,B) ( \
|
|
Int64ShllMod32( (LONGLONG) (B), (V)->BlockToByteShift ) \
|
|
)
|
|
|
|
#define BlockAlign(V,L) ( \
|
|
((ULONG)(L) + (V)->BlockMask) & (V)->BlockInverseMask \
|
|
)
|
|
|
|
//
|
|
// Carefully make sure the mask is sign extended to 64bits
|
|
//
|
|
|
|
#define LlBlockAlign(V,L) ( \
|
|
((LONGLONG)(L) + (V)->BlockMask) & (LONGLONG)((LONG)(V)->BlockInverseMask) \
|
|
)
|
|
|
|
#define BlockOffset(V,L) ( \
|
|
((ULONG) (L)) & (V)->BlockMask \
|
|
)
|
|
|
|
#define RawSectorAlign( B) ((((B)+(RAW_SECTOR_SIZE - 1)) / RAW_SECTOR_SIZE) * RAW_SECTOR_SIZE)
|
|
|
|
//
|
|
// 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;
|
|
|
|
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 longword to an aligned dsr longword
|
|
//
|
|
|
|
#define CopyUchar4(Dst,Src) { \
|
|
*((UCHAR4 *)(Dst)) = *((UNALIGNED UCHAR4 *)(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));\
|
|
}
|
|
|
|
//
|
|
// 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)); \
|
|
}
|
|
|
|
VOID
|
|
CdLbnToMmSsFf (
|
|
_In_ ULONG Blocks,
|
|
_Out_writes_(3) PUCHAR Msf
|
|
);
|
|
|
|
//
|
|
// Following routines handle entry in and out of the filesystem. They are
|
|
// contained in CdData.c
|
|
//
|
|
|
|
_IRQL_requires_max_(APC_LEVEL)
|
|
__drv_dispatchType(DRIVER_DISPATCH)
|
|
__drv_dispatchType(IRP_MJ_CREATE)
|
|
__drv_dispatchType(IRP_MJ_CLOSE)
|
|
__drv_dispatchType(IRP_MJ_READ)
|
|
__drv_dispatchType(IRP_MJ_WRITE)
|
|
__drv_dispatchType(IRP_MJ_QUERY_INFORMATION)
|
|
__drv_dispatchType(IRP_MJ_SET_INFORMATION)
|
|
__drv_dispatchType(IRP_MJ_QUERY_VOLUME_INFORMATION)
|
|
__drv_dispatchType(IRP_MJ_DIRECTORY_CONTROL)
|
|
__drv_dispatchType(IRP_MJ_FILE_SYSTEM_CONTROL)
|
|
__drv_dispatchType(IRP_MJ_DEVICE_CONTROL)
|
|
__drv_dispatchType(IRP_MJ_LOCK_CONTROL)
|
|
__drv_dispatchType(IRP_MJ_CLEANUP)
|
|
__drv_dispatchType(IRP_MJ_PNP)
|
|
__drv_dispatchType(IRP_MJ_SHUTDOWN)
|
|
NTSTATUS
|
|
NTAPI
|
|
CdFsdDispatch (
|
|
_In_ PDEVICE_OBJECT DeviceObject,
|
|
_Inout_ PIRP Irp
|
|
);
|
|
|
|
// DRIVER_DISPATCH CdFsdDispatch;
|
|
|
|
LONG
|
|
CdExceptionFilter (
|
|
_Inout_ PIRP_CONTEXT IrpContext,
|
|
_In_ PEXCEPTION_POINTERS ExceptionPointer
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
NTSTATUS
|
|
CdProcessException (
|
|
_In_opt_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PIRP Irp,
|
|
_In_ NTSTATUS ExceptionCode
|
|
);
|
|
|
|
VOID
|
|
CdCompleteRequest (
|
|
_Inout_opt_ PIRP_CONTEXT IrpContext,
|
|
_Inout_opt_ PIRP Irp,
|
|
_In_ NTSTATUS Status
|
|
);
|
|
|
|
//
|
|
// VOID
|
|
// CdRaiseStatus (
|
|
// _In_ PRIP_CONTEXT IrpContext,
|
|
// _In_ NT_STATUS Status
|
|
// );
|
|
//
|
|
// VOID
|
|
// CdNormalizeAndRaiseStatus (
|
|
// _In_ PRIP_CONTEXT IrpContext,
|
|
// _In_ NT_STATUS Status
|
|
// );
|
|
//
|
|
|
|
#if 0
|
|
#define AssertVerifyDevice(C, S) \
|
|
NT_ASSERT( (C) == NULL || \
|
|
FlagOn( (C)->Flags, IRP_CONTEXT_FLAG_IN_FSP ) || \
|
|
!((S) == STATUS_VERIFY_REQUIRED && \
|
|
IoGetDeviceToVerify( PsGetCurrentThread() ) == NULL ));
|
|
|
|
#define AssertVerifyDeviceIrp(I) \
|
|
NT_ASSERT( (I) == NULL || \
|
|
!(((I)->IoStatus.Status) == STATUS_VERIFY_REQUIRED && \
|
|
((I)->Tail.Overlay.Thread == NULL || \
|
|
IoGetDeviceToVerify( (I)->Tail.Overlay.Thread ) == NULL )));
|
|
#else
|
|
#define AssertVerifyDevice(C, S)
|
|
#define AssertVerifyDeviceIrp(I)
|
|
#endif
|
|
|
|
|
|
#ifdef CD_SANITY
|
|
|
|
DECLSPEC_NORETURN
|
|
VOID
|
|
CdRaiseStatusEx (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ NTSTATUS Status,
|
|
_In_ BOOLEAN NormalizeStatus,
|
|
_In_opt_ ULONG FileId,
|
|
_In_opt_ ULONG Line
|
|
);
|
|
|
|
#else
|
|
|
|
#ifdef __REACTOS__
|
|
static // make windows gcc release build compile
|
|
#endif
|
|
INLINE
|
|
DECLSPEC_NORETURN
|
|
VOID
|
|
CdRaiseStatusEx(
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_In_ NTSTATUS Status,
|
|
_In_ BOOLEAN NormalizeStatus,
|
|
_In_ ULONG Fileid,
|
|
_In_ ULONG Line
|
|
)
|
|
{
|
|
if (NormalizeStatus) {
|
|
|
|
IrpContext->ExceptionStatus = FsRtlNormalizeNtstatus( Status, STATUS_UNEXPECTED_IO_ERROR);
|
|
}
|
|
else {
|
|
|
|
IrpContext->ExceptionStatus = Status;
|
|
}
|
|
|
|
IrpContext->RaisedAtLineFile = (Fileid << 16) | Line;
|
|
|
|
ExRaiseStatus( IrpContext->ExceptionStatus );
|
|
}
|
|
|
|
#endif
|
|
|
|
#define CdRaiseStatus( IC, S) CdRaiseStatusEx( (IC), (S), FALSE, BugCheckFileId, __LINE__);
|
|
#define CdNormalizeAndRaiseStatus( IC, S) CdRaiseStatusEx( (IC), (S), TRUE, BugCheckFileId, __LINE__);
|
|
|
|
//
|
|
// Following are the fast entry points.
|
|
//
|
|
|
|
// _Success_(return != FALSE)
|
|
// BOOLEAN
|
|
// CdFastQueryBasicInfo (
|
|
// _In_ PFILE_OBJECT FileObject,
|
|
// _In_ BOOLEAN Wait,
|
|
// _Out_ PFILE_BASIC_INFORMATION Buffer,
|
|
// _Out_ PIO_STATUS_BLOCK IoStatus,
|
|
// _In_ PDEVICE_OBJECT DeviceObject
|
|
// );
|
|
|
|
FAST_IO_QUERY_BASIC_INFO CdFastQueryBasicInfo;
|
|
|
|
// _Success_(return != FALSE)
|
|
// BOOLEAN
|
|
// CdFastQueryStdInfo (
|
|
// _In_ PFILE_OBJECT FileObject,
|
|
// _In_ BOOLEAN Wait,
|
|
// _Out_ PFILE_STANDARD_INFORMATION Buffer,
|
|
// _Out_ PIO_STATUS_BLOCK IoStatus,
|
|
// _In_ PDEVICE_OBJECT DeviceObject
|
|
// );
|
|
|
|
FAST_IO_QUERY_STANDARD_INFO CdFastQueryStdInfo;
|
|
|
|
// BOOLEAN
|
|
// CdFastLock (
|
|
// _In_ PFILE_OBJECT FileObject,
|
|
// _In_ PLARGE_INTEGER FileOffset,
|
|
// _In_ PLARGE_INTEGER Length,
|
|
// _In_ PEPROCESS ProcessId,
|
|
// _In_ ULONG Key,
|
|
// _In_ BOOLEAN FailImmediately,
|
|
// _In_ BOOLEAN ExclusiveLock,
|
|
// _Out_ PIO_STATUS_BLOCK IoStatus,
|
|
// _In_ PDEVICE_OBJECT DeviceObject
|
|
// );
|
|
|
|
FAST_IO_LOCK CdFastLock;
|
|
|
|
// BOOLEAN
|
|
// CdFastUnlockSingle (
|
|
// _In_ PFILE_OBJECT FileObject,
|
|
// _In_ PLARGE_INTEGER FileOffset,
|
|
// _In_ PLARGE_INTEGER Length,
|
|
// _In_ PEPROCESS ProcessId,
|
|
// _In_ ULONG Key,
|
|
// _Out_ PIO_STATUS_BLOCK IoStatus,
|
|
// _In_ PDEVICE_OBJECT DeviceObject
|
|
// );
|
|
|
|
FAST_IO_UNLOCK_SINGLE CdFastUnlockSingle;
|
|
|
|
// BOOLEAN
|
|
// CdFastUnlockAll (
|
|
// _In_ PFILE_OBJECT FileObject,
|
|
// _In_ PEPROCESS ProcessId,
|
|
// _Out_ PIO_STATUS_BLOCK IoStatus,
|
|
// _In_ PDEVICE_OBJECT DeviceObject
|
|
// );
|
|
|
|
FAST_IO_UNLOCK_ALL CdFastUnlockAll;
|
|
|
|
// BOOLEAN
|
|
// CdFastUnlockAllByKey (
|
|
// _In_ PFILE_OBJECT FileObject,
|
|
// _In_ PVOID ProcessId,
|
|
// _In_ ULONG Key,
|
|
// _Out_ PIO_STATUS_BLOCK IoStatus,
|
|
// _In_ PDEVICE_OBJECT DeviceObject
|
|
// );
|
|
|
|
FAST_IO_UNLOCK_ALL_BY_KEY CdFastUnlockAllByKey;
|
|
|
|
// BOOLEAN
|
|
// CdFastIoCheckIfPossible (
|
|
// _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
|
|
// );
|
|
|
|
FAST_IO_CHECK_IF_POSSIBLE CdFastIoCheckIfPossible;
|
|
|
|
// _Success_(return != FALSE)
|
|
// BOOLEAN
|
|
// CdFastQueryNetworkInfo (
|
|
// _In_ PFILE_OBJECT FileObject,
|
|
// _In_ BOOLEAN Wait,
|
|
// _Out_ PFILE_NETWORK_OPEN_INFORMATION Buffer,
|
|
// _Out_ PIO_STATUS_BLOCK IoStatus,
|
|
// _In_ PDEVICE_OBJECT DeviceObject
|
|
// );
|
|
|
|
FAST_IO_QUERY_NETWORK_OPEN_INFO CdFastQueryNetworkInfo;
|
|
|
|
//
|
|
// Following are the routines to handle the top level thread logic.
|
|
//
|
|
|
|
VOID
|
|
CdSetThreadContext (
|
|
_Inout_ PIRP_CONTEXT IrpContext,
|
|
_In_ PTHREAD_CONTEXT ThreadContext
|
|
);
|
|
|
|
|
|
//
|
|
// VOID
|
|
// CdRestoreThreadContext (
|
|
// _Inout_ PIRP_CONTEXT IrpContext
|
|
// );
|
|
//
|
|
|
|
#define CdRestoreThreadContext(IC) \
|
|
(IC)->ThreadContext->Cdfs = 0; \
|
|
IoSetTopLevelIrp( (IC)->ThreadContext->SavedTopLevelIrp ); \
|
|
(IC)->ThreadContext = NULL
|
|
|
|
ULONG
|
|
CdSerial32 (
|
|
_In_reads_bytes_(ByteCount) PCHAR Buffer,
|
|
_In_ ULONG ByteCount
|
|
);
|
|
|
|
//
|
|
// 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 CdIsFastIoPossible(F) ((BOOLEAN) \
|
|
((((F)->Vcb->VcbCondition != VcbMounted ) || \
|
|
!FsRtlOplockIsFastIoPossible( CdGetFcbOplock(F) )) ? \
|
|
\
|
|
FastIoIsNotPossible : \
|
|
\
|
|
((((F)->FileLock != NULL) && FsRtlAreThereCurrentFileLocks( (F)->FileLock )) ? \
|
|
\
|
|
FastIoIsQuestionable : \
|
|
\
|
|
FastIoIsPossible)) \
|
|
)
|
|
|
|
|
|
//
|
|
// 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
|
|
// CdFspDispatch ( // implemented in FspDisp.c
|
|
// _Inout_ PIRP_CONTEXT IrpContext
|
|
// );
|
|
|
|
WORKER_THREAD_ROUTINE CdFspDispatch;
|
|
|
|
VOID
|
|
CdFspClose ( // implemented in Close.c
|
|
_In_opt_ PVCB Vcb
|
|
);
|
|
|
|
//
|
|
// The following routines are the entry points for the different operations
|
|
// based on the IrpSp major functions.
|
|
//
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
NTSTATUS
|
|
CdCommonCreate ( // Implemented in Create.c
|
|
_Inout_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PIRP Irp
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
NTSTATUS
|
|
CdCommonClose ( // Implemented in Close.c
|
|
_Inout_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PIRP Irp
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
NTSTATUS
|
|
CdCommonRead ( // Implemented in Read.c
|
|
_Inout_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PIRP Irp
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
NTSTATUS
|
|
CdCommonWrite ( // Implemented in Write.c
|
|
_Inout_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PIRP Irp
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
NTSTATUS
|
|
CdCommonQueryInfo ( // Implemented in FileInfo.c
|
|
_Inout_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PIRP Irp
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
NTSTATUS
|
|
CdCommonSetInfo ( // Implemented in FileInfo.c
|
|
_Inout_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PIRP Irp
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
NTSTATUS
|
|
CdCommonQueryVolInfo ( // Implemented in VolInfo.c
|
|
_Inout_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PIRP Irp
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
NTSTATUS
|
|
CdCommonDirControl ( // Implemented in DirCtrl.c
|
|
_Inout_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PIRP Irp
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
NTSTATUS
|
|
CdCommonFsControl ( // Implemented in FsCtrl.c
|
|
_Inout_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
CdCommonDevControl ( // Implemented in DevCtrl.c
|
|
_Inout_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
CdCommonLockControl ( // Implemented in LockCtrl.c
|
|
_Inout_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PIRP Irp
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
NTSTATUS
|
|
CdCommonCleanup ( // Implemented in Cleanup.c
|
|
_Inout_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PIRP Irp
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
NTSTATUS
|
|
CdCommonPnp ( // Implemented in Pnp.c
|
|
_Inout_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PIRP Irp
|
|
);
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
NTSTATUS
|
|
CdCommonShutdown ( // Implemented in Shutdown.c
|
|
_Inout_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PIRP Irp
|
|
);
|
|
|
|
|
|
|
|
//
|
|
// 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; }
|
|
//
|
|
|
|
#ifndef __REACTOS__
|
|
#define try_return(S) { S; goto try_exit; }
|
|
#define try_leave(S) { S; leave; }
|
|
#else
|
|
#define try_return(S) { S; goto try_exit; }
|
|
#define try_leave(S) { S; _SEH2_LEAVE; }
|
|
#endif
|
|
|
|
//
|
|
// Encapsulate safe pool freeing
|
|
//
|
|
/* ReactOS Change: GCC "passing argument 1 of CdFreePool from incompatible pointer type" */
|
|
#define CdFreePool(x) _CdFreePool((PVOID*)(x))
|
|
|
|
static /* ReactOS Change: GCC "multiple definition" */
|
|
INLINE
|
|
VOID
|
|
_CdFreePool(
|
|
_Inout_ _At_(*Pool, __drv_freesMem(Mem) _Post_null_) PVOID *Pool
|
|
)
|
|
{
|
|
if (*Pool != NULL) {
|
|
|
|
ExFreePool(*Pool);
|
|
*Pool = NULL;
|
|
}
|
|
}
|
|
|
|
#ifdef CDFS_TELEMETRY_DATA
|
|
|
|
//
|
|
// CDFS Telemetry. Current implementation uses the Telemetry TraceLogging APIs.
|
|
//
|
|
// The Telemetry TraceLoggingWrite() routines use a lot of stack space. We must
|
|
// therefor wrap all our telemetry points with our own routines, and add a guard to
|
|
// make sure there's enough stack space to call these routines.
|
|
//
|
|
// These telemetry routines should not be called on high-performance code paths.
|
|
//
|
|
|
|
TRACELOGGING_DECLARE_PROVIDER( CdTelemetryProvider );
|
|
|
|
VOID
|
|
CdInitializeTelemetry (
|
|
VOID
|
|
);
|
|
|
|
DECLSPEC_NOINLINE
|
|
VOID
|
|
CdTelemetryMount (
|
|
__in PGUID VolumeGuid,
|
|
__in NTSTATUS Status,
|
|
__in PVCB Vcb
|
|
);
|
|
|
|
//
|
|
// Every additional argument passed to TraceLoggingWrite() consumes an additional
|
|
// 16 to 32 bytes extra stack space. Having 512 bytes reserved space should be
|
|
// sufficient for up to 20 arguments or so. This will be less of course if our
|
|
// wrapper routines also declare their own local variables.
|
|
//
|
|
|
|
#define CDFS_TELEMETRY_STACK_THRESHOLD_DEFAULT 512 // for "small" telemetry points
|
|
#define CDFS_TELEMETRY_STACK_THRESHOLD_LARGE 2048 // for "large" telemetry points
|
|
|
|
INLINE
|
|
BOOLEAN
|
|
CdTelemetryGuard (
|
|
__in ULONG StackSpaceNeeded )
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine returns TRUE only when:
|
|
|
|
1) There is an ETW listener, AND
|
|
2) There is enough free stack space to safely call the Telemetry TraceLogging APIs
|
|
|
|
We'll also count how many times there wasn't enough stack space, and include this
|
|
value as part of the periodic cdfs Telemetry.
|
|
|
|
Arguments:
|
|
|
|
StackSpaceNeeded - Stack space needed in bytes
|
|
|
|
--*/
|
|
{
|
|
ASSERT( IoGetRemainingStackSize() >= StackSpaceNeeded );
|
|
|
|
if (CdTelemetryProvider->LevelPlus1 <= 5) {
|
|
|
|
//
|
|
// Bail out early if there are no ETW listeners
|
|
//
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (IoGetRemainingStackSize() < StackSpaceNeeded) {
|
|
|
|
//
|
|
// Count how many times it was unsafe to generate telemetry because of
|
|
// not enough stack space.
|
|
//
|
|
|
|
InterlockedIncrement( &CdTelemetryData.MissedTelemetryPoints );
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#define CdTelemetryMountSafe( VolumeGuid, Status, Vcb ) \
|
|
if (CdTelemetryGuard( CDFS_TELEMETRY_STACK_THRESHOLD_LARGE )) { \
|
|
CdTelemetryMount( VolumeGuid, Status, Vcb ); \
|
|
}
|
|
|
|
#if DBG
|
|
#define CDFS_TELEMETRY_PERIODIC_INTERVAL CdTelemetryData.PeriodicInterval
|
|
#else
|
|
#define CDFS_TELEMETRY_PERIODIC_INTERVAL INTERVAL_ONE_DAY
|
|
#endif
|
|
|
|
#else // CDFS_TELEMETRY_DATA
|
|
|
|
//
|
|
// When CDFS_TELEMETRY_DATA is not defined then the CdTelemetry___Safe() routines
|
|
// expand to nothing. This minimizes the cdfs.sys binary footprint. This also
|
|
// means that the places where these Safe() routines are called do not
|
|
// have to have to be surrounded by #ifdef CDFS_TELEMETRY_DATA .. #endif
|
|
//
|
|
|
|
|
|
#define CdTelemetryMountSafe( ... ) NOTHING
|
|
|
|
#endif // CDFS_TELEMETRY_DATA
|
|
|
|
#endif // _CDPROCS_
|
|
|
|
|