Sample Code
Windows Driver Samples/ CDFS File System Driver/ C++/ cdprocs.h/
/*++ 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_ #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 #include <ntifs.h> #include <ntddcdrm.h> #include <ntdddisk.h> #include <ntddscsi.h> #ifndef INLINE #define INLINE __inline #endif #include "nodetype.h" #include "Cd.h" #include "CdStruc.h" #include "CdData.h" #pragma warning( pop ) //**** 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 ); VOID INLINE 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))); \ 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 CdNoopAcquire ( _In_ PVOID Fcb, _In_ BOOLEAN Wait ); VOID CdNoopRelease ( _In_ PVOID Fcb ); _Requires_lock_held_(_Global_critical_region_) _When_(return!=0, _Acquires_shared_lock_(*Fcb->Resource)) BOOLEAN CdAcquireForCache ( _Inout_ PFCB Fcb, _In_ BOOLEAN Wait ); _Requires_lock_held_(_Global_critical_region_) _Releases_lock_(*Fcb->Resource) VOID CdReleaseFromCache ( _Inout_ PFCB Fcb ); _Requires_lock_held_(_Global_critical_region_) NTSTATUS CdFilterCallbackAcquireForCreateSection ( _In_ PFS_FILTER_CALLBACK_DATA CallbackData, _Unreferenced_parameter_ PVOID *CompletionContext ); _Function_class_(FAST_IO_RELEASE_FILE) _Requires_lock_held_(_Global_critical_region_) VOID 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( &(IO) ) 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 // 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 CdPrePostIrp ( _Inout_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp ); _Requires_lock_held_(_Global_critical_region_) VOID 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 // //#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 \ ) 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 // // NTSTATUS // 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; } // #define try_return(S) { S; goto try_exit; } #define try_leave(S) { S; leave; } // // Encapsulate safe pool freeing // INLINE VOID CdFreePool( _Inout_ _At_(*Pool, __drv_freesMem(Mem) _Post_null_) PVOID *Pool ) { if (*Pool != NULL) { ExFreePool(*Pool); *Pool = NULL; } } #endif // _CDPROCS_
Our Services
-
What our customers say about us?
Read our customer testimonials to find out why our clients keep returning for their projects.
View Testimonials