3 Copyright (c) 1989-2000 Microsoft Corporation
11 This module defines all of the globally used procedures in the Cdfs
21 #pragma warning( disable: 4127 ) // conditional expression is constant
23 #pragma warning( push )
24 #pragma warning( disable: 4201 ) // nonstandard extension used : nameless struct/union
25 #pragma warning( disable: 4214 ) // nonstandard extension used : bit field types
34 #include <pseh/pseh2.h>
38 #define INLINE __inline
46 #ifdef CDFS_TELEMETRY_DATA
49 #include <TraceLoggingProvider.h>
50 #include <telemetry\MicrosoftTelemetry.h>
52 #endif // CDFS_TELEMETRY_DATA
55 #pragma warning( pop )
58 //**** x86 compiler bug ****
62 #define Int64ShraMod32(a, b) ((LONGLONG)(a) >> (b))
66 #define Min(a, b) ((a) < (b) ? (a) : (b))
70 #define Max(a, b) ((a) > (b) ? (a) : (b))
74 // Here are the different pool tags.
77 #define TAG_CCB 'ccdC' // Ccb
78 #define TAG_CDROM_TOC 'ctdC' // TOC
79 #define TAG_DIRENT_NAME 'nddC' // CdName in dirent
80 #define TAG_ENUM_EXPRESSION 'eedC' // Search expression for enumeration
81 #define TAG_FCB_DATA 'dfdC' // Data Fcb
82 #define TAG_FCB_INDEX 'ifdC' // Index Fcb
83 #define TAG_FCB_NONPAGED 'nfdC' // Nonpaged Fcb
84 #define TAG_FCB_TABLE 'tfdC' // Fcb Table entry
85 #define TAG_FILE_NAME 'nFdC' // Filename buffer
86 #define TAG_GEN_SHORT_NAME 'sgdC' // Generated short name
87 #define TAG_IO_BUFFER 'fbdC' // Temporary IO buffer
88 #define TAG_IO_CONTEXT 'oidC' // Io context for async reads
89 #define TAG_IRP_CONTEXT 'cidC' // Irp Context
90 #define TAG_IRP_CONTEXT_LITE 'lidC' // Irp Context lite
91 #define TAG_MCB_ARRAY 'amdC' // Mcb array
92 #define TAG_PATH_ENTRY_NAME 'nPdC' // CdName in path entry
93 #define TAG_PREFIX_ENTRY 'epdC' // Prefix Entry
94 #define TAG_PREFIX_NAME 'npdC' // Prefix Entry name
95 #define TAG_SPANNING_PATH_TABLE 'psdC' // Buffer for spanning path table
96 #define TAG_UPCASE_NAME 'nudC' // Buffer for upcased name
97 #define TAG_VOL_DESC 'dvdC' // Buffer for volume descriptor
98 #define TAG_VPB 'pvdC' // Vpb allocated in filesystem
101 // Tag all of our allocations if tagging is turned on
106 #undef FsRtlAllocatePool
107 #undef FsRtlAllocatePoolWithQuota
108 #define FsRtlAllocatePool(a,b) FsRtlAllocatePoolWithTag(a,b,'sfdC')
109 #define FsRtlAllocatePoolWithQuota(a,b) FsRtlAllocatePoolWithQuotaTag(a,b,'sfdC')
111 #endif // POOL_TAGGING
115 // File access check routine, implemented in AcChkSup.c
120 // CdIllegalFcbAccess (
121 // _In_ PIRP_CONTEXT IrpContext,
122 // _In_ TYPE_OF_OPEN TypeOfOpen,
123 // _In_ ACCESS_MASK DesiredAccess
127 #define CdIllegalFcbAccess(IC,T,DA) ( \
128 BooleanFlagOn( (DA), \
129 ((T) != UserVolumeOpen ? \
130 (FILE_WRITE_ATTRIBUTES | \
134 FILE_ADD_SUBDIRECTORY | \
135 FILE_APPEND_DATA) : 0) | \
136 FILE_DELETE_CHILD | \
142 // Allocation support routines, implemented in AllocSup.c
144 // These routines are for querying allocation on individual streams.
147 _Requires_lock_held_(_Global_critical_region_
)
150 _In_ PIRP_CONTEXT IrpContext
,
152 _In_ LONGLONG FileOffset
,
153 _Out_ PLONGLONG DiskOffset
,
154 _Out_ PULONG ByteCount
158 CdAddAllocationFromDirent (
159 _In_ PIRP_CONTEXT IrpContext
,
161 _In_ ULONG McbEntryOffset
,
162 _In_ LONGLONG StartingFileOffset
,
167 CdAddInitialAllocation (
168 _In_ PIRP_CONTEXT IrpContext
,
170 _In_ ULONG StartingBlock
,
171 _In_ LONGLONG DataLength
175 CdTruncateAllocation (
176 _In_ PIRP_CONTEXT IrpContext
,
178 _In_ LONGLONG StartingFileOffset
181 _At_(Fcb
->NodeByteSize
, _In_range_(>=, FIELD_OFFSET( FCB
, FcbType
)))
184 _In_ PIRP_CONTEXT IrpContext
,
185 _Inout_updates_bytes_(Fcb
->NodeByteSize
) PFCB Fcb
188 _At_(Fcb
->NodeByteSize
, _In_range_(>=, FIELD_OFFSET( FCB
, FcbType
)))
189 _When_(Fcb
->NodeTypeCode
== CDFS_NTC_FCB_PATH_TABLE
, _At_(Fcb
->NodeByteSize
, _In_range_(==, SIZEOF_FCB_INDEX
)))
190 _When_(Fcb
->NodeTypeCode
== CDFS_NTC_FCB_INDEX
, _At_(Fcb
->NodeByteSize
, _In_range_(==, SIZEOF_FCB_INDEX
)))
191 _When_(Fcb
->NodeTypeCode
== CDFS_NTC_FCB_DATA
, _At_(Fcb
->NodeByteSize
, _In_range_(==, SIZEOF_FCB_DATA
)))
194 _In_ PIRP_CONTEXT IrpContext
,
195 _Inout_updates_bytes_(Fcb
->NodeByteSize
) PFCB Fcb
200 // Buffer control routines for data caching, implemented in CacheSup.c
204 CdCreateInternalStream (
205 _In_ PIRP_CONTEXT IrpContext
,
208 _In_ PUNICODE_STRING Name
212 CdDeleteInternalStream (
213 _In_ PIRP_CONTEXT IrpContext
,
219 _In_ PIRP_CONTEXT IrpContext
,
223 _Requires_lock_held_(_Global_critical_region_
)
226 _In_ PIRP_CONTEXT IrpContext
,
228 _In_ BOOLEAN DismountUnderway
231 static /* ReactOS Change: GCC "multiple definition" */
232 INLINE
/* GCC only accepts __inline as the first modifier */
234 CdVerifyOrCreateDirStreamFile (
235 _In_ PIRP_CONTEXT IrpContext
,
240 // Unsafe test to see if call / lock neccessary.
243 if (NULL
== Fcb
->FileObject
) {
245 CdCreateInternalStream( IrpContext
,
248 &Fcb
->FileNamePrefix
.ExactCaseName
.FileName
);
256 // _In_ PIRP_CONTEXT IrpContext,
261 #define CdUnpinData(IC,B) \
262 if (*(B) != NULL) { CcUnpinData( *(B) ); *(B) = NULL; }
266 // Device I/O routines, implemented in DevIoSup.c
268 // These routines perform the actual device read and writes. They only affect
269 // the on disk structure and do not alter any other data structures.
272 _Requires_lock_held_(_Global_critical_region_
)
275 _In_ PIRP_CONTEXT IrpContext
278 _Requires_lock_held_(_Global_critical_region_
)
281 _In_ PIRP_CONTEXT IrpContext
,
283 _In_ LONGLONG StartingOffset
,
287 _Requires_lock_held_(_Global_critical_region_
)
290 _In_ PIRP_CONTEXT IrpContext
,
292 _In_ LONGLONG StartingOffset
,
296 _Requires_lock_held_(_Global_critical_region_
)
299 _In_ PIRP_CONTEXT IrpContext
,
301 _In_ LONGLONG StartingOffset
,
307 _In_ PIRP_CONTEXT IrpContext
,
308 _In_ LONGLONG StartingOffset
,
309 _In_ ULONG ByteCount
,
310 _In_ BOOLEAN ReturnError
,
311 _Out_writes_bytes_(ByteCount
) PVOID Buffer
,
312 _In_ PDEVICE_OBJECT TargetDeviceObject
317 _In_ PIRP_CONTEXT IrpContext
,
318 _In_ ULONG BufferLength
,
319 _In_ BOOLEAN RaiseOnError
,
320 _In_ LOCK_OPERATION Operation
326 _In_ PIRP_CONTEXT IrpContext
,
327 _In_ ULONG IoControlCode
,
328 _In_ PDEVICE_OBJECT Device
,
329 _Out_writes_bytes_opt_(OutputBufferLength
) PVOID OutputBuffer
,
330 _In_ ULONG OutputBufferLength
,
331 _In_ BOOLEAN InternalDeviceIoControl
,
332 _In_ BOOLEAN OverrideVerify
,
333 _Out_opt_ PIO_STATUS_BLOCK Iosb
337 CdPerformDevIoCtrlEx (
338 _In_ PIRP_CONTEXT IrpContext
,
339 _In_ ULONG IoControlCode
,
340 _In_ PDEVICE_OBJECT Device
,
341 _In_reads_bytes_opt_(InputBufferLength
) PVOID InputBuffer
,
342 _In_ ULONG InputBufferLength
,
343 _Out_writes_bytes_opt_(OutputBufferLength
) PVOID OutputBuffer
,
344 _In_ ULONG OutputBufferLength
,
345 _In_ BOOLEAN InternalDeviceIoControl
,
346 _In_ BOOLEAN OverrideVerify
,
347 _Out_opt_ PIO_STATUS_BLOCK Iosb
351 CdHijackIrpAndFlushDevice (
352 _In_ PIRP_CONTEXT IrpContext
,
354 _In_ PDEVICE_OBJECT TargetDeviceObject
361 // _In_ PIRP_CONTEXT IrpContext
362 // _Out_ PVOID UserBuffer
365 // Returns pointer to sys address. Will raise on failure.
369 // CdLockUserBuffer (
370 // _Inout_ PIRP_CONTEXT IrpContext,
371 // _In_ ULONG BufferLength
376 #define CdMapUserBuffer(IC, UB) { \
377 *(UB) = (PVOID) ( ((IC)->Irp->MdlAddress == NULL) ? \
378 (IC)->Irp->UserBuffer : \
379 (MmGetSystemAddressForMdlSafe( (IC)->Irp->MdlAddress, NormalPagePriority | MdlMappingNoExecute))); \
380 if (NULL == *(UB)) { \
381 CdRaiseStatus( (IC), STATUS_INSUFFICIENT_RESOURCES); \
386 #define CdMapUserBuffer(IC, UB) { \
387 *(UB) = (PVOID) ( ((IC)->Irp->MdlAddress == NULL) ? \
388 (IC)->Irp->UserBuffer : \
389 (MmGetSystemAddressForMdlSafe( (IC)->Irp->MdlAddress, NormalPagePriority))); \
390 if (NULL == *(UB)) { \
391 CdRaiseStatus( (IC), STATUS_INSUFFICIENT_RESOURCES); \
398 #define CdLockUserBuffer(IC,BL,OP) { \
399 if ((IC)->Irp->MdlAddress == NULL) { \
400 (VOID) CdCreateUserMdl( (IC), (BL), TRUE, (OP) ); \
406 // Dirent support routines, implemented in DirSup.c
411 _In_ PIRP_CONTEXT IrpContext
,
413 _In_ ULONG DirentOffset
,
414 _Out_ PDIRENT_ENUM_CONTEXT DirContext
419 _In_ PIRP_CONTEXT IrpContext
,
421 _In_ PDIRENT_ENUM_CONTEXT CurrentDirContext
,
422 _Inout_ PDIRENT_ENUM_CONTEXT NextDirContext
425 _At_(Dirent
->CdTime
, _Post_notnull_
)\f
427 CdUpdateDirentFromRawDirent (
428 _In_ PIRP_CONTEXT IrpContext
,
430 _In_ PDIRENT_ENUM_CONTEXT DirContext
,
431 _Inout_ PDIRENT Dirent
436 _In_ PIRP_CONTEXT IrpContext
,
437 _Inout_ PDIRENT Dirent
,
438 _In_ ULONG IgnoreCase
441 _Success_(return != FALSE
) BOOLEAN
443 _In_ PIRP_CONTEXT IrpContext
,
446 _In_ BOOLEAN IgnoreCase
,
447 _Inout_ PFILE_ENUM_CONTEXT FileContext
,
448 _Out_ PCD_NAME
*MatchingName
453 _In_ PIRP_CONTEXT IrpContext
,
456 _In_ BOOLEAN IgnoreCase
,
457 _Inout_ PFILE_ENUM_CONTEXT FileContext
460 _At_(FileContext
->ShortName
.FileName
.MaximumLength
, _In_range_(>=, BYTE_COUNT_8_DOT_3
))
462 CdFindFileByShortName (
463 _In_ PIRP_CONTEXT IrpContext
,
466 _In_ BOOLEAN IgnoreCase
,
467 _In_ ULONG ShortNameDirentOffset
,
468 _Inout_ PFILE_ENUM_CONTEXT FileContext
472 CdLookupNextInitialFileDirent (
473 _In_ PIRP_CONTEXT IrpContext
,
475 _Inout_ PFILE_ENUM_CONTEXT FileContext
479 CdLookupLastFileDirent (
480 _In_ PIRP_CONTEXT IrpContext
,
482 _In_ PFILE_ENUM_CONTEXT FileContext
486 CdCleanupFileContext (
487 _In_ PIRP_CONTEXT IrpContext
,
488 _In_ PFILE_ENUM_CONTEXT FileContext
493 // CdInitializeFileContext (
494 // _In_ PIRP_CONTEXT IrpContext,
495 // _Out_ PFILE_ENUM_CONTEXT FileContext
500 // CdInitializeDirent (
501 // _In_ PIRP_CONTEXT IrpContext,
502 // _Out_ PDIRENT Dirent
506 // CdInitializeDirContext (
507 // _In_ PIRP_CONTEXT IrpContext,
508 // _Out_ PDIRENT_ENUM_CONTEXT DirContext
513 // _In_ PIRP_CONTEXT IrpContext,
514 // _Inout_ PDIRENT Dirent
518 // CdCleanupDirContext (
519 // _In_ PIRP_CONTEXT IrpContext,
520 // _Inout_ PDIRENT_ENUM_CONTEXT DirContext
524 // CdLookupInitialFileDirent (
525 // _In_ PIRP_CONTEXT IrpContext,
527 // _Out_ PFILE_ENUM_CONTEXT FileContext,
528 // _In_ ULONG DirentOffset
532 #define CdInitializeFileContext(IC,FC) { \
533 RtlZeroMemory( FC, sizeof( FILE_ENUM_CONTEXT )); \
534 (FC)->PriorDirent = &(FC)->Dirents[0]; \
535 (FC)->InitialDirent = &(FC)->Dirents[1]; \
536 (FC)->CurrentDirent = &(FC)->Dirents[2]; \
537 (FC)->ShortName.FileName.MaximumLength = BYTE_COUNT_8_DOT_3; \
538 (FC)->ShortName.FileName.Buffer = (FC)->ShortNameBuffer; \
541 #define CdInitializeDirent(IC,D) \
542 RtlZeroMemory( D, sizeof( DIRENT ))
544 #define CdInitializeDirContext(IC,DC) \
545 RtlZeroMemory( DC, sizeof( DIRENT_ENUM_CONTEXT ))
547 #define CdCleanupDirent(IC,D) { \
548 if (FlagOn( (D)->Flags, DIRENT_FLAG_ALLOC_BUFFER )) { \
549 CdFreePool( &(D)->CdFileName.FileName.Buffer ); \
553 #define CdCleanupDirContext(IC,DC) \
554 CdUnpinData( (IC), &(DC)->Bcb )
556 #define CdLookupInitialFileDirent(IC,F,FC,DO) \
557 CdLookupDirent( IC, \
560 &(FC)->InitialDirent->DirContext ); \
561 CdUpdateDirentFromRawDirent( IC, \
563 &(FC)->InitialDirent->DirContext, \
564 &(FC)->InitialDirent->Dirent )
568 // The following routines are used to manipulate the fscontext fields
569 // of the file object, implemented in FilObSup.c
573 // Type of opens. FilObSup.c depends on this order.
576 typedef enum _TYPE_OF_OPEN
{
578 UnopenedFileObject
= 0,
586 typedef TYPE_OF_OPEN
*PTYPE_OF_OPEN
;
588 _When_(TypeOfOpen
== UnopenedFileObject
, _At_(Fcb
, _In_opt_
))
589 _When_(TypeOfOpen
!= UnopenedFileObject
, _At_(Fcb
, _In_
))
592 _In_ PIRP_CONTEXT IrpContext
,
593 _Inout_ PFILE_OBJECT FileObject
,
594 _In_ TYPE_OF_OPEN TypeOfOpen
,
599 _When_(return == UnopenedFileObject
, _At_(*Fcb
, _Post_null_
))
600 _When_(return != UnopenedFileObject
, _At_(Fcb
, _Outptr_
))
601 _When_(return == UnopenedFileObject
, _At_(*Ccb
, _Post_null_
))
602 _When_(return != UnopenedFileObject
, _At_(Ccb
, _Outptr_
))
605 _In_ PIRP_CONTEXT IrpContext
,
606 _In_ PFILE_OBJECT FileObject
,
612 CdFastDecodeFileObject (
613 _In_ PFILE_OBJECT FileObject
,
619 // Name support routines, implemented in NameSup.c
622 _Post_satisfies_(_Old_(CdName
->FileName
.Length
) >=
623 CdName
->FileName
.Length
+ CdName
->VersionString
.Length
)
625 CdConvertNameToCdName (
626 _In_ PIRP_CONTEXT IrpContext
,
627 _Inout_ PCD_NAME CdName
631 CdConvertBigToLittleEndian (
632 _In_ PIRP_CONTEXT IrpContext
,
633 _In_reads_bytes_(ByteCount
) PCHAR BigEndian
,
634 _In_ ULONG ByteCount
,
635 _Out_writes_bytes_(ByteCount
) PCHAR LittleEndian
640 _In_ PIRP_CONTEXT IrpContext
,
642 _Inout_ PCD_NAME UpcaseName
647 _In_ PIRP_CONTEXT IrpContext
,
648 _Inout_ PUNICODE_STRING RemainingName
,
649 _Out_ PUNICODE_STRING FinalName
654 _In_ PIRP_CONTEXT IrpContext
,
655 _In_ PUNICODE_STRING FileName
660 _In_ PIRP_CONTEXT IrpContext
,
661 _In_ UNICODE_STRING FileName
665 CdGenerate8dot3Name (
666 _In_ PIRP_CONTEXT IrpContext
,
667 _In_ PUNICODE_STRING FileName
,
668 _In_ ULONG DirentOffset
,
669 _Out_writes_bytes_to_(BYTE_COUNT_8_DOT_3
, *ShortByteCount
) PWCHAR ShortFileName
,
670 _Out_ PUSHORT ShortByteCount
674 CdIsNameInExpression (
675 _In_ PIRP_CONTEXT IrpContext
,
676 _In_ PCD_NAME CurrentName
,
677 _In_ PCD_NAME SearchExpression
,
678 _In_ ULONG WildcardFlags
,
679 _In_ BOOLEAN CheckVersion
683 CdShortNameDirentOffset (
684 _In_ PIRP_CONTEXT IrpContext
,
685 _In_ PUNICODE_STRING Name
688 FSRTL_COMPARISON_RESULT
690 _In_ PIRP_CONTEXT IrpContext
,
691 _In_ PUNICODE_STRING NameA
,
692 _In_ PUNICODE_STRING NameB
697 // Filesystem control operations. Implemented in Fsctrl.c
700 _Requires_lock_held_(_Global_critical_region_
)
701 _Requires_lock_held_(Vcb
->VcbResource
)
703 CdLockVolumeInternal (
704 _In_ PIRP_CONTEXT IrpContext
,
706 _In_opt_ PFILE_OBJECT FileObject
710 CdUnlockVolumeInternal (
711 _In_ PIRP_CONTEXT IrpContext
,
713 _In_opt_ PFILE_OBJECT FileObject
718 // Path table enumeration routines. Implemented in PathSup.c
723 _In_ PIRP_CONTEXT IrpContext
,
724 _In_ ULONG PathEntryOffset
,
726 _In_ BOOLEAN VerifyBounds
,
727 _Inout_ PCOMPOUND_PATH_ENTRY CompoundPathEntry
731 CdLookupNextPathEntry (
732 _In_ PIRP_CONTEXT IrpContext
,
733 _Inout_ PPATH_ENUM_CONTEXT PathContext
,
734 _Inout_ PPATH_ENTRY PathEntry
737 _Success_(return != FALSE
)\f
740 _In_ PIRP_CONTEXT IrpContext
,
742 _In_ PCD_NAME DirName
,
743 _In_ BOOLEAN IgnoreCase
,
744 _Inout_ PCOMPOUND_PATH_ENTRY CompoundPathEntry
748 CdUpdatePathEntryName (
749 _In_ PIRP_CONTEXT IrpContext
,
750 _Inout_ PPATH_ENTRY PathEntry
,
751 _In_ BOOLEAN IgnoreCase
756 // CdInitializeCompoundPathEntry (
757 // _In_ PIRP_CONTEXT IrpContext,
758 // _Out_ PCOMPOUND_PATH_ENTRY CompoundPathEntry
762 // CdCleanupCompoundPathEntry (
763 // _In_ PIRP_CONTEXT IrpContext,
764 // _Out_ PCOMPOUND_PATH_ENTRY CompoundPathEntry
768 #define CdInitializeCompoundPathEntry(IC,CP) \
769 RtlZeroMemory( CP, sizeof( COMPOUND_PATH_ENTRY ))
771 #define CdCleanupCompoundPathEntry(IC,CP) { \
772 CdUnpinData( (IC), &(CP)->PathContext.Bcb ); \
773 if ((CP)->PathContext.AllocatedData) { \
774 CdFreePool( &(CP)->PathContext.Data ); \
776 if (FlagOn( (CP)->PathEntry.Flags, PATH_ENTRY_FLAG_ALLOC_BUFFER )) { \
777 CdFreePool( &(CP)->PathEntry.CdDirName.FileName.Buffer ); \
783 // Largest matching prefix searching routines, implemented in PrefxSup.c
788 _In_ PIRP_CONTEXT IrpContext
,
791 _In_ BOOLEAN IgnoreCase
,
792 _In_ BOOLEAN ShortNameMatch
,
793 _Inout_ PFCB ParentFcb
798 _In_ PIRP_CONTEXT IrpContext
,
802 _Requires_lock_held_(_Global_critical_region_
)
805 _In_ PIRP_CONTEXT IrpContext
,
806 _Inout_ PFCB
*CurrentFcb
,
807 _Inout_ PUNICODE_STRING RemainingName
,
808 _In_ BOOLEAN IgnoreCase
813 // Synchronization routines. Implemented in Resrcsup.c
815 // The following routines/macros are used to synchronize the in-memory structures.
817 // Routine/Macro Synchronizes Subsequent
819 // CdAcquireCdData Volume Mounts/Dismounts,Vcb Queue CdReleaseCdData
820 // CdAcquireVcbExclusive Vcb for open/close CdReleaseVcb
821 // CdAcquireVcbShared Vcb for open/close CdReleaseVcb
822 // CdAcquireAllFiles Locks out operations to all files CdReleaseAllFiles
823 // CdAcquireFileExclusive Locks out file operations CdReleaseFile
824 // CdAcquireFileShared Files for file operations CdReleaseFile
825 // CdAcquireFcbExclusive Fcb for open/close CdReleaseFcb
826 // CdAcquireFcbShared Fcb for open/close CdReleaseFcb
827 // CdLockCdData Fields in CdData CdUnlockCdData
828 // CdLockVcb Vcb fields, FcbReference, FcbTable CdUnlockVcb
829 // CdLockFcb Fcb fields, prefix table, Mcb CdUnlockFcb
832 typedef enum _TYPE_OF_ACQUIRE
{
836 AcquireSharedStarveExclusive
838 } TYPE_OF_ACQUIRE
, *PTYPE_OF_ACQUIRE
;
840 _Requires_lock_held_(_Global_critical_region_
)
841 _When_(Type
== AcquireExclusive
&& return != FALSE
, _Acquires_exclusive_lock_(*Resource
))
842 _When_(Type
== AcquireShared
&& return != FALSE
, _Acquires_shared_lock_(*Resource
))
843 _When_(Type
== AcquireSharedStarveExclusive
&& return != FALSE
, _Acquires_shared_lock_(*Resource
))
844 _When_(IgnoreWait
== FALSE
, _Post_satisfies_(return == TRUE
))
847 _In_ PIRP_CONTEXT IrpContext
,
848 _Inout_ PERESOURCE Resource
,
849 _In_ BOOLEAN IgnoreWait
,
850 _In_ TYPE_OF_ACQUIRE Type
856 // _In_ PIRP_CONTEXT IrpContext
861 // _In_ PIRP_CONTEXT IrpContext
865 // CdAcquireVcbExclusive (
866 // _In_ PIRP_CONTEXT IrpContext,
868 // _In_ BOOLEAN IgnoreWait
872 // CdAcquireVcbShared (
873 // _In_ PIRP_CONTEXT IrpContext,
875 // _In_ BOOLEAN IgnoreWait
880 // _In_ PIRP_CONTEXT IrpContext,
885 // CdAcquireAllFiles (
886 // _In_ PIRP_CONTEXT,
891 // CdReleaseAllFiles (
892 // _In_ PIRP_CONTEXT,
897 // CdAcquireFileExclusive (
898 // _In_ PIRP_CONTEXT IrpContext,
903 // CdAcquireFileShared (
904 // _In_ PIRP_CONTEXT IrpContext,
910 // _In_ PIRP_CONTEXT IrpContext,
915 // CdAcquireFcbExclusive (
916 // _In_ PIRP_CONTEXT IrpContext,
918 // _In_ BOOLEAN IgnoreWait
922 // CdAcquireFcbShared (
923 // _In_ PIRP_CONTEXT IrpContext,
925 // _In_ BOOLEAN IgnoreWait
930 // _In_ PIRP_CONTEXT IrpContext,
944 // _In_ PIRP_CONTEXT IrpContext
949 // _In_ PIRP_CONTEXT IrpContext
954 // _In_ PIRP_CONTEXT IrpContext,
960 // _In_ PIRP_CONTEXT IrpContext,
966 #define CdAcquireCacheForRead( IC) \
967 ExAcquireResourceSharedLite( &(IC)->Vcb->SectorCacheResource, TRUE)
969 #define CdAcquireCacheForUpdate( IC) \
970 ExAcquireResourceExclusiveLite( &(IC)->Vcb->SectorCacheResource, TRUE)
972 #define CdReleaseCache( IC) \
973 ExReleaseResourceLite( &(IC)->Vcb->SectorCacheResource);
975 #define CdConvertCacheToShared( IC) \
976 ExConvertExclusiveToSharedLite( &(IC)->Vcb->SectorCacheResource);
978 #define CdAcquireCdData(IC) \
979 ExAcquireResourceExclusiveLite( &CdData.DataResource, TRUE )
981 #define CdReleaseCdData(IC) \
982 ExReleaseResourceLite( &CdData.DataResource )
984 #define CdAcquireVcbExclusive(IC,V,I) \
985 CdAcquireResource( (IC), &(V)->VcbResource, (I), AcquireExclusive )
987 #define CdAcquireVcbShared(IC,V,I) \
988 CdAcquireResource( (IC), &(V)->VcbResource, (I), AcquireShared )
990 #define CdReleaseVcb(IC,V) \
991 ExReleaseResourceLite( &(V)->VcbResource )
993 #define CdAcquireAllFiles(IC,V) \
994 CdAcquireResource( (IC), &(V)->FileResource, FALSE, AcquireExclusive )
996 #define CdReleaseAllFiles(IC,V) \
997 ExReleaseResourceLite( &(V)->FileResource )
999 #define CdAcquireFileExclusive(IC,F) \
1000 CdAcquireResource( (IC), (F)->Resource, FALSE, AcquireExclusive )
1002 #define CdAcquireFileShared(IC,F) \
1003 CdAcquireResource( (IC), (F)->Resource, FALSE, AcquireShared )
1005 #define CdAcquireFileSharedStarveExclusive(IC,F) \
1006 CdAcquireResource( (IC), (F)->Resource, FALSE, AcquireSharedStarveExclusive )
1008 #define CdReleaseFile(IC,F) \
1009 ExReleaseResourceLite( (F)->Resource )
1011 #define CdAcquireFcbExclusive(IC,F,I) \
1012 CdAcquireResource( (IC), &(F)->FcbNonpaged->FcbResource, (I), AcquireExclusive )
1014 #define CdAcquireFcbShared(IC,F,I) \
1015 CdAcquireResource( (IC), &(F)->FcbNonpaged->FcbResource, (I), AcquireShared )
1017 #define CdReleaseFcb(IC,F) \
1018 ExReleaseResourceLite( &(F)->FcbNonpaged->FcbResource )
1020 #define CdLockCdData() \
1021 ExAcquireFastMutex( &CdData.CdDataMutex ); \
1022 CdData.CdDataLockThread = PsGetCurrentThread()
1024 #define CdUnlockCdData() \
1025 CdData.CdDataLockThread = NULL; \
1026 ExReleaseFastMutex( &CdData.CdDataMutex )
1028 #define CdLockVcb(IC,V) \
1029 ExAcquireFastMutex( &(V)->VcbMutex ); \
1030 NT_ASSERT( NULL == (V)->VcbLockThread); \
1031 (V)->VcbLockThread = PsGetCurrentThread()
1033 #define CdUnlockVcb(IC,V) \
1034 NT_ASSERT( NULL != (V)->VcbLockThread); \
1035 (V)->VcbLockThread = NULL; \
1036 ExReleaseFastMutex( &(V)->VcbMutex )
1038 #if defined(_PREFAST_)
1041 _IRQL_saves_global_(OldIrql
, FastMutex
)
1042 BOOLEAN
DummySaveIrql(_Inout_ PFAST_MUTEX FastMutex
);
1045 _IRQL_restores_global_(OldIrql
, FastMutex
)
1046 BOOLEAN
DummyRestoreIrql(_Inout_ PFAST_MUTEX FastMutex
);
1049 #define CdLockFcb(IC,F) { \
1050 PVOID _CurrentThread = PsGetCurrentThread(); \
1051 if (_CurrentThread != (F)->FcbLockThread) { \
1052 ExAcquireFastMutex( &(F)->FcbNonpaged->FcbMutex ); \
1053 NT_ASSERT( (F)->FcbLockCount == 0 ); \
1054 _Analysis_assume_( (F)->FcbLockCount == 0 ); \
1055 (F)->FcbLockThread = _CurrentThread; \
1059 _Analysis_assume_lock_held_( (F)->FcbNonpaged->FcbMutex ); \
1060 _Analysis_assume_(FALSE != DummySaveIrql(&(F)->FcbNonpaged->FcbMutex)); \
1062 (F)->FcbLockCount += 1; \
1065 #define CdUnlockFcb(IC,F) { \
1066 (F)->FcbLockCount -= 1; \
1067 if ((F)->FcbLockCount == 0) { \
1068 (F)->FcbLockThread = NULL; \
1069 ExReleaseFastMutex( &(F)->FcbNonpaged->FcbMutex ); \
1073 _Analysis_assume_lock_not_held_( (F)->FcbNonpaged->FcbMutex ); \
1074 _Analysis_assume_(FALSE != DummyRestoreIrql(&(F)->FcbNonpaged->FcbMutex)); \
1079 // The following macro is used to retrieve the oplock structure within
1080 // the Fcb. This structure was moved to the advanced Fcb header
1084 #if (NTDDI_VERSION >= NTDDI_WIN8)
1086 #define CdGetFcbOplock(F) &(F)->Header.Oplock
1090 #define CdGetFcbOplock(F) &(F)->Oplock
1095 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
1102 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
1107 _Requires_lock_held_(_Global_critical_region_
)
1108 _When_(return!=0, _Acquires_shared_lock_(*Fcb
->Resource
))
1110 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
1116 _Requires_lock_held_(_Global_critical_region_
)
1117 _Releases_lock_(*Fcb
->Resource
)
1119 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
1120 CdReleaseFromCache (
1125 _Requires_lock_held_(_Global_critical_region_
)
1127 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
1128 CdFilterCallbackAcquireForCreateSection (
1129 _In_ PFS_FILTER_CALLBACK_DATA CallbackData
,
1130 _Unreferenced_parameter_ PVOID
*CompletionContext
1134 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
1135 CdAcquireForCreateSection (
1136 IN PFILE_OBJECT FileObject
1140 _Function_class_(FAST_IO_RELEASE_FILE
)
1141 _Requires_lock_held_(_Global_critical_region_
)
1143 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
1144 CdReleaseForCreateSection (
1145 _In_ PFILE_OBJECT FileObject
1150 // In-memory structure support routines. Implemented in StrucSup.c
1155 _In_ PIRP_CONTEXT IrpContext
,
1157 _In_ __drv_aliasesMem PDEVICE_OBJECT TargetDeviceObject
,
1158 _In_ __drv_aliasesMem PVPB Vpb
,
1159 _In_ __drv_aliasesMem PCDROM_TOC_LARGE CdromToc
,
1160 _In_ ULONG TocLength
,
1161 _In_ ULONG TocTrackCount
,
1162 _In_ ULONG TocDiskFlags
,
1163 _In_ ULONG BlockFactor
,
1164 _In_ ULONG MediaChangeCount
1168 CdUpdateVcbFromVolDescriptor (
1169 _In_ PIRP_CONTEXT IrpContext
,
1171 _In_reads_bytes_opt_(SECTOR_SIZE
) PCHAR RawIsoVd
1176 _In_ PIRP_CONTEXT IrpContext
,
1182 _In_ PIRP_CONTEXT IrpContext
,
1183 _In_ FILE_ID FileId
,
1184 _In_ NODE_TYPE_CODE NodeTypeCode
,
1185 _Out_opt_ PBOOLEAN FcbExisted
1189 CdInitializeFcbFromPathEntry (
1190 _In_ PIRP_CONTEXT IrpContext
,
1192 _In_opt_ PFCB ParentFcb
,
1193 _In_ PPATH_ENTRY PathEntry
1197 CdInitializeFcbFromFileContext (
1198 _In_ PIRP_CONTEXT IrpContext
,
1200 _In_ PFCB ParentFcb
,
1201 _In_ PFILE_ENUM_CONTEXT FileContext
1206 _In_ PIRP_CONTEXT IrpContext
,
1213 _In_ PIRP_CONTEXT IrpContext
,
1214 _In_
__drv_freesMem( Pool
) PCCB Ccb
1217 _When_(RaiseOnError
|| return, _At_(Fcb
->FileLock
, _Post_notnull_
))
1218 _When_(RaiseOnError
, _At_(IrpContext
, _Pre_notnull_
))
1221 _In_opt_ PIRP_CONTEXT IrpContext
,
1223 _In_ BOOLEAN RaiseOnError
1228 _In_ PIRP_CONTEXT IrpContext
,
1229 _Inout_ PFILE_LOCK FileLock
1232 _Ret_valid_ PIRP_CONTEXT
1233 CdCreateIrpContext (
1239 CdCleanupIrpContext (
1240 _In_ PIRP_CONTEXT IrpContext
,
1245 CdInitializeStackIrpContext (
1246 _Out_ PIRP_CONTEXT IrpContext
,
1247 _In_ PIRP_CONTEXT_LITE IrpContextLite
1251 // PIRP_CONTEXT_LITE
1252 // CdCreateIrpContextLite (
1253 // _In_ PIRP_CONTEXT IrpContext
1257 // CdFreeIrpContextLite (
1258 // _Inout_ PIRP_CONTEXT_LITE IrpContextLite
1262 #define CdCreateIrpContextLite(IC) \
1263 ExAllocatePoolWithTag( CdNonPagedPool, sizeof( IRP_CONTEXT_LITE ), TAG_IRP_CONTEXT_LITE )
1265 #define CdFreeIrpContextLite(ICL) \
1266 CdFreePool( &(ICL) )
1268 _Requires_lock_held_(_Global_critical_region_
)
1270 CdTeardownStructures (
1271 _In_ PIRP_CONTEXT IrpContext
,
1272 _Inout_ PFCB StartingFcb
,
1273 _Out_ PBOOLEAN RemovedStartingFcb
1278 // CdIncrementCleanupCounts (
1279 // _In_ PIRP_CONTEXT IrpContext,
1284 // CdDecrementCleanupCounts (
1285 // _In_ PIRP_CONTEXT IrpContext,
1290 // CdIncrementReferenceCounts (
1291 // _In_ PIRP_CONTEXT IrpContext,
1292 // _Inout_ PFCB Fcb,
1293 // _In_ ULONG ReferenceCount
1294 // _In_ ULONG UserReferenceCount
1298 // CdDecrementReferenceCounts (
1299 // _In_ PIRP_CONTEXT IrpContext,
1300 // _Inout_ PFCB Fcb,
1301 // _In_ ULONG ReferenceCount
1302 // _In_ ULONG UserReferenceCount
1306 // CdIncrementFcbReference (
1307 // _In_ PIRP_CONTEXT IrpContext,
1312 // CdDecrementFcbReference (
1313 // _In_ PIRP_CONTEXT IrpContext,
1318 #define CdIncrementCleanupCounts(IC,F) { \
1319 ASSERT_LOCKED_VCB( (F)->Vcb ); \
1320 (F)->FcbCleanup += 1; \
1321 (F)->Vcb->VcbCleanup += 1; \
1324 #define CdDecrementCleanupCounts(IC,F) { \
1325 ASSERT_LOCKED_VCB( (F)->Vcb ); \
1326 (F)->FcbCleanup -= 1; \
1327 (F)->Vcb->VcbCleanup -= 1; \
1330 #define CdIncrementReferenceCounts(IC,F,C,UC) { \
1331 ASSERT_LOCKED_VCB( (F)->Vcb ); \
1332 (F)->FcbReference += (C); \
1333 (F)->FcbUserReference += (UC); \
1334 (F)->Vcb->VcbReference += (C); \
1335 (F)->Vcb->VcbUserReference += (UC); \
1338 #define CdDecrementReferenceCounts(IC,F,C,UC) { \
1339 ASSERT_LOCKED_VCB( (F)->Vcb ); \
1340 (F)->FcbReference -= (C); \
1341 (F)->FcbUserReference -= (UC); \
1342 (F)->Vcb->VcbReference -= (C); \
1343 (F)->Vcb->VcbUserReference -= (UC); \
1348 // CdAllocateIoContext (
1352 // CdFreeIoContext (
1353 // PCD_IO_CONTEXT IoContext
1357 #define CdAllocateIoContext() \
1358 FsRtlAllocatePoolWithTag( CdNonPagedPool, \
1359 sizeof( CD_IO_CONTEXT ), \
1362 #define CdFreeIoContext(IO) CdFreePool( (PVOID) &(IO) ) /* ReactOS Change: GCC "passing argument 1 from incompatible pointer type" */
1366 _In_ PIRP_CONTEXT IrpContext
,
1373 _In_ PIRP_CONTEXT IrpContext
,
1375 _In_ PVOID
*RestartKey
1380 _In_ PIRP_CONTEXT IrpContext
,
1381 _In_ PDEVICE_OBJECT TargetDeviceObject
,
1382 _In_ PCDROM_TOC_LARGE CdromToc
,
1383 _Inout_ PULONG Length
,
1384 _Out_ PULONG TrackCount
,
1385 _Inout_ PULONG DiskFlags
1389 // For debugging purposes we sometimes want to allocate our structures from nonpaged
1390 // pool so that in the kernel debugger we can walk all the structures.
1393 #define CdPagedPool PagedPool
1395 #define CdNonPagedPool NonPagedPoolNx
1396 #define CdNonPagedPoolCacheAligned NonPagedPoolNxCacheAligned
1398 #define CdNonPagedPool NonPagedPool
1399 #define CdNonPagedPoolCacheAligned NonPagedPoolCacheAligned
1404 // Verification support routines. Contained in verfysup.c
1407 static /* ReactOS Change: GCC "multiple definition" */
1410 CdOperationIsDasdOpen (
1411 _In_ PIRP_CONTEXT IrpContext
1414 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( IrpContext
->Irp
);
1416 return ((IrpContext
->MajorFunction
== IRP_MJ_CREATE
) &&
1417 (IrpSp
->FileObject
->FileName
.Length
== 0) &&
1418 (IrpSp
->FileObject
->RelatedFileObject
== NULL
));
1421 _Requires_lock_held_(_Global_critical_region_
)
1424 _Inout_ PIRP_CONTEXT IrpContext
,
1426 _In_ PDEVICE_OBJECT DeviceToVerify
1429 _Requires_lock_held_(_Global_critical_region_
)
1431 CdCheckForDismount (
1432 _In_ PIRP_CONTEXT IrpContext
,
1438 CdMarkDevForVerifyIfVcbMounted (
1444 _In_ PIRP_CONTEXT IrpContext
,
1449 CdVerifyFcbOperation (
1450 _In_opt_ PIRP_CONTEXT IrpContext
,
1454 _Requires_lock_held_(_Global_critical_region_
)
1457 _In_ PIRP_CONTEXT IrpContext
,
1463 // Macros to abstract device verify flag changes.
1466 #define CdUpdateMediaChangeCount( V, C) (V)->MediaChangeCount = (C)
1467 #define CdUpdateVcbCondition( V, C) (V)->VcbCondition = (C)
1469 #define CdMarkRealDevForVerify( DO) SetFlag( (DO)->Flags, DO_VERIFY_VOLUME)
1471 #define CdMarkRealDevVerifyOk( DO) ClearFlag( (DO)->Flags, DO_VERIFY_VOLUME)
1474 #define CdRealDevNeedsVerify( DO) BooleanFlagOn( (DO)->Flags, DO_VERIFY_VOLUME)
1479 // _In_ PIRP_CONTEXT IrpContext,
1480 // _In_ NTSTATUS Status
1484 #define CdIsRawDevice(IC,S) ( \
1485 ((S) == STATUS_DEVICE_NOT_READY) || \
1486 ((S) == STATUS_NO_MEDIA_IN_DEVICE) \
1491 // Work queue routines for posting and retrieving an Irp, implemented in
1495 _Requires_lock_held_(_Global_critical_region_
)
1498 _Inout_ PIRP_CONTEXT IrpContext
,
1502 _Requires_lock_held_(_Global_critical_region_
)
1504 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
1506 _Inout_ PIRP_CONTEXT IrpContext
,
1510 _Requires_lock_held_(_Global_critical_region_
)
1512 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
1514 _Inout_ PIRP_CONTEXT IrpContext
,
1520 // Miscellaneous support routines
1524 // This macro returns TRUE if a flag in a set of flags is on and FALSE
1528 /* GCC complains about multi-line comments.
1529 //#ifndef BooleanFlagOn
1530 //#define BooleanFlagOn(F,SF) ( \
1531 // (BOOLEAN)(((F) & (SF)) != 0) \
1536 //#define SetFlag(Flags,SingleFlag) { \
1537 // (Flags) |= (SingleFlag); \
1542 //#define ClearFlag(Flags,SingleFlag) { \
1543 // (Flags) &= ~(SingleFlag); \
1551 // _In_ PVOID Pointer,
1552 // _In_ ULONG Increment
1558 // _In_ PVOID BasePtr,
1559 // _In_ PVOID OffsetPtr
1563 #define Add2Ptr(PTR,INC,CAST) ((CAST)((PUCHAR)(PTR) + (INC)))
1565 #define PtrOffset(BASE,OFFSET) ((ULONG)((ULONG_PTR)(OFFSET) - (ULONG_PTR)(BASE)))
1568 // This macro takes a pointer (or ulong) and returns its rounded up word
1572 #define WordAlign(Ptr) ( \
1573 ((((ULONG)(Ptr)) + 1) & 0xfffffffe) \
1577 // This macro takes a pointer (or ulong) and returns its rounded up longword
1581 #define LongAlign(Ptr) ( \
1582 ((((ULONG)(Ptr)) + 3) & 0xfffffffc) \
1586 // This macro takes a pointer (or ulong) and returns its rounded up quadword
1590 #define QuadAlign(Ptr) ( \
1591 ((((ULONG)(Ptr)) + 7) & 0xfffffff8) \
1595 // The following macros round up and down to sector boundaries.
1598 #define SectorAlign(L) ( \
1599 ((((ULONG)(L)) + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1)) \
1602 #define LlSectorAlign(L) ( \
1603 ((((LONGLONG)(L)) + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1)) \
1606 #define SectorTruncate(L) ( \
1607 ((ULONG)(L)) & ~(SECTOR_SIZE - 1) \
1610 #define LlSectorTruncate(L) ( \
1611 ((LONGLONG)(L)) & ~(SECTOR_SIZE - 1) \
1614 #define BytesFromSectors(L) ( \
1615 ((ULONG) (L)) << SECTOR_SHIFT \
1618 #define SectorsFromBytes(L) ( \
1619 ((ULONG) (L)) >> SECTOR_SHIFT \
1622 static /* ReactOS Change: GCC "multiple definition" */
1629 return (ULONG
)(Bytes
>> SECTOR_SHIFT
);
1632 #define LlBytesFromSectors(L) ( \
1633 Int64ShllMod32( (LONGLONG)(L), SECTOR_SHIFT ) \
1636 #define LlSectorsFromBytes(L) ( \
1637 Int64ShraMod32( (LONGLONG)(L), SECTOR_SHIFT ) \
1640 #define SectorOffset(L) ( \
1641 ((ULONG)(ULONG_PTR) (L)) & SECTOR_MASK \
1644 #define SectorBlockOffset(V,LB) ( \
1645 ((ULONG) (LB)) & ((V)->BlocksPerSector - 1) \
1648 #define BytesFromBlocks(V,B) ( \
1649 (ULONG) (B) << (V)->BlockToByteShift \
1652 #define LlBytesFromBlocks(V,B) ( \
1653 Int64ShllMod32( (LONGLONG) (B), (V)->BlockToByteShift ) \
1656 #define BlockAlign(V,L) ( \
1657 ((ULONG)(L) + (V)->BlockMask) & (V)->BlockInverseMask \
1661 // Carefully make sure the mask is sign extended to 64bits
1664 #define LlBlockAlign(V,L) ( \
1665 ((LONGLONG)(L) + (V)->BlockMask) & (LONGLONG)((LONG)(V)->BlockInverseMask) \
1668 #define BlockOffset(V,L) ( \
1669 ((ULONG) (L)) & (V)->BlockMask \
1672 #define RawSectorAlign( B) ((((B)+(RAW_SECTOR_SIZE - 1)) / RAW_SECTOR_SIZE) * RAW_SECTOR_SIZE)
1675 // The following types and macros are used to help unpack the packed and
1676 // misaligned fields found in the Bios parameter block
1679 typedef union _UCHAR1
{
1681 UCHAR ForceAlignment
;
1684 typedef union _UCHAR2
{
1686 USHORT ForceAlignment
;
1689 typedef union _UCHAR4
{
1691 ULONG ForceAlignment
;
1694 typedef union _USHORT2
{
1696 ULONG ForceAlignment
;
1697 } USHORT2
, *PUSHORT2
;
1700 // This macro copies an unaligned src byte to an aligned dst byte
1703 #define CopyUchar1(Dst,Src) { \
1704 *((UCHAR1 *)(Dst)) = *((UNALIGNED UCHAR1 *)(Src)); \
1708 // This macro copies an unaligned src word to an aligned dst word
1711 #define CopyUchar2(Dst,Src) { \
1712 *((UCHAR2 *)(Dst)) = *((UNALIGNED UCHAR2 *)(Src)); \
1716 // This macro copies an unaligned src longword to an aligned dsr longword
1719 #define CopyUchar4(Dst,Src) { \
1720 *((UCHAR4 *)(Dst)) = *((UNALIGNED UCHAR4 *)(Src)); \
1724 // This macro copies an unaligned src longword to an aligned dsr longword
1725 // accessing the source on a word boundary.
1728 #define CopyUshort2(Dst,Src) { \
1729 *((USHORT2 *)(Dst)) = *((UNALIGNED USHORT2 *)(Src));\
1733 // This macro copies an unaligned src longword to a dst longword,
1734 // performing an little/big endian swap.
1737 #define SwapCopyUchar4(Dst,Src) { \
1738 *((UNALIGNED UCHAR1 *)(Dst)) = *((UNALIGNED UCHAR1 *)(Src) + 3); \
1739 *((UNALIGNED UCHAR1 *)(Dst) + 1) = *((UNALIGNED UCHAR1 *)(Src) + 2); \
1740 *((UNALIGNED UCHAR1 *)(Dst) + 2) = *((UNALIGNED UCHAR1 *)(Src) + 1); \
1741 *((UNALIGNED UCHAR1 *)(Dst) + 3) = *((UNALIGNED UCHAR1 *)(Src)); \
1747 _Out_writes_(3) PUCHAR Msf
1751 // Following routines handle entry in and out of the filesystem. They are
1752 // contained in CdData.c
1755 _IRQL_requires_max_(APC_LEVEL
)
1756 __drv_dispatchType(DRIVER_DISPATCH
)
1757 __drv_dispatchType(IRP_MJ_CREATE
)
1758 __drv_dispatchType(IRP_MJ_CLOSE
)
1759 __drv_dispatchType(IRP_MJ_READ
)
1760 __drv_dispatchType(IRP_MJ_WRITE
)
1761 __drv_dispatchType(IRP_MJ_QUERY_INFORMATION
)
1762 __drv_dispatchType(IRP_MJ_SET_INFORMATION
)
1763 __drv_dispatchType(IRP_MJ_QUERY_VOLUME_INFORMATION
)
1764 __drv_dispatchType(IRP_MJ_DIRECTORY_CONTROL
)
1765 __drv_dispatchType(IRP_MJ_FILE_SYSTEM_CONTROL
)
1766 __drv_dispatchType(IRP_MJ_DEVICE_CONTROL
)
1767 __drv_dispatchType(IRP_MJ_LOCK_CONTROL
)
1768 __drv_dispatchType(IRP_MJ_CLEANUP
)
1769 __drv_dispatchType(IRP_MJ_PNP
)
1770 __drv_dispatchType(IRP_MJ_SHUTDOWN
)
1773 _In_ PDEVICE_OBJECT DeviceObject
,
1777 // DRIVER_DISPATCH CdFsdDispatch;
1781 _Inout_ PIRP_CONTEXT IrpContext
,
1782 _In_ PEXCEPTION_POINTERS ExceptionPointer
1785 _Requires_lock_held_(_Global_critical_region_
)
1787 CdProcessException (
1788 _In_opt_ PIRP_CONTEXT IrpContext
,
1790 _In_ NTSTATUS ExceptionCode
1795 _Inout_opt_ PIRP_CONTEXT IrpContext
,
1796 _Inout_opt_ PIRP Irp
,
1797 _In_ NTSTATUS Status
1803 // _In_ PRIP_CONTEXT IrpContext,
1804 // _In_ NT_STATUS Status
1808 // CdNormalizeAndRaiseStatus (
1809 // _In_ PRIP_CONTEXT IrpContext,
1810 // _In_ NT_STATUS Status
1815 #define AssertVerifyDevice(C, S) \
1816 NT_ASSERT( (C) == NULL || \
1817 FlagOn( (C)->Flags, IRP_CONTEXT_FLAG_IN_FSP ) || \
1818 !((S) == STATUS_VERIFY_REQUIRED && \
1819 IoGetDeviceToVerify( PsGetCurrentThread() ) == NULL ));
1821 #define AssertVerifyDeviceIrp(I) \
1822 NT_ASSERT( (I) == NULL || \
1823 !(((I)->IoStatus.Status) == STATUS_VERIFY_REQUIRED && \
1824 ((I)->Tail.Overlay.Thread == NULL || \
1825 IoGetDeviceToVerify( (I)->Tail.Overlay.Thread ) == NULL )));
1827 #define AssertVerifyDevice(C, S)
1828 #define AssertVerifyDeviceIrp(I)
1837 _In_ PIRP_CONTEXT IrpContext
,
1838 _In_ NTSTATUS Status
,
1839 _In_ BOOLEAN NormalizeStatus
,
1840 _In_opt_ ULONG FileId
,
1850 _In_ PIRP_CONTEXT IrpContext
,
1851 _In_ NTSTATUS Status
,
1852 _In_ BOOLEAN NormalizeStatus
,
1857 if (NormalizeStatus
) {
1859 IrpContext
->ExceptionStatus
= FsRtlNormalizeNtstatus( Status
, STATUS_UNEXPECTED_IO_ERROR
);
1863 IrpContext
->ExceptionStatus
= Status
;
1866 IrpContext
->RaisedAtLineFile
= (Fileid
<< 16) | Line
;
1868 ExRaiseStatus( IrpContext
->ExceptionStatus
);
1873 #define CdRaiseStatus( IC, S) CdRaiseStatusEx( (IC), (S), FALSE, BugCheckFileId, __LINE__);
1874 #define CdNormalizeAndRaiseStatus( IC, S) CdRaiseStatusEx( (IC), (S), TRUE, BugCheckFileId, __LINE__);
1877 // Following are the fast entry points.
1880 // _Success_(return != FALSE)
1882 // CdFastQueryBasicInfo (
1883 // _In_ PFILE_OBJECT FileObject,
1884 // _In_ BOOLEAN Wait,
1885 // _Out_ PFILE_BASIC_INFORMATION Buffer,
1886 // _Out_ PIO_STATUS_BLOCK IoStatus,
1887 // _In_ PDEVICE_OBJECT DeviceObject
1890 FAST_IO_QUERY_BASIC_INFO CdFastQueryBasicInfo
;
1892 // _Success_(return != FALSE)
1894 // CdFastQueryStdInfo (
1895 // _In_ PFILE_OBJECT FileObject,
1896 // _In_ BOOLEAN Wait,
1897 // _Out_ PFILE_STANDARD_INFORMATION Buffer,
1898 // _Out_ PIO_STATUS_BLOCK IoStatus,
1899 // _In_ PDEVICE_OBJECT DeviceObject
1902 FAST_IO_QUERY_STANDARD_INFO CdFastQueryStdInfo
;
1906 // _In_ PFILE_OBJECT FileObject,
1907 // _In_ PLARGE_INTEGER FileOffset,
1908 // _In_ PLARGE_INTEGER Length,
1909 // _In_ PEPROCESS ProcessId,
1911 // _In_ BOOLEAN FailImmediately,
1912 // _In_ BOOLEAN ExclusiveLock,
1913 // _Out_ PIO_STATUS_BLOCK IoStatus,
1914 // _In_ PDEVICE_OBJECT DeviceObject
1917 FAST_IO_LOCK CdFastLock
;
1920 // CdFastUnlockSingle (
1921 // _In_ PFILE_OBJECT FileObject,
1922 // _In_ PLARGE_INTEGER FileOffset,
1923 // _In_ PLARGE_INTEGER Length,
1924 // _In_ PEPROCESS ProcessId,
1926 // _Out_ PIO_STATUS_BLOCK IoStatus,
1927 // _In_ PDEVICE_OBJECT DeviceObject
1930 FAST_IO_UNLOCK_SINGLE CdFastUnlockSingle
;
1933 // CdFastUnlockAll (
1934 // _In_ PFILE_OBJECT FileObject,
1935 // _In_ PEPROCESS ProcessId,
1936 // _Out_ PIO_STATUS_BLOCK IoStatus,
1937 // _In_ PDEVICE_OBJECT DeviceObject
1940 FAST_IO_UNLOCK_ALL CdFastUnlockAll
;
1943 // CdFastUnlockAllByKey (
1944 // _In_ PFILE_OBJECT FileObject,
1945 // _In_ PVOID ProcessId,
1947 // _Out_ PIO_STATUS_BLOCK IoStatus,
1948 // _In_ PDEVICE_OBJECT DeviceObject
1951 FAST_IO_UNLOCK_ALL_BY_KEY CdFastUnlockAllByKey
;
1954 // CdFastIoCheckIfPossible (
1955 // _In_ PFILE_OBJECT FileObject,
1956 // _In_ PLARGE_INTEGER FileOffset,
1957 // _In_ ULONG Length,
1958 // _In_ BOOLEAN Wait,
1959 // _In_ ULONG LockKey,
1960 // _In_ BOOLEAN CheckForReadOperation,
1961 // _Out_ PIO_STATUS_BLOCK IoStatus,
1962 // _In_ PDEVICE_OBJECT DeviceObject
1965 FAST_IO_CHECK_IF_POSSIBLE CdFastIoCheckIfPossible
;
1967 // _Success_(return != FALSE)
1969 // CdFastQueryNetworkInfo (
1970 // _In_ PFILE_OBJECT FileObject,
1971 // _In_ BOOLEAN Wait,
1972 // _Out_ PFILE_NETWORK_OPEN_INFORMATION Buffer,
1973 // _Out_ PIO_STATUS_BLOCK IoStatus,
1974 // _In_ PDEVICE_OBJECT DeviceObject
1977 FAST_IO_QUERY_NETWORK_OPEN_INFO CdFastQueryNetworkInfo
;
1980 // Following are the routines to handle the top level thread logic.
1984 CdSetThreadContext (
1985 _Inout_ PIRP_CONTEXT IrpContext
,
1986 _In_ PTHREAD_CONTEXT ThreadContext
1992 // CdRestoreThreadContext (
1993 // _Inout_ PIRP_CONTEXT IrpContext
1997 #define CdRestoreThreadContext(IC) \
1998 (IC)->ThreadContext->Cdfs = 0; \
1999 IoSetTopLevelIrp( (IC)->ThreadContext->SavedTopLevelIrp ); \
2000 (IC)->ThreadContext = NULL
2004 _In_reads_bytes_(ByteCount
) PCHAR Buffer
,
2005 _In_ ULONG ByteCount
2009 // The following macro is used to determine if an FSD thread can block
2010 // for I/O or wait for a resource. It returns TRUE if the thread can
2011 // block and FALSE otherwise. This attribute can then be used to call
2012 // the FSD & FSP common work routine with the proper wait value.
2015 #define CanFsdWait(I) IoIsOperationSynchronous(I)
2018 // The following macro is used to set the fast i/o possible bits in the
2021 // FastIoIsNotPossible - If the Fcb is bad or there are oplocks on the file.
2023 // FastIoIsQuestionable - If there are file locks.
2025 // FastIoIsPossible - In all other cases.
2029 #define CdIsFastIoPossible(F) ((BOOLEAN) \
2030 ((((F)->Vcb->VcbCondition != VcbMounted ) || \
2031 !FsRtlOplockIsFastIoPossible( CdGetFcbOplock(F) )) ? \
2033 FastIoIsNotPossible : \
2035 ((((F)->FileLock != NULL) && FsRtlAreThereCurrentFileLocks( (F)->FileLock )) ? \
2037 FastIoIsQuestionable : \
2039 FastIoIsPossible)) \
2044 // The FSP level dispatch/main routine. This is the routine that takes
2045 // IRP's off of the work queue and calls the appropriate FSP level
2050 // CdFspDispatch ( // implemented in FspDisp.c
2051 // _Inout_ PIRP_CONTEXT IrpContext
2054 WORKER_THREAD_ROUTINE CdFspDispatch
;
2057 CdFspClose ( // implemented in Close.c
2062 // The following routines are the entry points for the different operations
2063 // based on the IrpSp major functions.
2066 _Requires_lock_held_(_Global_critical_region_
)
2068 CdCommonCreate ( // Implemented in Create.c
2069 _Inout_ PIRP_CONTEXT IrpContext
,
2073 _Requires_lock_held_(_Global_critical_region_
)
2075 CdCommonClose ( // Implemented in Close.c
2076 _Inout_ PIRP_CONTEXT IrpContext
,
2080 _Requires_lock_held_(_Global_critical_region_
)
2082 CdCommonRead ( // Implemented in Read.c
2083 _Inout_ PIRP_CONTEXT IrpContext
,
2087 _Requires_lock_held_(_Global_critical_region_
)
2089 CdCommonWrite ( // Implemented in Write.c
2090 _Inout_ PIRP_CONTEXT IrpContext
,
2094 _Requires_lock_held_(_Global_critical_region_
)
2096 CdCommonQueryInfo ( // Implemented in FileInfo.c
2097 _Inout_ PIRP_CONTEXT IrpContext
,
2101 _Requires_lock_held_(_Global_critical_region_
)
2103 CdCommonSetInfo ( // Implemented in FileInfo.c
2104 _Inout_ PIRP_CONTEXT IrpContext
,
2108 _Requires_lock_held_(_Global_critical_region_
)
2110 CdCommonQueryVolInfo ( // Implemented in VolInfo.c
2111 _Inout_ PIRP_CONTEXT IrpContext
,
2115 _Requires_lock_held_(_Global_critical_region_
)
2117 CdCommonDirControl ( // Implemented in DirCtrl.c
2118 _Inout_ PIRP_CONTEXT IrpContext
,
2122 _Requires_lock_held_(_Global_critical_region_
)
2124 CdCommonFsControl ( // Implemented in FsCtrl.c
2125 _Inout_ PIRP_CONTEXT IrpContext
,
2130 CdCommonDevControl ( // Implemented in DevCtrl.c
2131 _Inout_ PIRP_CONTEXT IrpContext
,
2136 CdCommonLockControl ( // Implemented in LockCtrl.c
2137 _Inout_ PIRP_CONTEXT IrpContext
,
2141 _Requires_lock_held_(_Global_critical_region_
)
2143 CdCommonCleanup ( // Implemented in Cleanup.c
2144 _Inout_ PIRP_CONTEXT IrpContext
,
2148 _Requires_lock_held_(_Global_critical_region_
)
2150 CdCommonPnp ( // Implemented in Pnp.c
2151 _Inout_ PIRP_CONTEXT IrpContext
,
2155 _Requires_lock_held_(_Global_critical_region_
)
2157 CdCommonShutdown ( // Implemented in Shutdown.c
2158 _Inout_ PIRP_CONTEXT IrpContext
,
2165 // The following macros are used to establish the semantics needed
2166 // to do a return from within a try-finally clause. As a rule every
2167 // try clause must end with a label call try_exit. For example,
2173 // try_exit: NOTHING;
2180 // Every return statement executed inside of a try clause should use the
2181 // try_return macro. If the compiler fully supports the try-finally construct
2182 // then the macro should be
2184 // #define try_return(S) { return(S); }
2186 // If the compiler does not support the try-finally construct then the macro
2189 // #define try_return(S) { S; goto try_exit; }
2193 #define try_return(S) { S; goto try_exit; }
2194 #define try_leave(S) { S; leave; }
2196 #define try_return(S) { S; goto try_exit; }
2197 #define try_leave(S) { S; _SEH2_LEAVE; }
2201 // Encapsulate safe pool freeing
2203 /* ReactOS Change: GCC "passing argument 1 of CdFreePool from incompatible pointer type" */
2204 #define CdFreePool(x) _CdFreePool((PVOID*)(x))
2206 static /* ReactOS Change: GCC "multiple definition" */
2210 _Inout_
_At_(*Pool
, __drv_freesMem(Mem
) _Post_null_
) PVOID
*Pool
2213 if (*Pool
!= NULL
) {
2220 #ifdef CDFS_TELEMETRY_DATA
2223 // CDFS Telemetry. Current implementation uses the Telemetry TraceLogging APIs.
2225 // The Telemetry TraceLoggingWrite() routines use a lot of stack space. We must
2226 // therefor wrap all our telemetry points with our own routines, and add a guard to
2227 // make sure there's enough stack space to call these routines.
2229 // These telemetry routines should not be called on high-performance code paths.
2232 TRACELOGGING_DECLARE_PROVIDER( CdTelemetryProvider
);
2235 CdInitializeTelemetry (
2242 __in PGUID VolumeGuid
,
2243 __in NTSTATUS Status
,
2248 // Every additional argument passed to TraceLoggingWrite() consumes an additional
2249 // 16 to 32 bytes extra stack space. Having 512 bytes reserved space should be
2250 // sufficient for up to 20 arguments or so. This will be less of course if our
2251 // wrapper routines also declare their own local variables.
2254 #define CDFS_TELEMETRY_STACK_THRESHOLD_DEFAULT 512 // for "small" telemetry points
2255 #define CDFS_TELEMETRY_STACK_THRESHOLD_LARGE 2048 // for "large" telemetry points
2260 __in ULONG StackSpaceNeeded
)
2263 Routine Description:
2265 This routine returns TRUE only when:
2267 1) There is an ETW listener, AND
2268 2) There is enough free stack space to safely call the Telemetry TraceLogging APIs
2270 We'll also count how many times there wasn't enough stack space, and include this
2271 value as part of the periodic cdfs Telemetry.
2275 StackSpaceNeeded - Stack space needed in bytes
2279 ASSERT( IoGetRemainingStackSize() >= StackSpaceNeeded
);
2281 if (CdTelemetryProvider
->LevelPlus1
<= 5) {
2284 // Bail out early if there are no ETW listeners
2290 if (IoGetRemainingStackSize() < StackSpaceNeeded
) {
2293 // Count how many times it was unsafe to generate telemetry because of
2294 // not enough stack space.
2297 InterlockedIncrement( &CdTelemetryData
.MissedTelemetryPoints
);
2305 #define CdTelemetryMountSafe( VolumeGuid, Status, Vcb ) \
2306 if (CdTelemetryGuard( CDFS_TELEMETRY_STACK_THRESHOLD_LARGE )) { \
2307 CdTelemetryMount( VolumeGuid, Status, Vcb ); \
2311 #define CDFS_TELEMETRY_PERIODIC_INTERVAL CdTelemetryData.PeriodicInterval
2313 #define CDFS_TELEMETRY_PERIODIC_INTERVAL INTERVAL_ONE_DAY
2316 #else // CDFS_TELEMETRY_DATA
2319 // When CDFS_TELEMETRY_DATA is not defined then the CdTelemetry___Safe() routines
2320 // expand to nothing. This minimizes the cdfs.sys binary footprint. This also
2321 // means that the places where these Safe() routines are called do not
2322 // have to have to be surrounded by #ifdef CDFS_TELEMETRY_DATA .. #endif
2326 #define CdTelemetryMountSafe( ... ) NOTHING
2328 #endif // CDFS_TELEMETRY_DATA