ReactOS  0.4.14-dev-49-gfb4591c
fsctrl.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) 1989-2000 Microsoft Corporation
4 
5 Module Name:
6 
7  FsCtrl.c
8 
9 Abstract:
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_)
38 CdUserFsctl (
39  _Inout_ PIRP_CONTEXT IrpContext,
41  );
42 
43 VOID
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_)
53 CdMountVolume (
54  _Inout_ PIRP_CONTEXT IrpContext,
56  );
57 
58 _Requires_lock_held_(_Global_critical_region_)
60 CdVerifyVolume (
61  _Inout_ PIRP_CONTEXT IrpContext,
63  );
64 
65 _Requires_lock_held_(_Global_critical_region_)
67 CdOplockRequest (
68  _Inout_ PIRP_CONTEXT IrpContext,
70  );
71 
72 _Requires_lock_held_(_Global_critical_region_)
74 CdLockVolume (
75  _Inout_ PIRP_CONTEXT IrpContext,
77  );
78 
79 _Requires_lock_held_(_Global_critical_region_)
81 CdUnlockVolume (
82  _Inout_ PIRP_CONTEXT IrpContext,
84  );
85 
86 _Requires_lock_held_(_Global_critical_region_)
88 CdDismountVolume (
89  _Inout_ PIRP_CONTEXT IrpContext,
91  );
92 
95  _Inout_ PIRP_CONTEXT IrpContext,
97  );
98 
101  _Inout_ PIRP_CONTEXT IrpContext,
103  );
104 
105 NTSTATUS
107  _Inout_ PIRP_CONTEXT IrpContext,
109  );
110 
111 _Requires_lock_held_(_Global_critical_region_)
112 NTSTATUS
113 CdInvalidateVolumes (
114  _Inout_ PIRP_CONTEXT IrpContext,
116  );
117 
118 NTSTATUS
120  _Inout_ PIRP_CONTEXT IrpContext,
122  );
123 
124 _Requires_lock_held_(_Global_critical_region_)
125 VOID
126 CdScanForDismountedVcb (
127  _Inout_ PIRP_CONTEXT IrpContext
128  );
129 
130 _Success_(return != FALSE)
131 BOOLEAN
132 CdFindPrimaryVd (
133  _In_ PIRP_CONTEXT IrpContext,
134  _Inout_ PVCB Vcb,
136  _In_ ULONG BlockFactor,
137  _In_ BOOLEAN ReturnOnError,
138  _In_ BOOLEAN VerifyVolume
139  );
140 
141 _Success_(return != FALSE) BOOLEAN
142 CdIsRemount (
143  _In_ PIRP_CONTEXT IrpContext,
144  _In_ PVCB Vcb,
145  _Out_ PVCB *OldVcb
146  );
147 
148 VOID
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)
182 NTSTATUS
183 CdLockVolumeInternal (
184  _In_ PIRP_CONTEXT IrpContext,
185  _Inout_ PVCB Vcb,
187  )
188 
189 /*++
190 
191 Routine 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 
199 Arguments:
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 
206 Return 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 
287 NTSTATUS
289  _In_ PIRP_CONTEXT IrpContext,
290  _Inout_ PVCB Vcb,
292  )
293 
294 /*++
295 
296 Routine Description:
297 
298  This routine performs the actual unlock volume operation.
299 
300  The volume must be held exclusive by the caller.
301 
302 Arguments:
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 
309 Return 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_)
348 NTSTATUS
349 CdCommonFsControl (
350  _Inout_ PIRP_CONTEXT IrpContext,
352  )
353 
354 /*++
355 
356 Routine Description:
357 
358  This is the common routine for doing FileSystem control operations called
359  by both the fsd and fsp threads
360 
361 Arguments:
362 
363  Irp - Supplies the Irp to process
364 
365 Return 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 
390  case IRP_MN_MOUNT_VOLUME:
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_)
416 NTSTATUS
417 CdUserFsctl (
418  _Inout_ PIRP_CONTEXT IrpContext,
420  )
421 /*++
422 
423 Routine Description:
424 
425  This is the common routine for implementing the user's requests made
426  through NtFsControlFile.
427 
428 Arguments:
429 
430  Irp - Supplies the Irp being processed
431 
432 Return 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 
467  case FSCTL_UNLOCK_VOLUME :
468 
469  Status = CdUnlockVolume( IrpContext, Irp );
470  break;
471 
472  case FSCTL_DISMOUNT_VOLUME :
473 
474  Status = CdDismountVolume( IrpContext, Irp );
475  break;
476 
477  case FSCTL_IS_VOLUME_DIRTY :
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 
517 VOID
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;
527  PUCHAR Buffer;
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_)
571 NTSTATUS
572 CdMountVolume (
573  _Inout_ PIRP_CONTEXT IrpContext,
575  )
576 
577 /*++
578 
579 Routine 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 
602 Arguments:
603 
604  Irp - Supplies the Irp to process
605 
606 Return Value:
607 
608  NTSTATUS - The return status for the operation
609 
610 --*/
611 
612 {
614 
615  PVOLUME_DEVICE_OBJECT VolDo = NULL;
616  PVCB Vcb = NULL;
617  PVCB OldVcb;
619 
620  BOOLEAN FoundPvd = FALSE;
621  BOOLEAN SetDoVerifyOnFail;
622 
624  PDEVICE_OBJECT DeviceObjectWeTalkTo = IrpSp->Parameters.MountVolume.DeviceObject;
625  PVPB Vpb = IrpSp->Parameters.MountVolume.Vpb;
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 
707  return STATUS_SYSTEM_SHUTDOWN;
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 ),
803  TAG_CDROM_TOC );
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  }
1028 
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 
1237  if ((_SEH2_AbnormalTermination() || (Status != STATUS_SUCCESS)) &&
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_)
1310 NTSTATUS
1311 CdVerifyVolume (
1312  _Inout_ PIRP_CONTEXT IrpContext,
1313  _Inout_ PIRP Irp
1314  )
1315 
1316 /*++
1317 
1318 Routine Description:
1319 
1320  This routine performs the verify volume operation. It is responsible for
1321  either completing of enqueuing the input Irp.
1322 
1323 Arguments:
1324 
1325  Irp - Supplies the Irp to process
1326 
1327 Return Value:
1328 
1329  NTSTATUS - The return status for the operation
1330 
1331 --*/
1332 
1333 {
1335  PVPB Vpb = IrpSp->Parameters.VerifyVolume.Vpb;
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 
1422  if (FlagOn( IrpSp->Flags, SL_ALLOW_RAW_MOUNT )) {
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 
1515  ROUND_TO_PAGES( 2 * SECTOR_SIZE ),
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 
1527  if (FlagOn( IrpSp->Flags, SL_ALLOW_RAW_MOUNT )) {
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 
1603  if (NT_SUCCESS( RtlOemStringToCountedUnicodeString( &UnicodeLabel,
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 
1676  ClearFlag( Vcb->VcbState, VCB_STATE_NOTIFY_REMOUNT );
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 {
1752  _Analysis_assume_lock_not_held_(Vcb->VcbResource);
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_)
1782 NTSTATUS
1783 CdOplockRequest (
1784  _Inout_ PIRP_CONTEXT IrpContext,
1785  _Inout_ PIRP Irp
1786  )
1787 
1788 /*++
1789 
1790 Routine Description:
1791 
1792  This is the common routine to handle oplock requests made via the
1793  NtFsControlFile call.
1794 
1795 Arguments:
1796 
1797  Irp - Supplies the Irp being processed
1798 
1799 Return 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,
1820  IrpSp->FileObject,
1821  &Fcb,
1822  &Ccb ) != UserFileOpen ) {
1823 
1825  return STATUS_INVALID_PARAMETER;
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 
1850  if (IrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_REQUEST_OPLOCK_LEVEL_2) {
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 
1879  return STATUS_INVALID_PARAMETER;
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_)
1939 NTSTATUS
1940 CdLockVolume (
1941  _Inout_ PIRP_CONTEXT IrpContext,
1942  _Inout_ PIRP Irp
1943  )
1944 
1945 /*++
1946 
1947 Routine Description:
1948 
1949  This routine performs the lock volume operation. It is responsible for
1950  either completing of enqueuing the input Irp.
1951 
1952 Arguments:
1953 
1954  Irp - Supplies the Irp to process
1955 
1956 Return 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 
1982  return STATUS_INVALID_PARAMETER;
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_)
2037 NTSTATUS
2038 CdUnlockVolume (
2039  _Inout_ PIRP_CONTEXT IrpContext,
2040  _Inout_ PIRP Irp
2041  )
2042 
2043 /*++
2044 
2045 Routine Description:
2046 
2047  This routine performs the unlock volume operation. It is responsible for
2048  either completing of enqueuing the input Irp.
2049 
2050 Arguments:
2051 
2052  Irp - Supplies the Irp to process
2053 
2054 Return Value:
2055 
2056  NTSTATUS - The return status for the operation
2057 
2058 --*/
2059 
2060 {
2061  NTSTATUS Status;
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 
2079  return STATUS_INVALID_PARAMETER;
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 
2095  Status = CdUnlockVolumeInternal( IrpContext, Vcb, IrpSp->FileObject );
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_)
2127 NTSTATUS
2128 CdDismountVolume (
2129  _Inout_ PIRP_CONTEXT IrpContext,
2130  _Inout_ PIRP Irp
2131  )
2132 
2133 /*++
2134 
2135 Routine 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 
2143 Arguments:
2144 
2145  Irp - Supplies the Irp to process
2146 
2147 Return Value:
2148 
2149  NTSTATUS - The return status for the operation
2150 
2151 --*/
2152 
2153 {
2154  NTSTATUS Status;
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 
2166  return STATUS_INVALID_PARAMETER;
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 
2258 NTSTATUS
2260  _Inout_ PIRP_CONTEXT IrpContext,
2261  _Inout_ PIRP Irp
2262  )
2263 
2264 /*++
2265 
2266 Routine Description:
2267 
2268  This routine determines if a volume is currently dirty.
2269 
2270 Arguments:
2271 
2272  Irp - Supplies the Irp to process
2273 
2274 Return 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 
2320  return STATUS_INVALID_PARAMETER;
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 
2334  return STATUS_INVALID_PARAMETER;
2335  }
2336 
2337  if (Fcb->Vcb->VcbCondition != VcbMounted) {
2338 
2340  return STATUS_VOLUME_DISMOUNTED;
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 
2359 NTSTATUS
2361  _Inout_ PIRP_CONTEXT IrpContext,
2362  _Inout_ PIRP Irp
2363  )
2364 
2365 /*++
2366 
2367 Routine Description:
2368 
2369  This routine determines if a volume is currently mounted.
2370 
2371 Arguments:
2372 
2373  Irp - Supplies the Irp to process
2374 
2375 Return 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 
2420 NTSTATUS
2422  _Inout_ PIRP_CONTEXT IrpContext,
2423  _Inout_ PIRP Irp
2424  )
2425 
2426 /*++
2427 
2428 Routine Description:
2429 
2430  This routine determines if pathname is a valid CDFS pathname.
2431  We always succeed this request.
2432 
2433 Arguments:
2434 
2435  Irp - Supplies the Irp to process.
2436 
2437 Return 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_)
2456 NTSTATUS
2457 CdInvalidateVolumes (
2458  _Inout_ PIRP_CONTEXT IrpContext,
2459  _Inout_ PIRP Irp
2460  )
2461 
2462 /*++
2463 
2464 Routine 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 
2470 Arguments:
2471 
2472  Irp - Supplies the Irp to process
2473 
2474 Return Value:
2475 
2476  NTSTATUS - The return status for the operation
2477 
2478 --*/
2479 
2480 {
2481  NTSTATUS Status;
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 
2537  return STATUS_INVALID_PARAMETER;
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 
2550  return STATUS_INVALID_PARAMETER;
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 
2704 NTSTATUS
2706  _Inout_ PIRP_CONTEXT IrpContext,
2707  _Inout_ PIRP Irp
2708  )
2709 
2710 /*++
2711 
2712 Routine 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 
2718 Arguments:
2719 
2720  Irp - Supplies the Irp to process
2721 
2722 Return Value:
2723 
2724  NTSTATUS - The return status for the operation
2725 
2726 --*/
2727 
2728 {
2729  NTSTATUS Status;
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_)
2762 VOID
2763 CdScanForDismountedVcb (
2764  _Inout_ PIRP_CONTEXT IrpContext
2765  )
2766 
2767 /*++
2768 
2769 Routine 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 
2775 Arguments:
2776 
2777 Return 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 //
2825 _Success_(return != FALSE)
2826 BOOLEAN
2827 CdFindPrimaryVd (
2828  _In_ PIRP_CONTEXT IrpContext,
2829  _Inout_ PVCB Vcb,
2831  _In_ ULONG BlockFactor,
2832  _In_ BOOLEAN ReturnOnError,
2833  _In_ BOOLEAN VerifyVolume
2834  )
2835 
2836 /*++
2837 
2838 Routine 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 
2845 Arguments:
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 
2861 Return Value:
2862 
2863  BOOLEAN - TRUE if a valid primary volume descriptor found, FALSE
2864  otherwise.
2865 
2866 --*/
2867 
2868 {
2869  NTSTATUS Status;
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 ),
3043  SECTOR_SIZE,
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 
3055  if (RtlEqualMemory( CdIsoId,
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 
3140 CdIsRemount (
3141  _In_ PIRP_CONTEXT IrpContext,
3142  _In_ PVCB Vcb,
3143  _Out_ PVCB *OldVcb
3144  )
3145 /*++
3146 
3147 Routine 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 
3175 Arguments:
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 
3183 Return Value:
3184 
3185  BOOLEAN - TRUE if this is in fact a remount, FALSE otherwise.
3186 
3187 --*/
3188 
3189 {
3190  PLIST_ENTRY Link;
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 
3288 VOID
3290  _In_ PIRP_CONTEXT IrpContext,
3291  _In_ PVCB Vcb,
3293  _In_ BOOLEAN VerifyVolume
3294  )
3295 
3296 /*++
3297 
3298 Routine 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 
3308 Arguments:
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 
3319 Return 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 ),
3357  SECTOR_SIZE,
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) &&
3380  (RtlEqualMemory( CdRvdEsc( RawIsoVd, VCB_STATE_JOLIET ),
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 
#define DO_DEVICE_INITIALIZING
Definition: env_spec_w32.h:399
#define _Inout_updates_bytes_(size)
Definition: no_sal2.h:287
signed char * PCHAR
Definition: retypes.h:7
#define VCB_STATE_JOLIET
Definition: cdstruc.h:714
FILE_LOCK FileLock
Definition: fatstruc.h:1070
#define CdRvdVersion(R, F)
Definition: cd.h:265
#define VCB_STATE_AUDIO_DISK
Definition: cdstruc.h:718
#define FSRTL_VOLUME_DISMOUNT
Definition: ntifs_ex.h:439
#define _Analysis_suppress_lock_checking_(lock)
Definition: no_sal2.h:685
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
IN PVCB IN FAT_VOLUME_STATE VolumeState
Definition: fatprocs.h:1987
#define FSCTL_UNLOCK_VOLUME
Definition: nt_native.h:833
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define FSCTL_IS_PATHNAME_VALID
Definition: nt_native.h:837
#define IRP_CONTEXT_FLAG_WAIT
Definition: cdstruc.h:1221
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define Add2Ptr(PTR, INC)
WCHAR VolumeLabel[MAXIMUM_VOLUME_LABEL_LENGTH/sizeof(WCHAR)]
Definition: iotypes.h:175
#define CCB_FLAG_DISMOUNT_ON_CLOSE
Definition: cdstruc.h:1113
UCHAR FirstTrack
Definition: cdstruc.h:448
PDEVICE_OBJECT FileSystemDeviceObject
Definition: cdstruc.h:356
PVOID NTAPI FsRtlAllocatePoolWithTag(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes, IN ULONG Tag)
Definition: filter.c:229
USHORT Flags
Definition: iotypes.h:169
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define IRP_CONTEXT_FLAG_FORCE_POST
Definition: cdstruc.h:1222
TRACK_DATA TrackData[MAXIMUM_NUMBER_TRACKS_LARGE]
Definition: cdstruc.h:455
_In_ PIRP Irp
Definition: csq.h:116
unsigned int * PUINT32
Definition: basetsd.h:127
#define CDFS_RESIDUAL_USER_REFERENCE
Definition: cddata.h:44
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
Definition: cdstruc.h:908
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
struct _DEVICE_OBJECT * PDEVICE_OBJECT
#define IOCTL_CDROM_CHECK_VERIFY
Definition: ntddcdrm.h:34
#define CdTelemetryMountSafe(...)
Definition: cdprocs.h:2322
#define CCB_FLAG_ALLOW_EXTENDED_DASD_IO
Definition: cdstruc.h:1114
#define VCB_STATE_NOTIFY_REMOUNT
Definition: cdstruc.h:719
Definition: cdstruc.h:1073
unsigned char * PUCHAR
Definition: retypes.h:3
LONG NTSTATUS
Definition: precomp.h:26
#define IOCTL_DISK_CHECK_VERIFY
Definition: cdrw_usr.h:175
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 CdReleaseFcb(IC, F)
Definition: cdprocs.h:1017
#define IOCTL_CDROM_GET_LAST_SESSION
Definition: ntddcdrm.h:52
#define FSRTL_VOLUME_UNLOCK
Definition: ntifs_ex.h:443
NTSTATUS ExInitializeResourceLite(PULONG res)
Definition: env_spec_w32.h:641
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define FSCTL_OPLOCK_BREAK_ACK_NO_2
Definition: nt_native.h:846
VOID NTAPI IoAcquireVpbSpinLock(OUT PKIRQL Irql)
Definition: volume.c:1209
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
Definition: cdstruc.h:504
struct _FCB * RootIndexFcb
Definition: cdstruc.h:566
BOOLEAN NTAPI SeSinglePrivilegeCheck(IN LUID PrivilegeValue, IN KPROCESSOR_MODE PreviousMode)
Definition: priv.c:524
NTSTATUS NTAPI RtlOemStringToCountedUnicodeString(IN OUT PUNICODE_STRING UniDest, IN PCOEM_STRING OemSource, IN BOOLEAN AllocateDestinationString)
Definition: unicode.c:1463
NTSYSAPI NTSTATUS WINAPI RtlOemToUnicodeN(LPWSTR, DWORD, LPDWORD, LPCSTR, DWORD)
CHAR CdIsoId[]
Definition: cddata.c:62
#define CdAcquireFcbShared(IC, F, I)
Definition: cdprocs.h:1014
#define IRP_CONTEXT_FLAG_DISABLE_POPUPS
Definition: cdstruc.h:1228
#define FSCTL_OPBATCH_ACK_CLOSE_PENDING
Definition: nt_native.h:830
ULONG BytesPerSector
Definition: ntdddisk.h:376
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
UCHAR Address[4]
Definition: ntddcdrm.h:108
#define STATUS_WRONG_VOLUME
Definition: udferr_usr.h:140
ULONG VcbState
Definition: cdstruc.h:546
NTSTATUS CdIsPathnameValid(_Inout_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp)
Definition: fsctrl.c:2421
VOLUME_DEVICE_OBJECT * PVOLUME_DEVICE_OBJECT
Definition: cdstruc.h:775
PVOID NTAPI FsRtlAllocatePool(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes)
Definition: filter.c:116
VOID NTAPI IoInitializeIrp(IN PIRP Irp, IN USHORT PacketSize, IN CCHAR StackSize)
Definition: irp.c:1854
#define FSCTL_REQUEST_BATCH_OPLOCK
Definition: nt_native.h:828
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
PVPB SwapVpb
Definition: cdstruc.h:673
static int Link(const char **args)
Definition: vfdcmd.c:2414
#define CdAcquireFcbExclusive(IC, F, I)
Definition: cdprocs.h:1011
#define PAGED_CODE()
Definition: video.h:57
#define _In_opt_
Definition: no_sal2.h:213
VOID CdFspClose(_In_opt_ PVCB Vcb)
#define VOLUME_ID_LENGTH
Definition: cd.h:59
#define CdUnlockFcb(IC, F)
Definition: cdprocs.h:1065
_SEH2_TRY
Definition: create.c:4250
ULONG OverflowQueueCount
Definition: cdstruc.h:752
#define VCB_STATE_HSG
Definition: cdstruc.h:712
#define FILE_DEVICE_CD_ROM
Definition: winioctl.h:107
#define FSRTL_VOLUME_LOCK_FAILED
Definition: ntifs_ex.h:442
UCHAR KIRQL
Definition: env_spec_w32.h:591
NTSTATUS NTAPI FsRtlOplockFsctrl(IN POPLOCK Oplock, IN PIRP Irp, IN ULONG OpenCount)
Definition: oplock.c:1432
#define IRP_MN_VERIFY_VOLUME
Definition: iotypes.h:4049
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN TypeOfOpen
Definition: cdprocs.h:593
#define VOL_ID_LEN
Definition: cd.h:50
#define CdGetFcbOplock(F)
Definition: cdprocs.h:1086
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:496
#define CdIsRawDevice(IC, S)
Definition: cdprocs.h:1476
#define SE_TCB_PRIVILEGE
Definition: security.c:661
#define FSCTL_OPLOCK_BREAK_NOTIFY
Definition: nt_native.h:831
unsigned int UINT32
_Must_inspect_result_ typedef _Out_ PHIDP_CAPS Capabilities
Definition: hidclass.h:103
#define CdMarkRealDevForVerify(DO)
Definition: cdprocs.h:1461
#define FSCTL_INVALIDATE_VOLUMES
Definition: nt_native.h:847
#define CdRealDevNeedsVerify(DO)
Definition: cdprocs.h:1466
VOID CdCompleteRequest(_Inout_opt_ PIRP_CONTEXT IrpContext, _Inout_opt_ PIRP Irp, _In_ NTSTATUS Status)
Definition: cddata.c:914
#define STATUS_UNRECOGNIZED_VOLUME
Definition: udferr_usr.h:173
#define VPB_LOCKED
Definition: iotypes.h:1765
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
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
CHAR * PCH
Definition: ntbasedef.h:398
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:251
#define SectorOffset(L)
Definition: cdprocs.h:1632
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
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 _SEH2_AbnormalTermination()
Definition: pseh2_64.h:13
#define _Out_writes_bytes_(size)
Definition: no_sal2.h:370
#define _Out_
Definition: no_sal2.h:323
#define MAXIMUM_VOLUME_LABEL_LENGTH
Definition: iotypes.h:154
PDRIVER_OBJECT DriverObject
Definition: cdstruc.h:334
Definition: bufpool.h:45
#define VCB_STATE_LOCKED
Definition: cdstruc.h:715
#define VPB_REMOVE_PENDING
Definition: ntifs_ex.h:428
DEVICE_OBJECT DeviceObject
Definition: cdstruc.h:735
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
#define FsRtlAreThereCurrentFileLocks(FL)
Definition: fsrtlfuncs.h:1584
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define CdRvdId(R, F)
Definition: cd.h:259
VOID CdReMountOldVcb(_In_ PIRP_CONTEXT IrpContext, _Inout_ PVCB OldVcb, _Inout_ PVCB NewVcb, _In_ PDEVICE_OBJECT DeviceObjectWeTalkTo)
Definition: fsctrl.c:518
#define FILE_DEVICE_DISK_FILE_SYSTEM
Definition: winioctl.h:113
UCHAR LastTrack
Definition: cdstruc.h:449
#define PCHAR
Definition: match.c:90
#define FSCTL_OPLOCK_BREAK_ACKNOWLEDGE
Definition: nt_native.h:829
#define FSCTL_DISMOUNT_VOLUME
Definition: nt_native.h:834
#define try_leave(S)
Definition: cdprocs.h:2190
#define CdAcquireVcbExclusive(IC, V, I)
Definition: cdprocs.h:984
#define TOC_DATA_TRACK
Definition: cd.h:99
#define IRP_MN_MOUNT_VOLUME
Definition: iotypes.h:4048
NTSTATUS NTAPI CcWaitForCurrentLazyWriterActivity(VOID)
Definition: lazyrite.c:30
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
_In_ HANDLE Handle
Definition: extypes.h:390
#define IRP_MN_USER_FS_REQUEST
Definition: iotypes.h:4047
#define CdMarkRealDevVerifyOk(DO)
Definition: cdprocs.h:1463
USHORT Flags
Definition: cdstruc.h:386
PCHAR CdJolietEscape[]
Definition: cddata.c:86
NTSTATUS NTAPI FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, IN ULONG EventCode)
Definition: pnp.c:38
CD_DATA CdData
Definition: cddata.c:42
#define ESC_SEQ_LEN
Definition: cd.h:51
NTSYSAPI ULONG NTAPI RtlEqualMemory(CONST VOID *Source1, CONST VOID *Source2, ULONG Length)
__wchar_t WCHAR
Definition: xmlstorage.h:180
return Iosb
Definition: create.c:4426
#define CdReleaseVcb(IC, V)
Definition: cdprocs.h:990
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define VCB_STATE_ISO
Definition: cdstruc.h:713
#define LlBytesFromSectors(L)
Definition: cdprocs.h:1624
#define FSCTL_REQUEST_OPLOCK_LEVEL_2
Definition: nt_native.h:827
#define try_return(S)
Definition: cdprocs.h:2189
#define IOCTL_CDROM_GET_DRIVE_GEOMETRY
Definition: ntddcdrm.h:46
#define CdNonPagedPool
Definition: cdprocs.h:1387
char CCHAR
Definition: typedefs.h:50
#define CdUnlockVcb(IC, V)
Definition: cdprocs.h:1033
#define FIRST_VD_SECTOR
Definition: cd.h:48
struct _DEVICE_OBJECT * RealDevice
Definition: iotypes.h:172
#define VD_TERMINATOR
Definition: cd.h:55
#define Vcb
Definition: cdprocs.h:1425
_Requires_lock_held_(_Requires_lock_held_() VOIDCdScanForDismountedVcb(_Inout_ PIRP_CONTEXT IrpContext) _Global_critical_region_)
Definition: fsctrl.c:36
static const UCHAR Index[8]
Definition: usbohci.c:18
PVOID HANDLE
Definition: typedefs.h:71
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2867
#define CdPagedPool
Definition: cdprocs.h:1385
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define _Inout_
Definition: no_sal2.h:244
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define CDFS_RESIDUAL_REFERENCE
Definition: cddata.h:43
#define SL_ALLOW_RAW_MOUNT
Definition: iotypes.h:1798
* PFILE_OBJECT
Definition: iotypes.h:1955
#define FSCTL_ALLOW_EXTENDED_DASD_IO
Definition: winioctl.h:124
CSHORT Size
Definition: iotypes.h:168
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
std::wstring STRING
Definition: fontsub.cpp:33
#define CdLockVcb(IC, V)
Definition: cdprocs.h:1028
ULONG Flags
Definition: ntfs.h:532
unsigned char UCHAR
Definition: xmlstorage.h:181
static const WCHAR L[]
Definition: oid.c:1250
#define CdRvdVolId(R, F)
Definition: cd.h:283
#define CdIsFastIoPossible(F)
Definition: cdprocs.h:2025
BOOLEAN CdNoJoliet
Definition: fsctrl.c:30
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:414
#define CdRvdDescType(R, F)
Definition: cd.h:271
enum _TYPE_OF_OPEN TYPE_OF_OPEN
#define LongToHandle(h)
Definition: basetsd.h:82
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:593
#define NOTHING
Definition: env_spec_w32.h:461
Definition: typedefs.h:117
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
_In_ USHORT _In_ CCHAR StackSize
Definition: iofuncs.h:1056
#define FSCTL_REQUEST_OPLOCK_LEVEL_1
Definition: nt_native.h:826
NTSTATUS CdAllowExtendedDasdIo(_Inout_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp)
Definition: fsctrl.c:2705
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
ULONG AlignmentRequirement
Definition: env_spec_w32.h:420
#define VCB_STATE_CDXA
Definition: cdstruc.h:717
#define CdAcquireCdData(IC)
Definition: cdprocs.h:978
#define IO_TYPE_VPB
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
struct _VPB VPB
Status
Definition: gdiplustypes.h:24
#define CdLockFcb(IC, F)
Definition: cdprocs.h:1049
#define _In_
Definition: no_sal2.h:204
VOID CdVerifyVcb(_In_ PIRP_CONTEXT IrpContext, _Inout_ PVCB Vcb)
Definition: verfysup.c:411
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
NTSTATUS CdIsVolumeDirty(_Inout_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp)
Definition: fsctrl.c:2259
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1251
_Success_(return !=FALSE)
Definition: fsctrl.c:2825
#define FSRTL_VOLUME_LOCK
Definition: ntifs_ex.h:441
#define CD_SEC_CACHE_CHUNKS
Definition: cdstruc.h:466
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
PFILE_OBJECT FileObject
Definition: iotypes.h:2813
_SEH2_END
Definition: create.c:4424
CHAR CdHsgId[]
Definition: cddata.c:61
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define CdFreePool(x)
Definition: cdprocs.h:2200
#define ROUND_TO_PAGES(Size)
unsigned short USHORT
Definition: pedump.c:61
#define CdRaiseStatus(IC, S)
Definition: cdprocs.h:1869
VCB_CONDITION VcbCondition
Definition: cdstruc.h:547
#define IoSizeOfIrp(_StackSize)
NTSTATUS CdUnlockVolumeInternal(_In_ PIRP_CONTEXT IrpContext, _Inout_ PVCB Vcb, _In_opt_ PFILE_OBJECT FileObject)
Definition: fsctrl.c:288
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
#define CdRvdEsc(R, F)
Definition: cd.h:277
#define VD_SECONDARY
Definition: cd.h:57
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129
__volatile LONG PostedRequestCount
Definition: cdstruc.h:745
#define CD_SEC_CHUNK_BLOCKS
Definition: cdstruc.h:467
#define DEVICE_TYPE
Definition: guid.c:10
#define FSCTL_REQUEST_FILTER_OPLOCK
Definition: nt_native.h:849
_SEH2_FINALLY
Definition: create.c:4395
#define CdReleaseCdData(IC)
Definition: cdprocs.h:981
unsigned int * PULONG
Definition: retypes.h:1
BOOLEAN CdVerifyFcbOperation(_In_opt_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb)
Definition: verfysup.c:615
#define FSCTL_IS_VOLUME_DIRTY
Definition: winioctl.h:636
ULONG CdSerial32(_In_reads_bytes_(ByteCount) PCHAR Buffer, _In_ ULONG ByteCount)
Definition: cddata.c:1185
LIST_ENTRY VcbQueue
Definition: cdstruc.h:340
#define FSCTL_IS_VOLUME_MOUNTED
Definition: nt_native.h:836
CSHORT Type
Definition: iotypes.h:167
#define IOCTL_SCSI_GET_CAPABILITIES
Definition: scsi_port.h:50
Definition: iotypes.h:166
#define FILE_DEVICE_CD_ROM_FILE_SYSTEM
Definition: winioctl.h:108
#define ObReferenceObject
Definition: obfuncs.h:204
USHORT VolumeLabelLength
Definition: iotypes.h:170
#define STATUS_VOLUME_DISMOUNTED
Definition: ntstatus.h:733
#define STATUS_NOT_LOCKED
Definition: ntstatus.h:265
#define FSRTL_VOLUME_MOUNT
Definition: ntifs_ex.h:444
#define FSCTL_LOCK_VOLUME
Definition: nt_native.h:832
#define VD_PRIMARY
Definition: cd.h:56
#define TAG_VOL_DESC
Definition: cdprocs.h:97
unsigned int ULONG
Definition: retypes.h:1
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
#define RAW_SECTOR_SIZE
Definition: mcicda.c:50
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
PVCB Vcb
Definition: cdstruc.h:939
#define _Analysis_assume_lock_not_held_(lock)
Definition: no_sal2.h:683
KSPIN_LOCK OverflowQueueSpinLock
Definition: cdstruc.h:766
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3167
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
#define SECTOR_SIZE
Definition: fs.h:22
#define VCB_STATE_VPB_NOT_ON_DEVICE
Definition: cdstruc.h:720
#define CD_FLAGS_SHUTDOWN
Definition: cdstruc.h:428
#define CDROM_DISK_AUDIO_TRACK
Definition: ntddcdrm.h:112
ULONG SerialNumber
Definition: iotypes.h:173
BOOLEAN CdDisable
Definition: fsctrl.c:29
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
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
_In_ PFCB Fcb
Definition: cdprocs.h:151
#define TAG_CDROM_TOC
Definition: cdprocs.h:78
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
return STATUS_SUCCESS
Definition: btrfs.c:2966
LIST_ENTRY OverflowQueue
Definition: cdstruc.h:760
#define VPB_MOUNTED
Definition: iotypes.h:1764
VOID NTAPI IoReleaseVpbSpinLock(IN KIRQL Irql)
Definition: volume.c:1220
IN OUT PVCB IN PDEVICE_OBJECT IN PVPB Vpb
Definition: fatprocs.h:1664
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
#define VCB_STATE_DISMOUNTED
Definition: cdstruc.h:722
#define CdUpdateMediaChangeCount(V, C)
Definition: cdprocs.h:1458
#define STATUS_SYSTEM_SHUTDOWN
Definition: ntstatus.h:841
#define VERSION_1
Definition: cd.h:53
NTSTATUS CdIsVolumeMounted(_Inout_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp)
Definition: fsctrl.c:2360
VOID CdUpdateVcbFromVolDescriptor(_In_ PIRP_CONTEXT IrpContext, _Inout_ PVCB Vcb, _In_reads_bytes_opt_(SECTOR_SIZE) PCHAR RawIsoVd)
Definition: strucsup.c:436
ULONG FcbCleanup
Definition: cdstruc.h:969
#define CdUpdateVcbCondition(V, C)
Definition: cdprocs.h:1459
#define NT_ASSERT
Definition: rtlfuncs.h:3312