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