xref: /reactos/drivers/filesystems/cdfs/cdprocs.h (revision 8540ab04)
1 /*++
2 
3 Copyright (c) 1989-2000 Microsoft Corporation
4 
5 Module Name:
6 
7     CdProcs.h
8 
9 Abstract:
10 
11     This module defines all of the globally used procedures in the Cdfs
12     file system.
13 
14 
15 --*/
16 
17 #ifndef _CDPROCS_
18 #define _CDPROCS_
19 
20 #ifdef _MSC_VER
21 #pragma warning( disable: 4127 ) // conditional expression is constant
22 
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
26 #endif
27 
28 #include <ntifs.h>
29 
30 #include <ntddcdrm.h>
31 #include <ntdddisk.h>
32 #include <ntddscsi.h>
33 #ifdef __REACTOS__
34 #include <pseh/pseh2.h>
35 #endif
36 
37 #ifndef INLINE
38 #define INLINE __inline
39 #endif
40 
41 #include "nodetype.h"
42 #include "cd.h"
43 #include "cdstruc.h"
44 #include "cddata.h"
45 
46 #ifdef CDFS_TELEMETRY_DATA
47 
48 #include <winmeta.h>
49 #include <TraceLoggingProvider.h>
50 #include <telemetry\MicrosoftTelemetry.h>
51 
52 #endif // CDFS_TELEMETRY_DATA
53 
54 #ifdef _MSC_VER
55 #pragma warning( pop )
56 #endif
57 
58 //**** x86 compiler bug ****
59 
60 #if defined(_M_IX86)
61 #undef Int64ShraMod32
62 #define Int64ShraMod32(a, b) ((LONGLONG)(a) >> (b))
63 #endif
64 
65 #ifndef Min
66 #define Min(a, b)   ((a) < (b) ? (a) : (b))
67 #endif
68 
69 #ifndef Max
70 #define Max(a, b)   ((a) > (b) ? (a) : (b))
71 #endif
72 
73 //
74 //  Here are the different pool tags.
75 //
76 
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
99 
100 //
101 //  Tag all of our allocations if tagging is turned on
102 //
103 
104 #ifdef POOL_TAGGING
105 
106 #undef FsRtlAllocatePool
107 #undef FsRtlAllocatePoolWithQuota
108 #define FsRtlAllocatePool(a,b) FsRtlAllocatePoolWithTag(a,b,'sfdC')
109 #define FsRtlAllocatePoolWithQuota(a,b) FsRtlAllocatePoolWithQuotaTag(a,b,'sfdC')
110 
111 #endif // POOL_TAGGING
112 
113 
114 //
115 //  File access check routine, implemented in AcChkSup.c
116 //
117 
118 //
119 //  BOOLEAN
120 //  CdIllegalFcbAccess (
121 //      _In_ PIRP_CONTEXT IrpContext,
122 //      _In_ TYPE_OF_OPEN TypeOfOpen,
123 //      _In_ ACCESS_MASK DesiredAccess
124 //      );
125 //
126 
127 #define CdIllegalFcbAccess(IC,T,DA) (                           \
128            BooleanFlagOn( (DA),                                 \
129                           ((T) != UserVolumeOpen ?              \
130                            (FILE_WRITE_ATTRIBUTES           |   \
131                             FILE_WRITE_DATA                 |   \
132                             FILE_WRITE_EA                   |   \
133                             FILE_ADD_FILE                   |   \
134                             FILE_ADD_SUBDIRECTORY           |   \
135                             FILE_APPEND_DATA) : 0)          |   \
136                           FILE_DELETE_CHILD                 |   \
137                           DELETE                            |   \
138                           WRITE_DAC ))
139 
140 
141 //
142 //  Allocation support routines, implemented in AllocSup.c
143 //
144 //  These routines are for querying allocation on individual streams.
145 //
146 
147 _Requires_lock_held_(_Global_critical_region_)
148 VOID
149 CdLookupAllocation (
150     _In_ PIRP_CONTEXT IrpContext,
151     _In_ PFCB Fcb,
152     _In_ LONGLONG FileOffset,
153     _Out_ PLONGLONG DiskOffset,
154     _Out_ PULONG ByteCount
155     );
156 
157 VOID
158 CdAddAllocationFromDirent (
159     _In_ PIRP_CONTEXT IrpContext,
160     _Inout_ PFCB Fcb,
161     _In_ ULONG McbEntryOffset,
162     _In_ LONGLONG StartingFileOffset,
163     _In_ PDIRENT Dirent
164     );
165 
166 VOID
167 CdAddInitialAllocation (
168     _In_ PIRP_CONTEXT IrpContext,
169     _Inout_ PFCB Fcb,
170     _In_ ULONG StartingBlock,
171     _In_ LONGLONG DataLength
172     );
173 
174 VOID
175 CdTruncateAllocation (
176     _In_ PIRP_CONTEXT IrpContext,
177     _Inout_ PFCB Fcb,
178     _In_ LONGLONG StartingFileOffset
179     );
180 
181 _At_(Fcb->NodeByteSize, _In_range_(>=, FIELD_OFFSET( FCB, FcbType )))
182 VOID
183 CdInitializeMcb (
184     _In_ PIRP_CONTEXT IrpContext,
185     _Inout_updates_bytes_(Fcb->NodeByteSize) PFCB Fcb
186     );
187 
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)))
192 VOID
193 CdUninitializeMcb (
194     _In_ PIRP_CONTEXT IrpContext,
195     _Inout_updates_bytes_(Fcb->NodeByteSize) PFCB Fcb
196     );
197 
198 
199 //
200 //   Buffer control routines for data caching, implemented in CacheSup.c
201 //
202 
203 VOID
204 CdCreateInternalStream (
205     _In_ PIRP_CONTEXT IrpContext,
206     _In_ PVCB Vcb,
207     _Inout_ PFCB Fcb,
208     _In_ PUNICODE_STRING Name
209     );
210 
211 VOID
212 CdDeleteInternalStream (
213     _In_ PIRP_CONTEXT IrpContext,
214     _Inout_ PFCB Fcb
215     );
216 
217 NTSTATUS
218 CdCompleteMdl (
219     _In_ PIRP_CONTEXT IrpContext,
220     _Inout_ PIRP Irp
221     );
222 
223 _Requires_lock_held_(_Global_critical_region_)
224 NTSTATUS
225 CdPurgeVolume (
226     _In_ PIRP_CONTEXT IrpContext,
227     _In_ PVCB Vcb,
228     _In_ BOOLEAN DismountUnderway
229     );
230 
231 static /* ReactOS Change: GCC "multiple definition" */
232 INLINE /* GCC only accepts __inline as the first modifier */
233 VOID
234 CdVerifyOrCreateDirStreamFile (
235     _In_ PIRP_CONTEXT IrpContext,
236     _In_ PFCB Fcb
237     )
238 {
239     //
240     //  Unsafe test to see if call / lock neccessary.
241     //
242 
243     if (NULL == Fcb->FileObject) {
244 
245         CdCreateInternalStream( IrpContext,
246                                 Fcb->Vcb,
247                                 Fcb,
248                                 &Fcb->FileNamePrefix.ExactCaseName.FileName);
249     }
250 }
251 
252 
253 //
254 //  VOID
255 //  CdUnpinData (
256 //      _In_ PIRP_CONTEXT IrpContext,
257 //      _Inout_ PBCB *Bcb
258 //      );
259 //
260 
261 #define CdUnpinData(IC,B)   \
262     if (*(B) != NULL) { CcUnpinData( *(B) ); *(B) = NULL; }
263 
264 
265 //
266 //  Device I/O routines, implemented in DevIoSup.c
267 //
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.
270 //
271 
272 _Requires_lock_held_(_Global_critical_region_)
273 VOID
274 CdFreeDirCache (
275     _In_ PIRP_CONTEXT IrpContext
276     );
277 
278 _Requires_lock_held_(_Global_critical_region_)
279 NTSTATUS
280 CdNonCachedRead (
281     _In_ PIRP_CONTEXT IrpContext,
282     _In_ PFCB Fcb,
283     _In_ LONGLONG StartingOffset,
284     _In_ ULONG ByteCount
285     );
286 
287 _Requires_lock_held_(_Global_critical_region_)
288 NTSTATUS
289 CdNonCachedXARead (
290     _In_ PIRP_CONTEXT IrpContext,
291     _In_ PFCB Fcb,
292     _In_ LONGLONG StartingOffset,
293     _In_ ULONG ByteCount
294     );
295 
296 _Requires_lock_held_(_Global_critical_region_)
297 NTSTATUS
298 CdVolumeDasdWrite (
299     _In_ PIRP_CONTEXT IrpContext,
300     _In_ PFCB Fcb,
301     _In_ LONGLONG StartingOffset,
302     _In_ ULONG ByteCount
303     );
304 
305 BOOLEAN
306 CdReadSectors (
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
313     );
314 
315 NTSTATUS
316 CdCreateUserMdl (
317     _In_ PIRP_CONTEXT IrpContext,
318     _In_ ULONG BufferLength,
319     _In_ BOOLEAN RaiseOnError,
320     _In_ LOCK_OPERATION Operation
321     );
322 
323 NTSTATUS
324 FASTCALL
325 CdPerformDevIoCtrl (
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
334     );
335 
336 NTSTATUS
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
348     );
349 
350 NTSTATUS
351 CdHijackIrpAndFlushDevice (
352     _In_ PIRP_CONTEXT IrpContext,
353     _Inout_ PIRP Irp,
354     _In_ PDEVICE_OBJECT TargetDeviceObject
355     );
356 
357 
358 //
359 //  VOID
360 //  CdMapUserBuffer (
361 //      _In_ PIRP_CONTEXT IrpContext
362 //      _Out_ PVOID UserBuffer
363 //      );
364 //
365 //  Returns pointer to sys address.  Will raise on failure.
366 //
367 //
368 //  VOID
369 //  CdLockUserBuffer (
370 //      _Inout_ PIRP_CONTEXT IrpContext,
371 //      _In_ ULONG BufferLength
372 //      );
373 //
374 
375 #ifndef __REACTOS__
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);            \
382             }                                                                   \
383         }
384 
385 #else
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);            \
392             }                                                                   \
393         }
394 
395 #endif
396 
397 
398 #define CdLockUserBuffer(IC,BL,OP) {                        \
399     if ((IC)->Irp->MdlAddress == NULL) {                    \
400         (VOID) CdCreateUserMdl( (IC), (BL), TRUE, (OP) );   \
401     }                                                       \
402 }
403 
404 
405 //
406 //  Dirent support routines, implemented in DirSup.c
407 //
408 
409 VOID
410 CdLookupDirent (
411     _In_ PIRP_CONTEXT IrpContext,
412     _In_ PFCB Fcb,
413     _In_ ULONG DirentOffset,
414     _Out_ PDIRENT_ENUM_CONTEXT DirContext
415     );
416 
417 BOOLEAN
418 CdLookupNextDirent (
419     _In_ PIRP_CONTEXT IrpContext,
420     _In_ PFCB Fcb,
421     _In_ PDIRENT_ENUM_CONTEXT CurrentDirContext,
422     _Inout_ PDIRENT_ENUM_CONTEXT NextDirContext
423     );
424 
425 _At_(Dirent->CdTime, _Post_notnull_)
426 VOID
427 CdUpdateDirentFromRawDirent (
428     _In_ PIRP_CONTEXT IrpContext,
429     _In_ PFCB Fcb,
430     _In_ PDIRENT_ENUM_CONTEXT DirContext,
431     _Inout_ PDIRENT Dirent
432     );
433 
434 VOID
435 CdUpdateDirentName (
436     _In_ PIRP_CONTEXT IrpContext,
437     _Inout_ PDIRENT Dirent,
438     _In_ ULONG IgnoreCase
439     );
440 
441 _Success_(return != FALSE) BOOLEAN
442 CdFindFile (
443     _In_ PIRP_CONTEXT IrpContext,
444     _In_ PFCB Fcb,
445     _In_ PCD_NAME Name,
446     _In_ BOOLEAN IgnoreCase,
447     _Inout_ PFILE_ENUM_CONTEXT FileContext,
448     _Out_ PCD_NAME *MatchingName
449     );
450 
451 BOOLEAN
452 CdFindDirectory (
453     _In_ PIRP_CONTEXT IrpContext,
454     _In_ PFCB Fcb,
455     _In_ PCD_NAME Name,
456     _In_ BOOLEAN IgnoreCase,
457     _Inout_ PFILE_ENUM_CONTEXT FileContext
458     );
459 
460 _At_(FileContext->ShortName.FileName.MaximumLength, _In_range_(>=, BYTE_COUNT_8_DOT_3))
461 BOOLEAN
462 CdFindFileByShortName (
463     _In_ PIRP_CONTEXT IrpContext,
464     _In_ PFCB Fcb,
465     _In_ PCD_NAME Name,
466     _In_ BOOLEAN IgnoreCase,
467     _In_ ULONG ShortNameDirentOffset,
468     _Inout_ PFILE_ENUM_CONTEXT FileContext
469     );
470 
471 BOOLEAN
472 CdLookupNextInitialFileDirent (
473     _In_ PIRP_CONTEXT IrpContext,
474     _In_ PFCB Fcb,
475     _Inout_ PFILE_ENUM_CONTEXT FileContext
476     );
477 
478 VOID
479 CdLookupLastFileDirent (
480     _In_ PIRP_CONTEXT IrpContext,
481     _In_ PFCB Fcb,
482     _In_ PFILE_ENUM_CONTEXT FileContext
483     );
484 
485 VOID
486 CdCleanupFileContext (
487     _In_ PIRP_CONTEXT IrpContext,
488     _In_ PFILE_ENUM_CONTEXT FileContext
489     );
490 
491 //
492 //  VOID
493 //  CdInitializeFileContext (
494 //      _In_ PIRP_CONTEXT IrpContext,
495 //      _Out_ PFILE_ENUM_CONTEXT FileContext
496 //      );
497 //
498 //
499 //  VOID
500 //  CdInitializeDirent (
501 //      _In_ PIRP_CONTEXT IrpContext,
502 //      _Out_ PDIRENT Dirent
503 //      );
504 //
505 //  VOID
506 //  CdInitializeDirContext (
507 //      _In_ PIRP_CONTEXT IrpContext,
508 //      _Out_ PDIRENT_ENUM_CONTEXT DirContext
509 //      );
510 //
511 //  VOID
512 //  CdCleanupDirent (
513 //      _In_ PIRP_CONTEXT IrpContext,
514 //      _Inout_ PDIRENT Dirent
515 //      );
516 //
517 //  VOID
518 //  CdCleanupDirContext (
519 //      _In_ PIRP_CONTEXT IrpContext,
520 //      _Inout_ PDIRENT_ENUM_CONTEXT DirContext
521 //      );
522 //
523 //  VOID
524 //  CdLookupInitialFileDirent (
525 //      _In_ PIRP_CONTEXT IrpContext,
526 //      _In_ PFCB Fcb,
527 //      _Out_ PFILE_ENUM_CONTEXT FileContext,
528 //      _In_ ULONG DirentOffset
529 //      );
530 //
531 
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;            \
539 }
540 
541 #define CdInitializeDirent(IC,D)                                \
542     RtlZeroMemory( D, sizeof( DIRENT ))
543 
544 #define CdInitializeDirContext(IC,DC)                           \
545     RtlZeroMemory( DC, sizeof( DIRENT_ENUM_CONTEXT ))
546 
547 #define CdCleanupDirent(IC,D)  {                                \
548     if (FlagOn( (D)->Flags, DIRENT_FLAG_ALLOC_BUFFER )) {       \
549         CdFreePool( &(D)->CdFileName.FileName.Buffer );          \
550     }                                                           \
551 }
552 
553 #define CdCleanupDirContext(IC,DC)                              \
554     CdUnpinData( (IC), &(DC)->Bcb )
555 
556 #define CdLookupInitialFileDirent(IC,F,FC,DO)                       \
557     CdLookupDirent( IC,                                             \
558                     F,                                              \
559                     DO,                                             \
560                     &(FC)->InitialDirent->DirContext );             \
561     CdUpdateDirentFromRawDirent( IC,                                \
562                                  F,                                 \
563                                  &(FC)->InitialDirent->DirContext,  \
564                                  &(FC)->InitialDirent->Dirent )
565 
566 
567 //
568 //  The following routines are used to manipulate the fscontext fields
569 //  of the file object, implemented in FilObSup.c
570 //
571 
572 //
573 //  Type of opens.  FilObSup.c depends on this order.
574 //
575 
576 typedef enum _TYPE_OF_OPEN {
577 
578     UnopenedFileObject = 0,
579     StreamFileOpen,
580     UserVolumeOpen,
581     UserDirectoryOpen,
582     UserFileOpen,
583     BeyondValidType
584 
585 } TYPE_OF_OPEN;
586 typedef TYPE_OF_OPEN *PTYPE_OF_OPEN;
587 
588 _When_(TypeOfOpen == UnopenedFileObject, _At_(Fcb, _In_opt_))
589 _When_(TypeOfOpen != UnopenedFileObject, _At_(Fcb, _In_))
590 VOID
591 CdSetFileObject (
592     _In_ PIRP_CONTEXT IrpContext,
593     _Inout_ PFILE_OBJECT FileObject,
594     _In_ TYPE_OF_OPEN TypeOfOpen,
595     PFCB Fcb,
596     _In_opt_ PCCB Ccb
597     );
598 
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_))
603 TYPE_OF_OPEN
604 CdDecodeFileObject (
605     _In_ PIRP_CONTEXT IrpContext,
606     _In_ PFILE_OBJECT FileObject,
607     PFCB *Fcb,
608     PCCB *Ccb
609     );
610 
611 TYPE_OF_OPEN
612 CdFastDecodeFileObject (
613     _In_ PFILE_OBJECT FileObject,
614     _Out_ PFCB *Fcb
615     );
616 
617 
618 //
619 //  Name support routines, implemented in NameSup.c
620 //
621 
622 _Post_satisfies_(_Old_(CdName->FileName.Length) >=
623                  CdName->FileName.Length + CdName->VersionString.Length)
624 VOID
625 CdConvertNameToCdName (
626     _In_ PIRP_CONTEXT IrpContext,
627     _Inout_ PCD_NAME CdName
628     );
629 
630 VOID
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
636     );
637 
638 VOID
639 CdUpcaseName (
640     _In_ PIRP_CONTEXT IrpContext,
641     _In_ PCD_NAME Name,
642     _Inout_ PCD_NAME UpcaseName
643     );
644 
645 VOID
646 CdDissectName (
647     _In_ PIRP_CONTEXT IrpContext,
648     _Inout_ PUNICODE_STRING RemainingName,
649     _Out_ PUNICODE_STRING FinalName
650     );
651 
652 BOOLEAN
653 CdIsLegalName (
654     _In_ PIRP_CONTEXT IrpContext,
655     _In_ PUNICODE_STRING FileName
656     );
657 
658 BOOLEAN
659 CdIs8dot3Name (
660     _In_ PIRP_CONTEXT IrpContext,
661     _In_ UNICODE_STRING FileName
662     );
663 
664 VOID
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
671     );
672 
673 BOOLEAN
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
680     );
681 
682 ULONG
683 CdShortNameDirentOffset (
684     _In_ PIRP_CONTEXT IrpContext,
685     _In_ PUNICODE_STRING Name
686     );
687 
688 FSRTL_COMPARISON_RESULT
689 CdFullCompareNames (
690     _In_ PIRP_CONTEXT IrpContext,
691     _In_ PUNICODE_STRING NameA,
692     _In_ PUNICODE_STRING NameB
693     );
694 
695 
696 //
697 //  Filesystem control operations.  Implemented in Fsctrl.c
698 //
699 
700 _Requires_lock_held_(_Global_critical_region_)
701 _Requires_lock_held_(Vcb->VcbResource)
702 NTSTATUS
703 CdLockVolumeInternal (
704     _In_ PIRP_CONTEXT IrpContext,
705     _Inout_ PVCB Vcb,
706     _In_opt_ PFILE_OBJECT FileObject
707     );
708 
709 NTSTATUS
710 CdUnlockVolumeInternal (
711     _In_ PIRP_CONTEXT IrpContext,
712     _Inout_ PVCB Vcb,
713     _In_opt_ PFILE_OBJECT FileObject
714     );
715 
716 
717 //
718 //  Path table enumeration routines.  Implemented in PathSup.c
719 //
720 
721 VOID
722 CdLookupPathEntry (
723     _In_ PIRP_CONTEXT IrpContext,
724     _In_ ULONG PathEntryOffset,
725     _In_ ULONG Ordinal,
726     _In_ BOOLEAN VerifyBounds,
727     _Inout_ PCOMPOUND_PATH_ENTRY CompoundPathEntry
728     );
729 
730 BOOLEAN
731 CdLookupNextPathEntry (
732     _In_ PIRP_CONTEXT IrpContext,
733     _Inout_ PPATH_ENUM_CONTEXT PathContext,
734     _Inout_ PPATH_ENTRY PathEntry
735     );
736 
737 _Success_(return != FALSE)
738 BOOLEAN
739 CdFindPathEntry (
740     _In_ PIRP_CONTEXT IrpContext,
741     _In_ PFCB ParentFcb,
742     _In_ PCD_NAME DirName,
743     _In_ BOOLEAN IgnoreCase,
744     _Inout_ PCOMPOUND_PATH_ENTRY CompoundPathEntry
745     );
746 
747 VOID
748 CdUpdatePathEntryName (
749     _In_ PIRP_CONTEXT IrpContext,
750     _Inout_ PPATH_ENTRY PathEntry,
751     _In_ BOOLEAN IgnoreCase
752     );
753 
754 //
755 //  VOID
756 //  CdInitializeCompoundPathEntry (
757 //      _In_ PIRP_CONTEXT IrpContext,
758 //      _Out_ PCOMPOUND_PATH_ENTRY CompoundPathEntry
759 //      );
760 //
761 //  VOID
762 //  CdCleanupCompoundPathEntry (
763 //      _In_ PIRP_CONTEXT IrpContext,
764 //      _Out_ PCOMPOUND_PATH_ENTRY CompoundPathEntry
765 //      );
766 //
767 
768 #define CdInitializeCompoundPathEntry(IC,CP)                                    \
769     RtlZeroMemory( CP, sizeof( COMPOUND_PATH_ENTRY ))
770 
771 #define CdCleanupCompoundPathEntry(IC,CP)     {                                 \
772     CdUnpinData( (IC), &(CP)->PathContext.Bcb );                                \
773     if ((CP)->PathContext.AllocatedData) {                                      \
774         CdFreePool( &(CP)->PathContext.Data );                                   \
775     }                                                                           \
776     if (FlagOn( (CP)->PathEntry.Flags, PATH_ENTRY_FLAG_ALLOC_BUFFER )) {        \
777         CdFreePool( &(CP)->PathEntry.CdDirName.FileName.Buffer );                \
778     }                                                                           \
779 }
780 
781 
782 //
783 //  Largest matching prefix searching routines, implemented in PrefxSup.c
784 //
785 
786 VOID
787 CdInsertPrefix (
788     _In_ PIRP_CONTEXT IrpContext,
789     _Inout_ PFCB Fcb,
790     _In_ PCD_NAME Name,
791     _In_ BOOLEAN IgnoreCase,
792     _In_ BOOLEAN ShortNameMatch,
793     _Inout_ PFCB ParentFcb
794     );
795 
796 VOID
797 CdRemovePrefix (
798     _In_ PIRP_CONTEXT IrpContext,
799     _Inout_ PFCB Fcb
800     );
801 
802 _Requires_lock_held_(_Global_critical_region_)
803 VOID
804 CdFindPrefix (
805     _In_ PIRP_CONTEXT IrpContext,
806     _Inout_ PFCB *CurrentFcb,
807     _Inout_ PUNICODE_STRING RemainingName,
808     _In_ BOOLEAN IgnoreCase
809     );
810 
811 
812 //
813 //  Synchronization routines.  Implemented in Resrcsup.c
814 //
815 //  The following routines/macros are used to synchronize the in-memory structures.
816 //
817 //      Routine/Macro               Synchronizes                            Subsequent
818 //
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
830 //
831 
832 typedef enum _TYPE_OF_ACQUIRE {
833 
834     AcquireExclusive,
835     AcquireShared,
836     AcquireSharedStarveExclusive
837 
838 } TYPE_OF_ACQUIRE, *PTYPE_OF_ACQUIRE;
839 
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))
845 BOOLEAN
846 CdAcquireResource (
847     _In_ PIRP_CONTEXT IrpContext,
848     _Inout_ PERESOURCE Resource,
849     _In_ BOOLEAN IgnoreWait,
850     _In_ TYPE_OF_ACQUIRE Type
851     );
852 
853 //
854 //  BOOLEAN
855 //  CdAcquireCdData (
856 //      _In_ PIRP_CONTEXT IrpContext
857 //      );
858 //
859 //  VOID
860 //  CdReleaseCdData (
861 //      _In_ PIRP_CONTEXT IrpContext
862 //    );
863 //
864 //  BOOLEAN
865 //  CdAcquireVcbExclusive (
866 //      _In_ PIRP_CONTEXT IrpContext,
867 //      _Inout_ PVCB Vcb,
868 //      _In_ BOOLEAN IgnoreWait
869 //      );
870 //
871 //  BOOLEAN
872 //  CdAcquireVcbShared (
873 //      _In_ PIRP_CONTEXT IrpContext,
874 //      _Inout_ PVCB Vcb,
875 //      _In_ BOOLEAN IgnoreWait
876 //      );
877 //
878 //  VOID
879 //  CdReleaseVcb (
880 //      _In_ PIRP_CONTEXT IrpContext,
881 //      _Inout_ PVCB Vcb
882 //      );
883 //
884 //  VOID
885 //  CdAcquireAllFiles (
886 //      _In_ PIRP_CONTEXT,
887 //      _In_ PVCB Vcb
888 //      );
889 //
890 //  VOID
891 //  CdReleaseAllFiles (
892 //      _In_ PIRP_CONTEXT,
893 //      _In_ PVCB Vcb
894 //      );
895 //
896 //  VOID
897 //  CdAcquireFileExclusive (
898 //      _In_ PIRP_CONTEXT IrpContext,
899 //      _Inout_ PFCB Fcb,
900 //      );
901 //
902 //  VOID
903 //  CdAcquireFileShared (
904 //      _In_ PIRP_CONTEXT IrpContext,
905 //      _Inout_ PFCB Fcb
906 //      );
907 //
908 //  VOID
909 //  CdReleaseFile (
910 //      _In_ PIRP_CONTEXT IrpContext,
911 //      _Inout_ PFCB Fcb
912 //    );
913 //
914 //  BOOLEAN
915 //  CdAcquireFcbExclusive (
916 //      _In_ PIRP_CONTEXT IrpContext,
917 //      _Inout_ PFCB Fcb,
918 //      _In_ BOOLEAN IgnoreWait
919 //      );
920 //
921 //  BOOLEAN
922 //  CdAcquireFcbShared (
923 //      _In_ PIRP_CONTEXT IrpContext,
924 //      _Inout_ PFCB Fcb,
925 //      _In_ BOOLEAN IgnoreWait
926 //      );
927 //
928 //  BOOLEAN
929 //  CdReleaseFcb (
930 //      _In_ PIRP_CONTEXT IrpContext,
931 //      _Inout_ PFCB Fcb
932 //      );
933 //
934 //  VOID
935 //  CdLockCdData (
936 //      );
937 //
938 //  VOID
939 //  CdUnlockCdData (
940 //      );
941 //
942 //  VOID
943 //  CdLockVcb (
944 //      _In_ PIRP_CONTEXT IrpContext
945 //      );
946 //
947 //  VOID
948 //  CdUnlockVcb (
949 //      _In_ PIRP_CONTEXT IrpContext
950 //      );
951 //
952 //  VOID
953 //  CdLockFcb (
954 //      _In_ PIRP_CONTEXT IrpContext,
955 //      _Inout_ PFCB Fcb
956 //      );
957 //
958 //  VOID
959 //  CdUnlockFcb (
960 //      _In_ PIRP_CONTEXT IrpContext,
961 //      _Inout_ PFCB Fcb
962 //      );
963 //
964 
965 
966 #define CdAcquireCacheForRead( IC)                                                      \
967     ExAcquireResourceSharedLite( &(IC)->Vcb->SectorCacheResource, TRUE)
968 
969 #define CdAcquireCacheForUpdate( IC)                                                    \
970     ExAcquireResourceExclusiveLite( &(IC)->Vcb->SectorCacheResource, TRUE)
971 
972 #define CdReleaseCache( IC)                                                             \
973     ExReleaseResourceLite( &(IC)->Vcb->SectorCacheResource);
974 
975 #define CdConvertCacheToShared( IC)                                                     \
976     ExConvertExclusiveToSharedLite( &(IC)->Vcb->SectorCacheResource);
977 
978 #define CdAcquireCdData(IC)                                                             \
979     ExAcquireResourceExclusiveLite( &CdData.DataResource, TRUE )
980 
981 #define CdReleaseCdData(IC)                                                             \
982     ExReleaseResourceLite( &CdData.DataResource )
983 
984 #define CdAcquireVcbExclusive(IC,V,I)                                                   \
985     CdAcquireResource( (IC), &(V)->VcbResource, (I), AcquireExclusive )
986 
987 #define CdAcquireVcbShared(IC,V,I)                                                      \
988     CdAcquireResource( (IC), &(V)->VcbResource, (I), AcquireShared )
989 
990 #define CdReleaseVcb(IC,V)                                                              \
991     ExReleaseResourceLite( &(V)->VcbResource )
992 
993 #define CdAcquireAllFiles(IC,V)                                                         \
994     CdAcquireResource( (IC), &(V)->FileResource, FALSE, AcquireExclusive )
995 
996 #define CdReleaseAllFiles(IC,V)                                                         \
997     ExReleaseResourceLite( &(V)->FileResource )
998 
999 #define CdAcquireFileExclusive(IC,F)                                                    \
1000     CdAcquireResource( (IC), (F)->Resource, FALSE, AcquireExclusive )
1001 
1002 #define CdAcquireFileShared(IC,F)                                                       \
1003     CdAcquireResource( (IC), (F)->Resource, FALSE, AcquireShared )
1004 
1005 #define CdAcquireFileSharedStarveExclusive(IC,F)                                        \
1006     CdAcquireResource( (IC), (F)->Resource, FALSE, AcquireSharedStarveExclusive )
1007 
1008 #define CdReleaseFile(IC,F)                                                             \
1009     ExReleaseResourceLite( (F)->Resource )
1010 
1011 #define CdAcquireFcbExclusive(IC,F,I)                                                   \
1012     CdAcquireResource( (IC), &(F)->FcbNonpaged->FcbResource, (I), AcquireExclusive )
1013 
1014 #define CdAcquireFcbShared(IC,F,I)                                                      \
1015     CdAcquireResource( (IC), &(F)->FcbNonpaged->FcbResource, (I), AcquireShared )
1016 
1017 #define CdReleaseFcb(IC,F)                                                              \
1018     ExReleaseResourceLite( &(F)->FcbNonpaged->FcbResource )
1019 
1020 #define CdLockCdData()                                                                  \
1021     ExAcquireFastMutex( &CdData.CdDataMutex );                                          \
1022     CdData.CdDataLockThread = PsGetCurrentThread()
1023 
1024 #define CdUnlockCdData()                                                                \
1025     CdData.CdDataLockThread = NULL;                                                     \
1026     ExReleaseFastMutex( &CdData.CdDataMutex )
1027 
1028 #define CdLockVcb(IC,V)                                                                 \
1029     ExAcquireFastMutex( &(V)->VcbMutex );                                               \
1030     NT_ASSERT( NULL == (V)->VcbLockThread);                                             \
1031     (V)->VcbLockThread = PsGetCurrentThread()
1032 
1033 #define CdUnlockVcb(IC,V)                                                               \
1034     NT_ASSERT( NULL != (V)->VcbLockThread);                                             \
1035     (V)->VcbLockThread = NULL;                                                          \
1036     ExReleaseFastMutex( &(V)->VcbMutex )
1037 
1038 #if defined(_PREFAST_)
1039 
1040 _Success_(return)
1041 _IRQL_saves_global_(OldIrql, FastMutex)
1042 BOOLEAN DummySaveIrql(_Inout_ PFAST_MUTEX FastMutex);
1043 
1044 _Success_(return)
1045 _IRQL_restores_global_(OldIrql, FastMutex)
1046 BOOLEAN DummyRestoreIrql(_Inout_ PFAST_MUTEX FastMutex);
1047 #endif // _PREFAST_
1048 
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;                                            \
1056     }                                                                                   \
1057     else                                                                                \
1058     {                                                                                   \
1059         _Analysis_assume_lock_held_( (F)->FcbNonpaged->FcbMutex );                      \
1060         _Analysis_assume_(FALSE != DummySaveIrql(&(F)->FcbNonpaged->FcbMutex));   \
1061     }                                                                                   \
1062     (F)->FcbLockCount += 1;                                                             \
1063 }
1064 
1065 #define CdUnlockFcb(IC,F) {                                                             \
1066     (F)->FcbLockCount -= 1;                                                             \
1067     if ((F)->FcbLockCount == 0) {                                                       \
1068         (F)->FcbLockThread = NULL;                                                      \
1069         ExReleaseFastMutex( &(F)->FcbNonpaged->FcbMutex );                              \
1070     }                                                                                   \
1071     else                                                                                \
1072     {                                                                                   \
1073         _Analysis_assume_lock_not_held_( (F)->FcbNonpaged->FcbMutex );                  \
1074         _Analysis_assume_(FALSE != DummyRestoreIrql(&(F)->FcbNonpaged->FcbMutex)); \
1075     }                                                                                   \
1076 }
1077 
1078 //
1079 //  The following macro is used to retrieve the oplock structure within
1080 //  the Fcb. This structure was moved to the advanced Fcb header
1081 //  in Win8.
1082 //
1083 
1084 #if (NTDDI_VERSION >= NTDDI_WIN8)
1085 
1086 #define CdGetFcbOplock(F)   &(F)->Header.Oplock
1087 
1088 #else
1089 
1090 #define CdGetFcbOplock(F)   &(F)->Oplock
1091 
1092 #endif
1093 
1094 BOOLEAN
1095 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1096 CdNoopAcquire (
1097     _In_ PVOID Fcb,
1098     _In_ BOOLEAN Wait
1099     );
1100 
1101 VOID
1102 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1103 CdNoopRelease (
1104     _In_ PVOID Fcb
1105     );
1106 
1107 _Requires_lock_held_(_Global_critical_region_)
1108 _When_(return!=0, _Acquires_shared_lock_(*Fcb->Resource))
1109 BOOLEAN
1110 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1111 CdAcquireForCache (
1112     _Inout_ PFCB Fcb,
1113     _In_ BOOLEAN Wait
1114     );
1115 
1116 _Requires_lock_held_(_Global_critical_region_)
1117 _Releases_lock_(*Fcb->Resource)
1118 VOID
1119 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1120 CdReleaseFromCache (
1121     _Inout_ PFCB Fcb
1122     );
1123 
1124 _Requires_lock_held_(_Global_critical_region_)
1125 NTSTATUS
1126 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1127 CdFilterCallbackAcquireForCreateSection (
1128     _In_ PFS_FILTER_CALLBACK_DATA CallbackData,
1129     _Unreferenced_parameter_ PVOID *CompletionContext
1130     );
1131 
1132 _Function_class_(FAST_IO_RELEASE_FILE)
1133 _Requires_lock_held_(_Global_critical_region_)
1134 VOID
1135 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1136 CdReleaseForCreateSection (
1137     _In_ PFILE_OBJECT FileObject
1138     );
1139 
1140 
1141 //
1142 //  In-memory structure support routines.  Implemented in StrucSup.c
1143 //
1144 
1145 VOID
1146 CdInitializeVcb (
1147     _In_ PIRP_CONTEXT IrpContext,
1148     _Inout_ PVCB Vcb,
1149     _In_ __drv_aliasesMem PDEVICE_OBJECT TargetDeviceObject,
1150     _In_ __drv_aliasesMem PVPB Vpb,
1151     _In_ __drv_aliasesMem PCDROM_TOC_LARGE CdromToc,
1152     _In_ ULONG TocLength,
1153     _In_ ULONG TocTrackCount,
1154     _In_ ULONG TocDiskFlags,
1155     _In_ ULONG BlockFactor,
1156     _In_ ULONG MediaChangeCount
1157     );
1158 
1159 VOID
1160 CdUpdateVcbFromVolDescriptor (
1161     _In_ PIRP_CONTEXT IrpContext,
1162     _Inout_ PVCB Vcb,
1163     _In_reads_bytes_opt_(SECTOR_SIZE) PCHAR RawIsoVd
1164     );
1165 
1166 VOID
1167 CdDeleteVcb (
1168     _In_ PIRP_CONTEXT IrpContext,
1169     _Inout_ PVCB Vcb
1170     );
1171 
1172 PFCB
1173 CdCreateFcb (
1174     _In_ PIRP_CONTEXT IrpContext,
1175     _In_ FILE_ID FileId,
1176     _In_ NODE_TYPE_CODE NodeTypeCode,
1177     _Out_opt_ PBOOLEAN FcbExisted
1178     );
1179 
1180 VOID
1181 CdInitializeFcbFromPathEntry (
1182     _In_ PIRP_CONTEXT IrpContext,
1183     _Inout_ PFCB Fcb,
1184     _In_opt_ PFCB ParentFcb,
1185     _In_ PPATH_ENTRY PathEntry
1186     );
1187 
1188 VOID
1189 CdInitializeFcbFromFileContext (
1190     _In_ PIRP_CONTEXT IrpContext,
1191     _Inout_ PFCB Fcb,
1192     _In_ PFCB ParentFcb,
1193     _In_ PFILE_ENUM_CONTEXT FileContext
1194     );
1195 
1196 PCCB
1197 CdCreateCcb (
1198     _In_ PIRP_CONTEXT IrpContext,
1199     _In_ PFCB Fcb,
1200     _In_ ULONG Flags
1201     );
1202 
1203 VOID
1204 CdDeleteCcb (
1205     _In_ PIRP_CONTEXT IrpContext,
1206     _In_ __drv_freesMem( Pool ) PCCB Ccb
1207     );
1208 
1209 _When_(RaiseOnError || return, _At_(Fcb->FileLock, _Post_notnull_))
1210 _When_(RaiseOnError, _At_(IrpContext, _Pre_notnull_))
1211 BOOLEAN
1212 CdCreateFileLock (
1213     _In_opt_ PIRP_CONTEXT IrpContext,
1214     _Inout_ PFCB Fcb,
1215     _In_ BOOLEAN RaiseOnError
1216     );
1217 
1218 VOID
1219 CdDeleteFileLock (
1220     _In_ PIRP_CONTEXT IrpContext,
1221     _Inout_ PFILE_LOCK FileLock
1222     );
1223 
1224 _Ret_valid_ PIRP_CONTEXT
1225 CdCreateIrpContext (
1226     _In_ PIRP Irp,
1227     _In_ BOOLEAN Wait
1228     );
1229 
1230 VOID
1231 CdCleanupIrpContext (
1232     _In_ PIRP_CONTEXT IrpContext,
1233     _In_ BOOLEAN Post
1234     );
1235 
1236 VOID
1237 CdInitializeStackIrpContext (
1238     _Out_ PIRP_CONTEXT IrpContext,
1239     _In_ PIRP_CONTEXT_LITE IrpContextLite
1240     );
1241 
1242 //
1243 //  PIRP_CONTEXT_LITE
1244 //  CdCreateIrpContextLite (
1245 //      _In_ PIRP_CONTEXT IrpContext
1246 //      );
1247 //
1248 //  VOID
1249 //  CdFreeIrpContextLite (
1250 //      _Inout_ PIRP_CONTEXT_LITE IrpContextLite
1251 //      );
1252 //
1253 
1254 #define CdCreateIrpContextLite(IC)  \
1255     ExAllocatePoolWithTag( CdNonPagedPool, sizeof( IRP_CONTEXT_LITE ), TAG_IRP_CONTEXT_LITE )
1256 
1257 #define CdFreeIrpContextLite(ICL)  \
1258     CdFreePool( &(ICL) )
1259 
1260 _Requires_lock_held_(_Global_critical_region_)
1261 VOID
1262 CdTeardownStructures (
1263     _In_ PIRP_CONTEXT IrpContext,
1264     _Inout_ PFCB StartingFcb,
1265     _Out_ PBOOLEAN RemovedStartingFcb
1266     );
1267 
1268 //
1269 //  VOID
1270 //  CdIncrementCleanupCounts (
1271 //      _In_ PIRP_CONTEXT IrpContext,
1272 //      _Inout_ PFCB Fcb
1273 //      );
1274 //
1275 //  VOID
1276 //  CdDecrementCleanupCounts (
1277 //      _In_ PIRP_CONTEXT IrpContext,
1278 //      _Inout_ PFCB Fcb
1279 //      );
1280 //
1281 //  VOID
1282 //  CdIncrementReferenceCounts (
1283 //      _In_ PIRP_CONTEXT IrpContext,
1284 //      _Inout_ PFCB Fcb,
1285 //      _In_ ULONG ReferenceCount
1286 //      _In_ ULONG UserReferenceCount
1287 //      );
1288 //
1289 //  VOID
1290 //  CdDecrementReferenceCounts (
1291 //      _In_ PIRP_CONTEXT IrpContext,
1292 //      _Inout_ PFCB Fcb,
1293 //      _In_ ULONG ReferenceCount
1294 //      _In_ ULONG UserReferenceCount
1295 //      );
1296 //
1297 //  VOID
1298 //  CdIncrementFcbReference (
1299 //      _In_ PIRP_CONTEXT IrpContext,
1300 //      _Inout_ PFCB Fcb
1301 //      );
1302 //
1303 //  VOID
1304 //  CdDecrementFcbReference (
1305 //      _In_ PIRP_CONTEXT IrpContext,
1306 //      _Inout_ PFCB Fcb
1307 //      );
1308 //
1309 
1310 #define CdIncrementCleanupCounts(IC,F) {        \
1311     ASSERT_LOCKED_VCB( (F)->Vcb );              \
1312     (F)->FcbCleanup += 1;                       \
1313     (F)->Vcb->VcbCleanup += 1;                  \
1314 }
1315 
1316 #define CdDecrementCleanupCounts(IC,F) {        \
1317     ASSERT_LOCKED_VCB( (F)->Vcb );              \
1318     (F)->FcbCleanup -= 1;                       \
1319     (F)->Vcb->VcbCleanup -= 1;                  \
1320 }
1321 
1322 #define CdIncrementReferenceCounts(IC,F,C,UC) { \
1323     ASSERT_LOCKED_VCB( (F)->Vcb );              \
1324     (F)->FcbReference += (C);                   \
1325     (F)->FcbUserReference += (UC);              \
1326     (F)->Vcb->VcbReference += (C);              \
1327     (F)->Vcb->VcbUserReference += (UC);         \
1328 }
1329 
1330 #define CdDecrementReferenceCounts(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);         \
1336 }
1337 
1338 //
1339 //  PCD_IO_CONTEXT
1340 //  CdAllocateIoContext (
1341 //      );
1342 //
1343 //  VOID
1344 //  CdFreeIoContext (
1345 //      PCD_IO_CONTEXT IoContext
1346 //      );
1347 //
1348 
1349 #define CdAllocateIoContext()                           \
1350     FsRtlAllocatePoolWithTag( CdNonPagedPool,           \
1351                               sizeof( CD_IO_CONTEXT ),  \
1352                               TAG_IO_CONTEXT )
1353 
1354 #define CdFreeIoContext(IO)     CdFreePool( (PVOID) &(IO) ) /* ReactOS Change: GCC "passing argument 1 from incompatible pointer type" */
1355 
1356 PFCB
1357 CdLookupFcbTable (
1358     _In_ PIRP_CONTEXT IrpContext,
1359     _In_ PVCB Vcb,
1360     _In_ FILE_ID FileId
1361     );
1362 
1363 PFCB
1364 CdGetNextFcb (
1365     _In_ PIRP_CONTEXT IrpContext,
1366     _In_ PVCB Vcb,
1367     _In_ PVOID *RestartKey
1368     );
1369 
1370 NTSTATUS
1371 CdProcessToc (
1372     _In_ PIRP_CONTEXT IrpContext,
1373     _In_ PDEVICE_OBJECT TargetDeviceObject,
1374     _In_ PCDROM_TOC_LARGE CdromToc,
1375     _Inout_ PULONG Length,
1376     _Out_ PULONG TrackCount,
1377     _Inout_ PULONG DiskFlags
1378     );
1379 
1380 //
1381 //  For debugging purposes we sometimes want to allocate our structures from nonpaged
1382 //  pool so that in the kernel debugger we can walk all the structures.
1383 //
1384 
1385 #define CdPagedPool                 PagedPool
1386 #ifndef __REACTOS__
1387 #define CdNonPagedPool              NonPagedPoolNx
1388 #define CdNonPagedPoolCacheAligned  NonPagedPoolNxCacheAligned
1389 #else
1390 #define CdNonPagedPool              NonPagedPool
1391 #define CdNonPagedPoolCacheAligned  NonPagedPoolCacheAligned
1392 #endif
1393 
1394 
1395 //
1396 //  Verification support routines.  Contained in verfysup.c
1397 //
1398 
1399 static /* ReactOS Change: GCC "multiple definition" */
1400 INLINE
1401 BOOLEAN
1402 CdOperationIsDasdOpen (
1403     _In_ PIRP_CONTEXT IrpContext
1404     )
1405 {
1406     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( IrpContext->Irp);
1407 
1408     return ((IrpContext->MajorFunction == IRP_MJ_CREATE) &&
1409             (IrpSp->FileObject->FileName.Length == 0) &&
1410             (IrpSp->FileObject->RelatedFileObject == NULL));
1411 }
1412 
1413 _Requires_lock_held_(_Global_critical_region_)
1414 NTSTATUS
1415 CdPerformVerify (
1416     _Inout_ PIRP_CONTEXT IrpContext,
1417     _Inout_ PIRP Irp,
1418     _In_ PDEVICE_OBJECT DeviceToVerify
1419     );
1420 
1421 _Requires_lock_held_(_Global_critical_region_)
1422 BOOLEAN
1423 CdCheckForDismount (
1424     _In_ PIRP_CONTEXT IrpContext,
1425     _Inout_ PVCB Vcb,
1426     _In_ BOOLEAN Force
1427     );
1428 
1429 BOOLEAN
1430 CdMarkDevForVerifyIfVcbMounted (
1431     _Inout_ PVCB Vcb
1432     );
1433 
1434 VOID
1435 CdVerifyVcb (
1436     _In_ PIRP_CONTEXT IrpContext,
1437     _Inout_ PVCB Vcb
1438     );
1439 
1440 BOOLEAN
1441 CdVerifyFcbOperation (
1442     _In_opt_ PIRP_CONTEXT IrpContext,
1443     _In_ PFCB Fcb
1444     );
1445 
1446 _Requires_lock_held_(_Global_critical_region_)
1447 BOOLEAN
1448 CdDismountVcb (
1449     _In_ PIRP_CONTEXT IrpContext,
1450     _Inout_ PVCB Vcb
1451     );
1452 
1453 
1454 //
1455 //  Macros to abstract device verify flag changes.
1456 //
1457 
1458 #define CdUpdateMediaChangeCount( V, C)  (V)->MediaChangeCount = (C)
1459 #define CdUpdateVcbCondition( V, C)      (V)->VcbCondition = (C)
1460 
1461 #define CdMarkRealDevForVerify( DO)  SetFlag( (DO)->Flags, DO_VERIFY_VOLUME)
1462 
1463 #define CdMarkRealDevVerifyOk( DO)   ClearFlag( (DO)->Flags, DO_VERIFY_VOLUME)
1464 
1465 
1466 #define CdRealDevNeedsVerify( DO)    BooleanFlagOn( (DO)->Flags, DO_VERIFY_VOLUME)
1467 
1468 //
1469 //  BOOLEAN
1470 //  CdIsRawDevice (
1471 //      _In_ PIRP_CONTEXT IrpContext,
1472 //      _In_ NTSTATUS Status
1473 //      );
1474 //
1475 
1476 #define CdIsRawDevice(IC,S) (           \
1477     ((S) == STATUS_DEVICE_NOT_READY) || \
1478     ((S) == STATUS_NO_MEDIA_IN_DEVICE)  \
1479 )
1480 
1481 
1482 //
1483 //  Work queue routines for posting and retrieving an Irp, implemented in
1484 //  workque.c
1485 //
1486 
1487 _Requires_lock_held_(_Global_critical_region_)
1488 NTSTATUS
1489 CdFsdPostRequest (
1490     _Inout_ PIRP_CONTEXT IrpContext,
1491     _Inout_ PIRP Irp
1492     );
1493 
1494 _Requires_lock_held_(_Global_critical_region_)
1495 VOID
1496 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1497 CdPrePostIrp (
1498     _Inout_ PIRP_CONTEXT IrpContext,
1499     _Inout_ PIRP Irp
1500     );
1501 
1502 _Requires_lock_held_(_Global_critical_region_)
1503 VOID
1504 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1505 CdOplockComplete (
1506     _Inout_ PIRP_CONTEXT IrpContext,
1507     _Inout_ PIRP Irp
1508     );
1509 
1510 
1511 //
1512 //  Miscellaneous support routines
1513 //
1514 
1515 //
1516 //  This macro returns TRUE if a flag in a set of flags is on and FALSE
1517 //  otherwise
1518 //
1519 
1520 /* GCC complains about multi-line comments.
1521 //#ifndef BooleanFlagOn
1522 //#define BooleanFlagOn(F,SF) (    \
1523 //    (BOOLEAN)(((F) & (SF)) != 0) \
1524 //)
1525 //#endif
1526 
1527 //#ifndef SetFlag
1528 //#define SetFlag(Flags,SingleFlag) { \
1529 //    (Flags) |= (SingleFlag);        \
1530 //}
1531 //#endif
1532 
1533 //#ifndef ClearFlag
1534 //#define ClearFlag(Flags,SingleFlag) { \
1535 //    (Flags) &= ~(SingleFlag);         \
1536 //}
1537 //#endif
1538 */
1539 
1540 //
1541 //      CAST
1542 //      Add2Ptr (
1543 //          _In_ PVOID Pointer,
1544 //          _In_ ULONG Increment
1545 //          _In_ (CAST)
1546 //          );
1547 //
1548 //      ULONG
1549 //      PtrOffset (
1550 //          _In_ PVOID BasePtr,
1551 //          _In_ PVOID OffsetPtr
1552 //          );
1553 //
1554 
1555 #define Add2Ptr(PTR,INC,CAST) ((CAST)((PUCHAR)(PTR) + (INC)))
1556 
1557 #define PtrOffset(BASE,OFFSET) ((ULONG)((ULONG_PTR)(OFFSET) - (ULONG_PTR)(BASE)))
1558 
1559 //
1560 //  This macro takes a pointer (or ulong) and returns its rounded up word
1561 //  value
1562 //
1563 
1564 #define WordAlign(Ptr) (                \
1565     ((((ULONG)(Ptr)) + 1) & 0xfffffffe) \
1566     )
1567 
1568 //
1569 //  This macro takes a pointer (or ulong) and returns its rounded up longword
1570 //  value
1571 //
1572 
1573 #define LongAlign(Ptr) (                \
1574     ((((ULONG)(Ptr)) + 3) & 0xfffffffc) \
1575     )
1576 
1577 //
1578 //  This macro takes a pointer (or ulong) and returns its rounded up quadword
1579 //  value
1580 //
1581 
1582 #define QuadAlign(Ptr) (                \
1583     ((((ULONG)(Ptr)) + 7) & 0xfffffff8) \
1584     )
1585 
1586 //
1587 //  The following macros round up and down to sector boundaries.
1588 //
1589 
1590 #define SectorAlign(L) (                                                \
1591     ((((ULONG)(L)) + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1))           \
1592 )
1593 
1594 #define LlSectorAlign(L) (                                              \
1595     ((((LONGLONG)(L)) + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1))        \
1596 )
1597 
1598 #define SectorTruncate(L) (                                             \
1599     ((ULONG)(L)) & ~(SECTOR_SIZE - 1)                                   \
1600 )
1601 
1602 #define LlSectorTruncate(L) (                                           \
1603     ((LONGLONG)(L)) & ~(SECTOR_SIZE - 1)                                \
1604 )
1605 
1606 #define BytesFromSectors(L) (                                           \
1607     ((ULONG) (L)) << SECTOR_SHIFT                                       \
1608 )
1609 
1610 #define SectorsFromBytes(L) (                                           \
1611     ((ULONG) (L)) >> SECTOR_SHIFT                                       \
1612 )
1613 
1614 static /* ReactOS Change: GCC "multiple definition" */
1615 INLINE
1616 ULONG
1617 SectorsFromLlBytes(
1618     ULONGLONG Bytes
1619 ) {
1620 
1621     return (ULONG)(Bytes >> SECTOR_SHIFT);
1622 }
1623 
1624 #define LlBytesFromSectors(L) (                                         \
1625     Int64ShllMod32( (LONGLONG)(L), SECTOR_SHIFT )                       \
1626 )
1627 
1628 #define LlSectorsFromBytes(L) (                                         \
1629     Int64ShraMod32( (LONGLONG)(L), SECTOR_SHIFT )                       \
1630 )
1631 
1632 #define SectorOffset(L) (                                               \
1633     ((ULONG)(ULONG_PTR) (L)) & SECTOR_MASK                              \
1634 )
1635 
1636 #define SectorBlockOffset(V,LB) (                                       \
1637     ((ULONG) (LB)) & ((V)->BlocksPerSector - 1)                         \
1638 )
1639 
1640 #define BytesFromBlocks(V,B) (                                          \
1641     (ULONG) (B) << (V)->BlockToByteShift                                \
1642 )
1643 
1644 #define LlBytesFromBlocks(V,B) (                                        \
1645     Int64ShllMod32( (LONGLONG) (B), (V)->BlockToByteShift )             \
1646 )
1647 
1648 #define BlockAlign(V,L) (                                               \
1649     ((ULONG)(L) + (V)->BlockMask) & (V)->BlockInverseMask               \
1650 )
1651 
1652 //
1653 //  Carefully make sure the mask is sign extended to 64bits
1654 //
1655 
1656 #define LlBlockAlign(V,L) (                                                     \
1657     ((LONGLONG)(L) + (V)->BlockMask) & (LONGLONG)((LONG)(V)->BlockInverseMask)  \
1658 )
1659 
1660 #define BlockOffset(V,L) (                                              \
1661     ((ULONG) (L)) & (V)->BlockMask                                      \
1662 )
1663 
1664 #define RawSectorAlign( B) ((((B)+(RAW_SECTOR_SIZE - 1)) / RAW_SECTOR_SIZE) * RAW_SECTOR_SIZE)
1665 
1666 //
1667 //  The following types and macros are used to help unpack the packed and
1668 //  misaligned fields found in the Bios parameter block
1669 //
1670 
1671 typedef union _UCHAR1 {
1672     UCHAR  Uchar[1];
1673     UCHAR  ForceAlignment;
1674 } UCHAR1, *PUCHAR1;
1675 
1676 typedef union _UCHAR2 {
1677     UCHAR  Uchar[2];
1678     USHORT ForceAlignment;
1679 } UCHAR2, *PUCHAR2;
1680 
1681 typedef union _UCHAR4 {
1682     UCHAR  Uchar[4];
1683     ULONG  ForceAlignment;
1684 } UCHAR4, *PUCHAR4;
1685 
1686 typedef union _USHORT2 {
1687     USHORT Ushort[2];
1688     ULONG  ForceAlignment;
1689 } USHORT2, *PUSHORT2;
1690 
1691 //
1692 //  This macro copies an unaligned src byte to an aligned dst byte
1693 //
1694 
1695 #define CopyUchar1(Dst,Src) {                           \
1696     *((UCHAR1 *)(Dst)) = *((UNALIGNED UCHAR1 *)(Src));  \
1697     }
1698 
1699 //
1700 //  This macro copies an unaligned src word to an aligned dst word
1701 //
1702 
1703 #define CopyUchar2(Dst,Src) {                           \
1704     *((UCHAR2 *)(Dst)) = *((UNALIGNED UCHAR2 *)(Src));  \
1705     }
1706 
1707 //
1708 //  This macro copies an unaligned src longword to an aligned dsr longword
1709 //
1710 
1711 #define CopyUchar4(Dst,Src) {                           \
1712     *((UCHAR4 *)(Dst)) = *((UNALIGNED UCHAR4 *)(Src));  \
1713     }
1714 
1715 //
1716 //  This macro copies an unaligned src longword to an aligned dsr longword
1717 //  accessing the source on a word boundary.
1718 //
1719 
1720 #define CopyUshort2(Dst,Src) {                          \
1721     *((USHORT2 *)(Dst)) = *((UNALIGNED USHORT2 *)(Src));\
1722     }
1723 
1724 //
1725 //  This macro copies an unaligned src longword to a dst longword,
1726 //  performing an little/big endian swap.
1727 //
1728 
1729 #define SwapCopyUchar4(Dst,Src) {                                        \
1730     *((UNALIGNED UCHAR1 *)(Dst)) = *((UNALIGNED UCHAR1 *)(Src) + 3);     \
1731     *((UNALIGNED UCHAR1 *)(Dst) + 1) = *((UNALIGNED UCHAR1 *)(Src) + 2); \
1732     *((UNALIGNED UCHAR1 *)(Dst) + 2) = *((UNALIGNED UCHAR1 *)(Src) + 1); \
1733     *((UNALIGNED UCHAR1 *)(Dst) + 3) = *((UNALIGNED UCHAR1 *)(Src));     \
1734 }
1735 
1736 VOID
1737 CdLbnToMmSsFf (
1738     _In_ ULONG Blocks,
1739     _Out_writes_(3) PUCHAR Msf
1740     );
1741 
1742 //
1743 //  Following routines handle entry in and out of the filesystem.  They are
1744 //  contained in CdData.c
1745 //
1746 
1747 _IRQL_requires_max_(APC_LEVEL)
1748 __drv_dispatchType(DRIVER_DISPATCH)
1749 __drv_dispatchType(IRP_MJ_CREATE)
1750 __drv_dispatchType(IRP_MJ_CLOSE)
1751 __drv_dispatchType(IRP_MJ_READ)
1752 __drv_dispatchType(IRP_MJ_WRITE)
1753 __drv_dispatchType(IRP_MJ_QUERY_INFORMATION)
1754 __drv_dispatchType(IRP_MJ_SET_INFORMATION)
1755 __drv_dispatchType(IRP_MJ_QUERY_VOLUME_INFORMATION)
1756 __drv_dispatchType(IRP_MJ_DIRECTORY_CONTROL)
1757 __drv_dispatchType(IRP_MJ_FILE_SYSTEM_CONTROL)
1758 __drv_dispatchType(IRP_MJ_DEVICE_CONTROL)
1759 __drv_dispatchType(IRP_MJ_LOCK_CONTROL)
1760 __drv_dispatchType(IRP_MJ_CLEANUP)
1761 __drv_dispatchType(IRP_MJ_PNP)
1762 __drv_dispatchType(IRP_MJ_SHUTDOWN)
1763 NTSTATUS
1764 NTAPI
1765 CdFsdDispatch (
1766     _In_ PDEVICE_OBJECT DeviceObject,
1767     _Inout_ PIRP Irp
1768     );
1769 
1770 // DRIVER_DISPATCH CdFsdDispatch;
1771 
1772 LONG
1773 CdExceptionFilter (
1774     _Inout_ PIRP_CONTEXT IrpContext,
1775     _In_ PEXCEPTION_POINTERS ExceptionPointer
1776     );
1777 
1778 _Requires_lock_held_(_Global_critical_region_)
1779 NTSTATUS
1780 CdProcessException (
1781     _In_opt_ PIRP_CONTEXT IrpContext,
1782     _Inout_ PIRP Irp,
1783     _In_ NTSTATUS ExceptionCode
1784     );
1785 
1786 VOID
1787 CdCompleteRequest (
1788     _Inout_opt_ PIRP_CONTEXT IrpContext,
1789     _Inout_opt_ PIRP Irp,
1790     _In_ NTSTATUS Status
1791     );
1792 
1793 //
1794 //  VOID
1795 //  CdRaiseStatus (
1796 //      _In_ PRIP_CONTEXT IrpContext,
1797 //      _In_ NT_STATUS Status
1798 //      );
1799 //
1800 //  VOID
1801 //  CdNormalizeAndRaiseStatus (
1802 //      _In_ PRIP_CONTEXT IrpContext,
1803 //      _In_ NT_STATUS Status
1804 //      );
1805 //
1806 
1807 #if 0
1808 #define AssertVerifyDevice(C, S)                                                    \
1809     NT_ASSERT( (C) == NULL ||                                                          \
1810             FlagOn( (C)->Flags, IRP_CONTEXT_FLAG_IN_FSP ) ||                        \
1811             !((S) == STATUS_VERIFY_REQUIRED &&                                      \
1812               IoGetDeviceToVerify( PsGetCurrentThread() ) == NULL ));
1813 
1814 #define AssertVerifyDeviceIrp(I)                                                    \
1815     NT_ASSERT( (I) == NULL ||                                                          \
1816             !(((I)->IoStatus.Status) == STATUS_VERIFY_REQUIRED &&                   \
1817               ((I)->Tail.Overlay.Thread == NULL ||                                  \
1818                 IoGetDeviceToVerify( (I)->Tail.Overlay.Thread ) == NULL )));
1819 #else
1820 #define AssertVerifyDevice(C, S)
1821 #define AssertVerifyDeviceIrp(I)
1822 #endif
1823 
1824 
1825 #ifdef CD_SANITY
1826 
1827 DECLSPEC_NORETURN
1828 VOID
1829 CdRaiseStatusEx (
1830     _In_ PIRP_CONTEXT IrpContext,
1831     _In_ NTSTATUS Status,
1832     _In_ BOOLEAN NormalizeStatus,
1833     _In_opt_ ULONG FileId,
1834     _In_opt_ ULONG Line
1835     );
1836 
1837 #else
1838 
1839 INLINE
1840 DECLSPEC_NORETURN
1841 VOID
1842 CdRaiseStatusEx(
1843     _In_ PIRP_CONTEXT IrpContext,
1844     _In_ NTSTATUS Status,
1845     _In_ BOOLEAN NormalizeStatus,
1846     _In_ ULONG Fileid,
1847     _In_ ULONG Line
1848     )
1849 {
1850     if (NormalizeStatus)  {
1851 
1852         IrpContext->ExceptionStatus = FsRtlNormalizeNtstatus( Status, STATUS_UNEXPECTED_IO_ERROR);
1853     }
1854     else {
1855 
1856         IrpContext->ExceptionStatus = Status;
1857     }
1858 
1859     IrpContext->RaisedAtLineFile = (Fileid << 16) | Line;
1860 
1861     ExRaiseStatus( IrpContext->ExceptionStatus );
1862 }
1863 
1864 #endif
1865 
1866 #define CdRaiseStatus( IC, S)               CdRaiseStatusEx( (IC), (S), FALSE, BugCheckFileId, __LINE__);
1867 #define CdNormalizeAndRaiseStatus( IC, S)   CdRaiseStatusEx( (IC), (S), TRUE, BugCheckFileId, __LINE__);
1868 
1869 //
1870 //  Following are the fast entry points.
1871 //
1872 
1873 //  _Success_(return != FALSE)
1874 //  BOOLEAN
1875 //  CdFastQueryBasicInfo (
1876 //      _In_ PFILE_OBJECT FileObject,
1877 //      _In_ BOOLEAN Wait,
1878 //      _Out_ PFILE_BASIC_INFORMATION Buffer,
1879 //      _Out_ PIO_STATUS_BLOCK IoStatus,
1880 //      _In_ PDEVICE_OBJECT DeviceObject
1881 //      );
1882 
1883 FAST_IO_QUERY_BASIC_INFO CdFastQueryBasicInfo;
1884 
1885 //  _Success_(return != FALSE)
1886 //  BOOLEAN
1887 //  CdFastQueryStdInfo (
1888 //      _In_ PFILE_OBJECT FileObject,
1889 //      _In_ BOOLEAN Wait,
1890 //      _Out_ PFILE_STANDARD_INFORMATION Buffer,
1891 //      _Out_ PIO_STATUS_BLOCK IoStatus,
1892 //      _In_ PDEVICE_OBJECT DeviceObject
1893 //      );
1894 
1895 FAST_IO_QUERY_STANDARD_INFO CdFastQueryStdInfo;
1896 
1897 //  BOOLEAN
1898 //  CdFastLock (
1899 //      _In_ PFILE_OBJECT FileObject,
1900 //      _In_ PLARGE_INTEGER FileOffset,
1901 //      _In_ PLARGE_INTEGER Length,
1902 //      _In_ PEPROCESS ProcessId,
1903 //      _In_ ULONG Key,
1904 //      _In_ BOOLEAN FailImmediately,
1905 //      _In_ BOOLEAN ExclusiveLock,
1906 //      _Out_ PIO_STATUS_BLOCK IoStatus,
1907 //      _In_ PDEVICE_OBJECT DeviceObject
1908 //      );
1909 
1910 FAST_IO_LOCK CdFastLock;
1911 
1912 //  BOOLEAN
1913 //  CdFastUnlockSingle (
1914 //      _In_ PFILE_OBJECT FileObject,
1915 //      _In_ PLARGE_INTEGER FileOffset,
1916 //      _In_ PLARGE_INTEGER Length,
1917 //      _In_ PEPROCESS ProcessId,
1918 //      _In_ ULONG Key,
1919 //      _Out_ PIO_STATUS_BLOCK IoStatus,
1920 //      _In_ PDEVICE_OBJECT DeviceObject
1921 //      );
1922 
1923 FAST_IO_UNLOCK_SINGLE CdFastUnlockSingle;
1924 
1925 //  BOOLEAN
1926 //  CdFastUnlockAll (
1927 //      _In_ PFILE_OBJECT FileObject,
1928 //      _In_ PEPROCESS ProcessId,
1929 //      _Out_ PIO_STATUS_BLOCK IoStatus,
1930 //      _In_ PDEVICE_OBJECT DeviceObject
1931 //      );
1932 
1933 FAST_IO_UNLOCK_ALL CdFastUnlockAll;
1934 
1935 //  BOOLEAN
1936 //  CdFastUnlockAllByKey (
1937 //      _In_ PFILE_OBJECT FileObject,
1938 //      _In_ PVOID ProcessId,
1939 //      _In_ ULONG Key,
1940 //      _Out_ PIO_STATUS_BLOCK IoStatus,
1941 //      _In_ PDEVICE_OBJECT DeviceObject
1942 //      );
1943 
1944 FAST_IO_UNLOCK_ALL_BY_KEY CdFastUnlockAllByKey;
1945 
1946 //  BOOLEAN
1947 //  CdFastIoCheckIfPossible (
1948 //      _In_ PFILE_OBJECT FileObject,
1949 //      _In_ PLARGE_INTEGER FileOffset,
1950 //      _In_ ULONG Length,
1951 //      _In_ BOOLEAN Wait,
1952 //      _In_ ULONG LockKey,
1953 //      _In_ BOOLEAN CheckForReadOperation,
1954 //      _Out_ PIO_STATUS_BLOCK IoStatus,
1955 //      _In_ PDEVICE_OBJECT DeviceObject
1956 //      );
1957 
1958 FAST_IO_CHECK_IF_POSSIBLE CdFastIoCheckIfPossible;
1959 
1960 //  _Success_(return != FALSE)
1961 //  BOOLEAN
1962 //  CdFastQueryNetworkInfo (
1963 //      _In_ PFILE_OBJECT FileObject,
1964 //      _In_ BOOLEAN Wait,
1965 //      _Out_ PFILE_NETWORK_OPEN_INFORMATION Buffer,
1966 //      _Out_ PIO_STATUS_BLOCK IoStatus,
1967 //      _In_ PDEVICE_OBJECT DeviceObject
1968 //      );
1969 
1970 FAST_IO_QUERY_NETWORK_OPEN_INFO CdFastQueryNetworkInfo;
1971 
1972 //
1973 //  Following are the routines to handle the top level thread logic.
1974 //
1975 
1976 VOID
1977 CdSetThreadContext (
1978     _Inout_ PIRP_CONTEXT IrpContext,
1979     _In_ PTHREAD_CONTEXT ThreadContext
1980     );
1981 
1982 
1983 //
1984 //  VOID
1985 //  CdRestoreThreadContext (
1986 //      _Inout_ PIRP_CONTEXT IrpContext
1987 //      );
1988 //
1989 
1990 #define CdRestoreThreadContext(IC)                              \
1991     (IC)->ThreadContext->Cdfs = 0;                              \
1992     IoSetTopLevelIrp( (IC)->ThreadContext->SavedTopLevelIrp );  \
1993     (IC)->ThreadContext = NULL
1994 
1995 ULONG
1996 CdSerial32 (
1997     _In_reads_bytes_(ByteCount) PCHAR Buffer,
1998     _In_ ULONG ByteCount
1999     );
2000 
2001 //
2002 //  The following macro is used to determine if an FSD thread can block
2003 //  for I/O or wait for a resource.  It returns TRUE if the thread can
2004 //  block and FALSE otherwise.  This attribute can then be used to call
2005 //  the FSD & FSP common work routine with the proper wait value.
2006 //
2007 
2008 #define CanFsdWait(I)   IoIsOperationSynchronous(I)
2009 
2010 //
2011 //  The following macro is used to set the fast i/o possible bits in the
2012 //  FsRtl header.
2013 //
2014 //      FastIoIsNotPossible - If the Fcb is bad or there are oplocks on the file.
2015 //
2016 //      FastIoIsQuestionable - If there are file locks.
2017 //
2018 //      FastIoIsPossible - In all other cases.
2019 //
2020 //
2021 
2022 #define CdIsFastIoPossible(F) ((BOOLEAN)                                            \
2023     ((((F)->Vcb->VcbCondition != VcbMounted ) ||                                    \
2024       !FsRtlOplockIsFastIoPossible( CdGetFcbOplock(F) )) ?                          \
2025                                                                                     \
2026      FastIoIsNotPossible :                                                          \
2027                                                                                     \
2028      ((((F)->FileLock != NULL) && FsRtlAreThereCurrentFileLocks( (F)->FileLock )) ? \
2029                                                                                     \
2030         FastIoIsQuestionable :                                                      \
2031                                                                                     \
2032         FastIoIsPossible))                                                          \
2033 )
2034 
2035 
2036 //
2037 //  The FSP level dispatch/main routine.  This is the routine that takes
2038 //  IRP's off of the work queue and calls the appropriate FSP level
2039 //  work routine.
2040 //
2041 
2042 //  VOID
2043 //  CdFspDispatch (                             //  implemented in FspDisp.c
2044 //      _Inout_ PIRP_CONTEXT IrpContext
2045 //      );
2046 
2047 WORKER_THREAD_ROUTINE CdFspDispatch;
2048 
2049 VOID
2050 CdFspClose (                                //  implemented in Close.c
2051     _In_opt_ PVCB Vcb
2052     );
2053 
2054 //
2055 //  The following routines are the entry points for the different operations
2056 //  based on the IrpSp major functions.
2057 //
2058 
2059 _Requires_lock_held_(_Global_critical_region_)
2060 NTSTATUS
2061 CdCommonCreate (                            //  Implemented in Create.c
2062     _Inout_ PIRP_CONTEXT IrpContext,
2063     _Inout_ PIRP Irp
2064     );
2065 
2066 _Requires_lock_held_(_Global_critical_region_)
2067 NTSTATUS
2068 CdCommonClose (                             //  Implemented in Close.c
2069     _Inout_ PIRP_CONTEXT IrpContext,
2070     _Inout_ PIRP Irp
2071     );
2072 
2073 _Requires_lock_held_(_Global_critical_region_)
2074 NTSTATUS
2075 CdCommonRead (                              //  Implemented in Read.c
2076     _Inout_ PIRP_CONTEXT IrpContext,
2077     _Inout_ PIRP Irp
2078     );
2079 
2080 _Requires_lock_held_(_Global_critical_region_)
2081 NTSTATUS
2082 CdCommonWrite (                             //  Implemented in Write.c
2083     _Inout_ PIRP_CONTEXT IrpContext,
2084     _Inout_ PIRP Irp
2085     );
2086 
2087 _Requires_lock_held_(_Global_critical_region_)
2088 NTSTATUS
2089 CdCommonQueryInfo (                         //  Implemented in FileInfo.c
2090     _Inout_ PIRP_CONTEXT IrpContext,
2091     _Inout_ PIRP Irp
2092     );
2093 
2094 _Requires_lock_held_(_Global_critical_region_)
2095 NTSTATUS
2096 CdCommonSetInfo (                           //  Implemented in FileInfo.c
2097     _Inout_ PIRP_CONTEXT IrpContext,
2098     _Inout_ PIRP Irp
2099     );
2100 
2101 _Requires_lock_held_(_Global_critical_region_)
2102 NTSTATUS
2103 CdCommonQueryVolInfo (                      //  Implemented in VolInfo.c
2104     _Inout_ PIRP_CONTEXT IrpContext,
2105     _Inout_ PIRP Irp
2106     );
2107 
2108 _Requires_lock_held_(_Global_critical_region_)
2109 NTSTATUS
2110 CdCommonDirControl (                        //  Implemented in DirCtrl.c
2111     _Inout_ PIRP_CONTEXT IrpContext,
2112     _Inout_ PIRP Irp
2113     );
2114 
2115 _Requires_lock_held_(_Global_critical_region_)
2116 NTSTATUS
2117 CdCommonFsControl (                         //  Implemented in FsCtrl.c
2118     _Inout_ PIRP_CONTEXT IrpContext,
2119     _Inout_ PIRP Irp
2120     );
2121 
2122 NTSTATUS
2123 CdCommonDevControl (                        //  Implemented in DevCtrl.c
2124     _Inout_ PIRP_CONTEXT IrpContext,
2125     _Inout_ PIRP Irp
2126     );
2127 
2128 NTSTATUS
2129 CdCommonLockControl (                       //  Implemented in LockCtrl.c
2130     _Inout_ PIRP_CONTEXT IrpContext,
2131     _Inout_ PIRP Irp
2132     );
2133 
2134 _Requires_lock_held_(_Global_critical_region_)
2135 NTSTATUS
2136 CdCommonCleanup (                           //  Implemented in Cleanup.c
2137     _Inout_ PIRP_CONTEXT IrpContext,
2138     _Inout_ PIRP Irp
2139     );
2140 
2141 _Requires_lock_held_(_Global_critical_region_)
2142 NTSTATUS
2143 CdCommonPnp (                               //  Implemented in Pnp.c
2144     _Inout_ PIRP_CONTEXT IrpContext,
2145     _Inout_ PIRP Irp
2146     );
2147 
2148 _Requires_lock_held_(_Global_critical_region_)
2149 NTSTATUS
2150 CdCommonShutdown (                         //  Implemented in Shutdown.c
2151     _Inout_ PIRP_CONTEXT IrpContext,
2152     _Inout_ PIRP Irp
2153     );
2154 
2155 
2156 
2157 //
2158 //  The following macros are used to establish the semantics needed
2159 //  to do a return from within a try-finally clause.  As a rule every
2160 //  try clause must end with a label call try_exit.  For example,
2161 //
2162 //      try {
2163 //              :
2164 //              :
2165 //
2166 //      try_exit: NOTHING;
2167 //      } finally {
2168 //
2169 //              :
2170 //              :
2171 //      }
2172 //
2173 //  Every return statement executed inside of a try clause should use the
2174 //  try_return macro.  If the compiler fully supports the try-finally construct
2175 //  then the macro should be
2176 //
2177 //      #define try_return(S)  { return(S); }
2178 //
2179 //  If the compiler does not support the try-finally construct then the macro
2180 //  should be
2181 //
2182 //      #define try_return(S)  { S; goto try_exit; }
2183 //
2184 
2185 #ifndef __REACTOS__
2186 #define try_return(S) { S; goto try_exit; }
2187 #define try_leave(S) { S; leave; }
2188 #else
2189 #define try_return(S) { S; goto try_exit; }
2190 #define try_leave(S) { S; _SEH2_LEAVE; }
2191 #endif
2192 
2193 //
2194 //  Encapsulate safe pool freeing
2195 //
2196 /* ReactOS Change: GCC "passing argument 1 of CdFreePool from incompatible pointer type" */
2197 #define CdFreePool(x) _CdFreePool((PVOID*)(x))
2198 
2199 static /* ReactOS Change: GCC "multiple definition" */
2200 INLINE
2201 VOID
2202 _CdFreePool(
2203     _Inout_ _At_(*Pool, __drv_freesMem(Mem) _Post_null_) PVOID *Pool
2204     )
2205 {
2206     if (*Pool != NULL) {
2207 
2208         ExFreePool(*Pool);
2209         *Pool = NULL;
2210     }
2211 }
2212 
2213 #ifdef CDFS_TELEMETRY_DATA
2214 
2215 //
2216 //  CDFS Telemetry.  Current implementation uses the Telemetry TraceLogging APIs.
2217 //
2218 //  The Telemetry TraceLoggingWrite() routines use a lot of stack space. We must
2219 //  therefor wrap all our telemetry points with our own routines, and add a guard to
2220 //  make sure there's enough stack space to call these routines.
2221 //
2222 //  These telemetry routines should not be called on high-performance code paths.
2223 //
2224 
2225 TRACELOGGING_DECLARE_PROVIDER( CdTelemetryProvider );
2226 
2227 VOID
2228 CdInitializeTelemetry (
2229     VOID
2230     );
2231 
2232 DECLSPEC_NOINLINE
2233 VOID
2234 CdTelemetryMount (
2235         __in PGUID VolumeGuid,
2236         __in NTSTATUS Status,
2237         __in PVCB Vcb
2238         );
2239 
2240 //
2241 //  Every additional argument passed to TraceLoggingWrite() consumes an additional
2242 //  16 to 32 bytes extra stack space. Having 512 bytes reserved space should be
2243 //  sufficient for up to 20 arguments or so. This will be less of course if our
2244 //  wrapper routines also declare their own local variables.
2245 //
2246 
2247 #define CDFS_TELEMETRY_STACK_THRESHOLD_DEFAULT  512    // for "small" telemetry points
2248 #define CDFS_TELEMETRY_STACK_THRESHOLD_LARGE    2048   // for "large" telemetry points
2249 
2250 INLINE
2251 BOOLEAN
2252 CdTelemetryGuard (
2253     __in ULONG StackSpaceNeeded )
2254 /*++
2255 
2256 Routine Description:
2257 
2258     This routine returns TRUE only when:
2259 
2260       1)  There is an ETW listener, AND
2261       2)  There is enough free stack space to safely call the Telemetry TraceLogging APIs
2262 
2263     We'll also count how many times there wasn't enough stack space, and include this
2264     value as part of the periodic cdfs Telemetry.
2265 
2266 Arguments:
2267 
2268     StackSpaceNeeded - Stack space needed in bytes
2269 
2270 --*/
2271 {
2272     ASSERT( IoGetRemainingStackSize() >= StackSpaceNeeded );
2273 
2274     if (CdTelemetryProvider->LevelPlus1 <= 5) {
2275 
2276         //
2277         //  Bail out early if there are no ETW listeners
2278         //
2279 
2280         return FALSE;
2281     }
2282 
2283     if (IoGetRemainingStackSize() < StackSpaceNeeded) {
2284 
2285         //
2286         //  Count how many times it was unsafe to generate telemetry because of
2287         //  not enough stack space.
2288         //
2289 
2290         InterlockedIncrement( &CdTelemetryData.MissedTelemetryPoints );
2291 
2292         return FALSE;
2293     }
2294 
2295     return TRUE;
2296 }
2297 
2298 #define CdTelemetryMountSafe( VolumeGuid, Status, Vcb ) \
2299     if (CdTelemetryGuard( CDFS_TELEMETRY_STACK_THRESHOLD_LARGE )) { \
2300         CdTelemetryMount( VolumeGuid, Status, Vcb ); \
2301     }
2302 
2303 #if DBG
2304 #define CDFS_TELEMETRY_PERIODIC_INTERVAL  CdTelemetryData.PeriodicInterval
2305 #else
2306 #define CDFS_TELEMETRY_PERIODIC_INTERVAL  INTERVAL_ONE_DAY
2307 #endif
2308 
2309 #else  // CDFS_TELEMETRY_DATA
2310 
2311 //
2312 //  When CDFS_TELEMETRY_DATA is not defined then the CdTelemetry___Safe() routines
2313 //  expand to nothing.  This minimizes the cdfs.sys binary footprint.  This also
2314 //  means that the places where these Safe() routines are called do not
2315 //  have to have to be surrounded by  #ifdef CDFS_TELEMETRY_DATA .. #endif
2316 //
2317 
2318 
2319 #define CdTelemetryMountSafe( ... )           NOTHING
2320 
2321 #endif  // CDFS_TELEMETRY_DATA
2322 
2323 #endif // _CDPROCS_
2324 
2325 
2326