xref: /reactos/drivers/filesystems/cdfs/cdprocs.h (revision e5873161)
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 #ifdef __REACTOS__
1840 static //  make windows gcc release build compile
1841 #endif
1842 INLINE
1843 DECLSPEC_NORETURN
1844 VOID
1845 CdRaiseStatusEx(
1846     _In_ PIRP_CONTEXT IrpContext,
1847     _In_ NTSTATUS Status,
1848     _In_ BOOLEAN NormalizeStatus,
1849     _In_ ULONG Fileid,
1850     _In_ ULONG Line
1851     )
1852 {
1853     if (NormalizeStatus)  {
1854 
1855         IrpContext->ExceptionStatus = FsRtlNormalizeNtstatus( Status, STATUS_UNEXPECTED_IO_ERROR);
1856     }
1857     else {
1858 
1859         IrpContext->ExceptionStatus = Status;
1860     }
1861 
1862     IrpContext->RaisedAtLineFile = (Fileid << 16) | Line;
1863 
1864     ExRaiseStatus( IrpContext->ExceptionStatus );
1865 }
1866 
1867 #endif
1868 
1869 #define CdRaiseStatus( IC, S)               CdRaiseStatusEx( (IC), (S), FALSE, BugCheckFileId, __LINE__);
1870 #define CdNormalizeAndRaiseStatus( IC, S)   CdRaiseStatusEx( (IC), (S), TRUE, BugCheckFileId, __LINE__);
1871 
1872 //
1873 //  Following are the fast entry points.
1874 //
1875 
1876 //  _Success_(return != FALSE)
1877 //  BOOLEAN
1878 //  CdFastQueryBasicInfo (
1879 //      _In_ PFILE_OBJECT FileObject,
1880 //      _In_ BOOLEAN Wait,
1881 //      _Out_ PFILE_BASIC_INFORMATION Buffer,
1882 //      _Out_ PIO_STATUS_BLOCK IoStatus,
1883 //      _In_ PDEVICE_OBJECT DeviceObject
1884 //      );
1885 
1886 FAST_IO_QUERY_BASIC_INFO CdFastQueryBasicInfo;
1887 
1888 //  _Success_(return != FALSE)
1889 //  BOOLEAN
1890 //  CdFastQueryStdInfo (
1891 //      _In_ PFILE_OBJECT FileObject,
1892 //      _In_ BOOLEAN Wait,
1893 //      _Out_ PFILE_STANDARD_INFORMATION Buffer,
1894 //      _Out_ PIO_STATUS_BLOCK IoStatus,
1895 //      _In_ PDEVICE_OBJECT DeviceObject
1896 //      );
1897 
1898 FAST_IO_QUERY_STANDARD_INFO CdFastQueryStdInfo;
1899 
1900 //  BOOLEAN
1901 //  CdFastLock (
1902 //      _In_ PFILE_OBJECT FileObject,
1903 //      _In_ PLARGE_INTEGER FileOffset,
1904 //      _In_ PLARGE_INTEGER Length,
1905 //      _In_ PEPROCESS ProcessId,
1906 //      _In_ ULONG Key,
1907 //      _In_ BOOLEAN FailImmediately,
1908 //      _In_ BOOLEAN ExclusiveLock,
1909 //      _Out_ PIO_STATUS_BLOCK IoStatus,
1910 //      _In_ PDEVICE_OBJECT DeviceObject
1911 //      );
1912 
1913 FAST_IO_LOCK CdFastLock;
1914 
1915 //  BOOLEAN
1916 //  CdFastUnlockSingle (
1917 //      _In_ PFILE_OBJECT FileObject,
1918 //      _In_ PLARGE_INTEGER FileOffset,
1919 //      _In_ PLARGE_INTEGER Length,
1920 //      _In_ PEPROCESS ProcessId,
1921 //      _In_ ULONG Key,
1922 //      _Out_ PIO_STATUS_BLOCK IoStatus,
1923 //      _In_ PDEVICE_OBJECT DeviceObject
1924 //      );
1925 
1926 FAST_IO_UNLOCK_SINGLE CdFastUnlockSingle;
1927 
1928 //  BOOLEAN
1929 //  CdFastUnlockAll (
1930 //      _In_ PFILE_OBJECT FileObject,
1931 //      _In_ PEPROCESS ProcessId,
1932 //      _Out_ PIO_STATUS_BLOCK IoStatus,
1933 //      _In_ PDEVICE_OBJECT DeviceObject
1934 //      );
1935 
1936 FAST_IO_UNLOCK_ALL CdFastUnlockAll;
1937 
1938 //  BOOLEAN
1939 //  CdFastUnlockAllByKey (
1940 //      _In_ PFILE_OBJECT FileObject,
1941 //      _In_ PVOID ProcessId,
1942 //      _In_ ULONG Key,
1943 //      _Out_ PIO_STATUS_BLOCK IoStatus,
1944 //      _In_ PDEVICE_OBJECT DeviceObject
1945 //      );
1946 
1947 FAST_IO_UNLOCK_ALL_BY_KEY CdFastUnlockAllByKey;
1948 
1949 //  BOOLEAN
1950 //  CdFastIoCheckIfPossible (
1951 //      _In_ PFILE_OBJECT FileObject,
1952 //      _In_ PLARGE_INTEGER FileOffset,
1953 //      _In_ ULONG Length,
1954 //      _In_ BOOLEAN Wait,
1955 //      _In_ ULONG LockKey,
1956 //      _In_ BOOLEAN CheckForReadOperation,
1957 //      _Out_ PIO_STATUS_BLOCK IoStatus,
1958 //      _In_ PDEVICE_OBJECT DeviceObject
1959 //      );
1960 
1961 FAST_IO_CHECK_IF_POSSIBLE CdFastIoCheckIfPossible;
1962 
1963 //  _Success_(return != FALSE)
1964 //  BOOLEAN
1965 //  CdFastQueryNetworkInfo (
1966 //      _In_ PFILE_OBJECT FileObject,
1967 //      _In_ BOOLEAN Wait,
1968 //      _Out_ PFILE_NETWORK_OPEN_INFORMATION Buffer,
1969 //      _Out_ PIO_STATUS_BLOCK IoStatus,
1970 //      _In_ PDEVICE_OBJECT DeviceObject
1971 //      );
1972 
1973 FAST_IO_QUERY_NETWORK_OPEN_INFO CdFastQueryNetworkInfo;
1974 
1975 //
1976 //  Following are the routines to handle the top level thread logic.
1977 //
1978 
1979 VOID
1980 CdSetThreadContext (
1981     _Inout_ PIRP_CONTEXT IrpContext,
1982     _In_ PTHREAD_CONTEXT ThreadContext
1983     );
1984 
1985 
1986 //
1987 //  VOID
1988 //  CdRestoreThreadContext (
1989 //      _Inout_ PIRP_CONTEXT IrpContext
1990 //      );
1991 //
1992 
1993 #define CdRestoreThreadContext(IC)                              \
1994     (IC)->ThreadContext->Cdfs = 0;                              \
1995     IoSetTopLevelIrp( (IC)->ThreadContext->SavedTopLevelIrp );  \
1996     (IC)->ThreadContext = NULL
1997 
1998 ULONG
1999 CdSerial32 (
2000     _In_reads_bytes_(ByteCount) PCHAR Buffer,
2001     _In_ ULONG ByteCount
2002     );
2003 
2004 //
2005 //  The following macro is used to determine if an FSD thread can block
2006 //  for I/O or wait for a resource.  It returns TRUE if the thread can
2007 //  block and FALSE otherwise.  This attribute can then be used to call
2008 //  the FSD & FSP common work routine with the proper wait value.
2009 //
2010 
2011 #define CanFsdWait(I)   IoIsOperationSynchronous(I)
2012 
2013 //
2014 //  The following macro is used to set the fast i/o possible bits in the
2015 //  FsRtl header.
2016 //
2017 //      FastIoIsNotPossible - If the Fcb is bad or there are oplocks on the file.
2018 //
2019 //      FastIoIsQuestionable - If there are file locks.
2020 //
2021 //      FastIoIsPossible - In all other cases.
2022 //
2023 //
2024 
2025 #define CdIsFastIoPossible(F) ((BOOLEAN)                                            \
2026     ((((F)->Vcb->VcbCondition != VcbMounted ) ||                                    \
2027       !FsRtlOplockIsFastIoPossible( CdGetFcbOplock(F) )) ?                          \
2028                                                                                     \
2029      FastIoIsNotPossible :                                                          \
2030                                                                                     \
2031      ((((F)->FileLock != NULL) && FsRtlAreThereCurrentFileLocks( (F)->FileLock )) ? \
2032                                                                                     \
2033         FastIoIsQuestionable :                                                      \
2034                                                                                     \
2035         FastIoIsPossible))                                                          \
2036 )
2037 
2038 
2039 //
2040 //  The FSP level dispatch/main routine.  This is the routine that takes
2041 //  IRP's off of the work queue and calls the appropriate FSP level
2042 //  work routine.
2043 //
2044 
2045 //  VOID
2046 //  CdFspDispatch (                             //  implemented in FspDisp.c
2047 //      _Inout_ PIRP_CONTEXT IrpContext
2048 //      );
2049 
2050 WORKER_THREAD_ROUTINE CdFspDispatch;
2051 
2052 VOID
2053 CdFspClose (                                //  implemented in Close.c
2054     _In_opt_ PVCB Vcb
2055     );
2056 
2057 //
2058 //  The following routines are the entry points for the different operations
2059 //  based on the IrpSp major functions.
2060 //
2061 
2062 _Requires_lock_held_(_Global_critical_region_)
2063 NTSTATUS
2064 CdCommonCreate (                            //  Implemented in Create.c
2065     _Inout_ PIRP_CONTEXT IrpContext,
2066     _Inout_ PIRP Irp
2067     );
2068 
2069 _Requires_lock_held_(_Global_critical_region_)
2070 NTSTATUS
2071 CdCommonClose (                             //  Implemented in Close.c
2072     _Inout_ PIRP_CONTEXT IrpContext,
2073     _Inout_ PIRP Irp
2074     );
2075 
2076 _Requires_lock_held_(_Global_critical_region_)
2077 NTSTATUS
2078 CdCommonRead (                              //  Implemented in Read.c
2079     _Inout_ PIRP_CONTEXT IrpContext,
2080     _Inout_ PIRP Irp
2081     );
2082 
2083 _Requires_lock_held_(_Global_critical_region_)
2084 NTSTATUS
2085 CdCommonWrite (                             //  Implemented in Write.c
2086     _Inout_ PIRP_CONTEXT IrpContext,
2087     _Inout_ PIRP Irp
2088     );
2089 
2090 _Requires_lock_held_(_Global_critical_region_)
2091 NTSTATUS
2092 CdCommonQueryInfo (                         //  Implemented in FileInfo.c
2093     _Inout_ PIRP_CONTEXT IrpContext,
2094     _Inout_ PIRP Irp
2095     );
2096 
2097 _Requires_lock_held_(_Global_critical_region_)
2098 NTSTATUS
2099 CdCommonSetInfo (                           //  Implemented in FileInfo.c
2100     _Inout_ PIRP_CONTEXT IrpContext,
2101     _Inout_ PIRP Irp
2102     );
2103 
2104 _Requires_lock_held_(_Global_critical_region_)
2105 NTSTATUS
2106 CdCommonQueryVolInfo (                      //  Implemented in VolInfo.c
2107     _Inout_ PIRP_CONTEXT IrpContext,
2108     _Inout_ PIRP Irp
2109     );
2110 
2111 _Requires_lock_held_(_Global_critical_region_)
2112 NTSTATUS
2113 CdCommonDirControl (                        //  Implemented in DirCtrl.c
2114     _Inout_ PIRP_CONTEXT IrpContext,
2115     _Inout_ PIRP Irp
2116     );
2117 
2118 _Requires_lock_held_(_Global_critical_region_)
2119 NTSTATUS
2120 CdCommonFsControl (                         //  Implemented in FsCtrl.c
2121     _Inout_ PIRP_CONTEXT IrpContext,
2122     _Inout_ PIRP Irp
2123     );
2124 
2125 NTSTATUS
2126 CdCommonDevControl (                        //  Implemented in DevCtrl.c
2127     _Inout_ PIRP_CONTEXT IrpContext,
2128     _Inout_ PIRP Irp
2129     );
2130 
2131 NTSTATUS
2132 CdCommonLockControl (                       //  Implemented in LockCtrl.c
2133     _Inout_ PIRP_CONTEXT IrpContext,
2134     _Inout_ PIRP Irp
2135     );
2136 
2137 _Requires_lock_held_(_Global_critical_region_)
2138 NTSTATUS
2139 CdCommonCleanup (                           //  Implemented in Cleanup.c
2140     _Inout_ PIRP_CONTEXT IrpContext,
2141     _Inout_ PIRP Irp
2142     );
2143 
2144 _Requires_lock_held_(_Global_critical_region_)
2145 NTSTATUS
2146 CdCommonPnp (                               //  Implemented in Pnp.c
2147     _Inout_ PIRP_CONTEXT IrpContext,
2148     _Inout_ PIRP Irp
2149     );
2150 
2151 _Requires_lock_held_(_Global_critical_region_)
2152 NTSTATUS
2153 CdCommonShutdown (                         //  Implemented in Shutdown.c
2154     _Inout_ PIRP_CONTEXT IrpContext,
2155     _Inout_ PIRP Irp
2156     );
2157 
2158 
2159 
2160 //
2161 //  The following macros are used to establish the semantics needed
2162 //  to do a return from within a try-finally clause.  As a rule every
2163 //  try clause must end with a label call try_exit.  For example,
2164 //
2165 //      try {
2166 //              :
2167 //              :
2168 //
2169 //      try_exit: NOTHING;
2170 //      } finally {
2171 //
2172 //              :
2173 //              :
2174 //      }
2175 //
2176 //  Every return statement executed inside of a try clause should use the
2177 //  try_return macro.  If the compiler fully supports the try-finally construct
2178 //  then the macro should be
2179 //
2180 //      #define try_return(S)  { return(S); }
2181 //
2182 //  If the compiler does not support the try-finally construct then the macro
2183 //  should be
2184 //
2185 //      #define try_return(S)  { S; goto try_exit; }
2186 //
2187 
2188 #ifndef __REACTOS__
2189 #define try_return(S) { S; goto try_exit; }
2190 #define try_leave(S) { S; leave; }
2191 #else
2192 #define try_return(S) { S; goto try_exit; }
2193 #define try_leave(S) { S; _SEH2_LEAVE; }
2194 #endif
2195 
2196 //
2197 //  Encapsulate safe pool freeing
2198 //
2199 /* ReactOS Change: GCC "passing argument 1 of CdFreePool from incompatible pointer type" */
2200 #define CdFreePool(x) _CdFreePool((PVOID*)(x))
2201 
2202 static /* ReactOS Change: GCC "multiple definition" */
2203 INLINE
2204 VOID
2205 _CdFreePool(
2206     _Inout_ _At_(*Pool, __drv_freesMem(Mem) _Post_null_) PVOID *Pool
2207     )
2208 {
2209     if (*Pool != NULL) {
2210 
2211         ExFreePool(*Pool);
2212         *Pool = NULL;
2213     }
2214 }
2215 
2216 #ifdef CDFS_TELEMETRY_DATA
2217 
2218 //
2219 //  CDFS Telemetry.  Current implementation uses the Telemetry TraceLogging APIs.
2220 //
2221 //  The Telemetry TraceLoggingWrite() routines use a lot of stack space. We must
2222 //  therefor wrap all our telemetry points with our own routines, and add a guard to
2223 //  make sure there's enough stack space to call these routines.
2224 //
2225 //  These telemetry routines should not be called on high-performance code paths.
2226 //
2227 
2228 TRACELOGGING_DECLARE_PROVIDER( CdTelemetryProvider );
2229 
2230 VOID
2231 CdInitializeTelemetry (
2232     VOID
2233     );
2234 
2235 DECLSPEC_NOINLINE
2236 VOID
2237 CdTelemetryMount (
2238         __in PGUID VolumeGuid,
2239         __in NTSTATUS Status,
2240         __in PVCB Vcb
2241         );
2242 
2243 //
2244 //  Every additional argument passed to TraceLoggingWrite() consumes an additional
2245 //  16 to 32 bytes extra stack space. Having 512 bytes reserved space should be
2246 //  sufficient for up to 20 arguments or so. This will be less of course if our
2247 //  wrapper routines also declare their own local variables.
2248 //
2249 
2250 #define CDFS_TELEMETRY_STACK_THRESHOLD_DEFAULT  512    // for "small" telemetry points
2251 #define CDFS_TELEMETRY_STACK_THRESHOLD_LARGE    2048   // for "large" telemetry points
2252 
2253 INLINE
2254 BOOLEAN
2255 CdTelemetryGuard (
2256     __in ULONG StackSpaceNeeded )
2257 /*++
2258 
2259 Routine Description:
2260 
2261     This routine returns TRUE only when:
2262 
2263       1)  There is an ETW listener, AND
2264       2)  There is enough free stack space to safely call the Telemetry TraceLogging APIs
2265 
2266     We'll also count how many times there wasn't enough stack space, and include this
2267     value as part of the periodic cdfs Telemetry.
2268 
2269 Arguments:
2270 
2271     StackSpaceNeeded - Stack space needed in bytes
2272 
2273 --*/
2274 {
2275     ASSERT( IoGetRemainingStackSize() >= StackSpaceNeeded );
2276 
2277     if (CdTelemetryProvider->LevelPlus1 <= 5) {
2278 
2279         //
2280         //  Bail out early if there are no ETW listeners
2281         //
2282 
2283         return FALSE;
2284     }
2285 
2286     if (IoGetRemainingStackSize() < StackSpaceNeeded) {
2287 
2288         //
2289         //  Count how many times it was unsafe to generate telemetry because of
2290         //  not enough stack space.
2291         //
2292 
2293         InterlockedIncrement( &CdTelemetryData.MissedTelemetryPoints );
2294 
2295         return FALSE;
2296     }
2297 
2298     return TRUE;
2299 }
2300 
2301 #define CdTelemetryMountSafe( VolumeGuid, Status, Vcb ) \
2302     if (CdTelemetryGuard( CDFS_TELEMETRY_STACK_THRESHOLD_LARGE )) { \
2303         CdTelemetryMount( VolumeGuid, Status, Vcb ); \
2304     }
2305 
2306 #if DBG
2307 #define CDFS_TELEMETRY_PERIODIC_INTERVAL  CdTelemetryData.PeriodicInterval
2308 #else
2309 #define CDFS_TELEMETRY_PERIODIC_INTERVAL  INTERVAL_ONE_DAY
2310 #endif
2311 
2312 #else  // CDFS_TELEMETRY_DATA
2313 
2314 //
2315 //  When CDFS_TELEMETRY_DATA is not defined then the CdTelemetry___Safe() routines
2316 //  expand to nothing.  This minimizes the cdfs.sys binary footprint.  This also
2317 //  means that the places where these Safe() routines are called do not
2318 //  have to have to be surrounded by  #ifdef CDFS_TELEMETRY_DATA .. #endif
2319 //
2320 
2321 
2322 #define CdTelemetryMountSafe( ... )           NOTHING
2323 
2324 #endif  // CDFS_TELEMETRY_DATA
2325 
2326 #endif // _CDPROCS_
2327 
2328 
2329