mirror of
https://github.com/reactos/reactos.git
synced 2024-08-14 15:16:27 +00:00
2326 lines
62 KiB
C
Executable file
2326 lines
62 KiB
C
Executable file
/*++
|
||
|
||
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
|
||
|
||
//**** 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
|
||
// );
|
||
//
|
||
|
||
#ifndef __REACTOS__
|
||
#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); \
|
||
} \
|
||
}
|
||
|
||
#else
|
||
#define CdMapUserBuffer(IC, UB) { \
|
||
*(UB) = (PVOID) ( ((IC)->Irp->MdlAddress == NULL) ? \
|
||
(IC)->Irp->UserBuffer : \
|
||
(MmGetSystemAddressForMdlSafe( (IC)->Irp->MdlAddress, NormalPagePriority))); \
|
||
if (NULL == *(UB)) { \
|
||
CdRaiseStatus( (IC), STATUS_INSUFFICIENT_RESOURCES); \
|
||
} \
|
||
}
|
||
|
||
#endif
|
||
|
||
|
||
#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
|
||
#ifndef __REACTOS__
|
||
#define CdNonPagedPool NonPagedPoolNx
|
||
#define CdNonPagedPoolCacheAligned NonPagedPoolNxCacheAligned
|
||
#else
|
||
#define CdNonPagedPool NonPagedPool
|
||
#define CdNonPagedPoolCacheAligned NonPagedPoolCacheAligned
|
||
#endif
|
||
|
||
|
||
//
|
||
// 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
|
||
|
||
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_
|
||
|
||
|