ReactOS 0.4.16-dev-303-g11d5cb8
fsctrl.c
Go to the documentation of this file.
1/*++
2
3Copyright (c) 1989-2000 Microsoft Corporation
4
5Module Name:
6
7 FsCtrl.c
8
9Abstract:
10
11 This module implements the File System Control routines for Cdfs called
12 by the Fsd/Fsp dispatch drivers.
13
14
15--*/
16
17#include "cdprocs.h"
18
19//
20// The Bug check file id for this module
21//
22
23#define BugCheckFileId (CDFS_BUG_CHECK_FSCTRL)
24
25//
26// Local constants
27//
28
31
32//
33// Local support routines
34//
35
36_Requires_lock_held_(_Global_critical_region_)
38CdUserFsctl (
39 _Inout_ PIRP_CONTEXT IrpContext,
41 );
42
43VOID
45 _In_ PIRP_CONTEXT IrpContext,
46 _Inout_ PVCB OldVcb,
47 _Inout_ PVCB NewVcb,
48 _In_ PDEVICE_OBJECT DeviceObjectWeTalkTo
49 );
50
51_Requires_lock_held_(_Global_critical_region_)
53CdMountVolume (
54 _Inout_ PIRP_CONTEXT IrpContext,
56 );
57
58_Requires_lock_held_(_Global_critical_region_)
60CdVerifyVolume (
61 _Inout_ PIRP_CONTEXT IrpContext,
63 );
64
65_Requires_lock_held_(_Global_critical_region_)
67CdOplockRequest (
68 _Inout_ PIRP_CONTEXT IrpContext,
70 );
71
72_Requires_lock_held_(_Global_critical_region_)
74CdLockVolume (
75 _Inout_ PIRP_CONTEXT IrpContext,
77 );
78
79_Requires_lock_held_(_Global_critical_region_)
81CdUnlockVolume (
82 _Inout_ PIRP_CONTEXT IrpContext,
84 );
85
86_Requires_lock_held_(_Global_critical_region_)
88CdDismountVolume (
89 _Inout_ PIRP_CONTEXT IrpContext,
91 );
92
95 _Inout_ PIRP_CONTEXT IrpContext,
97 );
98
101 _Inout_ PIRP_CONTEXT IrpContext,
103 );
104
107 _Inout_ PIRP_CONTEXT IrpContext,
109 );
110
111_Requires_lock_held_(_Global_critical_region_)
113CdInvalidateVolumes (
114 _Inout_ PIRP_CONTEXT IrpContext,
116 );
117
120 _Inout_ PIRP_CONTEXT IrpContext,
122 );
123
124_Requires_lock_held_(_Global_critical_region_)
125VOID
126CdScanForDismountedVcb (
127 _Inout_ PIRP_CONTEXT IrpContext
128 );
129
130_Success_(return != FALSE)
132CdFindPrimaryVd (
133 _In_ PIRP_CONTEXT IrpContext,
136 _In_ ULONG BlockFactor,
137 _In_ BOOLEAN ReturnOnError,
138 _In_ BOOLEAN VerifyVolume
139 );
140
141_Success_(return != FALSE) BOOLEAN
142CdIsRemount (
143 _In_ PIRP_CONTEXT IrpContext,
144 _In_ PVCB Vcb,
145 _Out_ PVCB *OldVcb
146 );
147
148VOID
150 _In_ PIRP_CONTEXT IrpContext,
151 _In_ PVCB Vcb,
153 _In_ BOOLEAN VerifyVolume
154 );
155
156#ifdef ALLOC_PRAGMA
157#pragma alloc_text(PAGE, CdCommonFsControl)
158#pragma alloc_text(PAGE, CdDismountVolume)
159#pragma alloc_text(PAGE, CdFindActiveVolDescriptor)
160#pragma alloc_text(PAGE, CdFindPrimaryVd)
161#pragma alloc_text(PAGE, CdIsPathnameValid)
162#pragma alloc_text(PAGE, CdIsRemount)
163#pragma alloc_text(PAGE, CdIsVolumeDirty)
164#pragma alloc_text(PAGE, CdIsVolumeMounted)
165#pragma alloc_text(PAGE, CdLockVolume)
166#pragma alloc_text(PAGE, CdMountVolume)
167#pragma alloc_text(PAGE, CdOplockRequest)
168#pragma alloc_text(PAGE, CdAllowExtendedDasdIo)
169#pragma alloc_text(PAGE, CdScanForDismountedVcb)
170#pragma alloc_text(PAGE, CdUnlockVolume)
171#pragma alloc_text(PAGE, CdUserFsctl)
172#pragma alloc_text(PAGE, CdVerifyVolume)
173#endif
174
175
176//
177// Local support routine
178//
179
180_Requires_lock_held_(_Global_critical_region_)
181_Requires_lock_held_(Vcb->VcbResource)
183CdLockVolumeInternal (
184 _In_ PIRP_CONTEXT IrpContext,
187 )
188
189/*++
190
191Routine Description:
192
193 This routine performs the actual lock volume operation. It will be called
194 by anyone wishing to try to protect the volume for a long duration. PNP
195 operations are such a user.
196
197 The volume must be held exclusive by the caller.
198
199Arguments:
200
201 Vcb - The volume being locked.
202
203 FileObject - File corresponding to the handle locking the volume. If this
204 is not specified, a system lock is assumed.
205
206Return Value:
207
208 NTSTATUS - The return status for the operation
209
210--*/
211
212{
214 KIRQL SavedIrql;
216 ULONG RemainingUserReferences = (FileObject? 1: 0);
217
218 //
219 // The cleanup count for the volume only reflects the fileobject that
220 // will lock the volume. Otherwise, we must fail the request.
221 //
222 // Since the only cleanup is for the provided fileobject, we will try
223 // to get rid of all of the other user references. If there is only one
224 // remaining after the purge then we can allow the volume to be locked.
225 //
226
227 CdPurgeVolume( IrpContext, Vcb, FALSE );
228
229 //
230 // Now back out of our synchronization and wait for the lazy writer
231 // to finish off any lazy closes that could have been outstanding.
232 //
233 // Since we purged, we know that the lazy writer will issue all
234 // possible lazy closes in the next tick - if we hadn't, an otherwise
235 // unopened file with a large amount of dirty data could have hung
236 // around for a while as the data trickled out to the disk.
237 //
238 // This is even more important now since we send notification to
239 // alert other folks that this style of check is about to happen so
240 // that they can close their handles. We don't want to enter a fast
241 // race with the lazy writer tearing down his references to the file.
242 //
243
244 CdReleaseVcb( IrpContext, Vcb );
245
247
248 //
249 // This is intentional. If we were able to get the Vcb before, just
250 // wait for it and take advantage of knowing that it is OK to leave
251 // the flag up.
252 //
253
254 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
255 CdAcquireVcbExclusive( IrpContext, Vcb, FALSE );
256
257 if (!NT_SUCCESS( Status )) {
258
259 return Status;
260 }
261
262 CdFspClose( Vcb );
263
264 //
265 // If the volume is already explicitly locked then fail. We use the
266 // Vpb locked flag as an 'explicit lock' flag in the same way as Fat.
267 //
268
269 IoAcquireVpbSpinLock( &SavedIrql );
270
271 if (!FlagOn( Vcb->Vpb->Flags, VPB_LOCKED ) &&
272 (Vcb->VcbCleanup == RemainingUserReferences) &&
273 (Vcb->VcbUserReference == CDFS_RESIDUAL_USER_REFERENCE + RemainingUserReferences)) {
274
275 SetFlag( Vcb->VcbState, VCB_STATE_LOCKED );
276 SetFlag( Vcb->Vpb->Flags, VPB_LOCKED);
277 Vcb->VolumeLockFileObject = FileObject;
278 FinalStatus = STATUS_SUCCESS;
279 }
280
281 IoReleaseVpbSpinLock( SavedIrql );
282
283 return FinalStatus;
284}
285
286
289 _In_ PIRP_CONTEXT IrpContext,
292 )
293
294/*++
295
296Routine Description:
297
298 This routine performs the actual unlock volume operation.
299
300 The volume must be held exclusive by the caller.
301
302Arguments:
303
304 Vcb - The volume being locked.
305
306 FileObject - File corresponding to the handle locking the volume. If this
307 is not specified, a system lock is assumed.
308
309Return Value:
310
311 NTSTATUS - The return status for the operation
312
313 Attempting to remove a system lock that did not exist is OK.
314
315--*/
316
317{
319 KIRQL SavedIrql;
320
321 UNREFERENCED_PARAMETER( IrpContext );
322
323 //
324 // Note that we check the VPB_LOCKED flag here rather than the Vcb
325 // lock flag. The Vpb flag is only set for an explicit lock request, not
326 // for the implicit lock obtained on a volume open with zero share mode.
327 //
328
329 IoAcquireVpbSpinLock( &SavedIrql );
330
331 if (FlagOn(Vcb->Vpb->Flags, VPB_LOCKED) &&
332 (FileObject == Vcb->VolumeLockFileObject)) {
333
334 ClearFlag( Vcb->VcbState, VCB_STATE_LOCKED );
335 ClearFlag( Vcb->Vpb->Flags, VPB_LOCKED);
336 Vcb->VolumeLockFileObject = NULL;
338 }
339
340 IoReleaseVpbSpinLock( SavedIrql );
341
342 return Status;
343}
344
345
346
347_Requires_lock_held_(_Global_critical_region_)
349CdCommonFsControl (
350 _Inout_ PIRP_CONTEXT IrpContext,
352 )
353
354/*++
355
356Routine Description:
357
358 This is the common routine for doing FileSystem control operations called
359 by both the fsd and fsp threads
360
361Arguments:
362
363 Irp - Supplies the Irp to process
364
365Return Value:
366
367 NTSTATUS - The return status for the operation
368
369--*/
370
371{
374
375 PAGED_CODE();
376
377 //
378 // We know this is a file system control so we'll case on the
379 // minor function, and call a internal worker routine to complete
380 // the irp.
381 //
382
383 switch (IrpSp->MinorFunction) {
384
386
387 Status = CdUserFsctl( IrpContext, Irp );
388 break;
389
391
392 Status = CdMountVolume( IrpContext, Irp );
393 break;
394
396
397 Status = CdVerifyVolume( IrpContext, Irp );
398 break;
399
400 default:
401
404 break;
405 }
406
407 return Status;
408}
409
410
411//
412// Local support routine
413//
414
415_Requires_lock_held_(_Global_critical_region_)
417CdUserFsctl (
418 _Inout_ PIRP_CONTEXT IrpContext,
420 )
421/*++
422
423Routine Description:
424
425 This is the common routine for implementing the user's requests made
426 through NtFsControlFile.
427
428Arguments:
429
430 Irp - Supplies the Irp being processed
431
432Return Value:
433
434 NTSTATUS - The return status for the operation
435
436--*/
437
438{
441
442 PAGED_CODE();
443
444 //
445 // Case on the control code.
446 //
447
448 switch ( IrpSp->Parameters.FileSystemControl.FsControlCode ) {
449
458
459 Status = CdOplockRequest( IrpContext, Irp );
460 break;
461
462 case FSCTL_LOCK_VOLUME :
463
464 Status = CdLockVolume( IrpContext, Irp );
465 break;
466
468
469 Status = CdUnlockVolume( IrpContext, Irp );
470 break;
471
473
474 Status = CdDismountVolume( IrpContext, Irp );
475 break;
476
478
479 Status = CdIsVolumeDirty( IrpContext, Irp );
480 break;
481
483
484 Status = CdIsVolumeMounted( IrpContext, Irp );
485 break;
486
488
489 Status = CdIsPathnameValid( IrpContext, Irp );
490 break;
491
493
494 Status = CdInvalidateVolumes( IrpContext, Irp );
495 break;
496
498
499 Status = CdAllowExtendedDasdIo( IrpContext, Irp );
500 break;
501
502 //
503 // We don't support any of the known or unknown requests.
504 //
505
506 default:
507
510 break;
511 }
512
513 return Status;
514}
515
516
517VOID
519 _In_ PIRP_CONTEXT IrpContext,
520 _Inout_ PVCB OldVcb,
521 _Inout_ PVCB NewVcb,
522 _In_ PDEVICE_OBJECT DeviceObjectWeTalkTo
523 )
524{
525 KIRQL SavedIrql;
526 ULONG Index;
528
529 UNREFERENCED_PARAMETER( IrpContext );
530
531 ObDereferenceObject( OldVcb->TargetDeviceObject );
532
533 IoAcquireVpbSpinLock( &SavedIrql );
534
535#ifdef _MSC_VER
536#pragma prefast(suppress: 28175, "this is a filesystem driver, touching the vpb is allowed")
537#endif
538 NewVcb->Vpb->RealDevice->Vpb = OldVcb->Vpb;
539
540 OldVcb->Vpb->RealDevice = NewVcb->Vpb->RealDevice;
541 OldVcb->TargetDeviceObject = DeviceObjectWeTalkTo;
542
544 CdUpdateMediaChangeCount( OldVcb, NewVcb->MediaChangeCount);
545
546 ClearFlag( OldVcb->VcbState, VCB_STATE_VPB_NOT_ON_DEVICE);
547
548 Buffer = OldVcb->SectorCacheBuffer = NewVcb->SectorCacheBuffer;
549 NewVcb->SectorCacheBuffer = NULL;
550
551 if (NULL != Buffer) {
552
553 for (Index = 0; Index < CD_SEC_CACHE_CHUNKS; Index++) {
554
555 OldVcb->SecCacheChunks[ Index].Buffer = Buffer;
556 OldVcb->SecCacheChunks[ Index].BaseLbn = (ULONG)-1;
557
559 }
560 }
561
562 IoReleaseVpbSpinLock( SavedIrql );
563}
564
565
566//
567// Local support routine
568//
569
570_Requires_lock_held_(_Global_critical_region_)
572CdMountVolume (
573 _Inout_ PIRP_CONTEXT IrpContext,
575 )
576
577/*++
578
579Routine Description:
580
581 This routine performs the mount volume operation. It is responsible for
582 either completing of enqueuing the input Irp.
583
584 Its job is to verify that the volume denoted in the IRP is a Cdrom volume,
585 and create the VCB and root DCB structures. The algorithm it
586 uses is essentially as follows:
587
588 1. Create a new Vcb Structure, and initialize it enough to do I/O
589 through the on-disk volume descriptors.
590
591 2. Read the disk and check if it is a Cdrom volume.
592
593 3. If it is not a Cdrom volume then delete the Vcb and
594 complete the IRP back with an appropriate status.
595
596 4. Check if the volume was previously mounted and if it was then do a
597 remount operation. This involves deleting the VCB, hook in the
598 old VCB, and complete the IRP.
599
600 5. Otherwise create a Vcb and root DCB for each valid volume descriptor.
601
602Arguments:
603
604 Irp - Supplies the Irp to process
605
606Return Value:
607
608 NTSTATUS - The return status for the operation
609
610--*/
611
612{
614
616 PVCB Vcb = NULL;
617 PVCB OldVcb;
619
620 BOOLEAN FoundPvd = FALSE;
621 BOOLEAN SetDoVerifyOnFail;
622
624 PDEVICE_OBJECT DeviceObjectWeTalkTo = IrpSp->Parameters.MountVolume.DeviceObject;
626
627 PFILE_OBJECT FileObjectToNotify = NULL;
628
629 ULONG BlockFactor;
630 DISK_GEOMETRY DiskGeometry;
631
633
635
636 PCHAR RawIsoVd = NULL;
637
638 PCDROM_TOC_LARGE CdromToc = NULL;
639 ULONG TocLength = 0;
640 ULONG TocTrackCount = 0;
641 ULONG TocDiskFlags = 0;
642 ULONG MediaChangeCount = 0;
643
644#ifdef __REACTOS__
645 DEVICE_TYPE FilesystemDeviceType;
646#endif
647
648#ifdef CDFS_TELEMETRY_DATA
649 GUID VolumeGuid;
650 GUID VolumeCorrelationId = { 0 };
651#endif
652
653 PAGED_CODE();
654
655 //
656 // Check that we are talking to a Cdrom device. This request should
657 // always be waitable.
658 //
659
660#ifdef __REACTOS__
661 if (IrpSp->DeviceObject == CdData.HddFileSystemDeviceObject) {
662 FilesystemDeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
663 } else {
664#endif
665 NT_ASSERT( Vpb->RealDevice->DeviceType == FILE_DEVICE_CD_ROM );
666#ifdef __REACTOS__
667 FilesystemDeviceType = FILE_DEVICE_CD_ROM_FILE_SYSTEM;
668 }
669#endif
670 NT_ASSERT( FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT ));
671
672#ifdef CDFS_TELEMETRY_DATA
673 //
674 // We don't want a bogus VolumeGuid to show up in our telemetry
675 //
676
677 RtlZeroMemory( &VolumeGuid, sizeof(GUID) );
678
679#endif
680
681 //
682 // Update the real device in the IrpContext from the Vpb. There was no available
683 // file object when the IrpContext was created.
684 //
685
686 IrpContext->RealDevice = Vpb->RealDevice;
687
688 SetDoVerifyOnFail = CdRealDevNeedsVerify( IrpContext->RealDevice);
689
690 //
691 // Check if we have disabled the mount process.
692 //
693
694 if (CdDisable) {
695
698 }
699
700 //
701 // If we've shutdown disallow further mounts.
702 //
703
705
708 }
709
710 //
711 // Do a CheckVerify here to lift the MediaChange ticker from the driver
712 //
713
714 Status = CdPerformDevIoCtrl( IrpContext,
715#ifndef __REACTOS__
717#else
719#endif
720 DeviceObjectWeTalkTo,
721 &MediaChangeCount,
722 sizeof(ULONG),
723 FALSE,
724 TRUE,
725 &Iosb );
726
727 if (!NT_SUCCESS( Status )) {
728
729 CdCompleteRequest( IrpContext, Irp, Status );
730 return Status;
731 }
732
733 if (Iosb.Information != sizeof(ULONG)) {
734
735 //
736 // Be safe about the count in case the driver didn't fill it in
737 //
738
739 MediaChangeCount = 0;
740 }
741
742 //
743 // Now let's make Jeff delirious and call to get the disk geometry. This
744 // will fix the case where the first change line is swallowed.
745 //
746
747 Status = CdPerformDevIoCtrl( IrpContext,
748#ifndef __REACTOS__
750#else
752#endif
753 DeviceObjectWeTalkTo,
754 &DiskGeometry,
755 sizeof( DISK_GEOMETRY ),
756 FALSE,
757 TRUE,
758 NULL );
759
760 //
761 // Return insufficient sources to our caller.
762 //
763
765
766 CdCompleteRequest( IrpContext, Irp, Status );
767 return Status;
768 }
769
770 //
771 // Now check the block factor for addressing the volume descriptors.
772 // If the call for the disk geometry failed then assume there is one
773 // block per sector.
774 //
775
776 BlockFactor = 1;
777
778 if (NT_SUCCESS( Status ) &&
779 (DiskGeometry.BytesPerSector != 0) &&
780 (DiskGeometry.BytesPerSector < SECTOR_SIZE)) {
781
782 BlockFactor = SECTOR_SIZE / DiskGeometry.BytesPerSector;
783 }
784
785 //
786 // Acquire the global resource to do mount operations.
787 //
788
789 CdAcquireCdData( IrpContext );
790
791 //
792 // Use a try-finally to facilitate cleanup.
793 //
794
795 _SEH2_TRY {
796
797 //
798 // Allocate a buffer to query the TOC.
799 //
800
802 sizeof( CDROM_TOC_LARGE ),
804
805 RtlZeroMemory( CdromToc, sizeof( CDROM_TOC_LARGE ));
806
807 //
808 // Do a quick check to see if there any Vcb's which can be removed.
809 //
810
811 CdScanForDismountedVcb( IrpContext );
812
813 //
814 // Get our device object and alignment requirement.
815 //
816
818 sizeof( VOLUME_DEVICE_OBJECT ) - sizeof( DEVICE_OBJECT ),
819 NULL,
820#ifndef __REACTOS__
822#else
823 FilesystemDeviceType,
824#endif
825 0,
826 FALSE,
827 (PDEVICE_OBJECT *) &VolDo );
828
829 if (!NT_SUCCESS( Status )) { try_leave( Status ); }
830
831 //
832 // Our alignment requirement is the larger of the processor alignment requirement
833 // already in the volume device object and that in the DeviceObjectWeTalkTo
834 //
835
836 if (DeviceObjectWeTalkTo->AlignmentRequirement > VolDo->DeviceObject.AlignmentRequirement) {
837
838 VolDo->DeviceObject.AlignmentRequirement = DeviceObjectWeTalkTo->AlignmentRequirement;
839 }
840
841 //
842 // We must initialize the stack size in our device object before
843 // the following reads, because the I/O system has not done it yet.
844 //
845
846 ((PDEVICE_OBJECT) VolDo)->StackSize = (CCHAR) (DeviceObjectWeTalkTo->StackSize + 1);
847 StackSize = ((PDEVICE_OBJECT) VolDo)->StackSize;
848
850
851 //
852 // Initialize the overflow queue for the volume
853 //
854
855 VolDo->OverflowQueueCount = 0;
857
858 VolDo->PostedRequestCount = 0;
860
861 //
862 // Let's query for the Toc now and handle any error we get from this operation.
863 //
864
865 Status = CdProcessToc( IrpContext,
866 DeviceObjectWeTalkTo,
867 CdromToc,
868 &TocLength,
869 &TocTrackCount,
870 &TocDiskFlags );
871
872 //
873 // If we failed to read the TOC, then bail out. Probably blank media.
874 //
875
876 if (Status != STATUS_SUCCESS) {
877
878#ifdef __REACTOS__
879
880 //
881 // Don't bail out if that was a disk based ISO image, it is legit
882 //
883
884 if (FilesystemDeviceType == FILE_DEVICE_DISK_FILE_SYSTEM) {
885 CdFreePool( &CdromToc );
887 } else {
888#endif
889 try_leave( Status );
890#ifdef __REACTOS__
891 }
892#endif
893 }
894
895 //
896 // Now before we can initialize the Vcb we need to set up the
897 // device object field in the VPB to point to our new volume device
898 // object.
899 //
900
901 Vpb->DeviceObject = (PDEVICE_OBJECT) VolDo;
902
903 //
904 // Initialize the Vcb. This routine will raise on an allocation
905 // failure.
906 //
907
908 CdInitializeVcb( IrpContext,
909 &VolDo->Vcb,
910 DeviceObjectWeTalkTo,
911 Vpb,
912 CdromToc,
913 TocLength,
914 TocTrackCount,
915 TocDiskFlags,
916 BlockFactor,
917 MediaChangeCount );
918
919 //
920 // Show that we initialized the Vcb and can cleanup with the Vcb.
921 //
922
923 Vcb = &VolDo->Vcb;
924 VolDo = NULL;
925 Vpb = NULL;
926 CdromToc = NULL;
927
928#ifdef CDFS_TELEMETRY_DATA
929
930 //
931 // Initialize the volume guid.
932 //
933
934 if (NT_SUCCESS( IoVolumeDeviceToGuid( Vcb->TargetDeviceObject, &VolumeGuid ))) {
935
936 //
937 // We got a GUID, set it in the Telemetry structure
938 //
939
940 RtlCopyMemory( &CdTelemetryData.VolumeGuid, &VolumeGuid, sizeof(GUID) );
941 }
942
943 //
944 // Initialize the correlation ID.
945 //
946
947 if (NT_SUCCESS( FsRtlVolumeDeviceToCorrelationId( Vcb->TargetDeviceObject, &VolumeCorrelationId ) )) {
948
949 //
950 // Stash a copy away in the VCB.
951 //
952
953 RtlCopyMemory( &Vcb->VolumeCorrelationId, &VolumeCorrelationId, sizeof( GUID ) );
954 }
955
956#endif // CDFS_TELEMETRY_DATA
957
958 // Lock object is acquired and released using internal state
960
961 //
962 // Store the Vcb in the IrpContext as we didn't have one before.
963 //
964
965 IrpContext->Vcb = Vcb;
966
967 CdAcquireVcbExclusive( IrpContext, Vcb, FALSE );
968
969 //
970 // Let's reference the Vpb to make sure we are the one to
971 // have the last dereference.
972 //
973
974 Vcb->Vpb->ReferenceCount += 1;
975
976 //
977 // Clear the verify bit for the start of mount.
978 //
979
980 CdMarkRealDevVerifyOk( Vcb->Vpb->RealDevice);
981
982 if (!FlagOn( Vcb->VcbState, VCB_STATE_AUDIO_DISK)) {
983
984 //
985 // Allocate a buffer to read in the volume descriptors. We allocate a full
986 // page to make sure we don't hit any alignment problems.
987 //
988
991 TAG_VOL_DESC );
992
993 //
994 // Try to find the primary volume descriptor.
995 //
996
997 FoundPvd = CdFindPrimaryVd( IrpContext,
998 Vcb,
999 RawIsoVd,
1000 BlockFactor,
1001 TRUE,
1002 FALSE );
1003
1004 if (!FoundPvd) {
1005
1006 //
1007 // We failed to find a valid VD in the data track, but there were also
1008 // audio tracks on this disc, so we'll try to mount it as an audio CD.
1009 // Since we're always last in the mount order, we won't be preventing
1010 // any other FS from trying to mount the data track. However if the
1011 // data track was at the start of the disc, then we abort, to avoid
1012 // having to filter it from our synthesised directory listing later. We
1013 // already filtered off any data track at the end.
1014 //
1015
1016 if (!(TocDiskFlags & CDROM_DISK_AUDIO_TRACK) ||
1017 BooleanFlagOn( Vcb->CdromToc->TrackData[0].Control, TOC_DATA_TRACK)) {
1018
1020 }
1021
1023
1024 CdFreePool( &RawIsoVd );
1025 RawIsoVd = NULL;
1026 }
1027 }
1029 //
1030 // Look and see if there is a secondary volume descriptor we want to
1031 // use.
1032 //
1033
1034 if (FoundPvd) {
1035
1036 //
1037 // Store the primary volume descriptor in the second half of
1038 // RawIsoVd. Then if our search for a secondary fails we can
1039 // recover this immediately.
1040 //
1041
1042 RtlCopyMemory( Add2Ptr( RawIsoVd, SECTOR_SIZE, PVOID ),
1043 RawIsoVd,
1044 SECTOR_SIZE );
1045
1046 //
1047 // We have the initial volume descriptor. Locate a secondary
1048 // volume descriptor if present.
1049 //
1050
1051 CdFindActiveVolDescriptor( IrpContext,
1052 Vcb,
1053 RawIsoVd,
1054 FALSE);
1055 }
1056
1057 //
1058 // Allocate a block cache to speed directory operations. We can't
1059 // use the cache if there is any chance the volume has link blocks
1060 // in the data area (i.e. was packet written and then finalized to
1061 // Joliet/9660). So we simply only allow the cache to operate on
1062 // media with a single track - since we're really targetting pressed
1063 // installation media here. We can't be more precise, since D/CD-ROM
1064 // drives don't support READ_TRACK_INFO, which is the only way for
1065 // certain to know whether or not a track was packet written.
1066 //
1067
1068 if (!FlagOn( Vcb->VcbState, VCB_STATE_AUDIO_DISK) &&
1069#ifndef __REACTOS__
1070 ((Vcb->CdromToc->LastTrack - Vcb->CdromToc->FirstTrack) == 0)) {
1071#else
1072 ((FilesystemDeviceType == FILE_DEVICE_DISK_FILE_SYSTEM) ||
1073 ((Vcb->CdromToc->LastTrack - Vcb->CdromToc->FirstTrack) == 0))) {
1074#endif
1075
1076 ULONG Index;
1077 PUCHAR Buffer;
1078
1079 Buffer =
1080 Vcb->SectorCacheBuffer = FsRtlAllocatePool( CdPagedPool,
1083 SECTOR_SIZE);
1084
1085 for (Index = 0; Index < (ULONG)CD_SEC_CACHE_CHUNKS; Index++) {
1086
1087 Vcb->SecCacheChunks[ Index].Buffer = Buffer;
1088 Vcb->SecCacheChunks[ Index].BaseLbn = (ULONG)-1;
1089
1091 }
1092
1093 Vcb->SectorCacheIrp = IoAllocateIrp( StackSize, FALSE);
1094
1095 if (Vcb->SectorCacheIrp == NULL) {
1096
1098 }
1099
1100 IoInitializeIrp( Vcb->SectorCacheIrp,
1102 (CCHAR)StackSize);
1103
1104 KeInitializeEvent( &Vcb->SectorCacheEvent, SynchronizationEvent, FALSE);
1105 ExInitializeResourceLite( &Vcb->SectorCacheResource);
1106 }
1107
1108 //
1109 // Check if this is a remount operation. If so then clean up
1110 // the data structures passed in and created here.
1111 //
1112
1113 if (CdIsRemount( IrpContext, Vcb, &OldVcb )) {
1114
1115 NT_ASSERT( NULL != OldVcb->SwapVpb );
1116
1117 //
1118 // Link the old Vcb to point to the new device object that we
1119 // should be talking to, dereferencing the previous. Call a
1120 // nonpaged routine to do this since we take the Vpb spinlock.
1121 //
1122
1123 CdReMountOldVcb( IrpContext,
1124 OldVcb,
1125 Vcb,
1126 DeviceObjectWeTalkTo);
1127
1128 //
1129 // See if we will need to provide notification of the remount. This is the readonly
1130 // filesystem's form of dismount/mount notification - we promise that whenever a
1131 // volume is "dismounted", that a mount notification will occur when it is revalidated.
1132 // Note that we do not send mount on normal remounts - that would duplicate the media
1133 // arrival notification of the device driver.
1134 //
1135
1136 if (FlagOn( OldVcb->VcbState, VCB_STATE_NOTIFY_REMOUNT )) {
1137
1139
1140 FileObjectToNotify = OldVcb->RootIndexFcb->FileObject;
1141 ObReferenceObject( FileObjectToNotify );
1142 }
1143
1145 }
1146
1147 //
1148 // This is a new mount. Go ahead and initialize the
1149 // Vcb from the volume descriptor.
1150 //
1151
1152 CdUpdateVcbFromVolDescriptor( IrpContext,
1153 Vcb,
1154 RawIsoVd );
1155
1156 //
1157 // Drop an extra reference on the root dir file so we'll be able to send
1158 // notification.
1159 //
1160
1161 if (Vcb->RootIndexFcb) {
1162
1163 FileObjectToNotify = Vcb->RootIndexFcb->FileObject;
1164 ObReferenceObject( FileObjectToNotify );
1165 }
1166
1167 //
1168 // Now check the maximum transfer limits on the device in case we
1169 // get raw reads on this volume.
1170 //
1171
1172 Status = CdPerformDevIoCtrl( IrpContext,
1174 DeviceObjectWeTalkTo,
1175 &Capabilities,
1176 sizeof( IO_SCSI_CAPABILITIES ),
1177 FALSE,
1178 TRUE,
1179 NULL );
1180
1181 if (NT_SUCCESS(Status)) {
1182
1183 Vcb->MaximumTransferRawSectors = Capabilities.MaximumTransferLength / RAW_SECTOR_SIZE;
1184 Vcb->MaximumPhysicalPages = Capabilities.MaximumPhysicalPages;
1185
1186 } else {
1187
1188 //
1189 // This should never happen, but we can safely assume 64k and 16 pages.
1190 //
1191
1192 Vcb->MaximumTransferRawSectors = (64 * 1024) / RAW_SECTOR_SIZE;
1193 Vcb->MaximumPhysicalPages = 16;
1194 }
1195
1196 //
1197 // The new mount is complete. Remove the additional references on this
1198 // Vcb and the device we are mounted on top of.
1199 //
1200
1201 Vcb->VcbReference -= CDFS_RESIDUAL_REFERENCE;
1202 NT_ASSERT( Vcb->VcbReference == CDFS_RESIDUAL_REFERENCE );
1203
1204 ObDereferenceObject( Vcb->TargetDeviceObject );
1205
1207
1208 CdReleaseVcb( IrpContext, Vcb );
1209 Vcb = NULL;
1210
1212
1213 } _SEH2_FINALLY {
1214
1215 //
1216 // Free the TOC buffer if not in the Vcb.
1217 //
1218
1219 if (CdromToc != NULL) {
1220
1221 CdFreePool( &CdromToc );
1222 }
1223
1224 //
1225 // Free the sector buffer if allocated.
1226 //
1227
1228 if (RawIsoVd != NULL) {
1229
1230 CdFreePool( &RawIsoVd );
1231 }
1232
1233 //
1234 // If we are not mounting the device, then set the verify bit again.
1235 //
1236
1238 SetDoVerifyOnFail) {
1239
1240 CdMarkRealDevForVerify( IrpContext->RealDevice);
1241 }
1242
1243 //
1244 // If we didn't complete the mount then cleanup any remaining structures.
1245 //
1246
1247 if (Vpb != NULL) { Vpb->DeviceObject = NULL; }
1248
1249 if (Vcb != NULL) {
1250
1251 //
1252 // Make sure there is no Vcb in the IrpContext since it could go away
1253 //
1254
1255 IrpContext->Vcb = NULL;
1256
1257 Vcb->VcbReference -= CDFS_RESIDUAL_REFERENCE;
1258
1259 if (CdDismountVcb( IrpContext, Vcb )) {
1260
1261 CdReleaseVcb( IrpContext, Vcb );
1262 }
1263
1264 } else if (VolDo != NULL) {
1265
1266 IoDeleteDevice( (PDEVICE_OBJECT) VolDo );
1267 }
1268
1269 //
1270 // Release the global resource.
1271 //
1272
1273 CdReleaseCdData( IrpContext );
1274 } _SEH2_END;
1275
1276 //
1277 // Now send mount notification.
1278 //
1279
1280 if (FileObjectToNotify) {
1281
1282 FsRtlNotifyVolumeEvent( FileObjectToNotify, FSRTL_VOLUME_MOUNT );
1283 ObDereferenceObject( FileObjectToNotify );
1284 }
1285
1286#ifdef CDFS_TELEMETRY_DATA
1287
1288 //
1289 // Send Telemetry
1290 //
1291
1292 CdTelemetryMountSafe( &VolumeCorrelationId, STATUS_SUCCESS, Vcb );
1293
1294#endif
1295
1296 //
1297 // Complete the request if no exception.
1298 //
1299
1300 CdCompleteRequest( IrpContext, Irp, Status );
1301 return Status;
1302}
1303
1304
1305//
1306// Local support routine
1307//
1308
1309_Requires_lock_held_(_Global_critical_region_)
1311CdVerifyVolume (
1312 _Inout_ PIRP_CONTEXT IrpContext,
1314 )
1315
1316/*++
1317
1318Routine Description:
1319
1320 This routine performs the verify volume operation. It is responsible for
1321 either completing of enqueuing the input Irp.
1322
1323Arguments:
1324
1325 Irp - Supplies the Irp to process
1326
1327Return Value:
1328
1329 NTSTATUS - The return status for the operation
1330
1331--*/
1332
1333{
1336 PVCB Vcb = &((PVOLUME_DEVICE_OBJECT) IrpSp->Parameters.VerifyVolume.DeviceObject)->Vcb;
1337
1338 PCHAR RawIsoVd = NULL;
1339
1340 PCDROM_TOC_LARGE CdromToc = NULL;
1341 ULONG TocLength = 0;
1342 ULONG TocTrackCount = 0;
1343 ULONG TocDiskFlags = 0;
1344
1345 ULONG MediaChangeCount = Vcb->MediaChangeCount;
1346
1347 PFILE_OBJECT FileObjectToNotify = NULL;
1348
1349 BOOLEAN ReturnError;
1350 BOOLEAN ReleaseVcb = FALSE;
1351
1353
1354 STRING AnsiLabel;
1355 UNICODE_STRING UnicodeLabel;
1356
1357 WCHAR VolumeLabel[ VOLUME_ID_LENGTH ];
1358 ULONG VolumeLabelLength;
1359
1360 ULONG Index;
1361
1363
1364 PAGED_CODE();
1365
1366 //
1367 // We check that we are talking to a Cdrom device.
1368 //
1369
1370 NT_ASSERT( Vpb->RealDevice->DeviceType == FILE_DEVICE_CD_ROM );
1371 NT_ASSERT( FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT ));
1372
1373 //
1374 // Update the real device in the IrpContext from the Vpb. There was no available
1375 // file object when the IrpContext was created.
1376 //
1377
1378 IrpContext->RealDevice = Vpb->RealDevice;
1379
1380 //
1381 // Acquire the global resource to synchronise against mounts and teardown,
1382 // finally clause releases.
1383 //
1384
1385 CdAcquireCdData( IrpContext );
1386
1387 _SEH2_TRY {
1388
1389 CdAcquireVcbExclusive( IrpContext, Vcb, FALSE );
1390 ReleaseVcb = TRUE;
1391
1392 //
1393 // Check to see if the volume is eligible for verification.
1394 //
1395
1396 if ((Vcb->VcbCondition == VcbInvalid) ||
1397 (Vcb->VcbCondition == VcbDismountInProgress)) {
1398
1400 }
1401
1402 //
1403 // Verify that there is a disk here.
1404 //
1405
1406 Status = CdPerformDevIoCtrl( IrpContext,
1408 Vcb->TargetDeviceObject,
1409 &MediaChangeCount,
1410 sizeof(ULONG),
1411 FALSE,
1412 TRUE,
1413 &Iosb );
1414
1415 if (!NT_SUCCESS( Status )) {
1416
1417 //
1418 // If we will allow a raw mount then return WRONG_VOLUME to
1419 // allow the volume to be mounted by raw.
1420 //
1421
1423
1425 }
1426
1427 try_return( Status );
1428 }
1429
1430 if (Iosb.Information != sizeof(ULONG)) {
1431
1432 //
1433 // Be safe about the count in case the driver didn't fill it in
1434 //
1435
1436 MediaChangeCount = 0;
1437 }
1438
1439 //
1440 // Verify that the device actually saw a change. If the driver does not
1441 // support the MCC, then we must verify the volume in any case.
1442 //
1443
1444 if (MediaChangeCount == 0 ||
1445 (Vcb->MediaChangeCount != MediaChangeCount)) {
1446
1447 //
1448 // Allocate a buffer to query the TOC.
1449 //
1450
1452 sizeof( CDROM_TOC_LARGE ),
1453 TAG_CDROM_TOC );
1454
1455 RtlZeroMemory( CdromToc, sizeof( CDROM_TOC_LARGE ));
1456
1457 //
1458 // Let's query for the Toc now and handle any error we get from this operation.
1459 //
1460
1461 Status = CdProcessToc( IrpContext,
1462 Vcb->TargetDeviceObject,
1463 CdromToc,
1464 &TocLength,
1465 &TocTrackCount,
1466 &TocDiskFlags );
1467
1468 //
1469 // If we failed to read the TOC, then give up now. Drives will fail
1470 // a TOC read on, for example, erased CD-RW media.
1471 //
1472
1473 if (Status != STATUS_SUCCESS) {
1474
1475 //
1476 // For any errors other than no media and not ready, commute the
1477 // status to ensure that the current VPB is kicked off the device
1478 // below - there is probably blank media in the drive, since we got
1479 // further than the check verify.
1480 //
1481
1482 if (!CdIsRawDevice( IrpContext, Status )) {
1483
1485 }
1486
1487 try_return( Status );
1488
1489 //
1490 // We got a TOC. Verify that it matches the previous Toc.
1491 //
1492
1493 } else if ((Vcb->TocLength != TocLength) ||
1494 (Vcb->TrackCount != TocTrackCount) ||
1495 (Vcb->DiskFlags != TocDiskFlags) ||
1496 !RtlEqualMemory( CdromToc,
1497 Vcb->CdromToc,
1498 TocLength )) {
1499
1501 }
1502
1503 //
1504 // If the disk to verify is an audio disk then we already have a
1505 // match. Otherwise we need to check the volume descriptor.
1506 //
1507
1508 if (!FlagOn( Vcb->VcbState, VCB_STATE_AUDIO_DISK )) {
1509
1510 //
1511 // Allocate a buffer for the sector buffer.
1512 //
1513
1516 TAG_VOL_DESC );
1517
1518 //
1519 // Read the primary volume descriptor for this volume. If we
1520 // get an io error and this verify was a the result of DASD open,
1521 // commute the Io error to STATUS_WRONG_VOLUME. Note that if we currently
1522 // expect a music disk then this request should fail.
1523 //
1524
1525 ReturnError = FALSE;
1526
1528
1529 ReturnError = TRUE;
1530 }
1531
1532 if (!CdFindPrimaryVd( IrpContext,
1533 Vcb,
1534 RawIsoVd,
1535 Vcb->BlockFactor,
1536 ReturnError,
1537 TRUE )) {
1538
1539 //
1540 // If the previous Vcb did not represent a raw disk
1541 // then show this volume was dismounted.
1542 //
1543
1545
1546 }
1547 else {
1548
1549 //
1550 // Look for a supplementary VD.
1551 //
1552 // Store the primary volume descriptor in the second half of
1553 // RawIsoVd. Then if our search for a secondary fails we can
1554 // recover this immediately.
1555 //
1556
1557 RtlCopyMemory( Add2Ptr( RawIsoVd, SECTOR_SIZE, PVOID ),
1558 RawIsoVd,
1559 SECTOR_SIZE );
1560
1561 //
1562 // We have the initial volume descriptor. Locate a secondary
1563 // volume descriptor if present.
1564 //
1565
1566 CdFindActiveVolDescriptor( IrpContext,
1567 Vcb,
1568 RawIsoVd,
1569 TRUE);
1570 //
1571 // Compare the serial numbers. If they don't match, set the
1572 // status to wrong volume.
1573 //
1574
1575 if (Vpb->SerialNumber != CdSerial32( RawIsoVd, SECTOR_SIZE )) {
1576
1578 }
1579
1580 //
1581 // Verify the volume labels.
1582 //
1583
1584 if (!FlagOn( Vcb->VcbState, VCB_STATE_JOLIET )) {
1585
1586 //
1587 // Compute the length of the volume name
1588 //
1589
1590 AnsiLabel.Buffer = (PCHAR)CdRvdVolId( RawIsoVd, Vcb->VcbState );
1591 AnsiLabel.MaximumLength = AnsiLabel.Length = (ULONG)VOLUME_ID_LENGTH;
1592
1593 UnicodeLabel.MaximumLength = VOLUME_ID_LENGTH * sizeof( WCHAR );
1594 UnicodeLabel.Buffer = VolumeLabel;
1595
1596 //
1597 // Convert this to unicode. If we get any error then use a name
1598 // length of zero.
1599 //
1600
1601 VolumeLabelLength = 0;
1602
1604 &AnsiLabel,
1605 FALSE ))) {
1606
1607 VolumeLabelLength = UnicodeLabel.Length;
1608 }
1609
1610 //
1611 // We need to convert from big-endian to little endian.
1612 //
1613
1614 } else {
1615
1616 CdConvertBigToLittleEndian( IrpContext,
1617 (PCHAR) CdRvdVolId( RawIsoVd, Vcb->VcbState ),
1619 (PCHAR) VolumeLabel );
1620
1621 VolumeLabelLength = VOLUME_ID_LENGTH;
1622 }
1623
1624 //
1625 // Strip the trailing spaces or zeroes from the name.
1626 //
1627
1628 Index = VolumeLabelLength / sizeof( WCHAR );
1629
1630 while (Index > 0) {
1631
1632 if ((VolumeLabel[ Index - 1 ] != L'\0') &&
1633 (VolumeLabel[ Index - 1 ] != L' ')) {
1634
1635 break;
1636 }
1637
1638 Index -= 1;
1639 }
1640
1641 //
1642 // Now set the final length for the name.
1643 //
1644
1645 VolumeLabelLength = (USHORT) (Index * sizeof( WCHAR ));
1646
1647 //
1648 // Now check that the label matches.
1649 //
1650 if ((Vpb->VolumeLabelLength != VolumeLabelLength) ||
1651 !RtlEqualMemory( Vpb->VolumeLabel,
1652 VolumeLabel,
1653 VolumeLabelLength )) {
1654
1656 }
1657 }
1658 }
1659 }
1660
1661 //
1662 // The volume is OK, clear the verify bit.
1663 //
1664
1666
1667 CdMarkRealDevVerifyOk( Vpb->RealDevice);
1668
1669 //
1670 // See if we will need to provide notification of the remount. This is the readonly
1671 // filesystem's form of dismount/mount notification.
1672 //
1673
1674 if (FlagOn( Vcb->VcbState, VCB_STATE_NOTIFY_REMOUNT )) {
1675
1677
1678 FileObjectToNotify = Vcb->RootIndexFcb->FileObject;
1679 ObReferenceObject( FileObjectToNotify );
1680 }
1681
1682 try_exit: NOTHING;
1683
1684 //
1685 // Update the media change count to note that we have verified the volume
1686 // at this value - regardless of the outcome.
1687 //
1688
1689 CdUpdateMediaChangeCount( Vcb, MediaChangeCount);
1690
1691 //
1692 // If the volume was already unmounted, nothing more to do.
1693 //
1694
1695 if (Vcb->VcbCondition == VcbNotMounted) {
1696
1698
1699 //
1700 // If we got the wrong volume then free any remaining XA sector in
1701 // the current Vcb. Also mark the Vcb as not mounted.
1702 //
1703
1704 } else if ((Vcb->VcbCondition == VcbMounted) && (Status == STATUS_WRONG_VOLUME)) {
1705
1707
1708 if (Vcb->XASector != NULL) {
1709
1710 CdFreePool( &Vcb->XASector );
1711 Vcb->XASector = 0;
1712 Vcb->XADiskOffset = 0;
1713 }
1714
1715 CdFreeDirCache( IrpContext);
1716
1717 //
1718 // Now, if there are no user handles to the volume, try to spark
1719 // teardown by purging the volume.
1720 //
1721
1722 if (Vcb->VcbCleanup == 0) {
1723
1724 if (NT_SUCCESS( CdPurgeVolume( IrpContext, Vcb, FALSE ))) {
1725
1726 ReleaseVcb = CdCheckForDismount( IrpContext, Vcb, FALSE );
1727 }
1728 }
1729 }
1730
1731 } _SEH2_FINALLY {
1732
1733 //
1734 // Free the TOC buffer if allocated.
1735 //
1736
1737 if (CdromToc != NULL) {
1738
1739 CdFreePool( &CdromToc );
1740 }
1741
1742 if (RawIsoVd != NULL) {
1743
1744 CdFreePool( &RawIsoVd );
1745 }
1746
1747 if (ReleaseVcb) {
1748
1749 CdReleaseVcb( IrpContext, Vcb );
1750 }
1751 else {
1753 }
1754
1755 CdReleaseCdData( IrpContext );
1756 } _SEH2_END;
1757
1758 //
1759 // Now send mount notification.
1760 //
1761
1762 if (FileObjectToNotify) {
1763
1764 FsRtlNotifyVolumeEvent( FileObjectToNotify, FSRTL_VOLUME_MOUNT );
1765 ObDereferenceObject( FileObjectToNotify );
1766 }
1767
1768 //
1769 // Complete the request if no exception.
1770 //
1771
1772 CdCompleteRequest( IrpContext, Irp, Status );
1773 return Status;
1774}
1775
1776
1777//
1778// Local support routine
1779//
1780
1781_Requires_lock_held_(_Global_critical_region_)
1783CdOplockRequest (
1784 _Inout_ PIRP_CONTEXT IrpContext,
1786 )
1787
1788/*++
1789
1790Routine Description:
1791
1792 This is the common routine to handle oplock requests made via the
1793 NtFsControlFile call.
1794
1795Arguments:
1796
1797 Irp - Supplies the Irp being processed
1798
1799Return Value:
1800
1801 NTSTATUS - The return status for the operation
1802
1803--*/
1804
1805{
1807 PFCB Fcb;
1808 PCCB Ccb;
1809
1810 ULONG OplockCount = 0;
1812
1813 PAGED_CODE();
1814
1815 //
1816 // We only permit oplock requests on files.
1817 //
1818
1819 if (CdDecodeFileObject( IrpContext,
1821 &Fcb,
1822 &Ccb ) != UserFileOpen ) {
1823
1826 }
1827
1828 //
1829 // Make this a waitable Irpcontext so we don't fail to acquire
1830 // the resources.
1831 //
1832
1833 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
1834 ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_FORCE_POST );
1835
1836 //
1837 // Switch on the function control code. We grab the Fcb exclusively
1838 // for oplock requests, shared for oplock break acknowledgement.
1839 //
1840
1841 switch (IrpSp->Parameters.FileSystemControl.FsControlCode) {
1842
1847
1848 CdAcquireFcbExclusive( IrpContext, Fcb, FALSE );
1849
1851
1852 if (Fcb->FileLock != NULL) {
1853
1854#if (NTDDI_VERSION >= NTDDI_WIN7)
1855 OplockCount = (ULONG) FsRtlAreThereCurrentOrInProgressFileLocks( Fcb->FileLock );
1856#else
1857 OplockCount = (ULONG) FsRtlAreThereCurrentFileLocks( Fcb->FileLock );
1858#endif
1859 }
1860
1861 } else {
1862
1863 OplockCount = Fcb->FcbCleanup;
1864 }
1865
1866 break;
1867
1872
1873 CdAcquireFcbShared( IrpContext, Fcb, FALSE );
1874 break;
1875
1876 default:
1877
1880 }
1881
1882 //
1883 // Use a try finally to free the Fcb.
1884 //
1885
1886 _SEH2_TRY {
1887
1888 //
1889 // Verify the Fcb.
1890 //
1891
1892 CdVerifyFcbOperation( IrpContext, Fcb );
1893
1894 //
1895 // Call the FsRtl routine to grant/acknowledge oplock.
1896 //
1897
1899 Irp,
1900 OplockCount );
1901
1902 //
1903 // Set the flag indicating if Fast I/O is possible
1904 //
1905
1906 CdLockFcb( IrpContext, Fcb );
1907 Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb );
1908 CdUnlockFcb( IrpContext, Fcb );
1909
1910 //
1911 // The oplock package will complete the Irp.
1912 //
1913
1914 Irp = NULL;
1915
1916 } _SEH2_FINALLY {
1917
1918 //
1919 // Release all of our resources
1920 //
1921
1922 CdReleaseFcb( IrpContext, Fcb );
1923 } _SEH2_END;
1924
1925 //
1926 // Complete the request if there was no exception.
1927 //
1928
1929 CdCompleteRequest( IrpContext, Irp, Status );
1930 return Status;
1931}
1932
1933
1934//
1935// Local support routine
1936//
1937
1938_Requires_lock_held_(_Global_critical_region_)
1940CdLockVolume (
1941 _Inout_ PIRP_CONTEXT IrpContext,
1943 )
1944
1945/*++
1946
1947Routine Description:
1948
1949 This routine performs the lock volume operation. It is responsible for
1950 either completing of enqueuing the input Irp.
1951
1952Arguments:
1953
1954 Irp - Supplies the Irp to process
1955
1956Return Value:
1957
1958 NTSTATUS - The return status for the operation
1959
1960--*/
1961
1962{
1964
1966
1967 PVCB Vcb;
1968 PFCB Fcb;
1969 PCCB Ccb;
1970
1971 PAGED_CODE();
1972
1973 //
1974 // Decode the file object, the only type of opens we accept are
1975 // user volume opens.
1976 //
1977
1978 if (CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb ) != UserVolumeOpen) {
1979
1981
1983 }
1984
1985 //
1986 // Send our notification so that folks that like to hold handles on
1987 // volumes can get out of the way.
1988 //
1989
1991
1992 //
1993 // Acquire exclusive access to the Vcb.
1994 //
1995
1996 Vcb = Fcb->Vcb;
1997 CdAcquireVcbExclusive( IrpContext, Vcb, FALSE );
1998
1999 _SEH2_TRY {
2000
2001 //
2002 // Verify the Vcb.
2003 //
2004
2005 CdVerifyVcb( IrpContext, Vcb );
2006
2007 Status = CdLockVolumeInternal( IrpContext, Vcb, IrpSp->FileObject );
2008
2009 } _SEH2_FINALLY {
2010
2011 //
2012 // Release the Vcb.
2013 //
2014
2015 CdReleaseVcb( IrpContext, Vcb );
2016
2018
2020 }
2021 } _SEH2_END;
2022
2023 //
2024 // Complete the request if there haven't been any exceptions.
2025 //
2026
2027 CdCompleteRequest( IrpContext, Irp, Status );
2028 return Status;
2029}
2030
2031
2032//
2033// Local support routine
2034//
2035
2036_Requires_lock_held_(_Global_critical_region_)
2038CdUnlockVolume (
2039 _Inout_ PIRP_CONTEXT IrpContext,
2041 )
2042
2043/*++
2044
2045Routine Description:
2046
2047 This routine performs the unlock volume operation. It is responsible for
2048 either completing of enqueuing the input Irp.
2049
2050Arguments:
2051
2052 Irp - Supplies the Irp to process
2053
2054Return Value:
2055
2056 NTSTATUS - The return status for the operation
2057
2058--*/
2059
2060{
2062
2064
2065 PVCB Vcb;
2066 PFCB Fcb;
2067 PCCB Ccb;
2068
2069 PAGED_CODE();
2070
2071 //
2072 // Decode the file object, the only type of opens we accept are
2073 // user volume opens.
2074 //
2075
2076 if (CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb ) != UserVolumeOpen ) {
2077
2080 }
2081
2082 //
2083 // Acquire exclusive access to the Vcb.
2084 //
2085
2086 Vcb = Fcb->Vcb;
2087
2088 CdAcquireVcbExclusive( IrpContext, Vcb, FALSE );
2089
2090 //
2091 // We won't check for a valid Vcb for this request. An unlock will always
2092 // succeed on a locked volume.
2093 //
2094
2096
2097 //
2098 // Release all of our resources
2099 //
2100
2101 CdReleaseVcb( IrpContext, Vcb );
2102
2103 //
2104 // Send notification that the volume is avaliable.
2105 //
2106
2107 if (NT_SUCCESS( Status )) {
2108
2110 }
2111
2112 //
2113 // Complete the request if there haven't been any exceptions.
2114 //
2115
2116 CdCompleteRequest( IrpContext, Irp, Status );
2117 return Status;
2118}
2119
2120
2121
2122//
2123// Local support routine
2124//
2125
2126_Requires_lock_held_(_Global_critical_region_)
2128CdDismountVolume (
2129 _Inout_ PIRP_CONTEXT IrpContext,
2131 )
2132
2133/*++
2134
2135Routine Description:
2136
2137 This routine performs the dismount volume operation. It is responsible for
2138 either completing of enqueuing the input Irp. We only dismount a volume which
2139 has been locked. The intent here is that someone has locked the volume (they are the
2140 only remaining handle). We set the verify bit here and the user will close his handle.
2141 We will dismount a volume with no user's handles in the verify path.
2142
2143Arguments:
2144
2145 Irp - Supplies the Irp to process
2146
2147Return Value:
2148
2149 NTSTATUS - The return status for the operation
2150
2151--*/
2152
2153{
2156
2157 PVCB Vcb;
2158 PFCB Fcb;
2159 PCCB Ccb;
2160
2161 PAGED_CODE();
2162
2163 if (CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb ) != UserVolumeOpen ) {
2164
2167 }
2168
2169 Vcb = Fcb->Vcb;
2170
2171 //
2172 // Send dismount notification.
2173 //
2174
2176
2177 //
2178 // Make this request waitable.
2179 //
2180
2181 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
2182
2183 //
2184 // Acquire exclusive access to the Vcb, and take the global resource to
2185 // sync. against mounts, verifies etc.
2186 //
2187
2188 CdAcquireCdData( IrpContext );
2189 CdAcquireVcbExclusive( IrpContext, Vcb, FALSE );
2190
2191 //
2192 // Mark the volume as needs to be verified, but only do it if
2193 // the vcb is locked by this handle and the volume is currently mounted.
2194 //
2195
2196 if (Vcb->VcbCondition != VcbMounted) {
2197
2199
2200 } else {
2201
2202 //
2203 // Invalidate the volume right now.
2204 //
2205 // The intent here is to make every subsequent operation
2206 // on the volume fail and grease the rails toward dismount.
2207 // By definition there is no going back from a SURPRISE.
2208 //
2209
2210 CdLockVcb( IrpContext, Vcb );
2211
2212 if (Vcb->VcbCondition != VcbDismountInProgress) {
2213
2215 }
2216
2217 SetFlag( Vcb->VcbState, VCB_STATE_DISMOUNTED );
2218
2219 CdUnlockVcb( IrpContext, Vcb );
2220
2221
2222 //
2223 // Set flag to tell the close path that we want to force dismount
2224 // the volume when this handle is closed.
2225 //
2226
2228
2230 }
2231
2232 //
2233 // Release all of our resources
2234 //
2235
2236 CdReleaseVcb( IrpContext, Vcb );
2237 CdReleaseCdData( IrpContext );
2238
2239#if (NTDDI_VERSION >= NTDDI_WIN8)
2240
2241 FsRtlDismountComplete( Vcb->TargetDeviceObject, Status );
2242
2243#endif
2244
2245 //
2246 // Complete the request if there haven't been any exceptions.
2247 //
2248
2249 CdCompleteRequest( IrpContext, Irp, Status );
2250 return Status;
2251}
2252
2253
2254//
2255// Local support routine
2256//
2257
2260 _Inout_ PIRP_CONTEXT IrpContext,
2262 )
2263
2264/*++
2265
2266Routine Description:
2267
2268 This routine determines if a volume is currently dirty.
2269
2270Arguments:
2271
2272 Irp - Supplies the Irp to process
2273
2274Return Value:
2275
2276 NTSTATUS - The return status for the operation
2277
2278--*/
2279
2280{
2282
2284 PFCB Fcb;
2285 PCCB Ccb;
2286
2288
2289 PAGED_CODE();
2290
2291 //
2292 // Get the current stack location and extract the output
2293 // buffer information.
2294 //
2295
2297
2298 //
2299 // Get a pointer to the output buffer.
2300 //
2301
2302 if (Irp->AssociatedIrp.SystemBuffer != NULL) {
2303
2304 VolumeState = Irp->AssociatedIrp.SystemBuffer;
2305
2306 } else {
2307
2310 }
2311
2312 //
2313 // Make sure the output buffer is large enough and then initialize
2314 // the answer to be that the volume isn't dirty.
2315 //
2316
2317 if (IrpSp->Parameters.FileSystemControl.OutputBufferLength < sizeof(ULONG)) {
2318
2321 }
2322
2323 *VolumeState = 0;
2324
2325 //
2326 // Decode the file object
2327 //
2328
2329 TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb );
2330
2331 if (TypeOfOpen != UserVolumeOpen) {
2332
2335 }
2336
2337 if (Fcb->Vcb->VcbCondition != VcbMounted) {
2338
2341 }
2342
2343 //
2344 // Now set up to return the clean state. CDs obviously can never be dirty
2345 // but we want to make sure we have enforced the full semantics of this call.
2346 //
2347
2348 Irp->IoStatus.Information = sizeof( ULONG );
2349
2350 CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
2351 return STATUS_SUCCESS;
2352}
2353
2354
2355//
2356// Local support routine
2357//
2358
2361 _Inout_ PIRP_CONTEXT IrpContext,
2363 )
2364
2365/*++
2366
2367Routine Description:
2368
2369 This routine determines if a volume is currently mounted.
2370
2371Arguments:
2372
2373 Irp - Supplies the Irp to process
2374
2375Return Value:
2376
2377 NTSTATUS - The return status for the operation
2378
2379--*/
2380
2381{
2383
2384 PFCB Fcb;
2385 PCCB Ccb;
2386
2387 PAGED_CODE();
2388
2389 //
2390 // Decode the file object.
2391 //
2392
2393 CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb );
2394
2395 if (Fcb != NULL) {
2396
2397 //
2398 // Disable PopUps, we want to return any error.
2399 //
2400
2401 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS );
2402
2403 //
2404 // Verify the Vcb. This will raise in the error condition.
2405 //
2406
2407 CdVerifyVcb( IrpContext, Fcb->Vcb );
2408 }
2409
2410 CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
2411
2412 return STATUS_SUCCESS;
2413}
2414
2415
2416//
2417// Local support routine
2418//
2419
2422 _Inout_ PIRP_CONTEXT IrpContext,
2424 )
2425
2426/*++
2427
2428Routine Description:
2429
2430 This routine determines if pathname is a valid CDFS pathname.
2431 We always succeed this request.
2432
2433Arguments:
2434
2435 Irp - Supplies the Irp to process.
2436
2437Return Value:
2438
2439 None
2440
2441--*/
2442
2443{
2444 PAGED_CODE();
2445
2446 CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
2447 return STATUS_SUCCESS;
2448}
2449
2450
2451//
2452// Local support routine
2453//
2454
2455_Requires_lock_held_(_Global_critical_region_)
2457CdInvalidateVolumes (
2458 _Inout_ PIRP_CONTEXT IrpContext,
2460 )
2461
2462/*++
2463
2464Routine Description:
2465
2466 This routine searches for all the volumes mounted on the same real device
2467 of the current DASD handle, and marks them all bad. The only operation
2468 that can be done on such handles is cleanup and close.
2469
2470Arguments:
2471
2472 Irp - Supplies the Irp to process
2473
2474Return Value:
2475
2476 NTSTATUS - The return status for the operation
2477
2478--*/
2479
2480{
2483 KIRQL SavedIrql;
2484
2485 BOOLEAN UnlockVcb = FALSE;
2486
2487 LUID TcbPrivilege = {SE_TCB_PRIVILEGE, 0};
2488
2489 HANDLE Handle;
2490
2491 PVCB Vcb;
2492
2493 PLIST_ENTRY Links;
2494
2495 PFILE_OBJECT FileToMarkBad;
2496 PDEVICE_OBJECT DeviceToMarkBad;
2497
2498 //
2499 // We only allow the invalidate call to come in on our file system devices.
2500 //
2501
2502#ifndef __REACTOS__
2504#else
2506 IrpSp->DeviceObject != CdData.HddFileSystemDeviceObject) {
2507#endif
2508
2510
2512 }
2513
2514 //
2515 // Check for the correct security access.
2516 // The caller must have the SeTcbPrivilege.
2517 //
2518
2519 if (!SeSinglePrivilegeCheck( TcbPrivilege, Irp->RequestorMode )) {
2520
2522
2524 }
2525
2526 //
2527 // Try to get a pointer to the device object from the handle passed in.
2528 //
2529
2530#if defined(_WIN64) && BUILD_WOW64_ENABLED
2531
2532 if (IoIs32bitProcess( Irp )) {
2533
2534 if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof( UINT32 )) {
2535
2538 }
2539
2540 Handle = (HANDLE) LongToHandle( *((PUINT32) Irp->AssociatedIrp.SystemBuffer) );
2541
2542 } else
2543
2544#endif
2545
2546 {
2547 if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof( HANDLE )) {
2548
2551 }
2552
2553 Handle = *((PHANDLE) Irp->AssociatedIrp.SystemBuffer);
2554 }
2555
2557 0,
2559 KernelMode,
2560 (PVOID*)&FileToMarkBad, /* ReactOS Change: GCC "passing argument 5 of 'ObReferenceObjectByHandle' from incompatible pointer type" */
2561 NULL );
2562
2563 if (!NT_SUCCESS(Status)) {
2564
2565 CdCompleteRequest( IrpContext, Irp, Status );
2566 return Status;
2567 }
2568
2569 //
2570 // Grab the DeviceObject from the FileObject.
2571 //
2572
2573 DeviceToMarkBad = FileToMarkBad->DeviceObject;
2574
2575 //
2576 // We only needed the device object involved, not a reference to the file.
2577 //
2578
2579 ObDereferenceObject( FileToMarkBad );
2580
2581 //
2582 // Make sure this request can wait.
2583 //
2584
2585 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
2586 ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_FORCE_POST );
2587
2588 //
2589 // Synchronise with pnp/mount/verify paths.
2590 //
2591
2592 CdAcquireCdData( IrpContext );
2593
2594 //
2595 // Nothing can go wrong now.
2596 //
2597
2598 //
2599 // Now walk through all the mounted Vcb's looking for candidates to
2600 // mark invalid.
2601 //
2602 // On volumes we mark invalid, check for dismount possibility (which is
2603 // why we have to get the next link so early).
2604 //
2605
2606 Links = CdData.VcbQueue.Flink;
2607
2608 while (Links != &CdData.VcbQueue) {
2609
2610 Vcb = CONTAINING_RECORD( Links, VCB, VcbLinks);
2611
2612 Links = Links->Flink;
2613
2614 //
2615 // If we get a match, mark the volume Bad, and also check to
2616 // see if the volume should go away.
2617 //
2618
2619 CdLockVcb( IrpContext, Vcb );
2620
2621 if (Vcb->Vpb->RealDevice == DeviceToMarkBad) {
2622
2623 //
2624 // Take the VPB spinlock, and look to see if this volume is the
2625 // one currently mounted on the actual device. If it is, pull it
2626 // off immediately.
2627 //
2628
2629 IoAcquireVpbSpinLock( &SavedIrql );
2630
2631#ifdef _MSC_VER
2632#pragma prefast(suppress: 28175, "this is a filesystem driver, touching the vpb is allowed")
2633#endif
2634 if (DeviceToMarkBad->Vpb == Vcb->Vpb) {
2635
2636 PVPB NewVpb = Vcb->SwapVpb;
2637
2638 NT_ASSERT( FlagOn( Vcb->Vpb->Flags, VPB_MOUNTED));
2639 NT_ASSERT( NULL != NewVpb);
2640
2641 RtlZeroMemory( NewVpb, sizeof( VPB ) );
2642
2643 NewVpb->Type = IO_TYPE_VPB;
2644 NewVpb->Size = sizeof( VPB );
2645 NewVpb->RealDevice = DeviceToMarkBad;
2646
2647#ifdef _MSC_VER
2648#pragma prefast(push)
2649#pragma prefast(disable: 28175, "this is a filesystem driver, touching the vpb is allowed")
2650#endif
2651 NewVpb->Flags = FlagOn( DeviceToMarkBad->Vpb->Flags, VPB_REMOVE_PENDING );
2652 DeviceToMarkBad->Vpb = NewVpb;
2653#ifdef _MSC_VER
2654#pragma prefast(pop)
2655#endif
2656
2657 Vcb->SwapVpb = NULL;
2658 }
2659
2660 IoReleaseVpbSpinLock( SavedIrql );
2661
2662 if (Vcb->VcbCondition != VcbDismountInProgress) {
2663
2665 }
2666
2667 CdUnlockVcb( IrpContext, Vcb );
2668
2669 CdAcquireVcbExclusive( IrpContext, Vcb, FALSE);
2670
2671 CdPurgeVolume( IrpContext, Vcb, FALSE );
2672
2673 UnlockVcb = CdCheckForDismount( IrpContext, Vcb, FALSE );
2674
2675 //
2676 // prefast: if UnlockVcb is false, then the VCB was already deleted, so we better not touch the Vcb.
2677 // tell Prefast something nice so it stops complaining about us leaking it.
2678 //
2679
2680 __analysis_assert( UnlockVcb == TRUE );
2681
2682 if (UnlockVcb) {
2683
2684 CdReleaseVcb( IrpContext, Vcb);
2685 }
2686
2687 } else {
2688
2689 CdUnlockVcb( IrpContext, Vcb );
2690 }
2691 }
2692
2693 CdReleaseCdData( IrpContext );
2694
2695 CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
2696 return STATUS_SUCCESS;
2697}
2698
2699
2700//
2701// Local support routine
2702//
2703
2706 _Inout_ PIRP_CONTEXT IrpContext,
2708 )
2709
2710/*++
2711
2712Routine Description:
2713
2714 This routine marks the CCB to indicate that the handle
2715 may be used to read past the end of the volume file. The
2716 handle must be a dasd handle.
2717
2718Arguments:
2719
2720 Irp - Supplies the Irp to process
2721
2722Return Value:
2723
2724 NTSTATUS - The return status for the operation
2725
2726--*/
2727
2728{
2731
2732 PFCB Fcb;
2733 PCCB Ccb;
2734
2735 PAGED_CODE();
2736
2737 //
2738 // Decode the file object, the only type of opens we accept are
2739 // user volume opens.
2740 //
2741
2742 if (CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb ) != UserVolumeOpen ) {
2743
2745 }
2746 else {
2747
2750 }
2751
2752 CdCompleteRequest( IrpContext, Irp, Status );
2753 return Status;
2754}
2755
2756
2757//
2758// Local support routine
2759//
2760
2761_Requires_lock_held_(_Global_critical_region_)
2762VOID
2763CdScanForDismountedVcb (
2764 _Inout_ PIRP_CONTEXT IrpContext
2765 )
2766
2767/*++
2768
2769Routine Description:
2770
2771 This routine walks through the list of Vcb's looking for any which may
2772 now be deleted. They may have been left on the list because there were
2773 outstanding references.
2774
2775Arguments:
2776
2777Return Value:
2778
2779 None
2780
2781--*/
2782
2783{
2784 PVCB Vcb;
2785 PLIST_ENTRY Links;
2786
2787 PAGED_CODE();
2788
2789 //
2790 // Walk through all of the Vcb's attached to the global data.
2791 //
2792
2793 Links = CdData.VcbQueue.Flink;
2794
2795 while (Links != &CdData.VcbQueue) {
2796
2797 Vcb = CONTAINING_RECORD( Links, VCB, VcbLinks );
2798
2799 //
2800 // Move to the next link now since the current Vcb may be deleted.
2801 //
2802
2803 Links = Links->Flink;
2804
2805 //
2806 // If dismount is already underway then check if this Vcb can
2807 // go away.
2808 //
2809
2810 if ((Vcb->VcbCondition == VcbDismountInProgress) ||
2811 (Vcb->VcbCondition == VcbInvalid) ||
2812 ((Vcb->VcbCondition == VcbNotMounted) && (Vcb->VcbReference <= CDFS_RESIDUAL_REFERENCE))) {
2813
2814 CdCheckForDismount( IrpContext, Vcb, FALSE );
2815 }
2816 }
2817
2818 return;
2819}
2820
2821
2822//
2823// Local support routine
2824//
2826BOOLEAN
2827CdFindPrimaryVd (
2828 _In_ PIRP_CONTEXT IrpContext,
2831 _In_ ULONG BlockFactor,
2832 _In_ BOOLEAN ReturnOnError,
2833 _In_ BOOLEAN VerifyVolume
2834 )
2835
2836/*++
2837
2838Routine Description:
2839
2840 This routine is called to walk through the volume descriptors looking
2841 for a primary volume descriptor. When/if a primary is found a 32-bit
2842 serial number is generated and stored into the Vpb. We also store the
2843 location of the primary volume descriptor in the Vcb.
2844
2845Arguments:
2846
2847 Vcb - Pointer to the VCB for the volume.
2848
2849 RawIsoVd - Pointer to a sector buffer which will contain the primary
2850 volume descriptor on exit, if successful.
2851
2852 BlockFactor - Block factor used by the current device for the TableOfContents.
2853
2854 ReturnOnError - Indicates that we should raise on I/O errors rather than
2855 returning a FALSE value.
2856
2857 VerifyVolume - Indicates if we were called from the verify path. We
2858 do a few things different in this path. We don't update the Vcb in
2859 the verify path.
2860
2861Return Value:
2862
2863 BOOLEAN - TRUE if a valid primary volume descriptor found, FALSE
2864 otherwise.
2865
2866--*/
2867
2868{
2870 ULONG ThisPass = 1;
2871 BOOLEAN FoundVd = FALSE;
2872
2873 ULONG BaseSector;
2875
2876 PCDROM_TOC_LARGE CdromToc;
2877
2878 ULONG VolumeFlags;
2879
2880 PAGED_CODE();
2881
2882 //
2883 // If there are no data tracks, don't even bother hunting for descriptors.
2884 //
2885 // This explicitly breaks various non-BlueBook compliant CDs that scribble
2886 // an ISO filesystem on media claiming only audio tracks. Since these
2887 // disks can cause serious problems in some CDROM units, fail fast. I admit
2888 // that it is possible that someone can still record the descriptors in the
2889 // audio track, record a data track (but fail to record descriptors there)
2890 // and still have the disk work. As this form of error worked in NT 4.0, and
2891 // since these disks really do exist, I don't want to change them.
2892 //
2893 // If we wished to support all such media (we don't), it would be neccesary
2894 // to clear this flag on finding ISO or HSG descriptors below.
2895 //
2896
2897 if (FlagOn(Vcb->VcbState, VCB_STATE_AUDIO_DISK)) {
2898
2899 return FALSE;
2900 }
2901
2902 //
2903 // We will make at most two passes through the volume descriptor sequence.
2904 //
2905 // On the first pass we will query for the last session. Using this
2906 // as a starting offset we will attempt to mount the volume. On any failure
2907 // we will go to the second pass and try without using any multi-session
2908 // information.
2909 //
2910 // On the second pass we will start offset from sector zero.
2911 //
2912
2913 while (!FoundVd && (ThisPass <= 2)) {
2914
2915 //
2916 // If we aren't at pass 1 then we start at sector 0. Otherwise we
2917 // try to look up the multi-session information.
2918 //
2919
2920 BaseSector = 0;
2921
2922 if (ThisPass == 1) {
2923
2924 CdromToc = NULL;
2925
2926 //
2927 // Check for whether this device supports XA and multi-session.
2928 //
2929
2930 _SEH2_TRY {
2931
2932 //
2933 // Allocate a buffer for the last session information.
2934 //
2935
2937 sizeof( CDROM_TOC_LARGE ),
2938 TAG_CDROM_TOC );
2939
2940 RtlZeroMemory( CdromToc, sizeof( CDROM_TOC_LARGE ));
2941
2942 //
2943 // Query the last session information from the driver.
2944 //
2945
2946 Status = CdPerformDevIoCtrl( IrpContext,
2948 Vcb->TargetDeviceObject,
2949 CdromToc,
2950 sizeof( CDROM_TOC_LARGE ),
2951 FALSE,
2952 TRUE,
2953 NULL );
2954
2955 //
2956 // Raise an exception if there was an allocation failure.
2957 //
2958
2960
2961 CdRaiseStatus( IrpContext, Status );
2962 }
2963
2964 //
2965 // We don't handle any errors yet. We will hit that below
2966 // as we try to scan the disk. If we have last session information
2967 // then modify the base sector.
2968 //
2969
2970 if (NT_SUCCESS( Status ) &&
2971 (CdromToc->FirstTrack != CdromToc->LastTrack)) {
2972
2973 PCHAR Source, Dest;
2974 ULONG Count;
2975
2976 Count = 4;
2977
2978 //
2979 // The track address is BigEndian, we need to flip the bytes.
2980 //
2981
2982 Source = (PCHAR) &CdromToc->TrackData[0].Address[3];
2983 Dest = (PCHAR) &BaseSector;
2984
2985 do {
2986
2987 *Dest++ = *Source--;
2988
2989 } while (--Count);
2990
2991 //
2992 // Now adjust the base sector by the block factor of the
2993 // device.
2994 //
2995
2996 BaseSector /= BlockFactor;
2997
2998 //
2999 // Make this look like the second pass since we are only using the
3000 // first session. No reason to retry on error.
3001 //
3002
3003 } else {
3004
3005 ThisPass += 1;
3006 }
3007
3008 } _SEH2_FINALLY {
3009
3010 if (CdromToc != NULL) { CdFreePool( &CdromToc ); }
3011 } _SEH2_END;
3012 }
3013
3014 //
3015 // Compute the starting sector offset from the start of the session.
3016 //
3017
3019
3020 //
3021 // Start by assuming we have neither Hsg or Iso volumes.
3022 //
3023
3024 VolumeFlags = 0;
3025
3026 //
3027 // Loop until either error encountered, primary volume descriptor is
3028 // found or a terminal volume descriptor is found.
3029 //
3030
3031 while (TRUE) {
3032
3033 //
3034 // Attempt to read the desired sector. Exit directly if operation
3035 // not completed.
3036 //
3037 // If this is pass 1 we will ignore errors in read sectors and just
3038 // go to the next pass.
3039 //
3040
3041 if (!CdReadSectors( IrpContext,
3042 LlBytesFromSectors( BaseSector + SectorOffset ),
3044 (BOOLEAN) ((ThisPass == 1) || ReturnOnError),
3045 RawIsoVd,
3046 Vcb->TargetDeviceObject )) {
3047
3048 break;
3049 }
3050
3051 //
3052 // Check if either an ISO or HSG volume.
3053 //
3054
3056 CdRvdId( RawIsoVd, VCB_STATE_ISO ),
3057 VOL_ID_LEN )) {
3058
3059 SetFlag( VolumeFlags, VCB_STATE_ISO );
3060
3061 } else if (RtlEqualMemory( CdHsgId,
3062 CdRvdId( RawIsoVd, VCB_STATE_HSG ),
3063 VOL_ID_LEN )) {
3064
3065 SetFlag( VolumeFlags, VCB_STATE_HSG );
3066
3067 //
3068 // We have neither so break out of the loop.
3069 //
3070
3071 } else {
3072
3073 break;
3074 }
3075
3076 //
3077 // Break out if the version number is incorrect or this is
3078 // a terminator.
3079 //
3080
3081 if ((CdRvdVersion( RawIsoVd, VolumeFlags ) != VERSION_1) ||
3082 (CdRvdDescType( RawIsoVd, VolumeFlags ) == VD_TERMINATOR)) {
3083
3084 break;
3085 }
3086
3087 //
3088 // If this is a primary volume descriptor then our search is over.
3089 //
3090
3091 if (CdRvdDescType( RawIsoVd, VolumeFlags ) == VD_PRIMARY) {
3092
3093 //
3094 // If we are not in the verify path then initialize the
3095 // fields in the Vcb with basic information from this
3096 // descriptor.
3097 //
3098
3099 if (!VerifyVolume) {
3100
3101 //
3102 // Set the flag for the volume type.
3103 //
3104
3105 SetFlag( Vcb->VcbState, VolumeFlags );
3106
3107 //
3108 // Store the base sector and sector offset for the
3109 // primary volume descriptor.
3110 //
3111
3112 Vcb->BaseSector = BaseSector;
3113 Vcb->VdSectorOffset = SectorOffset;
3114 Vcb->PrimaryVdSectorOffset = SectorOffset;
3115 }
3116
3117 FoundVd = TRUE;
3118 break;
3119 }
3120
3121 //
3122 // Indicate that we're at the next sector.
3123 //
3124
3125 SectorOffset += 1;
3126 }
3127
3128 ThisPass += 1;
3129 }
3130
3131 return FoundVd;
3132}
3133
3134
3135//
3136// Local support routine
3137//
3138
3140CdIsRemount (
3141 _In_ PIRP_CONTEXT IrpContext,
3142 _In_ PVCB Vcb,
3143 _Out_ PVCB *OldVcb
3144 )
3145/*++
3146
3147Routine Description:
3148
3149 This routine walks through the links of the Vcb chain in the global
3150 data structure. The remount condition is met when the following
3151 conditions are all met:
3152
3153 If the new Vcb is a device only Mvcb and there is a previous
3154 device only Mvcb.
3155
3156 Otherwise following conditions must be matched.
3157
3158 1 - The 32 serial in the current VPB matches that in a previous
3159 VPB.
3160
3161 2 - The volume label in the Vpb matches that in the previous
3162 Vpb.
3163
3164 3 - The system pointer to the real device object in the current
3165 VPB matches that in the same previous VPB.
3166
3167 4 - Finally the previous Vcb cannot be invalid or have a dismount
3168 underway.
3169
3170 If a VPB is found which matches these conditions, then the address of
3171 the VCB for that VPB is returned via the pointer Vcb.
3172
3173 Skip over the current Vcb.
3174
3175Arguments:
3176
3177 Vcb - This is the Vcb we are checking for a remount.
3178
3179 OldVcb - A pointer to the address to store the address for the Vcb
3180 for the volume if this is a remount. (This is a pointer to
3181 a pointer)
3182
3183Return Value:
3184
3185 BOOLEAN - TRUE if this is in fact a remount, FALSE otherwise.
3186
3187--*/
3188
3189{
3191
3192 PVPB Vpb = Vcb->Vpb;
3193 PVPB OldVpb;
3194
3195 BOOLEAN Remount = FALSE;
3196
3197 PAGED_CODE();
3198
3199 UNREFERENCED_PARAMETER( IrpContext );
3200
3201 //
3202 // Check whether we are looking for a device only Mvcb.
3203 //
3204
3205 for (Link = CdData.VcbQueue.Flink;
3206 Link != &CdData.VcbQueue;
3207 Link = Link->Flink) {
3208
3209 *OldVcb = CONTAINING_RECORD( Link, VCB, VcbLinks );
3210
3211 //
3212 // Skip ourselves.
3213 //
3214
3215 if (Vcb == *OldVcb) { continue; }
3216
3217 //
3218 // Look at the Vpb and state of the previous Vcb.
3219 //
3220
3221 OldVpb = (*OldVcb)->Vpb;
3222
3223 if ((OldVpb != Vpb) &&
3224 (OldVpb->RealDevice == Vpb->RealDevice) &&
3225 ((*OldVcb)->VcbCondition == VcbNotMounted)) {
3226
3227 //
3228 // If the current disk is a raw disk then it can match a previous music or
3229 // raw disk.
3230 //
3231
3232 if (FlagOn( Vcb->VcbState, VCB_STATE_AUDIO_DISK)) {
3233
3234 if (FlagOn( (*OldVcb)->VcbState, VCB_STATE_AUDIO_DISK )) {
3235
3236 //
3237 // If we have both TOC then fail the remount if the lengths
3238 // are different or they don't match.
3239 //
3240
3241 if ((Vcb->TocLength != (*OldVcb)->TocLength) ||
3242 ((Vcb->TocLength != 0) &&
3243 !RtlEqualMemory( Vcb->CdromToc,
3244 (*OldVcb)->CdromToc,
3245 Vcb->TocLength ))) {
3246
3247 continue;
3248 }
3249
3250 Remount = TRUE;
3251 break;
3252 }
3253
3254 //
3255 // The current disk is not a raw disk. Go ahead and compare
3256 // serial numbers, volume label and TOC.
3257 //
3258
3259 }
3260 else if ((OldVpb->SerialNumber == Vpb->SerialNumber) &&
3261 (Vcb->TocLength == (*OldVcb)->TocLength) &&
3262 ((Vcb->TocLength == 0) || RtlEqualMemory( Vcb->CdromToc,
3263 (*OldVcb)->CdromToc,
3264 Vcb->TocLength )) &&
3265 (Vpb->VolumeLabelLength == OldVpb->VolumeLabelLength) &&
3266 (RtlEqualMemory( OldVpb->VolumeLabel,
3267 Vpb->VolumeLabel,
3268 Vpb->VolumeLabelLength ))) {
3269 //
3270 // Remember the old Vcb. Then set the return value to
3271 // TRUE and break.
3272 //
3273
3274 Remount = TRUE;
3275 break;
3276 }
3277 }
3278 }
3279
3280 return Remount;
3281}
3282
3283
3284//
3285// Local support routine
3286//
3287
3288VOID
3290 _In_ PIRP_CONTEXT IrpContext,
3291 _In_ PVCB Vcb,
3293 _In_ BOOLEAN VerifyVolume
3294 )
3295
3296/*++
3297
3298Routine Description:
3299
3300 This routine is called to search for a valid secondary volume descriptor that
3301 we will support. Right now we only support Joliet escape sequences for
3302 the secondary descriptor.
3303
3304 If we don't find the secondary descriptor then we will reread the primary.
3305
3306 This routine will update the serial number and volume label in the Vpb.
3307
3308Arguments:
3309
3310 Vcb - This is the Vcb for the volume being mounted.
3311
3312 RawIsoVd - Sector buffer used to read the volume descriptors from the disks, but
3313 on input should contain the PVD (ISO) in the SECOND 'sector' of the
3314 buffer.
3315
3316 VerifyVolume - indicates we are being called by the verify path, and should
3317 not modify the Vcb fields.
3318
3319Return Value:
3320
3321 None
3322
3323--*/
3324
3325{
3326 BOOLEAN FoundSecondaryVd = FALSE;
3328
3329 ULONG Length;
3330
3331 ULONG Index;
3332
3333 PAGED_CODE();
3334
3335 //
3336 // We only look for secondary volume descriptors on an Iso disk.
3337 //
3338
3339 if ((FlagOn( Vcb->VcbState, VCB_STATE_ISO) || VerifyVolume) && !CdNoJoliet) {
3340
3341 //
3342 // Scan the volume descriptors from the beginning looking for a valid
3343 // secondary or a terminator.
3344 //
3345
3347
3348 while (TRUE) {
3349
3350 //
3351 // Read the next sector. We should never have an error in this
3352 // path.
3353 //
3354
3355 CdReadSectors( IrpContext,
3356 LlBytesFromSectors( Vcb->BaseSector + SectorOffset ),
3358 FALSE,
3359 RawIsoVd,
3360 Vcb->TargetDeviceObject );
3361
3362 //
3363 // Break out if the version number or standard Id is incorrect.
3364 // Also break out if this is a terminator.
3365 //
3366
3367 if (!RtlEqualMemory( CdIsoId, CdRvdId( RawIsoVd, VCB_STATE_JOLIET ), VOL_ID_LEN ) ||
3368 (CdRvdVersion( RawIsoVd, VCB_STATE_JOLIET ) != VERSION_1) ||
3369 (CdRvdDescType( RawIsoVd, VCB_STATE_JOLIET ) == VD_TERMINATOR)) {
3370
3371 break;
3372 }
3373
3374 //
3375 // We have a match if this is a secondary descriptor with a matching
3376 // escape sequence.
3377 //
3378
3379 if ((CdRvdDescType( RawIsoVd, VCB_STATE_JOLIET ) == VD_SECONDARY) &&
3381 CdJolietEscape[0],
3382 ESC_SEQ_LEN ) ||
3384 CdJolietEscape[1],
3385 ESC_SEQ_LEN ) ||
3387 CdJolietEscape[2],
3388 ESC_SEQ_LEN ))) {
3389
3390 if (!VerifyVolume) {
3391
3392 //
3393 // Update the Vcb with the new volume descriptor.
3394 //
3395
3396 ClearFlag( Vcb->VcbState, VCB_STATE_ISO );
3397 SetFlag( Vcb->VcbState, VCB_STATE_JOLIET );
3398
3399 Vcb->VdSectorOffset = SectorOffset;
3400 }
3401
3402 FoundSecondaryVd = TRUE;
3403 break;
3404 }
3405
3406 //
3407 // Otherwise move on to the next sector.
3408 //
3409
3410 SectorOffset += 1;
3411 }
3412
3413 //
3414 // If we didn't find the secondary then recover the original volume
3415 // descriptor stored in the second half of the RawIsoVd.
3416 //
3417
3418 if (!FoundSecondaryVd) {
3419
3420 RtlCopyMemory( RawIsoVd,
3421 Add2Ptr( RawIsoVd, SECTOR_SIZE, PVOID ),
3422 SECTOR_SIZE );
3423 }
3424 }
3425
3426 //
3427 // If we're in the verify path, our work is done, since we don't want
3428 // to update any Vcb/Vpb values.
3429 //
3430
3431 if (VerifyVolume) {
3432
3433 return;
3434 }
3435
3436 //
3437 // Compute the serial number and volume label from the volume descriptor.
3438 //
3439
3440 Vcb->Vpb->SerialNumber = CdSerial32( RawIsoVd, SECTOR_SIZE );
3441
3442 //
3443 // Make sure the CD label will fit in the Vpb.
3444 //
3445
3447
3448 //
3449 // If this is not a Unicode label we must convert it to unicode.
3450 //
3451
3452 if (!FlagOn( Vcb->VcbState, VCB_STATE_JOLIET )) {
3453
3454 //
3455 // Convert the label to unicode. If we get any error then use a name
3456 // length of zero.
3457 //
3458
3459 Vcb->Vpb->VolumeLabelLength = 0;
3460
3461 if (NT_SUCCESS( RtlOemToUnicodeN( &Vcb->Vpb->VolumeLabel[0],
3463 &Length,
3464 (PCH)CdRvdVolId( RawIsoVd, Vcb->VcbState ),
3465 VOLUME_ID_LENGTH ))) {
3466
3467 Vcb->Vpb->VolumeLabelLength = (USHORT) Length;
3468 }
3469
3470 //
3471 // We need to convert from big-endian to little endian.
3472 //
3473
3474 } else {
3475
3476 CdConvertBigToLittleEndian( IrpContext,
3477 (PCHAR) CdRvdVolId( RawIsoVd, Vcb->VcbState ),
3479 (PCHAR) Vcb->Vpb->VolumeLabel );
3480
3481 Vcb->Vpb->VolumeLabelLength = VOLUME_ID_LENGTH * sizeof( WCHAR );
3482 }
3483
3484 //
3485 // Strip the trailing spaces or zeroes from the name.
3486 //
3487
3488 Index = Vcb->Vpb->VolumeLabelLength / sizeof( WCHAR );
3489
3490 while (Index > 0) {
3491
3492 if ((Vcb->Vpb->VolumeLabel[ Index - 1 ] != L'\0') &&
3493 (Vcb->Vpb->VolumeLabel[ Index - 1 ] != L' ')) {
3494
3495 break;
3496 }
3497
3498 Index -= 1;
3499 }
3500
3501 //
3502 // Now set the final length for the name.
3503 //
3504
3505 Vcb->Vpb->VolumeLabelLength = (USHORT) (Index * sizeof( WCHAR ));
3506}
3507
3508
3509
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define PAGED_CODE()
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
unsigned char BOOLEAN
unsigned int UINT32
static ULONG StackSize
Definition: StackOverflow.c:19
LONG NTSTATUS
Definition: precomp.h:26
#define LongToHandle(h)
Definition: basetsd.h:82
unsigned int * PUINT32
Definition: basetsd.h:125
#define SECTOR_SIZE
Definition: fs.h:22
#define VD_TERMINATOR
Definition: cd.h:55
#define VOLUME_ID_LENGTH
Definition: cd.h:59
#define CdRvdVolId(R, F)
Definition: cd.h:283
#define VOL_ID_LEN
Definition: cd.h:50
#define CdRvdVersion(R, F)
Definition: cd.h:265
#define CdRvdId(R, F)
Definition: cd.h:259
#define CdRvdEsc(R, F)
Definition: cd.h:277
#define ESC_SEQ_LEN
Definition: cd.h:51
#define TOC_DATA_TRACK
Definition: cd.h:99
#define CdRvdDescType(R, F)
Definition: cd.h:271
#define VERSION_1
Definition: cd.h:53
#define VD_SECONDARY
Definition: cd.h:57
#define FIRST_VD_SECTOR
Definition: cd.h:48
#define VD_PRIMARY
Definition: cd.h:56
VOID CdCompleteRequest(_Inout_opt_ PIRP_CONTEXT IrpContext, _Inout_opt_ PIRP Irp, _In_ NTSTATUS Status)
Definition: cddata.c:914
ULONG CdSerial32(_In_reads_bytes_(ByteCount) PCHAR Buffer, _In_ ULONG ByteCount)
Definition: cddata.c:1185
CHAR CdHsgId[]
Definition: cddata.c:61
CHAR CdIsoId[]
Definition: cddata.c:62
CD_DATA CdData
Definition: cddata.c:42
PCHAR CdJolietEscape[]
Definition: cddata.c:86
#define CDFS_RESIDUAL_USER_REFERENCE
Definition: cddata.h:44
#define CDFS_RESIDUAL_REFERENCE
Definition: cddata.h:43
NTSTATUS CdIsPathnameValid(_Inout_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp)
Definition: fsctrl.c:2421
VOID CdFindActiveVolDescriptor(_In_ PIRP_CONTEXT IrpContext, _In_ PVCB Vcb, _Inout_updates_bytes_(ROUND_TO_PAGES(SECTOR_SIZE)) PCHAR RawIsoVd, _In_ BOOLEAN VerifyVolume)
Definition: fsctrl.c:3289
BOOLEAN CdDisable
Definition: fsctrl.c:29
NTSTATUS CdUnlockVolumeInternal(_In_ PIRP_CONTEXT IrpContext, _Inout_ PVCB Vcb, _In_opt_ PFILE_OBJECT FileObject)
Definition: fsctrl.c:288
NTSTATUS CdAllowExtendedDasdIo(_Inout_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp)
Definition: fsctrl.c:2705
NTSTATUS CdIsVolumeMounted(_Inout_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp)
Definition: fsctrl.c:2360
NTSTATUS CdIsVolumeDirty(_Inout_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp)
Definition: fsctrl.c:2259
VOID CdReMountOldVcb(_In_ PIRP_CONTEXT IrpContext, _Inout_ PVCB OldVcb, _Inout_ PVCB NewVcb, _In_ PDEVICE_OBJECT DeviceObjectWeTalkTo)
Definition: fsctrl.c:518
BOOLEAN CdNoJoliet
Definition: fsctrl.c:30
#define CdUpdateMediaChangeCount(V, C)
Definition: cdprocs.h:1448
#define CdLockFcb(IC, F)
Definition: cdprocs.h:1044
#define CdAcquireCdData(IC)
Definition: cdprocs.h:973
VOID CdFspClose(_In_opt_ PVCB Vcb)
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN TypeOfOpen
Definition: cdprocs.h:589
#define CdAcquireFcbShared(IC, F, I)
Definition: cdprocs.h:1009
#define CdUpdateVcbCondition(V, C)
Definition: cdprocs.h:1449
VOID CdConvertBigToLittleEndian(_In_ PIRP_CONTEXT IrpContext, _In_reads_bytes_(ByteCount) PCHAR BigEndian, _In_ ULONG ByteCount, _Out_writes_bytes_(ByteCount) PCHAR LittleEndian)
Definition: namesup.c:110
#define CdReleaseVcb(IC, V)
Definition: cdprocs.h:985
#define CdReleaseFcb(IC, F)
Definition: cdprocs.h:1012
VOID CdVerifyVcb(_In_ PIRP_CONTEXT IrpContext, _Inout_ PVCB Vcb)
Definition: verfysup.c:411
#define CdTelemetryMountSafe(...)
Definition: cdprocs.h:2312
@ UserFileOpen
Definition: cdprocs.h:577
@ UserVolumeOpen
Definition: cdprocs.h:575
#define CdLockVcb(IC, V)
Definition: cdprocs.h:1023
#define CdGetFcbOplock(F)
Definition: cdprocs.h:1081
#define CdRealDevNeedsVerify(DO)
Definition: cdprocs.h:1456
#define CdReleaseCdData(IC)
Definition: cdprocs.h:976
VOID CdInitializeVcb(_In_ PIRP_CONTEXT IrpContext, _Inout_ PVCB Vcb, _In_ __drv_aliasesMem PDEVICE_OBJECT TargetDeviceObject, _In_ __drv_aliasesMem PVPB Vpb, _In_ __drv_aliasesMem PCDROM_TOC_LARGE CdromToc, _In_ ULONG TocLength, _In_ ULONG TocTrackCount, _In_ ULONG TocDiskFlags, _In_ ULONG BlockFactor, _In_ ULONG MediaChangeCount)
Definition: strucsup.c:241
#define CdMarkRealDevVerifyOk(DO)
Definition: cdprocs.h:1453
#define CdUnlockVcb(IC, V)
Definition: cdprocs.h:1028
#define LlBytesFromSectors(L)
Definition: cdprocs.h:1614
_In_ PFCB Fcb
Definition: cdprocs.h:159
#define CdNonPagedPool
Definition: cdprocs.h:1381
BOOLEAN CdReadSectors(_In_ PIRP_CONTEXT IrpContext, _In_ LONGLONG StartingOffset, _In_ ULONG ByteCount, _In_ BOOLEAN ReturnError, _Out_writes_bytes_(ByteCount) PVOID Buffer, _In_ PDEVICE_OBJECT TargetDeviceObject)
Definition: deviosup.c:1080
#define TAG_VOL_DESC
Definition: cdprocs.h:105
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:592
#define try_leave(S)
Definition: cdprocs.h:2180
#define CdAcquireVcbExclusive(IC, V, I)
Definition: cdprocs.h:979
BOOLEAN CdVerifyFcbOperation(_In_opt_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb)
Definition: verfysup.c:615
#define CdMarkRealDevForVerify(DO)
Definition: cdprocs.h:1451
#define SectorOffset(L)
Definition: cdprocs.h:1622
#define CdAcquireFcbExclusive(IC, F, I)
Definition: cdprocs.h:1006
NTSTATUS CdProcessToc(_In_ PIRP_CONTEXT IrpContext, _In_ PDEVICE_OBJECT TargetDeviceObject, _In_ PCDROM_TOC_LARGE CdromToc, _Inout_ PULONG Length, _Out_ PULONG TrackCount, _Inout_ PULONG DiskFlags)
Definition: strucsup.c:2201
enum _TYPE_OF_OPEN TYPE_OF_OPEN
NTSTATUS FASTCALL CdPerformDevIoCtrl(_In_ PIRP_CONTEXT IrpContext, _In_ ULONG IoControlCode, _In_ PDEVICE_OBJECT Device, _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer, _In_ ULONG OutputBufferLength, _In_ BOOLEAN InternalDeviceIoControl, _In_ BOOLEAN OverrideVerify, _Out_opt_ PIO_STATUS_BLOCK Iosb)
Definition: deviosup.c:1446
#define CdFreePool(x)
Definition: cdprocs.h:2190
#define try_return(S)
Definition: cdprocs.h:2179
#define CdPagedPool
Definition: cdprocs.h:1380
#define CdIsRawDevice(IC, S)
Definition: cdprocs.h:1466
#define CdIsFastIoPossible(F)
Definition: cdprocs.h:2015
#define TAG_CDROM_TOC
Definition: cdprocs.h:86
VOID CdUpdateVcbFromVolDescriptor(_In_ PIRP_CONTEXT IrpContext, _Inout_ PVCB Vcb, _In_reads_bytes_opt_(SECTOR_SIZE) PCHAR RawIsoVd)
Definition: strucsup.c:436
#define CdUnlockFcb(IC, F)
Definition: cdprocs.h:1060
#define CdRaiseStatus(IC, S)
Definition: cdprocs.h:1859
#define IOCTL_DISK_CHECK_VERIFY
Definition: cdrw_usr.h:175
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
#define VCB_STATE_HSG
Definition: cdstruc.h:706
#define CCB_FLAG_ALLOW_EXTENDED_DASD_IO
Definition: cdstruc.h:1108
#define IRP_CONTEXT_FLAG_FORCE_POST
Definition: cdstruc.h:1216
#define CCB_FLAG_DISMOUNT_ON_CLOSE
Definition: cdstruc.h:1107
#define CD_FLAGS_SHUTDOWN
Definition: cdstruc.h:422
#define VCB_STATE_CDXA
Definition: cdstruc.h:711
#define VCB_STATE_VPB_NOT_ON_DEVICE
Definition: cdstruc.h:714
#define IRP_CONTEXT_FLAG_WAIT
Definition: cdstruc.h:1215
#define VCB_STATE_AUDIO_DISK
Definition: cdstruc.h:712
#define VCB_STATE_JOLIET
Definition: cdstruc.h:708
VOLUME_DEVICE_OBJECT * PVOLUME_DEVICE_OBJECT
Definition: cdstruc.h:769
#define CD_SEC_CACHE_CHUNKS
Definition: cdstruc.h:460
#define VCB_STATE_DISMOUNTED
Definition: cdstruc.h:716
#define VCB_STATE_LOCKED
Definition: cdstruc.h:709
#define VCB_STATE_ISO
Definition: cdstruc.h:707
#define CD_SEC_CHUNK_BLOCKS
Definition: cdstruc.h:461
#define IRP_CONTEXT_FLAG_DISABLE_POPUPS
Definition: cdstruc.h:1222
@ VcbMounted
Definition: cdstruc.h:492
@ VcbNotMounted
Definition: cdstruc.h:490
@ VcbDismountInProgress
Definition: cdstruc.h:494
@ VcbInvalid
Definition: cdstruc.h:493
#define VCB_STATE_NOTIFY_REMOUNT
Definition: cdstruc.h:713
Definition: bufpool.h:45
#define _Analysis_assume_lock_not_held_(lock)
#define _Requires_lock_held_(lock)
#define _Analysis_suppress_lock_checking_(lock)
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define DEVICE_TYPE
Definition: guid.c:10
#define RAW_SECTOR_SIZE
Definition: mcicda.c:50
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
return Iosb
Definition: create.c:4402
UCHAR KIRQL
Definition: env_spec_w32.h:591
NTSTATUS ExInitializeResourceLite(PULONG res)
Definition: env_spec_w32.h:641
struct _DEVICE_OBJECT * PDEVICE_OBJECT
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define DO_DEVICE_INITIALIZING
Definition: env_spec_w32.h:399
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
#define ClearFlag(_F, _SF)
Definition: ext2fs.h:191
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
IN OUT PVCB IN PDEVICE_OBJECT IN PVPB Vpb
Definition: fatprocs.h:1676
IN PVCB IN FAT_VOLUME_STATE VolumeState
Definition: fatprocs.h:1999
std::wstring STRING
Definition: fontsub.cpp:33
#define FsRtlAreThereCurrentFileLocks(FL)
Definition: fsrtlfuncs.h:1584
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
_Must_inspect_result_ typedef _Out_ PHIDP_CAPS Capabilities
Definition: hidclass.h:103
#define NOTHING
Definition: input_list.c:10
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
#define Add2Ptr(PTR, INC)
#define RtlEqualMemory(dst, src, len)
Definition: kdvm.h:18
NTSTATUS NTAPI CcWaitForCurrentLazyWriterActivity(VOID)
Definition: lazyrite.c:30
#define PCHAR
Definition: match.c:90
#define SE_TCB_PRIVILEGE
Definition: security.c:661
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3169
#define KernelMode
Definition: asm.h:34
_Use_decl_annotations_ NTSTATUS NTAPI RtlOemToUnicodeN(_Out_ PWCHAR UnicodeString, _In_ ULONG UnicodeSize, _Out_opt_ PULONG ResultSize, _In_ PCCH OemString, _In_ ULONG OemSize)
Definition: nlsboot.c:282
#define _Inout_
Definition: no_sal2.h:162
#define _Success_(c)
Definition: no_sal2.h:84
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define _Inout_updates_bytes_(s)
Definition: no_sal2.h:184
#define _Out_writes_bytes_(s)
Definition: no_sal2.h:178
int Count
Definition: noreturn.cpp:7
#define FSCTL_OPLOCK_BREAK_NOTIFY
Definition: nt_native.h:831
#define FSCTL_LOCK_VOLUME
Definition: nt_native.h:832
#define FSCTL_OPLOCK_BREAK_ACKNOWLEDGE
Definition: nt_native.h:829
#define FSCTL_REQUEST_OPLOCK_LEVEL_1
Definition: nt_native.h:826
#define FSCTL_REQUEST_FILTER_OPLOCK
Definition: nt_native.h:849
#define FSCTL_INVALIDATE_VOLUMES
Definition: nt_native.h:847
#define FSCTL_IS_PATHNAME_VALID
Definition: nt_native.h:837
#define FSCTL_UNLOCK_VOLUME
Definition: nt_native.h:833
#define FSCTL_REQUEST_BATCH_OPLOCK
Definition: nt_native.h:828
#define FSCTL_OPBATCH_ACK_CLOSE_PENDING
Definition: nt_native.h:830
#define FSCTL_OPLOCK_BREAK_ACK_NO_2
Definition: nt_native.h:846
#define FSCTL_IS_VOLUME_MOUNTED
Definition: nt_native.h:836
#define FSCTL_REQUEST_OPLOCK_LEVEL_2
Definition: nt_native.h:827
#define FSCTL_DISMOUNT_VOLUME
Definition: nt_native.h:834
CHAR * PCH
Definition: ntbasedef.h:399
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
#define IOCTL_CDROM_GET_LAST_SESSION
Definition: ntddcdrm.h:64
#define IOCTL_CDROM_CHECK_VERIFY
Definition: ntddcdrm.h:103
#define CDROM_DISK_AUDIO_TRACK
Definition: ntddcdrm.h:145
#define IOCTL_CDROM_GET_DRIVE_GEOMETRY
Definition: ntddcdrm.h:73
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ SynchronizationEvent
#define FSRTL_VOLUME_UNLOCK
Definition: ntifs_ex.h:443
#define FSRTL_VOLUME_LOCK
Definition: ntifs_ex.h:441
#define FSRTL_VOLUME_DISMOUNT
Definition: ntifs_ex.h:439
#define FSRTL_VOLUME_MOUNT
Definition: ntifs_ex.h:444
#define VPB_REMOVE_PENDING
Definition: ntifs_ex.h:428
#define FSRTL_VOLUME_LOCK_FAILED
Definition: ntifs_ex.h:442
PVOID NTAPI FsRtlAllocatePool(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes)
Definition: filter.c:116
PVOID NTAPI FsRtlAllocatePoolWithTag(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes, IN ULONG Tag)
Definition: filter.c:229
NTSTATUS NTAPI FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, IN ULONG EventCode)
Definition: pnp.c:38
NTSTATUS NTAPI IoCreateDevice(IN PDRIVER_OBJECT DriverObject, IN ULONG DeviceExtensionSize, IN PUNICODE_STRING DeviceName, IN DEVICE_TYPE DeviceType, IN ULONG DeviceCharacteristics, IN BOOLEAN Exclusive, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1031
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1251
VOID NTAPI IoInitializeIrp(IN PIRP Irp, IN USHORT PacketSize, IN CCHAR StackSize)
Definition: irp.c:1854
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
VOID NTAPI IoReleaseVpbSpinLock(IN KIRQL Irql)
Definition: volume.c:1215
VOID NTAPI IoAcquireVpbSpinLock(OUT PKIRQL Irql)
Definition: volume.c:1204
BOOLEAN NTAPI SeSinglePrivilegeCheck(_In_ LUID PrivilegeValue, _In_ KPROCESSOR_MODE PreviousMode)
Checks if a single privilege is present in the context of the calling thread.
Definition: priv.c:744
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_SYSTEM_SHUTDOWN
Definition: ntstatus.h:855
#define STATUS_VOLUME_DISMOUNTED
Definition: ntstatus.h:747
#define STATUS_NOT_LOCKED
Definition: ntstatus.h:279
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
NTSTATUS NTAPI FsRtlOplockFsctrl(IN POPLOCK Oplock, IN PIRP Irp, IN ULONG OpenCount)
Definition: oplock.c:1430
unsigned short USHORT
Definition: pedump.c:61
#define Vcb
Definition: cdprocs.h:1415
#define FILE_DEVICE_DISK_FILE_SYSTEM
Definition: winioctl.h:53
#define FSCTL_IS_VOLUME_DIRTY
Definition: winioctl.h:755
#define FILE_DEVICE_CD_ROM
Definition: winioctl.h:47
#define FILE_DEVICE_CD_ROM_FILE_SYSTEM
Definition: winioctl.h:48
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:166
#define _SEH2_FINALLY
Definition: pseh2_64.h:114
#define _SEH2_END
Definition: pseh2_64.h:155
#define _SEH2_TRY
Definition: pseh2_64.h:55
#define FSCTL_ALLOW_EXTENDED_DASD_IO
Definition: winioctl.h:124
#define IOCTL_SCSI_GET_CAPABILITIES
Definition: scsi_port.h:50
NTSTATUS NTAPI RtlOemStringToCountedUnicodeString(IN OUT PUNICODE_STRING UniDest, IN PCOEM_STRING OemSource, IN BOOLEAN AllocateDestinationString)
Definition: unicode.c:1473
#define STATUS_SUCCESS
Definition: shellext.h:65
#define __analysis_assert(e)
Definition: specstrings.h:259
Definition: cdstruc.h:1067
TRACK_DATA TrackData[MAXIMUM_NUMBER_TRACKS_LARGE]
Definition: cdstruc.h:449
UCHAR LastTrack
Definition: cdstruc.h:443
UCHAR FirstTrack
Definition: cdstruc.h:442
USHORT Flags
Definition: cdstruc.h:380
LIST_ENTRY VcbQueue
Definition: cdstruc.h:334
PDRIVER_OBJECT DriverObject
Definition: cdstruc.h:328
PDEVICE_OBJECT FileSystemDeviceObject
Definition: cdstruc.h:350
ULONG AlignmentRequirement
Definition: env_spec_w32.h:420
ULONG BytesPerSector
Definition: ntdddisk.h:404
Definition: cdstruc.h:902
ULONG Flags
Definition: ntfs.h:536
PVCB Vcb
Definition: cdstruc.h:933
FILE_LOCK FileLock
Definition: fatstruc.h:1071
ULONG FcbCleanup
Definition: cdstruc.h:963
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:3223
struct _IO_STACK_LOCATION::@3979::@3994 FileSystemControl
union _IO_STACK_LOCATION::@1580 Parameters
struct _IO_STACK_LOCATION::@3979::@4000 VerifyVolume
struct _IO_STACK_LOCATION::@3979::@3999 MountVolume
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
UCHAR Address[4]
Definition: ntddcdrm.h:141
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: cdstruc.h:498
struct _FCB * RootIndexFcb
Definition: cdstruc.h:560
PVPB SwapVpb
Definition: cdstruc.h:667
VCB_CONDITION VcbCondition
Definition: cdstruc.h:541
ULONG VcbState
Definition: cdstruc.h:540
__volatile LONG PostedRequestCount
Definition: cdstruc.h:739
DEVICE_OBJECT DeviceObject
Definition: cdstruc.h:729
KSPIN_LOCK OverflowQueueSpinLock
Definition: cdstruc.h:760
LIST_ENTRY OverflowQueue
Definition: cdstruc.h:754
ULONG OverflowQueueCount
Definition: cdstruc.h:746
Definition: iotypes.h:189
WCHAR VolumeLabel[MAXIMUM_VOLUME_LABEL_LENGTH/sizeof(WCHAR)]
Definition: iotypes.h:198
CSHORT Type
Definition: iotypes.h:190
USHORT VolumeLabelLength
Definition: iotypes.h:193
CSHORT Size
Definition: iotypes.h:191
USHORT Flags
Definition: iotypes.h:192
ULONG SerialNumber
Definition: iotypes.h:196
struct _DEVICE_OBJECT * RealDevice
Definition: iotypes.h:195
uint32_t * PULONG
Definition: typedefs.h:59
PVOID HANDLE
Definition: typedefs.h:73
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
char CCHAR
Definition: typedefs.h:51
char * PCHAR
Definition: typedefs.h:51
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNRECOGNIZED_VOLUME
Definition: udferr_usr.h:173
#define STATUS_WRONG_VOLUME
Definition: udferr_usr.h:140
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
static int Link(const char **args)
Definition: vfdcmd.c:2414
_In_ WDFCOLLECTION _In_ ULONG Index
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
#define IoSizeOfIrp(_StackSize)
#define VPB_MOUNTED
Definition: iotypes.h:1807
#define IO_TYPE_VPB
#define IRP_MN_VERIFY_VOLUME
Definition: iotypes.h:4405
#define IRP_MN_USER_FS_REQUEST
Definition: iotypes.h:4403
#define SL_ALLOW_RAW_MOUNT
Definition: iotypes.h:1841
struct _VPB VPB
* PFILE_OBJECT
Definition: iotypes.h:1998
#define VPB_LOCKED
Definition: iotypes.h:1808
#define MAXIMUM_VOLUME_LABEL_LENGTH
Definition: iotypes.h:177
#define IRP_MN_MOUNT_VOLUME
Definition: iotypes.h:4404
#define ROUND_TO_PAGES(Size)
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ObReferenceObject
Definition: obfuncs.h:204
#define NT_ASSERT
Definition: rtlfuncs.h:3327
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180