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